@dforge-core/dforge-cli 0.1.0-rc.1

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 +79 -0
  2. package/index.js +61 -0
  3. package/package.json +26 -0
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @dforge-core/dforge-cli
2
+
3
+ Native CLI for authoring dForge modules: validate, pack, publish to the
4
+ marketplace, install to a running tenant.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npm install -g @dforge-core/dforge-cli
10
+ # or, no install:
11
+ npx @dforge-core/dforge-cli --help
12
+ ```
13
+
14
+ npm picks the right platform binary via `optionalDependencies`. Supported:
15
+ macOS arm64/x64, Linux x64/arm64, Windows x64/arm64.
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ # STATIC checks: manifest identifiers, translation completeness, menu/folder/entity
21
+ # coverage, folder paths. DB-bound checks (FK target resolution, package-filter SQL,
22
+ # migration safety) only surface during `module install` against a live tenant —
23
+ # a clean `validate` does NOT guarantee a clean install.
24
+ dforge-cli module validate ./my-module
25
+ dforge-cli module validate ./my-module-1.0.0.dforge
26
+
27
+ # Package a module directory into a .dforge archive
28
+ dforge-cli module pack ./my-module # writes my-module-1.0.0.dforge in cwd
29
+ dforge-cli module pack ./my-module -o ./dist/ # writes ./dist/my-module-1.0.0.dforge
30
+ dforge-cli module pack ./my-module -o pkg.dforge # writes ./pkg.dforge
31
+
32
+ # Publish a .dforge to the marketplace (org-scoped)
33
+ dforge-cli marketplace publish ./my-module-1.0.0.dforge --org acme
34
+
35
+ # Install a .dforge (or source directory) to a running tenant over HTTP
36
+ DFORGE_URL=https://app.example.com DFORGE_TOKEN=<jwt> \
37
+ dforge-cli module install --path ./my-module-1.0.0.dforge
38
+
39
+ # DBML → module scaffold (stub — implementation lands in a follow-up)
40
+ dforge-cli dbml-import --from-dbml ./schema.dbml
41
+ ```
42
+
43
+ ## Auth
44
+
45
+ The remote `module install --url` and `marketplace publish` flows need a JWT
46
+ issued by the target dForge auth service. Three ways to provide one, in
47
+ precedence order:
48
+
49
+ 1. `--token <jwt>` on the command line
50
+ 2. `DFORGE_TOKEN` env var
51
+ 3. **Browser sign-in** (recommended):
52
+ ```bash
53
+ dforge-cli auth login --url https://app.example.com # for module install
54
+ dforge-cli marketplace login --marketplace-url https://... # for marketplace publish
55
+ ```
56
+ These open your browser to the tenant `/login` page, capture the OAuth
57
+ callback on `http://127.0.0.1:51719`, exchange the one-time code, and
58
+ **persist the resulting access token to disk** at:
59
+ - `~/.dforge/auth/<sha256-of-url>.json` — for `module install` / `auth login`
60
+ - `~/.dforge/marketplace/<sha256-of-url>.json` — for `marketplace login`
61
+
62
+ Files are mode 0600 on Unix. One file per target URL so a developer who
63
+ works against multiple environments (dev/staging/prod) stays signed in to
64
+ all of them. Clear with `dforge-cli auth logout [--url X | --all]` or the
65
+ marketplace equivalent. Inspect with `auth whoami` / `marketplace whoami`.
66
+
67
+ If you'd rather not write a token to disk, stick with `--token` /
68
+ `DFORGE_TOKEN` and the CLI won't touch `~/.dforge/`.
69
+
70
+ Optional `--code <tenantCd>` on `module install --url` is a sanity check: the
71
+ server verifies it matches the JWT's tenant and refuses with `TENANT_CODE_MISMATCH`
72
+ if not. Drop it if you trust the token.
73
+
74
+ ## Why a native CLI
75
+
76
+ The validate/pack/install pipeline is the same code that runs on the dForge
77
+ server, packaged as a single-file binary per platform via `dotnet publish
78
+ --self-contained`. Avoids drift between author-time validation and server-side
79
+ install validation: same parser, same validators, same error messages.
package/index.js ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ // Resolve the platform-specific binary package via require.resolve. Mirrors the
3
+ // esbuild distribution model: each supported platform is a separately-published
4
+ // optionalDependency with `os`/`cpu` pins, so npm installs only the right one
5
+ // for the user's machine. Fails fast with a clear message when no binary
6
+ // matches (most often: user is on an unsupported platform, or someone passed
7
+ // --no-optional to npm install).
8
+ const { spawnSync } = require("node:child_process");
9
+ const path = require("node:path");
10
+ const fs = require("node:fs");
11
+
12
+ const platformMap = {
13
+ "darwin-arm64": "@dforge-core/dforge-cli-darwin-arm64",
14
+ "darwin-x64": "@dforge-core/dforge-cli-darwin-x64",
15
+ "linux-x64": "@dforge-core/dforge-cli-linux-x64",
16
+ "linux-arm64": "@dforge-core/dforge-cli-linux-arm64",
17
+ "win32-x64": "@dforge-core/dforge-cli-win32-x64",
18
+ "win32-arm64": "@dforge-core/dforge-cli-win32-arm64",
19
+ };
20
+
21
+ function resolveBinary() {
22
+ const key = `${process.platform}-${process.arch}`;
23
+ const pkg = platformMap[key];
24
+ if (!pkg) {
25
+ console.error(
26
+ `dforge-cli: unsupported platform "${key}". Supported: ${Object.keys(platformMap).join(", ")}.`,
27
+ );
28
+ process.exit(1);
29
+ }
30
+
31
+ let pkgJsonPath;
32
+ try {
33
+ pkgJsonPath = require.resolve(`${pkg}/package.json`);
34
+ } catch {
35
+ console.error(
36
+ `dforge-cli: platform package "${pkg}" not installed. ` +
37
+ `Re-run \`npm install\` without --no-optional, or install it explicitly.`,
38
+ );
39
+ process.exit(1);
40
+ }
41
+
42
+ const pkgDir = path.dirname(pkgJsonPath);
43
+ const binName = process.platform === "win32" ? "dforge-cli.exe" : "dforge-cli";
44
+ const binPath = path.join(pkgDir, "bin", binName);
45
+ if (!fs.existsSync(binPath)) {
46
+ console.error(`dforge-cli: binary missing at ${binPath}`);
47
+ process.exit(1);
48
+ }
49
+ return binPath;
50
+ }
51
+
52
+ const result = spawnSync(resolveBinary(), process.argv.slice(2), {
53
+ stdio: "inherit",
54
+ shell: false,
55
+ });
56
+
57
+ if (result.error) {
58
+ console.error(`dforge-cli: failed to exec binary: ${result.error.message}`);
59
+ process.exit(1);
60
+ }
61
+ process.exit(result.status ?? 1);
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@dforge-core/dforge-cli",
3
+ "version": "0.1.0-rc.1",
4
+ "description": "dForge CLI — validate, pack, publish, and install dForge modules. Distributes a single-file native binary per platform via optionalDependencies (esbuild-style).",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/dforge-core/create-module",
7
+ "bin": {
8
+ "dforge-cli": "index.js"
9
+ },
10
+ "files": [
11
+ "index.js",
12
+ "README.md"
13
+ ],
14
+ "main": "index.js",
15
+ "engines": {
16
+ "node": ">=18"
17
+ },
18
+ "optionalDependencies": {
19
+ "@dforge-core/dforge-cli-darwin-arm64": "0.1.0-rc.1",
20
+ "@dforge-core/dforge-cli-darwin-x64": "0.1.0-rc.1",
21
+ "@dforge-core/dforge-cli-win32-x64": "0.1.0-rc.1",
22
+ "@dforge-core/dforge-cli-linux-x64": "0.1.0-rc.1",
23
+ "@dforge-core/dforge-cli-win32-arm64": "0.1.0-rc.1",
24
+ "@dforge-core/dforge-cli-linux-arm64": "0.1.0-rc.1"
25
+ }
26
+ }