create-spellcraft
v0.1.0
Published
Scaffolds a new spell for @c6fc/spellcraft.
Readme
create-spellcraft
Scaffolds a new spell for SpellCraft.
npm init spellcraft my-spell
cd my-spell
npm run genA spell is a project you render, not a package you publish. If you're building
something for other projects to import, you want
create-spellcraft-module
instead.
Usage
npm init spellcraft [directory] [options]
npx create-spellcraft [directory] [options]The directory is created if it doesn't exist and defaults to the current one.
Anything not passed as an option is prompted for, with a default drawn from your
npm config (init-author-name, init-author-email, init-scope), your git
config, and the directory name.
| option | default |
|---|---|
| --name <name> | directory name, scoped by init-scope |
| --description <text> | — |
| --author <author> | npm config, then git config |
| --license <id> | MIT |
| --repo <url> | git remote get-url origin, when the target is the repo root |
| -y, --yes | take every default, never prompt |
npm init can consume flags before they reach the generator, so pass them after
a -- separator, or call npx create-spellcraft directly:
npm init spellcraft my-spell -- --yesWithout a TTY the generator never prompts: it takes every default rather than
hanging a CI job on a question, and fails outright only when it cannot settle on
a name — pass --name if the directory basename isn't a valid npm package name.
It also refuses to scaffold into a directory that holds other projects, which
is the shape of ~/repos and almost never the shape of a spell directory.
What gets generated
├── manifest.jsonnet the spell itself; start here
├── spellcraft_modules/
│ └── util.js local JavaScript, reachable from Jsonnet
├── package.json
├── .gitignore
├── LICENSE MIT only; another --license emits none
└── README.mdHow a spell works
manifest.jsonnet is the whole program. Its top-level keys are filenames and
its values are the file contents, so spellcraft generate manifest.jsonnet
evaluates it and writes the result into render/.
What makes this more than a templating language is that evaluation can call live APIs. Configuration works out its own context — account IDs, existing buckets, enabled services — instead of having those values pasted into it.
Three kinds of import are available:
local spellcraft = import "spellcraft"; // built-ins
local modules = import "modules"; // spellcraft_modules/
local aws = import "@c6fc/spellcraft-aws-auth/module.libsonnet"; // installed pluginsLocal JavaScript
Every .js file in spellcraft_modules/ is loaded automatically, and its
exports appear in Jsonnet as modules.<filename>.<export>. This is the fast
path — no package, no metadata, no publishing — for the one-off logic Jsonnet
can't express on its own.
exports.replicasFor = [(environment) => environment === 'prod' ? 3 : 1, 'environment'];{ "app.json": { replicas: modules.util.replicasFor("prod") } }When that logic outgrows a single file, or you want to share it between spells, it graduates to a plugin.
Plugins
Plugins are ordinary npm packages. Core finds them by walking your dependencies
for packages flagged "spellcraft": true, so installing one is all it takes:
npm install --save @c6fc/spellcraft-aws-authlocal aws = import "@c6fc/spellcraft-aws-auth/module.libsonnet";
{ "account.json": aws.getCallerIdentity() }Development
npm testThe tests generate real spells into temp directories and assert that they install cleanly, render the output the templates promise, and trip the safety guards.
