@c6fc/spellcraft 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,189 @@
1
- # SpellCraft for JSonnet workflows
1
+ # SpellCraft
2
2
 
3
- Spellcraft is an opinionated approach to manifesting and applying configurations for various tools. SpellCraft is the core engine which can accept plugins like @c6fc/spellcraft-packer for Hashicorp Packer configurations, or @c6fc/spellcraft-aws for interacting with Amazon Web Services
3
+ **The Sorcerer's Toolkit for Unified Configuration Management.**
4
4
 
5
- ## Installation
5
+ SpellCraft is a powerful framework for generating and managing configurations across a diverse toolchain. It was born from the challenge of orchestrating tools like Terraform, Packer, Kubernetes, and Ansible, each with its own fragmented and isolated configuration format (YAML, JSON, HCL, etc.).
6
6
 
7
- Install spellcraft with `npm install` and add plugins with `npx spellcraft importModule`
7
+ SpellCraft provides a single, unified source of truth, allowing you to generate tightly-integrated, context-aware configurations for any tool, all from one place.
8
+
9
+ [![NPM Version](https://img.shields.io/npm/v/@c6fc/spellcraft.svg)](https://www.npmjs.com/package/@c6fc/spellcraft)
10
+ [![License](https://img.shields.io/npm/l/@c6fc/spellcraft.svg)](https://github.com/your-repo/spellcraft/blob/main/LICENSE)
11
+
12
+ ---
13
+
14
+ ## The SpellCraft Philosophy
15
+
16
+ SpellCraft is built on three core principles to provide a superior Infrastructure-as-Code experience:
17
+
18
+ 1. **Declarative Power (Jsonnet):** Configurations are written in [Jsonnet](https://jsonnet.org/), a superset of JSON. This gives you the power of variables, functions, conditionals, loops, and inheritance, eliminating the endless copy-pasting and structural limitations of plain YAML or JSON. Define a component once, and reuse it everywhere.
19
+
20
+ 2. **Seamless Extensibility (Node.js):** Sometimes, declarative logic isn't enough. SpellCraft allows you to "escape" the confines of Jsonnet by writing custom logic in Node.js. Need to fetch a secret from a vault, call a third-party API, or perform complex data manipulation? Simply write a JavaScript function and expose it directly to your Jsonnet code as a `std.native()` function.
21
+
22
+ 3. **Robust Modularity (NPM):** SpellCraft's module system is built on the battle-tested foundation of NPM. This means you can version, share, and manage your infrastructure modules just like any other software dependency. Leverage public or private NPM registries to build a reusable, maintainable, and collaborative infrastructure codebase.
23
+
24
+ ## Quick Start
25
+
26
+ Get up and running with SpellCraft in minutes.
27
+
28
+ ### 1. Installation
29
+
30
+ Install the SpellCraft CLI and core library into your project.
31
+
32
+ ```sh
33
+ npm install --save @c6fc/spellcraft
34
+ ```
35
+
36
+ ### 2. Import a Module
37
+
38
+ Modules are the building blocks of SpellCraft. Let's import a module for interacting with AWS. The `importModule` command will install the package from NPM and link it into your project.
39
+
40
+ ```sh
41
+ npx spellcraft importModule @c6fc/spellcraft-aws-auth
42
+
43
+ # Expected Output:
44
+ # [*] Attempting to install @c6fc/spellcraft-aws-auth...
45
+ # [+] Successfully installed @c6fc/spellcraft-aws-auth.
46
+ # [+] Linked @c6fc/spellcraft-aws-auth as SpellCraft module 'awsauth'
47
+ ```
48
+ This makes the `@c6fc/spellcraft-aws-auth` package available in your Jsonnet files under the name `awsauth`.
49
+
50
+ ### 3. Create Your First Spell
51
+
52
+ A "Spell" is a `.jsonnet` file that defines the files you want to create. The top-level keys of the output object become filenames.
53
+
54
+ Create a file named `manifest.jsonnet`:
55
+ ```jsonnet
56
+ // manifest.jsonnet
57
+ local modules = import 'modules';
58
+
59
+ {
60
+ // The 'awsauth' module provides a native function `getCallerIdentity()`.
61
+ // We call it here and direct its output to a file named 'aws-identity.json'.
62
+ 'aws-identity.json': modules.awsauth.getCallerIdentity(),
63
+
64
+ // We can also create YAML files. SpellCraft has built-in handlers for common types.
65
+ 'config.yaml': {
66
+ apiVersion: 'v1',
67
+ kind: 'ConfigMap',
68
+ metadata: {
69
+ name: 'my-app-config',
70
+ },
71
+ data: {
72
+ region: std.native('envvar')('AWS_REGION') || 'us-east-1',
73
+ // The result of the native function is just data. We can reuse it!
74
+ callerArn: modules.awsauth.getCallerIdentity().Arn,
75
+ },
76
+ },
77
+ }
78
+ ```
79
+
80
+ ### 4. Generate the Artifacts
81
+
82
+ Use the `generate` command to render your `.jsonnet` file into the `render/` directory.
8
83
 
9
84
  ```sh
10
- $ npm i -p @c6fc/spellcraft
11
- $ npx spellcraft importModule @c6fc/spellcraft-packer packer
85
+ npx spellcraft generate manifest.jsonnet
86
+
87
+ # Expected Output:
88
+ # [+] Linked @c6fc/spellcraft-aws-auth as awsauth.libsonnet
89
+ # ...
90
+ # [+] Registered native functions [getCallerIdentity, ...] to modules.awsauth
91
+ # [+] Evaluating Jsonnet file manifest.jsonnet
92
+ # [+] Writing files to: render
93
+ # -> aws-identity.json
94
+ # -> config.yaml
95
+ # [+] Generation complete.
96
+ ```
97
+
98
+ Check your `render/` directory. You will find two files created from your single source of truth!
99
+
100
+ ```
101
+ .
102
+ ├── manifest.jsonnet
103
+ ├── node_modules/
104
+ ├── package.json
105
+ └── render/
106
+ ├── aws-identity.json
107
+ └── config.yaml
108
+ ```
109
+
110
+ ## The SpellCraft CLI
111
+
112
+ The `spellcraft` CLI is your primary interface for managing modules and generating files.
113
+
114
+ ### Core Commands
115
+
116
+ - `generate <filename>`: Renders a `.jsonnet` file and writes the output to the `render/` directory.
117
+ - `importModule <npmPackage> [name]`: Installs an NPM package and links it as a SpellCraft module. If `[name]` is omitted, it uses the default name defined by the module.
118
+
119
+ ### Extensible CLI
120
+
121
+ Modules can extend the SpellCraft CLI with their own custom commands. For example, after importing `@c6fc/spellcraft-aws-auth`, you gain new AWS-related commands.
122
+
123
+ Run `npx spellcraft --help` to see all available commands, including those added by modules.
124
+
125
+ ```sh
126
+ $ npx spellcraft --help
127
+
128
+ # ... output showing core commands and module-added commands ...
129
+ Commands:
130
+ spellcraft generate <filename> Generates files from a configuration
131
+ spellcraft importModule <npmPackage> [name] Configures the current project to use a SpellCraft module
132
+ spellcraft aws-identity Display the AWS IAM identity of the SpellCraft context
133
+ spellcraft aws-exportcredentials Export the current credentials as environment variables
12
134
  ```
13
135
 
14
- The importModule command above will expose the methods from `@c6fc/spellcraft-packer` with `local packer = require "packer"`
136
+ ## Programmatic Usage (API)
137
+
138
+ For more advanced workflows, such as integration into larger automation scripts, you can use the `SpellFrame` class directly in your Node.js code.
139
+
140
+ The typical flow is:
141
+ 1. Instantiate `SpellFrame`.
142
+ 2. Load necessary modules.
143
+ 3. (Optional) Run module initializers with `init()`.
144
+ 4. Render the Jsonnet file with `render()`.
145
+ 5. Write the resulting object to disk with `write()`.
146
+
147
+ ```javascript
148
+ // my-automation-script.js
149
+ const { SpellFrame } = require('@c6fc/spellcraft');
150
+ const path = require('path');
151
+
152
+ // 1. Instantiate the SpellFrame
153
+ // Options allow you to customize output paths, cleaning behavior, etc.
154
+ const frame = new SpellFrame({
155
+ renderPath: "dist", // Output to 'dist/' instead of 'render/'
156
+ cleanBeforeRender: true,
157
+ });
158
+
159
+ (async () => {
160
+ try {
161
+ // 2. Load modules programmatically (this assumes they are in package.json)
162
+ // This loads modules listed in 'spellcraft_modules/packages.json'
163
+ // and from the local 'spellcraft_modules/' directory.
164
+ // frame.loadModuleByName('my-module-key', 'my-npm-package');
165
+
166
+ // 3. Initialize modules (if any modules registered an init function)
167
+ await frame.init();
168
+
169
+ // 4. Render the master Jsonnet file
170
+ const manifest = await frame.render(path.resolve('./manifest.jsonnet'));
171
+
172
+ // The result is available in memory
173
+ console.log('Rendered Manifest:', JSON.stringify(manifest, null, 2));
174
+
175
+ // 5. Write the manifest object to the filesystem
176
+ frame.write(manifest);
177
+
178
+ console.log('Successfully wrote files to the dist/ directory!');
179
+
180
+ } catch (error) {
181
+ console.error('An error occurred during the SpellCraft process:', error);
182
+ process.exit(1);
183
+ }
184
+ })();
185
+ ```
15
186
 
187
+ ## Creating Your Own Spells (Modules)
16
188
 
17
- ## More details to be added soon
189
+ When you're ready to start writing your own modules and unleashing the true power of SpellCraft, check out **[create-spellcraft-module](https://www.npmjs.com/package/@c6fc/spellcraft)**
package/bin/spellcraft.js CHANGED
@@ -115,7 +115,7 @@ const spellframe = new SpellFrame();
115
115
  },
116
116
  async (argv) => {
117
117
  await sfInstance.importSpellCraftModuleFromNpm(argv.npmPackage, argv.name);
118
- console.log(`[+] Module '${argv.npmPackage.green}' ${argv.name ? `(aliased as ${argv.name.green})` : ''} linked successfully.`);
118
+ console.log(`[+] Module '${argv.npmPackage.green}' ${argv.name ? `(aliased as ${argv.name.green}) ` : ''}linked successfully.`);
119
119
  });
120
120
 
121
121
  // No JSDoc for CLI extensions loop if considered internal detail
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "name": "@c6fc/spellcraft",
10
10
  "description": "Extensible JSonnet CLI platform",
11
- "version": "0.0.7",
11
+ "version": "0.0.8",
12
12
  "main": "src/index.js",
13
13
  "directories": {
14
14
  "lib": "lib"
package/src/index.js CHANGED
@@ -1,4 +1,3 @@
1
- // ./src/index.js
2
1
  'use strict';
3
2
 
4
3
  const fs = require("fs");
@@ -129,7 +128,7 @@ exports.SpellFrame = class SpellFrame {
129
128
  }
130
129
 
131
130
  addJpath(jpath) {
132
- console.log(`[*] Adding Jpath ${jpath}`);
131
+ // console.log(`[*] Adding Jpath ${jpath}`);
133
132
  this.jsonnet.addJpath(jpath);
134
133
  return this;
135
134
  }