jsonata-w 1.0.0 → 1.1.0
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 +28 -15
- package/dist/cli.js +10 -4
- package/dist/core/SchemaValidator.js +5 -2
- package/dist/core/SourceLoader.js +7 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,36 +1,41 @@
|
|
|
1
1
|
# JSONata Workflow (jsonata-w)
|
|
2
2
|
|
|
3
|
-
The **w** stands for **Workflow**. A command-line utility optimized to assist AI agents in transforming and inspecting JSON files, but equally powerful for manual workflows.
|
|
3
|
+
The **w** stands for **Workflow**. A command-line utility optimized to assist AI agents in transforming and inspecting JSON/YAML files, but equally powerful for manual workflows.
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
7
7
|
### Inspect
|
|
8
|
-
Inspects the structure of a JSON file.
|
|
8
|
+
Inspects the structure of a JSON or YAML file.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
jsonata-w inspect <file> [options]
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
#### Options
|
|
15
|
-
- `-s, --summary`: Show a high-level summary of the
|
|
15
|
+
- `-s, --summary`: Show a high-level summary of the structure (paths and keys).
|
|
16
16
|
- `--schema`: Generate and print the JSON schema for the scanned file.
|
|
17
17
|
- `-d, --depth <number>`: Limit the depth of inspection (default: 1).
|
|
18
|
-
- `--jsonpath <query>`: Filter the input
|
|
19
|
-
- `--jsonata <expression>`: Filter the input
|
|
18
|
+
- `--jsonpath <query>`: Filter the input using a JSONPath expression before inspecting.
|
|
19
|
+
- `--jsonata <expression>`: Filter the input using a JSONata expression before inspecting.
|
|
20
20
|
|
|
21
21
|
#### Examples
|
|
22
|
-
**Summary view:**
|
|
22
|
+
**Summary view (JSON):**
|
|
23
23
|
```bash
|
|
24
24
|
jsonata-w inspect data.json --summary
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
**Summary view (YAML):**
|
|
28
|
+
```bash
|
|
29
|
+
jsonata-w inspect tokens.yml --summary
|
|
30
|
+
```
|
|
31
|
+
|
|
27
32
|
**Filter with JSONPath:**
|
|
28
33
|
```bash
|
|
29
34
|
jsonata-w inspect data.json --jsonpath "$.users[*].name"
|
|
30
35
|
```
|
|
31
36
|
|
|
32
37
|
### Transform
|
|
33
|
-
Transforms a JSON file using a JSONata expression file. The input and output paths are defined directly within the JSONata file using a standard configuration block.
|
|
38
|
+
Transforms a JSON or YAML file using a JSONata expression file. The input and output paths are defined directly within the JSONata file using a standard configuration block.
|
|
34
39
|
|
|
35
40
|
```bash
|
|
36
41
|
jsonata-w transform <file>
|
|
@@ -40,11 +45,14 @@ jsonata-w transform <file>
|
|
|
40
45
|
The JSONata file MUST start with a configuration comment block:
|
|
41
46
|
|
|
42
47
|
```javascript
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
/**
|
|
49
|
+
* @config {
|
|
50
|
+
* "input": "./path/to/input.yml",
|
|
51
|
+
* "output": "./path/to/output.json",
|
|
52
|
+
* "schema": "./optional/schema.yml",
|
|
53
|
+
* "examples": "./path/to/example.yml"
|
|
54
|
+
* }
|
|
55
|
+
*/
|
|
48
56
|
|
|
49
57
|
(
|
|
50
58
|
/* Your JSONata expression here */
|
|
@@ -52,10 +60,15 @@ The JSONata file MUST start with a configuration comment block:
|
|
|
52
60
|
)
|
|
53
61
|
```
|
|
54
62
|
|
|
55
|
-
- `input`: Path to the source
|
|
56
|
-
- `output`: Path where the
|
|
57
|
-
- `
|
|
63
|
+
- `input`: Path to the source file — supports `.json`, `.yml`, `.yaml` (relative to the .jsonata file).
|
|
64
|
+
- `output`: Path where the result will be saved — format is auto-detected from extension:
|
|
65
|
+
- `.json` → JSON output
|
|
66
|
+
- `.yml` / `.yaml` → YAML output
|
|
67
|
+
- other → raw string output
|
|
68
|
+
- `schema`: (Optional) Path to a JSON or YAML schema for validation.
|
|
69
|
+
- `examples`: (Optional) Path to a JSON or YAML file containing the expected output subset for validation.
|
|
58
70
|
|
|
59
71
|
#### Features
|
|
72
|
+
- **YAML Support**: Full YAML support for input, output, schema, and example files. File format is detected from the extension (`.yml`/`.yaml` = YAML, everything else = JSON).
|
|
60
73
|
- **Embedded Config**: No need for CLI arguments for input/output.
|
|
61
74
|
- **Auto-Unflattening**: Results containing dot-notation keys (e.g., `{"a.b": 1}`) are automatically expanded into nested objects (`{"a": {"b": 1}}`). This simplifies generating deep hierarchies.
|
package/dist/cli.js
CHANGED
|
@@ -58,9 +58,9 @@ function pickSubset(data, template) {
|
|
|
58
58
|
return result;
|
|
59
59
|
}
|
|
60
60
|
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
61
|
-
.command('inspect <file>', 'Inspect JSON structure', (yargs) => {
|
|
61
|
+
.command('inspect <file>', 'Inspect JSON/YAML structure', (yargs) => {
|
|
62
62
|
return yargs
|
|
63
|
-
.positional('file', { describe: 'JSON file to inspect', type: 'string', demandOption: true })
|
|
63
|
+
.positional('file', { describe: 'JSON/YAML file to inspect', type: 'string', demandOption: true })
|
|
64
64
|
.option('depth', { alias: 'd', type: 'number', default: 1, describe: 'Depth to inspect' })
|
|
65
65
|
.option('summary', { alias: 's', type: 'boolean', default: false, describe: 'Show structure summary' })
|
|
66
66
|
.option('schema', { type: 'boolean', default: false, describe: 'Generate JSON schema from file' })
|
|
@@ -102,7 +102,7 @@ function pickSubset(data, template) {
|
|
|
102
102
|
process.exit(1);
|
|
103
103
|
}
|
|
104
104
|
})
|
|
105
|
-
.command('transform <file>', 'Transform JSON using a single JSONata file with embedded @config', (yargs) => {
|
|
105
|
+
.command('transform <file>', 'Transform JSON/YAML using a single JSONata file with embedded @config', (yargs) => {
|
|
106
106
|
return yargs
|
|
107
107
|
.positional('file', { describe: 'JSONata file with embedded @config', type: 'string', demandOption: true });
|
|
108
108
|
}, async (argv) => {
|
|
@@ -182,7 +182,13 @@ function pickSubset(data, template) {
|
|
|
182
182
|
const dir = path_1.default.dirname(outputPath);
|
|
183
183
|
if (!fs_1.default.existsSync(dir))
|
|
184
184
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
185
|
-
|
|
185
|
+
const isYamlOutput = outputPath.endsWith('.yml') || outputPath.endsWith('.yaml');
|
|
186
|
+
const outputContent = (typeof finalResult === 'string')
|
|
187
|
+
? finalResult
|
|
188
|
+
: isYamlOutput
|
|
189
|
+
? js_yaml_1.default.dump(finalResult, { indent: 2, lineWidth: -1 })
|
|
190
|
+
: JSON.stringify(finalResult, null, 2);
|
|
191
|
+
fs_1.default.writeFileSync(outputPath, outputContent);
|
|
186
192
|
console.log(`Transformed ${config.input} -> ${config.output}`);
|
|
187
193
|
}
|
|
188
194
|
catch (e) {
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.SchemaValidator = void 0;
|
|
7
7
|
const ajv_1 = __importDefault(require("ajv"));
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
9
10
|
class SchemaValidator {
|
|
10
11
|
constructor() {
|
|
11
12
|
this.ajv = new ajv_1.default();
|
|
@@ -17,10 +18,12 @@ class SchemaValidator {
|
|
|
17
18
|
const schemaContent = fs_1.default.readFileSync(schemaPath, 'utf-8');
|
|
18
19
|
let schema;
|
|
19
20
|
try {
|
|
20
|
-
|
|
21
|
+
const isYaml = schemaPath.endsWith('.yml') || schemaPath.endsWith('.yaml');
|
|
22
|
+
schema = isYaml ? js_yaml_1.default.load(schemaContent) : JSON.parse(schemaContent);
|
|
21
23
|
}
|
|
22
24
|
catch (_e) {
|
|
23
|
-
|
|
25
|
+
const format = (schemaPath.endsWith('.yml') || schemaPath.endsWith('.yaml')) ? 'YAML' : 'JSON';
|
|
26
|
+
throw new Error(`Invalid ${format} schema in file: ${schemaPath}`);
|
|
24
27
|
}
|
|
25
28
|
const validate = this.ajv.compile(schema);
|
|
26
29
|
const valid = validate(data);
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.SourceLoader = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
8
9
|
class SourceLoader {
|
|
9
10
|
constructor() {
|
|
10
11
|
this.cache = new Map();
|
|
@@ -18,12 +19,14 @@ class SourceLoader {
|
|
|
18
19
|
}
|
|
19
20
|
const content = fs_1.default.readFileSync(path, 'utf-8');
|
|
20
21
|
try {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
const isYaml = path.endsWith('.yml') || path.endsWith('.yaml');
|
|
23
|
+
const data = isYaml ? js_yaml_1.default.load(content) : JSON.parse(content);
|
|
24
|
+
this.cache.set(path, data);
|
|
25
|
+
return data;
|
|
24
26
|
}
|
|
25
27
|
catch (_e) {
|
|
26
|
-
|
|
28
|
+
const format = (path.endsWith('.yml') || path.endsWith('.yaml')) ? 'YAML' : 'JSON';
|
|
29
|
+
throw new Error(`Invalid ${format} in file: ${path}`);
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
clearCache() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsonata-w",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Tool to assist AI in transforming JSON files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,4 +44,4 @@
|
|
|
44
44
|
"typescript": "^5.7.2",
|
|
45
45
|
"typescript-eslint": "^8.51.0"
|
|
46
46
|
}
|
|
47
|
-
}
|
|
47
|
+
}
|