jsonata-w 1.0.0 → 1.0.2

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.
Files changed (3) hide show
  1. package/README.md +9 -5
  2. package/dist/cli.js +42 -10
  3. package/package.json +17 -2
package/README.md CHANGED
@@ -40,11 +40,14 @@ jsonata-w transform <file>
40
40
  The JSONata file MUST start with a configuration comment block:
41
41
 
42
42
  ```javascript
43
- /* @config {
44
- "input": "./path/to/input.json",
45
- "output": "./path/to/output.json",
46
- "schema": "./optional/schema.json"
47
- } */
43
+ /**
44
+ * @config {
45
+ * "input": "./path/to/input.json",
46
+ * "output": "./path/to/output.json",
47
+ * "schema": "./optional/schema.json",
48
+ * "examples": "./path/to/example.json"
49
+ * }
50
+ */
48
51
 
49
52
  (
50
53
  /* Your JSONata expression here */
@@ -55,6 +58,7 @@ The JSONata file MUST start with a configuration comment block:
55
58
  - `input`: Path to the source JSON file (relative to the .jsonata file).
56
59
  - `output`: Path where the transformed JSON will be saved (relative to the .jsonata file).
57
60
  - `schema`: (Optional) Path to a JSON schema for validation.
61
+ - `examples`: (Optional) Path to a JSON/YAML file containing the expected output subset for validation.
58
62
 
59
63
  #### Features
60
64
  - **Embedded Config**: No need for CLI arguments for input/output.
package/dist/cli.js CHANGED
@@ -104,7 +104,8 @@ function pickSubset(data, template) {
104
104
  })
105
105
  .command('transform <file>', 'Transform JSON using a single JSONata file with embedded @config', (yargs) => {
106
106
  return yargs
107
- .positional('file', { describe: 'JSONata file with embedded @config', type: 'string', demandOption: true });
107
+ .positional('file', { describe: 'JSONata file with embedded @config', type: 'string', demandOption: true })
108
+ .option('dry-run', { type: 'boolean', default: false, describe: 'Execute and validate without writing output to disk' });
108
109
  }, async (argv) => {
109
110
  try {
110
111
  const filePath = path_1.default.resolve(argv.file);
@@ -117,12 +118,14 @@ function pickSubset(data, template) {
117
118
  const resolvePath = (p) => path_1.default.resolve(fileDir, p);
118
119
  const inputPath = resolvePath(config.input);
119
120
  const outputPath = resolvePath(config.output);
120
- console.log(`Loading input from ${inputPath}...`);
121
+ if (!argv['dry-run'])
122
+ console.log(`Loading input from ${inputPath}...`);
121
123
  const json = loader.load(inputPath);
122
- console.log(`Executing transformation...`);
123
- // Use evaluate since we already have the content
124
+ if (!argv['dry-run'])
125
+ console.log(`Executing transformation...`);
124
126
  const result = await transformer.evaluate(json, fileContent);
125
- console.log(`Unflattening result...`);
127
+ if (!argv['dry-run'])
128
+ console.log(`Unflattening result...`);
126
129
  const finalResult = unflatten(result);
127
130
  if (config.schema) {
128
131
  const schemaPath = resolvePath(config.schema);
@@ -179,11 +182,40 @@ function pickSubset(data, template) {
179
182
  console.log('✅ Example validation passed.');
180
183
  }
181
184
  }
182
- const dir = path_1.default.dirname(outputPath);
183
- if (!fs_1.default.existsSync(dir))
184
- fs_1.default.mkdirSync(dir, { recursive: true });
185
- fs_1.default.writeFileSync(outputPath, JSON.stringify(finalResult, null, 2));
186
- console.log(`Transformed ${config.input} -> ${config.output}`);
185
+ // Determine output format based on file extension
186
+ const ext = path_1.default.extname(outputPath).toLowerCase();
187
+ let outputContent;
188
+ if (ext === '.yaml' || ext === '.yml') {
189
+ outputContent = js_yaml_1.default.dump(finalResult, { indent: 2, lineWidth: -1 });
190
+ }
191
+ else if (ext === '.json') {
192
+ outputContent = JSON.stringify(finalResult, null, 2);
193
+ }
194
+ else {
195
+ // For other extensions (e.g., .css, .txt, .js), output as string
196
+ if (typeof finalResult === 'string') {
197
+ outputContent = finalResult;
198
+ }
199
+ else if (Array.isArray(finalResult) && finalResult.every(item => typeof item === 'string')) {
200
+ outputContent = finalResult.join('');
201
+ }
202
+ else if (typeof finalResult === 'number' || typeof finalResult === 'boolean') {
203
+ outputContent = String(finalResult);
204
+ }
205
+ else {
206
+ outputContent = JSON.stringify(finalResult, null, 2);
207
+ }
208
+ }
209
+ if (argv['dry-run']) {
210
+ process.stdout.write(outputContent);
211
+ }
212
+ else {
213
+ const dir = path_1.default.dirname(outputPath);
214
+ if (!fs_1.default.existsSync(dir))
215
+ fs_1.default.mkdirSync(dir, { recursive: true });
216
+ fs_1.default.writeFileSync(outputPath, outputContent);
217
+ console.log(`Transformed ${config.input} -> ${config.output}`);
218
+ }
187
219
  }
188
220
  catch (e) {
189
221
  console.error(e.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsonata-w",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Tool to assist AI in transforming JSON files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -20,6 +20,21 @@
20
20
  },
21
21
  "author": "",
22
22
  "license": "ISC",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/pen-drop/jsonata-w.git"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/pen-drop/jsonata-w/issues"
29
+ },
30
+ "homepage": "https://github.com/pen-drop/jsonata-w#readme",
31
+ "keywords": [
32
+ "jsonata",
33
+ "json",
34
+ "yaml",
35
+ "transform",
36
+ "cli"
37
+ ],
23
38
  "dependencies": {
24
39
  "@types/jsonpath": "^0.2.4",
25
40
  "ajv": "^8.17.1",
@@ -44,4 +59,4 @@
44
59
  "typescript": "^5.7.2",
45
60
  "typescript-eslint": "^8.51.0"
46
61
  }
47
- }
62
+ }