@morphql/cli 0.1.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniele Traverso
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # @morphql/cli
2
+
3
+ CLI tool for **morphql** - structural data transformation powered by the Morph Query Language (MorphQL).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @morphql/cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ morphql [-f <input-file> | -i <raw-input>] [-t <output-file>] -q <query>
15
+ ```
16
+
17
+ ### Options
18
+
19
+ - `-f, --from <path>`: Path to the source file (JSON, XML).
20
+ - `-i, --input <string>`: Raw source content as a string.
21
+ - `-t, --to <path>`: Path to the destination file. If omitted, result is printed to `stdout`.
22
+ - `-q, --query <string>`: The MorphQL query to execute.
23
+ - `--cache-dir <path>`: Directory for compiled cache (default: `.compiled`).
24
+
25
+ ### Examples
26
+
27
+ **Transforming a file to another file:**
28
+
29
+ ```bash
30
+ morphql --from ./data.json --to ./output.xml -q "from json to xml transform set fullName = firstName + \" \" + lastName"
31
+ ```
32
+
33
+ **Transforming raw input to stdout (useful for piping):**
34
+
35
+ ```bash
36
+ morphql -i '{"name": "John"}' -q "from json to xml"
37
+ ```
38
+
39
+ **Piping output to another tool:**
40
+
41
+ ```bash
42
+ morphql --from data.json -q "from json to json" | jq .
43
+ ```
44
+
45
+ > [!NOTE]
46
+ > All status and success messages are printed to `stderr`, ensuring that `stdout` contains only the transformation result.
47
+
48
+ ## Features
49
+
50
+ - **Blazing Fast**: Compiles queries to native JavaScript for high performance.
51
+ - **Smart Caching**: Standardized file-system caching to avoid re-compilation of queries.
52
+ - **Format Agnostic**: Seamlessly convert between JSON and XML.
53
+ - **Shell Friendly**: Supports raw input strings and stdout output for easy integration into pipelines.
54
+
55
+ ## License
56
+
57
+ MIT
package/bin/morphql.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ // src/index.ts
2
+ import { compile } from "@morphql/core";
3
+
4
+ // src/file-cache.ts
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ import { createHash } from "crypto";
8
+ var MorphQLFileCache = class {
9
+ cacheDir;
10
+ constructor(cacheDir = ".compiled") {
11
+ this.cacheDir = path.resolve(process.cwd(), cacheDir);
12
+ }
13
+ async retrieve(query) {
14
+ try {
15
+ const hash = this.getHash(query);
16
+ const filePath = path.join(this.cacheDir, `morph_${hash}.js`);
17
+ if (fs.existsSync(filePath)) {
18
+ return fs.promises.readFile(filePath, "utf8");
19
+ }
20
+ } catch (err) {
21
+ }
22
+ return null;
23
+ }
24
+ async save(query, code) {
25
+ try {
26
+ if (!fs.existsSync(this.cacheDir)) {
27
+ fs.mkdirSync(this.cacheDir, { recursive: true });
28
+ }
29
+ const hash = this.getHash(query);
30
+ const filePath = path.join(this.cacheDir, `morph_${hash}.js`);
31
+ const content = `/*
32
+ Query:
33
+ ${query}
34
+ */
35
+
36
+ ${code}`;
37
+ await fs.promises.writeFile(filePath, content, "utf8");
38
+ } catch (err) {
39
+ }
40
+ }
41
+ getHash(content) {
42
+ return createHash("sha256").update(content).digest("hex").substring(0, 12);
43
+ }
44
+ };
45
+
46
+ // src/index.ts
47
+ import { Command } from "commander";
48
+ import * as fs2 from "fs/promises";
49
+ import * as path2 from "path";
50
+ import { existsSync as existsSync2 } from "fs";
51
+ async function readStdin() {
52
+ const chunks = [];
53
+ for await (const chunk of process.stdin) {
54
+ chunks.push(chunk);
55
+ }
56
+ return Buffer.concat(chunks).toString("utf8");
57
+ }
58
+ var program = new Command();
59
+ program.name("morphql").description(
60
+ "CLI tool for morphql - transform structural data from the command line."
61
+ ).version("0.1.3").option("-f, --from <path>", "Path to the source file").option("-i, --input <string>", "Raw source content as string").option(
62
+ "-t, --to <path>",
63
+ "Path to the destination file (if omitted, result is printed to stdout)"
64
+ ).requiredOption("-q, --query <string>", "MorphQL query string").option("--cache-dir <path>", "Directory for compiled cache", ".compiled").action(async (options) => {
65
+ try {
66
+ const { from, input, to, query, cacheDir } = options;
67
+ let sourceContent;
68
+ if (input) {
69
+ sourceContent = input;
70
+ } else if (from) {
71
+ if (!existsSync2(from)) {
72
+ console.error(`Error: Source file not found: ${from}`);
73
+ process.exit(1);
74
+ }
75
+ sourceContent = await fs2.readFile(from, "utf8");
76
+ } else if (!process.stdin.isTTY) {
77
+ sourceContent = await readStdin();
78
+ } else {
79
+ console.error(
80
+ "Error: Either --from <path>, --input <string>, or pipe data via stdin must be provided."
81
+ );
82
+ process.exit(1);
83
+ }
84
+ const cache = new MorphQLFileCache(cacheDir);
85
+ const engine = await compile(query, { cache });
86
+ const result = await engine(sourceContent);
87
+ if (to) {
88
+ const destDir = path2.dirname(to);
89
+ if (!existsSync2(destDir)) {
90
+ await fs2.mkdir(destDir, { recursive: true });
91
+ }
92
+ await fs2.writeFile(to, result, "utf8");
93
+ console.error(`Successfully transformed to ${to}`);
94
+ } else {
95
+ console.log(result);
96
+ }
97
+ } catch (error) {
98
+ console.error(`Error during transformation: ${error.message}`);
99
+ process.exit(1);
100
+ }
101
+ });
102
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@morphql/cli",
3
+ "version": "0.1.3",
4
+ "description": "CLI tool for morphql - transform structural data from the command line.",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "bin": {
10
+ "morphql": "./bin/morphql.js"
11
+ },
12
+ "scripts": {
13
+ "build": "tsup src/index.ts --format esm --clean",
14
+ "dev": "tsup src/index.ts --format esm --watch",
15
+ "lint": "eslint src/**/*.ts",
16
+ "typecheck": "tsc --noEmit"
17
+ },
18
+ "keywords": [
19
+ "morphql",
20
+ "cli",
21
+ "transform",
22
+ "json",
23
+ "xml"
24
+ ],
25
+ "author": "Hyperwindmill",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/Hyperwindmill/morphql.git",
30
+ "directory": "packages/cli"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/Hyperwindmill/morphql/issues"
34
+ },
35
+ "homepage": "https://github.com/Hyperwindmill/morphql/tree/main/packages/cli#readme",
36
+ "files": [
37
+ "dist",
38
+ "bin",
39
+ "README.md",
40
+ "LICENSE"
41
+ ],
42
+ "dependencies": {
43
+ "@morphql/core": "*",
44
+ "commander": "^13.1.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^25.0.9",
48
+ "tsup": "^8.5.1",
49
+ "typescript": "^5.9.3"
50
+ }
51
+ }