@dforge-core/dforge-cli 0.2.16 → 0.2.17
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/dist/cli.js +147 -112
- package/dist/lib.d.mts +48 -4
- package/dist/lib.d.ts +48 -4
- package/dist/lib.js +109 -20
- package/dist/lib.mjs +104 -19
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -272,7 +272,7 @@ function fD({ input: e2 = import_node_process.stdin, output: u2 = import_node_pr
|
|
|
272
272
|
e2.off("keypress", i), F2 && u2.write(import_sisteransi.cursor.show), e2.isTTY && !AD && e2.setRawMode(false), s.terminal = false, s.close();
|
|
273
273
|
};
|
|
274
274
|
}
|
|
275
|
-
var import_sisteransi, import_node_process, g, import_node_readline, import_node_stream, import_picocolors, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, dD, A,
|
|
275
|
+
var import_sisteransi, import_node_process, g, import_node_readline, import_node_stream, import_picocolors, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, dD, A, OD, PD, J, LD, RD;
|
|
276
276
|
var init_dist = __esm({
|
|
277
277
|
"node_modules/.pnpm/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
|
|
278
278
|
"use strict";
|
|
@@ -514,41 +514,6 @@ var init_dist = __esm({
|
|
|
514
514
|
}
|
|
515
515
|
};
|
|
516
516
|
A = /* @__PURE__ */ new WeakMap();
|
|
517
|
-
kD = Object.defineProperty;
|
|
518
|
-
$D = (e2, u2, t) => u2 in e2 ? kD(e2, u2, { enumerable: true, configurable: true, writable: true, value: t }) : e2[u2] = t;
|
|
519
|
-
H = (e2, u2, t) => ($D(e2, typeof u2 != "symbol" ? u2 + "" : u2, t), t);
|
|
520
|
-
SD = class extends x {
|
|
521
|
-
constructor(u2) {
|
|
522
|
-
super(u2, false), H(this, "options"), H(this, "cursor", 0), this.options = u2.options, this.value = [...u2.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: t }) => t === u2.cursorAt), 0), this.on("key", (t) => {
|
|
523
|
-
t === "a" && this.toggleAll();
|
|
524
|
-
}), this.on("cursor", (t) => {
|
|
525
|
-
switch (t) {
|
|
526
|
-
case "left":
|
|
527
|
-
case "up":
|
|
528
|
-
this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
|
|
529
|
-
break;
|
|
530
|
-
case "down":
|
|
531
|
-
case "right":
|
|
532
|
-
this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
|
|
533
|
-
break;
|
|
534
|
-
case "space":
|
|
535
|
-
this.toggleValue();
|
|
536
|
-
break;
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
get _value() {
|
|
541
|
-
return this.options[this.cursor].value;
|
|
542
|
-
}
|
|
543
|
-
toggleAll() {
|
|
544
|
-
const u2 = this.value.length === this.options.length;
|
|
545
|
-
this.value = u2 ? [] : this.options.map((t) => t.value);
|
|
546
|
-
}
|
|
547
|
-
toggleValue() {
|
|
548
|
-
const u2 = this.value.includes(this._value);
|
|
549
|
-
this.value = u2 ? this.value.filter((t) => t !== this._value) : [...this.value, this._value];
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
517
|
OD = Object.defineProperty;
|
|
553
518
|
PD = (e2, u2, t) => u2 in e2 ? OD(e2, u2, { enumerable: true, configurable: true, writable: true, value: t }) : e2[u2] = t;
|
|
554
519
|
J = (e2, u2, t) => (PD(e2, typeof u2 != "symbol" ? u2 + "" : u2, t), t);
|
|
@@ -598,7 +563,7 @@ var init_dist = __esm({
|
|
|
598
563
|
function ce() {
|
|
599
564
|
return import_node_process2.default.platform !== "win32" ? import_node_process2.default.env.TERM !== "linux" : !!import_node_process2.default.env.CI || !!import_node_process2.default.env.WT_SESSION || !!import_node_process2.default.env.TERMINUS_SUBLIME || import_node_process2.default.env.ConEmuTask === "{cmd::Cmder}" || import_node_process2.default.env.TERM_PROGRAM === "Terminus-Sublime" || import_node_process2.default.env.TERM_PROGRAM === "vscode" || import_node_process2.default.env.TERM === "xterm-256color" || import_node_process2.default.env.TERM === "alacritty" || import_node_process2.default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
600
565
|
}
|
|
601
|
-
var import_node_util, import_node_process2, import_picocolors2, import_sisteransi2, V2, u, le, L2, W2, C, ue, o, d2, k2, P2, A2, T, F, $e, _2, me, de, pe, q, D, U, K2, b2, G2, he, ye, ve,
|
|
566
|
+
var import_node_util, import_node_process2, import_picocolors2, import_sisteransi2, V2, u, le, L2, W2, C, ue, o, d2, k2, P2, A2, T, F, $e, _2, me, de, pe, q, D, U, K2, b2, G2, he, ye, ve, xe, Ie, Se, J2, Y2, Ce;
|
|
602
567
|
var init_dist2 = __esm({
|
|
603
568
|
"node_modules/.pnpm/@clack+prompts@0.11.0/node_modules/@clack/prompts/dist/index.mjs"() {
|
|
604
569
|
"use strict";
|
|
@@ -722,46 +687,6 @@ ${import_picocolors2.default.gray(o)}`;
|
|
|
722
687
|
return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
|
|
723
688
|
${import_picocolors2.default.cyan(o)} `)}
|
|
724
689
|
${import_picocolors2.default.cyan(d2)}
|
|
725
|
-
`;
|
|
726
|
-
}
|
|
727
|
-
} }).prompt();
|
|
728
|
-
};
|
|
729
|
-
fe = (t) => {
|
|
730
|
-
const n = (r2, i) => {
|
|
731
|
-
const s = r2.label ?? String(r2.value);
|
|
732
|
-
return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(T)} ${import_picocolors2.default.dim(s)} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active-selected" ? `${import_picocolors2.default.green(T)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(s)}` : `${import_picocolors2.default.dim(F)} ${import_picocolors2.default.dim(s)}`;
|
|
733
|
-
};
|
|
734
|
-
return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? true, cursorAt: t.cursorAt, validate(r2) {
|
|
735
|
-
if (this.required && r2.length === 0) return `Please select at least one option.
|
|
736
|
-
${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
|
|
737
|
-
}, render() {
|
|
738
|
-
const r2 = `${import_picocolors2.default.gray(o)}
|
|
739
|
-
${b2(this.state)} ${t.message}
|
|
740
|
-
`, i = (s, c) => {
|
|
741
|
-
const a = this.value.includes(s.value);
|
|
742
|
-
return c && a ? n(s, "active-selected") : a ? n(s, "selected") : n(s, c ? "active" : "inactive");
|
|
743
|
-
};
|
|
744
|
-
switch (this.state) {
|
|
745
|
-
case "submit":
|
|
746
|
-
return `${r2}${import_picocolors2.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => n(s, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
|
|
747
|
-
case "cancel": {
|
|
748
|
-
const s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => n(c, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
749
|
-
return `${r2}${import_picocolors2.default.gray(o)} ${s.trim() ? `${s}
|
|
750
|
-
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
751
|
-
}
|
|
752
|
-
case "error": {
|
|
753
|
-
const s = this.error.split(`
|
|
754
|
-
`).map((c, a) => a === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(c)}` : ` ${c}`).join(`
|
|
755
|
-
`);
|
|
756
|
-
return `${r2 + import_picocolors2.default.yellow(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
757
|
-
${import_picocolors2.default.yellow(o)} `)}
|
|
758
|
-
${s}
|
|
759
|
-
`;
|
|
760
|
-
}
|
|
761
|
-
default:
|
|
762
|
-
return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
763
|
-
${import_picocolors2.default.cyan(o)} `)}
|
|
764
|
-
${import_picocolors2.default.cyan(d2)}
|
|
765
690
|
`;
|
|
766
691
|
}
|
|
767
692
|
} }).prompt();
|
|
@@ -802,7 +727,7 @@ ${import_picocolors2.default.gray(d2)} ${t}
|
|
|
802
727
|
}, R2 = (m2) => m2.replace(/\.+$/, ""), O2 = (m2) => {
|
|
803
728
|
const h2 = (performance.now() - m2) / 1e3, w2 = Math.floor(h2 / 60), I2 = Math.floor(h2 % 60);
|
|
804
729
|
return w2 > 0 ? `[${w2}m ${I2}s]` : `[${I2}s]`;
|
|
805
|
-
},
|
|
730
|
+
}, H = (m2 = "") => {
|
|
806
731
|
a = true, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors2.default.gray(o)}
|
|
807
732
|
`);
|
|
808
733
|
let h2 = 0, w2 = 0;
|
|
@@ -825,7 +750,7 @@ ${import_picocolors2.default.gray(d2)} ${t}
|
|
|
825
750
|
`) : process.stdout.write(`${w2} ${l2}
|
|
826
751
|
`), E(), s();
|
|
827
752
|
};
|
|
828
|
-
return { start:
|
|
753
|
+
return { start: H, stop: N2, message: (m2 = "") => {
|
|
829
754
|
l2 = R2(m2 ?? l2);
|
|
830
755
|
} };
|
|
831
756
|
};
|
|
@@ -902,19 +827,46 @@ function buildManifest(opts, moduleId) {
|
|
|
902
827
|
if (opts.license) manifest.license = opts.license;
|
|
903
828
|
if (opts.dependencies.length > 0) {
|
|
904
829
|
manifest.dependencies = Object.fromEntries(
|
|
905
|
-
opts.dependencies.map(
|
|
830
|
+
opts.dependencies.map(
|
|
831
|
+
(d3) => typeof d3 === "string" ? [d3, DEPENDENCY_RANGE] : [d3.module, { version: DEPENDENCY_RANGE, entities: d3.entities }]
|
|
832
|
+
)
|
|
906
833
|
);
|
|
907
834
|
}
|
|
908
835
|
return manifest;
|
|
909
836
|
}
|
|
837
|
+
function buildDepsContract(dep, consumerCode) {
|
|
838
|
+
return {
|
|
839
|
+
module: dep.module,
|
|
840
|
+
version: DEPENDENCY_RANGE,
|
|
841
|
+
entities: Object.fromEntries(
|
|
842
|
+
dep.entities.map((e2) => [
|
|
843
|
+
e2,
|
|
844
|
+
{ pk: `${e2}_id`, use: [`ref:${consumerCode}`] }
|
|
845
|
+
])
|
|
846
|
+
)
|
|
847
|
+
};
|
|
848
|
+
}
|
|
910
849
|
function buildEntity(entity) {
|
|
911
850
|
const traits = entity.traits === "identity+audit" ? ["identity", "audit"] : ["identity"];
|
|
912
851
|
const built = {
|
|
913
852
|
description: entity.label,
|
|
914
853
|
dbObject: entity.name,
|
|
915
|
-
|
|
854
|
+
// The traits only add a PK and audit stamps, so an entity with no fields
|
|
855
|
+
// of its own has nothing renderable: its grid view fails the data-view
|
|
856
|
+
// column check and `toString` has nothing to interpolate. Scaffold one
|
|
857
|
+
// visible name column so the module validates and the grid shows a row.
|
|
858
|
+
toString: `{${NAME_FIELD}}`,
|
|
916
859
|
traits,
|
|
917
|
-
fields: {
|
|
860
|
+
fields: {
|
|
861
|
+
[NAME_FIELD]: {
|
|
862
|
+
dbDatatype: "varchar",
|
|
863
|
+
fieldTypeCd: "text",
|
|
864
|
+
flags: "VEM",
|
|
865
|
+
maxLen: 200,
|
|
866
|
+
orderNum: 10,
|
|
867
|
+
description: "Name"
|
|
868
|
+
}
|
|
869
|
+
}
|
|
918
870
|
};
|
|
919
871
|
if (entity.constraints?.length) {
|
|
920
872
|
built.constraints = Object.fromEntries(
|
|
@@ -999,7 +951,8 @@ function buildTranslations(opts) {
|
|
|
999
951
|
for (const e2 of opts.entities) {
|
|
1000
952
|
const fields = {
|
|
1001
953
|
// identity trait → primary key column
|
|
1002
|
-
[`${e2.name}_id`]: { label: `${e2.label} ID` }
|
|
954
|
+
[`${e2.name}_id`]: { label: `${e2.label} ID` },
|
|
955
|
+
[NAME_FIELD]: { label: "Name" }
|
|
1003
956
|
};
|
|
1004
957
|
if (e2.traits === "identity+audit") {
|
|
1005
958
|
fields.created_date = { label: "Created Date" };
|
|
@@ -1040,8 +993,9 @@ function buildTranslations(opts) {
|
|
|
1040
993
|
}
|
|
1041
994
|
};
|
|
1042
995
|
}
|
|
1043
|
-
function buildSeedData() {
|
|
1044
|
-
|
|
996
|
+
function buildSeedData(entity) {
|
|
997
|
+
const entityCode = typeof entity === "string" ? entity : entity?.name ?? "";
|
|
998
|
+
return { entityCode, records: [] };
|
|
1045
999
|
}
|
|
1046
1000
|
function buildGitignore() {
|
|
1047
1001
|
return [
|
|
@@ -1055,30 +1009,78 @@ function buildGitignore() {
|
|
|
1055
1009
|
""
|
|
1056
1010
|
].join("\n");
|
|
1057
1011
|
}
|
|
1012
|
+
function schemaEntries() {
|
|
1013
|
+
return SCHEMA_BINDINGS.map((b3) => ({
|
|
1014
|
+
fileMatch: b3.fileMatch,
|
|
1015
|
+
url: `${SCHEMA_BASE}/${b3.schema}.schema.json`
|
|
1016
|
+
}));
|
|
1017
|
+
}
|
|
1058
1018
|
function buildVscodeSettings() {
|
|
1059
|
-
return {
|
|
1060
|
-
"json.schemas": SCHEMA_BINDINGS.map((b3) => ({
|
|
1061
|
-
fileMatch: b3.fileMatch,
|
|
1062
|
-
url: `${SCHEMA_BASE}/${b3.schema}.schema.json`
|
|
1063
|
-
}))
|
|
1064
|
-
};
|
|
1019
|
+
return { "json.schemas": schemaEntries() };
|
|
1065
1020
|
}
|
|
1066
1021
|
function buildZedSettings() {
|
|
1067
1022
|
return {
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1023
|
+
lsp: {
|
|
1024
|
+
"json-language-server": {
|
|
1025
|
+
settings: { json: { schemas: schemaEntries() } }
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1028
|
+
context_servers: {
|
|
1029
|
+
dforge: {
|
|
1030
|
+
source: "custom",
|
|
1031
|
+
command: "npx",
|
|
1032
|
+
args: ["-y", "@dforge-core/dforge-mcp@latest"],
|
|
1033
|
+
env: {}
|
|
1074
1034
|
}
|
|
1075
1035
|
}
|
|
1076
1036
|
};
|
|
1077
1037
|
}
|
|
1078
|
-
|
|
1038
|
+
function buildZedTasks() {
|
|
1039
|
+
const CLI = "npx";
|
|
1040
|
+
const CLI_ARGS = ["-y", "@dforge-core/dforge-cli@latest"];
|
|
1041
|
+
const DEFAULT_TENANT = "http://localhost:5179";
|
|
1042
|
+
const task = (label, args) => ({
|
|
1043
|
+
label: `dForge: ${label}`,
|
|
1044
|
+
command: CLI,
|
|
1045
|
+
args: [...CLI_ARGS, ...args],
|
|
1046
|
+
cwd: "$ZED_WORKTREE_ROOT",
|
|
1047
|
+
env: { DFORGE_URL: DEFAULT_TENANT },
|
|
1048
|
+
use_new_terminal: false,
|
|
1049
|
+
allow_concurrent_runs: false,
|
|
1050
|
+
reveal: "always"
|
|
1051
|
+
});
|
|
1052
|
+
return [
|
|
1053
|
+
task("Pack module", ["module", "pack", "$ZED_WORKTREE_ROOT"]),
|
|
1054
|
+
// --force matches the extension's dev-loop default: without it the CLI
|
|
1055
|
+
// skips the reinstall when the version hasn't changed and your edits
|
|
1056
|
+
// silently never reach the tenant.
|
|
1057
|
+
task("Install module to tenant", [
|
|
1058
|
+
"module",
|
|
1059
|
+
"install",
|
|
1060
|
+
"--path",
|
|
1061
|
+
"$ZED_WORKTREE_ROOT",
|
|
1062
|
+
"--url",
|
|
1063
|
+
"$DFORGE_URL",
|
|
1064
|
+
"--force"
|
|
1065
|
+
]),
|
|
1066
|
+
task("Sign in to tenant", [
|
|
1067
|
+
"auth",
|
|
1068
|
+
"login",
|
|
1069
|
+
"--url",
|
|
1070
|
+
"$DFORGE_URL",
|
|
1071
|
+
"--login-url",
|
|
1072
|
+
"$DFORGE_URL"
|
|
1073
|
+
]),
|
|
1074
|
+
task("Show signed-in user", ["auth", "whoami", "--url", "$DFORGE_URL"]),
|
|
1075
|
+
task("List installed modules", ["module", "list", "--url", "$DFORGE_URL"])
|
|
1076
|
+
];
|
|
1077
|
+
}
|
|
1078
|
+
var DEPENDENCY_RANGE, NAME_FIELD, SCHEMA_BASE, SCHEMA_BINDINGS;
|
|
1079
1079
|
var init_templates = __esm({
|
|
1080
1080
|
"src/init/templates.ts"() {
|
|
1081
1081
|
"use strict";
|
|
1082
|
+
DEPENDENCY_RANGE = ">=0.0.1";
|
|
1083
|
+
NAME_FIELD = "name";
|
|
1082
1084
|
SCHEMA_BASE = "https://cdn.jsdelivr.net/npm/@dforge-core/dforge-mcp@latest/resources/schemas";
|
|
1083
1085
|
SCHEMA_BINDINGS = [
|
|
1084
1086
|
{ fileMatch: ["manifest.json"], schema: "manifest" },
|
|
@@ -1087,8 +1089,12 @@ var init_templates = __esm({
|
|
|
1087
1089
|
{ fileMatch: ["ui/folders.json"], schema: "folders" },
|
|
1088
1090
|
{ fileMatch: ["ui/menus.json"], schema: "menus" },
|
|
1089
1091
|
{ fileMatch: ["ui/reports.json"], schema: "reports" },
|
|
1092
|
+
{ fileMatch: ["ui/print_templates.json"], schema: "print-templates" },
|
|
1090
1093
|
{ fileMatch: ["security/roles.json"], schema: "roles" },
|
|
1091
1094
|
{ fileMatch: ["logic/jobs.json"], schema: "jobs" },
|
|
1095
|
+
{ fileMatch: ["logic/triggers.json"], schema: "triggers" },
|
|
1096
|
+
{ fileMatch: ["logic/webhooks.json"], schema: "webhooks" },
|
|
1097
|
+
{ fileMatch: ["deps/*.json"], schema: "deps" },
|
|
1092
1098
|
{ fileMatch: ["seed-data/*.json"], schema: "seed-data" },
|
|
1093
1099
|
{ fileMatch: ["settings.json"], schema: "settings" }
|
|
1094
1100
|
];
|
|
@@ -1156,6 +1162,12 @@ async function runInitModule(argv2) {
|
|
|
1156
1162
|
Se(`Created module ${opts.code} at ${opts.path}`);
|
|
1157
1163
|
}
|
|
1158
1164
|
console.log("");
|
|
1165
|
+
if (opts.dependencies.length > 0) {
|
|
1166
|
+
const files = opts.dependencies.map((d3) => `deps/${typeof d3 === "string" ? d3 : d3.module}.json`).join(", ");
|
|
1167
|
+
console.log(`Wrote ${files}. Correct each entity's 'pk' against the provider and`);
|
|
1168
|
+
console.log("replace the placeholder 'use' token with the real usage before you pack.");
|
|
1169
|
+
console.log("");
|
|
1170
|
+
}
|
|
1159
1171
|
console.log("Next steps:");
|
|
1160
1172
|
console.log(` cd ${path2.relative(process.cwd(), opts.path) || "."}`);
|
|
1161
1173
|
console.log(` dforge-cli module install --path . --code <tenant>`);
|
|
@@ -1266,11 +1278,33 @@ function buildOptsFromArgs(absPath, args) {
|
|
|
1266
1278
|
license: args.license ?? "MIT",
|
|
1267
1279
|
version,
|
|
1268
1280
|
dbSchemaVersion,
|
|
1269
|
-
dependencies: args.dependencies ?? [
|
|
1281
|
+
dependencies: parseDependencies(args.dependencies ?? []),
|
|
1270
1282
|
preset,
|
|
1271
1283
|
entities
|
|
1272
1284
|
};
|
|
1273
1285
|
}
|
|
1286
|
+
function parseDependencies(tokens) {
|
|
1287
|
+
return tokens.map((token) => {
|
|
1288
|
+
const [module2, entityList] = token.split(":");
|
|
1289
|
+
if (!module2 || !entityList) {
|
|
1290
|
+
throw new Error(
|
|
1291
|
+
`dforge-cli init module: --dependencies "${token}" must name the entities you consume, as module:entity[+entity]. Every dependency needs a deps/${module2 || "<module>"}.json contract declaring at least one entity, so a dependency with no named entity cannot be scaffolded. If you do not consume anything from it yet, leave it out and add it later with dforge_dependency_add.`
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
if (SYSTEM_MODULES.has(module2)) {
|
|
1295
|
+
throw new Error(
|
|
1296
|
+
`dforge-cli init module: '${module2}' is a system module \u2014 it is provisioned into every tenant, so depending on it buys nothing. Declare it by hand only to require a minimum platform version for a feature you use (e.g. "metadata": ">=1.5.0"), with a contract naming the entity that feature introduced.`
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
const entities = entityList.split("+").map((e2) => e2.trim()).filter(Boolean);
|
|
1300
|
+
if (entities.length === 0) {
|
|
1301
|
+
throw new Error(
|
|
1302
|
+
`dforge-cli init module: --dependencies "${token}" names no entities after the colon.`
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
return { module: module2, entities };
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1274
1308
|
function printModuleHelp() {
|
|
1275
1309
|
console.log("Usage: dforge-cli init module <path> [options]");
|
|
1276
1310
|
console.log("");
|
|
@@ -1285,7 +1319,8 @@ function printModuleHelp() {
|
|
|
1285
1319
|
console.log(" --license <id> Default: MIT");
|
|
1286
1320
|
console.log(" --version <semver> Default: 0.1.0");
|
|
1287
1321
|
console.log(" --db-schema-version <ver> Default: 0.0.1");
|
|
1288
|
-
console.log(" --dependencies <
|
|
1322
|
+
console.log(" --dependencies <mod:ent> Consumed module + entities, e.g. fin:invoice+line.");
|
|
1323
|
+
console.log(" Repeatable/comma-separated. Default: none.");
|
|
1289
1324
|
console.log(" --preset <p> minimal | minimal-plus | full (default: minimal)");
|
|
1290
1325
|
console.log(" --entity <name[,name\u2026]> Entities to scaffold (default: item). Repeatable.");
|
|
1291
1326
|
console.log(" --traits <t> identity+audit | identity (default: identity+audit)");
|
|
@@ -1328,15 +1363,6 @@ async function collectOpts(absPath) {
|
|
|
1328
1363
|
initialValue: "0.0.1",
|
|
1329
1364
|
validate: validateSemver
|
|
1330
1365
|
}),
|
|
1331
|
-
dependencies: () => fe({
|
|
1332
|
-
message: "Depend on system modules (space to toggle)",
|
|
1333
|
-
options: [
|
|
1334
|
-
{ value: "admin", label: "admin (required for most modules)" },
|
|
1335
|
-
{ value: "metadata", label: "metadata (required for most modules)" }
|
|
1336
|
-
],
|
|
1337
|
-
initialValues: ["admin", "metadata"],
|
|
1338
|
-
required: false
|
|
1339
|
-
}),
|
|
1340
1366
|
preset: () => ve({
|
|
1341
1367
|
message: "Scaffold preset",
|
|
1342
1368
|
options: [
|
|
@@ -1386,7 +1412,7 @@ async function collectOpts(absPath) {
|
|
|
1386
1412
|
license: meta.license ?? "MIT",
|
|
1387
1413
|
version: meta.version,
|
|
1388
1414
|
dbSchemaVersion: meta.dbSchemaVersion,
|
|
1389
|
-
dependencies:
|
|
1415
|
+
dependencies: [],
|
|
1390
1416
|
preset: meta.preset,
|
|
1391
1417
|
entities
|
|
1392
1418
|
};
|
|
@@ -1442,16 +1468,24 @@ function writeAll(opts) {
|
|
|
1442
1468
|
writeJson(path2.join(root, "ui", "menus.json"), buildMenus(opts));
|
|
1443
1469
|
writeJson(path2.join(root, "ui", "actions.json"), buildActions());
|
|
1444
1470
|
writeJson(path2.join(root, "security", "roles.json"), buildRoles(opts));
|
|
1471
|
+
for (const dep of opts.dependencies) {
|
|
1472
|
+
if (typeof dep === "string") continue;
|
|
1473
|
+
writeJson(
|
|
1474
|
+
path2.join(root, "deps", `${dep.module}.json`),
|
|
1475
|
+
buildDepsContract(dep, opts.code)
|
|
1476
|
+
);
|
|
1477
|
+
}
|
|
1445
1478
|
writeText(path2.join(root, ".gitignore"), buildGitignore());
|
|
1446
1479
|
writeJson(path2.join(root, ".vscode", "settings.json"), buildVscodeSettings());
|
|
1447
1480
|
writeJson(path2.join(root, ".zed", "settings.json"), buildZedSettings());
|
|
1481
|
+
writeJson(path2.join(root, ".zed", "tasks.json"), buildZedTasks());
|
|
1448
1482
|
if (opts.preset === "full") {
|
|
1449
1483
|
writeJson(path2.join(root, "settings.json"), buildSettings());
|
|
1450
1484
|
writeJson(path2.join(root, "translations", "en-US.json"), buildTranslations(opts));
|
|
1451
1485
|
for (const e2 of opts.entities) {
|
|
1452
1486
|
writeJson(
|
|
1453
1487
|
path2.join(root, "seed-data", `01-${e2.name}.json`),
|
|
1454
|
-
buildSeedData()
|
|
1488
|
+
buildSeedData(e2)
|
|
1455
1489
|
);
|
|
1456
1490
|
}
|
|
1457
1491
|
ensureDir(path2.join(root, "logic", "actions"));
|
|
@@ -1480,7 +1514,7 @@ function tryGitUserName() {
|
|
|
1480
1514
|
return void 0;
|
|
1481
1515
|
}
|
|
1482
1516
|
}
|
|
1483
|
-
var fs2, path2, import_node_child_process2, import_node_crypto, CANCEL_EXIT, PRESETS, TRAITS_VALUES;
|
|
1517
|
+
var fs2, path2, import_node_child_process2, import_node_crypto, CANCEL_EXIT, PRESETS, TRAITS_VALUES, SYSTEM_MODULES;
|
|
1484
1518
|
var init_module = __esm({
|
|
1485
1519
|
"src/init/module.ts"() {
|
|
1486
1520
|
"use strict";
|
|
@@ -1494,6 +1528,7 @@ var init_module = __esm({
|
|
|
1494
1528
|
CANCEL_EXIT = 130;
|
|
1495
1529
|
PRESETS = /* @__PURE__ */ new Set(["minimal", "minimal-plus", "full"]);
|
|
1496
1530
|
TRAITS_VALUES = /* @__PURE__ */ new Set(["identity+audit", "identity"]);
|
|
1531
|
+
SYSTEM_MODULES = /* @__PURE__ */ new Set(["admin", "metadata", "workspace"]);
|
|
1497
1532
|
}
|
|
1498
1533
|
});
|
|
1499
1534
|
|
package/dist/lib.d.mts
CHANGED
|
@@ -13,6 +13,16 @@ interface EntitySpec {
|
|
|
13
13
|
traits: Traits;
|
|
14
14
|
constraints?: ConstraintSpec[];
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* One declared dependency. `entities` is what the module consumes from it and
|
|
18
|
+
* is never empty: the platform requires a deps/<module>.json contract naming at
|
|
19
|
+
* least one entity for every manifest dependency, so a dependency we cannot
|
|
20
|
+
* name an entity for is one we must not scaffold.
|
|
21
|
+
*/
|
|
22
|
+
interface DependencySpec {
|
|
23
|
+
module: string;
|
|
24
|
+
entities: string[];
|
|
25
|
+
}
|
|
16
26
|
interface ScaffoldOpts {
|
|
17
27
|
path: string;
|
|
18
28
|
code: string;
|
|
@@ -22,7 +32,11 @@ interface ScaffoldOpts {
|
|
|
22
32
|
license: string;
|
|
23
33
|
version: string;
|
|
24
34
|
dbSchemaVersion: string;
|
|
25
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Accepts bare module codes too: @dforge-core/dforge-mcp calls these builders
|
|
37
|
+
* across a caret range and older published versions still pass string[].
|
|
38
|
+
*/
|
|
39
|
+
dependencies: Array<DependencySpec | string>;
|
|
26
40
|
preset: Preset;
|
|
27
41
|
entities: EntitySpec[];
|
|
28
42
|
}
|
|
@@ -38,7 +52,15 @@ interface Manifest {
|
|
|
38
52
|
name: string;
|
|
39
53
|
};
|
|
40
54
|
license?: string;
|
|
41
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Either a bare semver range or the object form that narrows the dependency
|
|
57
|
+
* to named entities. The scaffolder always writes the object form, since it
|
|
58
|
+
* only declares a dependency whose consumed entities it knows.
|
|
59
|
+
*/
|
|
60
|
+
dependencies?: Record<string, string | {
|
|
61
|
+
version: string;
|
|
62
|
+
entities: string[];
|
|
63
|
+
}>;
|
|
42
64
|
entities: Record<string, string>;
|
|
43
65
|
created?: string;
|
|
44
66
|
updated?: string;
|
|
@@ -61,6 +83,22 @@ interface DataView {
|
|
|
61
83
|
}
|
|
62
84
|
|
|
63
85
|
declare function buildManifest(opts: ScaffoldOpts, moduleId: string): Manifest;
|
|
86
|
+
/** Range written for a scaffolded dependency, in the manifest and its contract alike. */
|
|
87
|
+
declare const DEPENDENCY_RANGE = ">=0.0.1";
|
|
88
|
+
/**
|
|
89
|
+
* The deps/<module>.json contract that every manifest dependency requires —
|
|
90
|
+
* without it the module fails `module validate`, `module pack` and install.
|
|
91
|
+
* `pk` follows the identity trait's `<entity>_id`, and `use` is a placeholder
|
|
92
|
+
* naming this module: both are starting points the author has to correct, which
|
|
93
|
+
* is what the post-scaffold note says.
|
|
94
|
+
*/
|
|
95
|
+
declare function buildDepsContract(dep: DependencySpec, consumerCode: string): Record<string, unknown>;
|
|
96
|
+
/**
|
|
97
|
+
* The one field every scaffolded entity gets: a visible, editable, mandatory
|
|
98
|
+
* label column. It is what `toString` interpolates and what the entity's grid
|
|
99
|
+
* renders.
|
|
100
|
+
*/
|
|
101
|
+
declare const NAME_FIELD = "name";
|
|
64
102
|
declare function buildEntity(entity: EntitySpec): Entity;
|
|
65
103
|
declare function buildDataViews(entities: EntitySpec[]): Record<string, DataView>;
|
|
66
104
|
declare function buildFolders(opts: ScaffoldOpts): Record<string, unknown>;
|
|
@@ -69,9 +107,15 @@ declare function buildRoles(opts: ScaffoldOpts): Record<string, unknown>;
|
|
|
69
107
|
declare function buildActions(): Record<string, unknown>;
|
|
70
108
|
declare function buildSettings(): Record<string, unknown>;
|
|
71
109
|
declare function buildTranslations(opts: ScaffoldOpts): Record<string, unknown>;
|
|
72
|
-
|
|
110
|
+
/**
|
|
111
|
+
* A seed file is an OBJECT ({ entityCode, records }), not a bare array — a bare
|
|
112
|
+
* array fails to deserialize and takes `module validate` down with it. Ships
|
|
113
|
+
* with no records: seeding needs explicit PKs, which only the author can pick.
|
|
114
|
+
*/
|
|
115
|
+
declare function buildSeedData(entity?: EntitySpec | string): Record<string, unknown>;
|
|
73
116
|
declare function buildGitignore(): string;
|
|
74
117
|
declare function buildVscodeSettings(): Record<string, unknown>;
|
|
75
118
|
declare function buildZedSettings(): Record<string, unknown>;
|
|
119
|
+
declare function buildZedTasks(): unknown[];
|
|
76
120
|
|
|
77
|
-
export { type ConstraintSpec, type DataView, type Entity, type EntitySpec, type Manifest, type Preset, type ScaffoldOpts, type Traits, buildActions, buildDataViews, buildEntity, buildFolders, buildGitignore, buildManifest, buildMenus, buildRoles, buildSeedData, buildSettings, buildTranslations, buildVscodeSettings, buildZedSettings };
|
|
121
|
+
export { type ConstraintSpec, DEPENDENCY_RANGE, type DataView, type DependencySpec, type Entity, type EntitySpec, type Manifest, NAME_FIELD, type Preset, type ScaffoldOpts, type Traits, buildActions, buildDataViews, buildDepsContract, buildEntity, buildFolders, buildGitignore, buildManifest, buildMenus, buildRoles, buildSeedData, buildSettings, buildTranslations, buildVscodeSettings, buildZedSettings, buildZedTasks };
|
package/dist/lib.d.ts
CHANGED
|
@@ -13,6 +13,16 @@ interface EntitySpec {
|
|
|
13
13
|
traits: Traits;
|
|
14
14
|
constraints?: ConstraintSpec[];
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* One declared dependency. `entities` is what the module consumes from it and
|
|
18
|
+
* is never empty: the platform requires a deps/<module>.json contract naming at
|
|
19
|
+
* least one entity for every manifest dependency, so a dependency we cannot
|
|
20
|
+
* name an entity for is one we must not scaffold.
|
|
21
|
+
*/
|
|
22
|
+
interface DependencySpec {
|
|
23
|
+
module: string;
|
|
24
|
+
entities: string[];
|
|
25
|
+
}
|
|
16
26
|
interface ScaffoldOpts {
|
|
17
27
|
path: string;
|
|
18
28
|
code: string;
|
|
@@ -22,7 +32,11 @@ interface ScaffoldOpts {
|
|
|
22
32
|
license: string;
|
|
23
33
|
version: string;
|
|
24
34
|
dbSchemaVersion: string;
|
|
25
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Accepts bare module codes too: @dforge-core/dforge-mcp calls these builders
|
|
37
|
+
* across a caret range and older published versions still pass string[].
|
|
38
|
+
*/
|
|
39
|
+
dependencies: Array<DependencySpec | string>;
|
|
26
40
|
preset: Preset;
|
|
27
41
|
entities: EntitySpec[];
|
|
28
42
|
}
|
|
@@ -38,7 +52,15 @@ interface Manifest {
|
|
|
38
52
|
name: string;
|
|
39
53
|
};
|
|
40
54
|
license?: string;
|
|
41
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Either a bare semver range or the object form that narrows the dependency
|
|
57
|
+
* to named entities. The scaffolder always writes the object form, since it
|
|
58
|
+
* only declares a dependency whose consumed entities it knows.
|
|
59
|
+
*/
|
|
60
|
+
dependencies?: Record<string, string | {
|
|
61
|
+
version: string;
|
|
62
|
+
entities: string[];
|
|
63
|
+
}>;
|
|
42
64
|
entities: Record<string, string>;
|
|
43
65
|
created?: string;
|
|
44
66
|
updated?: string;
|
|
@@ -61,6 +83,22 @@ interface DataView {
|
|
|
61
83
|
}
|
|
62
84
|
|
|
63
85
|
declare function buildManifest(opts: ScaffoldOpts, moduleId: string): Manifest;
|
|
86
|
+
/** Range written for a scaffolded dependency, in the manifest and its contract alike. */
|
|
87
|
+
declare const DEPENDENCY_RANGE = ">=0.0.1";
|
|
88
|
+
/**
|
|
89
|
+
* The deps/<module>.json contract that every manifest dependency requires —
|
|
90
|
+
* without it the module fails `module validate`, `module pack` and install.
|
|
91
|
+
* `pk` follows the identity trait's `<entity>_id`, and `use` is a placeholder
|
|
92
|
+
* naming this module: both are starting points the author has to correct, which
|
|
93
|
+
* is what the post-scaffold note says.
|
|
94
|
+
*/
|
|
95
|
+
declare function buildDepsContract(dep: DependencySpec, consumerCode: string): Record<string, unknown>;
|
|
96
|
+
/**
|
|
97
|
+
* The one field every scaffolded entity gets: a visible, editable, mandatory
|
|
98
|
+
* label column. It is what `toString` interpolates and what the entity's grid
|
|
99
|
+
* renders.
|
|
100
|
+
*/
|
|
101
|
+
declare const NAME_FIELD = "name";
|
|
64
102
|
declare function buildEntity(entity: EntitySpec): Entity;
|
|
65
103
|
declare function buildDataViews(entities: EntitySpec[]): Record<string, DataView>;
|
|
66
104
|
declare function buildFolders(opts: ScaffoldOpts): Record<string, unknown>;
|
|
@@ -69,9 +107,15 @@ declare function buildRoles(opts: ScaffoldOpts): Record<string, unknown>;
|
|
|
69
107
|
declare function buildActions(): Record<string, unknown>;
|
|
70
108
|
declare function buildSettings(): Record<string, unknown>;
|
|
71
109
|
declare function buildTranslations(opts: ScaffoldOpts): Record<string, unknown>;
|
|
72
|
-
|
|
110
|
+
/**
|
|
111
|
+
* A seed file is an OBJECT ({ entityCode, records }), not a bare array — a bare
|
|
112
|
+
* array fails to deserialize and takes `module validate` down with it. Ships
|
|
113
|
+
* with no records: seeding needs explicit PKs, which only the author can pick.
|
|
114
|
+
*/
|
|
115
|
+
declare function buildSeedData(entity?: EntitySpec | string): Record<string, unknown>;
|
|
73
116
|
declare function buildGitignore(): string;
|
|
74
117
|
declare function buildVscodeSettings(): Record<string, unknown>;
|
|
75
118
|
declare function buildZedSettings(): Record<string, unknown>;
|
|
119
|
+
declare function buildZedTasks(): unknown[];
|
|
76
120
|
|
|
77
|
-
export { type ConstraintSpec, type DataView, type Entity, type EntitySpec, type Manifest, type Preset, type ScaffoldOpts, type Traits, buildActions, buildDataViews, buildEntity, buildFolders, buildGitignore, buildManifest, buildMenus, buildRoles, buildSeedData, buildSettings, buildTranslations, buildVscodeSettings, buildZedSettings };
|
|
121
|
+
export { type ConstraintSpec, DEPENDENCY_RANGE, type DataView, type DependencySpec, type Entity, type EntitySpec, type Manifest, NAME_FIELD, type Preset, type ScaffoldOpts, type Traits, buildActions, buildDataViews, buildDepsContract, buildEntity, buildFolders, buildGitignore, buildManifest, buildMenus, buildRoles, buildSeedData, buildSettings, buildTranslations, buildVscodeSettings, buildZedSettings, buildZedTasks };
|
package/dist/lib.js
CHANGED
|
@@ -20,8 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/lib.ts
|
|
21
21
|
var lib_exports = {};
|
|
22
22
|
__export(lib_exports, {
|
|
23
|
+
DEPENDENCY_RANGE: () => DEPENDENCY_RANGE,
|
|
24
|
+
NAME_FIELD: () => NAME_FIELD,
|
|
23
25
|
buildActions: () => buildActions,
|
|
24
26
|
buildDataViews: () => buildDataViews,
|
|
27
|
+
buildDepsContract: () => buildDepsContract,
|
|
25
28
|
buildEntity: () => buildEntity,
|
|
26
29
|
buildFolders: () => buildFolders,
|
|
27
30
|
buildGitignore: () => buildGitignore,
|
|
@@ -32,7 +35,8 @@ __export(lib_exports, {
|
|
|
32
35
|
buildSettings: () => buildSettings,
|
|
33
36
|
buildTranslations: () => buildTranslations,
|
|
34
37
|
buildVscodeSettings: () => buildVscodeSettings,
|
|
35
|
-
buildZedSettings: () => buildZedSettings
|
|
38
|
+
buildZedSettings: () => buildZedSettings,
|
|
39
|
+
buildZedTasks: () => buildZedTasks
|
|
36
40
|
});
|
|
37
41
|
module.exports = __toCommonJS(lib_exports);
|
|
38
42
|
|
|
@@ -57,19 +61,48 @@ function buildManifest(opts, moduleId) {
|
|
|
57
61
|
if (opts.license) manifest.license = opts.license;
|
|
58
62
|
if (opts.dependencies.length > 0) {
|
|
59
63
|
manifest.dependencies = Object.fromEntries(
|
|
60
|
-
opts.dependencies.map(
|
|
64
|
+
opts.dependencies.map(
|
|
65
|
+
(d) => typeof d === "string" ? [d, DEPENDENCY_RANGE] : [d.module, { version: DEPENDENCY_RANGE, entities: d.entities }]
|
|
66
|
+
)
|
|
61
67
|
);
|
|
62
68
|
}
|
|
63
69
|
return manifest;
|
|
64
70
|
}
|
|
71
|
+
var DEPENDENCY_RANGE = ">=0.0.1";
|
|
72
|
+
function buildDepsContract(dep, consumerCode) {
|
|
73
|
+
return {
|
|
74
|
+
module: dep.module,
|
|
75
|
+
version: DEPENDENCY_RANGE,
|
|
76
|
+
entities: Object.fromEntries(
|
|
77
|
+
dep.entities.map((e) => [
|
|
78
|
+
e,
|
|
79
|
+
{ pk: `${e}_id`, use: [`ref:${consumerCode}`] }
|
|
80
|
+
])
|
|
81
|
+
)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
var NAME_FIELD = "name";
|
|
65
85
|
function buildEntity(entity) {
|
|
66
86
|
const traits = entity.traits === "identity+audit" ? ["identity", "audit"] : ["identity"];
|
|
67
87
|
const built = {
|
|
68
88
|
description: entity.label,
|
|
69
89
|
dbObject: entity.name,
|
|
70
|
-
|
|
90
|
+
// The traits only add a PK and audit stamps, so an entity with no fields
|
|
91
|
+
// of its own has nothing renderable: its grid view fails the data-view
|
|
92
|
+
// column check and `toString` has nothing to interpolate. Scaffold one
|
|
93
|
+
// visible name column so the module validates and the grid shows a row.
|
|
94
|
+
toString: `{${NAME_FIELD}}`,
|
|
71
95
|
traits,
|
|
72
|
-
fields: {
|
|
96
|
+
fields: {
|
|
97
|
+
[NAME_FIELD]: {
|
|
98
|
+
dbDatatype: "varchar",
|
|
99
|
+
fieldTypeCd: "text",
|
|
100
|
+
flags: "VEM",
|
|
101
|
+
maxLen: 200,
|
|
102
|
+
orderNum: 10,
|
|
103
|
+
description: "Name"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
73
106
|
};
|
|
74
107
|
if (entity.constraints?.length) {
|
|
75
108
|
built.constraints = Object.fromEntries(
|
|
@@ -154,7 +187,8 @@ function buildTranslations(opts) {
|
|
|
154
187
|
for (const e of opts.entities) {
|
|
155
188
|
const fields = {
|
|
156
189
|
// identity trait → primary key column
|
|
157
|
-
[`${e.name}_id`]: { label: `${e.label} ID` }
|
|
190
|
+
[`${e.name}_id`]: { label: `${e.label} ID` },
|
|
191
|
+
[NAME_FIELD]: { label: "Name" }
|
|
158
192
|
};
|
|
159
193
|
if (e.traits === "identity+audit") {
|
|
160
194
|
fields.created_date = { label: "Created Date" };
|
|
@@ -195,8 +229,9 @@ function buildTranslations(opts) {
|
|
|
195
229
|
}
|
|
196
230
|
};
|
|
197
231
|
}
|
|
198
|
-
function buildSeedData() {
|
|
199
|
-
|
|
232
|
+
function buildSeedData(entity) {
|
|
233
|
+
const entityCode = typeof entity === "string" ? entity : entity?.name ?? "";
|
|
234
|
+
return { entityCode, records: [] };
|
|
200
235
|
}
|
|
201
236
|
function buildGitignore() {
|
|
202
237
|
return [
|
|
@@ -218,35 +253,88 @@ var SCHEMA_BINDINGS = [
|
|
|
218
253
|
{ fileMatch: ["ui/folders.json"], schema: "folders" },
|
|
219
254
|
{ fileMatch: ["ui/menus.json"], schema: "menus" },
|
|
220
255
|
{ fileMatch: ["ui/reports.json"], schema: "reports" },
|
|
256
|
+
{ fileMatch: ["ui/print_templates.json"], schema: "print-templates" },
|
|
221
257
|
{ fileMatch: ["security/roles.json"], schema: "roles" },
|
|
222
258
|
{ fileMatch: ["logic/jobs.json"], schema: "jobs" },
|
|
259
|
+
{ fileMatch: ["logic/triggers.json"], schema: "triggers" },
|
|
260
|
+
{ fileMatch: ["logic/webhooks.json"], schema: "webhooks" },
|
|
261
|
+
{ fileMatch: ["deps/*.json"], schema: "deps" },
|
|
223
262
|
{ fileMatch: ["seed-data/*.json"], schema: "seed-data" },
|
|
224
263
|
{ fileMatch: ["settings.json"], schema: "settings" }
|
|
225
264
|
];
|
|
265
|
+
function schemaEntries() {
|
|
266
|
+
return SCHEMA_BINDINGS.map((b) => ({
|
|
267
|
+
fileMatch: b.fileMatch,
|
|
268
|
+
url: `${SCHEMA_BASE}/${b.schema}.schema.json`
|
|
269
|
+
}));
|
|
270
|
+
}
|
|
226
271
|
function buildVscodeSettings() {
|
|
227
|
-
return {
|
|
228
|
-
"json.schemas": SCHEMA_BINDINGS.map((b) => ({
|
|
229
|
-
fileMatch: b.fileMatch,
|
|
230
|
-
url: `${SCHEMA_BASE}/${b.schema}.schema.json`
|
|
231
|
-
}))
|
|
232
|
-
};
|
|
272
|
+
return { "json.schemas": schemaEntries() };
|
|
233
273
|
}
|
|
234
274
|
function buildZedSettings() {
|
|
235
275
|
return {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
276
|
+
lsp: {
|
|
277
|
+
"json-language-server": {
|
|
278
|
+
settings: { json: { schemas: schemaEntries() } }
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
context_servers: {
|
|
282
|
+
dforge: {
|
|
283
|
+
source: "custom",
|
|
284
|
+
command: "npx",
|
|
285
|
+
args: ["-y", "@dforge-core/dforge-mcp@latest"],
|
|
286
|
+
env: {}
|
|
242
287
|
}
|
|
243
288
|
}
|
|
244
289
|
};
|
|
245
290
|
}
|
|
291
|
+
function buildZedTasks() {
|
|
292
|
+
const CLI = "npx";
|
|
293
|
+
const CLI_ARGS = ["-y", "@dforge-core/dforge-cli@latest"];
|
|
294
|
+
const DEFAULT_TENANT = "http://localhost:5179";
|
|
295
|
+
const task = (label, args) => ({
|
|
296
|
+
label: `dForge: ${label}`,
|
|
297
|
+
command: CLI,
|
|
298
|
+
args: [...CLI_ARGS, ...args],
|
|
299
|
+
cwd: "$ZED_WORKTREE_ROOT",
|
|
300
|
+
env: { DFORGE_URL: DEFAULT_TENANT },
|
|
301
|
+
use_new_terminal: false,
|
|
302
|
+
allow_concurrent_runs: false,
|
|
303
|
+
reveal: "always"
|
|
304
|
+
});
|
|
305
|
+
return [
|
|
306
|
+
task("Pack module", ["module", "pack", "$ZED_WORKTREE_ROOT"]),
|
|
307
|
+
// --force matches the extension's dev-loop default: without it the CLI
|
|
308
|
+
// skips the reinstall when the version hasn't changed and your edits
|
|
309
|
+
// silently never reach the tenant.
|
|
310
|
+
task("Install module to tenant", [
|
|
311
|
+
"module",
|
|
312
|
+
"install",
|
|
313
|
+
"--path",
|
|
314
|
+
"$ZED_WORKTREE_ROOT",
|
|
315
|
+
"--url",
|
|
316
|
+
"$DFORGE_URL",
|
|
317
|
+
"--force"
|
|
318
|
+
]),
|
|
319
|
+
task("Sign in to tenant", [
|
|
320
|
+
"auth",
|
|
321
|
+
"login",
|
|
322
|
+
"--url",
|
|
323
|
+
"$DFORGE_URL",
|
|
324
|
+
"--login-url",
|
|
325
|
+
"$DFORGE_URL"
|
|
326
|
+
]),
|
|
327
|
+
task("Show signed-in user", ["auth", "whoami", "--url", "$DFORGE_URL"]),
|
|
328
|
+
task("List installed modules", ["module", "list", "--url", "$DFORGE_URL"])
|
|
329
|
+
];
|
|
330
|
+
}
|
|
246
331
|
// Annotate the CommonJS export names for ESM import in node:
|
|
247
332
|
0 && (module.exports = {
|
|
333
|
+
DEPENDENCY_RANGE,
|
|
334
|
+
NAME_FIELD,
|
|
248
335
|
buildActions,
|
|
249
336
|
buildDataViews,
|
|
337
|
+
buildDepsContract,
|
|
250
338
|
buildEntity,
|
|
251
339
|
buildFolders,
|
|
252
340
|
buildGitignore,
|
|
@@ -257,5 +345,6 @@ function buildZedSettings() {
|
|
|
257
345
|
buildSettings,
|
|
258
346
|
buildTranslations,
|
|
259
347
|
buildVscodeSettings,
|
|
260
|
-
buildZedSettings
|
|
348
|
+
buildZedSettings,
|
|
349
|
+
buildZedTasks
|
|
261
350
|
});
|
package/dist/lib.mjs
CHANGED
|
@@ -19,19 +19,48 @@ function buildManifest(opts, moduleId) {
|
|
|
19
19
|
if (opts.license) manifest.license = opts.license;
|
|
20
20
|
if (opts.dependencies.length > 0) {
|
|
21
21
|
manifest.dependencies = Object.fromEntries(
|
|
22
|
-
opts.dependencies.map(
|
|
22
|
+
opts.dependencies.map(
|
|
23
|
+
(d) => typeof d === "string" ? [d, DEPENDENCY_RANGE] : [d.module, { version: DEPENDENCY_RANGE, entities: d.entities }]
|
|
24
|
+
)
|
|
23
25
|
);
|
|
24
26
|
}
|
|
25
27
|
return manifest;
|
|
26
28
|
}
|
|
29
|
+
var DEPENDENCY_RANGE = ">=0.0.1";
|
|
30
|
+
function buildDepsContract(dep, consumerCode) {
|
|
31
|
+
return {
|
|
32
|
+
module: dep.module,
|
|
33
|
+
version: DEPENDENCY_RANGE,
|
|
34
|
+
entities: Object.fromEntries(
|
|
35
|
+
dep.entities.map((e) => [
|
|
36
|
+
e,
|
|
37
|
+
{ pk: `${e}_id`, use: [`ref:${consumerCode}`] }
|
|
38
|
+
])
|
|
39
|
+
)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
var NAME_FIELD = "name";
|
|
27
43
|
function buildEntity(entity) {
|
|
28
44
|
const traits = entity.traits === "identity+audit" ? ["identity", "audit"] : ["identity"];
|
|
29
45
|
const built = {
|
|
30
46
|
description: entity.label,
|
|
31
47
|
dbObject: entity.name,
|
|
32
|
-
|
|
48
|
+
// The traits only add a PK and audit stamps, so an entity with no fields
|
|
49
|
+
// of its own has nothing renderable: its grid view fails the data-view
|
|
50
|
+
// column check and `toString` has nothing to interpolate. Scaffold one
|
|
51
|
+
// visible name column so the module validates and the grid shows a row.
|
|
52
|
+
toString: `{${NAME_FIELD}}`,
|
|
33
53
|
traits,
|
|
34
|
-
fields: {
|
|
54
|
+
fields: {
|
|
55
|
+
[NAME_FIELD]: {
|
|
56
|
+
dbDatatype: "varchar",
|
|
57
|
+
fieldTypeCd: "text",
|
|
58
|
+
flags: "VEM",
|
|
59
|
+
maxLen: 200,
|
|
60
|
+
orderNum: 10,
|
|
61
|
+
description: "Name"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
35
64
|
};
|
|
36
65
|
if (entity.constraints?.length) {
|
|
37
66
|
built.constraints = Object.fromEntries(
|
|
@@ -116,7 +145,8 @@ function buildTranslations(opts) {
|
|
|
116
145
|
for (const e of opts.entities) {
|
|
117
146
|
const fields = {
|
|
118
147
|
// identity trait → primary key column
|
|
119
|
-
[`${e.name}_id`]: { label: `${e.label} ID` }
|
|
148
|
+
[`${e.name}_id`]: { label: `${e.label} ID` },
|
|
149
|
+
[NAME_FIELD]: { label: "Name" }
|
|
120
150
|
};
|
|
121
151
|
if (e.traits === "identity+audit") {
|
|
122
152
|
fields.created_date = { label: "Created Date" };
|
|
@@ -157,8 +187,9 @@ function buildTranslations(opts) {
|
|
|
157
187
|
}
|
|
158
188
|
};
|
|
159
189
|
}
|
|
160
|
-
function buildSeedData() {
|
|
161
|
-
|
|
190
|
+
function buildSeedData(entity) {
|
|
191
|
+
const entityCode = typeof entity === "string" ? entity : entity?.name ?? "";
|
|
192
|
+
return { entityCode, records: [] };
|
|
162
193
|
}
|
|
163
194
|
function buildGitignore() {
|
|
164
195
|
return [
|
|
@@ -180,34 +211,87 @@ var SCHEMA_BINDINGS = [
|
|
|
180
211
|
{ fileMatch: ["ui/folders.json"], schema: "folders" },
|
|
181
212
|
{ fileMatch: ["ui/menus.json"], schema: "menus" },
|
|
182
213
|
{ fileMatch: ["ui/reports.json"], schema: "reports" },
|
|
214
|
+
{ fileMatch: ["ui/print_templates.json"], schema: "print-templates" },
|
|
183
215
|
{ fileMatch: ["security/roles.json"], schema: "roles" },
|
|
184
216
|
{ fileMatch: ["logic/jobs.json"], schema: "jobs" },
|
|
217
|
+
{ fileMatch: ["logic/triggers.json"], schema: "triggers" },
|
|
218
|
+
{ fileMatch: ["logic/webhooks.json"], schema: "webhooks" },
|
|
219
|
+
{ fileMatch: ["deps/*.json"], schema: "deps" },
|
|
185
220
|
{ fileMatch: ["seed-data/*.json"], schema: "seed-data" },
|
|
186
221
|
{ fileMatch: ["settings.json"], schema: "settings" }
|
|
187
222
|
];
|
|
223
|
+
function schemaEntries() {
|
|
224
|
+
return SCHEMA_BINDINGS.map((b) => ({
|
|
225
|
+
fileMatch: b.fileMatch,
|
|
226
|
+
url: `${SCHEMA_BASE}/${b.schema}.schema.json`
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
188
229
|
function buildVscodeSettings() {
|
|
189
|
-
return {
|
|
190
|
-
"json.schemas": SCHEMA_BINDINGS.map((b) => ({
|
|
191
|
-
fileMatch: b.fileMatch,
|
|
192
|
-
url: `${SCHEMA_BASE}/${b.schema}.schema.json`
|
|
193
|
-
}))
|
|
194
|
-
};
|
|
230
|
+
return { "json.schemas": schemaEntries() };
|
|
195
231
|
}
|
|
196
232
|
function buildZedSettings() {
|
|
197
233
|
return {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
234
|
+
lsp: {
|
|
235
|
+
"json-language-server": {
|
|
236
|
+
settings: { json: { schemas: schemaEntries() } }
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
context_servers: {
|
|
240
|
+
dforge: {
|
|
241
|
+
source: "custom",
|
|
242
|
+
command: "npx",
|
|
243
|
+
args: ["-y", "@dforge-core/dforge-mcp@latest"],
|
|
244
|
+
env: {}
|
|
204
245
|
}
|
|
205
246
|
}
|
|
206
247
|
};
|
|
207
248
|
}
|
|
249
|
+
function buildZedTasks() {
|
|
250
|
+
const CLI = "npx";
|
|
251
|
+
const CLI_ARGS = ["-y", "@dforge-core/dforge-cli@latest"];
|
|
252
|
+
const DEFAULT_TENANT = "http://localhost:5179";
|
|
253
|
+
const task = (label, args) => ({
|
|
254
|
+
label: `dForge: ${label}`,
|
|
255
|
+
command: CLI,
|
|
256
|
+
args: [...CLI_ARGS, ...args],
|
|
257
|
+
cwd: "$ZED_WORKTREE_ROOT",
|
|
258
|
+
env: { DFORGE_URL: DEFAULT_TENANT },
|
|
259
|
+
use_new_terminal: false,
|
|
260
|
+
allow_concurrent_runs: false,
|
|
261
|
+
reveal: "always"
|
|
262
|
+
});
|
|
263
|
+
return [
|
|
264
|
+
task("Pack module", ["module", "pack", "$ZED_WORKTREE_ROOT"]),
|
|
265
|
+
// --force matches the extension's dev-loop default: without it the CLI
|
|
266
|
+
// skips the reinstall when the version hasn't changed and your edits
|
|
267
|
+
// silently never reach the tenant.
|
|
268
|
+
task("Install module to tenant", [
|
|
269
|
+
"module",
|
|
270
|
+
"install",
|
|
271
|
+
"--path",
|
|
272
|
+
"$ZED_WORKTREE_ROOT",
|
|
273
|
+
"--url",
|
|
274
|
+
"$DFORGE_URL",
|
|
275
|
+
"--force"
|
|
276
|
+
]),
|
|
277
|
+
task("Sign in to tenant", [
|
|
278
|
+
"auth",
|
|
279
|
+
"login",
|
|
280
|
+
"--url",
|
|
281
|
+
"$DFORGE_URL",
|
|
282
|
+
"--login-url",
|
|
283
|
+
"$DFORGE_URL"
|
|
284
|
+
]),
|
|
285
|
+
task("Show signed-in user", ["auth", "whoami", "--url", "$DFORGE_URL"]),
|
|
286
|
+
task("List installed modules", ["module", "list", "--url", "$DFORGE_URL"])
|
|
287
|
+
];
|
|
288
|
+
}
|
|
208
289
|
export {
|
|
290
|
+
DEPENDENCY_RANGE,
|
|
291
|
+
NAME_FIELD,
|
|
209
292
|
buildActions,
|
|
210
293
|
buildDataViews,
|
|
294
|
+
buildDepsContract,
|
|
211
295
|
buildEntity,
|
|
212
296
|
buildFolders,
|
|
213
297
|
buildGitignore,
|
|
@@ -218,5 +302,6 @@ export {
|
|
|
218
302
|
buildSettings,
|
|
219
303
|
buildTranslations,
|
|
220
304
|
buildVscodeSettings,
|
|
221
|
-
buildZedSettings
|
|
305
|
+
buildZedSettings,
|
|
306
|
+
buildZedTasks
|
|
222
307
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dforge-core/dforge-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.17",
|
|
4
4
|
"description": "dForge CLI - validate, pack, publish, and install dForge modules. Distributes a single-file native binary per platform via optionalDependencies (esbuild-style).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/dforge-core/dforge-cli",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"typescript": "^6.0.3"
|
|
42
42
|
},
|
|
43
43
|
"optionalDependencies": {
|
|
44
|
-
"@dforge-core/dforge-cli-darwin-arm64": "0.2.
|
|
45
|
-
"@dforge-core/dforge-cli-darwin-x64": "0.2.
|
|
46
|
-
"@dforge-core/dforge-cli-linux-arm64": "0.2.
|
|
47
|
-
"@dforge-core/dforge-cli-linux-x64": "0.2.
|
|
48
|
-
"@dforge-core/dforge-cli-win32-arm64": "0.2.
|
|
49
|
-
"@dforge-core/dforge-cli-win32-x64": "0.2.
|
|
44
|
+
"@dforge-core/dforge-cli-darwin-arm64": "0.2.17",
|
|
45
|
+
"@dforge-core/dforge-cli-darwin-x64": "0.2.17",
|
|
46
|
+
"@dforge-core/dforge-cli-linux-arm64": "0.2.17",
|
|
47
|
+
"@dforge-core/dforge-cli-linux-x64": "0.2.17",
|
|
48
|
+
"@dforge-core/dforge-cli-win32-arm64": "0.2.17",
|
|
49
|
+
"@dforge-core/dforge-cli-win32-x64": "0.2.17"
|
|
50
50
|
}
|
|
51
51
|
}
|