@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/cli/index.js
CHANGED
|
@@ -6469,7 +6469,8 @@ function convertOnEvent(sub) {
|
|
|
6469
6469
|
};
|
|
6470
6470
|
}
|
|
6471
6471
|
function emitIR(extracted) {
|
|
6472
|
-
const { slug, name, version, description, category, fields, states, transitions } = extracted;
|
|
6472
|
+
const { slug, name, version, description, category: rawCategory, fields, states, transitions } = extracted;
|
|
6473
|
+
const category = Array.isArray(rawCategory) ? rawCategory : [rawCategory];
|
|
6473
6474
|
const stateArray = Array.from(states.values());
|
|
6474
6475
|
if (stateArray.length === 0) {
|
|
6475
6476
|
stateArray.push({
|
|
@@ -6857,13 +6858,15 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
6857
6858
|
}
|
|
6858
6859
|
]
|
|
6859
6860
|
});
|
|
6860
|
-
const
|
|
6861
|
+
const rawCat = extracted.category;
|
|
6861
6862
|
let categoryArray;
|
|
6862
|
-
if (
|
|
6863
|
-
|
|
6863
|
+
if (Array.isArray(rawCat)) {
|
|
6864
|
+
categoryArray = rawCat;
|
|
6865
|
+
} else if (rawCat.includes("/")) {
|
|
6866
|
+
const [primary, ...tags] = rawCat.split("/");
|
|
6864
6867
|
categoryArray = (0, import_player_core.normalizeCategory)(primary, ...tags);
|
|
6865
6868
|
} else {
|
|
6866
|
-
categoryArray = [
|
|
6869
|
+
categoryArray = [rawCat];
|
|
6867
6870
|
}
|
|
6868
6871
|
return {
|
|
6869
6872
|
slug: ir.slug,
|
|
@@ -7010,7 +7013,7 @@ function compilerStateToWorkflow(state, metadata) {
|
|
|
7010
7013
|
name: metadata.name || "Workflow",
|
|
7011
7014
|
version: metadata.version || "0.1.0",
|
|
7012
7015
|
description: metadata.description,
|
|
7013
|
-
category: metadata.category || "workflow",
|
|
7016
|
+
category: metadata.categoryArray ? metadata.categoryArray : [metadata.category || "workflow"],
|
|
7014
7017
|
fields: state.fields || [],
|
|
7015
7018
|
states: state.states || /* @__PURE__ */ new Map(),
|
|
7016
7019
|
transitions: state.transitions || [],
|
|
@@ -7954,7 +7957,7 @@ function extractRouterWorkflow(pages, options = {}) {
|
|
|
7954
7957
|
name: "Router",
|
|
7955
7958
|
version: "1.0.0",
|
|
7956
7959
|
description: "Auto-derived router workflow from file-based routing",
|
|
7957
|
-
category: "router",
|
|
7960
|
+
category: ["router"],
|
|
7958
7961
|
fields,
|
|
7959
7962
|
states,
|
|
7960
7963
|
transitions,
|
|
@@ -8053,7 +8056,8 @@ function compileModel(filename, source, options = {}) {
|
|
|
8053
8056
|
parserOpts: { plugins: parserPlugins, attachComment: true }
|
|
8054
8057
|
});
|
|
8055
8058
|
const ir = babelResult?.metadata?.mindmatrixIR ?? createEmptyModelIR(interfaceName);
|
|
8056
|
-
|
|
8059
|
+
const catOverride = options.categoryOverride || annotation.category || "data";
|
|
8060
|
+
ir.category = Array.isArray(catOverride) ? catOverride : [catOverride];
|
|
8057
8061
|
if (options.slugOverride) {
|
|
8058
8062
|
ir.slug = options.slugOverride;
|
|
8059
8063
|
}
|
|
@@ -8117,7 +8121,7 @@ function createEmptyModelIR(interfaceName) {
|
|
|
8117
8121
|
name: interfaceName,
|
|
8118
8122
|
version: "1.0.0",
|
|
8119
8123
|
description: "Data model: " + interfaceName,
|
|
8120
|
-
category: "data",
|
|
8124
|
+
category: ["data"],
|
|
8121
8125
|
fields: [],
|
|
8122
8126
|
states: [{
|
|
8123
8127
|
name: "draft",
|
|
@@ -8285,7 +8289,7 @@ function buildRouterIR(routes, layouts, allParams, slugPrefix) {
|
|
|
8285
8289
|
name: "Router",
|
|
8286
8290
|
version: "1.0.0",
|
|
8287
8291
|
description: "Auto-generated router from app/ directory structure",
|
|
8288
|
-
category: "router",
|
|
8292
|
+
category: ["router"],
|
|
8289
8293
|
fields,
|
|
8290
8294
|
states,
|
|
8291
8295
|
transitions,
|
|
@@ -8534,7 +8538,7 @@ function extractAction(source, filename) {
|
|
|
8534
8538
|
slug,
|
|
8535
8539
|
name: humanName,
|
|
8536
8540
|
version: "0.1.0",
|
|
8537
|
-
category: "action",
|
|
8541
|
+
category: ["action"],
|
|
8538
8542
|
fields,
|
|
8539
8543
|
states: states2,
|
|
8540
8544
|
transitions: transitions2,
|
|
@@ -8586,7 +8590,7 @@ function extractAction(source, filename) {
|
|
|
8586
8590
|
slug,
|
|
8587
8591
|
name: humanName,
|
|
8588
8592
|
version: "0.1.0",
|
|
8589
|
-
category: "action",
|
|
8593
|
+
category: ["action"],
|
|
8590
8594
|
fields,
|
|
8591
8595
|
states,
|
|
8592
8596
|
transitions,
|
|
@@ -10023,7 +10027,7 @@ function applyConfig(ir, config) {
|
|
|
10023
10027
|
if (config.name) ir.name = config.name;
|
|
10024
10028
|
if (config.version) ir.version = config.version;
|
|
10025
10029
|
if (config.description !== void 0) ir.description = config.description;
|
|
10026
|
-
if (config.category) ir.category = config.category;
|
|
10030
|
+
if (config.category) ir.category = Array.isArray(config.category) ? config.category : [config.category];
|
|
10027
10031
|
if (!ir.metadata) ir.metadata = {};
|
|
10028
10032
|
ir.metadata.stable_id = "def-" + ir.slug;
|
|
10029
10033
|
ir.metadata.provenance = {
|
|
@@ -10039,7 +10043,7 @@ function createEmptyIR(config) {
|
|
|
10039
10043
|
name: config.name || "Project",
|
|
10040
10044
|
version: config.version || "0.1.0",
|
|
10041
10045
|
description: config.description,
|
|
10042
|
-
category: config.category || "workflow",
|
|
10046
|
+
category: Array.isArray(config.category) ? config.category : [config.category || "workflow"],
|
|
10043
10047
|
fields: [],
|
|
10044
10048
|
states: [{
|
|
10045
10049
|
name: "draft",
|
|
@@ -10197,8 +10201,10 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
|
|
|
10197
10201
|
if (isWorkflowFile(filename)) {
|
|
10198
10202
|
workflowIRs.push(ir);
|
|
10199
10203
|
} else if (isModelFile2(filename)) {
|
|
10200
|
-
|
|
10201
|
-
|
|
10204
|
+
const cat = ir.category;
|
|
10205
|
+
const isDefault = !cat || cat === "workflow" || Array.isArray(cat) && cat.length === 1 && cat[0] === "workflow";
|
|
10206
|
+
if (isDefault) {
|
|
10207
|
+
ir.category = ["data"];
|
|
10202
10208
|
}
|
|
10203
10209
|
modelIRs.push(ir);
|
|
10204
10210
|
} else if (isServerActionFile2(filename)) {
|
|
@@ -12187,7 +12193,8 @@ function determineSplitStrategy(def) {
|
|
|
12187
12193
|
const stateCount = def.states.length;
|
|
12188
12194
|
const hasExperience = !!def.experience || !!def.views?.default;
|
|
12189
12195
|
const hasChildren = Array.isArray(def.metadata?.childSlugs) && def.metadata.childSlugs.length > 0;
|
|
12190
|
-
|
|
12196
|
+
const catArr = Array.isArray(def.category) ? def.category : [def.category];
|
|
12197
|
+
if (catArr.includes("blueprint") || hasChildren) {
|
|
12191
12198
|
return {
|
|
12192
12199
|
tier: "large",
|
|
12193
12200
|
emitModels: fieldCount > 0,
|
|
@@ -12474,6 +12481,10 @@ var project_decompiler_exports = {};
|
|
|
12474
12481
|
__export(project_decompiler_exports, {
|
|
12475
12482
|
decompileProjectEnhanced: () => decompileProjectEnhanced
|
|
12476
12483
|
});
|
|
12484
|
+
function hasCategory(cat, target) {
|
|
12485
|
+
if (!cat) return false;
|
|
12486
|
+
return Array.isArray(cat) ? cat.includes(target) : cat === target;
|
|
12487
|
+
}
|
|
12477
12488
|
function pascalCase3(slug) {
|
|
12478
12489
|
return slug.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
|
|
12479
12490
|
}
|
|
@@ -12945,7 +12956,7 @@ function generateLayoutFile(slug, roles) {
|
|
|
12945
12956
|
function extractRouteTable(childDefinitions) {
|
|
12946
12957
|
if (!childDefinitions) return [];
|
|
12947
12958
|
const router = childDefinitions.find(
|
|
12948
|
-
(c) => c.slug.endsWith("-router") || c.category
|
|
12959
|
+
(c) => c.slug.endsWith("-router") || hasCategory(c.category, "router")
|
|
12949
12960
|
);
|
|
12950
12961
|
if (!router?.states) return [];
|
|
12951
12962
|
return router.states.filter((s) => s.description?.startsWith("Route:")).map((s) => {
|
|
@@ -13073,7 +13084,7 @@ function extractPageSections(experience, childDefinitions) {
|
|
|
13073
13084
|
if (routerExtracted) return routerExtracted;
|
|
13074
13085
|
const routeTable = extractRouteTable(childDefinitions);
|
|
13075
13086
|
const childSlugs = new Set(
|
|
13076
|
-
(childDefinitions || []).filter((c) => !c.slug.endsWith("-router") && c.category
|
|
13087
|
+
(childDefinitions || []).filter((c) => !c.slug.endsWith("-router") && !hasCategory(c.category, "router")).map((c) => c.slug)
|
|
13077
13088
|
);
|
|
13078
13089
|
const pages = [];
|
|
13079
13090
|
const childViews = [];
|
|
@@ -13242,7 +13253,7 @@ function generatePageFileFromSection(page, modelSlugToPath) {
|
|
|
13242
13253
|
slug: page.slug,
|
|
13243
13254
|
name: page.componentName,
|
|
13244
13255
|
version: "1.0.0",
|
|
13245
|
-
category: "
|
|
13256
|
+
category: ["view"],
|
|
13246
13257
|
states: [],
|
|
13247
13258
|
transitions: [],
|
|
13248
13259
|
fields,
|
|
@@ -13497,7 +13508,7 @@ function generateComponentFromDefinition(name, experience, props) {
|
|
|
13497
13508
|
slug: name.toLowerCase(),
|
|
13498
13509
|
name,
|
|
13499
13510
|
version: "1.0.0",
|
|
13500
|
-
category: "component",
|
|
13511
|
+
category: ["component"],
|
|
13501
13512
|
states: [],
|
|
13502
13513
|
transitions: [],
|
|
13503
13514
|
fields: [],
|
|
@@ -13734,7 +13745,7 @@ function decompileProjectEnhanced(definition) {
|
|
|
13734
13745
|
if (definition.childDefinitions) {
|
|
13735
13746
|
for (const child of definition.childDefinitions) {
|
|
13736
13747
|
const cs = child.slug;
|
|
13737
|
-
if (!cs.endsWith("-router") && child.category
|
|
13748
|
+
if (!cs.endsWith("-router") && !hasCategory(child.category, "router")) {
|
|
13738
13749
|
modelSlugToPath.set(cs, `models/${cs}.ts`);
|
|
13739
13750
|
}
|
|
13740
13751
|
}
|
|
@@ -13755,7 +13766,7 @@ function decompileProjectEnhanced(definition) {
|
|
|
13755
13766
|
for (const child of definition.childDefinitions) {
|
|
13756
13767
|
const childSlug = child.slug;
|
|
13757
13768
|
if (childSlug === slug) continue;
|
|
13758
|
-
const isRouter = childSlug.endsWith("-router") || child.category
|
|
13769
|
+
const isRouter = childSlug.endsWith("-router") || hasCategory(child.category, "router");
|
|
13759
13770
|
if (isRouter && routerIsCompilerGenerated) continue;
|
|
13760
13771
|
if (!mergedChildren.has(childSlug)) {
|
|
13761
13772
|
mergedChildren.set(childSlug, { ...child });
|
|
@@ -13810,7 +13821,7 @@ function decompileProjectEnhanced(definition) {
|
|
|
13810
13821
|
if (child.version && child.version !== "0.1.0" && (!existing.version || existing.version === "0.1.0")) {
|
|
13811
13822
|
existing.version = child.version;
|
|
13812
13823
|
}
|
|
13813
|
-
if (child.category && child.category
|
|
13824
|
+
if (child.category && !hasCategory(child.category, "data") && (!existing.category || hasCategory(existing.category, "data"))) {
|
|
13814
13825
|
existing.category = child.category;
|
|
13815
13826
|
}
|
|
13816
13827
|
if (child.description && !existing.description) {
|
|
@@ -13820,8 +13831,8 @@ function decompileProjectEnhanced(definition) {
|
|
|
13820
13831
|
}
|
|
13821
13832
|
}
|
|
13822
13833
|
for (const [childSlug, child] of mergedChildren) {
|
|
13823
|
-
const isRouter = childSlug.endsWith("-router") || child.category
|
|
13824
|
-
const isAction = child.category
|
|
13834
|
+
const isRouter = childSlug.endsWith("-router") || hasCategory(child.category, "router");
|
|
13835
|
+
const isAction = hasCategory(child.category, "action");
|
|
13825
13836
|
const childTransitions = isRouter ? reduceRouterTransitions(child.transitions, child.states) : child.transitions;
|
|
13826
13837
|
if (isAction) {
|
|
13827
13838
|
const actionFilePath = `actions/${childSlug}.ts`;
|
|
@@ -14078,14 +14089,12 @@ async function deploy(options) {
|
|
|
14078
14089
|
}
|
|
14079
14090
|
async function fetchExistingDefinition(apiUrl, token, slug) {
|
|
14080
14091
|
try {
|
|
14081
|
-
const res = await fetch(`${apiUrl}/workflow/definitions
|
|
14092
|
+
const res = await fetch(`${apiUrl}/workflow/definitions/${encodeURIComponent(slug)}`, {
|
|
14082
14093
|
headers: { Authorization: `Bearer ${token}` }
|
|
14083
14094
|
});
|
|
14084
14095
|
if (!res.ok) return null;
|
|
14085
|
-
const
|
|
14086
|
-
|
|
14087
|
-
if (!definitions || definitions.length === 0) return null;
|
|
14088
|
-
const def = definitions[0];
|
|
14096
|
+
const def = await res.json();
|
|
14097
|
+
if (!def || !def.id) return null;
|
|
14089
14098
|
return {
|
|
14090
14099
|
id: def.id,
|
|
14091
14100
|
slug: def.slug,
|
|
@@ -14103,7 +14112,7 @@ async function createDefinition(apiUrl, token, ir) {
|
|
|
14103
14112
|
"Content-Type": "application/json",
|
|
14104
14113
|
Authorization: `Bearer ${token}`
|
|
14105
14114
|
},
|
|
14106
|
-
body: JSON.stringify(ir)
|
|
14115
|
+
body: JSON.stringify({ ...ir, visibility: "PUBLIC" })
|
|
14107
14116
|
});
|
|
14108
14117
|
if (!res.ok) {
|
|
14109
14118
|
const errorText = await res.text();
|
|
@@ -14883,7 +14892,7 @@ function mindmatrixReact(options) {
|
|
|
14883
14892
|
slug: ir.slug,
|
|
14884
14893
|
name: ir.name,
|
|
14885
14894
|
version: ir.version,
|
|
14886
|
-
category: ir.category || "workflow",
|
|
14895
|
+
category: ir.category || ["workflow"],
|
|
14887
14896
|
fields: ir.fields || [],
|
|
14888
14897
|
states: ir.states || [],
|
|
14889
14898
|
transitions: ir.transitions || [],
|
|
@@ -15033,431 +15042,6 @@ var init_vite = __esm({
|
|
|
15033
15042
|
}
|
|
15034
15043
|
});
|
|
15035
15044
|
|
|
15036
|
-
// src/cli/local-server.ts
|
|
15037
|
-
async function startLocalServer(options = {}) {
|
|
15038
|
-
const { port = 4200, noAuth = true } = options;
|
|
15039
|
-
const store = new MemoryStore();
|
|
15040
|
-
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
15041
|
-
function json(res, status, body) {
|
|
15042
|
-
const data = JSON.stringify(body);
|
|
15043
|
-
res.writeHead(status, {
|
|
15044
|
-
"Content-Type": "application/json",
|
|
15045
|
-
"Access-Control-Allow-Origin": "*",
|
|
15046
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
15047
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
15048
|
-
"Content-Length": Buffer.byteLength(data)
|
|
15049
|
-
});
|
|
15050
|
-
res.end(data);
|
|
15051
|
-
}
|
|
15052
|
-
function readBody(req) {
|
|
15053
|
-
return new Promise((resolve7, reject) => {
|
|
15054
|
-
const chunks = [];
|
|
15055
|
-
req.on("data", (chunk) => chunks.push(chunk));
|
|
15056
|
-
req.on("end", () => resolve7(Buffer.concat(chunks).toString()));
|
|
15057
|
-
req.on("error", reject);
|
|
15058
|
-
});
|
|
15059
|
-
}
|
|
15060
|
-
function parseQuery(url) {
|
|
15061
|
-
const idx = url.indexOf("?");
|
|
15062
|
-
if (idx === -1) return {};
|
|
15063
|
-
const params = {};
|
|
15064
|
-
const qs = url.slice(idx + 1);
|
|
15065
|
-
for (const pair of qs.split("&")) {
|
|
15066
|
-
const [k, v] = pair.split("=");
|
|
15067
|
-
if (k) params[decodeURIComponent(k)] = decodeURIComponent(v ?? "");
|
|
15068
|
-
}
|
|
15069
|
-
return params;
|
|
15070
|
-
}
|
|
15071
|
-
const server = http.createServer(async (req, res) => {
|
|
15072
|
-
const method = req.method?.toUpperCase() ?? "GET";
|
|
15073
|
-
const rawUrl = req.url ?? "/";
|
|
15074
|
-
const queryStart = rawUrl.indexOf("?");
|
|
15075
|
-
const path = queryStart >= 0 ? rawUrl.slice(0, queryStart) : rawUrl;
|
|
15076
|
-
const query = parseQuery(rawUrl);
|
|
15077
|
-
if (method === "OPTIONS") {
|
|
15078
|
-
res.writeHead(204, {
|
|
15079
|
-
"Access-Control-Allow-Origin": "*",
|
|
15080
|
-
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
15081
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
15082
|
-
"Access-Control-Max-Age": "86400"
|
|
15083
|
-
});
|
|
15084
|
-
res.end();
|
|
15085
|
-
return;
|
|
15086
|
-
}
|
|
15087
|
-
try {
|
|
15088
|
-
if (path === "/health" && method === "GET") {
|
|
15089
|
-
return json(res, 200, {
|
|
15090
|
-
status: "ok",
|
|
15091
|
-
service: "mm-local-dev",
|
|
15092
|
-
mode: "in-memory",
|
|
15093
|
-
started_at: startedAt,
|
|
15094
|
-
definitions: store.definitions.size,
|
|
15095
|
-
instances: store.instances.size
|
|
15096
|
-
});
|
|
15097
|
-
}
|
|
15098
|
-
if (path === "/api/v1/auth/login" && (method === "POST" || method === "GET")) {
|
|
15099
|
-
return json(res, 200, {
|
|
15100
|
-
token: "dev-token-local",
|
|
15101
|
-
user: {
|
|
15102
|
-
id: "dev-user-001",
|
|
15103
|
-
email: "dev@localhost",
|
|
15104
|
-
role: "admin",
|
|
15105
|
-
name: "Local Developer"
|
|
15106
|
-
}
|
|
15107
|
-
});
|
|
15108
|
-
}
|
|
15109
|
-
if (path === "/api/v1/workflow/definitions" && method === "GET") {
|
|
15110
|
-
const result = store.listDefinitions({
|
|
15111
|
-
category: query.category,
|
|
15112
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
15113
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
15114
|
-
});
|
|
15115
|
-
if (query.slug) {
|
|
15116
|
-
const def = store.getDefinition(query.slug);
|
|
15117
|
-
return json(res, 200, { items: def ? [def] : [], total: def ? 1 : 0 });
|
|
15118
|
-
}
|
|
15119
|
-
return json(res, 200, result);
|
|
15120
|
-
}
|
|
15121
|
-
const defMatch = path.match(/^\/api\/v1\/workflow\/definitions\/([^/]+)$/);
|
|
15122
|
-
if (defMatch && method === "GET") {
|
|
15123
|
-
const def = store.getDefinition(defMatch[1]);
|
|
15124
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
15125
|
-
return json(res, 200, def);
|
|
15126
|
-
}
|
|
15127
|
-
if (path === "/api/v1/workflow/definitions" && method === "POST") {
|
|
15128
|
-
const body = JSON.parse(await readBody(req));
|
|
15129
|
-
const def = store.createDefinition(body);
|
|
15130
|
-
return json(res, 201, def);
|
|
15131
|
-
}
|
|
15132
|
-
if (defMatch && method === "PATCH") {
|
|
15133
|
-
const body = JSON.parse(await readBody(req));
|
|
15134
|
-
const updated = store.patchDefinition(defMatch[1], body);
|
|
15135
|
-
if (!updated) return json(res, 404, { error: "Not found" });
|
|
15136
|
-
return json(res, 200, updated);
|
|
15137
|
-
}
|
|
15138
|
-
if (defMatch && method === "DELETE") {
|
|
15139
|
-
const deleted = store.deleteDefinition(defMatch[1]);
|
|
15140
|
-
if (!deleted) return json(res, 404, { error: "Not found" });
|
|
15141
|
-
return json(res, 204, null);
|
|
15142
|
-
}
|
|
15143
|
-
if (path === "/api/v1/workflow/instances" && method === "GET") {
|
|
15144
|
-
const result = store.listInstances({
|
|
15145
|
-
definition_id: query.definition_id,
|
|
15146
|
-
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
15147
|
-
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
15148
|
-
});
|
|
15149
|
-
return json(res, 200, result);
|
|
15150
|
-
}
|
|
15151
|
-
if (path === "/api/v1/workflow/instances" && method === "POST") {
|
|
15152
|
-
const body = JSON.parse(await readBody(req));
|
|
15153
|
-
const inst = store.createInstance(body);
|
|
15154
|
-
if (!inst) return json(res, 404, { error: "Definition not found" });
|
|
15155
|
-
return json(res, 201, inst);
|
|
15156
|
-
}
|
|
15157
|
-
const instMatch = path.match(/^\/api\/v1\/workflow\/instances\/([^/]+)$/);
|
|
15158
|
-
if (instMatch && method === "GET") {
|
|
15159
|
-
const inst = store.getInstance(instMatch[1]);
|
|
15160
|
-
if (!inst) return json(res, 404, { error: "Not found" });
|
|
15161
|
-
return json(res, 200, inst);
|
|
15162
|
-
}
|
|
15163
|
-
if (path === "/api/v1/workflow/execute-action" && method === "POST") {
|
|
15164
|
-
const body = JSON.parse(await readBody(req));
|
|
15165
|
-
const result = store.executeAction(body);
|
|
15166
|
-
return json(res, 200, result);
|
|
15167
|
-
}
|
|
15168
|
-
const dataMatch = path.match(/^\/api\/v1\/data\/([^/]+)$/);
|
|
15169
|
-
if (dataMatch && method === "GET") {
|
|
15170
|
-
const def = store.getDefinition(dataMatch[1]);
|
|
15171
|
-
if (!def) return json(res, 404, { error: "Not found" });
|
|
15172
|
-
const instances = store.listInstances({ definition_id: def.id });
|
|
15173
|
-
return json(res, 200, instances);
|
|
15174
|
-
}
|
|
15175
|
-
if (path.startsWith("/api/v1/")) {
|
|
15176
|
-
return json(res, 501, { error: "Not implemented in local dev mode", path, method });
|
|
15177
|
-
}
|
|
15178
|
-
return json(res, 404, { error: "Not found", path });
|
|
15179
|
-
} catch (err) {
|
|
15180
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
15181
|
-
console.error(`[mm-local] ${method} ${path} \u2014 Error: ${message}`);
|
|
15182
|
-
return json(res, 500, { error: message });
|
|
15183
|
-
}
|
|
15184
|
-
});
|
|
15185
|
-
return new Promise((resolve7, reject) => {
|
|
15186
|
-
server.on("error", (err) => {
|
|
15187
|
-
if (err.code === "EADDRINUSE") {
|
|
15188
|
-
reject(new Error(`Port ${port} is already in use. Is another server running?`));
|
|
15189
|
-
} else {
|
|
15190
|
-
reject(err);
|
|
15191
|
-
}
|
|
15192
|
-
});
|
|
15193
|
-
server.listen(port, () => {
|
|
15194
|
-
console.log(`[mm-local] Local API server running at http://localhost:${port}`);
|
|
15195
|
-
console.log(`[mm-local] Mode: in-memory (data lost on restart)`);
|
|
15196
|
-
console.log(`[mm-local] Auth: disabled (all requests accepted)`);
|
|
15197
|
-
resolve7({
|
|
15198
|
-
server,
|
|
15199
|
-
port,
|
|
15200
|
-
store,
|
|
15201
|
-
async close() {
|
|
15202
|
-
return new Promise((res) => {
|
|
15203
|
-
server.close(() => {
|
|
15204
|
-
console.log("[mm-local] Local API server stopped");
|
|
15205
|
-
res();
|
|
15206
|
-
});
|
|
15207
|
-
});
|
|
15208
|
-
}
|
|
15209
|
-
});
|
|
15210
|
-
});
|
|
15211
|
-
});
|
|
15212
|
-
}
|
|
15213
|
-
var http, import_node_crypto, MemoryStore;
|
|
15214
|
-
var init_local_server = __esm({
|
|
15215
|
-
"src/cli/local-server.ts"() {
|
|
15216
|
-
"use strict";
|
|
15217
|
-
http = __toESM(require("http"));
|
|
15218
|
-
import_node_crypto = require("crypto");
|
|
15219
|
-
MemoryStore = class {
|
|
15220
|
-
constructor() {
|
|
15221
|
-
this.definitions = /* @__PURE__ */ new Map();
|
|
15222
|
-
this.instances = /* @__PURE__ */ new Map();
|
|
15223
|
-
this.slugIndex = /* @__PURE__ */ new Map();
|
|
15224
|
-
}
|
|
15225
|
-
// slug → id
|
|
15226
|
-
// ── Definitions ──────────────────────────────────────────────────────
|
|
15227
|
-
createDefinition(input) {
|
|
15228
|
-
if (this.slugIndex.has(input.slug)) {
|
|
15229
|
-
const existing = this.definitions.get(this.slugIndex.get(input.slug));
|
|
15230
|
-
if (existing) return existing;
|
|
15231
|
-
}
|
|
15232
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15233
|
-
const def = {
|
|
15234
|
-
id: input.id ?? (0, import_node_crypto.randomUUID)(),
|
|
15235
|
-
slug: input.slug,
|
|
15236
|
-
name: input.name,
|
|
15237
|
-
version: input.version ?? "1.0.0",
|
|
15238
|
-
description: input.description ?? null,
|
|
15239
|
-
category: input.category ?? "workflow",
|
|
15240
|
-
fields: input.fields ?? [],
|
|
15241
|
-
states: input.states ?? [],
|
|
15242
|
-
transitions: input.transitions ?? [],
|
|
15243
|
-
roles: input.roles ?? [],
|
|
15244
|
-
experience: input.experience ?? null,
|
|
15245
|
-
metadata: input.metadata ?? {},
|
|
15246
|
-
child_definitions: input.child_definitions ?? [],
|
|
15247
|
-
is_immutable: input.is_immutable ?? false,
|
|
15248
|
-
tags: input.tags ?? [],
|
|
15249
|
-
inline_tags: input.inline_tags ?? [],
|
|
15250
|
-
created_at: now,
|
|
15251
|
-
updated_at: now
|
|
15252
|
-
};
|
|
15253
|
-
this.definitions.set(def.id, def);
|
|
15254
|
-
this.slugIndex.set(def.slug, def.id);
|
|
15255
|
-
return def;
|
|
15256
|
-
}
|
|
15257
|
-
getDefinition(idOrSlug) {
|
|
15258
|
-
const byId = this.definitions.get(idOrSlug);
|
|
15259
|
-
if (byId) return byId;
|
|
15260
|
-
const id = this.slugIndex.get(idOrSlug);
|
|
15261
|
-
if (id) return this.definitions.get(id);
|
|
15262
|
-
return void 0;
|
|
15263
|
-
}
|
|
15264
|
-
listDefinitions(opts) {
|
|
15265
|
-
let items = Array.from(this.definitions.values());
|
|
15266
|
-
if (opts?.category) {
|
|
15267
|
-
items = items.filter((d) => d.category === opts.category);
|
|
15268
|
-
}
|
|
15269
|
-
const total = items.length;
|
|
15270
|
-
const offset = opts?.offset ?? 0;
|
|
15271
|
-
const limit = opts?.limit ?? 50;
|
|
15272
|
-
items = items.slice(offset, offset + limit);
|
|
15273
|
-
return { items, total };
|
|
15274
|
-
}
|
|
15275
|
-
patchDefinition(id, patch) {
|
|
15276
|
-
const def = this.definitions.get(id);
|
|
15277
|
-
if (!def) return void 0;
|
|
15278
|
-
Object.assign(def, patch, { updated_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
15279
|
-
return def;
|
|
15280
|
-
}
|
|
15281
|
-
deleteDefinition(id) {
|
|
15282
|
-
const def = this.definitions.get(id);
|
|
15283
|
-
if (!def) return false;
|
|
15284
|
-
this.slugIndex.delete(def.slug);
|
|
15285
|
-
this.definitions.delete(id);
|
|
15286
|
-
return true;
|
|
15287
|
-
}
|
|
15288
|
-
// ── Instances ────────────────────────────────────────────────────────
|
|
15289
|
-
createInstance(input) {
|
|
15290
|
-
const def = this.getDefinition(input.definition_id) ?? this.getDefinition(input.definition_slug);
|
|
15291
|
-
if (!def) return null;
|
|
15292
|
-
const initialState = def.states.find((s) => s.type === "START" || s.type === "initial");
|
|
15293
|
-
const stateName = initialState?.name ?? "initial";
|
|
15294
|
-
const stateData = {};
|
|
15295
|
-
for (const field of def.fields) {
|
|
15296
|
-
if (field.default_value !== void 0) {
|
|
15297
|
-
stateData[field.name] = field.default_value;
|
|
15298
|
-
}
|
|
15299
|
-
}
|
|
15300
|
-
Object.assign(stateData, input.state_data ?? {});
|
|
15301
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15302
|
-
const inst = {
|
|
15303
|
-
id: (0, import_node_crypto.randomUUID)(),
|
|
15304
|
-
definition_id: def.id,
|
|
15305
|
-
definition_slug: def.slug,
|
|
15306
|
-
current_state: stateName,
|
|
15307
|
-
state_data: stateData,
|
|
15308
|
-
execution_lock_version: 0,
|
|
15309
|
-
event_log: [{
|
|
15310
|
-
event_type: "transition",
|
|
15311
|
-
message: `Instance created in state '${stateName}'`,
|
|
15312
|
-
timestamp: now
|
|
15313
|
-
}],
|
|
15314
|
-
created_at: now,
|
|
15315
|
-
updated_at: now
|
|
15316
|
-
};
|
|
15317
|
-
this.instances.set(inst.id, inst);
|
|
15318
|
-
return inst;
|
|
15319
|
-
}
|
|
15320
|
-
getInstance(id) {
|
|
15321
|
-
return this.instances.get(id);
|
|
15322
|
-
}
|
|
15323
|
-
listInstances(opts) {
|
|
15324
|
-
let items = Array.from(this.instances.values());
|
|
15325
|
-
if (opts?.definition_id) {
|
|
15326
|
-
items = items.filter((i) => i.definition_id === opts.definition_id);
|
|
15327
|
-
}
|
|
15328
|
-
const total = items.length;
|
|
15329
|
-
const offset = opts?.offset ?? 0;
|
|
15330
|
-
const limit = opts?.limit ?? 50;
|
|
15331
|
-
items = items.slice(offset, offset + limit);
|
|
15332
|
-
return { items, total };
|
|
15333
|
-
}
|
|
15334
|
-
// ── Execute Action (Transition) ──────────────────────────────────────
|
|
15335
|
-
executeAction(input) {
|
|
15336
|
-
const def = this.getDefinition(input.definition_id);
|
|
15337
|
-
if (!def) return { success: false, error: "Definition not found" };
|
|
15338
|
-
let inst;
|
|
15339
|
-
if (input.instance_id) {
|
|
15340
|
-
const existing = this.instances.get(input.instance_id);
|
|
15341
|
-
if (!existing) return { success: false, error: "Instance not found" };
|
|
15342
|
-
inst = existing;
|
|
15343
|
-
} else {
|
|
15344
|
-
const created = this.createInstance({
|
|
15345
|
-
definition_id: def.id,
|
|
15346
|
-
definition_slug: def.slug,
|
|
15347
|
-
state_data: input.payload
|
|
15348
|
-
});
|
|
15349
|
-
if (!created) return { success: false, error: "Failed to create instance" };
|
|
15350
|
-
inst = created;
|
|
15351
|
-
}
|
|
15352
|
-
if (input.payload && input.instance_id) {
|
|
15353
|
-
Object.assign(inst.state_data, input.payload);
|
|
15354
|
-
}
|
|
15355
|
-
const transition = def.transitions.find((t27) => t27.name === input.action_name && t27.from.includes(inst.current_state));
|
|
15356
|
-
if (!transition) {
|
|
15357
|
-
return {
|
|
15358
|
-
success: false,
|
|
15359
|
-
instance_id: inst.id,
|
|
15360
|
-
from_state: inst.current_state,
|
|
15361
|
-
to_state: null,
|
|
15362
|
-
state_data: inst.state_data,
|
|
15363
|
-
error: `No transition '${input.action_name}' from state '${inst.current_state}'`
|
|
15364
|
-
};
|
|
15365
|
-
}
|
|
15366
|
-
const fromState = inst.current_state;
|
|
15367
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15368
|
-
const events = [];
|
|
15369
|
-
let lastEvalResult = null;
|
|
15370
|
-
events.push({ event_type: "transition", message: `Transition '${transition.name}' started: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
15371
|
-
for (const action of transition.actions ?? []) {
|
|
15372
|
-
try {
|
|
15373
|
-
if (action.type === "set_field") {
|
|
15374
|
-
const field = action.config?.field;
|
|
15375
|
-
if (action.config?.expression) {
|
|
15376
|
-
const expr = action.config.expression;
|
|
15377
|
-
const result = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
15378
|
-
inst.state_data[field] = result;
|
|
15379
|
-
} else if (action.config?.value !== void 0) {
|
|
15380
|
-
inst.state_data[field] = action.config.value;
|
|
15381
|
-
}
|
|
15382
|
-
events.push({ event_type: "action_executed", message: `transition action 'set_field' succeeded`, timestamp: now });
|
|
15383
|
-
} else if (action.type === "eval") {
|
|
15384
|
-
const expr = action.config?.expression;
|
|
15385
|
-
lastEvalResult = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
15386
|
-
events.push({ event_type: "action_executed", message: `transition action 'eval' succeeded`, timestamp: now });
|
|
15387
|
-
} else {
|
|
15388
|
-
events.push({ event_type: "action_executed", message: `transition action '${action.type}' succeeded (no-op in local mode)`, timestamp: now });
|
|
15389
|
-
}
|
|
15390
|
-
} catch (err) {
|
|
15391
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
15392
|
-
events.push({ event_type: "action_failed", message: `transition action '${action.type}' failed: ${msg}`, timestamp: now });
|
|
15393
|
-
return {
|
|
15394
|
-
success: false,
|
|
15395
|
-
instance_id: inst.id,
|
|
15396
|
-
from_state: fromState,
|
|
15397
|
-
to_state: null,
|
|
15398
|
-
state_data: inst.state_data,
|
|
15399
|
-
event_log: events,
|
|
15400
|
-
error: `transition action failed: ${msg}`
|
|
15401
|
-
};
|
|
15402
|
-
}
|
|
15403
|
-
}
|
|
15404
|
-
inst.current_state = transition.to;
|
|
15405
|
-
inst.execution_lock_version++;
|
|
15406
|
-
inst.updated_at = now;
|
|
15407
|
-
events.push({ event_type: "transition", message: `State changed: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
15408
|
-
inst.event_log.push(...events);
|
|
15409
|
-
return {
|
|
15410
|
-
success: true,
|
|
15411
|
-
instance_id: inst.id,
|
|
15412
|
-
from_state: fromState,
|
|
15413
|
-
to_state: transition.to,
|
|
15414
|
-
state_data: inst.state_data,
|
|
15415
|
-
result: lastEvalResult,
|
|
15416
|
-
event_log: events
|
|
15417
|
-
};
|
|
15418
|
-
}
|
|
15419
|
-
/**
|
|
15420
|
-
* Minimal expression evaluator for local dev mode.
|
|
15421
|
-
* Handles: field references, arithmetic, string literals, simple comparisons.
|
|
15422
|
-
* Does NOT handle: while loops, if/else, function calls, multi-statement blocks.
|
|
15423
|
-
* For full evaluation, use mm-napi when available.
|
|
15424
|
-
*/
|
|
15425
|
-
evaluateSimpleExpression(expr, context) {
|
|
15426
|
-
if (context[expr] !== void 0) return context[expr];
|
|
15427
|
-
const arithMatch = expr.match(/^(\w+)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/);
|
|
15428
|
-
if (arithMatch) {
|
|
15429
|
-
const [, field, op, numStr] = arithMatch;
|
|
15430
|
-
const left = Number(context[field] ?? 0);
|
|
15431
|
-
const right = Number(numStr);
|
|
15432
|
-
switch (op) {
|
|
15433
|
-
case "+":
|
|
15434
|
-
return left + right;
|
|
15435
|
-
case "-":
|
|
15436
|
-
return left - right;
|
|
15437
|
-
case "*":
|
|
15438
|
-
return left * right;
|
|
15439
|
-
case "/":
|
|
15440
|
-
return right !== 0 ? left / right : 0;
|
|
15441
|
-
}
|
|
15442
|
-
}
|
|
15443
|
-
if (/^\d+(\.\d+)?$/.test(expr.trim())) {
|
|
15444
|
-
return Number(expr.trim());
|
|
15445
|
-
}
|
|
15446
|
-
const strMatch = expr.match(/^["'](.*)["']$/);
|
|
15447
|
-
if (strMatch) return strMatch[1];
|
|
15448
|
-
try {
|
|
15449
|
-
const keys = Object.keys(context);
|
|
15450
|
-
const values = Object.values(context);
|
|
15451
|
-
const fn = new Function(...keys, `"use strict"; return (${expr});`);
|
|
15452
|
-
return fn(...values);
|
|
15453
|
-
} catch {
|
|
15454
|
-
return null;
|
|
15455
|
-
}
|
|
15456
|
-
}
|
|
15457
|
-
};
|
|
15458
|
-
}
|
|
15459
|
-
});
|
|
15460
|
-
|
|
15461
15045
|
// src/cli/seed.ts
|
|
15462
15046
|
var seed_exports = {};
|
|
15463
15047
|
__export(seed_exports, {
|
|
@@ -15797,34 +15381,33 @@ async function createDevServer(options = {}) {
|
|
|
15797
15381
|
open = false
|
|
15798
15382
|
} = options;
|
|
15799
15383
|
const clients = /* @__PURE__ */ new Set();
|
|
15800
|
-
let localServer = null;
|
|
15801
15384
|
let apiUrl;
|
|
15802
|
-
|
|
15803
|
-
|
|
15804
|
-
|
|
15805
|
-
|
|
15806
|
-
|
|
15807
|
-
|
|
15808
|
-
|
|
15809
|
-
|
|
15810
|
-
|
|
15811
|
-
apiUrl = defaultRemote;
|
|
15812
|
-
} else {
|
|
15813
|
-
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
15814
|
-
if (localHealth.ok) {
|
|
15815
|
-
apiUrl = "http://localhost:4200/api/v1";
|
|
15385
|
+
if (rawApiUrl === "local" || rawApiUrl === "auto") {
|
|
15386
|
+
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
15387
|
+
if (localHealth.ok) {
|
|
15388
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
15389
|
+
} else if (rawApiUrl === "auto") {
|
|
15390
|
+
const defaultRemote = "https://dev.mindmatrix.club/api/v1";
|
|
15391
|
+
const remoteHealth = await checkBackendHealth(defaultRemote);
|
|
15392
|
+
if (remoteHealth.ok) {
|
|
15393
|
+
apiUrl = defaultRemote;
|
|
15816
15394
|
} else {
|
|
15817
|
-
console.
|
|
15818
|
-
|
|
15395
|
+
console.error("[mm-dev] No backend detected. Start the engine first:");
|
|
15396
|
+
console.error(" mmrc dev (auto-starts engine)");
|
|
15397
|
+
console.error(" mmrc engine start (manual start)");
|
|
15398
|
+
console.error("[mm-dev] Or specify a remote API: mmrc dev --api-url https://...");
|
|
15819
15399
|
apiUrl = "http://localhost:4200/api/v1";
|
|
15820
|
-
isLocalMode = true;
|
|
15821
15400
|
}
|
|
15401
|
+
} else {
|
|
15402
|
+
console.error("[mm-dev] Local engine not running on port 4200.");
|
|
15403
|
+
console.error(" Start it with: mmrc dev (or mmrc engine start)");
|
|
15404
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
15822
15405
|
}
|
|
15823
15406
|
} else {
|
|
15824
15407
|
apiUrl = rawApiUrl;
|
|
15825
15408
|
}
|
|
15826
|
-
const token =
|
|
15827
|
-
const health =
|
|
15409
|
+
const token = await resolveDevToken(apiUrl, explicitToken);
|
|
15410
|
+
const health = await checkBackendHealth(apiUrl);
|
|
15828
15411
|
let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
|
|
15829
15412
|
if (token && health.ok) {
|
|
15830
15413
|
const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
|
|
@@ -15884,63 +15467,169 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
15884
15467
|
`;
|
|
15885
15468
|
}
|
|
15886
15469
|
};
|
|
15887
|
-
const
|
|
15470
|
+
const { existsSync: fsExists } = await import("fs");
|
|
15471
|
+
const projectIndexPath = require("path").join(process.cwd(), "index.html");
|
|
15472
|
+
const hasProjectIndex = fsExists(projectIndexPath);
|
|
15473
|
+
if (!hasProjectIndex) {
|
|
15474
|
+
const { writeFileSync: fsWrite } = await import("fs");
|
|
15475
|
+
fsWrite(projectIndexPath, `<!DOCTYPE html>
|
|
15888
15476
|
<html lang="en">
|
|
15889
15477
|
<head>
|
|
15890
15478
|
<meta charset="UTF-8">
|
|
15891
15479
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
15892
15480
|
<title>MindMatrix Dev</title>
|
|
15893
|
-
<style>
|
|
15894
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
15895
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #fafafa; color: #111; }
|
|
15896
|
-
#root { min-height: 100vh; }
|
|
15897
|
-
.mm-loading { display: flex; align-items: center; justify-content: center; min-height: 100vh; flex-direction: column; gap: 12px; }
|
|
15898
|
-
.mm-loading h1 { font-size: 20px; font-weight: 600; color: #333; }
|
|
15899
|
-
.mm-loading p { color: #888; font-size: 14px; }
|
|
15900
|
-
</style>
|
|
15901
15481
|
</head>
|
|
15902
15482
|
<body>
|
|
15903
|
-
<div id="root">
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
|
|
15907
|
-
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
|
|
15911
|
-
|
|
15483
|
+
<div id="root"></div>
|
|
15484
|
+
<script type="module" src="/__mm_dev_entry.tsx"></script>
|
|
15485
|
+
</body>
|
|
15486
|
+
</html>`, "utf-8");
|
|
15487
|
+
}
|
|
15488
|
+
const devEntryPlugin = {
|
|
15489
|
+
name: "mindmatrix-dev-entry",
|
|
15490
|
+
resolveId(id) {
|
|
15491
|
+
if (id === "/__mm_dev_entry.tsx") return id;
|
|
15492
|
+
return null;
|
|
15493
|
+
},
|
|
15494
|
+
load(id) {
|
|
15495
|
+
if (id !== "/__mm_dev_entry.tsx") return null;
|
|
15496
|
+
return `
|
|
15497
|
+
import React, { useState, useEffect } from 'react';
|
|
15498
|
+
import { createRoot } from 'react-dom/client';
|
|
15499
|
+
import { DevPlayer } from '@mmapp/react/player';
|
|
15500
|
+
import { PlayerProvider, ExperienceRenderer, createApiResolver } from '@mmapp/react/player';
|
|
15501
|
+
|
|
15502
|
+
// Detect API base URL \u2014 proxy through dev server or use direct URL
|
|
15503
|
+
const API_BASE = window.location.origin + '/api/v1';
|
|
15504
|
+
const resolver = createApiResolver({ baseUrl: API_BASE, token: () => localStorage.getItem('auth_token') });
|
|
15505
|
+
|
|
15506
|
+
/**
|
|
15507
|
+
* Prepare experience tree for rendering.
|
|
15508
|
+
* Attaches metadata.dataSources to the root node and remaps
|
|
15509
|
+
* dataSource slugs to use definition-relative naming.
|
|
15510
|
+
*
|
|
15511
|
+
* @param definition - The main blueprint definition
|
|
15512
|
+
* @param allDefinitions - ALL definitions from the API (used for slug resolution)
|
|
15513
|
+
*/
|
|
15514
|
+
function prepareTree(definition, allDefinitions) {
|
|
15515
|
+
const exp = definition.experience;
|
|
15516
|
+
if (!exp || typeof exp !== 'object') return null;
|
|
15517
|
+
|
|
15518
|
+
const meta = definition.metadata || {};
|
|
15519
|
+
const dataSources = meta.dataSources || [];
|
|
15520
|
+
const mutationTargets = meta.mutationTargets || [];
|
|
15521
|
+
|
|
15522
|
+
// Build a slug map from ALL deployed definitions
|
|
15523
|
+
// This resolves bare model names (e.g. "item") to full slugs (e.g. "tutorial-1-item")
|
|
15524
|
+
const blueprintSlug = definition.slug || '';
|
|
15525
|
+
const allSlugs = (allDefinitions || []).map(d => d.slug).filter(Boolean);
|
|
15526
|
+
|
|
15527
|
+
function resolveSlug(bareSlug) {
|
|
15528
|
+
if (!bareSlug) return bareSlug;
|
|
15529
|
+
// Already a full slug (contains hyphen matching a known definition)
|
|
15530
|
+
if (allSlugs.includes(bareSlug)) return bareSlug;
|
|
15531
|
+
// Try blueprint-prefixed slug: "item" \u2192 "tutorial-1-item"
|
|
15532
|
+
const prefixed = blueprintSlug + '-' + bareSlug;
|
|
15533
|
+
if (allSlugs.includes(prefixed)) return prefixed;
|
|
15534
|
+
// Try matching by suffix across all definitions
|
|
15535
|
+
const match = allSlugs.find(s => s.endsWith('-' + bareSlug));
|
|
15536
|
+
if (match) return match;
|
|
15537
|
+
// Return original (will attempt as-is)
|
|
15538
|
+
return bareSlug;
|
|
15539
|
+
}
|
|
15540
|
+
|
|
15541
|
+
// Clone root node and attach dataSources
|
|
15542
|
+
const root = { ...exp };
|
|
15543
|
+
if (dataSources.length > 0 && !root.dataSources) {
|
|
15544
|
+
root.dataSources = dataSources.map(ds => ({
|
|
15545
|
+
...ds,
|
|
15546
|
+
slug: resolveSlug(ds.slug),
|
|
15547
|
+
}));
|
|
15548
|
+
}
|
|
15549
|
+
|
|
15550
|
+
// Remap mutation targets the same way
|
|
15551
|
+
if (mutationTargets.length > 0) {
|
|
15552
|
+
const resolvedTargets = mutationTargets.map(t => resolveSlug(t));
|
|
15553
|
+
root.config = { ...(root.config || {}), _mutationTargets: resolvedTargets };
|
|
15554
|
+
}
|
|
15555
|
+
|
|
15556
|
+
return root;
|
|
15557
|
+
}
|
|
15558
|
+
|
|
15559
|
+
function App() {
|
|
15560
|
+
const [tree, setTree] = useState(null);
|
|
15561
|
+
const [error, setError] = useState(null);
|
|
15562
|
+
|
|
15563
|
+
useEffect(() => {
|
|
15564
|
+
async function loadTree() {
|
|
15912
15565
|
try {
|
|
15913
|
-
const res = await fetch('/
|
|
15566
|
+
const res = await fetch(API_BASE + '/workflow/definitions');
|
|
15914
15567
|
const json = await res.json();
|
|
15915
|
-
const
|
|
15916
|
-
|
|
15917
|
-
|
|
15918
|
-
|
|
15919
|
-
|
|
15920
|
-
|
|
15921
|
-
}
|
|
15922
|
-
|
|
15923
|
-
|
|
15924
|
-
|
|
15925
|
-
|
|
15926
|
-
|
|
15927
|
-
|
|
15928
|
-
|
|
15929
|
-
|
|
15568
|
+
const rawItems = json.items || json.data || [];
|
|
15569
|
+
// Flatten: API returns { id, slug, definition: { experience, ... } }
|
|
15570
|
+
// Merge definition fields up to the top level for easier access
|
|
15571
|
+
const items = rawItems.map(d => {
|
|
15572
|
+
const def = d.definition || {};
|
|
15573
|
+
return { ...d, ...def, definition: undefined };
|
|
15574
|
+
});
|
|
15575
|
+
// Find the main blueprint definition (has experience tree)
|
|
15576
|
+
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];
|
|
15577
|
+
if (main?.experience) {
|
|
15578
|
+
const prepared = prepareTree(main, items);
|
|
15579
|
+
if (prepared) {
|
|
15580
|
+
setTree(prepared);
|
|
15581
|
+
return;
|
|
15582
|
+
}
|
|
15583
|
+
}
|
|
15584
|
+
if (main) {
|
|
15585
|
+
// No experience tree \u2014 show definition info
|
|
15586
|
+
setTree({
|
|
15587
|
+
type: 'Stack',
|
|
15588
|
+
props: { style: { padding: 40, gap: 16 } },
|
|
15589
|
+
children: [
|
|
15590
|
+
{ type: 'Text', props: { children: main.name || main.slug, style: { fontSize: 24, fontWeight: 'bold' } } },
|
|
15591
|
+
{ type: 'Text', props: { children: (main.states?.length || 0) + ' states, ' + (main.fields?.length || 0) + ' fields', style: { color: '#666' } } },
|
|
15592
|
+
...items.map((d, i) => ({
|
|
15593
|
+
type: 'Card',
|
|
15594
|
+
props: { key: i, style: { padding: 16, border: '1px solid #ddd', borderRadius: 8 } },
|
|
15595
|
+
children: [
|
|
15596
|
+
{ type: 'Text', props: { children: d.name || d.slug, style: { fontWeight: 600 } } },
|
|
15597
|
+
{ type: 'Text', props: { children: 'slug: ' + d.slug + ' | ' + (d.states?.length || 0) + ' states', style: { fontSize: 13, color: '#888' } } },
|
|
15598
|
+
],
|
|
15599
|
+
})),
|
|
15600
|
+
],
|
|
15601
|
+
});
|
|
15602
|
+
}
|
|
15930
15603
|
} catch (e) {
|
|
15931
|
-
|
|
15604
|
+
setError(e.message);
|
|
15932
15605
|
}
|
|
15933
15606
|
}
|
|
15934
|
-
|
|
15935
|
-
|
|
15936
|
-
|
|
15937
|
-
|
|
15938
|
-
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
|
|
15942
|
-
|
|
15943
|
-
|
|
15607
|
+
loadTree();
|
|
15608
|
+
}, []);
|
|
15609
|
+
|
|
15610
|
+
if (error) return React.createElement('div', { style: { padding: 40 } },
|
|
15611
|
+
React.createElement('h1', null, 'MindMatrix Dev'),
|
|
15612
|
+
React.createElement('p', { style: { color: '#c00' } }, 'Error: ' + error)
|
|
15613
|
+
);
|
|
15614
|
+
|
|
15615
|
+
if (!tree) return React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh' } },
|
|
15616
|
+
React.createElement('p', null, 'Loading...')
|
|
15617
|
+
);
|
|
15618
|
+
|
|
15619
|
+
// If tree has 'component' field, use ExperienceRenderer; otherwise legacy DevPlayer
|
|
15620
|
+
if (tree.component) {
|
|
15621
|
+
return React.createElement(PlayerProvider, { resolver },
|
|
15622
|
+
React.createElement(ExperienceRenderer, { tree, className: 'mm-experience-root' })
|
|
15623
|
+
);
|
|
15624
|
+
}
|
|
15625
|
+
|
|
15626
|
+
return React.createElement(DevPlayer, { tree, title: document.title || 'MindMatrix Dev' });
|
|
15627
|
+
}
|
|
15628
|
+
|
|
15629
|
+
createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
15630
|
+
`;
|
|
15631
|
+
}
|
|
15632
|
+
};
|
|
15944
15633
|
let deployInFlight = false;
|
|
15945
15634
|
const compileDeployPlugin = {
|
|
15946
15635
|
name: "mindmatrix-dev-compile-deploy",
|
|
@@ -15971,16 +15660,16 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
15971
15660
|
}
|
|
15972
15661
|
};
|
|
15973
15662
|
const viteConfig = {
|
|
15974
|
-
//
|
|
15975
|
-
root:
|
|
15976
|
-
// Pre-bundle React
|
|
15663
|
+
// Use the blueprint directory as Vite root (has node_modules with React).
|
|
15664
|
+
root: process.cwd(),
|
|
15665
|
+
// Pre-bundle React and the player for fast dev startup.
|
|
15977
15666
|
optimizeDeps: { include: ["react", "react-dom/client"] },
|
|
15978
15667
|
server: {
|
|
15979
15668
|
port,
|
|
15980
15669
|
open,
|
|
15981
15670
|
host: true,
|
|
15982
15671
|
// Allow serving files from the real project directory (fs.allow).
|
|
15983
|
-
fs: { allow: [
|
|
15672
|
+
fs: { allow: [process.cwd(), ".."] },
|
|
15984
15673
|
proxy: {
|
|
15985
15674
|
"/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
|
|
15986
15675
|
"/health": { target: proxyTarget, changeOrigin: true, secure: true },
|
|
@@ -15990,6 +15679,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
15990
15679
|
plugins: [
|
|
15991
15680
|
mindmatrixReact(pluginOpts),
|
|
15992
15681
|
compileDeployPlugin,
|
|
15682
|
+
devEntryPlugin,
|
|
15993
15683
|
devPlayerPlugin,
|
|
15994
15684
|
{ name: "mindmatrix-error-overlay", configureServer(server) {
|
|
15995
15685
|
server.middlewares.use(errorOverlayMiddleware());
|
|
@@ -15997,8 +15687,8 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
15997
15687
|
],
|
|
15998
15688
|
logLevel: "warn"
|
|
15999
15689
|
};
|
|
16000
|
-
const { createServer
|
|
16001
|
-
const vite = await
|
|
15690
|
+
const { createServer } = await import("vite");
|
|
15691
|
+
const vite = await createServer(viteConfig);
|
|
16002
15692
|
await vite.listen();
|
|
16003
15693
|
const resolvedPort = vite.config.server.port ?? port;
|
|
16004
15694
|
if (enableWs && vite.httpServer) {
|
|
@@ -16016,7 +15706,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
16016
15706
|
} catch {
|
|
16017
15707
|
}
|
|
16018
15708
|
}
|
|
16019
|
-
printBanner({ port: resolvedPort, apiUrl
|
|
15709
|
+
printBanner({ port: resolvedPort, apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
|
|
16020
15710
|
return {
|
|
16021
15711
|
vite,
|
|
16022
15712
|
port: resolvedPort,
|
|
@@ -16048,14 +15738,6 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
|
|
|
16048
15738
|
clients.clear();
|
|
16049
15739
|
currentErrors = null;
|
|
16050
15740
|
await vite.close();
|
|
16051
|
-
if (localServer) {
|
|
16052
|
-
await localServer.close();
|
|
16053
|
-
}
|
|
16054
|
-
try {
|
|
16055
|
-
const { rmSync } = await import("fs");
|
|
16056
|
-
rmSync(devRoot, { recursive: true, force: true });
|
|
16057
|
-
} catch {
|
|
16058
|
-
}
|
|
16059
15741
|
}
|
|
16060
15742
|
};
|
|
16061
15743
|
}
|
|
@@ -16065,7 +15747,6 @@ var init_dev_server = __esm({
|
|
|
16065
15747
|
"use strict";
|
|
16066
15748
|
init_vite();
|
|
16067
15749
|
init_build();
|
|
16068
|
-
init_local_server();
|
|
16069
15750
|
currentErrors = null;
|
|
16070
15751
|
}
|
|
16071
15752
|
});
|
|
@@ -16374,99 +16055,10 @@ function generateIndexHtml(name) {
|
|
|
16374
16055
|
<meta charset="UTF-8">
|
|
16375
16056
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
16376
16057
|
<title>${title} \u2014 MindMatrix Dev</title>
|
|
16377
|
-
<style>
|
|
16378
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
16379
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #fafafa; color: #111; }
|
|
16380
|
-
#root { min-height: 100vh; padding: 40px; max-width: 960px; margin: 0 auto; }
|
|
16381
|
-
h1 { font-size: 24px; margin-bottom: 8px; }
|
|
16382
|
-
.subtitle { color: #666; margin-bottom: 24px; }
|
|
16383
|
-
.card { border: 1px solid #e0e0e0; border-radius: 8px; padding: 16px; margin-bottom: 12px; background: #fff; }
|
|
16384
|
-
.card h3 { font-size: 16px; margin-bottom: 4px; }
|
|
16385
|
-
.card .meta { color: #888; font-size: 13px; }
|
|
16386
|
-
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
|
|
16387
|
-
.badge-state { background: #e3f2fd; color: #1565c0; }
|
|
16388
|
-
.empty { text-align: center; padding: 60px 20px; color: #888; }
|
|
16389
|
-
.error { color: #c62828; background: #ffebee; padding: 16px; border-radius: 8px; margin-bottom: 16px; }
|
|
16390
|
-
.actions { display: flex; gap: 8px; margin-top: 8px; }
|
|
16391
|
-
.btn { padding: 6px 12px; border-radius: 4px; border: 1px solid #ddd; background: #fff; cursor: pointer; font-size: 13px; }
|
|
16392
|
-
.btn:hover { background: #f5f5f5; }
|
|
16393
|
-
.btn-primary { background: #1976d2; color: #fff; border-color: #1976d2; }
|
|
16394
|
-
.btn-primary:hover { background: #1565c0; }
|
|
16395
|
-
</style>
|
|
16396
16058
|
</head>
|
|
16397
16059
|
<body>
|
|
16398
|
-
<div id="root">
|
|
16399
|
-
|
|
16400
|
-
<p class="subtitle">Loading...</p>
|
|
16401
|
-
</div>
|
|
16402
|
-
<script type="module">
|
|
16403
|
-
const API = '/api/v1';
|
|
16404
|
-
|
|
16405
|
-
async function api(path, opts) {
|
|
16406
|
-
const res = await fetch(API + path, {
|
|
16407
|
-
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer dev-local' },
|
|
16408
|
-
...opts,
|
|
16409
|
-
});
|
|
16410
|
-
return res.json();
|
|
16411
|
-
}
|
|
16412
|
-
|
|
16413
|
-
async function render() {
|
|
16414
|
-
const root = document.getElementById('root');
|
|
16415
|
-
try {
|
|
16416
|
-
const defs = await api('/workflow/definitions');
|
|
16417
|
-
const items = defs.items || defs.data || [];
|
|
16418
|
-
|
|
16419
|
-
let html = '<h1>${title}</h1>';
|
|
16420
|
-
html += '<p class="subtitle">' + items.length + ' definition(s) deployed</p>';
|
|
16421
|
-
|
|
16422
|
-
if (items.length === 0) {
|
|
16423
|
-
html += '<div class="empty"><p>No definitions deployed yet.</p><p style="margin-top:8px;font-size:13px">Edit your model files and save \u2014 mmrc dev will auto-compile and deploy.</p></div>';
|
|
16424
|
-
}
|
|
16425
|
-
|
|
16426
|
-
for (const def of items) {
|
|
16427
|
-
const states = def.states || [];
|
|
16428
|
-
const fields = def.fields || [];
|
|
16429
|
-
const transitions = def.transitions || [];
|
|
16430
|
-
html += '<div class="card">';
|
|
16431
|
-
html += '<h3>' + (def.name || def.slug || 'Unnamed') + '</h3>';
|
|
16432
|
-
html += '<p class="meta">' + states.length + ' states \xB7 ' + fields.length + ' fields \xB7 ' + transitions.length + ' transitions</p>';
|
|
16433
|
-
html += '<div class="actions">';
|
|
16434
|
-
html += '<button class="btn btn-primary" onclick="createInstance(\\'' + def.slug + '\\')">+ Create Instance</button>';
|
|
16435
|
-
html += '</div>';
|
|
16436
|
-
html += '</div>';
|
|
16437
|
-
}
|
|
16438
|
-
|
|
16439
|
-
// Show instances
|
|
16440
|
-
const instances = await api('/workflow/instances');
|
|
16441
|
-
const instItems = instances.items || instances.data || [];
|
|
16442
|
-
if (instItems.length > 0) {
|
|
16443
|
-
html += '<h2 style="margin-top:32px;margin-bottom:12px">Instances (' + instItems.length + ')</h2>';
|
|
16444
|
-
for (const inst of instItems) {
|
|
16445
|
-
html += '<div class="card">';
|
|
16446
|
-
html += '<h3>' + (inst.definition_slug || '?') + ' <span class="badge badge-state">' + (inst.current_state || inst.state || '?') + '</span></h3>';
|
|
16447
|
-
html += '<p class="meta">ID: ' + inst.id + '</p>';
|
|
16448
|
-
html += '</div>';
|
|
16449
|
-
}
|
|
16450
|
-
}
|
|
16451
|
-
|
|
16452
|
-
root.innerHTML = html;
|
|
16453
|
-
} catch (e) {
|
|
16454
|
-
root.innerHTML = '<h1>${title}</h1><div class="error">API Error: ' + e.message + '</div>';
|
|
16455
|
-
}
|
|
16456
|
-
}
|
|
16457
|
-
|
|
16458
|
-
window.createInstance = async function(slug) {
|
|
16459
|
-
await api('/workflow/instances', {
|
|
16460
|
-
method: 'POST',
|
|
16461
|
-
body: JSON.stringify({ definition_slug: slug, state_data: { title: 'New Item', priority: 'medium' } }),
|
|
16462
|
-
});
|
|
16463
|
-
render();
|
|
16464
|
-
};
|
|
16465
|
-
|
|
16466
|
-
render();
|
|
16467
|
-
// Auto-refresh every 3 seconds
|
|
16468
|
-
setInterval(render, 3000);
|
|
16469
|
-
</script>
|
|
16060
|
+
<div id="root"></div>
|
|
16061
|
+
<script type="module" src="/__mm_dev_entry.tsx"></script>
|
|
16470
16062
|
</body>
|
|
16471
16063
|
</html>`;
|
|
16472
16064
|
}
|
|
@@ -16625,37 +16217,48 @@ function generatePage(name) {
|
|
|
16625
16217
|
const title = toTitleCase(name);
|
|
16626
16218
|
const pascal = toPascalCase2(name);
|
|
16627
16219
|
return `/**
|
|
16628
|
-
* @workflow slug="${name}-home" version="1.0.0" category="
|
|
16220
|
+
* @workflow slug="${name}-home" version="1.0.0" category="view"
|
|
16629
16221
|
*
|
|
16630
|
-
* Index page \u2014
|
|
16222
|
+
* Index page \u2014 full CRUD with create form, search, transitions, and delete.
|
|
16631
16223
|
*/
|
|
16632
16224
|
|
|
16633
16225
|
import { useState } from 'react';
|
|
16634
16226
|
import itemModel from '../models/item';
|
|
16635
16227
|
import {
|
|
16636
16228
|
useQuery, useMutation, useRouter,
|
|
16637
|
-
Stack, Row, Text, Button, Icon, Card, Show, TextInput, Badge,
|
|
16229
|
+
Stack, Row, Text, Button, Icon, Card, Show, TextInput, Badge, Select,
|
|
16638
16230
|
} from '@mmapp/react';
|
|
16639
16231
|
|
|
16640
|
-
const PRIORITY_COLORS: Record<string, string> = {
|
|
16641
|
-
high: 'token:error',
|
|
16642
|
-
medium: 'token:warning',
|
|
16643
|
-
low: 'token:success',
|
|
16644
|
-
};
|
|
16645
|
-
|
|
16646
16232
|
export default function ${pascal}Home() {
|
|
16647
16233
|
const { data: items, loading } = useQuery(itemModel);
|
|
16648
16234
|
const mutation = useMutation(itemModel);
|
|
16649
16235
|
const router = useRouter();
|
|
16650
16236
|
const [search, setSearch] = useState('');
|
|
16237
|
+
const [showCreate, setShowCreate] = useState(false);
|
|
16238
|
+
const [newTitle, setNewTitle] = useState('');
|
|
16239
|
+
const [newDescription, setNewDescription] = useState('');
|
|
16240
|
+
const [newPriority, setNewPriority] = useState('medium');
|
|
16241
|
+
const [editingId, setEditingId] = useState<string | null>(null);
|
|
16242
|
+
const [editTitle, setEditTitle] = useState('');
|
|
16651
16243
|
|
|
16652
|
-
const
|
|
16653
|
-
const filtered =
|
|
16654
|
-
i.fields.title.toLowerCase().includes(search.toLowerCase())
|
|
16655
|
-
|
|
16244
|
+
const visibleItems = items.filter(i => i.state !== 'archived');
|
|
16245
|
+
const filtered = search
|
|
16246
|
+
? visibleItems.filter(i => i.fields.title.toLowerCase().includes(search.toLowerCase()))
|
|
16247
|
+
: visibleItems;
|
|
16656
16248
|
|
|
16657
16249
|
const handleCreate = async () => {
|
|
16658
|
-
|
|
16250
|
+
if (!newTitle.trim()) return;
|
|
16251
|
+
await mutation.create({ title: newTitle.trim(), description: newDescription, priority: newPriority });
|
|
16252
|
+
setNewTitle('');
|
|
16253
|
+
setNewDescription('');
|
|
16254
|
+
setNewPriority('medium');
|
|
16255
|
+
setShowCreate(false);
|
|
16256
|
+
};
|
|
16257
|
+
|
|
16258
|
+
const handleUpdate = async (id: string) => {
|
|
16259
|
+
if (!editTitle.trim()) return;
|
|
16260
|
+
await mutation.update(id, { title: editTitle.trim() });
|
|
16261
|
+
setEditingId(null);
|
|
16659
16262
|
};
|
|
16660
16263
|
|
|
16661
16264
|
return (
|
|
@@ -16664,9 +16267,9 @@ export default function ${pascal}Home() {
|
|
|
16664
16267
|
<Row justify="space-between" align="center">
|
|
16665
16268
|
<Stack gap={4}>
|
|
16666
16269
|
<Text variant="h3" weight="bold" value="${title}" />
|
|
16667
|
-
<Text variant="muted" size="sm" value={\`\${
|
|
16270
|
+
<Text variant="muted" size="sm" value={\`\${visibleItems.length} item\${visibleItems.length !== 1 ? 's' : ''}\`} />
|
|
16668
16271
|
</Stack>
|
|
16669
|
-
<Button variant="primary" onPress={
|
|
16272
|
+
<Button variant="primary" onPress={() => setShowCreate(true)}>
|
|
16670
16273
|
<Row gap={6} align="center">
|
|
16671
16274
|
<Icon name="plus" size={16} />
|
|
16672
16275
|
<Text value="Add Item" />
|
|
@@ -16674,6 +16277,42 @@ export default function ${pascal}Home() {
|
|
|
16674
16277
|
</Button>
|
|
16675
16278
|
</Row>
|
|
16676
16279
|
|
|
16280
|
+
{/* Create form */}
|
|
16281
|
+
<Show when={showCreate}>
|
|
16282
|
+
<Card padding={16}>
|
|
16283
|
+
<Stack gap={12}>
|
|
16284
|
+
<Text weight="bold" value="New Item" />
|
|
16285
|
+
<TextInput
|
|
16286
|
+
value={newTitle}
|
|
16287
|
+
onChange={setNewTitle}
|
|
16288
|
+
placeholder="Item title (required)"
|
|
16289
|
+
/>
|
|
16290
|
+
<TextInput
|
|
16291
|
+
value={newDescription}
|
|
16292
|
+
onChange={setNewDescription}
|
|
16293
|
+
placeholder="Description (optional)"
|
|
16294
|
+
/>
|
|
16295
|
+
<Select
|
|
16296
|
+
value={newPriority}
|
|
16297
|
+
onChange={setNewPriority}
|
|
16298
|
+
options={[
|
|
16299
|
+
{ label: 'Low', value: 'low' },
|
|
16300
|
+
{ label: 'Medium', value: 'medium' },
|
|
16301
|
+
{ label: 'High', value: 'high' },
|
|
16302
|
+
]}
|
|
16303
|
+
/>
|
|
16304
|
+
<Row gap={8} justify="flex-end">
|
|
16305
|
+
<Button variant="ghost" onPress={() => setShowCreate(false)}>
|
|
16306
|
+
<Text value="Cancel" />
|
|
16307
|
+
</Button>
|
|
16308
|
+
<Button variant="primary" onPress={handleCreate}>
|
|
16309
|
+
<Text value="Create" />
|
|
16310
|
+
</Button>
|
|
16311
|
+
</Row>
|
|
16312
|
+
</Stack>
|
|
16313
|
+
</Card>
|
|
16314
|
+
</Show>
|
|
16315
|
+
|
|
16677
16316
|
{/* Search */}
|
|
16678
16317
|
<TextInput
|
|
16679
16318
|
value={search}
|
|
@@ -16695,10 +16334,12 @@ export default function ${pascal}Home() {
|
|
|
16695
16334
|
<Card padding={32}>
|
|
16696
16335
|
<Stack align="center" gap={12}>
|
|
16697
16336
|
<Icon name="inbox" size={40} color="token:muted" />
|
|
16698
|
-
<Text variant="muted" value=
|
|
16699
|
-
<
|
|
16700
|
-
<
|
|
16701
|
-
|
|
16337
|
+
<Text variant="muted" value={search ? 'No items match your search' : 'No items yet'} />
|
|
16338
|
+
<Show when={!search}>
|
|
16339
|
+
<Button variant="outline" onPress={() => setShowCreate(true)}>
|
|
16340
|
+
<Text value="Create your first item" />
|
|
16341
|
+
</Button>
|
|
16342
|
+
</Show>
|
|
16702
16343
|
</Stack>
|
|
16703
16344
|
</Card>
|
|
16704
16345
|
</Show>
|
|
@@ -16710,13 +16351,48 @@ export default function ${pascal}Home() {
|
|
|
16710
16351
|
<Card key={item.id} padding={12}>
|
|
16711
16352
|
<Row align="center" gap={12}>
|
|
16712
16353
|
<Stack flex={1} gap={2}>
|
|
16713
|
-
<
|
|
16714
|
-
|
|
16715
|
-
|
|
16354
|
+
<Show when={editingId === item.id}>
|
|
16355
|
+
<Row gap={8}>
|
|
16356
|
+
<TextInput
|
|
16357
|
+
value={editTitle}
|
|
16358
|
+
onChange={setEditTitle}
|
|
16359
|
+
placeholder="Title"
|
|
16360
|
+
/>
|
|
16361
|
+
<Button variant="primary" size="sm" onPress={() => handleUpdate(item.id)}>
|
|
16362
|
+
<Text value="Save" />
|
|
16363
|
+
</Button>
|
|
16364
|
+
<Button variant="ghost" size="sm" onPress={() => setEditingId(null)}>
|
|
16365
|
+
<Text value="Cancel" />
|
|
16366
|
+
</Button>
|
|
16367
|
+
</Row>
|
|
16368
|
+
</Show>
|
|
16369
|
+
<Show when={editingId !== item.id}>
|
|
16370
|
+
<Text
|
|
16371
|
+
weight="medium"
|
|
16372
|
+
value={item.fields.title}
|
|
16373
|
+
onPress={() => { setEditingId(item.id); setEditTitle(item.fields.title); }}
|
|
16374
|
+
/>
|
|
16375
|
+
<Show when={!!item.fields.description}>
|
|
16376
|
+
<Text size="sm" variant="muted" value={item.fields.description} />
|
|
16377
|
+
</Show>
|
|
16716
16378
|
</Show>
|
|
16717
16379
|
</Stack>
|
|
16718
16380
|
<Badge value={item.fields.priority} />
|
|
16719
16381
|
<Badge value={item.state} variant={item.state === 'active' ? 'success' : 'default'} />
|
|
16382
|
+
{/* Transition buttons */}
|
|
16383
|
+
<Show when={item.state === 'draft'}>
|
|
16384
|
+
<Button variant="outline" size="sm" onPress={() => mutation.transition(item.id, 'activate')}>
|
|
16385
|
+
<Text value="Activate" />
|
|
16386
|
+
</Button>
|
|
16387
|
+
</Show>
|
|
16388
|
+
<Show when={item.state === 'active'}>
|
|
16389
|
+
<Button variant="ghost" size="sm" onPress={() => mutation.transition(item.id, 'archive')}>
|
|
16390
|
+
<Text value="Archive" />
|
|
16391
|
+
</Button>
|
|
16392
|
+
</Show>
|
|
16393
|
+
<Button variant="ghost" size="sm" onPress={() => mutation.remove(item.id)}>
|
|
16394
|
+
<Icon name="trash" size={14} color="token:error" />
|
|
16395
|
+
</Button>
|
|
16720
16396
|
</Row>
|
|
16721
16397
|
</Card>
|
|
16722
16398
|
))}
|