@mmapp/react-compiler 0.1.0-alpha.18 → 0.1.0-alpha.20
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-4FP5DXY4.mjs +3456 -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-EYLOSECJ.mjs +544 -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-I6SSPILI.mjs +550 -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-U6F7CTHK.mjs +550 -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-XUQ5R6F3.mjs +213 -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 +329 -653
- package/dist/cli/index.mjs +9 -9
- package/dist/config-PL24KEWL.mjs +219 -0
- package/dist/deploy-VAHWALWB.mjs +9 -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 +205 -522
- 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 +210 -525
- package/dist/index.mjs +10 -9
- package/dist/init-2XLTUF7O.mjs +407 -0
- package/dist/init-7FJENUDK.mjs +407 -0
- package/dist/init-AVZJHZYY.mjs +538 -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-QCZYY4TW.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-5WJ4LW4U.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/mm-dev.db +0 -0
- package/package.json +2 -2
package/dist/dev-server.js
CHANGED
|
@@ -6468,7 +6468,8 @@ function convertOnEvent(sub) {
|
|
|
6468
6468
|
};
|
|
6469
6469
|
}
|
|
6470
6470
|
function emitIR(extracted) {
|
|
6471
|
-
const { slug, name, version, description, category, fields, states, transitions } = extracted;
|
|
6471
|
+
const { slug, name, version, description, category: rawCategory, fields, states, transitions } = extracted;
|
|
6472
|
+
const category = Array.isArray(rawCategory) ? rawCategory : [rawCategory];
|
|
6472
6473
|
const stateArray = Array.from(states.values());
|
|
6473
6474
|
if (stateArray.length === 0) {
|
|
6474
6475
|
stateArray.push({
|
|
@@ -6856,13 +6857,15 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
6856
6857
|
}
|
|
6857
6858
|
]
|
|
6858
6859
|
});
|
|
6859
|
-
const
|
|
6860
|
+
const rawCat = extracted.category;
|
|
6860
6861
|
let categoryArray;
|
|
6861
|
-
if (
|
|
6862
|
-
|
|
6862
|
+
if (Array.isArray(rawCat)) {
|
|
6863
|
+
categoryArray = rawCat;
|
|
6864
|
+
} else if (rawCat.includes("/")) {
|
|
6865
|
+
const [primary, ...tags] = rawCat.split("/");
|
|
6863
6866
|
categoryArray = (0, import_player_core.normalizeCategory)(primary, ...tags);
|
|
6864
6867
|
} else {
|
|
6865
|
-
categoryArray = [
|
|
6868
|
+
categoryArray = [rawCat];
|
|
6866
6869
|
}
|
|
6867
6870
|
return {
|
|
6868
6871
|
slug: ir.slug,
|
|
@@ -7009,7 +7012,7 @@ function compilerStateToWorkflow(state, metadata) {
|
|
|
7009
7012
|
name: metadata.name || "Workflow",
|
|
7010
7013
|
version: metadata.version || "0.1.0",
|
|
7011
7014
|
description: metadata.description,
|
|
7012
|
-
category: metadata.category || "workflow",
|
|
7015
|
+
category: metadata.categoryArray ? metadata.categoryArray : [metadata.category || "workflow"],
|
|
7013
7016
|
fields: state.fields || [],
|
|
7014
7017
|
states: state.states || /* @__PURE__ */ new Map(),
|
|
7015
7018
|
transitions: state.transitions || [],
|
|
@@ -7787,7 +7790,7 @@ function extractRouterWorkflow(pages, options = {}) {
|
|
|
7787
7790
|
name: "Router",
|
|
7788
7791
|
version: "1.0.0",
|
|
7789
7792
|
description: "Auto-derived router workflow from file-based routing",
|
|
7790
|
-
category: "router",
|
|
7793
|
+
category: ["router"],
|
|
7791
7794
|
fields,
|
|
7792
7795
|
states,
|
|
7793
7796
|
transitions,
|
|
@@ -7886,7 +7889,8 @@ function compileModel(filename, source, options = {}) {
|
|
|
7886
7889
|
parserOpts: { plugins: parserPlugins, attachComment: true }
|
|
7887
7890
|
});
|
|
7888
7891
|
const ir = babelResult?.metadata?.mindmatrixIR ?? createEmptyModelIR(interfaceName);
|
|
7889
|
-
|
|
7892
|
+
const catOverride = options.categoryOverride || annotation.category || "data";
|
|
7893
|
+
ir.category = Array.isArray(catOverride) ? catOverride : [catOverride];
|
|
7890
7894
|
if (options.slugOverride) {
|
|
7891
7895
|
ir.slug = options.slugOverride;
|
|
7892
7896
|
}
|
|
@@ -7950,7 +7954,7 @@ function createEmptyModelIR(interfaceName) {
|
|
|
7950
7954
|
name: interfaceName,
|
|
7951
7955
|
version: "1.0.0",
|
|
7952
7956
|
description: "Data model: " + interfaceName,
|
|
7953
|
-
category: "data",
|
|
7957
|
+
category: ["data"],
|
|
7954
7958
|
fields: [],
|
|
7955
7959
|
states: [{
|
|
7956
7960
|
name: "draft",
|
|
@@ -8118,7 +8122,7 @@ function buildRouterIR(routes, layouts, allParams, slugPrefix) {
|
|
|
8118
8122
|
name: "Router",
|
|
8119
8123
|
version: "1.0.0",
|
|
8120
8124
|
description: "Auto-generated router from app/ directory structure",
|
|
8121
|
-
category: "router",
|
|
8125
|
+
category: ["router"],
|
|
8122
8126
|
fields,
|
|
8123
8127
|
states,
|
|
8124
8128
|
transitions,
|
|
@@ -8367,7 +8371,7 @@ function extractAction(source, filename) {
|
|
|
8367
8371
|
slug,
|
|
8368
8372
|
name: humanName,
|
|
8369
8373
|
version: "0.1.0",
|
|
8370
|
-
category: "action",
|
|
8374
|
+
category: ["action"],
|
|
8371
8375
|
fields,
|
|
8372
8376
|
states: states2,
|
|
8373
8377
|
transitions: transitions2,
|
|
@@ -8419,7 +8423,7 @@ function extractAction(source, filename) {
|
|
|
8419
8423
|
slug,
|
|
8420
8424
|
name: humanName,
|
|
8421
8425
|
version: "0.1.0",
|
|
8422
|
-
category: "action",
|
|
8426
|
+
category: ["action"],
|
|
8423
8427
|
fields,
|
|
8424
8428
|
states,
|
|
8425
8429
|
transitions,
|
|
@@ -9856,7 +9860,7 @@ function applyConfig(ir, config) {
|
|
|
9856
9860
|
if (config.name) ir.name = config.name;
|
|
9857
9861
|
if (config.version) ir.version = config.version;
|
|
9858
9862
|
if (config.description !== void 0) ir.description = config.description;
|
|
9859
|
-
if (config.category) ir.category = config.category;
|
|
9863
|
+
if (config.category) ir.category = Array.isArray(config.category) ? config.category : [config.category];
|
|
9860
9864
|
if (!ir.metadata) ir.metadata = {};
|
|
9861
9865
|
ir.metadata.stable_id = "def-" + ir.slug;
|
|
9862
9866
|
ir.metadata.provenance = {
|
|
@@ -9872,7 +9876,7 @@ function createEmptyIR(config) {
|
|
|
9872
9876
|
name: config.name || "Project",
|
|
9873
9877
|
version: config.version || "0.1.0",
|
|
9874
9878
|
description: config.description,
|
|
9875
|
-
category: config.category || "workflow",
|
|
9879
|
+
category: Array.isArray(config.category) ? config.category : [config.category || "workflow"],
|
|
9876
9880
|
fields: [],
|
|
9877
9881
|
states: [{
|
|
9878
9882
|
name: "draft",
|
|
@@ -10030,8 +10034,10 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
|
|
|
10030
10034
|
if (isWorkflowFile(filename)) {
|
|
10031
10035
|
workflowIRs.push(ir);
|
|
10032
10036
|
} else if (isModelFile2(filename)) {
|
|
10033
|
-
|
|
10034
|
-
|
|
10037
|
+
const cat = ir.category;
|
|
10038
|
+
const isDefault = !cat || cat === "workflow" || Array.isArray(cat) && cat.length === 1 && cat[0] === "workflow";
|
|
10039
|
+
if (isDefault) {
|
|
10040
|
+
ir.category = ["data"];
|
|
10035
10041
|
}
|
|
10036
10042
|
modelIRs.push(ir);
|
|
10037
10043
|
} else if (isServerActionFile2(filename)) {
|
|
@@ -10843,14 +10849,12 @@ async function deploy(options) {
|
|
|
10843
10849
|
}
|
|
10844
10850
|
async function fetchExistingDefinition(apiUrl, token, slug) {
|
|
10845
10851
|
try {
|
|
10846
|
-
const res = await fetch(`${apiUrl}/workflow/definitions
|
|
10852
|
+
const res = await fetch(`${apiUrl}/workflow/definitions/${encodeURIComponent(slug)}`, {
|
|
10847
10853
|
headers: { Authorization: `Bearer ${token}` }
|
|
10848
10854
|
});
|
|
10849
10855
|
if (!res.ok) return null;
|
|
10850
|
-
const
|
|
10851
|
-
|
|
10852
|
-
if (!definitions || definitions.length === 0) return null;
|
|
10853
|
-
const def = definitions[0];
|
|
10856
|
+
const def = await res.json();
|
|
10857
|
+
if (!def || !def.id) return null;
|
|
10854
10858
|
return {
|
|
10855
10859
|
id: def.id,
|
|
10856
10860
|
slug: def.slug,
|
|
@@ -10868,7 +10872,7 @@ async function createDefinition(apiUrl, token, ir) {
|
|
|
10868
10872
|
"Content-Type": "application/json",
|
|
10869
10873
|
Authorization: `Bearer ${token}`
|
|
10870
10874
|
},
|
|
10871
|
-
body: JSON.stringify(ir)
|
|
10875
|
+
body: JSON.stringify({ ...ir, visibility: "PUBLIC" })
|
|
10872
10876
|
});
|
|
10873
10877
|
if (!res.ok) {
|
|
10874
10878
|
const errorText = await res.text();
|
|
@@ -11171,7 +11175,7 @@ function mindmatrixReact(options) {
|
|
|
11171
11175
|
slug: ir.slug,
|
|
11172
11176
|
name: ir.name,
|
|
11173
11177
|
version: ir.version,
|
|
11174
|
-
category: ir.category || "workflow",
|
|
11178
|
+
category: ir.category || ["workflow"],
|
|
11175
11179
|
fields: ir.fields || [],
|
|
11176
11180
|
states: ir.states || [],
|
|
11177
11181
|
transitions: ir.transitions || [],
|
|
@@ -11705,425 +11709,6 @@ async function startWatchMode(options) {
|
|
|
11705
11709
|
});
|
|
11706
11710
|
}
|
|
11707
11711
|
|
|
11708
|
-
// src/cli/local-server.ts
|
|
11709
|
-
var http = __toESM(require("http"));
|
|
11710
|
-
var import_node_crypto = require("crypto");
|
|
11711
|
-
var MemoryStore = class {
|
|
11712
|
-
constructor() {
|
|
11713
|
-
this.definitions = /* @__PURE__ */ new Map();
|
|
11714
|
-
this.instances = /* @__PURE__ */ new Map();
|
|
11715
|
-
this.slugIndex = /* @__PURE__ */ new Map();
|
|
11716
|
-
}
|
|
11717
|
-
// slug → id
|
|
11718
|
-
// ── Definitions ──────────────────────────────────────────────────────
|
|
11719
|
-
createDefinition(input) {
|
|
11720
|
-
if (this.slugIndex.has(input.slug)) {
|
|
11721
|
-
const existing = this.definitions.get(this.slugIndex.get(input.slug));
|
|
11722
|
-
if (existing) return existing;
|
|
11723
|
-
}
|
|
11724
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11725
|
-
const def = {
|
|
11726
|
-
id: input.id ?? (0, import_node_crypto.randomUUID)(),
|
|
11727
|
-
slug: input.slug,
|
|
11728
|
-
name: input.name,
|
|
11729
|
-
version: input.version ?? "1.0.0",
|
|
11730
|
-
description: input.description ?? null,
|
|
11731
|
-
category: input.category ?? "workflow",
|
|
11732
|
-
fields: input.fields ?? [],
|
|
11733
|
-
states: input.states ?? [],
|
|
11734
|
-
transitions: input.transitions ?? [],
|
|
11735
|
-
roles: input.roles ?? [],
|
|
11736
|
-
experience: input.experience ?? null,
|
|
11737
|
-
metadata: input.metadata ?? {},
|
|
11738
|
-
child_definitions: input.child_definitions ?? [],
|
|
11739
|
-
is_immutable: input.is_immutable ?? false,
|
|
11740
|
-
tags: input.tags ?? [],
|
|
11741
|
-
inline_tags: input.inline_tags ?? [],
|
|
11742
|
-
created_at: now,
|
|
11743
|
-
updated_at: now
|
|
11744
|
-
};
|
|
11745
|
-
this.definitions.set(def.id, def);
|
|
11746
|
-
this.slugIndex.set(def.slug, def.id);
|
|
11747
|
-
return def;
|
|
11748
|
-
}
|
|
11749
|
-
getDefinition(idOrSlug) {
|
|
11750
|
-
const byId = this.definitions.get(idOrSlug);
|
|
11751
|
-
if (byId) return byId;
|
|
11752
|
-
const id = this.slugIndex.get(idOrSlug);
|
|
11753
|
-
if (id) return this.definitions.get(id);
|
|
11754
|
-
return void 0;
|
|
11755
|
-
}
|
|
11756
|
-
listDefinitions(opts) {
|
|
11757
|
-
let items = Array.from(this.definitions.values());
|
|
11758
|
-
if (opts?.category) {
|
|
11759
|
-
items = items.filter((d) => d.category === opts.category);
|
|
11760
|
-
}
|
|
11761
|
-
const total = items.length;
|
|
11762
|
-
const offset = opts?.offset ?? 0;
|
|
11763
|
-
const limit = opts?.limit ?? 50;
|
|
11764
|
-
items = items.slice(offset, offset + limit);
|
|
11765
|
-
return { items, total };
|
|
11766
|
-
}
|
|
11767
|
-
patchDefinition(id, patch) {
|
|
11768
|
-
const def = this.definitions.get(id);
|
|
11769
|
-
if (!def) return void 0;
|
|
11770
|
-
Object.assign(def, patch, { updated_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11771
|
-
return def;
|
|
11772
|
-
}
|
|
11773
|
-
deleteDefinition(id) {
|
|
11774
|
-
const def = this.definitions.get(id);
|
|
11775
|
-
if (!def) return false;
|
|
11776
|
-
this.slugIndex.delete(def.slug);
|
|
11777
|
-
this.definitions.delete(id);
|
|
11778
|
-
return true;
|
|
11779
|
-
}
|
|
11780
|
-
// ── Instances ────────────────────────────────────────────────────────
|
|
11781
|
-
createInstance(input) {
|
|
11782
|
-
const def = this.getDefinition(input.definition_id) ?? this.getDefinition(input.definition_slug);
|
|
11783
|
-
if (!def) return null;
|
|
11784
|
-
const initialState = def.states.find((s) => s.type === "START" || s.type === "initial");
|
|
11785
|
-
const stateName = initialState?.name ?? "initial";
|
|
11786
|
-
const stateData = {};
|
|
11787
|
-
for (const field of def.fields) {
|
|
11788
|
-
if (field.default_value !== void 0) {
|
|
11789
|
-
stateData[field.name] = field.default_value;
|
|
11790
|
-
}
|
|
11791
|
-
}
|
|
11792
|
-
Object.assign(stateData, input.state_data ?? {});
|
|
11793
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11794
|
-
const inst = {
|
|
11795
|
-
id: (0, import_node_crypto.randomUUID)(),
|
|
11796
|
-
definition_id: def.id,
|
|
11797
|
-
definition_slug: def.slug,
|
|
11798
|
-
current_state: stateName,
|
|
11799
|
-
state_data: stateData,
|
|
11800
|
-
execution_lock_version: 0,
|
|
11801
|
-
event_log: [{
|
|
11802
|
-
event_type: "transition",
|
|
11803
|
-
message: `Instance created in state '${stateName}'`,
|
|
11804
|
-
timestamp: now
|
|
11805
|
-
}],
|
|
11806
|
-
created_at: now,
|
|
11807
|
-
updated_at: now
|
|
11808
|
-
};
|
|
11809
|
-
this.instances.set(inst.id, inst);
|
|
11810
|
-
return inst;
|
|
11811
|
-
}
|
|
11812
|
-
getInstance(id) {
|
|
11813
|
-
return this.instances.get(id);
|
|
11814
|
-
}
|
|
11815
|
-
listInstances(opts) {
|
|
11816
|
-
let items = Array.from(this.instances.values());
|
|
11817
|
-
if (opts?.definition_id) {
|
|
11818
|
-
items = items.filter((i) => i.definition_id === opts.definition_id);
|
|
11819
|
-
}
|
|
11820
|
-
const total = items.length;
|
|
11821
|
-
const offset = opts?.offset ?? 0;
|
|
11822
|
-
const limit = opts?.limit ?? 50;
|
|
11823
|
-
items = items.slice(offset, offset + limit);
|
|
11824
|
-
return { items, total };
|
|
11825
|
-
}
|
|
11826
|
-
// ── Execute Action (Transition) ──────────────────────────────────────
|
|
11827
|
-
executeAction(input) {
|
|
11828
|
-
const def = this.getDefinition(input.definition_id);
|
|
11829
|
-
if (!def) return { success: false, error: "Definition not found" };
|
|
11830
|
-
let inst;
|
|
11831
|
-
if (input.instance_id) {
|
|
11832
|
-
const existing = this.instances.get(input.instance_id);
|
|
11833
|
-
if (!existing) return { success: false, error: "Instance not found" };
|
|
11834
|
-
inst = existing;
|
|
11835
|
-
} else {
|
|
11836
|
-
const created = this.createInstance({
|
|
11837
|
-
definition_id: def.id,
|
|
11838
|
-
definition_slug: def.slug,
|
|
11839
|
-
state_data: input.payload
|
|
11840
|
-
});
|
|
11841
|
-
if (!created) return { success: false, error: "Failed to create instance" };
|
|
11842
|
-
inst = created;
|
|
11843
|
-
}
|
|
11844
|
-
if (input.payload && input.instance_id) {
|
|
11845
|
-
Object.assign(inst.state_data, input.payload);
|
|
11846
|
-
}
|
|
11847
|
-
const transition = def.transitions.find((t23) => t23.name === input.action_name && t23.from.includes(inst.current_state));
|
|
11848
|
-
if (!transition) {
|
|
11849
|
-
return {
|
|
11850
|
-
success: false,
|
|
11851
|
-
instance_id: inst.id,
|
|
11852
|
-
from_state: inst.current_state,
|
|
11853
|
-
to_state: null,
|
|
11854
|
-
state_data: inst.state_data,
|
|
11855
|
-
error: `No transition '${input.action_name}' from state '${inst.current_state}'`
|
|
11856
|
-
};
|
|
11857
|
-
}
|
|
11858
|
-
const fromState = inst.current_state;
|
|
11859
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11860
|
-
const events = [];
|
|
11861
|
-
let lastEvalResult = null;
|
|
11862
|
-
events.push({ event_type: "transition", message: `Transition '${transition.name}' started: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
11863
|
-
for (const action of transition.actions ?? []) {
|
|
11864
|
-
try {
|
|
11865
|
-
if (action.type === "set_field") {
|
|
11866
|
-
const field = action.config?.field;
|
|
11867
|
-
if (action.config?.expression) {
|
|
11868
|
-
const expr = action.config.expression;
|
|
11869
|
-
const result = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
11870
|
-
inst.state_data[field] = result;
|
|
11871
|
-
} else if (action.config?.value !== void 0) {
|
|
11872
|
-
inst.state_data[field] = action.config.value;
|
|
11873
|
-
}
|
|
11874
|
-
events.push({ event_type: "action_executed", message: `transition action 'set_field' succeeded`, timestamp: now });
|
|
11875
|
-
} else if (action.type === "eval") {
|
|
11876
|
-
const expr = action.config?.expression;
|
|
11877
|
-
lastEvalResult = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
11878
|
-
events.push({ event_type: "action_executed", message: `transition action 'eval' succeeded`, timestamp: now });
|
|
11879
|
-
} else {
|
|
11880
|
-
events.push({ event_type: "action_executed", message: `transition action '${action.type}' succeeded (no-op in local mode)`, timestamp: now });
|
|
11881
|
-
}
|
|
11882
|
-
} catch (err) {
|
|
11883
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
11884
|
-
events.push({ event_type: "action_failed", message: `transition action '${action.type}' failed: ${msg}`, timestamp: now });
|
|
11885
|
-
return {
|
|
11886
|
-
success: false,
|
|
11887
|
-
instance_id: inst.id,
|
|
11888
|
-
from_state: fromState,
|
|
11889
|
-
to_state: null,
|
|
11890
|
-
state_data: inst.state_data,
|
|
11891
|
-
event_log: events,
|
|
11892
|
-
error: `transition action failed: ${msg}`
|
|
11893
|
-
};
|
|
11894
|
-
}
|
|
11895
|
-
}
|
|
11896
|
-
inst.current_state = transition.to;
|
|
11897
|
-
inst.execution_lock_version++;
|
|
11898
|
-
inst.updated_at = now;
|
|
11899
|
-
events.push({ event_type: "transition", message: `State changed: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
11900
|
-
inst.event_log.push(...events);
|
|
11901
|
-
return {
|
|
11902
|
-
success: true,
|
|
11903
|
-
instance_id: inst.id,
|
|
11904
|
-
from_state: fromState,
|
|
11905
|
-
to_state: transition.to,
|
|
11906
|
-
state_data: inst.state_data,
|
|
11907
|
-
result: lastEvalResult,
|
|
11908
|
-
event_log: events
|
|
11909
|
-
};
|
|
11910
|
-
}
|
|
11911
|
-
/**
|
|
11912
|
-
* Minimal expression evaluator for local dev mode.
|
|
11913
|
-
* Handles: field references, arithmetic, string literals, simple comparisons.
|
|
11914
|
-
* Does NOT handle: while loops, if/else, function calls, multi-statement blocks.
|
|
11915
|
-
* For full evaluation, use mm-napi when available.
|
|
11916
|
-
*/
|
|
11917
|
-
evaluateSimpleExpression(expr, context) {
|
|
11918
|
-
if (context[expr] !== void 0) return context[expr];
|
|
11919
|
-
const arithMatch = expr.match(/^(\w+)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/);
|
|
11920
|
-
if (arithMatch) {
|
|
11921
|
-
const [, field, op, numStr] = arithMatch;
|
|
11922
|
-
const left = Number(context[field] ?? 0);
|
|
11923
|
-
const right = Number(numStr);
|
|
11924
|
-
switch (op) {
|
|
11925
|
-
case "+":
|
|
11926
|
-
return left + right;
|
|
11927
|
-
case "-":
|
|
11928
|
-
return left - right;
|
|
11929
|
-
case "*":
|
|
11930
|
-
return left * right;
|
|
11931
|
-
case "/":
|
|
11932
|
-
return right !== 0 ? left / right : 0;
|
|
11933
|
-
}
|
|
11934
|
-
}
|
|
11935
|
-
if (/^\d+(\.\d+)?$/.test(expr.trim())) {
|
|
11936
|
-
return Number(expr.trim());
|
|
11937
|
-
}
|
|
11938
|
-
const strMatch = expr.match(/^["'](.*)["']$/);
|
|
11939
|
-
if (strMatch) return strMatch[1];
|
|
11940
|
-
try {
|
|
11941
|
-
const keys = Object.keys(context);
|
|
11942
|
-
const values = Object.values(context);
|
|
11943
|
-
const fn = new Function(...keys, `"use strict"; return (${expr});`);
|
|
11944
|
-
return fn(...values);
|
|
11945
|
-
} catch {
|
|
11946
|
-
return null;
|
|
11947
|
-
}
|
|
11948
|
-
}
|
|
11949
|
-
};
|
|
11950
|
-
async function startLocalServer(options = {}) {
|
|
11951
|
-
const { port = 4200, noAuth = true } = options;
|
|
11952
|
-
const store = new MemoryStore();
|
|
11953
|
-
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11954
|
-
function json(res, status, body) {
|
|
11955
|
-
const data = JSON.stringify(body);
|
|
11956
|
-
res.writeHead(status, {
|
|
11957
|
-
"Content-Type": "application/json",
|
|
11958
|
-
"Access-Control-Allow-Origin": "*",
|
|
11959
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
11960
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
11961
|
-
"Content-Length": Buffer.byteLength(data)
|
|
11962
|
-
});
|
|
11963
|
-
res.end(data);
|
|
11964
|
-
}
|
|
11965
|
-
function readBody(req) {
|
|
11966
|
-
return new Promise((resolve2, reject) => {
|
|
11967
|
-
const chunks = [];
|
|
11968
|
-
req.on("data", (chunk) => chunks.push(chunk));
|
|
11969
|
-
req.on("end", () => resolve2(Buffer.concat(chunks).toString()));
|
|
11970
|
-
req.on("error", reject);
|
|
11971
|
-
});
|
|
11972
|
-
}
|
|
11973
|
-
function parseQuery(url) {
|
|
11974
|
-
const idx = url.indexOf("?");
|
|
11975
|
-
if (idx === -1) return {};
|
|
11976
|
-
const params = {};
|
|
11977
|
-
const qs = url.slice(idx + 1);
|
|
11978
|
-
for (const pair of qs.split("&")) {
|
|
11979
|
-
const [k, v] = pair.split("=");
|
|
11980
|
-
if (k) params[decodeURIComponent(k)] = decodeURIComponent(v ?? "");
|
|
11981
|
-
}
|
|
11982
|
-
return params;
|
|
11983
|
-
}
|
|
11984
|
-
const server = http.createServer(async (req, res) => {
|
|
11985
|
-
const method = req.method?.toUpperCase() ?? "GET";
|
|
11986
|
-
const rawUrl = req.url ?? "/";
|
|
11987
|
-
const queryStart = rawUrl.indexOf("?");
|
|
11988
|
-
const path = queryStart >= 0 ? rawUrl.slice(0, queryStart) : rawUrl;
|
|
11989
|
-
const query = parseQuery(rawUrl);
|
|
11990
|
-
if (method === "OPTIONS") {
|
|
11991
|
-
res.writeHead(204, {
|
|
11992
|
-
"Access-Control-Allow-Origin": "*",
|
|
11993
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
11994
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
11995
|
-
"Access-Control-Max-Age": "86400"
|
|
11996
|
-
});
|
|
11997
|
-
res.end();
|
|
11998
|
-
return;
|
|
11999
|
-
}
|
|
12000
|
-
try {
|
|
12001
|
-
if (path === "/health" && method === "GET") {
|
|
12002
|
-
return json(res, 200, {
|
|
12003
|
-
status: "ok",
|
|
12004
|
-
service: "mm-local-dev",
|
|
12005
|
-
mode: "in-memory",
|
|
12006
|
-
started_at: startedAt,
|
|
12007
|
-
definitions: store.definitions.size,
|
|
12008
|
-
instances: store.instances.size
|
|
12009
|
-
});
|
|
12010
|
-
}
|
|
12011
|
-
if (path === "/api/v1/auth/login" && (method === "POST" || method === "GET")) {
|
|
12012
|
-
return json(res, 200, {
|
|
12013
|
-
token: "dev-token-local",
|
|
12014
|
-
user: {
|
|
12015
|
-
id: "dev-user-001",
|
|
12016
|
-
email: "dev@localhost",
|
|
12017
|
-
role: "admin",
|
|
12018
|
-
name: "Local Developer"
|
|
12019
|
-
}
|
|
12020
|
-
});
|
|
12021
|
-
}
|
|
12022
|
-
if (path === "/api/v1/workflow/definitions" && method === "GET") {
|
|
12023
|
-
const result = store.listDefinitions({
|
|
12024
|
-
category: query.category,
|
|
12025
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
12026
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
12027
|
-
});
|
|
12028
|
-
if (query.slug) {
|
|
12029
|
-
const def = store.getDefinition(query.slug);
|
|
12030
|
-
return json(res, 200, { items: def ? [def] : [], total: def ? 1 : 0 });
|
|
12031
|
-
}
|
|
12032
|
-
return json(res, 200, result);
|
|
12033
|
-
}
|
|
12034
|
-
const defMatch = path.match(/^\/api\/v1\/workflow\/definitions\/([^/]+)$/);
|
|
12035
|
-
if (defMatch && method === "GET") {
|
|
12036
|
-
const def = store.getDefinition(defMatch[1]);
|
|
12037
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
12038
|
-
return json(res, 200, def);
|
|
12039
|
-
}
|
|
12040
|
-
if (path === "/api/v1/workflow/definitions" && method === "POST") {
|
|
12041
|
-
const body = JSON.parse(await readBody(req));
|
|
12042
|
-
const def = store.createDefinition(body);
|
|
12043
|
-
return json(res, 201, def);
|
|
12044
|
-
}
|
|
12045
|
-
if (defMatch && method === "PATCH") {
|
|
12046
|
-
const body = JSON.parse(await readBody(req));
|
|
12047
|
-
const updated = store.patchDefinition(defMatch[1], body);
|
|
12048
|
-
if (!updated) return json(res, 404, { error: "Not found" });
|
|
12049
|
-
return json(res, 200, updated);
|
|
12050
|
-
}
|
|
12051
|
-
if (defMatch && method === "DELETE") {
|
|
12052
|
-
const deleted = store.deleteDefinition(defMatch[1]);
|
|
12053
|
-
if (!deleted) return json(res, 404, { error: "Not found" });
|
|
12054
|
-
return json(res, 204, null);
|
|
12055
|
-
}
|
|
12056
|
-
if (path === "/api/v1/workflow/instances" && method === "GET") {
|
|
12057
|
-
const result = store.listInstances({
|
|
12058
|
-
definition_id: query.definition_id,
|
|
12059
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
12060
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
12061
|
-
});
|
|
12062
|
-
return json(res, 200, result);
|
|
12063
|
-
}
|
|
12064
|
-
if (path === "/api/v1/workflow/instances" && method === "POST") {
|
|
12065
|
-
const body = JSON.parse(await readBody(req));
|
|
12066
|
-
const inst = store.createInstance(body);
|
|
12067
|
-
if (!inst) return json(res, 404, { error: "Definition not found" });
|
|
12068
|
-
return json(res, 201, inst);
|
|
12069
|
-
}
|
|
12070
|
-
const instMatch = path.match(/^\/api\/v1\/workflow\/instances\/([^/]+)$/);
|
|
12071
|
-
if (instMatch && method === "GET") {
|
|
12072
|
-
const inst = store.getInstance(instMatch[1]);
|
|
12073
|
-
if (!inst) return json(res, 404, { error: "Not found" });
|
|
12074
|
-
return json(res, 200, inst);
|
|
12075
|
-
}
|
|
12076
|
-
if (path === "/api/v1/workflow/execute-action" && method === "POST") {
|
|
12077
|
-
const body = JSON.parse(await readBody(req));
|
|
12078
|
-
const result = store.executeAction(body);
|
|
12079
|
-
return json(res, 200, result);
|
|
12080
|
-
}
|
|
12081
|
-
const dataMatch = path.match(/^\/api\/v1\/data\/([^/]+)$/);
|
|
12082
|
-
if (dataMatch && method === "GET") {
|
|
12083
|
-
const def = store.getDefinition(dataMatch[1]);
|
|
12084
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
12085
|
-
const instances = store.listInstances({ definition_id: def.id });
|
|
12086
|
-
return json(res, 200, instances);
|
|
12087
|
-
}
|
|
12088
|
-
if (path.startsWith("/api/v1/")) {
|
|
12089
|
-
return json(res, 501, { error: "Not implemented in local dev mode", path, method });
|
|
12090
|
-
}
|
|
12091
|
-
return json(res, 404, { error: "Not found", path });
|
|
12092
|
-
} catch (err) {
|
|
12093
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
12094
|
-
console.error(`[mm-local] ${method} ${path} \u2014 Error: ${message}`);
|
|
12095
|
-
return json(res, 500, { error: message });
|
|
12096
|
-
}
|
|
12097
|
-
});
|
|
12098
|
-
return new Promise((resolve2, reject) => {
|
|
12099
|
-
server.on("error", (err) => {
|
|
12100
|
-
if (err.code === "EADDRINUSE") {
|
|
12101
|
-
reject(new Error(`Port ${port} is already in use. Is another server running?`));
|
|
12102
|
-
} else {
|
|
12103
|
-
reject(err);
|
|
12104
|
-
}
|
|
12105
|
-
});
|
|
12106
|
-
server.listen(port, () => {
|
|
12107
|
-
console.log(`[mm-local] Local API server running at http://localhost:${port}`);
|
|
12108
|
-
console.log(`[mm-local] Mode: in-memory (data lost on restart)`);
|
|
12109
|
-
console.log(`[mm-local] Auth: disabled (all requests accepted)`);
|
|
12110
|
-
resolve2({
|
|
12111
|
-
server,
|
|
12112
|
-
port,
|
|
12113
|
-
store,
|
|
12114
|
-
async close() {
|
|
12115
|
-
return new Promise((res) => {
|
|
12116
|
-
server.close(() => {
|
|
12117
|
-
console.log("[mm-local] Local API server stopped");
|
|
12118
|
-
res();
|
|
12119
|
-
});
|
|
12120
|
-
});
|
|
12121
|
-
}
|
|
12122
|
-
});
|
|
12123
|
-
});
|
|
12124
|
-
});
|
|
12125
|
-
}
|
|
12126
|
-
|
|
12127
11712
|
// src/dev-server.ts
|
|
12128
11713
|
var currentErrors = null;
|
|
12129
11714
|
function escapeHtml(s) {
|
|
@@ -12300,34 +11885,33 @@ async function createDevServer(options = {}) {
|
|
|
12300
11885
|
open = false
|
|
12301
11886
|
} = options;
|
|
12302
11887
|
const clients = /* @__PURE__ */ new Set();
|
|
12303
|
-
let localServer = null;
|
|
12304
11888
|
let apiUrl;
|
|
12305
|
-
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
|
|
12314
|
-
apiUrl = defaultRemote;
|
|
12315
|
-
} else {
|
|
12316
|
-
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
12317
|
-
if (localHealth.ok) {
|
|
12318
|
-
apiUrl = "http://localhost:4200/api/v1";
|
|
11889
|
+
if (rawApiUrl === "local" || rawApiUrl === "auto") {
|
|
11890
|
+
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
11891
|
+
if (localHealth.ok) {
|
|
11892
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
11893
|
+
} else if (rawApiUrl === "auto") {
|
|
11894
|
+
const defaultRemote = "https://dev.mindmatrix.club/api/v1";
|
|
11895
|
+
const remoteHealth = await checkBackendHealth(defaultRemote);
|
|
11896
|
+
if (remoteHealth.ok) {
|
|
11897
|
+
apiUrl = defaultRemote;
|
|
12319
11898
|
} else {
|
|
12320
|
-
console.
|
|
12321
|
-
|
|
11899
|
+
console.error("[mm-dev] No backend detected. Start the engine first:");
|
|
11900
|
+
console.error(" mmrc dev (auto-starts engine)");
|
|
11901
|
+
console.error(" mmrc engine start (manual start)");
|
|
11902
|
+
console.error("[mm-dev] Or specify a remote API: mmrc dev --api-url https://...");
|
|
12322
11903
|
apiUrl = "http://localhost:4200/api/v1";
|
|
12323
|
-
isLocalMode = true;
|
|
12324
11904
|
}
|
|
11905
|
+
} else {
|
|
11906
|
+
console.error("[mm-dev] Local engine not running on port 4200.");
|
|
11907
|
+
console.error(" Start it with: mmrc dev (or mmrc engine start)");
|
|
11908
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
12325
11909
|
}
|
|
12326
11910
|
} else {
|
|
12327
11911
|
apiUrl = rawApiUrl;
|
|
12328
11912
|
}
|
|
12329
|
-
const token =
|
|
12330
|
-
const health =
|
|
11913
|
+
const token = await resolveDevToken(apiUrl, explicitToken);
|
|
11914
|
+
const health = await checkBackendHealth(apiUrl);
|
|
12331
11915
|
let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
|
|
12332
11916
|
if (token && health.ok) {
|
|
12333
11917
|
const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
|
|
@@ -12387,63 +11971,169 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
12387
11971
|
`;
|
|
12388
11972
|
}
|
|
12389
11973
|
};
|
|
12390
|
-
const
|
|
11974
|
+
const { existsSync: fsExists } = await import("fs");
|
|
11975
|
+
const projectIndexPath = require("path").join(process.cwd(), "index.html");
|
|
11976
|
+
const hasProjectIndex = fsExists(projectIndexPath);
|
|
11977
|
+
if (!hasProjectIndex) {
|
|
11978
|
+
const { writeFileSync: fsWrite } = await import("fs");
|
|
11979
|
+
fsWrite(projectIndexPath, `<!DOCTYPE html>
|
|
12391
11980
|
<html lang="en">
|
|
12392
11981
|
<head>
|
|
12393
11982
|
<meta charset="UTF-8">
|
|
12394
11983
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
12395
11984
|
<title>MindMatrix Dev</title>
|
|
12396
|
-
<style>
|
|
12397
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
12398
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #fafafa; color: #111; }
|
|
12399
|
-
#root { min-height: 100vh; }
|
|
12400
|
-
.mm-loading { display: flex; align-items: center; justify-content: center; min-height: 100vh; flex-direction: column; gap: 12px; }
|
|
12401
|
-
.mm-loading h1 { font-size: 20px; font-weight: 600; color: #333; }
|
|
12402
|
-
.mm-loading p { color: #888; font-size: 14px; }
|
|
12403
|
-
</style>
|
|
12404
11985
|
</head>
|
|
12405
11986
|
<body>
|
|
12406
|
-
<div id="root">
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
11987
|
+
<div id="root"></div>
|
|
11988
|
+
<script type="module" src="/__mm_dev_entry.tsx"></script>
|
|
11989
|
+
</body>
|
|
11990
|
+
</html>`, "utf-8");
|
|
11991
|
+
}
|
|
11992
|
+
const devEntryPlugin = {
|
|
11993
|
+
name: "mindmatrix-dev-entry",
|
|
11994
|
+
resolveId(id) {
|
|
11995
|
+
if (id === "/__mm_dev_entry.tsx") return id;
|
|
11996
|
+
return null;
|
|
11997
|
+
},
|
|
11998
|
+
load(id) {
|
|
11999
|
+
if (id !== "/__mm_dev_entry.tsx") return null;
|
|
12000
|
+
return `
|
|
12001
|
+
import React, { useState, useEffect } from 'react';
|
|
12002
|
+
import { createRoot } from 'react-dom/client';
|
|
12003
|
+
import { DevPlayer } from '@mmapp/react/player';
|
|
12004
|
+
import { PlayerProvider, ExperienceRenderer, createApiResolver } from '@mmapp/react/player';
|
|
12005
|
+
|
|
12006
|
+
// Detect API base URL \u2014 proxy through dev server or use direct URL
|
|
12007
|
+
const API_BASE = window.location.origin + '/api/v1';
|
|
12008
|
+
const resolver = createApiResolver({ baseUrl: API_BASE, token: () => localStorage.getItem('auth_token') });
|
|
12009
|
+
|
|
12010
|
+
/**
|
|
12011
|
+
* Prepare experience tree for rendering.
|
|
12012
|
+
* Attaches metadata.dataSources to the root node and remaps
|
|
12013
|
+
* dataSource slugs to use definition-relative naming.
|
|
12014
|
+
*
|
|
12015
|
+
* @param definition - The main blueprint definition
|
|
12016
|
+
* @param allDefinitions - ALL definitions from the API (used for slug resolution)
|
|
12017
|
+
*/
|
|
12018
|
+
function prepareTree(definition, allDefinitions) {
|
|
12019
|
+
const exp = definition.experience;
|
|
12020
|
+
if (!exp || typeof exp !== 'object') return null;
|
|
12021
|
+
|
|
12022
|
+
const meta = definition.metadata || {};
|
|
12023
|
+
const dataSources = meta.dataSources || [];
|
|
12024
|
+
const mutationTargets = meta.mutationTargets || [];
|
|
12025
|
+
|
|
12026
|
+
// Build a slug map from ALL deployed definitions
|
|
12027
|
+
// This resolves bare model names (e.g. "item") to full slugs (e.g. "tutorial-1-item")
|
|
12028
|
+
const blueprintSlug = definition.slug || '';
|
|
12029
|
+
const allSlugs = (allDefinitions || []).map(d => d.slug).filter(Boolean);
|
|
12030
|
+
|
|
12031
|
+
function resolveSlug(bareSlug) {
|
|
12032
|
+
if (!bareSlug) return bareSlug;
|
|
12033
|
+
// Already a full slug (contains hyphen matching a known definition)
|
|
12034
|
+
if (allSlugs.includes(bareSlug)) return bareSlug;
|
|
12035
|
+
// Try blueprint-prefixed slug: "item" \u2192 "tutorial-1-item"
|
|
12036
|
+
const prefixed = blueprintSlug + '-' + bareSlug;
|
|
12037
|
+
if (allSlugs.includes(prefixed)) return prefixed;
|
|
12038
|
+
// Try matching by suffix across all definitions
|
|
12039
|
+
const match = allSlugs.find(s => s.endsWith('-' + bareSlug));
|
|
12040
|
+
if (match) return match;
|
|
12041
|
+
// Return original (will attempt as-is)
|
|
12042
|
+
return bareSlug;
|
|
12043
|
+
}
|
|
12044
|
+
|
|
12045
|
+
// Clone root node and attach dataSources
|
|
12046
|
+
const root = { ...exp };
|
|
12047
|
+
if (dataSources.length > 0 && !root.dataSources) {
|
|
12048
|
+
root.dataSources = dataSources.map(ds => ({
|
|
12049
|
+
...ds,
|
|
12050
|
+
slug: resolveSlug(ds.slug),
|
|
12051
|
+
}));
|
|
12052
|
+
}
|
|
12053
|
+
|
|
12054
|
+
// Remap mutation targets the same way
|
|
12055
|
+
if (mutationTargets.length > 0) {
|
|
12056
|
+
const resolvedTargets = mutationTargets.map(t => resolveSlug(t));
|
|
12057
|
+
root.config = { ...(root.config || {}), _mutationTargets: resolvedTargets };
|
|
12058
|
+
}
|
|
12059
|
+
|
|
12060
|
+
return root;
|
|
12061
|
+
}
|
|
12062
|
+
|
|
12063
|
+
function App() {
|
|
12064
|
+
const [tree, setTree] = useState(null);
|
|
12065
|
+
const [error, setError] = useState(null);
|
|
12066
|
+
|
|
12067
|
+
useEffect(() => {
|
|
12068
|
+
async function loadTree() {
|
|
12415
12069
|
try {
|
|
12416
|
-
const res = await fetch('/
|
|
12070
|
+
const res = await fetch(API_BASE + '/workflow/definitions');
|
|
12417
12071
|
const json = await res.json();
|
|
12418
|
-
const
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
}
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12072
|
+
const rawItems = json.items || json.data || [];
|
|
12073
|
+
// Flatten: API returns { id, slug, definition: { experience, ... } }
|
|
12074
|
+
// Merge definition fields up to the top level for easier access
|
|
12075
|
+
const items = rawItems.map(d => {
|
|
12076
|
+
const def = d.definition || {};
|
|
12077
|
+
return { ...d, ...def, definition: undefined };
|
|
12078
|
+
});
|
|
12079
|
+
// Find the main blueprint definition (has experience tree)
|
|
12080
|
+
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];
|
|
12081
|
+
if (main?.experience) {
|
|
12082
|
+
const prepared = prepareTree(main, items);
|
|
12083
|
+
if (prepared) {
|
|
12084
|
+
setTree(prepared);
|
|
12085
|
+
return;
|
|
12086
|
+
}
|
|
12087
|
+
}
|
|
12088
|
+
if (main) {
|
|
12089
|
+
// No experience tree \u2014 show definition info
|
|
12090
|
+
setTree({
|
|
12091
|
+
type: 'Stack',
|
|
12092
|
+
props: { style: { padding: 40, gap: 16 } },
|
|
12093
|
+
children: [
|
|
12094
|
+
{ type: 'Text', props: { children: main.name || main.slug, style: { fontSize: 24, fontWeight: 'bold' } } },
|
|
12095
|
+
{ type: 'Text', props: { children: (main.states?.length || 0) + ' states, ' + (main.fields?.length || 0) + ' fields', style: { color: '#666' } } },
|
|
12096
|
+
...items.map((d, i) => ({
|
|
12097
|
+
type: 'Card',
|
|
12098
|
+
props: { key: i, style: { padding: 16, border: '1px solid #ddd', borderRadius: 8 } },
|
|
12099
|
+
children: [
|
|
12100
|
+
{ type: 'Text', props: { children: d.name || d.slug, style: { fontWeight: 600 } } },
|
|
12101
|
+
{ type: 'Text', props: { children: 'slug: ' + d.slug + ' | ' + (d.states?.length || 0) + ' states', style: { fontSize: 13, color: '#888' } } },
|
|
12102
|
+
],
|
|
12103
|
+
})),
|
|
12104
|
+
],
|
|
12105
|
+
});
|
|
12106
|
+
}
|
|
12433
12107
|
} catch (e) {
|
|
12434
|
-
|
|
12108
|
+
setError(e.message);
|
|
12435
12109
|
}
|
|
12436
12110
|
}
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12111
|
+
loadTree();
|
|
12112
|
+
}, []);
|
|
12113
|
+
|
|
12114
|
+
if (error) return React.createElement('div', { style: { padding: 40 } },
|
|
12115
|
+
React.createElement('h1', null, 'MindMatrix Dev'),
|
|
12116
|
+
React.createElement('p', { style: { color: '#c00' } }, 'Error: ' + error)
|
|
12117
|
+
);
|
|
12118
|
+
|
|
12119
|
+
if (!tree) return React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh' } },
|
|
12120
|
+
React.createElement('p', null, 'Loading...')
|
|
12121
|
+
);
|
|
12122
|
+
|
|
12123
|
+
// If tree has 'component' field, use ExperienceRenderer; otherwise legacy DevPlayer
|
|
12124
|
+
if (tree.component) {
|
|
12125
|
+
return React.createElement(PlayerProvider, { resolver },
|
|
12126
|
+
React.createElement(ExperienceRenderer, { tree, className: 'mm-experience-root' })
|
|
12127
|
+
);
|
|
12128
|
+
}
|
|
12129
|
+
|
|
12130
|
+
return React.createElement(DevPlayer, { tree, title: document.title || 'MindMatrix Dev' });
|
|
12131
|
+
}
|
|
12132
|
+
|
|
12133
|
+
createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
12134
|
+
`;
|
|
12135
|
+
}
|
|
12136
|
+
};
|
|
12447
12137
|
let deployInFlight = false;
|
|
12448
12138
|
const compileDeployPlugin = {
|
|
12449
12139
|
name: "mindmatrix-dev-compile-deploy",
|
|
@@ -12474,16 +12164,16 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
12474
12164
|
}
|
|
12475
12165
|
};
|
|
12476
12166
|
const viteConfig = {
|
|
12477
|
-
//
|
|
12478
|
-
root:
|
|
12479
|
-
// Pre-bundle React
|
|
12167
|
+
// Use the blueprint directory as Vite root (has node_modules with React).
|
|
12168
|
+
root: process.cwd(),
|
|
12169
|
+
// Pre-bundle React and the player for fast dev startup.
|
|
12480
12170
|
optimizeDeps: { include: ["react", "react-dom/client"] },
|
|
12481
12171
|
server: {
|
|
12482
12172
|
port,
|
|
12483
12173
|
open,
|
|
12484
12174
|
host: true,
|
|
12485
12175
|
// Allow serving files from the real project directory (fs.allow).
|
|
12486
|
-
fs: { allow: [
|
|
12176
|
+
fs: { allow: [process.cwd(), ".."] },
|
|
12487
12177
|
proxy: {
|
|
12488
12178
|
"/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
|
|
12489
12179
|
"/health": { target: proxyTarget, changeOrigin: true, secure: true },
|
|
@@ -12493,6 +12183,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
12493
12183
|
plugins: [
|
|
12494
12184
|
mindmatrixReact(pluginOpts),
|
|
12495
12185
|
compileDeployPlugin,
|
|
12186
|
+
devEntryPlugin,
|
|
12496
12187
|
devPlayerPlugin,
|
|
12497
12188
|
{ name: "mindmatrix-error-overlay", configureServer(server) {
|
|
12498
12189
|
server.middlewares.use(errorOverlayMiddleware());
|
|
@@ -12500,8 +12191,8 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
12500
12191
|
],
|
|
12501
12192
|
logLevel: "warn"
|
|
12502
12193
|
};
|
|
12503
|
-
const { createServer
|
|
12504
|
-
const vite = await
|
|
12194
|
+
const { createServer } = await import("vite");
|
|
12195
|
+
const vite = await createServer(viteConfig);
|
|
12505
12196
|
await vite.listen();
|
|
12506
12197
|
const resolvedPort = vite.config.server.port ?? port;
|
|
12507
12198
|
if (enableWs && vite.httpServer) {
|
|
@@ -12519,7 +12210,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
12519
12210
|
} catch {
|
|
12520
12211
|
}
|
|
12521
12212
|
}
|
|
12522
|
-
printBanner({ port: resolvedPort, apiUrl
|
|
12213
|
+
printBanner({ port: resolvedPort, apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
|
|
12523
12214
|
return {
|
|
12524
12215
|
vite,
|
|
12525
12216
|
port: resolvedPort,
|
|
@@ -12551,14 +12242,6 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
12551
12242
|
clients.clear();
|
|
12552
12243
|
currentErrors = null;
|
|
12553
12244
|
await vite.close();
|
|
12554
|
-
if (localServer) {
|
|
12555
|
-
await localServer.close();
|
|
12556
|
-
}
|
|
12557
|
-
try {
|
|
12558
|
-
const { rmSync } = await import("fs");
|
|
12559
|
-
rmSync(devRoot, { recursive: true, force: true });
|
|
12560
|
-
} catch {
|
|
12561
|
-
}
|
|
12562
12245
|
}
|
|
12563
12246
|
};
|
|
12564
12247
|
}
|