@mmapp/react-compiler 0.1.0-alpha.18 → 0.1.0-alpha.19
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 +1 -1
- package/dist/babel/index.d.ts +1 -1
- package/dist/babel/index.js +9 -6
- package/dist/babel/index.mjs +1 -1
- package/dist/chunk-26U577GB.mjs +3465 -0
- package/dist/chunk-2FBDFAX6.mjs +2362 -0
- package/dist/chunk-2REDFOER.mjs +931 -0
- package/dist/{chunk-FPAMQXKB.mjs → chunk-2UTXM2QX.mjs} +10 -20
- package/dist/chunk-2YDQTFAL.mjs +879 -0
- package/dist/chunk-2ZRKQE74.mjs +175 -0
- package/dist/chunk-3QHG2JWV.mjs +154 -0
- package/dist/chunk-466OWSTT.mjs +186 -0
- package/dist/chunk-467SFYOD.mjs +3127 -0
- package/dist/chunk-4AIJO7DZ.mjs +214 -0
- package/dist/chunk-4D43TZYL.mjs +7495 -0
- package/dist/chunk-4HX4PI4R.mjs +734 -0
- package/dist/chunk-4VU56NTZ.mjs +544 -0
- package/dist/chunk-4XHK6FWL.mjs +2058 -0
- package/dist/chunk-52C2JKH2.mjs +186 -0
- package/dist/chunk-52XHYD2V.mjs +214 -0
- package/dist/chunk-5GUFFFGL.mjs +148 -0
- package/dist/chunk-5N2FDDS6.mjs +214 -0
- package/dist/chunk-5ZSJXWZT.mjs +1646 -0
- package/dist/chunk-6CQOAAMV.mjs +1803 -0
- package/dist/chunk-6SEVAAVT.mjs +3516 -0
- package/dist/chunk-6YLR5ZDA.mjs +2829 -0
- package/dist/chunk-77UJB356.mjs +244 -0
- package/dist/chunk-7QOAJPQF.mjs +774 -0
- package/dist/chunk-A5RCMIBP.mjs +1795 -0
- package/dist/chunk-A63R3GKH.mjs +1803 -0
- package/dist/chunk-ABNTZXF5.mjs +951 -0
- package/dist/chunk-ADHWW56I.mjs +214 -0
- package/dist/chunk-AOGY2GK6.mjs +3292 -0
- package/dist/chunk-AXXUXRNA.mjs +1434 -0
- package/dist/chunk-BZLU5YK5.mjs +1025 -0
- package/dist/chunk-C7XCDDBH.mjs +1802 -0
- package/dist/chunk-CHLVKMQW.mjs +175 -0
- package/dist/chunk-CKGOZAB7.mjs +939 -0
- package/dist/chunk-CSXYDIVC.mjs +214 -0
- package/dist/chunk-CXTV4VGG.mjs +148 -0
- package/dist/chunk-D34RAZUX.mjs +2223 -0
- package/dist/chunk-DDIC7WM6.mjs +3127 -0
- package/dist/chunk-DPUQOBU6.mjs +4810 -0
- package/dist/chunk-E6MDVTGT.mjs +148 -0
- package/dist/chunk-EGKMUEM6.mjs +544 -0
- package/dist/chunk-EO6SYNCG.mjs +175 -0
- package/dist/chunk-EQGA6A6D.mjs +121 -0
- package/dist/chunk-EY2CSXYA.mjs +822 -0
- package/dist/chunk-FF5BQVII.mjs +148 -0
- package/dist/chunk-FIQ65CDR.mjs +925 -0
- package/dist/chunk-FOZXJFAR.mjs +186 -0
- package/dist/chunk-G2IAZ5Q6.mjs +148 -0
- package/dist/chunk-G7SMOWOL.mjs +828 -0
- package/dist/chunk-GK7NU6DO.mjs +214 -0
- package/dist/chunk-HDSCPEHY.mjs +4061 -0
- package/dist/chunk-HJELFNEA.mjs +186 -0
- package/dist/chunk-HOIUP6IF.mjs +690 -0
- package/dist/chunk-HRJGDPNE.mjs +148 -0
- package/dist/chunk-I3AU7GRD.mjs +120 -0
- package/dist/chunk-I3VQQJZ6.mjs +2843 -0
- package/dist/chunk-IPTX5MJU.mjs +3223 -0
- package/dist/chunk-ITGUSH2Z.mjs +2783 -0
- package/dist/chunk-IXHBCAMF.mjs +3306 -0
- package/dist/chunk-J7JUAHS4.mjs +186 -0
- package/dist/chunk-J7TWJ3TM.mjs +2784 -0
- package/dist/chunk-JDPLDGVF.mjs +4810 -0
- package/dist/chunk-JK72MQ4N.mjs +877 -0
- package/dist/chunk-K2HHCAS2.mjs +148 -0
- package/dist/chunk-K5HX2SVL.mjs +1902 -0
- package/dist/chunk-KAUEQ2F3.mjs +148 -0
- package/dist/chunk-KFVVOS5N.mjs +925 -0
- package/dist/chunk-KIH4AN3Y.mjs +154 -0
- package/dist/chunk-KPDMN5IX.mjs +175 -0
- package/dist/chunk-LZL2IRCH.mjs +186 -0
- package/dist/chunk-MIZV3TAN.mjs +3293 -0
- package/dist/chunk-MRH4J7IX.mjs +2846 -0
- package/dist/chunk-NKBL5GUC.mjs +186 -0
- package/dist/chunk-NQCNSCF6.mjs +148 -0
- package/dist/chunk-NRP5J3BR.mjs +4811 -0
- package/dist/chunk-NTB7OEX2.mjs +2918 -0
- package/dist/chunk-NUPJYPFU.mjs +801 -0
- package/dist/chunk-NVQUTSQX.mjs +3128 -0
- package/dist/chunk-OGMG64EY.mjs +148 -0
- package/dist/chunk-OL5B2HTH.mjs +175 -0
- package/dist/chunk-OPJKP747.mjs +7506 -0
- package/dist/chunk-OQLGGBNE.mjs +2918 -0
- package/dist/chunk-OW4AQUDL.mjs +544 -0
- package/dist/chunk-OWI6XWCD.mjs +3375 -0
- package/dist/chunk-OZT2EAF2.mjs +2776 -0
- package/dist/chunk-PBRBRKIQ.mjs +175 -0
- package/dist/chunk-PRUMNNDI.mjs +3192 -0
- package/dist/chunk-QPNHDTSM.mjs +4839 -0
- package/dist/chunk-RNEIAJDR.mjs +897 -0
- package/dist/chunk-RY7POBNT.mjs +3127 -0
- package/dist/chunk-S6FJ4DXL.mjs +1813 -0
- package/dist/chunk-SU4E6E7B.mjs +3153 -0
- package/dist/chunk-SYUUKW5A.mjs +3379 -0
- package/dist/chunk-THB5SX2S.mjs +113 -0
- package/dist/chunk-THFYE5ZX.mjs +244 -0
- package/dist/chunk-TK3QMXIP.mjs +2921 -0
- package/dist/chunk-TRR2NPAV.mjs +248 -0
- package/dist/chunk-TTTTOT7P.mjs +1803 -0
- package/dist/chunk-TXONBY6A.mjs +7509 -0
- package/dist/chunk-U2PX3JSY.mjs +1933 -0
- package/dist/chunk-UASOWKDI.mjs +186 -0
- package/dist/chunk-UDDTWG5J.mjs +734 -0
- package/dist/chunk-UIWLAQCL.mjs +175 -0
- package/dist/chunk-UL2XZEMA.mjs +3128 -0
- package/dist/chunk-US3AVDAI.mjs +3456 -0
- package/dist/chunk-V5DIDOTT.mjs +148 -0
- package/dist/chunk-VLTKQDJ3.mjs +244 -0
- package/dist/chunk-VVC42PTS.mjs +175 -0
- package/dist/chunk-VX3T3NIR.mjs +897 -0
- package/dist/chunk-WBYMW4NQ.mjs +3450 -0
- package/dist/chunk-XMWUHQVV.mjs +939 -0
- package/dist/chunk-Y6FXYEAI.mjs +10 -0
- package/dist/chunk-YCWC2SCO.mjs +148 -0
- package/dist/chunk-YFS6JMYO.mjs +3342 -0
- package/dist/chunk-ZE67HOSN.mjs +148 -0
- package/dist/chunk-ZSK5TPIV.mjs +148 -0
- package/dist/cli/index.js +317 -645
- package/dist/cli/index.mjs +8 -8
- package/dist/config-PL24KEWL.mjs +219 -0
- package/dist/dev-server-Bs_sz2DG.d.mts +111 -0
- package/dist/dev-server-Bs_sz2DG.d.ts +111 -0
- package/dist/dev-server-RmGHIntF.d.mts +113 -0
- package/dist/dev-server-RmGHIntF.d.ts +113 -0
- package/dist/dev-server.js +194 -515
- package/dist/dev-server.mjs +4 -4
- package/dist/engine-binary-KQB23JDR.mjs +97 -0
- package/dist/envelope-DD7v0v6E.d.mts +265 -0
- package/dist/envelope-DD7v0v6E.d.ts +265 -0
- package/dist/envelope.js +9 -6
- package/dist/envelope.mjs +2 -2
- package/dist/index-B5gSgvnd.d.mts +44 -0
- package/dist/index-B5gSgvnd.d.ts +44 -0
- package/dist/index-Bs0MnR54.d.mts +103 -0
- package/dist/index-Bs0MnR54.d.ts +103 -0
- package/dist/index-DR0nNc_f.d.mts +101 -0
- package/dist/index-DR0nNc_f.d.ts +101 -0
- package/dist/index-revho_gS.d.mts +104 -0
- package/dist/index-revho_gS.d.ts +104 -0
- package/dist/index-vQjwYekL.d.mts +104 -0
- package/dist/index-vQjwYekL.d.ts +104 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +198 -517
- package/dist/index.mjs +9 -8
- package/dist/init-2XLTUF7O.mjs +407 -0
- package/dist/init-7FJENUDK.mjs +407 -0
- package/dist/init-DQDX3QK6.mjs +369 -0
- package/dist/init-K3GVM4JS.mjs +538 -0
- package/dist/init-NXS5BJN3.mjs +454 -0
- package/dist/init-UC3FWPIW.mjs +367 -0
- package/dist/init-UNV5XIDE.mjs +367 -0
- package/dist/project-compiler-2HOPO7GC.mjs +10 -0
- package/dist/project-compiler-D245L5QR.mjs +10 -0
- package/dist/project-compiler-FUQRMB4X.mjs +10 -0
- package/dist/project-compiler-LA5OBI5P.mjs +10 -0
- package/dist/project-compiler-OP2VVGJQ.mjs +10 -0
- package/dist/project-compiler-PZNFE6AH.mjs +10 -0
- package/dist/project-compiler-QBVF6MFI.mjs +10 -0
- package/dist/project-compiler-VFR6CSDX.mjs +10 -0
- package/dist/project-compiler-WMJZA4UH.mjs +10 -0
- package/dist/project-compiler-XXS27TZT.mjs +10 -0
- package/dist/project-compiler-YYGDSHY5.mjs +10 -0
- package/dist/project-decompiler-5GY2KSG4.mjs +7 -0
- package/dist/project-decompiler-7I2OMUVY.mjs +7 -0
- package/dist/project-decompiler-US7GAVIC.mjs +7 -0
- package/dist/pull-2Q53HF3H.mjs +107 -0
- package/dist/pull-5AFHD3QG.mjs +109 -0
- package/dist/pull-65GUSX6F.mjs +109 -0
- package/dist/pull-6LVI4LMM.mjs +109 -0
- package/dist/pull-A2QUHW4K.mjs +109 -0
- package/dist/pull-B6T5BUKV.mjs +109 -0
- package/dist/pull-CKHWZT33.mjs +109 -0
- package/dist/pull-GM74ERRT.mjs +109 -0
- package/dist/pull-JBEQWVPE.mjs +109 -0
- package/dist/pull-P44LDRWB.mjs +109 -0
- package/dist/pull-W2US3T3E.mjs +109 -0
- package/dist/testing/index.js +9 -6
- package/dist/testing/index.mjs +1 -1
- package/dist/verify-3PPS4XAM.mjs +1833 -0
- package/dist/verify-GKEH5FZQ.mjs +1833 -0
- package/dist/verify-HDKUNHZ4.mjs +1833 -0
- package/dist/verify-SEIXUGN4.mjs +1833 -0
- package/dist/vite/index.js +10 -7
- package/dist/vite/index.mjs +2 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2115,7 +2115,8 @@ function convertOnEvent(sub) {
|
|
|
2115
2115
|
};
|
|
2116
2116
|
}
|
|
2117
2117
|
function emitIR(extracted) {
|
|
2118
|
-
const { slug, name, version, description, category, fields, states, transitions } = extracted;
|
|
2118
|
+
const { slug, name, version, description, category: rawCategory, fields, states, transitions } = extracted;
|
|
2119
|
+
const category = Array.isArray(rawCategory) ? rawCategory : [rawCategory];
|
|
2119
2120
|
const stateArray = Array.from(states.values());
|
|
2120
2121
|
if (stateArray.length === 0) {
|
|
2121
2122
|
stateArray.push({
|
|
@@ -2503,13 +2504,15 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
2503
2504
|
}
|
|
2504
2505
|
]
|
|
2505
2506
|
});
|
|
2506
|
-
const
|
|
2507
|
+
const rawCat = extracted.category;
|
|
2507
2508
|
let categoryArray;
|
|
2508
|
-
if (
|
|
2509
|
-
|
|
2509
|
+
if (Array.isArray(rawCat)) {
|
|
2510
|
+
categoryArray = rawCat;
|
|
2511
|
+
} else if (rawCat.includes("/")) {
|
|
2512
|
+
const [primary, ...tags] = rawCat.split("/");
|
|
2510
2513
|
categoryArray = (0, import_player_core.normalizeCategory)(primary, ...tags);
|
|
2511
2514
|
} else {
|
|
2512
|
-
categoryArray = [
|
|
2515
|
+
categoryArray = [rawCat];
|
|
2513
2516
|
}
|
|
2514
2517
|
return {
|
|
2515
2518
|
slug: ir.slug,
|
|
@@ -2662,7 +2665,7 @@ function compilerStateToWorkflow(state, metadata) {
|
|
|
2662
2665
|
name: metadata.name || "Workflow",
|
|
2663
2666
|
version: metadata.version || "0.1.0",
|
|
2664
2667
|
description: metadata.description,
|
|
2665
|
-
category: metadata.category || "workflow",
|
|
2668
|
+
category: metadata.categoryArray ? metadata.categoryArray : [metadata.category || "workflow"],
|
|
2666
2669
|
fields: state.fields || [],
|
|
2667
2670
|
states: state.states || /* @__PURE__ */ new Map(),
|
|
2668
2671
|
transitions: state.transitions || [],
|
|
@@ -7794,7 +7797,7 @@ function extractRouterWorkflow(pages, options = {}) {
|
|
|
7794
7797
|
name: "Router",
|
|
7795
7798
|
version: "1.0.0",
|
|
7796
7799
|
description: "Auto-derived router workflow from file-based routing",
|
|
7797
|
-
category: "router",
|
|
7800
|
+
category: ["router"],
|
|
7798
7801
|
fields,
|
|
7799
7802
|
states,
|
|
7800
7803
|
transitions,
|
|
@@ -7893,7 +7896,8 @@ function compileModel(filename, source, options = {}) {
|
|
|
7893
7896
|
parserOpts: { plugins: parserPlugins, attachComment: true }
|
|
7894
7897
|
});
|
|
7895
7898
|
const ir = babelResult?.metadata?.mindmatrixIR ?? createEmptyModelIR(interfaceName);
|
|
7896
|
-
|
|
7899
|
+
const catOverride = options.categoryOverride || annotation.category || "data";
|
|
7900
|
+
ir.category = Array.isArray(catOverride) ? catOverride : [catOverride];
|
|
7897
7901
|
if (options.slugOverride) {
|
|
7898
7902
|
ir.slug = options.slugOverride;
|
|
7899
7903
|
}
|
|
@@ -7957,7 +7961,7 @@ function createEmptyModelIR(interfaceName) {
|
|
|
7957
7961
|
name: interfaceName,
|
|
7958
7962
|
version: "1.0.0",
|
|
7959
7963
|
description: "Data model: " + interfaceName,
|
|
7960
|
-
category: "data",
|
|
7964
|
+
category: ["data"],
|
|
7961
7965
|
fields: [],
|
|
7962
7966
|
states: [{
|
|
7963
7967
|
name: "draft",
|
|
@@ -8125,7 +8129,7 @@ function buildRouterIR(routes, layouts, allParams, slugPrefix) {
|
|
|
8125
8129
|
name: "Router",
|
|
8126
8130
|
version: "1.0.0",
|
|
8127
8131
|
description: "Auto-generated router from app/ directory structure",
|
|
8128
|
-
category: "router",
|
|
8132
|
+
category: ["router"],
|
|
8129
8133
|
fields,
|
|
8130
8134
|
states,
|
|
8131
8135
|
transitions,
|
|
@@ -8394,7 +8398,7 @@ function extractAction(source, filename) {
|
|
|
8394
8398
|
slug,
|
|
8395
8399
|
name: humanName,
|
|
8396
8400
|
version: "0.1.0",
|
|
8397
|
-
category: "action",
|
|
8401
|
+
category: ["action"],
|
|
8398
8402
|
fields,
|
|
8399
8403
|
states: states2,
|
|
8400
8404
|
transitions: transitions2,
|
|
@@ -8446,7 +8450,7 @@ function extractAction(source, filename) {
|
|
|
8446
8450
|
slug,
|
|
8447
8451
|
name: humanName,
|
|
8448
8452
|
version: "0.1.0",
|
|
8449
|
-
category: "action",
|
|
8453
|
+
category: ["action"],
|
|
8450
8454
|
fields,
|
|
8451
8455
|
states,
|
|
8452
8456
|
transitions,
|
|
@@ -9883,7 +9887,7 @@ function applyConfig(ir, config) {
|
|
|
9883
9887
|
if (config.name) ir.name = config.name;
|
|
9884
9888
|
if (config.version) ir.version = config.version;
|
|
9885
9889
|
if (config.description !== void 0) ir.description = config.description;
|
|
9886
|
-
if (config.category) ir.category = config.category;
|
|
9890
|
+
if (config.category) ir.category = Array.isArray(config.category) ? config.category : [config.category];
|
|
9887
9891
|
if (!ir.metadata) ir.metadata = {};
|
|
9888
9892
|
ir.metadata.stable_id = "def-" + ir.slug;
|
|
9889
9893
|
ir.metadata.provenance = {
|
|
@@ -9899,7 +9903,7 @@ function createEmptyIR(config) {
|
|
|
9899
9903
|
name: config.name || "Project",
|
|
9900
9904
|
version: config.version || "0.1.0",
|
|
9901
9905
|
description: config.description,
|
|
9902
|
-
category: config.category || "workflow",
|
|
9906
|
+
category: Array.isArray(config.category) ? config.category : [config.category || "workflow"],
|
|
9903
9907
|
fields: [],
|
|
9904
9908
|
states: [{
|
|
9905
9909
|
name: "draft",
|
|
@@ -10057,8 +10061,10 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
|
|
|
10057
10061
|
if (isWorkflowFile(filename)) {
|
|
10058
10062
|
workflowIRs.push(ir);
|
|
10059
10063
|
} else if (isModelFile2(filename)) {
|
|
10060
|
-
|
|
10061
|
-
|
|
10064
|
+
const cat = ir.category;
|
|
10065
|
+
const isDefault = !cat || cat === "workflow" || Array.isArray(cat) && cat.length === 1 && cat[0] === "workflow";
|
|
10066
|
+
if (isDefault) {
|
|
10067
|
+
ir.category = ["data"];
|
|
10062
10068
|
}
|
|
10063
10069
|
modelIRs.push(ir);
|
|
10064
10070
|
} else if (isServerActionFile2(filename)) {
|
|
@@ -12856,7 +12862,8 @@ function decompileProject(definition, options) {
|
|
|
12856
12862
|
...child,
|
|
12857
12863
|
experience: child.views?.default
|
|
12858
12864
|
};
|
|
12859
|
-
|
|
12865
|
+
const childCatArr = Array.isArray(child.category) ? child.category : [child.category];
|
|
12866
|
+
if (childCatArr.includes("data") && child.fields.length > 0 && !options?.skipModels) {
|
|
12860
12867
|
let childModelContent = generateModelFile(childSlug, child.fields);
|
|
12861
12868
|
if (child.states.length > 0) {
|
|
12862
12869
|
childModelContent += generateStateEnum(childSlug, child.states);
|
|
@@ -13117,7 +13124,8 @@ function compareIR(original, roundTripped) {
|
|
|
13117
13124
|
const diffs = [];
|
|
13118
13125
|
comparePrimitive(diffs, "slug", original.slug, roundTripped.slug);
|
|
13119
13126
|
comparePrimitive(diffs, "version", original.version, roundTripped.version);
|
|
13120
|
-
|
|
13127
|
+
const normCat = (c) => JSON.stringify(Array.isArray(c) ? c : c ? [c] : []);
|
|
13128
|
+
comparePrimitive(diffs, "category", normCat(original.category), normCat(roundTripped.category));
|
|
13121
13129
|
compareFields(diffs, original.fields, roundTripped.fields);
|
|
13122
13130
|
compareStates(diffs, original.states, roundTripped.states);
|
|
13123
13131
|
compareTransitions(diffs, original.transitions, roundTripped.transitions);
|
|
@@ -13334,7 +13342,7 @@ function mindmatrixReact(options) {
|
|
|
13334
13342
|
slug: ir.slug,
|
|
13335
13343
|
name: ir.name,
|
|
13336
13344
|
version: ir.version,
|
|
13337
|
-
category: ir.category || "workflow",
|
|
13345
|
+
category: ir.category || ["workflow"],
|
|
13338
13346
|
fields: ir.fields || [],
|
|
13339
13347
|
states: ir.states || [],
|
|
13340
13348
|
transitions: ir.transitions || [],
|
|
@@ -13919,425 +13927,6 @@ async function startWatchMode(options) {
|
|
|
13919
13927
|
});
|
|
13920
13928
|
}
|
|
13921
13929
|
|
|
13922
|
-
// src/cli/local-server.ts
|
|
13923
|
-
var http = __toESM(require("http"));
|
|
13924
|
-
var import_node_crypto = require("crypto");
|
|
13925
|
-
var MemoryStore = class {
|
|
13926
|
-
constructor() {
|
|
13927
|
-
this.definitions = /* @__PURE__ */ new Map();
|
|
13928
|
-
this.instances = /* @__PURE__ */ new Map();
|
|
13929
|
-
this.slugIndex = /* @__PURE__ */ new Map();
|
|
13930
|
-
}
|
|
13931
|
-
// slug → id
|
|
13932
|
-
// ── Definitions ──────────────────────────────────────────────────────
|
|
13933
|
-
createDefinition(input) {
|
|
13934
|
-
if (this.slugIndex.has(input.slug)) {
|
|
13935
|
-
const existing = this.definitions.get(this.slugIndex.get(input.slug));
|
|
13936
|
-
if (existing) return existing;
|
|
13937
|
-
}
|
|
13938
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
13939
|
-
const def = {
|
|
13940
|
-
id: input.id ?? (0, import_node_crypto.randomUUID)(),
|
|
13941
|
-
slug: input.slug,
|
|
13942
|
-
name: input.name,
|
|
13943
|
-
version: input.version ?? "1.0.0",
|
|
13944
|
-
description: input.description ?? null,
|
|
13945
|
-
category: input.category ?? "workflow",
|
|
13946
|
-
fields: input.fields ?? [],
|
|
13947
|
-
states: input.states ?? [],
|
|
13948
|
-
transitions: input.transitions ?? [],
|
|
13949
|
-
roles: input.roles ?? [],
|
|
13950
|
-
experience: input.experience ?? null,
|
|
13951
|
-
metadata: input.metadata ?? {},
|
|
13952
|
-
child_definitions: input.child_definitions ?? [],
|
|
13953
|
-
is_immutable: input.is_immutable ?? false,
|
|
13954
|
-
tags: input.tags ?? [],
|
|
13955
|
-
inline_tags: input.inline_tags ?? [],
|
|
13956
|
-
created_at: now,
|
|
13957
|
-
updated_at: now
|
|
13958
|
-
};
|
|
13959
|
-
this.definitions.set(def.id, def);
|
|
13960
|
-
this.slugIndex.set(def.slug, def.id);
|
|
13961
|
-
return def;
|
|
13962
|
-
}
|
|
13963
|
-
getDefinition(idOrSlug) {
|
|
13964
|
-
const byId = this.definitions.get(idOrSlug);
|
|
13965
|
-
if (byId) return byId;
|
|
13966
|
-
const id = this.slugIndex.get(idOrSlug);
|
|
13967
|
-
if (id) return this.definitions.get(id);
|
|
13968
|
-
return void 0;
|
|
13969
|
-
}
|
|
13970
|
-
listDefinitions(opts) {
|
|
13971
|
-
let items = Array.from(this.definitions.values());
|
|
13972
|
-
if (opts?.category) {
|
|
13973
|
-
items = items.filter((d) => d.category === opts.category);
|
|
13974
|
-
}
|
|
13975
|
-
const total = items.length;
|
|
13976
|
-
const offset = opts?.offset ?? 0;
|
|
13977
|
-
const limit = opts?.limit ?? 50;
|
|
13978
|
-
items = items.slice(offset, offset + limit);
|
|
13979
|
-
return { items, total };
|
|
13980
|
-
}
|
|
13981
|
-
patchDefinition(id, patch) {
|
|
13982
|
-
const def = this.definitions.get(id);
|
|
13983
|
-
if (!def) return void 0;
|
|
13984
|
-
Object.assign(def, patch, { updated_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
13985
|
-
return def;
|
|
13986
|
-
}
|
|
13987
|
-
deleteDefinition(id) {
|
|
13988
|
-
const def = this.definitions.get(id);
|
|
13989
|
-
if (!def) return false;
|
|
13990
|
-
this.slugIndex.delete(def.slug);
|
|
13991
|
-
this.definitions.delete(id);
|
|
13992
|
-
return true;
|
|
13993
|
-
}
|
|
13994
|
-
// ── Instances ────────────────────────────────────────────────────────
|
|
13995
|
-
createInstance(input) {
|
|
13996
|
-
const def = this.getDefinition(input.definition_id) ?? this.getDefinition(input.definition_slug);
|
|
13997
|
-
if (!def) return null;
|
|
13998
|
-
const initialState = def.states.find((s) => s.type === "START" || s.type === "initial");
|
|
13999
|
-
const stateName = initialState?.name ?? "initial";
|
|
14000
|
-
const stateData = {};
|
|
14001
|
-
for (const field of def.fields) {
|
|
14002
|
-
if (field.default_value !== void 0) {
|
|
14003
|
-
stateData[field.name] = field.default_value;
|
|
14004
|
-
}
|
|
14005
|
-
}
|
|
14006
|
-
Object.assign(stateData, input.state_data ?? {});
|
|
14007
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14008
|
-
const inst = {
|
|
14009
|
-
id: (0, import_node_crypto.randomUUID)(),
|
|
14010
|
-
definition_id: def.id,
|
|
14011
|
-
definition_slug: def.slug,
|
|
14012
|
-
current_state: stateName,
|
|
14013
|
-
state_data: stateData,
|
|
14014
|
-
execution_lock_version: 0,
|
|
14015
|
-
event_log: [{
|
|
14016
|
-
event_type: "transition",
|
|
14017
|
-
message: `Instance created in state '${stateName}'`,
|
|
14018
|
-
timestamp: now
|
|
14019
|
-
}],
|
|
14020
|
-
created_at: now,
|
|
14021
|
-
updated_at: now
|
|
14022
|
-
};
|
|
14023
|
-
this.instances.set(inst.id, inst);
|
|
14024
|
-
return inst;
|
|
14025
|
-
}
|
|
14026
|
-
getInstance(id) {
|
|
14027
|
-
return this.instances.get(id);
|
|
14028
|
-
}
|
|
14029
|
-
listInstances(opts) {
|
|
14030
|
-
let items = Array.from(this.instances.values());
|
|
14031
|
-
if (opts?.definition_id) {
|
|
14032
|
-
items = items.filter((i) => i.definition_id === opts.definition_id);
|
|
14033
|
-
}
|
|
14034
|
-
const total = items.length;
|
|
14035
|
-
const offset = opts?.offset ?? 0;
|
|
14036
|
-
const limit = opts?.limit ?? 50;
|
|
14037
|
-
items = items.slice(offset, offset + limit);
|
|
14038
|
-
return { items, total };
|
|
14039
|
-
}
|
|
14040
|
-
// ── Execute Action (Transition) ──────────────────────────────────────
|
|
14041
|
-
executeAction(input) {
|
|
14042
|
-
const def = this.getDefinition(input.definition_id);
|
|
14043
|
-
if (!def) return { success: false, error: "Definition not found" };
|
|
14044
|
-
let inst;
|
|
14045
|
-
if (input.instance_id) {
|
|
14046
|
-
const existing = this.instances.get(input.instance_id);
|
|
14047
|
-
if (!existing) return { success: false, error: "Instance not found" };
|
|
14048
|
-
inst = existing;
|
|
14049
|
-
} else {
|
|
14050
|
-
const created = this.createInstance({
|
|
14051
|
-
definition_id: def.id,
|
|
14052
|
-
definition_slug: def.slug,
|
|
14053
|
-
state_data: input.payload
|
|
14054
|
-
});
|
|
14055
|
-
if (!created) return { success: false, error: "Failed to create instance" };
|
|
14056
|
-
inst = created;
|
|
14057
|
-
}
|
|
14058
|
-
if (input.payload && input.instance_id) {
|
|
14059
|
-
Object.assign(inst.state_data, input.payload);
|
|
14060
|
-
}
|
|
14061
|
-
const transition = def.transitions.find((t27) => t27.name === input.action_name && t27.from.includes(inst.current_state));
|
|
14062
|
-
if (!transition) {
|
|
14063
|
-
return {
|
|
14064
|
-
success: false,
|
|
14065
|
-
instance_id: inst.id,
|
|
14066
|
-
from_state: inst.current_state,
|
|
14067
|
-
to_state: null,
|
|
14068
|
-
state_data: inst.state_data,
|
|
14069
|
-
error: `No transition '${input.action_name}' from state '${inst.current_state}'`
|
|
14070
|
-
};
|
|
14071
|
-
}
|
|
14072
|
-
const fromState = inst.current_state;
|
|
14073
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14074
|
-
const events = [];
|
|
14075
|
-
let lastEvalResult = null;
|
|
14076
|
-
events.push({ event_type: "transition", message: `Transition '${transition.name}' started: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
14077
|
-
for (const action of transition.actions ?? []) {
|
|
14078
|
-
try {
|
|
14079
|
-
if (action.type === "set_field") {
|
|
14080
|
-
const field = action.config?.field;
|
|
14081
|
-
if (action.config?.expression) {
|
|
14082
|
-
const expr = action.config.expression;
|
|
14083
|
-
const result = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
14084
|
-
inst.state_data[field] = result;
|
|
14085
|
-
} else if (action.config?.value !== void 0) {
|
|
14086
|
-
inst.state_data[field] = action.config.value;
|
|
14087
|
-
}
|
|
14088
|
-
events.push({ event_type: "action_executed", message: `transition action 'set_field' succeeded`, timestamp: now });
|
|
14089
|
-
} else if (action.type === "eval") {
|
|
14090
|
-
const expr = action.config?.expression;
|
|
14091
|
-
lastEvalResult = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
14092
|
-
events.push({ event_type: "action_executed", message: `transition action 'eval' succeeded`, timestamp: now });
|
|
14093
|
-
} else {
|
|
14094
|
-
events.push({ event_type: "action_executed", message: `transition action '${action.type}' succeeded (no-op in local mode)`, timestamp: now });
|
|
14095
|
-
}
|
|
14096
|
-
} catch (err) {
|
|
14097
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
14098
|
-
events.push({ event_type: "action_failed", message: `transition action '${action.type}' failed: ${msg}`, timestamp: now });
|
|
14099
|
-
return {
|
|
14100
|
-
success: false,
|
|
14101
|
-
instance_id: inst.id,
|
|
14102
|
-
from_state: fromState,
|
|
14103
|
-
to_state: null,
|
|
14104
|
-
state_data: inst.state_data,
|
|
14105
|
-
event_log: events,
|
|
14106
|
-
error: `transition action failed: ${msg}`
|
|
14107
|
-
};
|
|
14108
|
-
}
|
|
14109
|
-
}
|
|
14110
|
-
inst.current_state = transition.to;
|
|
14111
|
-
inst.execution_lock_version++;
|
|
14112
|
-
inst.updated_at = now;
|
|
14113
|
-
events.push({ event_type: "transition", message: `State changed: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
14114
|
-
inst.event_log.push(...events);
|
|
14115
|
-
return {
|
|
14116
|
-
success: true,
|
|
14117
|
-
instance_id: inst.id,
|
|
14118
|
-
from_state: fromState,
|
|
14119
|
-
to_state: transition.to,
|
|
14120
|
-
state_data: inst.state_data,
|
|
14121
|
-
result: lastEvalResult,
|
|
14122
|
-
event_log: events
|
|
14123
|
-
};
|
|
14124
|
-
}
|
|
14125
|
-
/**
|
|
14126
|
-
* Minimal expression evaluator for local dev mode.
|
|
14127
|
-
* Handles: field references, arithmetic, string literals, simple comparisons.
|
|
14128
|
-
* Does NOT handle: while loops, if/else, function calls, multi-statement blocks.
|
|
14129
|
-
* For full evaluation, use mm-napi when available.
|
|
14130
|
-
*/
|
|
14131
|
-
evaluateSimpleExpression(expr, context) {
|
|
14132
|
-
if (context[expr] !== void 0) return context[expr];
|
|
14133
|
-
const arithMatch = expr.match(/^(\w+)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/);
|
|
14134
|
-
if (arithMatch) {
|
|
14135
|
-
const [, field, op, numStr] = arithMatch;
|
|
14136
|
-
const left = Number(context[field] ?? 0);
|
|
14137
|
-
const right = Number(numStr);
|
|
14138
|
-
switch (op) {
|
|
14139
|
-
case "+":
|
|
14140
|
-
return left + right;
|
|
14141
|
-
case "-":
|
|
14142
|
-
return left - right;
|
|
14143
|
-
case "*":
|
|
14144
|
-
return left * right;
|
|
14145
|
-
case "/":
|
|
14146
|
-
return right !== 0 ? left / right : 0;
|
|
14147
|
-
}
|
|
14148
|
-
}
|
|
14149
|
-
if (/^\d+(\.\d+)?$/.test(expr.trim())) {
|
|
14150
|
-
return Number(expr.trim());
|
|
14151
|
-
}
|
|
14152
|
-
const strMatch = expr.match(/^["'](.*)["']$/);
|
|
14153
|
-
if (strMatch) return strMatch[1];
|
|
14154
|
-
try {
|
|
14155
|
-
const keys = Object.keys(context);
|
|
14156
|
-
const values = Object.values(context);
|
|
14157
|
-
const fn = new Function(...keys, `"use strict"; return (${expr});`);
|
|
14158
|
-
return fn(...values);
|
|
14159
|
-
} catch {
|
|
14160
|
-
return null;
|
|
14161
|
-
}
|
|
14162
|
-
}
|
|
14163
|
-
};
|
|
14164
|
-
async function startLocalServer(options = {}) {
|
|
14165
|
-
const { port = 4200, noAuth = true } = options;
|
|
14166
|
-
const store = new MemoryStore();
|
|
14167
|
-
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
14168
|
-
function json(res, status, body) {
|
|
14169
|
-
const data = JSON.stringify(body);
|
|
14170
|
-
res.writeHead(status, {
|
|
14171
|
-
"Content-Type": "application/json",
|
|
14172
|
-
"Access-Control-Allow-Origin": "*",
|
|
14173
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
14174
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
14175
|
-
"Content-Length": Buffer.byteLength(data)
|
|
14176
|
-
});
|
|
14177
|
-
res.end(data);
|
|
14178
|
-
}
|
|
14179
|
-
function readBody(req) {
|
|
14180
|
-
return new Promise((resolve3, reject) => {
|
|
14181
|
-
const chunks = [];
|
|
14182
|
-
req.on("data", (chunk) => chunks.push(chunk));
|
|
14183
|
-
req.on("end", () => resolve3(Buffer.concat(chunks).toString()));
|
|
14184
|
-
req.on("error", reject);
|
|
14185
|
-
});
|
|
14186
|
-
}
|
|
14187
|
-
function parseQuery(url) {
|
|
14188
|
-
const idx = url.indexOf("?");
|
|
14189
|
-
if (idx === -1) return {};
|
|
14190
|
-
const params = {};
|
|
14191
|
-
const qs = url.slice(idx + 1);
|
|
14192
|
-
for (const pair of qs.split("&")) {
|
|
14193
|
-
const [k, v] = pair.split("=");
|
|
14194
|
-
if (k) params[decodeURIComponent(k)] = decodeURIComponent(v ?? "");
|
|
14195
|
-
}
|
|
14196
|
-
return params;
|
|
14197
|
-
}
|
|
14198
|
-
const server = http.createServer(async (req, res) => {
|
|
14199
|
-
const method = req.method?.toUpperCase() ?? "GET";
|
|
14200
|
-
const rawUrl = req.url ?? "/";
|
|
14201
|
-
const queryStart = rawUrl.indexOf("?");
|
|
14202
|
-
const path = queryStart >= 0 ? rawUrl.slice(0, queryStart) : rawUrl;
|
|
14203
|
-
const query = parseQuery(rawUrl);
|
|
14204
|
-
if (method === "OPTIONS") {
|
|
14205
|
-
res.writeHead(204, {
|
|
14206
|
-
"Access-Control-Allow-Origin": "*",
|
|
14207
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
14208
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
14209
|
-
"Access-Control-Max-Age": "86400"
|
|
14210
|
-
});
|
|
14211
|
-
res.end();
|
|
14212
|
-
return;
|
|
14213
|
-
}
|
|
14214
|
-
try {
|
|
14215
|
-
if (path === "/health" && method === "GET") {
|
|
14216
|
-
return json(res, 200, {
|
|
14217
|
-
status: "ok",
|
|
14218
|
-
service: "mm-local-dev",
|
|
14219
|
-
mode: "in-memory",
|
|
14220
|
-
started_at: startedAt,
|
|
14221
|
-
definitions: store.definitions.size,
|
|
14222
|
-
instances: store.instances.size
|
|
14223
|
-
});
|
|
14224
|
-
}
|
|
14225
|
-
if (path === "/api/v1/auth/login" && (method === "POST" || method === "GET")) {
|
|
14226
|
-
return json(res, 200, {
|
|
14227
|
-
token: "dev-token-local",
|
|
14228
|
-
user: {
|
|
14229
|
-
id: "dev-user-001",
|
|
14230
|
-
email: "dev@localhost",
|
|
14231
|
-
role: "admin",
|
|
14232
|
-
name: "Local Developer"
|
|
14233
|
-
}
|
|
14234
|
-
});
|
|
14235
|
-
}
|
|
14236
|
-
if (path === "/api/v1/workflow/definitions" && method === "GET") {
|
|
14237
|
-
const result = store.listDefinitions({
|
|
14238
|
-
category: query.category,
|
|
14239
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
14240
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
14241
|
-
});
|
|
14242
|
-
if (query.slug) {
|
|
14243
|
-
const def = store.getDefinition(query.slug);
|
|
14244
|
-
return json(res, 200, { items: def ? [def] : [], total: def ? 1 : 0 });
|
|
14245
|
-
}
|
|
14246
|
-
return json(res, 200, result);
|
|
14247
|
-
}
|
|
14248
|
-
const defMatch = path.match(/^\/api\/v1\/workflow\/definitions\/([^/]+)$/);
|
|
14249
|
-
if (defMatch && method === "GET") {
|
|
14250
|
-
const def = store.getDefinition(defMatch[1]);
|
|
14251
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
14252
|
-
return json(res, 200, def);
|
|
14253
|
-
}
|
|
14254
|
-
if (path === "/api/v1/workflow/definitions" && method === "POST") {
|
|
14255
|
-
const body = JSON.parse(await readBody(req));
|
|
14256
|
-
const def = store.createDefinition(body);
|
|
14257
|
-
return json(res, 201, def);
|
|
14258
|
-
}
|
|
14259
|
-
if (defMatch && method === "PATCH") {
|
|
14260
|
-
const body = JSON.parse(await readBody(req));
|
|
14261
|
-
const updated = store.patchDefinition(defMatch[1], body);
|
|
14262
|
-
if (!updated) return json(res, 404, { error: "Not found" });
|
|
14263
|
-
return json(res, 200, updated);
|
|
14264
|
-
}
|
|
14265
|
-
if (defMatch && method === "DELETE") {
|
|
14266
|
-
const deleted = store.deleteDefinition(defMatch[1]);
|
|
14267
|
-
if (!deleted) return json(res, 404, { error: "Not found" });
|
|
14268
|
-
return json(res, 204, null);
|
|
14269
|
-
}
|
|
14270
|
-
if (path === "/api/v1/workflow/instances" && method === "GET") {
|
|
14271
|
-
const result = store.listInstances({
|
|
14272
|
-
definition_id: query.definition_id,
|
|
14273
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
14274
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
14275
|
-
});
|
|
14276
|
-
return json(res, 200, result);
|
|
14277
|
-
}
|
|
14278
|
-
if (path === "/api/v1/workflow/instances" && method === "POST") {
|
|
14279
|
-
const body = JSON.parse(await readBody(req));
|
|
14280
|
-
const inst = store.createInstance(body);
|
|
14281
|
-
if (!inst) return json(res, 404, { error: "Definition not found" });
|
|
14282
|
-
return json(res, 201, inst);
|
|
14283
|
-
}
|
|
14284
|
-
const instMatch = path.match(/^\/api\/v1\/workflow\/instances\/([^/]+)$/);
|
|
14285
|
-
if (instMatch && method === "GET") {
|
|
14286
|
-
const inst = store.getInstance(instMatch[1]);
|
|
14287
|
-
if (!inst) return json(res, 404, { error: "Not found" });
|
|
14288
|
-
return json(res, 200, inst);
|
|
14289
|
-
}
|
|
14290
|
-
if (path === "/api/v1/workflow/execute-action" && method === "POST") {
|
|
14291
|
-
const body = JSON.parse(await readBody(req));
|
|
14292
|
-
const result = store.executeAction(body);
|
|
14293
|
-
return json(res, 200, result);
|
|
14294
|
-
}
|
|
14295
|
-
const dataMatch = path.match(/^\/api\/v1\/data\/([^/]+)$/);
|
|
14296
|
-
if (dataMatch && method === "GET") {
|
|
14297
|
-
const def = store.getDefinition(dataMatch[1]);
|
|
14298
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
14299
|
-
const instances = store.listInstances({ definition_id: def.id });
|
|
14300
|
-
return json(res, 200, instances);
|
|
14301
|
-
}
|
|
14302
|
-
if (path.startsWith("/api/v1/")) {
|
|
14303
|
-
return json(res, 501, { error: "Not implemented in local dev mode", path, method });
|
|
14304
|
-
}
|
|
14305
|
-
return json(res, 404, { error: "Not found", path });
|
|
14306
|
-
} catch (err) {
|
|
14307
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14308
|
-
console.error(`[mm-local] ${method} ${path} \u2014 Error: ${message}`);
|
|
14309
|
-
return json(res, 500, { error: message });
|
|
14310
|
-
}
|
|
14311
|
-
});
|
|
14312
|
-
return new Promise((resolve3, reject) => {
|
|
14313
|
-
server.on("error", (err) => {
|
|
14314
|
-
if (err.code === "EADDRINUSE") {
|
|
14315
|
-
reject(new Error(`Port ${port} is already in use. Is another server running?`));
|
|
14316
|
-
} else {
|
|
14317
|
-
reject(err);
|
|
14318
|
-
}
|
|
14319
|
-
});
|
|
14320
|
-
server.listen(port, () => {
|
|
14321
|
-
console.log(`[mm-local] Local API server running at http://localhost:${port}`);
|
|
14322
|
-
console.log(`[mm-local] Mode: in-memory (data lost on restart)`);
|
|
14323
|
-
console.log(`[mm-local] Auth: disabled (all requests accepted)`);
|
|
14324
|
-
resolve3({
|
|
14325
|
-
server,
|
|
14326
|
-
port,
|
|
14327
|
-
store,
|
|
14328
|
-
async close() {
|
|
14329
|
-
return new Promise((res) => {
|
|
14330
|
-
server.close(() => {
|
|
14331
|
-
console.log("[mm-local] Local API server stopped");
|
|
14332
|
-
res();
|
|
14333
|
-
});
|
|
14334
|
-
});
|
|
14335
|
-
}
|
|
14336
|
-
});
|
|
14337
|
-
});
|
|
14338
|
-
});
|
|
14339
|
-
}
|
|
14340
|
-
|
|
14341
13930
|
// src/dev-server.ts
|
|
14342
13931
|
var currentErrors = null;
|
|
14343
13932
|
function escapeHtml(s) {
|
|
@@ -14514,34 +14103,33 @@ async function createDevServer(options = {}) {
|
|
|
14514
14103
|
open = false
|
|
14515
14104
|
} = options;
|
|
14516
14105
|
const clients = /* @__PURE__ */ new Set();
|
|
14517
|
-
let localServer = null;
|
|
14518
14106
|
let apiUrl;
|
|
14519
|
-
|
|
14520
|
-
|
|
14521
|
-
|
|
14522
|
-
|
|
14523
|
-
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
|
|
14528
|
-
apiUrl = defaultRemote;
|
|
14529
|
-
} else {
|
|
14530
|
-
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
14531
|
-
if (localHealth.ok) {
|
|
14532
|
-
apiUrl = "http://localhost:4200/api/v1";
|
|
14107
|
+
if (rawApiUrl === "local" || rawApiUrl === "auto") {
|
|
14108
|
+
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
14109
|
+
if (localHealth.ok) {
|
|
14110
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
14111
|
+
} else if (rawApiUrl === "auto") {
|
|
14112
|
+
const defaultRemote = "https://dev.mindmatrix.club/api/v1";
|
|
14113
|
+
const remoteHealth = await checkBackendHealth(defaultRemote);
|
|
14114
|
+
if (remoteHealth.ok) {
|
|
14115
|
+
apiUrl = defaultRemote;
|
|
14533
14116
|
} else {
|
|
14534
|
-
console.
|
|
14535
|
-
|
|
14117
|
+
console.error("[mm-dev] No backend detected. Start the engine first:");
|
|
14118
|
+
console.error(" mmrc dev (auto-starts engine)");
|
|
14119
|
+
console.error(" mmrc engine start (manual start)");
|
|
14120
|
+
console.error("[mm-dev] Or specify a remote API: mmrc dev --api-url https://...");
|
|
14536
14121
|
apiUrl = "http://localhost:4200/api/v1";
|
|
14537
|
-
isLocalMode = true;
|
|
14538
14122
|
}
|
|
14123
|
+
} else {
|
|
14124
|
+
console.error("[mm-dev] Local engine not running on port 4200.");
|
|
14125
|
+
console.error(" Start it with: mmrc dev (or mmrc engine start)");
|
|
14126
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
14539
14127
|
}
|
|
14540
14128
|
} else {
|
|
14541
14129
|
apiUrl = rawApiUrl;
|
|
14542
14130
|
}
|
|
14543
|
-
const token =
|
|
14544
|
-
const health =
|
|
14131
|
+
const token = await resolveDevToken(apiUrl, explicitToken);
|
|
14132
|
+
const health = await checkBackendHealth(apiUrl);
|
|
14545
14133
|
let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
|
|
14546
14134
|
if (token && health.ok) {
|
|
14547
14135
|
const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
|
|
@@ -14601,63 +14189,163 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14601
14189
|
`;
|
|
14602
14190
|
}
|
|
14603
14191
|
};
|
|
14604
|
-
const
|
|
14192
|
+
const { existsSync: fsExists } = await import("fs");
|
|
14193
|
+
const projectIndexPath = require("path").join(process.cwd(), "index.html");
|
|
14194
|
+
const hasProjectIndex = fsExists(projectIndexPath);
|
|
14195
|
+
if (!hasProjectIndex) {
|
|
14196
|
+
const { writeFileSync: fsWrite } = await import("fs");
|
|
14197
|
+
fsWrite(projectIndexPath, `<!DOCTYPE html>
|
|
14605
14198
|
<html lang="en">
|
|
14606
14199
|
<head>
|
|
14607
14200
|
<meta charset="UTF-8">
|
|
14608
14201
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
14609
14202
|
<title>MindMatrix Dev</title>
|
|
14610
|
-
<style>
|
|
14611
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
14612
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #fafafa; color: #111; }
|
|
14613
|
-
#root { min-height: 100vh; }
|
|
14614
|
-
.mm-loading { display: flex; align-items: center; justify-content: center; min-height: 100vh; flex-direction: column; gap: 12px; }
|
|
14615
|
-
.mm-loading h1 { font-size: 20px; font-weight: 600; color: #333; }
|
|
14616
|
-
.mm-loading p { color: #888; font-size: 14px; }
|
|
14617
|
-
</style>
|
|
14618
14203
|
</head>
|
|
14619
14204
|
<body>
|
|
14620
|
-
<div id="root">
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14205
|
+
<div id="root"></div>
|
|
14206
|
+
<script type="module" src="/__mm_dev_entry.tsx"></script>
|
|
14207
|
+
</body>
|
|
14208
|
+
</html>`, "utf-8");
|
|
14209
|
+
}
|
|
14210
|
+
const devEntryPlugin = {
|
|
14211
|
+
name: "mindmatrix-dev-entry",
|
|
14212
|
+
resolveId(id) {
|
|
14213
|
+
if (id === "/__mm_dev_entry.tsx") return id;
|
|
14214
|
+
return null;
|
|
14215
|
+
},
|
|
14216
|
+
load(id) {
|
|
14217
|
+
if (id !== "/__mm_dev_entry.tsx") return null;
|
|
14218
|
+
return `
|
|
14219
|
+
import React, { useState, useEffect } from 'react';
|
|
14220
|
+
import { createRoot } from 'react-dom/client';
|
|
14221
|
+
import { DevPlayer } from '@mmapp/react/player';
|
|
14222
|
+
import { PlayerProvider, ExperienceRenderer, createApiResolver } from '@mmapp/react/player';
|
|
14223
|
+
|
|
14224
|
+
// Detect API base URL \u2014 proxy through dev server or use direct URL
|
|
14225
|
+
const API_BASE = window.location.origin + '/api/v1';
|
|
14226
|
+
const resolver = createApiResolver({ baseUrl: API_BASE, token: () => localStorage.getItem('auth_token') });
|
|
14227
|
+
|
|
14228
|
+
/**
|
|
14229
|
+
* Prepare experience tree for rendering.
|
|
14230
|
+
* Attaches metadata.dataSources to the root node and remaps
|
|
14231
|
+
* dataSource slugs to use definition-relative naming.
|
|
14232
|
+
*
|
|
14233
|
+
* @param definition - The main blueprint definition
|
|
14234
|
+
* @param allDefinitions - ALL definitions from the API (used for slug resolution)
|
|
14235
|
+
*/
|
|
14236
|
+
function prepareTree(definition, allDefinitions) {
|
|
14237
|
+
const exp = definition.experience;
|
|
14238
|
+
if (!exp || typeof exp !== 'object') return null;
|
|
14239
|
+
|
|
14240
|
+
const meta = definition.metadata || {};
|
|
14241
|
+
const dataSources = meta.dataSources || [];
|
|
14242
|
+
const mutationTargets = meta.mutationTargets || [];
|
|
14243
|
+
|
|
14244
|
+
// Build a slug map from ALL deployed definitions
|
|
14245
|
+
// This resolves bare model names (e.g. "item") to full slugs (e.g. "tutorial-1-item")
|
|
14246
|
+
const blueprintSlug = definition.slug || '';
|
|
14247
|
+
const allSlugs = (allDefinitions || []).map(d => d.slug).filter(Boolean);
|
|
14248
|
+
|
|
14249
|
+
function resolveSlug(bareSlug) {
|
|
14250
|
+
if (!bareSlug) return bareSlug;
|
|
14251
|
+
// Already a full slug (contains hyphen matching a known definition)
|
|
14252
|
+
if (allSlugs.includes(bareSlug)) return bareSlug;
|
|
14253
|
+
// Try blueprint-prefixed slug: "item" \u2192 "tutorial-1-item"
|
|
14254
|
+
const prefixed = blueprintSlug + '-' + bareSlug;
|
|
14255
|
+
if (allSlugs.includes(prefixed)) return prefixed;
|
|
14256
|
+
// Try matching by suffix across all definitions
|
|
14257
|
+
const match = allSlugs.find(s => s.endsWith('-' + bareSlug));
|
|
14258
|
+
if (match) return match;
|
|
14259
|
+
// Return original (will attempt as-is)
|
|
14260
|
+
return bareSlug;
|
|
14261
|
+
}
|
|
14262
|
+
|
|
14263
|
+
// Clone root node and attach dataSources
|
|
14264
|
+
const root = { ...exp };
|
|
14265
|
+
if (dataSources.length > 0 && !root.dataSources) {
|
|
14266
|
+
root.dataSources = dataSources.map(ds => ({
|
|
14267
|
+
...ds,
|
|
14268
|
+
slug: resolveSlug(ds.slug),
|
|
14269
|
+
}));
|
|
14270
|
+
}
|
|
14271
|
+
|
|
14272
|
+
// Remap mutation targets the same way
|
|
14273
|
+
if (mutationTargets.length > 0) {
|
|
14274
|
+
const resolvedTargets = mutationTargets.map(t => resolveSlug(t));
|
|
14275
|
+
root.config = { ...(root.config || {}), _mutationTargets: resolvedTargets };
|
|
14276
|
+
}
|
|
14277
|
+
|
|
14278
|
+
return root;
|
|
14279
|
+
}
|
|
14280
|
+
|
|
14281
|
+
function App() {
|
|
14282
|
+
const [tree, setTree] = useState(null);
|
|
14283
|
+
const [error, setError] = useState(null);
|
|
14284
|
+
|
|
14285
|
+
useEffect(() => {
|
|
14286
|
+
async function loadTree() {
|
|
14629
14287
|
try {
|
|
14630
|
-
const res = await fetch('/
|
|
14288
|
+
const res = await fetch(API_BASE + '/workflow/definitions');
|
|
14631
14289
|
const json = await res.json();
|
|
14632
14290
|
const items = json.items || json.data || [];
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
|
|
14646
|
-
|
|
14291
|
+
// Find the main blueprint definition (has experience tree)
|
|
14292
|
+
const main = items.find(d => d.experience && !(Array.isArray(d.category) ? d.category.includes('data') : d.category === 'data')) || items.find(d => d.experience) || items[0];
|
|
14293
|
+
if (main?.experience) {
|
|
14294
|
+
const prepared = prepareTree(main, items);
|
|
14295
|
+
if (prepared) {
|
|
14296
|
+
setTree(prepared);
|
|
14297
|
+
return;
|
|
14298
|
+
}
|
|
14299
|
+
}
|
|
14300
|
+
if (main) {
|
|
14301
|
+
// No experience tree \u2014 show definition info
|
|
14302
|
+
setTree({
|
|
14303
|
+
type: 'Stack',
|
|
14304
|
+
props: { style: { padding: 40, gap: 16 } },
|
|
14305
|
+
children: [
|
|
14306
|
+
{ type: 'Text', props: { children: main.name || main.slug, style: { fontSize: 24, fontWeight: 'bold' } } },
|
|
14307
|
+
{ type: 'Text', props: { children: (main.states?.length || 0) + ' states, ' + (main.fields?.length || 0) + ' fields', style: { color: '#666' } } },
|
|
14308
|
+
...items.map((d, i) => ({
|
|
14309
|
+
type: 'Card',
|
|
14310
|
+
props: { key: i, style: { padding: 16, border: '1px solid #ddd', borderRadius: 8 } },
|
|
14311
|
+
children: [
|
|
14312
|
+
{ type: 'Text', props: { children: d.name || d.slug, style: { fontWeight: 600 } } },
|
|
14313
|
+
{ type: 'Text', props: { children: 'slug: ' + d.slug + ' | ' + (d.states?.length || 0) + ' states', style: { fontSize: 13, color: '#888' } } },
|
|
14314
|
+
],
|
|
14315
|
+
})),
|
|
14316
|
+
],
|
|
14317
|
+
});
|
|
14318
|
+
}
|
|
14647
14319
|
} catch (e) {
|
|
14648
|
-
|
|
14320
|
+
setError(e.message);
|
|
14649
14321
|
}
|
|
14650
14322
|
}
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
|
|
14323
|
+
loadTree();
|
|
14324
|
+
}, []);
|
|
14325
|
+
|
|
14326
|
+
if (error) return React.createElement('div', { style: { padding: 40 } },
|
|
14327
|
+
React.createElement('h1', null, 'MindMatrix Dev'),
|
|
14328
|
+
React.createElement('p', { style: { color: '#c00' } }, 'Error: ' + error)
|
|
14329
|
+
);
|
|
14330
|
+
|
|
14331
|
+
if (!tree) return React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh' } },
|
|
14332
|
+
React.createElement('p', null, 'Loading...')
|
|
14333
|
+
);
|
|
14334
|
+
|
|
14335
|
+
// If tree has 'component' field, use ExperienceRenderer; otherwise legacy DevPlayer
|
|
14336
|
+
if (tree.component) {
|
|
14337
|
+
return React.createElement(PlayerProvider, { resolver },
|
|
14338
|
+
React.createElement(ExperienceRenderer, { tree, className: 'mm-experience-root' })
|
|
14339
|
+
);
|
|
14340
|
+
}
|
|
14341
|
+
|
|
14342
|
+
return React.createElement(DevPlayer, { tree, title: document.title || 'MindMatrix Dev' });
|
|
14343
|
+
}
|
|
14344
|
+
|
|
14345
|
+
createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
14346
|
+
`;
|
|
14347
|
+
}
|
|
14348
|
+
};
|
|
14661
14349
|
let deployInFlight = false;
|
|
14662
14350
|
const compileDeployPlugin = {
|
|
14663
14351
|
name: "mindmatrix-dev-compile-deploy",
|
|
@@ -14688,16 +14376,16 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14688
14376
|
}
|
|
14689
14377
|
};
|
|
14690
14378
|
const viteConfig = {
|
|
14691
|
-
//
|
|
14692
|
-
root:
|
|
14693
|
-
// Pre-bundle React
|
|
14379
|
+
// Use the blueprint directory as Vite root (has node_modules with React).
|
|
14380
|
+
root: process.cwd(),
|
|
14381
|
+
// Pre-bundle React and the player for fast dev startup.
|
|
14694
14382
|
optimizeDeps: { include: ["react", "react-dom/client"] },
|
|
14695
14383
|
server: {
|
|
14696
14384
|
port,
|
|
14697
14385
|
open,
|
|
14698
14386
|
host: true,
|
|
14699
14387
|
// Allow serving files from the real project directory (fs.allow).
|
|
14700
|
-
fs: { allow: [
|
|
14388
|
+
fs: { allow: [process.cwd(), ".."] },
|
|
14701
14389
|
proxy: {
|
|
14702
14390
|
"/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
|
|
14703
14391
|
"/health": { target: proxyTarget, changeOrigin: true, secure: true },
|
|
@@ -14707,6 +14395,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14707
14395
|
plugins: [
|
|
14708
14396
|
mindmatrixReact(pluginOpts),
|
|
14709
14397
|
compileDeployPlugin,
|
|
14398
|
+
devEntryPlugin,
|
|
14710
14399
|
devPlayerPlugin,
|
|
14711
14400
|
{ name: "mindmatrix-error-overlay", configureServer(server) {
|
|
14712
14401
|
server.middlewares.use(errorOverlayMiddleware());
|
|
@@ -14714,8 +14403,8 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14714
14403
|
],
|
|
14715
14404
|
logLevel: "warn"
|
|
14716
14405
|
};
|
|
14717
|
-
const { createServer
|
|
14718
|
-
const vite = await
|
|
14406
|
+
const { createServer } = await import("vite");
|
|
14407
|
+
const vite = await createServer(viteConfig);
|
|
14719
14408
|
await vite.listen();
|
|
14720
14409
|
const resolvedPort = vite.config.server.port ?? port;
|
|
14721
14410
|
if (enableWs && vite.httpServer) {
|
|
@@ -14733,7 +14422,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14733
14422
|
} catch {
|
|
14734
14423
|
}
|
|
14735
14424
|
}
|
|
14736
|
-
printBanner({ port: resolvedPort, apiUrl
|
|
14425
|
+
printBanner({ port: resolvedPort, apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
|
|
14737
14426
|
return {
|
|
14738
14427
|
vite,
|
|
14739
14428
|
port: resolvedPort,
|
|
@@ -14765,14 +14454,6 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14765
14454
|
clients.clear();
|
|
14766
14455
|
currentErrors = null;
|
|
14767
14456
|
await vite.close();
|
|
14768
|
-
if (localServer) {
|
|
14769
|
-
await localServer.close();
|
|
14770
|
-
}
|
|
14771
|
-
try {
|
|
14772
|
-
const { rmSync } = await import("fs");
|
|
14773
|
-
rmSync(devRoot, { recursive: true, force: true });
|
|
14774
|
-
} catch {
|
|
14775
|
-
}
|
|
14776
14457
|
}
|
|
14777
14458
|
};
|
|
14778
14459
|
}
|