@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/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)) {
|
|
@@ -10870,14 +10876,12 @@ async function deploy(options) {
|
|
|
10870
10876
|
}
|
|
10871
10877
|
async function fetchExistingDefinition(apiUrl, token, slug) {
|
|
10872
10878
|
try {
|
|
10873
|
-
const res = await fetch(`${apiUrl}/workflow/definitions
|
|
10879
|
+
const res = await fetch(`${apiUrl}/workflow/definitions/${encodeURIComponent(slug)}`, {
|
|
10874
10880
|
headers: { Authorization: `Bearer ${token}` }
|
|
10875
10881
|
});
|
|
10876
10882
|
if (!res.ok) return null;
|
|
10877
|
-
const
|
|
10878
|
-
|
|
10879
|
-
if (!definitions || definitions.length === 0) return null;
|
|
10880
|
-
const def = definitions[0];
|
|
10883
|
+
const def = await res.json();
|
|
10884
|
+
if (!def || !def.id) return null;
|
|
10881
10885
|
return {
|
|
10882
10886
|
id: def.id,
|
|
10883
10887
|
slug: def.slug,
|
|
@@ -10895,7 +10899,7 @@ async function createDefinition(apiUrl, token, ir) {
|
|
|
10895
10899
|
"Content-Type": "application/json",
|
|
10896
10900
|
Authorization: `Bearer ${token}`
|
|
10897
10901
|
},
|
|
10898
|
-
body: JSON.stringify(ir)
|
|
10902
|
+
body: JSON.stringify({ ...ir, visibility: "PUBLIC" })
|
|
10899
10903
|
});
|
|
10900
10904
|
if (!res.ok) {
|
|
10901
10905
|
const errorText = await res.text();
|
|
@@ -12665,7 +12669,7 @@ function generatePageFile(page, _slug) {
|
|
|
12665
12669
|
slug: page.route || "page",
|
|
12666
12670
|
name: page.componentName,
|
|
12667
12671
|
version: "1.0.0",
|
|
12668
|
-
category: "
|
|
12672
|
+
category: "view",
|
|
12669
12673
|
states: [],
|
|
12670
12674
|
transitions: [],
|
|
12671
12675
|
fields: [],
|
|
@@ -12856,7 +12860,8 @@ function decompileProject(definition, options) {
|
|
|
12856
12860
|
...child,
|
|
12857
12861
|
experience: child.views?.default
|
|
12858
12862
|
};
|
|
12859
|
-
|
|
12863
|
+
const childCatArr = Array.isArray(child.category) ? child.category : [child.category];
|
|
12864
|
+
if (childCatArr.includes("data") && child.fields.length > 0 && !options?.skipModels) {
|
|
12860
12865
|
let childModelContent = generateModelFile(childSlug, child.fields);
|
|
12861
12866
|
if (child.states.length > 0) {
|
|
12862
12867
|
childModelContent += generateStateEnum(childSlug, child.states);
|
|
@@ -13117,7 +13122,8 @@ function compareIR(original, roundTripped) {
|
|
|
13117
13122
|
const diffs = [];
|
|
13118
13123
|
comparePrimitive(diffs, "slug", original.slug, roundTripped.slug);
|
|
13119
13124
|
comparePrimitive(diffs, "version", original.version, roundTripped.version);
|
|
13120
|
-
|
|
13125
|
+
const normCat = (c) => JSON.stringify(Array.isArray(c) ? c : c ? [c] : []);
|
|
13126
|
+
comparePrimitive(diffs, "category", normCat(original.category), normCat(roundTripped.category));
|
|
13121
13127
|
compareFields(diffs, original.fields, roundTripped.fields);
|
|
13122
13128
|
compareStates(diffs, original.states, roundTripped.states);
|
|
13123
13129
|
compareTransitions(diffs, original.transitions, roundTripped.transitions);
|
|
@@ -13334,7 +13340,7 @@ function mindmatrixReact(options) {
|
|
|
13334
13340
|
slug: ir.slug,
|
|
13335
13341
|
name: ir.name,
|
|
13336
13342
|
version: ir.version,
|
|
13337
|
-
category: ir.category || "workflow",
|
|
13343
|
+
category: ir.category || ["workflow"],
|
|
13338
13344
|
fields: ir.fields || [],
|
|
13339
13345
|
states: ir.states || [],
|
|
13340
13346
|
transitions: ir.transitions || [],
|
|
@@ -13919,425 +13925,6 @@ async function startWatchMode(options) {
|
|
|
13919
13925
|
});
|
|
13920
13926
|
}
|
|
13921
13927
|
|
|
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
13928
|
// src/dev-server.ts
|
|
14342
13929
|
var currentErrors = null;
|
|
14343
13930
|
function escapeHtml(s) {
|
|
@@ -14514,34 +14101,33 @@ async function createDevServer(options = {}) {
|
|
|
14514
14101
|
open = false
|
|
14515
14102
|
} = options;
|
|
14516
14103
|
const clients = /* @__PURE__ */ new Set();
|
|
14517
|
-
let localServer = null;
|
|
14518
14104
|
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";
|
|
14105
|
+
if (rawApiUrl === "local" || rawApiUrl === "auto") {
|
|
14106
|
+
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
14107
|
+
if (localHealth.ok) {
|
|
14108
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
14109
|
+
} else if (rawApiUrl === "auto") {
|
|
14110
|
+
const defaultRemote = "https://dev.mindmatrix.club/api/v1";
|
|
14111
|
+
const remoteHealth = await checkBackendHealth(defaultRemote);
|
|
14112
|
+
if (remoteHealth.ok) {
|
|
14113
|
+
apiUrl = defaultRemote;
|
|
14533
14114
|
} else {
|
|
14534
|
-
console.
|
|
14535
|
-
|
|
14115
|
+
console.error("[mm-dev] No backend detected. Start the engine first:");
|
|
14116
|
+
console.error(" mmrc dev (auto-starts engine)");
|
|
14117
|
+
console.error(" mmrc engine start (manual start)");
|
|
14118
|
+
console.error("[mm-dev] Or specify a remote API: mmrc dev --api-url https://...");
|
|
14536
14119
|
apiUrl = "http://localhost:4200/api/v1";
|
|
14537
|
-
isLocalMode = true;
|
|
14538
14120
|
}
|
|
14121
|
+
} else {
|
|
14122
|
+
console.error("[mm-dev] Local engine not running on port 4200.");
|
|
14123
|
+
console.error(" Start it with: mmrc dev (or mmrc engine start)");
|
|
14124
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
14539
14125
|
}
|
|
14540
14126
|
} else {
|
|
14541
14127
|
apiUrl = rawApiUrl;
|
|
14542
14128
|
}
|
|
14543
|
-
const token =
|
|
14544
|
-
const health =
|
|
14129
|
+
const token = await resolveDevToken(apiUrl, explicitToken);
|
|
14130
|
+
const health = await checkBackendHealth(apiUrl);
|
|
14545
14131
|
let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
|
|
14546
14132
|
if (token && health.ok) {
|
|
14547
14133
|
const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
|
|
@@ -14601,63 +14187,169 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14601
14187
|
`;
|
|
14602
14188
|
}
|
|
14603
14189
|
};
|
|
14604
|
-
const
|
|
14190
|
+
const { existsSync: fsExists } = await import("fs");
|
|
14191
|
+
const projectIndexPath = require("path").join(process.cwd(), "index.html");
|
|
14192
|
+
const hasProjectIndex = fsExists(projectIndexPath);
|
|
14193
|
+
if (!hasProjectIndex) {
|
|
14194
|
+
const { writeFileSync: fsWrite } = await import("fs");
|
|
14195
|
+
fsWrite(projectIndexPath, `<!DOCTYPE html>
|
|
14605
14196
|
<html lang="en">
|
|
14606
14197
|
<head>
|
|
14607
14198
|
<meta charset="UTF-8">
|
|
14608
14199
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
14609
14200
|
<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
14201
|
</head>
|
|
14619
14202
|
<body>
|
|
14620
|
-
<div id="root">
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14203
|
+
<div id="root"></div>
|
|
14204
|
+
<script type="module" src="/__mm_dev_entry.tsx"></script>
|
|
14205
|
+
</body>
|
|
14206
|
+
</html>`, "utf-8");
|
|
14207
|
+
}
|
|
14208
|
+
const devEntryPlugin = {
|
|
14209
|
+
name: "mindmatrix-dev-entry",
|
|
14210
|
+
resolveId(id) {
|
|
14211
|
+
if (id === "/__mm_dev_entry.tsx") return id;
|
|
14212
|
+
return null;
|
|
14213
|
+
},
|
|
14214
|
+
load(id) {
|
|
14215
|
+
if (id !== "/__mm_dev_entry.tsx") return null;
|
|
14216
|
+
return `
|
|
14217
|
+
import React, { useState, useEffect } from 'react';
|
|
14218
|
+
import { createRoot } from 'react-dom/client';
|
|
14219
|
+
import { DevPlayer } from '@mmapp/react/player';
|
|
14220
|
+
import { PlayerProvider, ExperienceRenderer, createApiResolver } from '@mmapp/react/player';
|
|
14221
|
+
|
|
14222
|
+
// Detect API base URL \u2014 proxy through dev server or use direct URL
|
|
14223
|
+
const API_BASE = window.location.origin + '/api/v1';
|
|
14224
|
+
const resolver = createApiResolver({ baseUrl: API_BASE, token: () => localStorage.getItem('auth_token') });
|
|
14225
|
+
|
|
14226
|
+
/**
|
|
14227
|
+
* Prepare experience tree for rendering.
|
|
14228
|
+
* Attaches metadata.dataSources to the root node and remaps
|
|
14229
|
+
* dataSource slugs to use definition-relative naming.
|
|
14230
|
+
*
|
|
14231
|
+
* @param definition - The main blueprint definition
|
|
14232
|
+
* @param allDefinitions - ALL definitions from the API (used for slug resolution)
|
|
14233
|
+
*/
|
|
14234
|
+
function prepareTree(definition, allDefinitions) {
|
|
14235
|
+
const exp = definition.experience;
|
|
14236
|
+
if (!exp || typeof exp !== 'object') return null;
|
|
14237
|
+
|
|
14238
|
+
const meta = definition.metadata || {};
|
|
14239
|
+
const dataSources = meta.dataSources || [];
|
|
14240
|
+
const mutationTargets = meta.mutationTargets || [];
|
|
14241
|
+
|
|
14242
|
+
// Build a slug map from ALL deployed definitions
|
|
14243
|
+
// This resolves bare model names (e.g. "item") to full slugs (e.g. "tutorial-1-item")
|
|
14244
|
+
const blueprintSlug = definition.slug || '';
|
|
14245
|
+
const allSlugs = (allDefinitions || []).map(d => d.slug).filter(Boolean);
|
|
14246
|
+
|
|
14247
|
+
function resolveSlug(bareSlug) {
|
|
14248
|
+
if (!bareSlug) return bareSlug;
|
|
14249
|
+
// Already a full slug (contains hyphen matching a known definition)
|
|
14250
|
+
if (allSlugs.includes(bareSlug)) return bareSlug;
|
|
14251
|
+
// Try blueprint-prefixed slug: "item" \u2192 "tutorial-1-item"
|
|
14252
|
+
const prefixed = blueprintSlug + '-' + bareSlug;
|
|
14253
|
+
if (allSlugs.includes(prefixed)) return prefixed;
|
|
14254
|
+
// Try matching by suffix across all definitions
|
|
14255
|
+
const match = allSlugs.find(s => s.endsWith('-' + bareSlug));
|
|
14256
|
+
if (match) return match;
|
|
14257
|
+
// Return original (will attempt as-is)
|
|
14258
|
+
return bareSlug;
|
|
14259
|
+
}
|
|
14260
|
+
|
|
14261
|
+
// Clone root node and attach dataSources
|
|
14262
|
+
const root = { ...exp };
|
|
14263
|
+
if (dataSources.length > 0 && !root.dataSources) {
|
|
14264
|
+
root.dataSources = dataSources.map(ds => ({
|
|
14265
|
+
...ds,
|
|
14266
|
+
slug: resolveSlug(ds.slug),
|
|
14267
|
+
}));
|
|
14268
|
+
}
|
|
14269
|
+
|
|
14270
|
+
// Remap mutation targets the same way
|
|
14271
|
+
if (mutationTargets.length > 0) {
|
|
14272
|
+
const resolvedTargets = mutationTargets.map(t => resolveSlug(t));
|
|
14273
|
+
root.config = { ...(root.config || {}), _mutationTargets: resolvedTargets };
|
|
14274
|
+
}
|
|
14275
|
+
|
|
14276
|
+
return root;
|
|
14277
|
+
}
|
|
14278
|
+
|
|
14279
|
+
function App() {
|
|
14280
|
+
const [tree, setTree] = useState(null);
|
|
14281
|
+
const [error, setError] = useState(null);
|
|
14282
|
+
|
|
14283
|
+
useEffect(() => {
|
|
14284
|
+
async function loadTree() {
|
|
14629
14285
|
try {
|
|
14630
|
-
const res = await fetch('/
|
|
14286
|
+
const res = await fetch(API_BASE + '/workflow/definitions');
|
|
14631
14287
|
const json = await res.json();
|
|
14632
|
-
const
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
}
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
|
|
14646
|
-
|
|
14288
|
+
const rawItems = json.items || json.data || [];
|
|
14289
|
+
// Flatten: API returns { id, slug, definition: { experience, ... } }
|
|
14290
|
+
// Merge definition fields up to the top level for easier access
|
|
14291
|
+
const items = rawItems.map(d => {
|
|
14292
|
+
const def = d.definition || {};
|
|
14293
|
+
return { ...d, ...def, definition: undefined };
|
|
14294
|
+
});
|
|
14295
|
+
// Find the main blueprint definition (has experience tree)
|
|
14296
|
+
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];
|
|
14297
|
+
if (main?.experience) {
|
|
14298
|
+
const prepared = prepareTree(main, items);
|
|
14299
|
+
if (prepared) {
|
|
14300
|
+
setTree(prepared);
|
|
14301
|
+
return;
|
|
14302
|
+
}
|
|
14303
|
+
}
|
|
14304
|
+
if (main) {
|
|
14305
|
+
// No experience tree \u2014 show definition info
|
|
14306
|
+
setTree({
|
|
14307
|
+
type: 'Stack',
|
|
14308
|
+
props: { style: { padding: 40, gap: 16 } },
|
|
14309
|
+
children: [
|
|
14310
|
+
{ type: 'Text', props: { children: main.name || main.slug, style: { fontSize: 24, fontWeight: 'bold' } } },
|
|
14311
|
+
{ type: 'Text', props: { children: (main.states?.length || 0) + ' states, ' + (main.fields?.length || 0) + ' fields', style: { color: '#666' } } },
|
|
14312
|
+
...items.map((d, i) => ({
|
|
14313
|
+
type: 'Card',
|
|
14314
|
+
props: { key: i, style: { padding: 16, border: '1px solid #ddd', borderRadius: 8 } },
|
|
14315
|
+
children: [
|
|
14316
|
+
{ type: 'Text', props: { children: d.name || d.slug, style: { fontWeight: 600 } } },
|
|
14317
|
+
{ type: 'Text', props: { children: 'slug: ' + d.slug + ' | ' + (d.states?.length || 0) + ' states', style: { fontSize: 13, color: '#888' } } },
|
|
14318
|
+
],
|
|
14319
|
+
})),
|
|
14320
|
+
],
|
|
14321
|
+
});
|
|
14322
|
+
}
|
|
14647
14323
|
} catch (e) {
|
|
14648
|
-
|
|
14324
|
+
setError(e.message);
|
|
14649
14325
|
}
|
|
14650
14326
|
}
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
|
|
14327
|
+
loadTree();
|
|
14328
|
+
}, []);
|
|
14329
|
+
|
|
14330
|
+
if (error) return React.createElement('div', { style: { padding: 40 } },
|
|
14331
|
+
React.createElement('h1', null, 'MindMatrix Dev'),
|
|
14332
|
+
React.createElement('p', { style: { color: '#c00' } }, 'Error: ' + error)
|
|
14333
|
+
);
|
|
14334
|
+
|
|
14335
|
+
if (!tree) return React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh' } },
|
|
14336
|
+
React.createElement('p', null, 'Loading...')
|
|
14337
|
+
);
|
|
14338
|
+
|
|
14339
|
+
// If tree has 'component' field, use ExperienceRenderer; otherwise legacy DevPlayer
|
|
14340
|
+
if (tree.component) {
|
|
14341
|
+
return React.createElement(PlayerProvider, { resolver },
|
|
14342
|
+
React.createElement(ExperienceRenderer, { tree, className: 'mm-experience-root' })
|
|
14343
|
+
);
|
|
14344
|
+
}
|
|
14345
|
+
|
|
14346
|
+
return React.createElement(DevPlayer, { tree, title: document.title || 'MindMatrix Dev' });
|
|
14347
|
+
}
|
|
14348
|
+
|
|
14349
|
+
createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
14350
|
+
`;
|
|
14351
|
+
}
|
|
14352
|
+
};
|
|
14661
14353
|
let deployInFlight = false;
|
|
14662
14354
|
const compileDeployPlugin = {
|
|
14663
14355
|
name: "mindmatrix-dev-compile-deploy",
|
|
@@ -14688,16 +14380,16 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14688
14380
|
}
|
|
14689
14381
|
};
|
|
14690
14382
|
const viteConfig = {
|
|
14691
|
-
//
|
|
14692
|
-
root:
|
|
14693
|
-
// Pre-bundle React
|
|
14383
|
+
// Use the blueprint directory as Vite root (has node_modules with React).
|
|
14384
|
+
root: process.cwd(),
|
|
14385
|
+
// Pre-bundle React and the player for fast dev startup.
|
|
14694
14386
|
optimizeDeps: { include: ["react", "react-dom/client"] },
|
|
14695
14387
|
server: {
|
|
14696
14388
|
port,
|
|
14697
14389
|
open,
|
|
14698
14390
|
host: true,
|
|
14699
14391
|
// Allow serving files from the real project directory (fs.allow).
|
|
14700
|
-
fs: { allow: [
|
|
14392
|
+
fs: { allow: [process.cwd(), ".."] },
|
|
14701
14393
|
proxy: {
|
|
14702
14394
|
"/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
|
|
14703
14395
|
"/health": { target: proxyTarget, changeOrigin: true, secure: true },
|
|
@@ -14707,6 +14399,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14707
14399
|
plugins: [
|
|
14708
14400
|
mindmatrixReact(pluginOpts),
|
|
14709
14401
|
compileDeployPlugin,
|
|
14402
|
+
devEntryPlugin,
|
|
14710
14403
|
devPlayerPlugin,
|
|
14711
14404
|
{ name: "mindmatrix-error-overlay", configureServer(server) {
|
|
14712
14405
|
server.middlewares.use(errorOverlayMiddleware());
|
|
@@ -14714,8 +14407,8 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14714
14407
|
],
|
|
14715
14408
|
logLevel: "warn"
|
|
14716
14409
|
};
|
|
14717
|
-
const { createServer
|
|
14718
|
-
const vite = await
|
|
14410
|
+
const { createServer } = await import("vite");
|
|
14411
|
+
const vite = await createServer(viteConfig);
|
|
14719
14412
|
await vite.listen();
|
|
14720
14413
|
const resolvedPort = vite.config.server.port ?? port;
|
|
14721
14414
|
if (enableWs && vite.httpServer) {
|
|
@@ -14733,7 +14426,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14733
14426
|
} catch {
|
|
14734
14427
|
}
|
|
14735
14428
|
}
|
|
14736
|
-
printBanner({ port: resolvedPort, apiUrl
|
|
14429
|
+
printBanner({ port: resolvedPort, apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
|
|
14737
14430
|
return {
|
|
14738
14431
|
vite,
|
|
14739
14432
|
port: resolvedPort,
|
|
@@ -14765,14 +14458,6 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
14765
14458
|
clients.clear();
|
|
14766
14459
|
currentErrors = null;
|
|
14767
14460
|
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
14461
|
}
|
|
14777
14462
|
};
|
|
14778
14463
|
}
|