npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@c6fc/spellcraft-aws-lambda

v2.0.0

Published

Lambda function factory covering packaging, environment wiring and the IAM that goes with it.

Readme

SpellCraft AWS Lambda Module

NPM version License

Allows you to trivially add NodeJS Lambda functions to your SpellCraft spells via AWS Terraform.

Features

nodejs_function(name, region, options={}) renders a complete, working Lambda deployment from a single call: the function itself, an execution role with inline and attached policies, a CloudWatch log group, X-Ray tracing, an archive_file data source that zips your source directory, and a null_resource that runs npm install in it first.

It's only reachable through config(), called once per file:

local lambda = (import "@c6fc/spellcraft-aws-lambda/module.libsonnet").config({ thisFile: std.thisFile });

lambda.nodejs_function("my_function", "us-east-1")

Source for my_function is then expected at lambda_functions/my_function/, sibling to thisFile.

Why config() is required, not optional

An earlier version let nodejs_function() work standalone, defaulting thisFile to something that resolved the same way ${path.module}/../lambda_functions/<name> always had. That default is indistinguishable, from inside the function, from a plugin author who simply forgot to call config() — and it's worse than just ambiguous: it can look correct during that author's own standalone testing, because render/'s parent happens to be their plugin's own root when they're the ones running it. It only actually breaks once someone else nests that plugin inside a different project, far from wherever the mistake was made, with a confusing terraform apply-time "source directory does not exist" rather than a clear failure at spellcraft generate time. Requiring config() closes that off entirely: calling nodejs_function() without it fails immediately, by name, for everyone, every time — plugin author or direct consumer alike.

thisFile can't have a default set here, either, for a related reason: std.thisFile is lexical, not dynamic — it names whichever file the token is physically written in, regardless of who calls the function that contains it or how deep the call chain goes. A default written in this file would itself be lexically bound to this plugin's own path, not yours, so it has to come from your own call site.

Shared defaults

Anything passed to config() besides thisFile becomes a default for every nodejs_function() call made through the returned object — any option in the table below, or anything passed through to the resource. A call's own options always wins over a config() default for the same key:

local lambda = (import "@c6fc/spellcraft-aws-lambda/module.libsonnet").config({
	thisFile: std.thisFile,
	tracing: "PassThrough",
});

lambda.nodejs_function("worker", "us-east-1")                          // inherits tracing: "PassThrough"
lambda.nodejs_function("scheduler", "us-east-1", { tracing: "Active" }) // overrides it

Nesting this plugin inside another

The same config() call is what lets this plugin work correctly when it's not the one being called directly from a project's manifest:

// Inside @your-org/some-component/module.libsonnet
local lambda = (import "@c6fc/spellcraft-aws-lambda/module.libsonnet").config({ thisFile: std.thisFile });

{
	build(region):: lambda.nodejs_function("worker", region),
	// -> resolves lambda_functions/worker/ inside @your-org/some-component itself,
	//    not inside whatever project eventually installs it
}

Optional keys — all hidden from the rendered resource, and all usable as config() defaults too:

| option | default | purpose | |---|---|---| | arns_allowed_to_invoke | [] | ARNs granted lambda:InvokeFunction | | services_allowed_to_invoke | [] | Objects with principal and optionally source_arn | | event_triggers | [] | aws_cloudwatch_event_rule bodies; rule, target and permission are wired up for you | | execution_policy_attachments | [] | Managed policy ARNs to attach to the role | | execution_policy_statements | [] | Inline IAM statement objects | | cloudwatch_log_retention_days | 30 | Log group retention | | retain_logs_on_destroy | true | Keep the log group when the function is destroyed | | tracing | 'Active' | X-Ray mode: Active or PassThrough |

Any other key is passed through to the aws_lambda_function resource, so runtime, handler, timeout, memory_size and environment can all be overridden.

refs — referencing what this call produces, without knowing its naming scheme

nodejs_function() builds more than one resource, each with its own derived name (lambda-my_function for the role, for instance) — internal details a caller extending or wiring into them shouldn't have to already know. The return value's hidden refs field makes every one of them addressable by the same convention Terraform itself uses: "<resource_type>.<name>".

local fn = lambda.nodejs_function("my_function", "us-east-1", { timeout: 30 });

{
	"lambda.tf.json": fn,

	// Extend the role this call created, without knowing it's named
	// "lambda-my_function" internally.
	"extra.tf.json": {
		resource: {
			aws_iam_role_policy_attachment: {
				extra: {
					role: "${%s.id}" % fn.refs["aws_iam_role.lambda-my_function"].terraform_id,
					policy_arn: "arn:aws:iam::aws:policy/SomeOtherPolicy",
				},
			},
		},
	},
}

Each entry is the call's own info — name, region, and every option (as given, not merged with this plugin's own built-in defaults) — plus one hidden field, terraform_id, holding the exact address to build a reference from. fn.refs["aws_lambda_function.my_function"].region reads a raw value straight back; "${%s.arn}" % fn.refs["..."].terraform_id builds a Terraform reference to whichever attribute you need — refs never guesses which attribute you want, so it never goes stale as new ones matter.

refs is hidden (::), so — like config()'s internals — it never appears in the rendered .tf.json, only in Jsonnet itself. The full set of keys for one call: aws_lambda_function.<name>, aws_iam_role.lambda-<name>, aws_iam_role_policy.lambda-<name>, aws_cloudwatch_log_group.lambda-<name>, local_file.lambda-<name>_envvars, null_resource.npm_install-<name>, and data.archive_file.<name> (a data source's own reference syntax already starts with data., so that's the type prefix there too).

Installation

Install the plugin as a dev dependency in your SpellCraft project:

npm install --save @c6fc/spellcraft-aws-lambda

Once installed, import the module directly by package path:

local lambda = (import "@c6fc/spellcraft-aws-lambda/module.libsonnet").config({ thisFile: std.thisFile });
local aws = import "@c6fc/spellcraft-aws-terraform/module.libsonnet";

{
	'providers.tf.json': {
		provider: aws.providerAliases("us-east-1")
	},

	// Source lives in lambda_functions/my_function/, sibling to this file
	'lambda.tf.json': lambda.nodejs_function("my_function", "us-east-1", {
		timeout: 30,
		memory_size: 512,

		execution_policy_statements: [{
			Effect: "Allow",
			Action: ["s3:GetObject"],
			Resource: "arn:aws:s3:::my-bucket/*"
		}],

		event_triggers: [{
			schedule_expression: "rate(1 hour)"
		}]
	})
}

This module renders Terraform only; pair it with @c6fc/spellcraft-aws-terraform for the AWS provider definitions and state backend.

Documentation

Regenerate the API and CLI sections above with npx spellcraft doc from this directory.