@mmapp/react-compiler 0.1.0-alpha.4 → 0.1.0-alpha.6
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/babel/index.d.mts +2 -2
- package/dist/babel/index.d.ts +2 -2
- package/dist/babel/index.js +5 -5
- package/dist/babel/index.mjs +1 -1
- package/dist/cli/index.js +797 -1941
- package/dist/cli/index.mjs +179 -77
- package/dist/codemod/cli.js +1 -1
- package/dist/codemod/cli.mjs +1 -1
- package/dist/codemod/index.d.mts +3 -3
- package/dist/codemod/index.d.ts +3 -3
- package/dist/codemod/index.js +1 -1
- package/dist/codemod/index.mjs +1 -1
- package/dist/dev-server.d.mts +2 -2
- package/dist/dev-server.d.ts +2 -2
- package/dist/dev-server.js +86 -1218
- package/dist/dev-server.mjs +4 -4
- package/dist/envelope.d.mts +2 -2
- package/dist/envelope.d.ts +2 -2
- package/dist/envelope.js +5 -5
- package/dist/envelope.mjs +2 -2
- package/dist/index.d.mts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +342 -1266
- package/dist/index.mjs +8 -8
- package/dist/testing/index.d.mts +8 -8
- package/dist/testing/index.d.ts +8 -8
- package/dist/testing/index.js +5 -5
- package/dist/testing/index.mjs +1 -1
- package/dist/vite/index.d.mts +1 -1
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +5 -5
- package/dist/vite/index.mjs +2 -2
- package/examples/authentication/main.workflow.tsx +1 -1
- package/examples/authentication/mm.config.ts +1 -1
- package/examples/authentication/pages/LoginPage.tsx +2 -2
- package/examples/authentication/pages/SignupPage.tsx +2 -2
- package/examples/counter.workflow.tsx +1 -1
- package/examples/dashboard.workflow.tsx +1 -1
- package/examples/invoice-approval/actions/invoice.server.ts +1 -1
- package/examples/invoice-approval/main.workflow.tsx +1 -1
- package/examples/invoice-approval/mm.config.ts +1 -1
- package/examples/invoice-approval/pages/InvoiceDetailPage.tsx +1 -1
- package/examples/invoice-approval/pages/InvoiceFormPage.tsx +1 -1
- package/examples/invoice-approval/pages/InvoiceListPage.tsx +1 -1
- package/examples/todo-app.workflow.tsx +1 -1
- package/examples/uber-app/actions/matching.server.ts +1 -1
- package/examples/uber-app/actions/notifications.server.ts +1 -1
- package/examples/uber-app/actions/payments.server.ts +1 -1
- package/examples/uber-app/actions/pricing.server.ts +1 -1
- package/examples/uber-app/app/admin/analytics.tsx +2 -2
- package/examples/uber-app/app/admin/fleet.tsx +2 -2
- package/examples/uber-app/app/admin/surge-pricing.tsx +2 -2
- package/examples/uber-app/app/driver/dashboard.tsx +2 -2
- package/examples/uber-app/app/driver/earnings.tsx +2 -2
- package/examples/uber-app/app/driver/navigation.tsx +2 -2
- package/examples/uber-app/app/driver/ride-acceptance.tsx +2 -2
- package/examples/uber-app/app/rider/home.tsx +2 -2
- package/examples/uber-app/app/rider/payment-methods.tsx +2 -2
- package/examples/uber-app/app/rider/ride-history.tsx +2 -2
- package/examples/uber-app/app/rider/ride-tracking.tsx +2 -2
- package/examples/uber-app/components/DriverCard.tsx +1 -1
- package/examples/uber-app/components/MapView.tsx +3 -3
- package/examples/uber-app/components/RatingStars.tsx +2 -2
- package/examples/uber-app/components/RideCard.tsx +1 -1
- package/examples/uber-app/mm.config.ts +1 -1
- package/examples/uber-app/workflows/dispute-resolution.workflow.tsx +2 -2
- package/examples/uber-app/workflows/driver-onboarding.workflow.tsx +2 -2
- package/examples/uber-app/workflows/payment-processing.workflow.tsx +2 -2
- package/examples/uber-app/workflows/ride-request.workflow.tsx +2 -2
- package/package.json +13 -9
- package/dist/auth-3UK75242.mjs +0 -17
- package/dist/chunk-5FTDWKHH.mjs +0 -244
- package/dist/chunk-7JRAEFRB.mjs +0 -7510
- package/dist/chunk-7T6Q5KAA.mjs +0 -7506
- package/dist/chunk-ABYPKRSB.mjs +0 -215
- package/dist/chunk-BZEXUPDH.mjs +0 -175
- package/dist/chunk-HRYR54PT.mjs +0 -175
- package/dist/chunk-J3M4GUS7.mjs +0 -161
- package/dist/chunk-JRGFBWTN.mjs +0 -2918
- package/dist/chunk-O4AUS7EU.mjs +0 -148
- package/dist/chunk-R2DD5GTY.mjs +0 -186
- package/dist/chunk-UDDTWG5J.mjs +0 -734
- package/dist/chunk-VLTKQDJ3.mjs +0 -244
- package/dist/chunk-WVYY32LD.mjs +0 -939
- package/dist/chunk-XDVM4YHX.mjs +0 -3450
- package/dist/chunk-Z2G5RZ4H.mjs +0 -186
- package/dist/chunk-ZE3KCHBM.mjs +0 -2918
- package/dist/deploy-YAJGW6II.mjs +0 -9
- package/dist/dev-server-CrQ041KP.d.mts +0 -79
- package/dist/dev-server-CrQ041KP.d.ts +0 -79
- package/dist/envelope-ChEkuHij.d.mts +0 -265
- package/dist/envelope-ChEkuHij.d.ts +0 -265
- package/dist/index-CEKyyazf.d.mts +0 -104
- package/dist/index-CEKyyazf.d.ts +0 -104
- package/dist/init-7FJENUDK.mjs +0 -407
- package/dist/project-compiler-NNK32MPG.mjs +0 -10
- package/dist/project-compiler-ZB4RUYVL.mjs +0 -10
- package/dist/project-decompiler-U55HQUHW.mjs +0 -7
- package/dist/pull-KOL2QAYQ.mjs +0 -109
- package/dist/seed-KOGEPGOJ.mjs +0 -154
- package/dist/server-VW6UPCHO.mjs +0 -277
- package/dist/verify-BYHUKARQ.mjs +0 -1833
- package/dist/verify-OQDEQYMS.mjs +0 -1833
package/dist/cli/index.js
CHANGED
|
@@ -4388,7 +4388,7 @@ function extractImperativeWorkflow(path, state) {
|
|
|
4388
4388
|
const source = node.source.value;
|
|
4389
4389
|
for (const spec of node.specifiers) {
|
|
4390
4390
|
const localName = spec.local.name;
|
|
4391
|
-
if (source.includes("@mmapp/react") || source.includes("@
|
|
4391
|
+
if (source.includes("@mmapp/react") || source.includes("@mindmatrix/react")) {
|
|
4392
4392
|
stdLibImports.add(localName);
|
|
4393
4393
|
} else {
|
|
4394
4394
|
importedFns.set(localName, source);
|
|
@@ -7028,7 +7028,7 @@ var import_player_core, PROP_RULES, COMPONENT_RENAMES, RENAME_EXTRA_CONFIG;
|
|
|
7028
7028
|
var init_pure_form_emitter = __esm({
|
|
7029
7029
|
"src/babel/emitters/pure-form-emitter.ts"() {
|
|
7030
7030
|
"use strict";
|
|
7031
|
-
import_player_core = require("@
|
|
7031
|
+
import_player_core = require("@mindmatrix/player-core");
|
|
7032
7032
|
init_transition_extractor();
|
|
7033
7033
|
init_experience_transform();
|
|
7034
7034
|
PROP_RULES = {
|
|
@@ -7407,7 +7407,7 @@ function createVisitor(options = {}) {
|
|
|
7407
7407
|
if (mode === "strict" && STRICT_BANNED_HOOKS[hookName]) {
|
|
7408
7408
|
const error = {
|
|
7409
7409
|
code: STRICT_BANNED_HOOKS[hookName],
|
|
7410
|
-
message: `${hookName}() is not allowed in strict mode. Use @
|
|
7410
|
+
message: `${hookName}() is not allowed in strict mode. Use @mindmatrix/react effect hooks instead.`,
|
|
7411
7411
|
line: path.node.loc?.start.line,
|
|
7412
7412
|
column: path.node.loc?.start.column,
|
|
7413
7413
|
severity: "error"
|
|
@@ -7499,12 +7499,12 @@ function createVisitor(options = {}) {
|
|
|
7499
7499
|
}
|
|
7500
7500
|
}
|
|
7501
7501
|
if (mode !== "strict") return;
|
|
7502
|
-
if (source.startsWith("@
|
|
7502
|
+
if (source.startsWith("@mindmatrix/") || source.startsWith("@mmapp/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
|
|
7503
7503
|
return;
|
|
7504
7504
|
}
|
|
7505
7505
|
const error = {
|
|
7506
7506
|
code: "STRICT_FORBIDDEN_IMPORT",
|
|
7507
|
-
message: `Import from '${source}' is not allowed in strict mode. Only @
|
|
7507
|
+
message: `Import from '${source}' is not allowed in strict mode. Only @mindmatrix/* and relative imports are permitted.`,
|
|
7508
7508
|
line: path.node.loc?.start.line,
|
|
7509
7509
|
column: path.node.loc?.start.column,
|
|
7510
7510
|
severity: "error"
|
|
@@ -11398,7 +11398,7 @@ function buildJSXTree(node, imports, symbols) {
|
|
|
11398
11398
|
}
|
|
11399
11399
|
const componentName = node.component;
|
|
11400
11400
|
if (REACT_ATOMS.has(componentName)) {
|
|
11401
|
-
addImport(imports, "@
|
|
11401
|
+
addImport(imports, "@mindmatrix/react", componentName);
|
|
11402
11402
|
}
|
|
11403
11403
|
const attributes = [];
|
|
11404
11404
|
if (node.config) {
|
|
@@ -11443,7 +11443,7 @@ function buildJSXTree(node, imports, symbols) {
|
|
|
11443
11443
|
isSelfClosing
|
|
11444
11444
|
);
|
|
11445
11445
|
if (node.visible_when) {
|
|
11446
|
-
addImport(imports, "@
|
|
11446
|
+
addImport(imports, "@mindmatrix/react", "Show");
|
|
11447
11447
|
return t24.jsxElement(
|
|
11448
11448
|
t24.jsxOpeningElement(
|
|
11449
11449
|
t24.jsxIdentifier("Show"),
|
|
@@ -11566,7 +11566,7 @@ function fieldTypeAnnotation(field) {
|
|
|
11566
11566
|
}
|
|
11567
11567
|
function emitFieldDeclarations(fields, imports) {
|
|
11568
11568
|
if (fields.length === 0) return [];
|
|
11569
|
-
addImport2(imports, "@
|
|
11569
|
+
addImport2(imports, "@mindmatrix/react", "useState");
|
|
11570
11570
|
const statements = [];
|
|
11571
11571
|
for (const field of fields) {
|
|
11572
11572
|
if (field.computed) continue;
|
|
@@ -11630,7 +11630,7 @@ function emitStateEffects(states, imports) {
|
|
|
11630
11630
|
const statements = [];
|
|
11631
11631
|
for (const state of states) {
|
|
11632
11632
|
if (state.on_enter.length > 0) {
|
|
11633
|
-
addImport2(imports, "@
|
|
11633
|
+
addImport2(imports, "@mindmatrix/react", "useOnEnter");
|
|
11634
11634
|
statements.push(
|
|
11635
11635
|
t25.expressionStatement(
|
|
11636
11636
|
t25.callExpression(t25.identifier("useOnEnter"), [
|
|
@@ -11641,7 +11641,7 @@ function emitStateEffects(states, imports) {
|
|
|
11641
11641
|
);
|
|
11642
11642
|
}
|
|
11643
11643
|
if (state.on_exit.length > 0) {
|
|
11644
|
-
addImport2(imports, "@
|
|
11644
|
+
addImport2(imports, "@mindmatrix/react", "useOnExit");
|
|
11645
11645
|
statements.push(
|
|
11646
11646
|
t25.expressionStatement(
|
|
11647
11647
|
t25.callExpression(t25.identifier("useOnExit"), [
|
|
@@ -11652,7 +11652,7 @@ function emitStateEffects(states, imports) {
|
|
|
11652
11652
|
);
|
|
11653
11653
|
}
|
|
11654
11654
|
if (state.during.length > 0) {
|
|
11655
|
-
addImport2(imports, "@
|
|
11655
|
+
addImport2(imports, "@mindmatrix/react", "useWhileIn");
|
|
11656
11656
|
for (const during of state.during) {
|
|
11657
11657
|
const args2 = [
|
|
11658
11658
|
t25.stringLiteral(state.name)
|
|
@@ -11673,7 +11673,7 @@ function emitStateEffects(states, imports) {
|
|
|
11673
11673
|
}
|
|
11674
11674
|
function emitTransitionDeclarations(transitions, imports) {
|
|
11675
11675
|
if (transitions.length === 0) return [];
|
|
11676
|
-
addImport2(imports, "@
|
|
11676
|
+
addImport2(imports, "@mindmatrix/react", "useTransition");
|
|
11677
11677
|
const correctedTransitions = correctFromFields(transitions);
|
|
11678
11678
|
const statements = [];
|
|
11679
11679
|
for (const transition of correctedTransitions) {
|
|
@@ -11908,7 +11908,7 @@ function emitSingleCondition(cond) {
|
|
|
11908
11908
|
function emitRoleDeclarations(metadata, imports) {
|
|
11909
11909
|
const roleDeps = metadata?.roleDependencies;
|
|
11910
11910
|
if (!roleDeps || roleDeps.length === 0) return [];
|
|
11911
|
-
addImport2(imports, "@
|
|
11911
|
+
addImport2(imports, "@mindmatrix/react", "useRole");
|
|
11912
11912
|
const statements = [];
|
|
11913
11913
|
for (const role of roleDeps) {
|
|
11914
11914
|
const varName = `is${toPascalCase(role)}`;
|
|
@@ -11929,7 +11929,7 @@ function emitQueryDeclarations(metadata, imports) {
|
|
|
11929
11929
|
const modelImports = metadata?.modelImports;
|
|
11930
11930
|
const addedModelImports = /* @__PURE__ */ new Set();
|
|
11931
11931
|
if (dataSources && dataSources.length > 0) {
|
|
11932
|
-
addImport2(imports, "@
|
|
11932
|
+
addImport2(imports, "@mindmatrix/react", "useQuery");
|
|
11933
11933
|
const usedVarNames = /* @__PURE__ */ new Set();
|
|
11934
11934
|
for (const ds of dataSources) {
|
|
11935
11935
|
if (ds.type !== "workflow") continue;
|
|
@@ -11996,7 +11996,7 @@ function emitQueryDeclarations(metadata, imports) {
|
|
|
11996
11996
|
}
|
|
11997
11997
|
const mutationTargets = metadata?.mutationTargets;
|
|
11998
11998
|
if (mutationTargets && mutationTargets.length > 0) {
|
|
11999
|
-
addImport2(imports, "@
|
|
11999
|
+
addImport2(imports, "@mindmatrix/react", "useMutation");
|
|
12000
12000
|
for (const slug of mutationTargets) {
|
|
12001
12001
|
const modelPath = modelImports?.[slug];
|
|
12002
12002
|
const modelVarName2 = modelPath ? `${toCamelCase2(slug.replace(/-/g, "_"))}Model` : void 0;
|
|
@@ -12021,7 +12021,7 @@ function emitQueryDeclarations(metadata, imports) {
|
|
|
12021
12021
|
function emitChangeWatchers(metadata, imports) {
|
|
12022
12022
|
const watchers = metadata?.fieldWatchers;
|
|
12023
12023
|
if (!watchers || watchers.length === 0) return [];
|
|
12024
|
-
addImport2(imports, "@
|
|
12024
|
+
addImport2(imports, "@mindmatrix/react", "useOnChange");
|
|
12025
12025
|
const statements = [];
|
|
12026
12026
|
for (const watcher of watchers) {
|
|
12027
12027
|
statements.push(
|
|
@@ -12037,7 +12037,7 @@ function emitChangeWatchers(metadata, imports) {
|
|
|
12037
12037
|
}
|
|
12038
12038
|
function emitEventSubscriptions(onEvent, imports) {
|
|
12039
12039
|
if (!onEvent || onEvent.length === 0) return [];
|
|
12040
|
-
addImport2(imports, "@
|
|
12040
|
+
addImport2(imports, "@mindmatrix/react", "useOnEvent");
|
|
12041
12041
|
const statements = [];
|
|
12042
12042
|
for (const sub of onEvent) {
|
|
12043
12043
|
const actions = sub.actions.map((a, i) => ({
|
|
@@ -12064,7 +12064,7 @@ function emitEventSubscriptions(onEvent, imports) {
|
|
|
12064
12064
|
function emitTransitionEffects(metadata, imports) {
|
|
12065
12065
|
const effects = metadata?.transitionEffects;
|
|
12066
12066
|
if (!effects || effects.length === 0) return [];
|
|
12067
|
-
addImport2(imports, "@
|
|
12067
|
+
addImport2(imports, "@mindmatrix/react", "useOnTransition");
|
|
12068
12068
|
const statements = [];
|
|
12069
12069
|
for (const effect of effects) {
|
|
12070
12070
|
statements.push(
|
|
@@ -12095,7 +12095,7 @@ function emitLocalDefaultDeclarations(experience, existingFields, imports) {
|
|
|
12095
12095
|
const camelName = toCamelCase2(key);
|
|
12096
12096
|
if (emittedCamelNames.has(camelName)) continue;
|
|
12097
12097
|
emittedCamelNames.add(camelName);
|
|
12098
|
-
addImport2(imports, "@
|
|
12098
|
+
addImport2(imports, "@mindmatrix/react", "useState");
|
|
12099
12099
|
const setter = `set${toPascalCase(key)}`;
|
|
12100
12100
|
let defaultExpr;
|
|
12101
12101
|
if (value === void 0 || value === null) {
|
|
@@ -12277,7 +12277,7 @@ function generateMmConfig(config) {
|
|
|
12277
12277
|
` * Auto-generated from workflow definition "${config.slug}".`,
|
|
12278
12278
|
` */`,
|
|
12279
12279
|
``,
|
|
12280
|
-
`import { ${fnName} } from '@
|
|
12280
|
+
`import { ${fnName} } from '@mindmatrix/react';`,
|
|
12281
12281
|
``,
|
|
12282
12282
|
`export default ${fnName}({`,
|
|
12283
12283
|
` slug: '${esc(config.slug)}',`,
|
|
@@ -12745,7 +12745,7 @@ function generateModelFile(slug, fields, states, transitions, meta) {
|
|
|
12745
12745
|
const version = meta?.version || "0.1.0";
|
|
12746
12746
|
const category = meta?.category || "data";
|
|
12747
12747
|
const lines = [];
|
|
12748
|
-
lines.push(`import { defineModel } from '@
|
|
12748
|
+
lines.push(`import { defineModel } from '@mindmatrix/react';`);
|
|
12749
12749
|
lines.push(``);
|
|
12750
12750
|
const sortedFields = [...fields].sort((a, b) => a.name.localeCompare(b.name));
|
|
12751
12751
|
if (sortedFields.length > 0) {
|
|
@@ -12907,7 +12907,7 @@ function generateLayoutFile(slug, roles) {
|
|
|
12907
12907
|
` * ${componentName} \u2014 root layout with auth guards.`,
|
|
12908
12908
|
` */`,
|
|
12909
12909
|
``,
|
|
12910
|
-
`import { useRole, Stack } from '@
|
|
12910
|
+
`import { useRole, Stack } from '@mindmatrix/react';`,
|
|
12911
12911
|
``,
|
|
12912
12912
|
`interface LayoutProps {`,
|
|
12913
12913
|
` children: React.ReactNode;`,
|
|
@@ -13360,7 +13360,7 @@ function generateServerActionFile(slug, actions) {
|
|
|
13360
13360
|
` * These run server-side during state transitions.`,
|
|
13361
13361
|
` */`,
|
|
13362
13362
|
``,
|
|
13363
|
-
`import type { TransitionContext } from '@
|
|
13363
|
+
`import type { TransitionContext } from '@mindmatrix/react';`,
|
|
13364
13364
|
``
|
|
13365
13365
|
];
|
|
13366
13366
|
for (const action of actions) {
|
|
@@ -13621,7 +13621,7 @@ function generateServerActionFileFromBodies(filePath, actions) {
|
|
|
13621
13621
|
` * Auto-generated from preserved function bodies.`,
|
|
13622
13622
|
` */`,
|
|
13623
13623
|
``,
|
|
13624
|
-
`import type { TransitionContext, ActionResult } from '@
|
|
13624
|
+
`import type { TransitionContext, ActionResult } from '@mindmatrix/react';`,
|
|
13625
13625
|
``
|
|
13626
13626
|
];
|
|
13627
13627
|
for (const action of actions) {
|
|
@@ -13917,7 +13917,7 @@ function decompileProjectEnhanced(definition) {
|
|
|
13917
13917
|
}
|
|
13918
13918
|
function generatePackageJson(def) {
|
|
13919
13919
|
const pkg = {
|
|
13920
|
-
name: `@
|
|
13920
|
+
name: `@mindmatrix/blueprint-${def.slug}`,
|
|
13921
13921
|
version: def.version || "1.0.0",
|
|
13922
13922
|
description: def.description || "",
|
|
13923
13923
|
type: "module",
|
|
@@ -13929,10 +13929,10 @@ function generatePackageJson(def) {
|
|
|
13929
13929
|
},
|
|
13930
13930
|
peerDependencies: {
|
|
13931
13931
|
react: ">=18.0.0",
|
|
13932
|
-
"@
|
|
13932
|
+
"@mindmatrix/react": "workspace:*"
|
|
13933
13933
|
},
|
|
13934
13934
|
devDependencies: {
|
|
13935
|
-
"@
|
|
13935
|
+
"@mindmatrix/react-compiler": "workspace:*",
|
|
13936
13936
|
"@types/react": "^19.0.0",
|
|
13937
13937
|
typescript: "^5.4.0"
|
|
13938
13938
|
}
|
|
@@ -13984,392 +13984,6 @@ var init_project_decompiler = __esm({
|
|
|
13984
13984
|
}
|
|
13985
13985
|
});
|
|
13986
13986
|
|
|
13987
|
-
// src/cli/deploy.ts
|
|
13988
|
-
var deploy_exports = {};
|
|
13989
|
-
__export(deploy_exports, {
|
|
13990
|
-
deploy: () => deploy,
|
|
13991
|
-
syncServices: () => syncServices
|
|
13992
|
-
});
|
|
13993
|
-
async function deploy(options) {
|
|
13994
|
-
const dir = options.dir ?? "dist/workflows";
|
|
13995
|
-
const targetLabel = options.targetName ? ` (target: ${options.targetName})` : "";
|
|
13996
|
-
console.log(`[mindmatrix-react] Deploying workflows from ${dir} to ${options.apiUrl}${targetLabel}...`);
|
|
13997
|
-
const files = await (0, import_glob3.glob)(`${dir}/**/*.workflow.json`);
|
|
13998
|
-
if (files.length === 0) {
|
|
13999
|
-
console.log(`[mindmatrix-react] No workflow files found in ${dir}`);
|
|
14000
|
-
return { created: [], updated: [], versioned: [], skipped: [], failed: [] };
|
|
14001
|
-
}
|
|
14002
|
-
const result = {
|
|
14003
|
-
created: [],
|
|
14004
|
-
updated: [],
|
|
14005
|
-
versioned: [],
|
|
14006
|
-
skipped: [],
|
|
14007
|
-
failed: []
|
|
14008
|
-
};
|
|
14009
|
-
const deployedIRs = [];
|
|
14010
|
-
for (const file2 of files) {
|
|
14011
|
-
try {
|
|
14012
|
-
const ir = JSON.parse((0, import_fs4.readFileSync)(file2, "utf-8"));
|
|
14013
|
-
const slug = ir.slug;
|
|
14014
|
-
if (options.dryRun) {
|
|
14015
|
-
console.log(` [dry-run] Would deploy ${slug} (${(0, import_path3.basename)(file2)})`);
|
|
14016
|
-
continue;
|
|
14017
|
-
}
|
|
14018
|
-
const existing = await fetchExistingDefinition(options.apiUrl, options.token, slug);
|
|
14019
|
-
if (!existing) {
|
|
14020
|
-
await createDefinition(options.apiUrl, options.token, ir);
|
|
14021
|
-
console.log(` \u2713 ${slug} (created)`);
|
|
14022
|
-
result.created.push(slug);
|
|
14023
|
-
} else if (existing.instanceCount === 0 || options.force) {
|
|
14024
|
-
await updateDefinition(options.apiUrl, options.token, existing.id, ir);
|
|
14025
|
-
console.log(` \u2713 ${slug} (updated)`);
|
|
14026
|
-
result.updated.push(slug);
|
|
14027
|
-
} else {
|
|
14028
|
-
const newVersion = bumpVersion(existing.version);
|
|
14029
|
-
ir.version = newVersion;
|
|
14030
|
-
await createDefinition(options.apiUrl, options.token, ir);
|
|
14031
|
-
console.log(` \u2713 ${slug} v${newVersion} (new version, ${existing.instanceCount} instances on v${existing.version})`);
|
|
14032
|
-
result.versioned.push(slug);
|
|
14033
|
-
}
|
|
14034
|
-
deployedIRs.push(ir);
|
|
14035
|
-
} catch (error) {
|
|
14036
|
-
const slug = (0, import_path3.basename)(file2).replace(".workflow.json", "");
|
|
14037
|
-
const msg = error.message;
|
|
14038
|
-
console.error(` \u2717 ${slug}: ${msg}`);
|
|
14039
|
-
result.failed.push({ slug, error: msg });
|
|
14040
|
-
}
|
|
14041
|
-
}
|
|
14042
|
-
if (!options.dryRun) {
|
|
14043
|
-
for (const ir of deployedIRs) {
|
|
14044
|
-
const serviceResult = await syncServices(options.apiUrl, options.token, ir);
|
|
14045
|
-
if (serviceResult) {
|
|
14046
|
-
if (!result.services) {
|
|
14047
|
-
result.services = { registered: [], updated: [], failed: [] };
|
|
14048
|
-
}
|
|
14049
|
-
result.services.registered.push(...serviceResult.registered);
|
|
14050
|
-
result.services.updated.push(...serviceResult.updated);
|
|
14051
|
-
result.services.failed.push(...serviceResult.failed);
|
|
14052
|
-
}
|
|
14053
|
-
}
|
|
14054
|
-
}
|
|
14055
|
-
if (options.reportFile) {
|
|
14056
|
-
(0, import_fs4.writeFileSync)(options.reportFile, JSON.stringify(result, null, 2), "utf-8");
|
|
14057
|
-
console.log(`
|
|
14058
|
-
Report written to ${options.reportFile}`);
|
|
14059
|
-
}
|
|
14060
|
-
const total = result.created.length + result.updated.length + result.versioned.length;
|
|
14061
|
-
console.log(
|
|
14062
|
-
`
|
|
14063
|
-
[mindmatrix-react] Deployed ${total} workflows (${result.created.length} created, ${result.updated.length} updated, ${result.versioned.length} versioned, ${result.failed.length} failed)`
|
|
14064
|
-
);
|
|
14065
|
-
if (result.services) {
|
|
14066
|
-
const svcTotal = result.services.registered.length + result.services.updated.length;
|
|
14067
|
-
if (svcTotal > 0 || result.services.failed.length > 0) {
|
|
14068
|
-
console.log(
|
|
14069
|
-
`[mindmatrix-react] Synced ${svcTotal} services (${result.services.registered.length} registered, ${result.services.updated.length} updated, ${result.services.failed.length} failed)`
|
|
14070
|
-
);
|
|
14071
|
-
}
|
|
14072
|
-
}
|
|
14073
|
-
return result;
|
|
14074
|
-
}
|
|
14075
|
-
async function fetchExistingDefinition(apiUrl, token, slug) {
|
|
14076
|
-
try {
|
|
14077
|
-
const res = await fetch(`${apiUrl}/workflow/definitions?slug=${encodeURIComponent(slug)}`, {
|
|
14078
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
14079
|
-
});
|
|
14080
|
-
if (!res.ok) return null;
|
|
14081
|
-
const data = await res.json();
|
|
14082
|
-
const definitions = Array.isArray(data) ? data : data.items ?? data.data;
|
|
14083
|
-
if (!definitions || definitions.length === 0) return null;
|
|
14084
|
-
const def = definitions[0];
|
|
14085
|
-
return {
|
|
14086
|
-
id: def.id,
|
|
14087
|
-
slug: def.slug,
|
|
14088
|
-
version: def.version || "0.1.0",
|
|
14089
|
-
instanceCount: def.instanceCount ?? def.instance_count ?? 0
|
|
14090
|
-
};
|
|
14091
|
-
} catch {
|
|
14092
|
-
return null;
|
|
14093
|
-
}
|
|
14094
|
-
}
|
|
14095
|
-
async function createDefinition(apiUrl, token, ir) {
|
|
14096
|
-
const res = await fetch(`${apiUrl}/workflow/definitions`, {
|
|
14097
|
-
method: "POST",
|
|
14098
|
-
headers: {
|
|
14099
|
-
"Content-Type": "application/json",
|
|
14100
|
-
Authorization: `Bearer ${token}`
|
|
14101
|
-
},
|
|
14102
|
-
body: JSON.stringify(ir)
|
|
14103
|
-
});
|
|
14104
|
-
if (!res.ok) {
|
|
14105
|
-
const errorText = await res.text();
|
|
14106
|
-
throw new Error(`Create failed: ${res.status} ${errorText}`);
|
|
14107
|
-
}
|
|
14108
|
-
}
|
|
14109
|
-
async function updateDefinition(apiUrl, token, id, ir) {
|
|
14110
|
-
const { slug: _slug, ...updatePayload } = ir;
|
|
14111
|
-
const res = await fetch(`${apiUrl}/workflow/definitions/${id}`, {
|
|
14112
|
-
method: "PATCH",
|
|
14113
|
-
headers: {
|
|
14114
|
-
"Content-Type": "application/json",
|
|
14115
|
-
Authorization: `Bearer ${token}`
|
|
14116
|
-
},
|
|
14117
|
-
body: JSON.stringify(updatePayload)
|
|
14118
|
-
});
|
|
14119
|
-
if (!res.ok) {
|
|
14120
|
-
const errorText = await res.text();
|
|
14121
|
-
throw new Error(`Update failed: ${res.status} ${errorText}`);
|
|
14122
|
-
}
|
|
14123
|
-
}
|
|
14124
|
-
function bumpVersion(version) {
|
|
14125
|
-
const parts = version.split(".");
|
|
14126
|
-
if (parts.length !== 3) return `${version}.1`;
|
|
14127
|
-
const patch = parseInt(parts[2], 10) || 0;
|
|
14128
|
-
return `${parts[0]}.${parts[1]}.${patch + 1}`;
|
|
14129
|
-
}
|
|
14130
|
-
async function syncServices(apiUrl, token, ir) {
|
|
14131
|
-
const metadata = ir.metadata;
|
|
14132
|
-
const orchestration = metadata?.orchestration;
|
|
14133
|
-
const services = orchestration?.services;
|
|
14134
|
-
if (!services || Object.keys(services).length === 0) return null;
|
|
14135
|
-
const result = { registered: [], updated: [], failed: [] };
|
|
14136
|
-
for (const [name, config] of Object.entries(services)) {
|
|
14137
|
-
try {
|
|
14138
|
-
const registration = {
|
|
14139
|
-
name,
|
|
14140
|
-
connection: {
|
|
14141
|
-
type: config.type || "webhook",
|
|
14142
|
-
url: config.url,
|
|
14143
|
-
queue: config.queue
|
|
14144
|
-
},
|
|
14145
|
-
actions: config.actions || [],
|
|
14146
|
-
labels: config.labels || {}
|
|
14147
|
-
};
|
|
14148
|
-
const existing = await fetchExistingService(apiUrl, token, name);
|
|
14149
|
-
if (existing) {
|
|
14150
|
-
await fetch(`${apiUrl}/services/${existing.id}`, {
|
|
14151
|
-
method: "PATCH",
|
|
14152
|
-
headers: {
|
|
14153
|
-
"Content-Type": "application/json",
|
|
14154
|
-
Authorization: `Bearer ${token}`
|
|
14155
|
-
},
|
|
14156
|
-
body: JSON.stringify(registration)
|
|
14157
|
-
});
|
|
14158
|
-
console.log(` \u2713 service: ${name} (updated)`);
|
|
14159
|
-
result.updated.push(name);
|
|
14160
|
-
} else {
|
|
14161
|
-
const res = await fetch(`${apiUrl}/services`, {
|
|
14162
|
-
method: "POST",
|
|
14163
|
-
headers: {
|
|
14164
|
-
"Content-Type": "application/json",
|
|
14165
|
-
Authorization: `Bearer ${token}`
|
|
14166
|
-
},
|
|
14167
|
-
body: JSON.stringify(registration)
|
|
14168
|
-
});
|
|
14169
|
-
if (!res.ok) {
|
|
14170
|
-
const errorText = await res.text();
|
|
14171
|
-
throw new Error(`Register failed: ${res.status} ${errorText}`);
|
|
14172
|
-
}
|
|
14173
|
-
console.log(` \u2713 service: ${name} (registered)`);
|
|
14174
|
-
result.registered.push(name);
|
|
14175
|
-
}
|
|
14176
|
-
} catch (error) {
|
|
14177
|
-
const msg = error.message;
|
|
14178
|
-
console.error(` \u2717 service: ${name}: ${msg}`);
|
|
14179
|
-
result.failed.push(name);
|
|
14180
|
-
}
|
|
14181
|
-
}
|
|
14182
|
-
return result;
|
|
14183
|
-
}
|
|
14184
|
-
async function fetchExistingService(apiUrl, token, name) {
|
|
14185
|
-
try {
|
|
14186
|
-
const res = await fetch(`${apiUrl}/services?name=${encodeURIComponent(name)}`, {
|
|
14187
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
14188
|
-
});
|
|
14189
|
-
if (!res.ok) return null;
|
|
14190
|
-
const data = await res.json();
|
|
14191
|
-
const servicesList = Array.isArray(data) ? data : data.services ?? data.items ?? data.data;
|
|
14192
|
-
if (!servicesList || servicesList.length === 0) return null;
|
|
14193
|
-
const found = servicesList.find((s) => s.name === name);
|
|
14194
|
-
return found ? { id: found.id, name: found.name } : null;
|
|
14195
|
-
} catch {
|
|
14196
|
-
return null;
|
|
14197
|
-
}
|
|
14198
|
-
}
|
|
14199
|
-
var import_glob3, import_fs4, import_path3;
|
|
14200
|
-
var init_deploy = __esm({
|
|
14201
|
-
"src/cli/deploy.ts"() {
|
|
14202
|
-
"use strict";
|
|
14203
|
-
import_glob3 = require("glob");
|
|
14204
|
-
import_fs4 = require("fs");
|
|
14205
|
-
import_path3 = require("path");
|
|
14206
|
-
}
|
|
14207
|
-
});
|
|
14208
|
-
|
|
14209
|
-
// src/cli/auth.ts
|
|
14210
|
-
var auth_exports = {};
|
|
14211
|
-
__export(auth_exports, {
|
|
14212
|
-
loadCredentials: () => loadCredentials,
|
|
14213
|
-
login: () => login,
|
|
14214
|
-
logout: () => logout,
|
|
14215
|
-
resolveToken: () => resolveToken,
|
|
14216
|
-
saveCredentials: () => saveCredentials,
|
|
14217
|
-
whoami: () => whoami
|
|
14218
|
-
});
|
|
14219
|
-
function loadCredentials() {
|
|
14220
|
-
if (!(0, import_fs5.existsSync)(CREDENTIALS_PATH)) return {};
|
|
14221
|
-
try {
|
|
14222
|
-
return JSON.parse((0, import_fs5.readFileSync)(CREDENTIALS_PATH, "utf-8"));
|
|
14223
|
-
} catch {
|
|
14224
|
-
return {};
|
|
14225
|
-
}
|
|
14226
|
-
}
|
|
14227
|
-
function saveCredentials(apiUrl, token) {
|
|
14228
|
-
(0, import_fs5.mkdirSync)(MMRC_DIR, { recursive: true, mode: 448 });
|
|
14229
|
-
const creds = loadCredentials();
|
|
14230
|
-
creds[apiUrl] = { token, savedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
14231
|
-
(0, import_fs5.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
14232
|
-
try {
|
|
14233
|
-
const { chmodSync } = require("fs");
|
|
14234
|
-
chmodSync(CREDENTIALS_PATH, 384);
|
|
14235
|
-
} catch {
|
|
14236
|
-
}
|
|
14237
|
-
}
|
|
14238
|
-
function removeCredentials(apiUrl) {
|
|
14239
|
-
if (!(0, import_fs5.existsSync)(CREDENTIALS_PATH)) return;
|
|
14240
|
-
if (!apiUrl) {
|
|
14241
|
-
(0, import_fs5.unlinkSync)(CREDENTIALS_PATH);
|
|
14242
|
-
return;
|
|
14243
|
-
}
|
|
14244
|
-
const creds = loadCredentials();
|
|
14245
|
-
delete creds[apiUrl];
|
|
14246
|
-
if (Object.keys(creds).length === 0) {
|
|
14247
|
-
(0, import_fs5.unlinkSync)(CREDENTIALS_PATH);
|
|
14248
|
-
} else {
|
|
14249
|
-
(0, import_fs5.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
14250
|
-
}
|
|
14251
|
-
}
|
|
14252
|
-
function resolveToken(apiUrl, explicitToken) {
|
|
14253
|
-
if (explicitToken) return explicitToken;
|
|
14254
|
-
const envToken = process.env.MMRC_TOKEN;
|
|
14255
|
-
if (envToken) return envToken;
|
|
14256
|
-
const creds = loadCredentials();
|
|
14257
|
-
const entry = creds[apiUrl];
|
|
14258
|
-
if (entry?.token) return entry.token;
|
|
14259
|
-
return null;
|
|
14260
|
-
}
|
|
14261
|
-
function prompt(question, hidden = false) {
|
|
14262
|
-
return new Promise((resolve6) => {
|
|
14263
|
-
const rl = (0, import_readline.createInterface)({
|
|
14264
|
-
input: process.stdin,
|
|
14265
|
-
output: process.stdout
|
|
14266
|
-
});
|
|
14267
|
-
if (hidden && process.stdin.isTTY) {
|
|
14268
|
-
const origWrite = process.stdout.write.bind(process.stdout);
|
|
14269
|
-
process.stdout.write = ((chunk, encodingOrCb, cb) => {
|
|
14270
|
-
if (typeof chunk === "string" && chunk.includes(question)) {
|
|
14271
|
-
return origWrite(chunk, encodingOrCb, cb);
|
|
14272
|
-
}
|
|
14273
|
-
if (typeof chunk === "string" && !chunk.includes("\n")) {
|
|
14274
|
-
return true;
|
|
14275
|
-
}
|
|
14276
|
-
return origWrite(chunk, encodingOrCb, cb);
|
|
14277
|
-
});
|
|
14278
|
-
rl.question(question, (answer) => {
|
|
14279
|
-
process.stdout.write = origWrite;
|
|
14280
|
-
console.log();
|
|
14281
|
-
rl.close();
|
|
14282
|
-
resolve6(answer.trim());
|
|
14283
|
-
});
|
|
14284
|
-
} else {
|
|
14285
|
-
rl.question(question, (answer) => {
|
|
14286
|
-
rl.close();
|
|
14287
|
-
resolve6(answer.trim());
|
|
14288
|
-
});
|
|
14289
|
-
}
|
|
14290
|
-
});
|
|
14291
|
-
}
|
|
14292
|
-
async function login(apiUrl, email, password) {
|
|
14293
|
-
if (!email) {
|
|
14294
|
-
email = await prompt("Email: ");
|
|
14295
|
-
}
|
|
14296
|
-
if (!password) {
|
|
14297
|
-
password = await prompt("Password: ", true);
|
|
14298
|
-
}
|
|
14299
|
-
if (!email || !password) {
|
|
14300
|
-
throw new Error("Email and password are required");
|
|
14301
|
-
}
|
|
14302
|
-
console.log(`[mmrc] Logging in to ${apiUrl}...`);
|
|
14303
|
-
const res = await fetch(`${apiUrl}/auth/login`, {
|
|
14304
|
-
method: "POST",
|
|
14305
|
-
headers: { "Content-Type": "application/json" },
|
|
14306
|
-
body: JSON.stringify({ email, password })
|
|
14307
|
-
});
|
|
14308
|
-
if (!res.ok) {
|
|
14309
|
-
const text = await res.text();
|
|
14310
|
-
throw new Error(`Login failed: ${res.status} ${text}`);
|
|
14311
|
-
}
|
|
14312
|
-
const data = await res.json();
|
|
14313
|
-
const token = data.token ?? data.access_token ?? data.accessToken;
|
|
14314
|
-
if (!token) {
|
|
14315
|
-
throw new Error("Login succeeded but no token in response");
|
|
14316
|
-
}
|
|
14317
|
-
saveCredentials(apiUrl, token);
|
|
14318
|
-
const userName = data.name ?? data.user?.name ?? data.user?.email ?? email;
|
|
14319
|
-
console.log(`[mmrc] Logged in as ${userName}`);
|
|
14320
|
-
console.log(`[mmrc] Token saved to ${CREDENTIALS_PATH}`);
|
|
14321
|
-
return token;
|
|
14322
|
-
}
|
|
14323
|
-
function logout(apiUrl) {
|
|
14324
|
-
if (apiUrl) {
|
|
14325
|
-
removeCredentials(apiUrl);
|
|
14326
|
-
console.log(`[mmrc] Credentials removed for ${apiUrl}`);
|
|
14327
|
-
} else {
|
|
14328
|
-
removeCredentials();
|
|
14329
|
-
console.log("[mmrc] All saved credentials removed");
|
|
14330
|
-
}
|
|
14331
|
-
}
|
|
14332
|
-
async function whoami(apiUrl) {
|
|
14333
|
-
const token = resolveToken(apiUrl);
|
|
14334
|
-
if (!token) {
|
|
14335
|
-
console.log("[mmrc] Not logged in. Run `mmrc login` to authenticate.");
|
|
14336
|
-
return;
|
|
14337
|
-
}
|
|
14338
|
-
try {
|
|
14339
|
-
const res = await fetch(`${apiUrl}/auth/me`, {
|
|
14340
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
14341
|
-
});
|
|
14342
|
-
if (!res.ok) {
|
|
14343
|
-
if (res.status === 401) {
|
|
14344
|
-
console.log("[mmrc] Token is expired or invalid. Run `mmrc login` to re-authenticate.");
|
|
14345
|
-
return;
|
|
14346
|
-
}
|
|
14347
|
-
console.log(`[mmrc] Failed to fetch user info: ${res.status}`);
|
|
14348
|
-
return;
|
|
14349
|
-
}
|
|
14350
|
-
const user = await res.json();
|
|
14351
|
-
console.log(`[mmrc] Logged in to ${apiUrl}`);
|
|
14352
|
-
console.log(` Name: ${user.name ?? "(unknown)"}`);
|
|
14353
|
-
console.log(` Email: ${user.email ?? "(unknown)"}`);
|
|
14354
|
-
if (user.id) console.log(` ID: ${user.id}`);
|
|
14355
|
-
if (user.role) console.log(` Role: ${user.role}`);
|
|
14356
|
-
} catch (error) {
|
|
14357
|
-
console.log(`[mmrc] Could not connect to ${apiUrl}: ${error.message}`);
|
|
14358
|
-
}
|
|
14359
|
-
}
|
|
14360
|
-
var import_fs5, import_path4, import_os, import_readline, MMRC_DIR, CREDENTIALS_PATH;
|
|
14361
|
-
var init_auth = __esm({
|
|
14362
|
-
"src/cli/auth.ts"() {
|
|
14363
|
-
"use strict";
|
|
14364
|
-
import_fs5 = require("fs");
|
|
14365
|
-
import_path4 = require("path");
|
|
14366
|
-
import_os = require("os");
|
|
14367
|
-
import_readline = require("readline");
|
|
14368
|
-
MMRC_DIR = (0, import_path4.join)((0, import_os.homedir)(), ".mmrc");
|
|
14369
|
-
CREDENTIALS_PATH = (0, import_path4.join)(MMRC_DIR, "credentials.json");
|
|
14370
|
-
}
|
|
14371
|
-
});
|
|
14372
|
-
|
|
14373
13987
|
// src/vite/index.ts
|
|
14374
13988
|
function mindmatrixReact(options) {
|
|
14375
13989
|
const include = options?.include ?? ["**/*.workflow.tsx"];
|
|
@@ -14539,735 +14153,17 @@ var init_vite = __esm({
|
|
|
14539
14153
|
"src/vite/index.ts"() {
|
|
14540
14154
|
"use strict";
|
|
14541
14155
|
import_core5 = require("@babel/core");
|
|
14542
|
-
import_fs6 = require("fs");
|
|
14543
|
-
import_path5 = require("path");
|
|
14544
|
-
init_babel();
|
|
14545
|
-
}
|
|
14546
|
-
});
|
|
14547
|
-
|
|
14548
|
-
// src/cli/local-server.ts
|
|
14549
|
-
async function startLocalServer(options = {}) {
|
|
14550
|
-
const { port = 4200, noAuth = true } = options;
|
|
14551
|
-
const store = new MemoryStore();
|
|
14552
|
-
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
14553
|
-
function json(res, status, body) {
|
|
14554
|
-
const data = JSON.stringify(body);
|
|
14555
|
-
res.writeHead(status, {
|
|
14556
|
-
"Content-Type": "application/json",
|
|
14557
|
-
"Access-Control-Allow-Origin": "*",
|
|
14558
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
14559
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
14560
|
-
"Content-Length": Buffer.byteLength(data)
|
|
14561
|
-
});
|
|
14562
|
-
res.end(data);
|
|
14563
|
-
}
|
|
14564
|
-
function readBody(req) {
|
|
14565
|
-
return new Promise((resolve6, reject) => {
|
|
14566
|
-
const chunks = [];
|
|
14567
|
-
req.on("data", (chunk) => chunks.push(chunk));
|
|
14568
|
-
req.on("end", () => resolve6(Buffer.concat(chunks).toString()));
|
|
14569
|
-
req.on("error", reject);
|
|
14570
|
-
});
|
|
14571
|
-
}
|
|
14572
|
-
function parseQuery(url) {
|
|
14573
|
-
const idx = url.indexOf("?");
|
|
14574
|
-
if (idx === -1) return {};
|
|
14575
|
-
const params = {};
|
|
14576
|
-
const qs = url.slice(idx + 1);
|
|
14577
|
-
for (const pair of qs.split("&")) {
|
|
14578
|
-
const [k, v] = pair.split("=");
|
|
14579
|
-
if (k) params[decodeURIComponent(k)] = decodeURIComponent(v ?? "");
|
|
14580
|
-
}
|
|
14581
|
-
return params;
|
|
14582
|
-
}
|
|
14583
|
-
const server = http.createServer(async (req, res) => {
|
|
14584
|
-
const method = req.method?.toUpperCase() ?? "GET";
|
|
14585
|
-
const rawUrl = req.url ?? "/";
|
|
14586
|
-
const queryStart = rawUrl.indexOf("?");
|
|
14587
|
-
const path = queryStart >= 0 ? rawUrl.slice(0, queryStart) : rawUrl;
|
|
14588
|
-
const query = parseQuery(rawUrl);
|
|
14589
|
-
if (method === "OPTIONS") {
|
|
14590
|
-
res.writeHead(204, {
|
|
14591
|
-
"Access-Control-Allow-Origin": "*",
|
|
14592
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
14593
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
14594
|
-
"Access-Control-Max-Age": "86400"
|
|
14595
|
-
});
|
|
14596
|
-
res.end();
|
|
14597
|
-
return;
|
|
14598
|
-
}
|
|
14599
|
-
try {
|
|
14600
|
-
if (path === "/health" && method === "GET") {
|
|
14601
|
-
return json(res, 200, {
|
|
14602
|
-
status: "ok",
|
|
14603
|
-
service: "mm-local-dev",
|
|
14604
|
-
mode: "in-memory",
|
|
14605
|
-
started_at: startedAt,
|
|
14606
|
-
definitions: store.definitions.size,
|
|
14607
|
-
instances: store.instances.size
|
|
14608
|
-
});
|
|
14609
|
-
}
|
|
14610
|
-
if (path === "/api/v1/auth/login" && (method === "POST" || method === "GET")) {
|
|
14611
|
-
return json(res, 200, {
|
|
14612
|
-
token: "dev-token-local",
|
|
14613
|
-
user: {
|
|
14614
|
-
id: "dev-user-001",
|
|
14615
|
-
email: "dev@localhost",
|
|
14616
|
-
role: "admin",
|
|
14617
|
-
name: "Local Developer"
|
|
14618
|
-
}
|
|
14619
|
-
});
|
|
14620
|
-
}
|
|
14621
|
-
if (path === "/api/v1/workflow/definitions" && method === "GET") {
|
|
14622
|
-
const result = store.listDefinitions({
|
|
14623
|
-
category: query.category,
|
|
14624
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
14625
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
14626
|
-
});
|
|
14627
|
-
if (query.slug) {
|
|
14628
|
-
const def = store.getDefinition(query.slug);
|
|
14629
|
-
return json(res, 200, { items: def ? [def] : [], total: def ? 1 : 0 });
|
|
14630
|
-
}
|
|
14631
|
-
return json(res, 200, result);
|
|
14632
|
-
}
|
|
14633
|
-
const defMatch = path.match(/^\/api\/v1\/workflow\/definitions\/([^/]+)$/);
|
|
14634
|
-
if (defMatch && method === "GET") {
|
|
14635
|
-
const def = store.getDefinition(defMatch[1]);
|
|
14636
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
14637
|
-
return json(res, 200, def);
|
|
14638
|
-
}
|
|
14639
|
-
if (path === "/api/v1/workflow/definitions" && method === "POST") {
|
|
14640
|
-
const body = JSON.parse(await readBody(req));
|
|
14641
|
-
const def = store.createDefinition(body);
|
|
14642
|
-
return json(res, 201, def);
|
|
14643
|
-
}
|
|
14644
|
-
if (defMatch && method === "PATCH") {
|
|
14645
|
-
const body = JSON.parse(await readBody(req));
|
|
14646
|
-
const updated = store.patchDefinition(defMatch[1], body);
|
|
14647
|
-
if (!updated) return json(res, 404, { error: "Not found" });
|
|
14648
|
-
return json(res, 200, updated);
|
|
14649
|
-
}
|
|
14650
|
-
if (defMatch && method === "DELETE") {
|
|
14651
|
-
const deleted = store.deleteDefinition(defMatch[1]);
|
|
14652
|
-
if (!deleted) return json(res, 404, { error: "Not found" });
|
|
14653
|
-
return json(res, 204, null);
|
|
14654
|
-
}
|
|
14655
|
-
if (path === "/api/v1/workflow/instances" && method === "GET") {
|
|
14656
|
-
const result = store.listInstances({
|
|
14657
|
-
definition_id: query.definition_id,
|
|
14658
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
14659
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
14660
|
-
});
|
|
14661
|
-
return json(res, 200, result);
|
|
14662
|
-
}
|
|
14663
|
-
if (path === "/api/v1/workflow/instances" && method === "POST") {
|
|
14664
|
-
const body = JSON.parse(await readBody(req));
|
|
14665
|
-
const inst = store.createInstance(body);
|
|
14666
|
-
if (!inst) return json(res, 404, { error: "Definition not found" });
|
|
14667
|
-
return json(res, 201, inst);
|
|
14668
|
-
}
|
|
14669
|
-
const instMatch = path.match(/^\/api\/v1\/workflow\/instances\/([^/]+)$/);
|
|
14670
|
-
if (instMatch && method === "GET") {
|
|
14671
|
-
const inst = store.getInstance(instMatch[1]);
|
|
14672
|
-
if (!inst) return json(res, 404, { error: "Not found" });
|
|
14673
|
-
return json(res, 200, inst);
|
|
14674
|
-
}
|
|
14675
|
-
if (path === "/api/v1/workflow/execute-action" && method === "POST") {
|
|
14676
|
-
const body = JSON.parse(await readBody(req));
|
|
14677
|
-
const result = store.executeAction(body);
|
|
14678
|
-
return json(res, 200, result);
|
|
14679
|
-
}
|
|
14680
|
-
const dataMatch = path.match(/^\/api\/v1\/data\/([^/]+)$/);
|
|
14681
|
-
if (dataMatch && method === "GET") {
|
|
14682
|
-
const def = store.getDefinition(dataMatch[1]);
|
|
14683
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
14684
|
-
const instances = store.listInstances({ definition_id: def.id });
|
|
14685
|
-
return json(res, 200, instances);
|
|
14686
|
-
}
|
|
14687
|
-
if (path.startsWith("/api/v1/")) {
|
|
14688
|
-
return json(res, 501, { error: "Not implemented in local dev mode", path, method });
|
|
14689
|
-
}
|
|
14690
|
-
return json(res, 404, { error: "Not found", path });
|
|
14691
|
-
} catch (err) {
|
|
14692
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14693
|
-
console.error(`[mm-local] ${method} ${path} \u2014 Error: ${message}`);
|
|
14694
|
-
return json(res, 500, { error: message });
|
|
14695
|
-
}
|
|
14696
|
-
});
|
|
14697
|
-
return new Promise((resolve6, reject) => {
|
|
14698
|
-
server.on("error", (err) => {
|
|
14699
|
-
if (err.code === "EADDRINUSE") {
|
|
14700
|
-
reject(new Error(`Port ${port} is already in use. Is another server running?`));
|
|
14701
|
-
} else {
|
|
14702
|
-
reject(err);
|
|
14703
|
-
}
|
|
14704
|
-
});
|
|
14705
|
-
server.listen(port, () => {
|
|
14706
|
-
console.log(`[mm-local] Local API server running at http://localhost:${port}`);
|
|
14707
|
-
console.log(`[mm-local] Mode: in-memory (data lost on restart)`);
|
|
14708
|
-
console.log(`[mm-local] Auth: disabled (all requests accepted)`);
|
|
14709
|
-
resolve6({
|
|
14710
|
-
server,
|
|
14711
|
-
port,
|
|
14712
|
-
store,
|
|
14713
|
-
async close() {
|
|
14714
|
-
return new Promise((res) => {
|
|
14715
|
-
server.close(() => {
|
|
14716
|
-
console.log("[mm-local] Local API server stopped");
|
|
14717
|
-
res();
|
|
14718
|
-
});
|
|
14719
|
-
});
|
|
14720
|
-
}
|
|
14721
|
-
});
|
|
14722
|
-
});
|
|
14723
|
-
});
|
|
14724
|
-
}
|
|
14725
|
-
var http, import_node_crypto, MemoryStore;
|
|
14726
|
-
var init_local_server = __esm({
|
|
14727
|
-
"src/cli/local-server.ts"() {
|
|
14728
|
-
"use strict";
|
|
14729
|
-
http = __toESM(require("http"));
|
|
14730
|
-
import_node_crypto = require("crypto");
|
|
14731
|
-
MemoryStore = class {
|
|
14732
|
-
constructor() {
|
|
14733
|
-
this.definitions = /* @__PURE__ */ new Map();
|
|
14734
|
-
this.instances = /* @__PURE__ */ new Map();
|
|
14735
|
-
this.slugIndex = /* @__PURE__ */ new Map();
|
|
14736
|
-
}
|
|
14737
|
-
// slug → id
|
|
14738
|
-
// ── Definitions ──────────────────────────────────────────────────────
|
|
14739
|
-
createDefinition(input) {
|
|
14740
|
-
if (this.slugIndex.has(input.slug)) {
|
|
14741
|
-
const existing = this.definitions.get(this.slugIndex.get(input.slug));
|
|
14742
|
-
if (existing) return existing;
|
|
14743
|
-
}
|
|
14744
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14745
|
-
const def = {
|
|
14746
|
-
id: input.id ?? (0, import_node_crypto.randomUUID)(),
|
|
14747
|
-
slug: input.slug,
|
|
14748
|
-
name: input.name,
|
|
14749
|
-
version: input.version ?? "1.0.0",
|
|
14750
|
-
description: input.description ?? null,
|
|
14751
|
-
category: input.category ?? "workflow",
|
|
14752
|
-
fields: input.fields ?? [],
|
|
14753
|
-
states: input.states ?? [],
|
|
14754
|
-
transitions: input.transitions ?? [],
|
|
14755
|
-
roles: input.roles ?? [],
|
|
14756
|
-
experience: input.experience ?? null,
|
|
14757
|
-
metadata: input.metadata ?? {},
|
|
14758
|
-
child_definitions: input.child_definitions ?? [],
|
|
14759
|
-
is_immutable: input.is_immutable ?? false,
|
|
14760
|
-
tags: input.tags ?? [],
|
|
14761
|
-
inline_tags: input.inline_tags ?? [],
|
|
14762
|
-
created_at: now,
|
|
14763
|
-
updated_at: now
|
|
14764
|
-
};
|
|
14765
|
-
this.definitions.set(def.id, def);
|
|
14766
|
-
this.slugIndex.set(def.slug, def.id);
|
|
14767
|
-
return def;
|
|
14768
|
-
}
|
|
14769
|
-
getDefinition(idOrSlug) {
|
|
14770
|
-
const byId = this.definitions.get(idOrSlug);
|
|
14771
|
-
if (byId) return byId;
|
|
14772
|
-
const id = this.slugIndex.get(idOrSlug);
|
|
14773
|
-
if (id) return this.definitions.get(id);
|
|
14774
|
-
return void 0;
|
|
14775
|
-
}
|
|
14776
|
-
listDefinitions(opts) {
|
|
14777
|
-
let items = Array.from(this.definitions.values());
|
|
14778
|
-
if (opts?.category) {
|
|
14779
|
-
items = items.filter((d) => d.category === opts.category);
|
|
14780
|
-
}
|
|
14781
|
-
const total = items.length;
|
|
14782
|
-
const offset = opts?.offset ?? 0;
|
|
14783
|
-
const limit = opts?.limit ?? 50;
|
|
14784
|
-
items = items.slice(offset, offset + limit);
|
|
14785
|
-
return { items, total };
|
|
14786
|
-
}
|
|
14787
|
-
patchDefinition(id, patch) {
|
|
14788
|
-
const def = this.definitions.get(id);
|
|
14789
|
-
if (!def) return void 0;
|
|
14790
|
-
Object.assign(def, patch, { updated_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
14791
|
-
return def;
|
|
14792
|
-
}
|
|
14793
|
-
deleteDefinition(id) {
|
|
14794
|
-
const def = this.definitions.get(id);
|
|
14795
|
-
if (!def) return false;
|
|
14796
|
-
this.slugIndex.delete(def.slug);
|
|
14797
|
-
this.definitions.delete(id);
|
|
14798
|
-
return true;
|
|
14799
|
-
}
|
|
14800
|
-
// ── Instances ────────────────────────────────────────────────────────
|
|
14801
|
-
createInstance(input) {
|
|
14802
|
-
const def = this.getDefinition(input.definition_id) ?? this.getDefinition(input.definition_slug);
|
|
14803
|
-
if (!def) return null;
|
|
14804
|
-
const initialState = def.states.find((s) => s.type === "START" || s.type === "initial");
|
|
14805
|
-
const stateName = initialState?.name ?? "initial";
|
|
14806
|
-
const stateData = {};
|
|
14807
|
-
for (const field of def.fields) {
|
|
14808
|
-
if (field.default_value !== void 0) {
|
|
14809
|
-
stateData[field.name] = field.default_value;
|
|
14810
|
-
}
|
|
14811
|
-
}
|
|
14812
|
-
Object.assign(stateData, input.state_data ?? {});
|
|
14813
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14814
|
-
const inst = {
|
|
14815
|
-
id: (0, import_node_crypto.randomUUID)(),
|
|
14816
|
-
definition_id: def.id,
|
|
14817
|
-
definition_slug: def.slug,
|
|
14818
|
-
current_state: stateName,
|
|
14819
|
-
state_data: stateData,
|
|
14820
|
-
execution_lock_version: 0,
|
|
14821
|
-
event_log: [{
|
|
14822
|
-
event_type: "transition",
|
|
14823
|
-
message: `Instance created in state '${stateName}'`,
|
|
14824
|
-
timestamp: now
|
|
14825
|
-
}],
|
|
14826
|
-
created_at: now,
|
|
14827
|
-
updated_at: now
|
|
14828
|
-
};
|
|
14829
|
-
this.instances.set(inst.id, inst);
|
|
14830
|
-
return inst;
|
|
14831
|
-
}
|
|
14832
|
-
getInstance(id) {
|
|
14833
|
-
return this.instances.get(id);
|
|
14834
|
-
}
|
|
14835
|
-
listInstances(opts) {
|
|
14836
|
-
let items = Array.from(this.instances.values());
|
|
14837
|
-
if (opts?.definition_id) {
|
|
14838
|
-
items = items.filter((i) => i.definition_id === opts.definition_id);
|
|
14839
|
-
}
|
|
14840
|
-
const total = items.length;
|
|
14841
|
-
const offset = opts?.offset ?? 0;
|
|
14842
|
-
const limit = opts?.limit ?? 50;
|
|
14843
|
-
items = items.slice(offset, offset + limit);
|
|
14844
|
-
return { items, total };
|
|
14845
|
-
}
|
|
14846
|
-
// ── Execute Action (Transition) ──────────────────────────────────────
|
|
14847
|
-
executeAction(input) {
|
|
14848
|
-
const def = this.getDefinition(input.definition_id);
|
|
14849
|
-
if (!def) return { success: false, error: "Definition not found" };
|
|
14850
|
-
let inst;
|
|
14851
|
-
if (input.instance_id) {
|
|
14852
|
-
const existing = this.instances.get(input.instance_id);
|
|
14853
|
-
if (!existing) return { success: false, error: "Instance not found" };
|
|
14854
|
-
inst = existing;
|
|
14855
|
-
} else {
|
|
14856
|
-
const created = this.createInstance({
|
|
14857
|
-
definition_id: def.id,
|
|
14858
|
-
definition_slug: def.slug,
|
|
14859
|
-
state_data: input.payload
|
|
14860
|
-
});
|
|
14861
|
-
if (!created) return { success: false, error: "Failed to create instance" };
|
|
14862
|
-
inst = created;
|
|
14863
|
-
}
|
|
14864
|
-
if (input.payload && input.instance_id) {
|
|
14865
|
-
Object.assign(inst.state_data, input.payload);
|
|
14866
|
-
}
|
|
14867
|
-
const transition = def.transitions.find((t27) => t27.name === input.action_name && t27.from.includes(inst.current_state));
|
|
14868
|
-
if (!transition) {
|
|
14869
|
-
return {
|
|
14870
|
-
success: false,
|
|
14871
|
-
instance_id: inst.id,
|
|
14872
|
-
from_state: inst.current_state,
|
|
14873
|
-
to_state: null,
|
|
14874
|
-
state_data: inst.state_data,
|
|
14875
|
-
error: `No transition '${input.action_name}' from state '${inst.current_state}'`
|
|
14876
|
-
};
|
|
14877
|
-
}
|
|
14878
|
-
const fromState = inst.current_state;
|
|
14879
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14880
|
-
const events = [];
|
|
14881
|
-
let lastEvalResult = null;
|
|
14882
|
-
events.push({ event_type: "transition", message: `Transition '${transition.name}' started: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
14883
|
-
for (const action of transition.actions ?? []) {
|
|
14884
|
-
try {
|
|
14885
|
-
if (action.type === "set_field") {
|
|
14886
|
-
const field = action.config?.field;
|
|
14887
|
-
if (action.config?.expression) {
|
|
14888
|
-
const expr = action.config.expression;
|
|
14889
|
-
const result = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
14890
|
-
inst.state_data[field] = result;
|
|
14891
|
-
} else if (action.config?.value !== void 0) {
|
|
14892
|
-
inst.state_data[field] = action.config.value;
|
|
14893
|
-
}
|
|
14894
|
-
events.push({ event_type: "action_executed", message: `transition action 'set_field' succeeded`, timestamp: now });
|
|
14895
|
-
} else if (action.type === "eval") {
|
|
14896
|
-
const expr = action.config?.expression;
|
|
14897
|
-
lastEvalResult = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
14898
|
-
events.push({ event_type: "action_executed", message: `transition action 'eval' succeeded`, timestamp: now });
|
|
14899
|
-
} else {
|
|
14900
|
-
events.push({ event_type: "action_executed", message: `transition action '${action.type}' succeeded (no-op in local mode)`, timestamp: now });
|
|
14901
|
-
}
|
|
14902
|
-
} catch (err) {
|
|
14903
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
14904
|
-
events.push({ event_type: "action_failed", message: `transition action '${action.type}' failed: ${msg}`, timestamp: now });
|
|
14905
|
-
return {
|
|
14906
|
-
success: false,
|
|
14907
|
-
instance_id: inst.id,
|
|
14908
|
-
from_state: fromState,
|
|
14909
|
-
to_state: null,
|
|
14910
|
-
state_data: inst.state_data,
|
|
14911
|
-
event_log: events,
|
|
14912
|
-
error: `transition action failed: ${msg}`
|
|
14913
|
-
};
|
|
14914
|
-
}
|
|
14915
|
-
}
|
|
14916
|
-
inst.current_state = transition.to;
|
|
14917
|
-
inst.execution_lock_version++;
|
|
14918
|
-
inst.updated_at = now;
|
|
14919
|
-
events.push({ event_type: "transition", message: `State changed: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
14920
|
-
inst.event_log.push(...events);
|
|
14921
|
-
return {
|
|
14922
|
-
success: true,
|
|
14923
|
-
instance_id: inst.id,
|
|
14924
|
-
from_state: fromState,
|
|
14925
|
-
to_state: transition.to,
|
|
14926
|
-
state_data: inst.state_data,
|
|
14927
|
-
result: lastEvalResult,
|
|
14928
|
-
event_log: events
|
|
14929
|
-
};
|
|
14930
|
-
}
|
|
14931
|
-
/**
|
|
14932
|
-
* Minimal expression evaluator for local dev mode.
|
|
14933
|
-
* Handles: field references, arithmetic, string literals, simple comparisons.
|
|
14934
|
-
* Does NOT handle: while loops, if/else, function calls, multi-statement blocks.
|
|
14935
|
-
* For full evaluation, use mm-napi when available.
|
|
14936
|
-
*/
|
|
14937
|
-
evaluateSimpleExpression(expr, context) {
|
|
14938
|
-
if (context[expr] !== void 0) return context[expr];
|
|
14939
|
-
const arithMatch = expr.match(/^(\w+)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/);
|
|
14940
|
-
if (arithMatch) {
|
|
14941
|
-
const [, field, op, numStr] = arithMatch;
|
|
14942
|
-
const left = Number(context[field] ?? 0);
|
|
14943
|
-
const right = Number(numStr);
|
|
14944
|
-
switch (op) {
|
|
14945
|
-
case "+":
|
|
14946
|
-
return left + right;
|
|
14947
|
-
case "-":
|
|
14948
|
-
return left - right;
|
|
14949
|
-
case "*":
|
|
14950
|
-
return left * right;
|
|
14951
|
-
case "/":
|
|
14952
|
-
return right !== 0 ? left / right : 0;
|
|
14953
|
-
}
|
|
14954
|
-
}
|
|
14955
|
-
if (/^\d+(\.\d+)?$/.test(expr.trim())) {
|
|
14956
|
-
return Number(expr.trim());
|
|
14957
|
-
}
|
|
14958
|
-
const strMatch = expr.match(/^["'](.*)["']$/);
|
|
14959
|
-
if (strMatch) return strMatch[1];
|
|
14960
|
-
try {
|
|
14961
|
-
const keys = Object.keys(context);
|
|
14962
|
-
const values = Object.values(context);
|
|
14963
|
-
const fn = new Function(...keys, `"use strict"; return (${expr});`);
|
|
14964
|
-
return fn(...values);
|
|
14965
|
-
} catch {
|
|
14966
|
-
return null;
|
|
14967
|
-
}
|
|
14968
|
-
}
|
|
14969
|
-
};
|
|
14970
|
-
}
|
|
14971
|
-
});
|
|
14972
|
-
|
|
14973
|
-
// src/cli/seed.ts
|
|
14974
|
-
var seed_exports = {};
|
|
14975
|
-
__export(seed_exports, {
|
|
14976
|
-
generateFieldValue: () => generateFieldValue,
|
|
14977
|
-
generateInstanceData: () => generateInstanceData,
|
|
14978
|
-
seedInstances: () => seedInstances
|
|
14979
|
-
});
|
|
14980
|
-
function randomInt(min, max) {
|
|
14981
|
-
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
14982
|
-
}
|
|
14983
|
-
function randomPick(arr) {
|
|
14984
|
-
return arr[Math.floor(Math.random() * arr.length)];
|
|
14985
|
-
}
|
|
14986
|
-
function loremSentence(words = 5) {
|
|
14987
|
-
const result = [];
|
|
14988
|
-
for (let i = 0; i < words; i++) result.push(randomPick(LOREM_WORDS));
|
|
14989
|
-
const s = result.join(" ");
|
|
14990
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
14991
|
-
}
|
|
14992
|
-
function generateFieldValue(field, index) {
|
|
14993
|
-
if (field.default_value !== void 0 && field.default_value !== null) {
|
|
14994
|
-
return field.default_value;
|
|
14995
|
-
}
|
|
14996
|
-
if (field.options && field.options.length > 0) {
|
|
14997
|
-
return field.options[index % field.options.length].value;
|
|
14998
|
-
}
|
|
14999
|
-
const ft = (field.field_type ?? field.type ?? "text").toLowerCase();
|
|
15000
|
-
switch (ft) {
|
|
15001
|
-
case "text":
|
|
15002
|
-
case "string":
|
|
15003
|
-
case "textarea":
|
|
15004
|
-
case "rich_text": {
|
|
15005
|
-
const name = field.name.toLowerCase();
|
|
15006
|
-
if (name.includes("email")) return `${randomPick(FIRST_NAMES).toLowerCase()}${++_counter}@${randomPick(DOMAINS)}`;
|
|
15007
|
-
if (name.includes("name") && name.includes("first")) return randomPick(FIRST_NAMES);
|
|
15008
|
-
if (name.includes("name") && name.includes("last")) return randomPick(LAST_NAMES);
|
|
15009
|
-
if (name.includes("name") || name === "title") return `${randomPick(FIRST_NAMES)} ${randomPick(LAST_NAMES)}`;
|
|
15010
|
-
if (name.includes("company") || name.includes("org")) return randomPick(COMPANIES);
|
|
15011
|
-
if (name.includes("phone")) return `+1-555-${randomInt(100, 999)}-${randomInt(1e3, 9999)}`;
|
|
15012
|
-
if (name.includes("url") || name.includes("website")) return `https://${randomPick(DOMAINS)}/${field.name}`;
|
|
15013
|
-
if (name.includes("description") || name.includes("note") || name.includes("comment")) return loremSentence(randomInt(8, 15));
|
|
15014
|
-
if (name.includes("address")) return `${randomInt(100, 9999)} ${loremSentence(2)} St`;
|
|
15015
|
-
return loremSentence(randomInt(2, 5));
|
|
15016
|
-
}
|
|
15017
|
-
case "number":
|
|
15018
|
-
case "numeric":
|
|
15019
|
-
case "integer":
|
|
15020
|
-
case "int": {
|
|
15021
|
-
const name = field.name.toLowerCase();
|
|
15022
|
-
if (name.includes("price") || name.includes("amount") || name.includes("cost") || name.includes("salary"))
|
|
15023
|
-
return randomInt(1e3, 99999) / 100;
|
|
15024
|
-
if (name.includes("age")) return randomInt(18, 65);
|
|
15025
|
-
if (name.includes("quantity") || name.includes("count") || name.includes("qty")) return randomInt(1, 100);
|
|
15026
|
-
if (name.includes("percent") || name.includes("rate")) return randomInt(1, 100);
|
|
15027
|
-
return randomInt(1, 1e3);
|
|
15028
|
-
}
|
|
15029
|
-
case "currency":
|
|
15030
|
-
case "decimal":
|
|
15031
|
-
return randomInt(100, 999999) / 100;
|
|
15032
|
-
case "boolean":
|
|
15033
|
-
case "bool":
|
|
15034
|
-
case "checkbox":
|
|
15035
|
-
case "toggle":
|
|
15036
|
-
return index % 2 === 0;
|
|
15037
|
-
case "date":
|
|
15038
|
-
case "datetime":
|
|
15039
|
-
case "timestamptz": {
|
|
15040
|
-
const d = /* @__PURE__ */ new Date();
|
|
15041
|
-
d.setDate(d.getDate() - randomInt(0, 365));
|
|
15042
|
-
return d.toISOString().split("T")[0];
|
|
15043
|
-
}
|
|
15044
|
-
case "select":
|
|
15045
|
-
case "enum":
|
|
15046
|
-
case "multi_select":
|
|
15047
|
-
return field.options?.[index % (field.options?.length || 1)]?.value ?? "option_1";
|
|
15048
|
-
case "email":
|
|
15049
|
-
return `${randomPick(FIRST_NAMES).toLowerCase()}${++_counter}@${randomPick(DOMAINS)}`;
|
|
15050
|
-
case "url":
|
|
15051
|
-
return `https://${randomPick(DOMAINS)}/${field.name}`;
|
|
15052
|
-
case "json":
|
|
15053
|
-
case "object":
|
|
15054
|
-
return {};
|
|
15055
|
-
case "array":
|
|
15056
|
-
return [];
|
|
15057
|
-
default:
|
|
15058
|
-
return loremSentence(3);
|
|
15059
|
-
}
|
|
15060
|
-
}
|
|
15061
|
-
function generateInstanceData(fields, index) {
|
|
15062
|
-
const data = {};
|
|
15063
|
-
for (const field of fields) {
|
|
15064
|
-
if (field.name === "id" || field.name === "created_at" || field.name === "updated_at") continue;
|
|
15065
|
-
data[field.name] = generateFieldValue(field, index);
|
|
15066
|
-
}
|
|
15067
|
-
return data;
|
|
15068
|
-
}
|
|
15069
|
-
async function seedInstances(options) {
|
|
15070
|
-
const dir = options.dir ?? "dist/workflows";
|
|
15071
|
-
const count = options.count ?? 7;
|
|
15072
|
-
const result = { created: 0, definitions: 0, errors: [] };
|
|
15073
|
-
const files = await (0, import_glob4.glob)(`${dir}/**/*.workflow.json`);
|
|
15074
|
-
if (files.length === 0) return result;
|
|
15075
|
-
for (const file2 of files) {
|
|
15076
|
-
let def;
|
|
15077
|
-
try {
|
|
15078
|
-
def = JSON.parse((0, import_fs7.readFileSync)(file2, "utf-8"));
|
|
15079
|
-
} catch {
|
|
15080
|
-
continue;
|
|
15081
|
-
}
|
|
15082
|
-
if (!def.slug || !def.fields || def.fields.length === 0) continue;
|
|
15083
|
-
const startState = def.states?.find((s) => s.state_type === "START")?.name ?? def.states?.[0]?.name ?? "initial";
|
|
15084
|
-
let defCreated = 0;
|
|
15085
|
-
for (let i = 0; i < count; i++) {
|
|
15086
|
-
const stateData = generateInstanceData(def.fields, i);
|
|
15087
|
-
try {
|
|
15088
|
-
const resp = await fetch(`${options.apiUrl}/workflow/instances`, {
|
|
15089
|
-
method: "POST",
|
|
15090
|
-
headers: {
|
|
15091
|
-
"Content-Type": "application/json",
|
|
15092
|
-
"Authorization": `Bearer ${options.token}`
|
|
15093
|
-
},
|
|
15094
|
-
body: JSON.stringify({
|
|
15095
|
-
definition_slug: def.slug,
|
|
15096
|
-
initial_state: startState,
|
|
15097
|
-
state_data: stateData
|
|
15098
|
-
})
|
|
15099
|
-
});
|
|
15100
|
-
if (resp.ok) {
|
|
15101
|
-
defCreated++;
|
|
15102
|
-
} else {
|
|
15103
|
-
const errText = await resp.text().catch(() => resp.statusText);
|
|
15104
|
-
result.errors.push(`${def.slug}[${i}]: ${resp.status} ${errText}`);
|
|
15105
|
-
}
|
|
15106
|
-
} catch (e) {
|
|
15107
|
-
result.errors.push(`${def.slug}[${i}]: ${e instanceof Error ? e.message : String(e)}`);
|
|
15108
|
-
}
|
|
15109
|
-
}
|
|
15110
|
-
if (defCreated > 0) {
|
|
15111
|
-
result.definitions++;
|
|
15112
|
-
result.created += defCreated;
|
|
15113
|
-
console.log(` [seed] ${def.slug}: ${defCreated} instances created`);
|
|
15114
|
-
}
|
|
15115
|
-
}
|
|
15116
|
-
return result;
|
|
15117
|
-
}
|
|
15118
|
-
var import_fs7, import_glob4, FIRST_NAMES, LAST_NAMES, COMPANIES, LOREM_WORDS, DOMAINS, _counter;
|
|
15119
|
-
var init_seed = __esm({
|
|
15120
|
-
"src/cli/seed.ts"() {
|
|
15121
|
-
"use strict";
|
|
15122
|
-
import_fs7 = require("fs");
|
|
15123
|
-
import_glob4 = require("glob");
|
|
15124
|
-
FIRST_NAMES = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank", "Grace", "Henry"];
|
|
15125
|
-
LAST_NAMES = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis"];
|
|
15126
|
-
COMPANIES = ["Acme Corp", "TechStart Inc", "GlobalTrade Ltd", "DataFlow Systems", "CloudPeak"];
|
|
15127
|
-
LOREM_WORDS = ["lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit", "sed", "do", "eiusmod", "tempor"];
|
|
15128
|
-
DOMAINS = ["example.com", "test.org", "demo.io", "sample.net"];
|
|
15129
|
-
_counter = 0;
|
|
15130
|
-
}
|
|
15131
|
-
});
|
|
15132
|
-
|
|
15133
|
-
// src/dev-server.ts
|
|
15134
|
-
var dev_server_exports = {};
|
|
15135
|
-
__export(dev_server_exports, {
|
|
15136
|
-
createDevServer: () => createDevServer
|
|
15137
|
-
});
|
|
15138
|
-
function escapeHtml(s) {
|
|
15139
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
15140
|
-
}
|
|
15141
|
-
function renderErrorOverlay(errors) {
|
|
15142
|
-
const cards = errors.map((err) => {
|
|
15143
|
-
const loc = err.line ? `${err.file}:${err.line}${err.column ? ":" + err.column : ""}` : err.file;
|
|
15144
|
-
const snippet = err.snippet ? `<pre style="background:#1a1a2e;color:#e0e0e0;padding:12px 16px;border-radius:6px;overflow-x:auto;margin-top:8px;font-size:13px;line-height:1.5">${escapeHtml(err.snippet)}</pre>` : "";
|
|
15145
|
-
return `<div style="background:#2d1b1b;border:1px solid #5c2020;border-radius:8px;padding:16px 20px;margin-bottom:12px">
|
|
15146
|
-
<div style="color:#ff6b6b;font-family:monospace;font-size:13px;margin-bottom:6px">${escapeHtml(loc)}</div>
|
|
15147
|
-
<div style="color:#ffa0a0;font-size:15px;font-weight:500">${escapeHtml(err.message)}</div>${snippet}</div>`;
|
|
15148
|
-
}).join("\n");
|
|
15149
|
-
return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
15150
|
-
<title>Compile Error - MindMatrix Dev</title>
|
|
15151
|
-
<style>*{box-sizing:border-box;margin:0;padding:0}body{background:#1a1a2e;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;padding:40px 20px;min-height:100vh}</style></head>
|
|
15152
|
-
<body><div style="max-width:800px;margin:0 auto">
|
|
15153
|
-
<div style="display:flex;align-items:center;gap:12px;margin-bottom:24px">
|
|
15154
|
-
<div style="background:#5c2020;color:#ff6b6b;font-size:14px;font-weight:600;padding:4px 10px;border-radius:4px">COMPILE ERROR</div>
|
|
15155
|
-
<div style="color:#888;font-size:13px">${errors.length} error${errors.length !== 1 ? "s" : ""}</div></div>
|
|
15156
|
-
${cards}
|
|
15157
|
-
<div style="color:#666;font-size:12px;margin-top:24px;text-align:center">Fix the error and save -- the page will reload automatically.</div></div>
|
|
15158
|
-
<script>const ws=new WebSocket('ws://'+location.host+'/__mm_dev');ws.onmessage=e=>{const m=JSON.parse(e.data);if(m.type==='workflow:compiled'||m.type==='workflow:rebuild')location.reload()};ws.onclose=()=>setTimeout(()=>location.reload(),2000)</script>
|
|
15159
|
-
</body></html>`;
|
|
15160
|
-
}
|
|
15161
|
-
function errorOverlayMiddleware() {
|
|
15162
|
-
return (req, res, next) => {
|
|
15163
|
-
if (!currentErrors || !req.url) return next();
|
|
15164
|
-
const url = req.url;
|
|
15165
|
-
if (url.startsWith("/api") || url.startsWith("/health") || url.startsWith("/ws") || url.startsWith("/__mm_dev") || url.startsWith("/@") || url.startsWith("/node_modules")) return next();
|
|
15166
|
-
const accept = req.headers?.accept ?? "";
|
|
15167
|
-
if (!accept.includes("text/html")) return next();
|
|
15168
|
-
res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
|
|
15169
|
-
res.end(renderErrorOverlay(currentErrors));
|
|
15170
|
-
};
|
|
15171
|
-
}
|
|
15172
|
-
async function resolveDevToken(apiUrl, explicit) {
|
|
15173
|
-
if (explicit) return explicit;
|
|
15174
|
-
try {
|
|
15175
|
-
const { resolveToken: resolveToken2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15176
|
-
const s = resolveToken2(apiUrl);
|
|
15177
|
-
if (s) return s;
|
|
15178
|
-
} catch {
|
|
15179
|
-
}
|
|
15180
|
-
try {
|
|
15181
|
-
const resp = await fetch(`${apiUrl}/auth/login`, {
|
|
15182
|
-
method: "POST",
|
|
15183
|
-
headers: { "Content-Type": "application/json" },
|
|
15184
|
-
body: JSON.stringify({ email: "admin@mindmatrix.com", password: "Admin123!" })
|
|
15185
|
-
});
|
|
15186
|
-
if (resp.ok) {
|
|
15187
|
-
const data = await resp.json();
|
|
15188
|
-
const token = data.token ?? data.access_token;
|
|
15189
|
-
if (token) {
|
|
15190
|
-
try {
|
|
15191
|
-
const { saveCredentials: saveCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15192
|
-
saveCredentials2(apiUrl, token);
|
|
15193
|
-
} catch {
|
|
15194
|
-
}
|
|
15195
|
-
return token;
|
|
15196
|
-
}
|
|
15197
|
-
}
|
|
15198
|
-
} catch {
|
|
15199
|
-
}
|
|
15200
|
-
return process.env.MINDMATRIX_TOKEN;
|
|
15201
|
-
}
|
|
15202
|
-
async function checkBackendHealth(apiUrl) {
|
|
15203
|
-
try {
|
|
15204
|
-
const base = apiUrl.replace(/\/api\/v1\/?$/, "");
|
|
15205
|
-
const resp = await fetch(`${base}/health`, { signal: AbortSignal.timeout(5e3) });
|
|
15206
|
-
if (resp.ok) {
|
|
15207
|
-
const d = await resp.json();
|
|
15208
|
-
return { ok: true, version: d.version, db: d.database };
|
|
15209
|
-
}
|
|
15210
|
-
return { ok: resp.status < 500 };
|
|
15211
|
-
} catch {
|
|
15212
|
-
return { ok: false };
|
|
15213
|
-
}
|
|
15214
|
-
}
|
|
15215
|
-
async function initialBuildDeploy(src, outDir, mode, apiUrl, token) {
|
|
15216
|
-
console.log("[mm-dev] Compiling project...");
|
|
15217
|
-
const buildResult = await build({ src, outDir, mode, skipTypeCheck: true });
|
|
15218
|
-
if (buildResult.errors > 0) {
|
|
15219
|
-
currentErrors = buildResult.errorDetails.map((e) => ({ file: e.file, message: e.message, line: e.line }));
|
|
15220
|
-
console.error(`[mm-dev] Build failed with ${buildResult.errors} error(s) -- error overlay active`);
|
|
15221
|
-
return { buildResult, deployed: false, slug: void 0 };
|
|
15222
|
-
}
|
|
15223
|
-
currentErrors = null;
|
|
15224
|
-
if (buildResult.compiled === 0) return { buildResult, deployed: false, slug: void 0 };
|
|
15225
|
-
console.log(`[mm-dev] Compiled ${buildResult.compiled} definition(s)`);
|
|
15226
|
-
try {
|
|
15227
|
-
const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
|
|
15228
|
-
const result = await deploy2({ apiUrl, token, dir: outDir });
|
|
15229
|
-
const total = result.created.length + result.updated.length + result.versioned.length;
|
|
15230
|
-
if (total > 0) console.log(`[mm-dev] Deployed: ${result.created.length} created, ${result.updated.length} updated`);
|
|
15231
|
-
return { buildResult, deployed: true, slug: buildResult.definitions?.[0]?.slug };
|
|
15232
|
-
} catch (e) {
|
|
15233
|
-
console.warn(`[mm-dev] Deploy failed: ${e instanceof Error ? e.message : e}`);
|
|
15234
|
-
return { buildResult, deployed: false, slug: void 0 };
|
|
15235
|
-
}
|
|
15236
|
-
}
|
|
15237
|
-
function printBanner(o) {
|
|
15238
|
-
const l = "-".repeat(58);
|
|
15239
|
-
console.log(`
|
|
15240
|
-
${l}
|
|
15241
|
-
MindMatrix Dev Server
|
|
15242
|
-
${l}
|
|
15243
|
-
`);
|
|
15244
|
-
console.log(` Preview: http://localhost:${o.port}`);
|
|
15245
|
-
console.log(` API Proxy: /api/* -> ${o.apiUrl}`);
|
|
15246
|
-
console.log(` WebSocket: ws://localhost:${o.port}/__mm_dev`);
|
|
15247
|
-
console.log(` Watching: ${o.src} (${o.include.join(", ")})
|
|
15248
|
-
`);
|
|
15249
|
-
console.log(` Backend: ${o.health.ok ? "connected" : "unreachable"}${o.health.version ? ` (v${o.health.version})` : ""}`);
|
|
15250
|
-
if (o.health.db) console.log(` Database: ${o.health.db}`);
|
|
15251
|
-
console.log(` Auth: ${o.token ? "authenticated" : "no token"}`);
|
|
15252
|
-
if (o.compiled > 0) {
|
|
15253
|
-
console.log(` Blueprint: ${o.slug ?? "unknown"} (${o.compiled} defs)`);
|
|
15254
|
-
console.log(` Deploy: ${o.deployed ? "synced" : "pending"}`);
|
|
15255
|
-
}
|
|
15256
|
-
if (o.errors > 0) console.log(` Errors: ${o.errors} compile error(s) -- overlay active`);
|
|
15257
|
-
console.log(`
|
|
15258
|
-
${l}
|
|
15259
|
-
`);
|
|
15260
|
-
}
|
|
15261
|
-
function broadcast(clients, data) {
|
|
15262
|
-
const msg = JSON.stringify(data);
|
|
15263
|
-
for (const c of clients) {
|
|
15264
|
-
try {
|
|
15265
|
-
if (c.readyState === 1) c.send(msg);
|
|
15266
|
-
} catch {
|
|
15267
|
-
clients.delete(c);
|
|
15268
|
-
}
|
|
14156
|
+
import_fs6 = require("fs");
|
|
14157
|
+
import_path5 = require("path");
|
|
14158
|
+
init_babel();
|
|
15269
14159
|
}
|
|
15270
|
-
}
|
|
14160
|
+
});
|
|
14161
|
+
|
|
14162
|
+
// src/dev-server.ts
|
|
14163
|
+
var dev_server_exports = {};
|
|
14164
|
+
__export(dev_server_exports, {
|
|
14165
|
+
createDevServer: () => createDevServer
|
|
14166
|
+
});
|
|
15271
14167
|
async function createDevServer(options = {}) {
|
|
15272
14168
|
const {
|
|
15273
14169
|
port = 5199,
|
|
@@ -15276,87 +14172,44 @@ async function createDevServer(options = {}) {
|
|
|
15276
14172
|
include = ["**/*.workflow.tsx"],
|
|
15277
14173
|
outDir = "dist/workflows",
|
|
15278
14174
|
seed = false,
|
|
15279
|
-
apiUrl
|
|
15280
|
-
authToken
|
|
14175
|
+
apiUrl = "http://localhost:4200/api/v1",
|
|
14176
|
+
authToken = process.env.MINDMATRIX_TOKEN,
|
|
15281
14177
|
ws: enableWs = true,
|
|
15282
14178
|
open = false
|
|
15283
14179
|
} = options;
|
|
15284
14180
|
const clients = /* @__PURE__ */ new Set();
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
|
|
15289
|
-
|
|
15290
|
-
apiUrl
|
|
15291
|
-
|
|
15292
|
-
}
|
|
15293
|
-
|
|
15294
|
-
|
|
15295
|
-
if (remoteHealth.ok) {
|
|
15296
|
-
apiUrl = defaultRemote;
|
|
15297
|
-
} else {
|
|
15298
|
-
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
15299
|
-
if (localHealth.ok) {
|
|
15300
|
-
apiUrl = "http://localhost:4200/api/v1";
|
|
15301
|
-
} else {
|
|
15302
|
-
console.log("[mm-dev] No backend detected \u2014 starting local in-memory API server...");
|
|
15303
|
-
localServer = await startLocalServer({ port: 4200 });
|
|
15304
|
-
apiUrl = "http://localhost:4200/api/v1";
|
|
15305
|
-
isLocalMode = true;
|
|
15306
|
-
}
|
|
15307
|
-
}
|
|
15308
|
-
} else {
|
|
15309
|
-
apiUrl = rawApiUrl;
|
|
15310
|
-
}
|
|
15311
|
-
const token = isLocalMode ? "dev-token-local" : await resolveDevToken(apiUrl, explicitToken);
|
|
15312
|
-
const health = isLocalMode ? { ok: true, version: "local", db: "in-memory" } : await checkBackendHealth(apiUrl);
|
|
15313
|
-
let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
|
|
15314
|
-
if (token && health.ok) {
|
|
15315
|
-
const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
|
|
15316
|
-
initialCompiled = r.buildResult.compiled;
|
|
15317
|
-
initialDeployed = r.deployed;
|
|
15318
|
-
initialSlug = r.slug;
|
|
15319
|
-
initialErrors = r.buildResult.errors;
|
|
15320
|
-
}
|
|
15321
|
-
if (seed && token && initialDeployed) {
|
|
15322
|
-
try {
|
|
15323
|
-
const { seedInstances: seedInstances2 } = await Promise.resolve().then(() => (init_seed(), seed_exports));
|
|
15324
|
-
console.log("[mm-dev] Seeding sample instances...");
|
|
15325
|
-
const sr = await seedInstances2({ apiUrl, token, dir: outDir });
|
|
15326
|
-
console.log(`[mm-dev] Seeded ${sr.created} instance(s) across ${sr.definitions} definition(s)`);
|
|
15327
|
-
} catch (e) {
|
|
15328
|
-
console.warn(`[mm-dev] Seed failed: ${e instanceof Error ? e.message : e}`);
|
|
15329
|
-
}
|
|
15330
|
-
}
|
|
15331
|
-
const pluginOpts = { mode, include, outDir, seedOnCompile: seed, apiUrl, authToken: token };
|
|
15332
|
-
const proxyTarget = apiUrl.replace(/\/api\/v1\/?$/, "") || apiUrl;
|
|
15333
|
-
let deployInFlight = false;
|
|
15334
|
-
const compileDeployPlugin = {
|
|
15335
|
-
name: "mindmatrix-dev-compile-deploy",
|
|
14181
|
+
const pluginOptions = {
|
|
14182
|
+
mode,
|
|
14183
|
+
include,
|
|
14184
|
+
outDir,
|
|
14185
|
+
seedOnCompile: seed,
|
|
14186
|
+
apiUrl,
|
|
14187
|
+
authToken
|
|
14188
|
+
};
|
|
14189
|
+
const notifyPlugin = {
|
|
14190
|
+
name: "mindmatrix-dev-notify",
|
|
15336
14191
|
enforce: "post",
|
|
15337
|
-
|
|
15338
|
-
const
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
}
|
|
15348
|
-
|
|
15349
|
-
if (token && !deployInFlight) {
|
|
15350
|
-
deployInFlight = true;
|
|
14192
|
+
handleHotUpdate(ctx) {
|
|
14193
|
+
const isWorkflow = include.some((pattern) => {
|
|
14194
|
+
const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "<<GLOBSTAR>>").replace(/\*/g, "[^/]*").replace(/<<GLOBSTAR>>/g, ".*").replace(/\?/g, ".");
|
|
14195
|
+
return new RegExp(regex).test(ctx.file);
|
|
14196
|
+
});
|
|
14197
|
+
if (!isWorkflow) return;
|
|
14198
|
+
const message = JSON.stringify({
|
|
14199
|
+
type: "workflow:compiled",
|
|
14200
|
+
file: ctx.file,
|
|
14201
|
+
timestamp: ctx.timestamp
|
|
14202
|
+
});
|
|
14203
|
+
for (const client of clients) {
|
|
15351
14204
|
try {
|
|
15352
|
-
|
|
15353
|
-
|
|
14205
|
+
if (client.readyState === 1) {
|
|
14206
|
+
client.send(message);
|
|
14207
|
+
}
|
|
15354
14208
|
} catch {
|
|
15355
|
-
|
|
15356
|
-
deployInFlight = false;
|
|
14209
|
+
clients.delete(client);
|
|
15357
14210
|
}
|
|
15358
14211
|
}
|
|
15359
|
-
|
|
14212
|
+
console.log(`[mm-dev] Compiled ${ctx.file.split("/").pop()} \u2014 notified ${clients.size} client(s)`);
|
|
15360
14213
|
}
|
|
15361
14214
|
};
|
|
15362
14215
|
const viteConfig = {
|
|
@@ -15364,87 +14217,94 @@ async function createDevServer(options = {}) {
|
|
|
15364
14217
|
server: {
|
|
15365
14218
|
port,
|
|
15366
14219
|
open,
|
|
15367
|
-
host: true
|
|
15368
|
-
proxy: {
|
|
15369
|
-
"/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
|
|
15370
|
-
"/health": { target: proxyTarget, changeOrigin: true, secure: true },
|
|
15371
|
-
"/ws": { target: proxyTarget.replace(/^http/, "ws"), changeOrigin: true, ws: true }
|
|
15372
|
-
}
|
|
14220
|
+
host: true
|
|
15373
14221
|
},
|
|
15374
14222
|
plugins: [
|
|
15375
|
-
mindmatrixReact(
|
|
15376
|
-
|
|
15377
|
-
{ name: "mindmatrix-error-overlay", configureServer(server) {
|
|
15378
|
-
server.middlewares.use(errorOverlayMiddleware());
|
|
15379
|
-
} }
|
|
14223
|
+
mindmatrixReact(pluginOptions),
|
|
14224
|
+
notifyPlugin
|
|
15380
14225
|
],
|
|
15381
|
-
logLevel: "
|
|
14226
|
+
logLevel: "info"
|
|
15382
14227
|
};
|
|
15383
|
-
const { createServer
|
|
15384
|
-
const vite = await
|
|
14228
|
+
const { createServer } = await import("vite");
|
|
14229
|
+
const vite = await createServer(viteConfig);
|
|
15385
14230
|
await vite.listen();
|
|
15386
14231
|
const resolvedPort = vite.config.server.port ?? port;
|
|
15387
14232
|
if (enableWs && vite.httpServer) {
|
|
15388
14233
|
try {
|
|
15389
|
-
const
|
|
15390
|
-
const
|
|
15391
|
-
if (
|
|
15392
|
-
const wss = new
|
|
15393
|
-
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
|
|
14234
|
+
const wsModule = await Function('return import("ws")')();
|
|
14235
|
+
const WebSocketServer = wsModule.WebSocketServer ?? wsModule.default?.WebSocketServer;
|
|
14236
|
+
if (WebSocketServer) {
|
|
14237
|
+
const wss = new WebSocketServer({
|
|
14238
|
+
server: vite.httpServer,
|
|
14239
|
+
path: "/__mm_dev"
|
|
14240
|
+
});
|
|
14241
|
+
wss.on("connection", (socket) => {
|
|
14242
|
+
clients.add(socket);
|
|
14243
|
+
console.log(`[mm-dev] Editor connected (${clients.size} total)`);
|
|
14244
|
+
socket.on("close", () => {
|
|
14245
|
+
clients.delete(socket);
|
|
14246
|
+
console.log(`[mm-dev] Editor disconnected (${clients.size} total)`);
|
|
14247
|
+
});
|
|
14248
|
+
socket.send(JSON.stringify({
|
|
14249
|
+
type: "mm:connected",
|
|
14250
|
+
version: "0.1.0",
|
|
14251
|
+
capabilities: ["compile", "seed", "notify"]
|
|
14252
|
+
}));
|
|
15397
14253
|
});
|
|
15398
14254
|
}
|
|
15399
14255
|
} catch {
|
|
14256
|
+
console.warn("[mm-dev] ws package not available \u2014 WebSocket notifications disabled");
|
|
15400
14257
|
}
|
|
15401
14258
|
}
|
|
15402
|
-
|
|
14259
|
+
console.log(`
|
|
14260
|
+
[mm-dev] MindMatrix Dev Server running`);
|
|
14261
|
+
console.log(` Local: http://localhost:${resolvedPort}`);
|
|
14262
|
+
console.log(` WebSocket: ws://localhost:${resolvedPort}/__mm_dev`);
|
|
14263
|
+
console.log(` Watching: ${src} (${include.join(", ")})`);
|
|
14264
|
+
if (seed) {
|
|
14265
|
+
console.log(` Seeding: ${apiUrl}`);
|
|
14266
|
+
}
|
|
14267
|
+
console.log();
|
|
15403
14268
|
return {
|
|
15404
14269
|
vite,
|
|
15405
14270
|
port: resolvedPort,
|
|
15406
14271
|
clients,
|
|
15407
14272
|
async rebuild() {
|
|
15408
|
-
|
|
15409
|
-
|
|
15410
|
-
|
|
15411
|
-
|
|
15412
|
-
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
|
|
15416
|
-
|
|
15417
|
-
|
|
15418
|
-
|
|
14273
|
+
console.log("[mm-dev] Full rebuild triggered...");
|
|
14274
|
+
const result = await build({ src, outDir, mode });
|
|
14275
|
+
const message = JSON.stringify({
|
|
14276
|
+
type: "workflow:rebuild",
|
|
14277
|
+
compiled: result.compiled,
|
|
14278
|
+
errors: result.errors,
|
|
14279
|
+
timestamp: Date.now()
|
|
14280
|
+
});
|
|
14281
|
+
for (const client of clients) {
|
|
14282
|
+
try {
|
|
14283
|
+
if (client.readyState === 1) client.send(message);
|
|
14284
|
+
} catch {
|
|
14285
|
+
clients.delete(client);
|
|
15419
14286
|
}
|
|
15420
14287
|
}
|
|
15421
|
-
|
|
15422
|
-
return r;
|
|
14288
|
+
return result;
|
|
15423
14289
|
},
|
|
15424
14290
|
async close() {
|
|
15425
|
-
for (const
|
|
14291
|
+
for (const client of clients) {
|
|
15426
14292
|
try {
|
|
15427
|
-
|
|
14293
|
+
client.close();
|
|
15428
14294
|
} catch {
|
|
15429
14295
|
}
|
|
15430
14296
|
}
|
|
15431
14297
|
clients.clear();
|
|
15432
|
-
currentErrors = null;
|
|
15433
14298
|
await vite.close();
|
|
15434
|
-
|
|
15435
|
-
await localServer.close();
|
|
15436
|
-
}
|
|
14299
|
+
console.log("[mm-dev] Server stopped");
|
|
15437
14300
|
}
|
|
15438
14301
|
};
|
|
15439
14302
|
}
|
|
15440
|
-
var currentErrors;
|
|
15441
14303
|
var init_dev_server = __esm({
|
|
15442
14304
|
"src/dev-server.ts"() {
|
|
15443
14305
|
"use strict";
|
|
15444
14306
|
init_vite();
|
|
15445
14307
|
init_build();
|
|
15446
|
-
init_local_server();
|
|
15447
|
-
currentErrors = null;
|
|
15448
14308
|
}
|
|
15449
14309
|
});
|
|
15450
14310
|
|
|
@@ -15486,7 +14346,7 @@ function findConfigPath(startDir) {
|
|
|
15486
14346
|
while (true) {
|
|
15487
14347
|
for (const name of ["mmrc.config.ts", "mmrc.config.json"]) {
|
|
15488
14348
|
const candidate = (0, import_path6.join)(dir, name);
|
|
15489
|
-
if ((0,
|
|
14349
|
+
if ((0, import_fs7.existsSync)(candidate)) return candidate;
|
|
15490
14350
|
}
|
|
15491
14351
|
const parent = (0, import_path6.resolve)(dir, "..");
|
|
15492
14352
|
if (parent === dir || parent === root) break;
|
|
@@ -15495,7 +14355,7 @@ function findConfigPath(startDir) {
|
|
|
15495
14355
|
return null;
|
|
15496
14356
|
}
|
|
15497
14357
|
function loadConfigFromFile(configPath) {
|
|
15498
|
-
const content = (0,
|
|
14358
|
+
const content = (0, import_fs7.readFileSync)(configPath, "utf-8");
|
|
15499
14359
|
if (configPath.endsWith(".json")) {
|
|
15500
14360
|
try {
|
|
15501
14361
|
return JSON.parse(content);
|
|
@@ -15576,7 +14436,7 @@ const config = ${json};
|
|
|
15576
14436
|
|
|
15577
14437
|
export default config;
|
|
15578
14438
|
`;
|
|
15579
|
-
(0,
|
|
14439
|
+
(0, import_fs7.writeFileSync)(configPath, content, "utf-8");
|
|
15580
14440
|
}
|
|
15581
14441
|
function resolveTarget(targetName, config, fallbackApiUrl) {
|
|
15582
14442
|
if (!config || !config.environments) {
|
|
@@ -15638,11 +14498,11 @@ function loadMmrcConfig(dir) {
|
|
|
15638
14498
|
const partial = loadConfigFromFile(path);
|
|
15639
14499
|
return deepMerge(DEFAULT_CONFIG, partial);
|
|
15640
14500
|
}
|
|
15641
|
-
var
|
|
14501
|
+
var import_fs7, import_path6, DEFAULT_CONFIG;
|
|
15642
14502
|
var init_config = __esm({
|
|
15643
14503
|
"src/cli/config.ts"() {
|
|
15644
14504
|
"use strict";
|
|
15645
|
-
|
|
14505
|
+
import_fs7 = require("fs");
|
|
15646
14506
|
import_path6 = require("path");
|
|
15647
14507
|
DEFAULT_CONFIG = {
|
|
15648
14508
|
dev: {
|
|
@@ -15676,9 +14536,7 @@ var init_config = __esm({
|
|
|
15676
14536
|
// src/cli/init.ts
|
|
15677
14537
|
var init_exports = {};
|
|
15678
14538
|
__export(init_exports, {
|
|
15679
|
-
init: () => init
|
|
15680
|
-
isInsideGitRepo: () => isInsideGitRepo,
|
|
15681
|
-
scaffoldGit: () => scaffoldGit
|
|
14539
|
+
init: () => init
|
|
15682
14540
|
});
|
|
15683
14541
|
function toTitleCase(slug) {
|
|
15684
14542
|
return slug.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -15689,7 +14547,7 @@ function toPascalCase2(slug) {
|
|
|
15689
14547
|
function generatePackageJson2(name) {
|
|
15690
14548
|
return JSON.stringify(
|
|
15691
14549
|
{
|
|
15692
|
-
name: `@
|
|
14550
|
+
name: `@mindmatrix/blueprint-${name}`,
|
|
15693
14551
|
version: "0.1.0",
|
|
15694
14552
|
private: true,
|
|
15695
14553
|
type: "module",
|
|
@@ -15997,38 +14855,6 @@ export default function ${pascal}Home() {
|
|
|
15997
14855
|
}
|
|
15998
14856
|
`;
|
|
15999
14857
|
}
|
|
16000
|
-
function generateGitignore() {
|
|
16001
|
-
return `node_modules
|
|
16002
|
-
dist
|
|
16003
|
-
dev.db
|
|
16004
|
-
.env
|
|
16005
|
-
.env.local
|
|
16006
|
-
.env.*.local
|
|
16007
|
-
*.log
|
|
16008
|
-
.DS_Store
|
|
16009
|
-
`;
|
|
16010
|
-
}
|
|
16011
|
-
function isInsideGitRepo(dir) {
|
|
16012
|
-
try {
|
|
16013
|
-
(0, import_child_process2.execSync)("git rev-parse --git-dir", { cwd: dir, stdio: "pipe" });
|
|
16014
|
-
return true;
|
|
16015
|
-
} catch {
|
|
16016
|
-
return false;
|
|
16017
|
-
}
|
|
16018
|
-
}
|
|
16019
|
-
function scaffoldGit(dir) {
|
|
16020
|
-
if (isInsideGitRepo(dir)) {
|
|
16021
|
-
return "Skipped git init (inside existing repo)";
|
|
16022
|
-
}
|
|
16023
|
-
try {
|
|
16024
|
-
(0, import_child_process2.execSync)("git init", { cwd: dir, stdio: "pipe" });
|
|
16025
|
-
(0, import_child_process2.execSync)("git add -A", { cwd: dir, stdio: "pipe" });
|
|
16026
|
-
(0, import_child_process2.execSync)('git commit -m "Initial commit from mmrc init"', { cwd: dir, stdio: "pipe" });
|
|
16027
|
-
return "Initialized git repository";
|
|
16028
|
-
} catch (e) {
|
|
16029
|
-
return `Git init failed: ${e.message}`;
|
|
16030
|
-
}
|
|
16031
|
-
}
|
|
16032
14858
|
async function init(options) {
|
|
16033
14859
|
const { name } = options;
|
|
16034
14860
|
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
@@ -16036,34 +14862,31 @@ async function init(options) {
|
|
|
16036
14862
|
process.exit(1);
|
|
16037
14863
|
}
|
|
16038
14864
|
const cwd = process.cwd();
|
|
16039
|
-
const packagesDir = (0,
|
|
14865
|
+
const packagesDir = (0, import_fs8.existsSync)((0, import_path7.join)(cwd, "packages")) ? (0, import_path7.join)(cwd, "packages") : cwd;
|
|
16040
14866
|
const blueprintDir = (0, import_path7.join)(packagesDir, `blueprint-${name}`);
|
|
16041
|
-
if ((0,
|
|
14867
|
+
if ((0, import_fs8.existsSync)(blueprintDir)) {
|
|
16042
14868
|
console.error(`[mmrc] Error: Directory already exists: ${blueprintDir}`);
|
|
16043
14869
|
process.exit(1);
|
|
16044
14870
|
}
|
|
16045
14871
|
console.log(`[mmrc] Creating blueprint: ${name}
|
|
16046
14872
|
`);
|
|
16047
|
-
(0,
|
|
16048
|
-
(0,
|
|
14873
|
+
(0, import_fs8.mkdirSync)((0, import_path7.join)(blueprintDir, "models"), { recursive: true });
|
|
14874
|
+
(0, import_fs8.mkdirSync)((0, import_path7.join)(blueprintDir, "app"), { recursive: true });
|
|
16049
14875
|
const { generateMmrcConfig: generateMmrcConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
16050
14876
|
const files = [
|
|
16051
14877
|
["package.json", generatePackageJson2(name)],
|
|
16052
14878
|
["tsconfig.json", generateTsconfig()],
|
|
16053
14879
|
["mm.config.ts", generateMmConfig2(name, options)],
|
|
16054
14880
|
["mmrc.config.ts", generateMmrcConfig2()],
|
|
16055
|
-
[".gitignore", generateGitignore()],
|
|
16056
14881
|
["models/item.ts", generateModel(name)],
|
|
16057
14882
|
["app/layout.tsx", generateLayout(name)],
|
|
16058
14883
|
["app/page.tsx", generatePage(name)]
|
|
16059
14884
|
];
|
|
16060
14885
|
for (const [relPath, content] of files) {
|
|
16061
14886
|
const fullPath = (0, import_path7.join)(blueprintDir, relPath);
|
|
16062
|
-
(0,
|
|
14887
|
+
(0, import_fs8.writeFileSync)(fullPath, content, "utf-8");
|
|
16063
14888
|
console.log(` + ${relPath}`);
|
|
16064
14889
|
}
|
|
16065
|
-
const gitMessage = scaffoldGit(blueprintDir);
|
|
16066
|
-
console.log(` ${gitMessage}`);
|
|
16067
14890
|
const title = toTitleCase(name);
|
|
16068
14891
|
console.log(`
|
|
16069
14892
|
[mmrc] Blueprint "${title}" created at:
|
|
@@ -16076,13 +14899,12 @@ Next steps:
|
|
|
16076
14899
|
4. mmrc deploy --build # Build + deploy to backend
|
|
16077
14900
|
`);
|
|
16078
14901
|
}
|
|
16079
|
-
var
|
|
14902
|
+
var import_fs8, import_path7;
|
|
16080
14903
|
var init_init = __esm({
|
|
16081
14904
|
"src/cli/init.ts"() {
|
|
16082
14905
|
"use strict";
|
|
16083
|
-
|
|
14906
|
+
import_fs8 = require("fs");
|
|
16084
14907
|
import_path7 = require("path");
|
|
16085
|
-
import_child_process2 = require("child_process");
|
|
16086
14908
|
}
|
|
16087
14909
|
});
|
|
16088
14910
|
|
|
@@ -17781,7 +16603,7 @@ function generateTestFile(ir) {
|
|
|
17781
16603
|
lines.push(`import { analyzeReachability } from '../verify/reachability';`);
|
|
17782
16604
|
lines.push(`import { analyzeSafety } from '../verify/safety';`);
|
|
17783
16605
|
lines.push(`import { analyzeLiveness } from '../verify/liveness';`);
|
|
17784
|
-
lines.push(`import type { IRWorkflowDefinition } from '@
|
|
16606
|
+
lines.push(`import type { IRWorkflowDefinition } from '@mindmatrix/player-core';`);
|
|
17785
16607
|
lines.push("");
|
|
17786
16608
|
lines.push(`const ir: IRWorkflowDefinition = ${JSON.stringify(ir, null, 2)} as unknown as IRWorkflowDefinition;`);
|
|
17787
16609
|
lines.push("");
|
|
@@ -17862,7 +16684,7 @@ __export(verify_exports, {
|
|
|
17862
16684
|
verifyCommand: () => verifyCommand
|
|
17863
16685
|
});
|
|
17864
16686
|
function compileToIR(filePath) {
|
|
17865
|
-
const code = (0,
|
|
16687
|
+
const code = (0, import_fs9.readFileSync)(filePath, "utf-8");
|
|
17866
16688
|
const result = (0, import_core6.transformSync)(code, {
|
|
17867
16689
|
filename: filePath,
|
|
17868
16690
|
plugins: [[babelPlugin, { mode: "strict" }]],
|
|
@@ -17879,10 +16701,10 @@ function compileToIR(filePath) {
|
|
|
17879
16701
|
}
|
|
17880
16702
|
async function resolveFiles(target) {
|
|
17881
16703
|
const resolved = (0, import_path8.resolve)(target);
|
|
17882
|
-
if (!(0,
|
|
16704
|
+
if (!(0, import_fs9.existsSync)(resolved)) {
|
|
17883
16705
|
throw new Error(`Path not found: ${resolved}`);
|
|
17884
16706
|
}
|
|
17885
|
-
const stat = (0,
|
|
16707
|
+
const stat = (0, import_fs9.statSync)(resolved);
|
|
17886
16708
|
if (stat.isFile()) {
|
|
17887
16709
|
const ext = (0, import_path8.extname)(resolved);
|
|
17888
16710
|
if (![".ts", ".tsx", ".js", ".jsx"].includes(ext)) {
|
|
@@ -17891,7 +16713,7 @@ async function resolveFiles(target) {
|
|
|
17891
16713
|
return [resolved];
|
|
17892
16714
|
}
|
|
17893
16715
|
if (stat.isDirectory()) {
|
|
17894
|
-
const files = await (0,
|
|
16716
|
+
const files = await (0, import_glob4.glob)(`${resolved}/**/*.{ts,tsx}`, {
|
|
17895
16717
|
ignore: ["**/node_modules/**", "**/dist/**", "**/*.test.*", "**/*.d.ts"]
|
|
17896
16718
|
});
|
|
17897
16719
|
if (files.length === 0) {
|
|
@@ -17966,13 +16788,13 @@ ${"=".repeat(50)}`);
|
|
|
17966
16788
|
}
|
|
17967
16789
|
return { success, filesProcessed, filesFailed, results };
|
|
17968
16790
|
}
|
|
17969
|
-
var
|
|
16791
|
+
var import_fs9, import_path8, import_glob4, import_core6;
|
|
17970
16792
|
var init_verify = __esm({
|
|
17971
16793
|
"src/cli/verify.ts"() {
|
|
17972
16794
|
"use strict";
|
|
17973
|
-
|
|
16795
|
+
import_fs9 = require("fs");
|
|
17974
16796
|
import_path8 = require("path");
|
|
17975
|
-
|
|
16797
|
+
import_glob4 = require("glob");
|
|
17976
16798
|
import_core6 = require("@babel/core");
|
|
17977
16799
|
init_babel();
|
|
17978
16800
|
init_cli();
|
|
@@ -17995,12 +16817,12 @@ async function pull(options) {
|
|
|
17995
16817
|
console.log(` Found: ${ir.name || ir.slug} (${ir.category || "workflow"}, v${ir.version || "1.0.0"})`);
|
|
17996
16818
|
console.log(` Fields: ${ir.fields?.length ?? 0}, States: ${ir.states?.length ?? 0}, Transitions: ${ir.transitions?.length ?? 0}`);
|
|
17997
16819
|
const result = decompileProjectEnhanced(ir);
|
|
17998
|
-
(0,
|
|
16820
|
+
(0, import_fs10.mkdirSync)(outDir, { recursive: true });
|
|
17999
16821
|
const filesWritten = [];
|
|
18000
16822
|
for (const file2 of result.files) {
|
|
18001
16823
|
const filePath = (0, import_path9.join)(outDir, file2.path);
|
|
18002
|
-
(0,
|
|
18003
|
-
(0,
|
|
16824
|
+
(0, import_fs10.mkdirSync)((0, import_path9.dirname)(filePath), { recursive: true });
|
|
16825
|
+
(0, import_fs10.writeFileSync)(filePath, file2.content, "utf-8");
|
|
18004
16826
|
filesWritten.push(file2.path);
|
|
18005
16827
|
console.log(` + ${file2.path}`);
|
|
18006
16828
|
}
|
|
@@ -18048,611 +16870,688 @@ async function tryFetch(url, token) {
|
|
|
18048
16870
|
if (data.length === 0) return null;
|
|
18049
16871
|
return normalizeApiResponse(data[0]);
|
|
18050
16872
|
}
|
|
18051
|
-
const items = data.items ?? data.data;
|
|
18052
|
-
if (items && Array.isArray(items)) {
|
|
18053
|
-
if (items.length === 0) return null;
|
|
18054
|
-
return normalizeApiResponse(items[0]);
|
|
16873
|
+
const items = data.items ?? data.data;
|
|
16874
|
+
if (items && Array.isArray(items)) {
|
|
16875
|
+
if (items.length === 0) return null;
|
|
16876
|
+
return normalizeApiResponse(items[0]);
|
|
16877
|
+
}
|
|
16878
|
+
return normalizeApiResponse(data);
|
|
16879
|
+
} catch {
|
|
16880
|
+
return null;
|
|
16881
|
+
}
|
|
16882
|
+
}
|
|
16883
|
+
function normalizeApiResponse(def) {
|
|
16884
|
+
const ir = {
|
|
16885
|
+
slug: def.slug,
|
|
16886
|
+
name: def.name,
|
|
16887
|
+
version: def.version || "1.0.0",
|
|
16888
|
+
description: def.description || "",
|
|
16889
|
+
category: def.category || "workflow",
|
|
16890
|
+
fields: def.fields || [],
|
|
16891
|
+
states: def.states || [],
|
|
16892
|
+
transitions: def.transitions || [],
|
|
16893
|
+
roles: def.roles || [],
|
|
16894
|
+
on_event: def.on_event || [],
|
|
16895
|
+
metadata: {
|
|
16896
|
+
...def.metadata || {}
|
|
16897
|
+
}
|
|
16898
|
+
};
|
|
16899
|
+
const experience = def.view || def.experience || def.metadata?.experience;
|
|
16900
|
+
if (experience) {
|
|
16901
|
+
ir.experience = experience;
|
|
16902
|
+
ir.metadata.experience = experience;
|
|
16903
|
+
ir.view = experience;
|
|
16904
|
+
}
|
|
16905
|
+
return ir;
|
|
16906
|
+
}
|
|
16907
|
+
var import_fs10, import_path9;
|
|
16908
|
+
var init_pull = __esm({
|
|
16909
|
+
"src/cli/pull.ts"() {
|
|
16910
|
+
"use strict";
|
|
16911
|
+
import_fs10 = require("fs");
|
|
16912
|
+
import_path9 = require("path");
|
|
16913
|
+
init_project_decompiler();
|
|
16914
|
+
}
|
|
16915
|
+
});
|
|
16916
|
+
|
|
16917
|
+
// src/cli/index.ts
|
|
16918
|
+
init_build();
|
|
16919
|
+
|
|
16920
|
+
// src/cli/test.ts
|
|
16921
|
+
var import_glob2 = require("glob");
|
|
16922
|
+
var import_fs3 = require("fs");
|
|
16923
|
+
var import_path2 = require("path");
|
|
16924
|
+
async function test(options = {}) {
|
|
16925
|
+
const srcDir = options.src ?? ".";
|
|
16926
|
+
const label = "[mindmatrix-react]";
|
|
16927
|
+
console.log(`${label} Round-trip fidelity test
|
|
16928
|
+
`);
|
|
16929
|
+
const configPath = (0, import_path2.resolve)(srcDir, "mm.config.ts");
|
|
16930
|
+
const isProject = (0, import_fs3.existsSync)(configPath);
|
|
16931
|
+
if (!isProject) {
|
|
16932
|
+
console.error(`${label} Error: No mm.config.ts found in ${srcDir}`);
|
|
16933
|
+
console.error(` Round-trip test requires a project with mm.config.ts`);
|
|
16934
|
+
process.exit(1);
|
|
16935
|
+
}
|
|
16936
|
+
const allFiles = await (0, import_glob2.glob)(`${srcDir}/**/*.{ts,tsx}`, {
|
|
16937
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/*.test.*"]
|
|
16938
|
+
});
|
|
16939
|
+
if (allFiles.length === 0) {
|
|
16940
|
+
console.error(`${label} Error: No source files found in ${srcDir}`);
|
|
16941
|
+
process.exit(1);
|
|
16942
|
+
}
|
|
16943
|
+
const fileMap = {};
|
|
16944
|
+
for (const f of allFiles) {
|
|
16945
|
+
const rel = f.startsWith(srcDir + "/") ? f.slice(srcDir.length + 1) : f;
|
|
16946
|
+
fileMap[rel] = (0, import_fs3.readFileSync)(f, "utf-8");
|
|
16947
|
+
}
|
|
16948
|
+
const { compileProject: compileProject2 } = await Promise.resolve().then(() => (init_project_compiler(), project_compiler_exports));
|
|
16949
|
+
const { decompileProjectEnhanced: decompileProjectEnhanced2 } = await Promise.resolve().then(() => (init_project_decompiler(), project_decompiler_exports));
|
|
16950
|
+
process.stdout.write(` Compiling project...`);
|
|
16951
|
+
const t0 = performance.now();
|
|
16952
|
+
let ir1;
|
|
16953
|
+
let childDefs1;
|
|
16954
|
+
try {
|
|
16955
|
+
const result = compileProject2(fileMap);
|
|
16956
|
+
ir1 = result.ir;
|
|
16957
|
+
childDefs1 = result.childDefinitions;
|
|
16958
|
+
const compileErrors = result.errors.filter((e) => e.severity === "error");
|
|
16959
|
+
if (compileErrors.length > 0) {
|
|
16960
|
+
console.log(` FAIL`);
|
|
16961
|
+
for (const err of compileErrors) {
|
|
16962
|
+
console.error(` ${err.file}: ${err.message}`);
|
|
16963
|
+
}
|
|
16964
|
+
process.exit(1);
|
|
16965
|
+
}
|
|
16966
|
+
} catch (err) {
|
|
16967
|
+
console.log(` FAIL`);
|
|
16968
|
+
console.error(` ${err.message}`);
|
|
16969
|
+
process.exit(1);
|
|
16970
|
+
}
|
|
16971
|
+
const t1 = performance.now();
|
|
16972
|
+
console.log(` \u2713 (${((t1 - t0) / 1e3).toFixed(1)}s)`);
|
|
16973
|
+
process.stdout.write(` Decompiling IR...`);
|
|
16974
|
+
const t27 = performance.now();
|
|
16975
|
+
let decompFiles;
|
|
16976
|
+
try {
|
|
16977
|
+
const decompInput = {
|
|
16978
|
+
...ir1,
|
|
16979
|
+
childDefinitions: childDefs1,
|
|
16980
|
+
experience: ir1.experience
|
|
16981
|
+
};
|
|
16982
|
+
const decompResult = decompileProjectEnhanced2(decompInput);
|
|
16983
|
+
decompFiles = {};
|
|
16984
|
+
for (const file2 of decompResult.files) {
|
|
16985
|
+
decompFiles[file2.path] = file2.content;
|
|
16986
|
+
}
|
|
16987
|
+
} catch (err) {
|
|
16988
|
+
console.log(` FAIL`);
|
|
16989
|
+
console.error(` ${err.message}`);
|
|
16990
|
+
process.exit(1);
|
|
16991
|
+
}
|
|
16992
|
+
const t32 = performance.now();
|
|
16993
|
+
console.log(` \u2713 (${((t32 - t27) / 1e3).toFixed(1)}s)`);
|
|
16994
|
+
process.stdout.write(` Recompiling...`);
|
|
16995
|
+
const t42 = performance.now();
|
|
16996
|
+
let ir2;
|
|
16997
|
+
try {
|
|
16998
|
+
const result2 = compileProject2(decompFiles);
|
|
16999
|
+
ir2 = result2.ir;
|
|
17000
|
+
const recompileErrors = result2.errors.filter((e) => e.severity === "error");
|
|
17001
|
+
if (recompileErrors.length > 0) {
|
|
17002
|
+
console.log(` FAIL`);
|
|
17003
|
+
for (const err of recompileErrors) {
|
|
17004
|
+
console.error(` ${err.file}: ${err.message}`);
|
|
17005
|
+
}
|
|
17006
|
+
process.exit(1);
|
|
17007
|
+
}
|
|
17008
|
+
} catch (err) {
|
|
17009
|
+
console.log(` FAIL`);
|
|
17010
|
+
console.error(` ${err.message}`);
|
|
17011
|
+
process.exit(1);
|
|
17012
|
+
}
|
|
17013
|
+
const t52 = performance.now();
|
|
17014
|
+
console.log(` \u2713 (${((t52 - t42) / 1e3).toFixed(1)}s)`);
|
|
17015
|
+
process.stdout.write(` Comparing IR...
|
|
17016
|
+
`);
|
|
17017
|
+
const t62 = performance.now();
|
|
17018
|
+
const diffs = [];
|
|
17019
|
+
if (ir1.slug !== ir2.slug) {
|
|
17020
|
+
diffs.push({ path: "slug", expected: ir1.slug, actual: ir2.slug, severity: "error" });
|
|
17021
|
+
}
|
|
17022
|
+
if (ir1.version !== ir2.version) {
|
|
17023
|
+
diffs.push({ path: "version", expected: ir1.version, actual: ir2.version, severity: "error" });
|
|
17024
|
+
}
|
|
17025
|
+
if (JSON.stringify(ir1.category) !== JSON.stringify(ir2.category)) {
|
|
17026
|
+
diffs.push({ path: "category", expected: ir1.category, actual: ir2.category, severity: "error" });
|
|
17027
|
+
}
|
|
17028
|
+
const { fieldMatch, fieldCount } = compareFields(diffs, ir1.fields, ir2.fields);
|
|
17029
|
+
const fieldOk = diffs.filter((d) => d.path.startsWith("fields") && d.severity === "error").length === 0;
|
|
17030
|
+
console.log(` Fields: ${fieldMatch}/${fieldCount} match ${fieldOk ? "\u2713" : "FAIL"}`);
|
|
17031
|
+
const { stateMatch, stateCount } = compareStates(diffs, ir1.states, ir2.states);
|
|
17032
|
+
const stateOk = diffs.filter((d) => d.path.startsWith("states") && d.severity === "error").length === 0;
|
|
17033
|
+
console.log(` States: ${stateMatch}/${stateCount} match ${stateOk ? "\u2713" : "FAIL"}`);
|
|
17034
|
+
const { transitionMatch, transitionCount } = compareTransitions(diffs, ir1.transitions, ir2.transitions);
|
|
17035
|
+
const transitionOk = diffs.filter((d) => d.path.startsWith("transitions") && d.severity === "error").length === 0;
|
|
17036
|
+
console.log(` Transitions: ${transitionMatch}/${transitionCount} match ${transitionOk ? "\u2713" : "FAIL"}`);
|
|
17037
|
+
const t72 = performance.now();
|
|
17038
|
+
const errors = diffs.filter((d) => d.severity === "error");
|
|
17039
|
+
const success = errors.length === 0;
|
|
17040
|
+
if (success) {
|
|
17041
|
+
console.log(` PASS \u2014 round-trip produces identical IR`);
|
|
17042
|
+
} else {
|
|
17043
|
+
console.log(` FAIL \u2014 ${errors.length} difference(s) found:`);
|
|
17044
|
+
for (const diff of errors) {
|
|
17045
|
+
console.log(` ${diff.path}: expected ${JSON.stringify(diff.expected)}, got ${JSON.stringify(diff.actual)}`);
|
|
17046
|
+
}
|
|
17047
|
+
}
|
|
17048
|
+
return {
|
|
17049
|
+
success,
|
|
17050
|
+
fieldCount,
|
|
17051
|
+
fieldMatch,
|
|
17052
|
+
stateCount,
|
|
17053
|
+
stateMatch,
|
|
17054
|
+
transitionCount,
|
|
17055
|
+
transitionMatch,
|
|
17056
|
+
diffs,
|
|
17057
|
+
timings: {
|
|
17058
|
+
compile: t1 - t0,
|
|
17059
|
+
decompile: t32 - t27,
|
|
17060
|
+
recompile: t52 - t42,
|
|
17061
|
+
compare: t72 - t62
|
|
17062
|
+
}
|
|
17063
|
+
};
|
|
17064
|
+
}
|
|
17065
|
+
function compareFields(diffs, fields1, fields2) {
|
|
17066
|
+
const map1 = new Map(fields1.map((f) => [f.name, f]));
|
|
17067
|
+
const map2 = new Map(fields2.map((f) => [f.name, f]));
|
|
17068
|
+
const fieldCount = map1.size;
|
|
17069
|
+
let fieldMatch = 0;
|
|
17070
|
+
for (const [name, f1] of map1) {
|
|
17071
|
+
const f2 = map2.get(name);
|
|
17072
|
+
if (!f2) {
|
|
17073
|
+
diffs.push({ path: `fields[${name}]`, expected: name, actual: void 0, severity: "error" });
|
|
17074
|
+
continue;
|
|
17075
|
+
}
|
|
17076
|
+
if (f1.type !== f2.type && !isCompatibleType(f1.type, f2.type)) {
|
|
17077
|
+
diffs.push({ path: `fields[${name}].type`, expected: f1.type, actual: f2.type, severity: "warning" });
|
|
18055
17078
|
}
|
|
18056
|
-
|
|
18057
|
-
} catch {
|
|
18058
|
-
return null;
|
|
17079
|
+
fieldMatch++;
|
|
18059
17080
|
}
|
|
18060
|
-
|
|
18061
|
-
|
|
18062
|
-
|
|
18063
|
-
slug: def.slug,
|
|
18064
|
-
name: def.name,
|
|
18065
|
-
version: def.version || "1.0.0",
|
|
18066
|
-
description: def.description || "",
|
|
18067
|
-
category: def.category || "workflow",
|
|
18068
|
-
fields: def.fields || [],
|
|
18069
|
-
states: def.states || [],
|
|
18070
|
-
transitions: def.transitions || [],
|
|
18071
|
-
roles: def.roles || [],
|
|
18072
|
-
on_event: def.on_event || [],
|
|
18073
|
-
metadata: {
|
|
18074
|
-
...def.metadata || {}
|
|
17081
|
+
for (const [name] of map2) {
|
|
17082
|
+
if (!map1.has(name)) {
|
|
17083
|
+
diffs.push({ path: `fields[${name}]`, expected: void 0, actual: name, severity: "warning" });
|
|
18075
17084
|
}
|
|
18076
|
-
};
|
|
18077
|
-
const experience = def.view || def.experience || def.metadata?.experience;
|
|
18078
|
-
if (experience) {
|
|
18079
|
-
ir.experience = experience;
|
|
18080
|
-
ir.metadata.experience = experience;
|
|
18081
|
-
ir.view = experience;
|
|
18082
17085
|
}
|
|
18083
|
-
return
|
|
17086
|
+
return { fieldMatch, fieldCount };
|
|
18084
17087
|
}
|
|
18085
|
-
|
|
18086
|
-
|
|
18087
|
-
"
|
|
18088
|
-
|
|
18089
|
-
|
|
18090
|
-
|
|
18091
|
-
init_project_decompiler();
|
|
18092
|
-
}
|
|
18093
|
-
});
|
|
18094
|
-
|
|
18095
|
-
// src/cli/server.ts
|
|
18096
|
-
var server_exports = {};
|
|
18097
|
-
__export(server_exports, {
|
|
18098
|
-
findServerBinary: () => findServerBinary,
|
|
18099
|
-
generateServerToml: () => generateServerToml,
|
|
18100
|
-
serverConfig: () => serverConfig,
|
|
18101
|
-
serverInit: () => serverInit,
|
|
18102
|
-
serverMigrate: () => serverMigrate,
|
|
18103
|
-
serverStart: () => serverStart,
|
|
18104
|
-
serverStatus: () => serverStatus
|
|
18105
|
-
});
|
|
18106
|
-
function findServerBinary(explicitPath) {
|
|
18107
|
-
if (explicitPath) {
|
|
18108
|
-
return (0, import_fs12.existsSync)(explicitPath) ? explicitPath : null;
|
|
18109
|
-
}
|
|
18110
|
-
for (const rel of BINARY_SEARCH_PATHS) {
|
|
18111
|
-
const abs = (0, import_path10.resolve)(process.cwd(), rel);
|
|
18112
|
-
if ((0, import_fs12.existsSync)(abs)) return abs;
|
|
18113
|
-
}
|
|
18114
|
-
try {
|
|
18115
|
-
const { execSync: execSync3 } = require("child_process");
|
|
18116
|
-
const result = execSync3("which mm-server 2>/dev/null || which mm-api 2>/dev/null", {
|
|
18117
|
-
encoding: "utf-8",
|
|
18118
|
-
timeout: 5e3
|
|
18119
|
-
}).trim();
|
|
18120
|
-
if (result) return result;
|
|
18121
|
-
} catch {
|
|
18122
|
-
}
|
|
18123
|
-
return null;
|
|
17088
|
+
function isCompatibleType(t1, t27) {
|
|
17089
|
+
const stringTypes = /* @__PURE__ */ new Set(["text", "rich_text", "email", "url", "phone", "color", "select"]);
|
|
17090
|
+
const numberTypes = /* @__PURE__ */ new Set(["number", "currency", "percentage", "rating", "duration"]);
|
|
17091
|
+
if (stringTypes.has(t1) && stringTypes.has(t27)) return true;
|
|
17092
|
+
if (numberTypes.has(t1) && numberTypes.has(t27)) return true;
|
|
17093
|
+
return false;
|
|
18124
17094
|
}
|
|
18125
|
-
|
|
18126
|
-
const
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
|
|
18130
|
-
|
|
18131
|
-
|
|
18132
|
-
|
|
18133
|
-
|
|
18134
|
-
|
|
18135
|
-
|
|
18136
|
-
|
|
18137
|
-
|
|
18138
|
-
|
|
18139
|
-
|
|
18140
|
-
|
|
18141
|
-
|
|
18142
|
-
|
|
18143
|
-
|
|
17095
|
+
function compareStates(diffs, states1, states2) {
|
|
17096
|
+
const map1 = new Map(states1.map((s) => [s.name, s]));
|
|
17097
|
+
const map2 = new Map(states2.map((s) => [s.name, s]));
|
|
17098
|
+
const stateCount = map1.size;
|
|
17099
|
+
let stateMatch = 0;
|
|
17100
|
+
for (const [name, s1] of map1) {
|
|
17101
|
+
const s2 = map2.get(name);
|
|
17102
|
+
const hasActions = s1.on_enter.length > 0 || s1.on_exit.length > 0 || s1.during.length > 0;
|
|
17103
|
+
if (!s2 && hasActions) {
|
|
17104
|
+
diffs.push({ path: `states[${name}]`, expected: name, actual: void 0, severity: "error" });
|
|
17105
|
+
continue;
|
|
17106
|
+
}
|
|
17107
|
+
if (!s2) {
|
|
17108
|
+
stateMatch++;
|
|
17109
|
+
continue;
|
|
17110
|
+
}
|
|
17111
|
+
let matched = true;
|
|
17112
|
+
if (s1.on_enter.length !== s2.on_enter.length) {
|
|
17113
|
+
diffs.push({
|
|
17114
|
+
path: `states[${name}].on_enter.length`,
|
|
17115
|
+
expected: s1.on_enter.length,
|
|
17116
|
+
actual: s2.on_enter.length,
|
|
17117
|
+
severity: s1.on_enter.length > 0 ? "error" : "warning"
|
|
17118
|
+
});
|
|
17119
|
+
if (s1.on_enter.length > 0) matched = false;
|
|
17120
|
+
}
|
|
17121
|
+
if (s1.on_exit.length !== s2.on_exit.length) {
|
|
17122
|
+
diffs.push({
|
|
17123
|
+
path: `states[${name}].on_exit.length`,
|
|
17124
|
+
expected: s1.on_exit.length,
|
|
17125
|
+
actual: s2.on_exit.length,
|
|
17126
|
+
severity: s1.on_exit.length > 0 ? "error" : "warning"
|
|
17127
|
+
});
|
|
17128
|
+
if (s1.on_exit.length > 0) matched = false;
|
|
17129
|
+
}
|
|
17130
|
+
if (s1.during.length !== s2.during.length) {
|
|
17131
|
+
diffs.push({
|
|
17132
|
+
path: `states[${name}].during.length`,
|
|
17133
|
+
expected: s1.during.length,
|
|
17134
|
+
actual: s2.during.length,
|
|
17135
|
+
severity: s1.during.length > 0 ? "error" : "warning"
|
|
17136
|
+
});
|
|
17137
|
+
if (s1.during.length > 0) matched = false;
|
|
17138
|
+
}
|
|
17139
|
+
if (matched) stateMatch++;
|
|
18144
17140
|
}
|
|
18145
|
-
|
|
18146
|
-
const args2 = [];
|
|
18147
|
-
const configPath = options.config ?? findConfigFile();
|
|
18148
|
-
if (configPath) {
|
|
18149
|
-
args2.push("--config", configPath);
|
|
18150
|
-
console.log(`[mmrc] Config: ${configPath}`);
|
|
18151
|
-
}
|
|
18152
|
-
if (options.port) {
|
|
18153
|
-
process.env.PORT = String(options.port);
|
|
18154
|
-
console.log(`[mmrc] Port: ${options.port}`);
|
|
18155
|
-
}
|
|
18156
|
-
if (options.migrate) {
|
|
18157
|
-
console.log("[mmrc] Running migrations...");
|
|
18158
|
-
process.env.MM_RUN_MIGRATIONS = "true";
|
|
18159
|
-
}
|
|
18160
|
-
const { spawn } = require("child_process");
|
|
18161
|
-
const child = spawn(binary, args2, {
|
|
18162
|
-
stdio: "inherit",
|
|
18163
|
-
env: { ...process.env, MM_CONFIG_PATH: configPath ?? "" }
|
|
18164
|
-
});
|
|
18165
|
-
child.on("error", (err) => {
|
|
18166
|
-
console.error(`[mmrc] Failed to start server: ${err.message}`);
|
|
18167
|
-
process.exit(1);
|
|
18168
|
-
});
|
|
18169
|
-
child.on("exit", (code) => {
|
|
18170
|
-
process.exit(code ?? 0);
|
|
18171
|
-
});
|
|
18172
|
-
const forward = (signal) => {
|
|
18173
|
-
process.on(signal, () => child.kill(signal));
|
|
18174
|
-
};
|
|
18175
|
-
forward("SIGINT");
|
|
18176
|
-
forward("SIGTERM");
|
|
17141
|
+
return { stateMatch, stateCount };
|
|
18177
17142
|
}
|
|
18178
|
-
|
|
18179
|
-
const
|
|
18180
|
-
|
|
18181
|
-
|
|
18182
|
-
|
|
18183
|
-
|
|
18184
|
-
|
|
17143
|
+
function compareTransitions(diffs, transitions1, transitions2) {
|
|
17144
|
+
const map1 = new Map(transitions1.map((t27) => [t27.name, t27]));
|
|
17145
|
+
const map2 = new Map(transitions2.map((t27) => [t27.name, t27]));
|
|
17146
|
+
const transitionCount = map1.size;
|
|
17147
|
+
let transitionMatch = 0;
|
|
17148
|
+
if (transitions1.length !== transitions2.length) {
|
|
17149
|
+
diffs.push({
|
|
17150
|
+
path: "transitions.length",
|
|
17151
|
+
expected: transitions1.length,
|
|
17152
|
+
actual: transitions2.length,
|
|
17153
|
+
severity: "error"
|
|
18185
17154
|
});
|
|
18186
|
-
|
|
18187
|
-
|
|
18188
|
-
|
|
18189
|
-
|
|
17155
|
+
}
|
|
17156
|
+
for (const [name, t1] of map1) {
|
|
17157
|
+
const t27 = map2.get(name);
|
|
17158
|
+
if (!t27) {
|
|
17159
|
+
diffs.push({ path: `transitions[${name}]`, expected: name, actual: void 0, severity: "error" });
|
|
17160
|
+
continue;
|
|
18190
17161
|
}
|
|
18191
|
-
|
|
18192
|
-
|
|
17162
|
+
let matched = true;
|
|
17163
|
+
if (t1.to !== t27.to) {
|
|
17164
|
+
diffs.push({ path: `transitions[${name}].to`, expected: t1.to, actual: t27.to, severity: "error" });
|
|
17165
|
+
matched = false;
|
|
18193
17166
|
}
|
|
18194
|
-
|
|
17167
|
+
const from1 = [...t1.from].sort();
|
|
17168
|
+
const from2 = [...t27.from].sort();
|
|
17169
|
+
if (JSON.stringify(from1) !== JSON.stringify(from2)) {
|
|
17170
|
+
diffs.push({ path: `transitions[${name}].from`, expected: from1, actual: from2, severity: "error" });
|
|
17171
|
+
matched = false;
|
|
17172
|
+
}
|
|
17173
|
+
const roles1 = [...t1.roles ?? []].sort();
|
|
17174
|
+
const roles2 = [...t27.roles ?? []].sort();
|
|
17175
|
+
if (JSON.stringify(roles1) !== JSON.stringify(roles2)) {
|
|
17176
|
+
diffs.push({ path: `transitions[${name}].roles`, expected: roles1, actual: roles2, severity: "error" });
|
|
17177
|
+
matched = false;
|
|
17178
|
+
}
|
|
17179
|
+
const req1 = [...t1.required_fields ?? []].sort();
|
|
17180
|
+
const req2 = [...t27.required_fields ?? []].sort();
|
|
17181
|
+
if (JSON.stringify(req1) !== JSON.stringify(req2)) {
|
|
17182
|
+
diffs.push({ path: `transitions[${name}].required_fields`, expected: req1, actual: req2, severity: "error" });
|
|
17183
|
+
matched = false;
|
|
17184
|
+
}
|
|
17185
|
+
if (!!t1.auto !== !!t27.auto) {
|
|
17186
|
+
diffs.push({ path: `transitions[${name}].auto`, expected: t1.auto, actual: t27.auto, severity: "error" });
|
|
17187
|
+
matched = false;
|
|
17188
|
+
}
|
|
17189
|
+
if (matched) transitionMatch++;
|
|
18195
17190
|
}
|
|
18196
|
-
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
17191
|
+
return { transitionMatch, transitionCount };
|
|
17192
|
+
}
|
|
17193
|
+
|
|
17194
|
+
// src/cli/deploy.ts
|
|
17195
|
+
var import_glob3 = require("glob");
|
|
17196
|
+
var import_fs4 = require("fs");
|
|
17197
|
+
var import_path3 = require("path");
|
|
17198
|
+
async function deploy(options) {
|
|
17199
|
+
const dir = options.dir ?? "dist/workflows";
|
|
17200
|
+
const targetLabel = options.targetName ? ` (target: ${options.targetName})` : "";
|
|
17201
|
+
console.log(`[mindmatrix-react] Deploying workflows from ${dir} to ${options.apiUrl}${targetLabel}...`);
|
|
17202
|
+
const files = await (0, import_glob3.glob)(`${dir}/**/*.workflow.json`);
|
|
17203
|
+
if (files.length === 0) {
|
|
17204
|
+
console.log(`[mindmatrix-react] No workflow files found in ${dir}`);
|
|
17205
|
+
return { created: [], updated: [], versioned: [], skipped: [], failed: [] };
|
|
18202
17206
|
}
|
|
18203
|
-
|
|
18204
|
-
|
|
18205
|
-
|
|
18206
|
-
|
|
18207
|
-
|
|
18208
|
-
|
|
18209
|
-
|
|
18210
|
-
|
|
18211
|
-
|
|
18212
|
-
|
|
18213
|
-
|
|
17207
|
+
const result = {
|
|
17208
|
+
created: [],
|
|
17209
|
+
updated: [],
|
|
17210
|
+
versioned: [],
|
|
17211
|
+
skipped: [],
|
|
17212
|
+
failed: []
|
|
17213
|
+
};
|
|
17214
|
+
const deployedIRs = [];
|
|
17215
|
+
for (const file2 of files) {
|
|
17216
|
+
try {
|
|
17217
|
+
const ir = JSON.parse((0, import_fs4.readFileSync)(file2, "utf-8"));
|
|
17218
|
+
const slug = ir.slug;
|
|
17219
|
+
if (options.dryRun) {
|
|
17220
|
+
console.log(` [dry-run] Would deploy ${slug} (${(0, import_path3.basename)(file2)})`);
|
|
17221
|
+
continue;
|
|
17222
|
+
}
|
|
17223
|
+
const existing = await fetchExistingDefinition(options.apiUrl, options.token, slug);
|
|
17224
|
+
if (!existing) {
|
|
17225
|
+
await createDefinition(options.apiUrl, options.token, ir);
|
|
17226
|
+
console.log(` \u2713 ${slug} (created)`);
|
|
17227
|
+
result.created.push(slug);
|
|
17228
|
+
} else if (existing.instanceCount === 0 || options.force) {
|
|
17229
|
+
await updateDefinition(options.apiUrl, options.token, existing.id, ir);
|
|
17230
|
+
console.log(` \u2713 ${slug} (updated)`);
|
|
17231
|
+
result.updated.push(slug);
|
|
17232
|
+
} else {
|
|
17233
|
+
const newVersion = bumpVersion(existing.version);
|
|
17234
|
+
ir.version = newVersion;
|
|
17235
|
+
await createDefinition(options.apiUrl, options.token, ir);
|
|
17236
|
+
console.log(` \u2713 ${slug} v${newVersion} (new version, ${existing.instanceCount} instances on v${existing.version})`);
|
|
17237
|
+
result.versioned.push(slug);
|
|
17238
|
+
}
|
|
17239
|
+
deployedIRs.push(ir);
|
|
17240
|
+
} catch (error) {
|
|
17241
|
+
const slug = (0, import_path3.basename)(file2).replace(".workflow.json", "");
|
|
17242
|
+
const msg = error.message;
|
|
17243
|
+
console.error(` \u2717 ${slug}: ${msg}`);
|
|
17244
|
+
result.failed.push({ slug, error: msg });
|
|
17245
|
+
}
|
|
18214
17246
|
}
|
|
18215
|
-
|
|
18216
|
-
|
|
18217
|
-
|
|
18218
|
-
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
17247
|
+
if (!options.dryRun) {
|
|
17248
|
+
for (const ir of deployedIRs) {
|
|
17249
|
+
const serviceResult = await syncServices(options.apiUrl, options.token, ir);
|
|
17250
|
+
if (serviceResult) {
|
|
17251
|
+
if (!result.services) {
|
|
17252
|
+
result.services = { registered: [], updated: [], failed: [] };
|
|
17253
|
+
}
|
|
17254
|
+
result.services.registered.push(...serviceResult.registered);
|
|
17255
|
+
result.services.updated.push(...serviceResult.updated);
|
|
17256
|
+
result.services.failed.push(...serviceResult.failed);
|
|
17257
|
+
}
|
|
17258
|
+
}
|
|
18223
17259
|
}
|
|
18224
|
-
|
|
18225
|
-
|
|
18226
|
-
|
|
18227
|
-
|
|
18228
|
-
}
|
|
18229
|
-
function generateServerToml(mode = "standalone", db = "$env:DATABASE_URL") {
|
|
18230
|
-
const lines = [];
|
|
18231
|
-
lines.push(`# MindMatrix Server Configuration`);
|
|
18232
|
-
lines.push(`# Generated by: mmrc server init --mode ${mode}`);
|
|
18233
|
-
lines.push(`# Docs: https://docs.mindmatrix.dev/server/configuration`);
|
|
18234
|
-
lines.push(`#`);
|
|
18235
|
-
lines.push(`# Environment variables can be referenced as $env:VAR_NAME`);
|
|
18236
|
-
lines.push(``);
|
|
18237
|
-
lines.push(`[server]`);
|
|
18238
|
-
lines.push(`# Server mode: "standalone" (all-in-one), "gateway" (API + routing), "worker" (action execution)`);
|
|
18239
|
-
lines.push(`mode = "${mode}"`);
|
|
18240
|
-
lines.push(`# Listen port (also configurable via PORT env var)`);
|
|
18241
|
-
lines.push(`port = 4200`);
|
|
18242
|
-
lines.push(`# Bind address`);
|
|
18243
|
-
lines.push(`host = "0.0.0.0"`);
|
|
18244
|
-
lines.push(``);
|
|
18245
|
-
lines.push(`[database]`);
|
|
18246
|
-
lines.push(`# PostgreSQL connection URL`);
|
|
18247
|
-
lines.push(`url = "${db}"`);
|
|
18248
|
-
lines.push(`# Connection pool size`);
|
|
18249
|
-
lines.push(`max_connections = 10`);
|
|
18250
|
-
lines.push(``);
|
|
18251
|
-
lines.push(`[auth]`);
|
|
18252
|
-
lines.push(`# JWT signing secret (also configurable via JWT_SECRET env var)`);
|
|
18253
|
-
lines.push(`jwt_secret = "$env:JWT_SECRET"`);
|
|
18254
|
-
lines.push(``);
|
|
18255
|
-
lines.push(`[telemetry]`);
|
|
18256
|
-
lines.push(`# Log output format: "pretty" (human-readable) or "json" (structured)`);
|
|
18257
|
-
lines.push(`log_format = "pretty"`);
|
|
18258
|
-
lines.push(`# Log level filter (RUST_LOG syntax)`);
|
|
18259
|
-
lines.push(`log_level = "mm_api=info,mm_storage=info,mm_engine=info"`);
|
|
18260
|
-
lines.push(`# OpenTelemetry OTLP endpoint (optional \u2014 enables distributed tracing)`);
|
|
18261
|
-
lines.push(`# otlp_endpoint = "http://localhost:4317"`);
|
|
18262
|
-
lines.push(``);
|
|
18263
|
-
if (mode === "gateway") {
|
|
18264
|
-
lines.push(`[gateway]`);
|
|
18265
|
-
lines.push(`# Worker pool for routing action execution`);
|
|
18266
|
-
lines.push(`pool = "default"`);
|
|
18267
|
-
lines.push(`# Maximum concurrent actions per worker`);
|
|
18268
|
-
lines.push(`max_concurrent = 16`);
|
|
18269
|
-
lines.push(`# Worker heartbeat interval`);
|
|
18270
|
-
lines.push(`heartbeat = "30s"`);
|
|
18271
|
-
lines.push(``);
|
|
17260
|
+
if (options.reportFile) {
|
|
17261
|
+
(0, import_fs4.writeFileSync)(options.reportFile, JSON.stringify(result, null, 2), "utf-8");
|
|
17262
|
+
console.log(`
|
|
17263
|
+
Report written to ${options.reportFile}`);
|
|
18272
17264
|
}
|
|
18273
|
-
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
17265
|
+
const total = result.created.length + result.updated.length + result.versioned.length;
|
|
17266
|
+
console.log(
|
|
17267
|
+
`
|
|
17268
|
+
[mindmatrix-react] Deployed ${total} workflows (${result.created.length} created, ${result.updated.length} updated, ${result.versioned.length} versioned, ${result.failed.length} failed)`
|
|
17269
|
+
);
|
|
17270
|
+
if (result.services) {
|
|
17271
|
+
const svcTotal = result.services.registered.length + result.services.updated.length;
|
|
17272
|
+
if (svcTotal > 0 || result.services.failed.length > 0) {
|
|
17273
|
+
console.log(
|
|
17274
|
+
`[mindmatrix-react] Synced ${svcTotal} services (${result.services.registered.length} registered, ${result.services.updated.length} updated, ${result.services.failed.length} failed)`
|
|
17275
|
+
);
|
|
17276
|
+
}
|
|
18278
17277
|
}
|
|
18279
|
-
|
|
18280
|
-
lines.push(`# Secret provider: "env" (environment variables) or "vault" (HashiCorp Vault)`);
|
|
18281
|
-
lines.push(`provider = "env"`);
|
|
18282
|
-
lines.push(``);
|
|
18283
|
-
lines.push(`# \u2500\u2500 Services \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
18284
|
-
lines.push(`# Register external services for action routing.`);
|
|
18285
|
-
lines.push(`# Each [[services]] block declares a service that can handle workflow actions.`);
|
|
18286
|
-
lines.push(`#`);
|
|
18287
|
-
lines.push(`# [[services]]`);
|
|
18288
|
-
lines.push(`# name = "email"`);
|
|
18289
|
-
lines.push(`# type = "webhook"`);
|
|
18290
|
-
lines.push(`# url = "https://hooks.example.com/email"`);
|
|
18291
|
-
lines.push(`# actions = ["send_email", "send_sms"]`);
|
|
18292
|
-
lines.push(`# [services.labels]`);
|
|
18293
|
-
lines.push(`# tier = "essential"`);
|
|
18294
|
-
lines.push(``);
|
|
18295
|
-
return lines.join("\n");
|
|
17278
|
+
return result;
|
|
18296
17279
|
}
|
|
18297
|
-
async function
|
|
18298
|
-
const apiUrl = options.apiUrl ?? "http://localhost:4200";
|
|
18299
|
-
console.log(`[mmrc] Checking server at ${apiUrl}...`);
|
|
17280
|
+
async function fetchExistingDefinition(apiUrl, token, slug) {
|
|
18300
17281
|
try {
|
|
18301
|
-
const res = await fetch(`${apiUrl}/
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
status: `unhealthy (HTTP ${res.status})`
|
|
18306
|
-
};
|
|
18307
|
-
console.log(`[mmrc] Server: ${result2.status}`);
|
|
18308
|
-
return result2;
|
|
18309
|
-
}
|
|
17282
|
+
const res = await fetch(`${apiUrl}/workflow/definitions?slug=${encodeURIComponent(slug)}`, {
|
|
17283
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
17284
|
+
});
|
|
17285
|
+
if (!res.ok) return null;
|
|
18310
17286
|
const data = await res.json();
|
|
18311
|
-
const
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18315
|
-
|
|
18316
|
-
|
|
17287
|
+
const definitions = Array.isArray(data) ? data : data.items ?? data.data;
|
|
17288
|
+
if (!definitions || definitions.length === 0) return null;
|
|
17289
|
+
const def = definitions[0];
|
|
17290
|
+
return {
|
|
17291
|
+
id: def.id,
|
|
17292
|
+
slug: def.slug,
|
|
17293
|
+
version: def.version || "0.1.0",
|
|
17294
|
+
instanceCount: def.instanceCount ?? def.instance_count ?? 0
|
|
18317
17295
|
};
|
|
18318
|
-
|
|
18319
|
-
|
|
18320
|
-
if (result.uptime) console.log(`[mmrc] Uptime: ${result.uptime}`);
|
|
18321
|
-
if (result.database) console.log(`[mmrc] Database: ${result.database}`);
|
|
18322
|
-
return result;
|
|
18323
|
-
} catch (e) {
|
|
18324
|
-
const error = e.message;
|
|
18325
|
-
const result = { reachable: false, error };
|
|
18326
|
-
console.error(`[mmrc] Server unreachable: ${error}`);
|
|
18327
|
-
console.error(`[mmrc] Is the server running? Try: mmrc server start`);
|
|
18328
|
-
return result;
|
|
17296
|
+
} catch {
|
|
17297
|
+
return null;
|
|
18329
17298
|
}
|
|
18330
17299
|
}
|
|
18331
|
-
function
|
|
18332
|
-
const
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
`);
|
|
18340
|
-
const raw = (0, import_fs12.readFileSync)(configPath, "utf-8");
|
|
18341
|
-
const resolved = raw.replace(/\$env:(\w+)/g, (_match, varName) => {
|
|
18342
|
-
const val = process.env[varName];
|
|
18343
|
-
return val ? `${val} # \u2190 $env:${varName}` : `(unset) # \u2190 $env:${varName}`;
|
|
17300
|
+
async function createDefinition(apiUrl, token, ir) {
|
|
17301
|
+
const res = await fetch(`${apiUrl}/workflow/definitions`, {
|
|
17302
|
+
method: "POST",
|
|
17303
|
+
headers: {
|
|
17304
|
+
"Content-Type": "application/json",
|
|
17305
|
+
Authorization: `Bearer ${token}`
|
|
17306
|
+
},
|
|
17307
|
+
body: JSON.stringify(ir)
|
|
18344
17308
|
});
|
|
18345
|
-
|
|
18346
|
-
|
|
18347
|
-
|
|
18348
|
-
const candidates = [
|
|
18349
|
-
"mm-server.toml",
|
|
18350
|
-
"engine/mm-server.toml",
|
|
18351
|
-
"mm-core/mm-server.toml"
|
|
18352
|
-
];
|
|
18353
|
-
for (const c of candidates) {
|
|
18354
|
-
const abs = (0, import_path10.resolve)(process.cwd(), c);
|
|
18355
|
-
if ((0, import_fs12.existsSync)(abs)) return abs;
|
|
17309
|
+
if (!res.ok) {
|
|
17310
|
+
const errorText = await res.text();
|
|
17311
|
+
throw new Error(`Create failed: ${res.status} ${errorText}`);
|
|
18356
17312
|
}
|
|
18357
|
-
return null;
|
|
18358
17313
|
}
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18366
|
-
|
|
18367
|
-
|
|
18368
|
-
"mm-core/target/release/mm-server",
|
|
18369
|
-
"mm-core/target/debug/mm-server",
|
|
18370
|
-
"target/release/mm-server",
|
|
18371
|
-
"target/debug/mm-server"
|
|
18372
|
-
];
|
|
18373
|
-
}
|
|
18374
|
-
});
|
|
18375
|
-
|
|
18376
|
-
// src/cli/index.ts
|
|
18377
|
-
init_build();
|
|
18378
|
-
|
|
18379
|
-
// src/cli/test.ts
|
|
18380
|
-
var import_glob2 = require("glob");
|
|
18381
|
-
var import_fs3 = require("fs");
|
|
18382
|
-
var import_path2 = require("path");
|
|
18383
|
-
async function test(options = {}) {
|
|
18384
|
-
const srcDir = options.src ?? ".";
|
|
18385
|
-
const label = "[mindmatrix-react]";
|
|
18386
|
-
console.log(`${label} Round-trip fidelity test
|
|
18387
|
-
`);
|
|
18388
|
-
const configPath = (0, import_path2.resolve)(srcDir, "mm.config.ts");
|
|
18389
|
-
const isProject = (0, import_fs3.existsSync)(configPath);
|
|
18390
|
-
if (!isProject) {
|
|
18391
|
-
console.error(`${label} Error: No mm.config.ts found in ${srcDir}`);
|
|
18392
|
-
console.error(` Round-trip test requires a project with mm.config.ts`);
|
|
18393
|
-
process.exit(1);
|
|
18394
|
-
}
|
|
18395
|
-
const allFiles = await (0, import_glob2.glob)(`${srcDir}/**/*.{ts,tsx}`, {
|
|
18396
|
-
ignore: ["**/node_modules/**", "**/dist/**", "**/*.test.*"]
|
|
17314
|
+
async function updateDefinition(apiUrl, token, id, ir) {
|
|
17315
|
+
const { slug: _slug, ...updatePayload } = ir;
|
|
17316
|
+
const res = await fetch(`${apiUrl}/workflow/definitions/${id}`, {
|
|
17317
|
+
method: "PATCH",
|
|
17318
|
+
headers: {
|
|
17319
|
+
"Content-Type": "application/json",
|
|
17320
|
+
Authorization: `Bearer ${token}`
|
|
17321
|
+
},
|
|
17322
|
+
body: JSON.stringify(updatePayload)
|
|
18397
17323
|
});
|
|
18398
|
-
if (
|
|
18399
|
-
|
|
18400
|
-
|
|
18401
|
-
}
|
|
18402
|
-
const fileMap = {};
|
|
18403
|
-
for (const f of allFiles) {
|
|
18404
|
-
const rel = f.startsWith(srcDir + "/") ? f.slice(srcDir.length + 1) : f;
|
|
18405
|
-
fileMap[rel] = (0, import_fs3.readFileSync)(f, "utf-8");
|
|
17324
|
+
if (!res.ok) {
|
|
17325
|
+
const errorText = await res.text();
|
|
17326
|
+
throw new Error(`Update failed: ${res.status} ${errorText}`);
|
|
18406
17327
|
}
|
|
18407
|
-
|
|
18408
|
-
|
|
18409
|
-
|
|
18410
|
-
|
|
18411
|
-
|
|
18412
|
-
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
|
|
18416
|
-
|
|
18417
|
-
|
|
18418
|
-
|
|
18419
|
-
|
|
18420
|
-
|
|
18421
|
-
|
|
17328
|
+
}
|
|
17329
|
+
function bumpVersion(version) {
|
|
17330
|
+
const parts = version.split(".");
|
|
17331
|
+
if (parts.length !== 3) return `${version}.1`;
|
|
17332
|
+
const patch = parseInt(parts[2], 10) || 0;
|
|
17333
|
+
return `${parts[0]}.${parts[1]}.${patch + 1}`;
|
|
17334
|
+
}
|
|
17335
|
+
async function syncServices(apiUrl, token, ir) {
|
|
17336
|
+
const metadata = ir.metadata;
|
|
17337
|
+
const orchestration = metadata?.orchestration;
|
|
17338
|
+
const services = orchestration?.services;
|
|
17339
|
+
if (!services || Object.keys(services).length === 0) return null;
|
|
17340
|
+
const result = { registered: [], updated: [], failed: [] };
|
|
17341
|
+
for (const [name, config] of Object.entries(services)) {
|
|
17342
|
+
try {
|
|
17343
|
+
const registration = {
|
|
17344
|
+
name,
|
|
17345
|
+
connection: {
|
|
17346
|
+
type: config.type || "webhook",
|
|
17347
|
+
url: config.url,
|
|
17348
|
+
queue: config.queue
|
|
17349
|
+
},
|
|
17350
|
+
actions: config.actions || [],
|
|
17351
|
+
labels: config.labels || {}
|
|
17352
|
+
};
|
|
17353
|
+
const existing = await fetchExistingService(apiUrl, token, name);
|
|
17354
|
+
if (existing) {
|
|
17355
|
+
await fetch(`${apiUrl}/services/${existing.id}`, {
|
|
17356
|
+
method: "PATCH",
|
|
17357
|
+
headers: {
|
|
17358
|
+
"Content-Type": "application/json",
|
|
17359
|
+
Authorization: `Bearer ${token}`
|
|
17360
|
+
},
|
|
17361
|
+
body: JSON.stringify(registration)
|
|
17362
|
+
});
|
|
17363
|
+
console.log(` \u2713 service: ${name} (updated)`);
|
|
17364
|
+
result.updated.push(name);
|
|
17365
|
+
} else {
|
|
17366
|
+
const res = await fetch(`${apiUrl}/services`, {
|
|
17367
|
+
method: "POST",
|
|
17368
|
+
headers: {
|
|
17369
|
+
"Content-Type": "application/json",
|
|
17370
|
+
Authorization: `Bearer ${token}`
|
|
17371
|
+
},
|
|
17372
|
+
body: JSON.stringify(registration)
|
|
17373
|
+
});
|
|
17374
|
+
if (!res.ok) {
|
|
17375
|
+
const errorText = await res.text();
|
|
17376
|
+
throw new Error(`Register failed: ${res.status} ${errorText}`);
|
|
17377
|
+
}
|
|
17378
|
+
console.log(` \u2713 service: ${name} (registered)`);
|
|
17379
|
+
result.registered.push(name);
|
|
18422
17380
|
}
|
|
18423
|
-
|
|
17381
|
+
} catch (error) {
|
|
17382
|
+
const msg = error.message;
|
|
17383
|
+
console.error(` \u2717 service: ${name}: ${msg}`);
|
|
17384
|
+
result.failed.push(name);
|
|
18424
17385
|
}
|
|
18425
|
-
} catch (err) {
|
|
18426
|
-
console.log(` FAIL`);
|
|
18427
|
-
console.error(` ${err.message}`);
|
|
18428
|
-
process.exit(1);
|
|
18429
17386
|
}
|
|
18430
|
-
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
const t27 = performance.now();
|
|
18434
|
-
let decompFiles;
|
|
17387
|
+
return result;
|
|
17388
|
+
}
|
|
17389
|
+
async function fetchExistingService(apiUrl, token, name) {
|
|
18435
17390
|
try {
|
|
18436
|
-
const
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
const
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
|
|
18447
|
-
console.log(` FAIL`);
|
|
18448
|
-
console.error(` ${err.message}`);
|
|
18449
|
-
process.exit(1);
|
|
17391
|
+
const res = await fetch(`${apiUrl}/services?name=${encodeURIComponent(name)}`, {
|
|
17392
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
17393
|
+
});
|
|
17394
|
+
if (!res.ok) return null;
|
|
17395
|
+
const data = await res.json();
|
|
17396
|
+
const servicesList = Array.isArray(data) ? data : data.services ?? data.items ?? data.data;
|
|
17397
|
+
if (!servicesList || servicesList.length === 0) return null;
|
|
17398
|
+
const found = servicesList.find((s) => s.name === name);
|
|
17399
|
+
return found ? { id: found.id, name: found.name } : null;
|
|
17400
|
+
} catch {
|
|
17401
|
+
return null;
|
|
18450
17402
|
}
|
|
18451
|
-
|
|
18452
|
-
|
|
18453
|
-
|
|
18454
|
-
|
|
18455
|
-
|
|
17403
|
+
}
|
|
17404
|
+
|
|
17405
|
+
// src/cli/auth.ts
|
|
17406
|
+
var import_fs5 = require("fs");
|
|
17407
|
+
var import_path4 = require("path");
|
|
17408
|
+
var import_os = require("os");
|
|
17409
|
+
var import_readline = require("readline");
|
|
17410
|
+
var MMRC_DIR = (0, import_path4.join)((0, import_os.homedir)(), ".mmrc");
|
|
17411
|
+
var CREDENTIALS_PATH = (0, import_path4.join)(MMRC_DIR, "credentials.json");
|
|
17412
|
+
function loadCredentials() {
|
|
17413
|
+
if (!(0, import_fs5.existsSync)(CREDENTIALS_PATH)) return {};
|
|
18456
17414
|
try {
|
|
18457
|
-
|
|
18458
|
-
|
|
18459
|
-
|
|
18460
|
-
if (recompileErrors.length > 0) {
|
|
18461
|
-
console.log(` FAIL`);
|
|
18462
|
-
for (const err of recompileErrors) {
|
|
18463
|
-
console.error(` ${err.file}: ${err.message}`);
|
|
18464
|
-
}
|
|
18465
|
-
process.exit(1);
|
|
18466
|
-
}
|
|
18467
|
-
} catch (err) {
|
|
18468
|
-
console.log(` FAIL`);
|
|
18469
|
-
console.error(` ${err.message}`);
|
|
18470
|
-
process.exit(1);
|
|
18471
|
-
}
|
|
18472
|
-
const t52 = performance.now();
|
|
18473
|
-
console.log(` \u2713 (${((t52 - t42) / 1e3).toFixed(1)}s)`);
|
|
18474
|
-
process.stdout.write(` Comparing IR...
|
|
18475
|
-
`);
|
|
18476
|
-
const t62 = performance.now();
|
|
18477
|
-
const diffs = [];
|
|
18478
|
-
if (ir1.slug !== ir2.slug) {
|
|
18479
|
-
diffs.push({ path: "slug", expected: ir1.slug, actual: ir2.slug, severity: "error" });
|
|
18480
|
-
}
|
|
18481
|
-
if (ir1.version !== ir2.version) {
|
|
18482
|
-
diffs.push({ path: "version", expected: ir1.version, actual: ir2.version, severity: "error" });
|
|
18483
|
-
}
|
|
18484
|
-
if (JSON.stringify(ir1.category) !== JSON.stringify(ir2.category)) {
|
|
18485
|
-
diffs.push({ path: "category", expected: ir1.category, actual: ir2.category, severity: "error" });
|
|
17415
|
+
return JSON.parse((0, import_fs5.readFileSync)(CREDENTIALS_PATH, "utf-8"));
|
|
17416
|
+
} catch {
|
|
17417
|
+
return {};
|
|
18486
17418
|
}
|
|
18487
|
-
|
|
18488
|
-
|
|
18489
|
-
|
|
18490
|
-
const
|
|
18491
|
-
|
|
18492
|
-
|
|
18493
|
-
|
|
18494
|
-
|
|
18495
|
-
|
|
18496
|
-
|
|
18497
|
-
const errors = diffs.filter((d) => d.severity === "error");
|
|
18498
|
-
const success = errors.length === 0;
|
|
18499
|
-
if (success) {
|
|
18500
|
-
console.log(` PASS \u2014 round-trip produces identical IR`);
|
|
18501
|
-
} else {
|
|
18502
|
-
console.log(` FAIL \u2014 ${errors.length} difference(s) found:`);
|
|
18503
|
-
for (const diff of errors) {
|
|
18504
|
-
console.log(` ${diff.path}: expected ${JSON.stringify(diff.expected)}, got ${JSON.stringify(diff.actual)}`);
|
|
18505
|
-
}
|
|
17419
|
+
}
|
|
17420
|
+
function saveCredentials(apiUrl, token) {
|
|
17421
|
+
(0, import_fs5.mkdirSync)(MMRC_DIR, { recursive: true, mode: 448 });
|
|
17422
|
+
const creds = loadCredentials();
|
|
17423
|
+
creds[apiUrl] = { token, savedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
17424
|
+
(0, import_fs5.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
17425
|
+
try {
|
|
17426
|
+
const { chmodSync } = require("fs");
|
|
17427
|
+
chmodSync(CREDENTIALS_PATH, 384);
|
|
17428
|
+
} catch {
|
|
18506
17429
|
}
|
|
18507
|
-
return {
|
|
18508
|
-
success,
|
|
18509
|
-
fieldCount,
|
|
18510
|
-
fieldMatch,
|
|
18511
|
-
stateCount,
|
|
18512
|
-
stateMatch,
|
|
18513
|
-
transitionCount,
|
|
18514
|
-
transitionMatch,
|
|
18515
|
-
diffs,
|
|
18516
|
-
timings: {
|
|
18517
|
-
compile: t1 - t0,
|
|
18518
|
-
decompile: t32 - t27,
|
|
18519
|
-
recompile: t52 - t42,
|
|
18520
|
-
compare: t72 - t62
|
|
18521
|
-
}
|
|
18522
|
-
};
|
|
18523
17430
|
}
|
|
18524
|
-
function
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
for (const [name, f1] of map1) {
|
|
18530
|
-
const f2 = map2.get(name);
|
|
18531
|
-
if (!f2) {
|
|
18532
|
-
diffs.push({ path: `fields[${name}]`, expected: name, actual: void 0, severity: "error" });
|
|
18533
|
-
continue;
|
|
18534
|
-
}
|
|
18535
|
-
if (f1.type !== f2.type && !isCompatibleType(f1.type, f2.type)) {
|
|
18536
|
-
diffs.push({ path: `fields[${name}].type`, expected: f1.type, actual: f2.type, severity: "warning" });
|
|
18537
|
-
}
|
|
18538
|
-
fieldMatch++;
|
|
17431
|
+
function removeCredentials(apiUrl) {
|
|
17432
|
+
if (!(0, import_fs5.existsSync)(CREDENTIALS_PATH)) return;
|
|
17433
|
+
if (!apiUrl) {
|
|
17434
|
+
(0, import_fs5.unlinkSync)(CREDENTIALS_PATH);
|
|
17435
|
+
return;
|
|
18539
17436
|
}
|
|
18540
|
-
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
|
|
17437
|
+
const creds = loadCredentials();
|
|
17438
|
+
delete creds[apiUrl];
|
|
17439
|
+
if (Object.keys(creds).length === 0) {
|
|
17440
|
+
(0, import_fs5.unlinkSync)(CREDENTIALS_PATH);
|
|
17441
|
+
} else {
|
|
17442
|
+
(0, import_fs5.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
18544
17443
|
}
|
|
18545
|
-
return { fieldMatch, fieldCount };
|
|
18546
17444
|
}
|
|
18547
|
-
function
|
|
18548
|
-
|
|
18549
|
-
const
|
|
18550
|
-
if (
|
|
18551
|
-
|
|
18552
|
-
|
|
17445
|
+
function resolveToken(apiUrl, explicitToken) {
|
|
17446
|
+
if (explicitToken) return explicitToken;
|
|
17447
|
+
const envToken = process.env.MMRC_TOKEN;
|
|
17448
|
+
if (envToken) return envToken;
|
|
17449
|
+
const creds = loadCredentials();
|
|
17450
|
+
const entry = creds[apiUrl];
|
|
17451
|
+
if (entry?.token) return entry.token;
|
|
17452
|
+
return null;
|
|
18553
17453
|
}
|
|
18554
|
-
function
|
|
18555
|
-
|
|
18556
|
-
|
|
18557
|
-
|
|
18558
|
-
|
|
18559
|
-
|
|
18560
|
-
|
|
18561
|
-
|
|
18562
|
-
|
|
18563
|
-
|
|
18564
|
-
|
|
18565
|
-
|
|
18566
|
-
|
|
18567
|
-
|
|
18568
|
-
|
|
18569
|
-
|
|
18570
|
-
let matched = true;
|
|
18571
|
-
if (s1.on_enter.length !== s2.on_enter.length) {
|
|
18572
|
-
diffs.push({
|
|
18573
|
-
path: `states[${name}].on_enter.length`,
|
|
18574
|
-
expected: s1.on_enter.length,
|
|
18575
|
-
actual: s2.on_enter.length,
|
|
18576
|
-
severity: s1.on_enter.length > 0 ? "error" : "warning"
|
|
17454
|
+
function prompt(question, hidden = false) {
|
|
17455
|
+
return new Promise((resolve5) => {
|
|
17456
|
+
const rl = (0, import_readline.createInterface)({
|
|
17457
|
+
input: process.stdin,
|
|
17458
|
+
output: process.stdout
|
|
17459
|
+
});
|
|
17460
|
+
if (hidden && process.stdin.isTTY) {
|
|
17461
|
+
const origWrite = process.stdout.write.bind(process.stdout);
|
|
17462
|
+
process.stdout.write = ((chunk, encodingOrCb, cb) => {
|
|
17463
|
+
if (typeof chunk === "string" && chunk.includes(question)) {
|
|
17464
|
+
return origWrite(chunk, encodingOrCb, cb);
|
|
17465
|
+
}
|
|
17466
|
+
if (typeof chunk === "string" && !chunk.includes("\n")) {
|
|
17467
|
+
return true;
|
|
17468
|
+
}
|
|
17469
|
+
return origWrite(chunk, encodingOrCb, cb);
|
|
18577
17470
|
});
|
|
18578
|
-
|
|
18579
|
-
|
|
18580
|
-
|
|
18581
|
-
|
|
18582
|
-
|
|
18583
|
-
expected: s1.on_exit.length,
|
|
18584
|
-
actual: s2.on_exit.length,
|
|
18585
|
-
severity: s1.on_exit.length > 0 ? "error" : "warning"
|
|
17471
|
+
rl.question(question, (answer) => {
|
|
17472
|
+
process.stdout.write = origWrite;
|
|
17473
|
+
console.log();
|
|
17474
|
+
rl.close();
|
|
17475
|
+
resolve5(answer.trim());
|
|
18586
17476
|
});
|
|
18587
|
-
|
|
18588
|
-
|
|
18589
|
-
|
|
18590
|
-
|
|
18591
|
-
path: `states[${name}].during.length`,
|
|
18592
|
-
expected: s1.during.length,
|
|
18593
|
-
actual: s2.during.length,
|
|
18594
|
-
severity: s1.during.length > 0 ? "error" : "warning"
|
|
17477
|
+
} else {
|
|
17478
|
+
rl.question(question, (answer) => {
|
|
17479
|
+
rl.close();
|
|
17480
|
+
resolve5(answer.trim());
|
|
18595
17481
|
});
|
|
18596
|
-
if (s1.during.length > 0) matched = false;
|
|
18597
17482
|
}
|
|
18598
|
-
|
|
17483
|
+
});
|
|
17484
|
+
}
|
|
17485
|
+
async function login(apiUrl, email, password) {
|
|
17486
|
+
if (!email) {
|
|
17487
|
+
email = await prompt("Email: ");
|
|
18599
17488
|
}
|
|
18600
|
-
|
|
17489
|
+
if (!password) {
|
|
17490
|
+
password = await prompt("Password: ", true);
|
|
17491
|
+
}
|
|
17492
|
+
if (!email || !password) {
|
|
17493
|
+
throw new Error("Email and password are required");
|
|
17494
|
+
}
|
|
17495
|
+
console.log(`[mmrc] Logging in to ${apiUrl}...`);
|
|
17496
|
+
const res = await fetch(`${apiUrl}/auth/login`, {
|
|
17497
|
+
method: "POST",
|
|
17498
|
+
headers: { "Content-Type": "application/json" },
|
|
17499
|
+
body: JSON.stringify({ email, password })
|
|
17500
|
+
});
|
|
17501
|
+
if (!res.ok) {
|
|
17502
|
+
const text = await res.text();
|
|
17503
|
+
throw new Error(`Login failed: ${res.status} ${text}`);
|
|
17504
|
+
}
|
|
17505
|
+
const data = await res.json();
|
|
17506
|
+
const token = data.token ?? data.access_token ?? data.accessToken;
|
|
17507
|
+
if (!token) {
|
|
17508
|
+
throw new Error("Login succeeded but no token in response");
|
|
17509
|
+
}
|
|
17510
|
+
saveCredentials(apiUrl, token);
|
|
17511
|
+
const userName = data.name ?? data.user?.name ?? data.user?.email ?? email;
|
|
17512
|
+
console.log(`[mmrc] Logged in as ${userName}`);
|
|
17513
|
+
console.log(`[mmrc] Token saved to ${CREDENTIALS_PATH}`);
|
|
17514
|
+
return token;
|
|
18601
17515
|
}
|
|
18602
|
-
function
|
|
18603
|
-
|
|
18604
|
-
|
|
18605
|
-
|
|
18606
|
-
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
path: "transitions.length",
|
|
18610
|
-
expected: transitions1.length,
|
|
18611
|
-
actual: transitions2.length,
|
|
18612
|
-
severity: "error"
|
|
18613
|
-
});
|
|
17516
|
+
function logout(apiUrl) {
|
|
17517
|
+
if (apiUrl) {
|
|
17518
|
+
removeCredentials(apiUrl);
|
|
17519
|
+
console.log(`[mmrc] Credentials removed for ${apiUrl}`);
|
|
17520
|
+
} else {
|
|
17521
|
+
removeCredentials();
|
|
17522
|
+
console.log("[mmrc] All saved credentials removed");
|
|
18614
17523
|
}
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
18620
|
-
|
|
18621
|
-
|
|
18622
|
-
|
|
18623
|
-
|
|
18624
|
-
|
|
18625
|
-
}
|
|
18626
|
-
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
|
|
18631
|
-
|
|
18632
|
-
|
|
18633
|
-
const roles2 = [...t27.roles ?? []].sort();
|
|
18634
|
-
if (JSON.stringify(roles1) !== JSON.stringify(roles2)) {
|
|
18635
|
-
diffs.push({ path: `transitions[${name}].roles`, expected: roles1, actual: roles2, severity: "error" });
|
|
18636
|
-
matched = false;
|
|
18637
|
-
}
|
|
18638
|
-
const req1 = [...t1.required_fields ?? []].sort();
|
|
18639
|
-
const req2 = [...t27.required_fields ?? []].sort();
|
|
18640
|
-
if (JSON.stringify(req1) !== JSON.stringify(req2)) {
|
|
18641
|
-
diffs.push({ path: `transitions[${name}].required_fields`, expected: req1, actual: req2, severity: "error" });
|
|
18642
|
-
matched = false;
|
|
18643
|
-
}
|
|
18644
|
-
if (!!t1.auto !== !!t27.auto) {
|
|
18645
|
-
diffs.push({ path: `transitions[${name}].auto`, expected: t1.auto, actual: t27.auto, severity: "error" });
|
|
18646
|
-
matched = false;
|
|
17524
|
+
}
|
|
17525
|
+
async function whoami(apiUrl) {
|
|
17526
|
+
const token = resolveToken(apiUrl);
|
|
17527
|
+
if (!token) {
|
|
17528
|
+
console.log("[mmrc] Not logged in. Run `mmrc login` to authenticate.");
|
|
17529
|
+
return;
|
|
17530
|
+
}
|
|
17531
|
+
try {
|
|
17532
|
+
const res = await fetch(`${apiUrl}/auth/me`, {
|
|
17533
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
17534
|
+
});
|
|
17535
|
+
if (!res.ok) {
|
|
17536
|
+
if (res.status === 401) {
|
|
17537
|
+
console.log("[mmrc] Token is expired or invalid. Run `mmrc login` to re-authenticate.");
|
|
17538
|
+
return;
|
|
17539
|
+
}
|
|
17540
|
+
console.log(`[mmrc] Failed to fetch user info: ${res.status}`);
|
|
17541
|
+
return;
|
|
18647
17542
|
}
|
|
18648
|
-
|
|
17543
|
+
const user = await res.json();
|
|
17544
|
+
console.log(`[mmrc] Logged in to ${apiUrl}`);
|
|
17545
|
+
console.log(` Name: ${user.name ?? "(unknown)"}`);
|
|
17546
|
+
console.log(` Email: ${user.email ?? "(unknown)"}`);
|
|
17547
|
+
if (user.id) console.log(` ID: ${user.id}`);
|
|
17548
|
+
if (user.role) console.log(` Role: ${user.role}`);
|
|
17549
|
+
} catch (error) {
|
|
17550
|
+
console.log(`[mmrc] Could not connect to ${apiUrl}: ${error.message}`);
|
|
18649
17551
|
}
|
|
18650
|
-
return { transitionMatch, transitionCount };
|
|
18651
17552
|
}
|
|
18652
17553
|
|
|
18653
17554
|
// src/cli/index.ts
|
|
18654
|
-
init_deploy();
|
|
18655
|
-
init_auth();
|
|
18656
17555
|
var import_meta = {};
|
|
18657
17556
|
var args = process.argv.slice(2);
|
|
18658
17557
|
var command = args[0];
|
|
@@ -18671,11 +17570,11 @@ function getPositional() {
|
|
|
18671
17570
|
}
|
|
18672
17571
|
async function loadDevConfig() {
|
|
18673
17572
|
try {
|
|
18674
|
-
const { existsSync:
|
|
18675
|
-
const { resolve:
|
|
18676
|
-
const configPath =
|
|
18677
|
-
if (!
|
|
18678
|
-
const content =
|
|
17573
|
+
const { existsSync: existsSync7, readFileSync: readFileSync8 } = await import("fs");
|
|
17574
|
+
const { resolve: resolve5 } = await import("path");
|
|
17575
|
+
const configPath = resolve5(process.cwd(), "mm.config.ts");
|
|
17576
|
+
if (!existsSync7(configPath)) return {};
|
|
17577
|
+
const content = readFileSync8(configPath, "utf-8");
|
|
18679
17578
|
const devMatch = content.match(/dev\s*:\s*\{([^}]*)\}/s);
|
|
18680
17579
|
if (!devMatch) return {};
|
|
18681
17580
|
const block = devMatch[1];
|
|
@@ -18703,7 +17602,7 @@ async function main() {
|
|
|
18703
17602
|
const src = getFlag("--src") ?? devCfg.src;
|
|
18704
17603
|
const mode = getFlag("--mode") ?? devCfg.mode;
|
|
18705
17604
|
const seed = hasFlag("--seed") || devCfg.seed === true;
|
|
18706
|
-
const apiUrl =
|
|
17605
|
+
const apiUrl = getFlag("--api-url") ?? devCfg.apiUrl;
|
|
18707
17606
|
const authToken = getFlag("--token") ?? devCfg.token;
|
|
18708
17607
|
const open = hasFlag("--open") || devCfg.open === true;
|
|
18709
17608
|
const { createDevServer: createDevServer2 } = await Promise.resolve().then(() => (init_dev_server(), dev_server_exports));
|
|
@@ -18774,19 +17673,19 @@ async function main() {
|
|
|
18774
17673
|
const srcDir = src ?? ".";
|
|
18775
17674
|
const outDir = dir ?? "dist/workflows";
|
|
18776
17675
|
console.log("[mmrc] Building before deploy...\n");
|
|
18777
|
-
const { existsSync:
|
|
18778
|
-
const { resolve:
|
|
18779
|
-
const { glob:
|
|
18780
|
-
const configPath =
|
|
18781
|
-
if (
|
|
17676
|
+
const { existsSync: existsSync7, readFileSync: readFileSync8, writeFileSync: writeFileSync8, mkdirSync: mkdirSync6 } = await import("fs");
|
|
17677
|
+
const { resolve: resolve5, join: join7 } = await import("path");
|
|
17678
|
+
const { glob: glob5 } = await import("glob");
|
|
17679
|
+
const configPath = resolve5(srcDir, "mm.config.ts");
|
|
17680
|
+
if (existsSync7(configPath)) {
|
|
18782
17681
|
const { compileProject: compileProject2 } = await Promise.resolve().then(() => (init_project_compiler(), project_compiler_exports));
|
|
18783
|
-
const allFiles = await
|
|
17682
|
+
const allFiles = await glob5(`${srcDir}/**/*.{ts,tsx}`, {
|
|
18784
17683
|
ignore: ["**/node_modules/**", "**/dist/**", "**/__tests__/**", "**/*.test.*"]
|
|
18785
17684
|
});
|
|
18786
17685
|
const fileMap = {};
|
|
18787
17686
|
for (const f of allFiles) {
|
|
18788
17687
|
const rel = f.startsWith(srcDir + "/") ? f.slice(srcDir.length + 1) : f;
|
|
18789
|
-
fileMap[rel] =
|
|
17688
|
+
fileMap[rel] = readFileSync8(f, "utf-8");
|
|
18790
17689
|
}
|
|
18791
17690
|
console.log(` Compiling project (${Object.keys(fileMap).length} files)...`);
|
|
18792
17691
|
const result = compileProject2(fileMap);
|
|
@@ -18801,14 +17700,14 @@ async function main() {
|
|
|
18801
17700
|
}
|
|
18802
17701
|
mkdirSync6(outDir, { recursive: true });
|
|
18803
17702
|
const irPath = join7(outDir, `${result.ir.slug}.workflow.json`);
|
|
18804
|
-
|
|
17703
|
+
writeFileSync8(irPath, JSON.stringify(result.ir, null, 2), "utf-8");
|
|
18805
17704
|
console.log(` + ${result.ir.slug}.workflow.json`);
|
|
18806
17705
|
const seenSlugs = /* @__PURE__ */ new Set([result.ir.slug]);
|
|
18807
17706
|
for (const child of result.childDefinitions) {
|
|
18808
17707
|
if (seenSlugs.has(child.slug)) continue;
|
|
18809
17708
|
seenSlugs.add(child.slug);
|
|
18810
17709
|
const childPath = join7(outDir, `${child.slug}.workflow.json`);
|
|
18811
|
-
|
|
17710
|
+
writeFileSync8(childPath, JSON.stringify(child, null, 2), "utf-8");
|
|
18812
17711
|
console.log(` + ${child.slug}.workflow.json`);
|
|
18813
17712
|
}
|
|
18814
17713
|
console.log(` Compiled ${1 + result.childDefinitions.length} definitions.
|
|
@@ -18884,22 +17783,6 @@ async function main() {
|
|
|
18884
17783
|
}
|
|
18885
17784
|
const { pull: pull2 } = await Promise.resolve().then(() => (init_pull(), pull_exports));
|
|
18886
17785
|
await pull2({ slug, apiUrl, token, outDir });
|
|
18887
|
-
} else if (command === "seed") {
|
|
18888
|
-
const apiUrl = getFlag("--api-url") ?? "http://localhost:4200/api/v1";
|
|
18889
|
-
const token = resolveToken(apiUrl, getFlag("--token"));
|
|
18890
|
-
const dir = getFlag("--dir");
|
|
18891
|
-
const count = getFlag("--count") ? parseInt(getFlag("--count"), 10) : void 0;
|
|
18892
|
-
if (!token) {
|
|
18893
|
-
console.error("[mmrc] Error: No auth token found. Run `mmrc login` first.");
|
|
18894
|
-
process.exit(1);
|
|
18895
|
-
}
|
|
18896
|
-
const { seedInstances: seedInstances2 } = await Promise.resolve().then(() => (init_seed(), seed_exports));
|
|
18897
|
-
const result = await seedInstances2({ apiUrl, token, dir, count });
|
|
18898
|
-
console.log(`
|
|
18899
|
-
[mmrc] Seed complete: ${result.created} instances across ${result.definitions} definitions`);
|
|
18900
|
-
if (result.errors.length > 0) {
|
|
18901
|
-
console.warn(` ${result.errors.length} error(s)`);
|
|
18902
|
-
}
|
|
18903
17786
|
} else if (command === "config") {
|
|
18904
17787
|
const subcommand = args[1];
|
|
18905
17788
|
const { getConfig: getConfig2, getConfigValue: getConfigValue2, setConfigValue: setConfigValue2, flattenConfig: flattenConfig2, findConfigPath: findConfigPath2, writeConfigFile: writeConfigFile2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
@@ -18944,44 +17827,17 @@ async function main() {
|
|
|
18944
17827
|
console.error(" Usage: mmrc config [get <key> | set <key> <value> | list]");
|
|
18945
17828
|
process.exit(1);
|
|
18946
17829
|
}
|
|
18947
|
-
} else if (command === "server") {
|
|
18948
|
-
const subcommand = args[1];
|
|
18949
|
-
const { serverStart: serverStart2, serverMigrate: serverMigrate2, serverInit: serverInit2, serverStatus: serverStatus2, serverConfig: serverConfig2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
18950
|
-
if (subcommand === "start") {
|
|
18951
|
-
await serverStart2({
|
|
18952
|
-
config: getFlag("--config"),
|
|
18953
|
-
port: getFlag("--port") ? parseInt(getFlag("--port"), 10) : void 0,
|
|
18954
|
-
migrate: hasFlag("--migrate"),
|
|
18955
|
-
binary: getFlag("--binary")
|
|
18956
|
-
});
|
|
18957
|
-
} else if (subcommand === "migrate") {
|
|
18958
|
-
await serverMigrate2({ apiUrl: getFlag("--api-url"), config: getFlag("--config") });
|
|
18959
|
-
} else if (subcommand === "init") {
|
|
18960
|
-
serverInit2({
|
|
18961
|
-
mode: getFlag("--mode"),
|
|
18962
|
-
db: getFlag("--db"),
|
|
18963
|
-
output: getFlag("--output")
|
|
18964
|
-
});
|
|
18965
|
-
} else if (subcommand === "status") {
|
|
18966
|
-
await serverStatus2({ apiUrl: getFlag("--api-url") });
|
|
18967
|
-
} else if (subcommand === "config") {
|
|
18968
|
-
serverConfig2({ config: getFlag("--config") });
|
|
18969
|
-
} else {
|
|
18970
|
-
console.error(`[mmrc] Unknown server subcommand: ${subcommand ?? "(none)"}`);
|
|
18971
|
-
console.error(" Usage: mmrc server [start|migrate|init|status|config]");
|
|
18972
|
-
process.exit(1);
|
|
18973
|
-
}
|
|
18974
17830
|
} else if (command === "version" || command === "-v" || command === "--version" || hasFlag("--version") || hasFlag("-v")) {
|
|
18975
|
-
const { readFileSync:
|
|
18976
|
-
const { resolve:
|
|
17831
|
+
const { readFileSync: readFileSync8 } = await import("fs");
|
|
17832
|
+
const { resolve: resolve5, dirname: dirname4 } = await import("path");
|
|
18977
17833
|
try {
|
|
18978
|
-
const pkgPath =
|
|
18979
|
-
const pkg = JSON.parse(
|
|
17834
|
+
const pkgPath = resolve5(dirname4(new URL(import_meta.url).pathname), "../../package.json");
|
|
17835
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
18980
17836
|
console.log(`mmrc ${pkg.version}`);
|
|
18981
17837
|
} catch {
|
|
18982
17838
|
try {
|
|
18983
|
-
const pkgPath =
|
|
18984
|
-
const pkg = JSON.parse(
|
|
17839
|
+
const pkgPath = resolve5(__dirname, "../../package.json");
|
|
17840
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
18985
17841
|
console.log(`mmrc ${pkg.version}`);
|
|
18986
17842
|
} catch {
|
|
18987
17843
|
console.log("mmrc (version unknown)");
|
|
@@ -18990,10 +17846,10 @@ async function main() {
|
|
|
18990
17846
|
} else {
|
|
18991
17847
|
let version = "";
|
|
18992
17848
|
try {
|
|
18993
|
-
const { readFileSync:
|
|
18994
|
-
const { resolve:
|
|
18995
|
-
const pkgPath =
|
|
18996
|
-
const pkg = JSON.parse(
|
|
17849
|
+
const { readFileSync: readFileSync8 } = await import("fs");
|
|
17850
|
+
const { resolve: resolve5 } = await import("path");
|
|
17851
|
+
const pkgPath = resolve5(__dirname, "../../package.json");
|
|
17852
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
18997
17853
|
version = ` v${pkg.version}`;
|
|
18998
17854
|
} catch {
|
|
18999
17855
|
}
|