@mmapp/react-compiler 0.1.0-alpha.7 → 0.1.0-alpha.9
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/auth-3UK75242.mjs +17 -0
- package/dist/babel/index.d.mts +2 -2
- package/dist/babel/index.d.ts +2 -2
- package/dist/babel/index.js +27 -31
- package/dist/babel/index.mjs +1 -1
- package/dist/chunk-7T6Q5KAA.mjs +7506 -0
- package/dist/chunk-ABYPKRSB.mjs +215 -0
- package/dist/chunk-BZEXUPDH.mjs +175 -0
- package/dist/chunk-J3M4GUS7.mjs +161 -0
- package/dist/chunk-JRGFBWTN.mjs +2918 -0
- package/dist/chunk-R2DD5GTY.mjs +186 -0
- package/dist/chunk-UDDTWG5J.mjs +734 -0
- package/dist/chunk-VLTKQDJ3.mjs +244 -0
- package/dist/chunk-WVYY32LD.mjs +939 -0
- package/dist/chunk-XDVM4YHX.mjs +3450 -0
- package/dist/cli/index.js +4372 -3240
- package/dist/cli/index.mjs +77 -179
- package/dist/codemod/cli.js +1 -1
- package/dist/codemod/cli.mjs +1 -1
- package/dist/codemod/index.d.mts +3 -3
- package/dist/codemod/index.d.ts +3 -3
- package/dist/codemod/index.js +1 -1
- package/dist/codemod/index.mjs +1 -1
- package/dist/deploy-YAJGW6II.mjs +9 -0
- package/dist/dev-server-CrQ041KP.d.mts +79 -0
- package/dist/dev-server-CrQ041KP.d.ts +79 -0
- package/dist/dev-server.d.mts +2 -2
- package/dist/dev-server.d.ts +2 -2
- package/dist/dev-server.js +1240 -120
- package/dist/dev-server.mjs +4 -4
- package/dist/envelope-ChEkuHij.d.mts +265 -0
- package/dist/envelope-ChEkuHij.d.ts +265 -0
- package/dist/envelope.d.mts +2 -2
- package/dist/envelope.d.ts +2 -2
- package/dist/envelope.js +27 -31
- package/dist/envelope.mjs +2 -2
- package/dist/index-CEKyyazf.d.mts +104 -0
- package/dist/index-CEKyyazf.d.ts +104 -0
- package/dist/index.d.mts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +1512 -600
- package/dist/index.mjs +8 -8
- package/dist/init-7FJENUDK.mjs +407 -0
- package/dist/project-compiler-ZB4RUYVL.mjs +10 -0
- package/dist/project-decompiler-U55HQUHW.mjs +7 -0
- package/dist/pull-KOL2QAYQ.mjs +109 -0
- package/dist/seed-KOGEPGOJ.mjs +154 -0
- package/dist/server-VW6UPCHO.mjs +277 -0
- package/dist/testing/index.d.mts +8 -8
- package/dist/testing/index.d.ts +8 -8
- package/dist/testing/index.js +27 -31
- package/dist/testing/index.mjs +1 -1
- package/dist/verify-OQDEQYMS.mjs +1833 -0
- package/dist/vite/index.d.mts +1 -1
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +27 -31
- package/dist/vite/index.mjs +2 -2
- package/examples/authentication/main.workflow.tsx +1 -1
- package/examples/authentication/mm.config.ts +1 -1
- package/examples/authentication/pages/LoginPage.tsx +2 -2
- package/examples/authentication/pages/SignupPage.tsx +2 -2
- package/examples/counter.workflow.tsx +1 -1
- package/examples/dashboard.workflow.tsx +1 -1
- package/examples/invoice-approval/actions/invoice.server.ts +1 -1
- package/examples/invoice-approval/main.workflow.tsx +1 -1
- package/examples/invoice-approval/mm.config.ts +1 -1
- package/examples/invoice-approval/pages/InvoiceDetailPage.tsx +1 -1
- package/examples/invoice-approval/pages/InvoiceFormPage.tsx +1 -1
- package/examples/invoice-approval/pages/InvoiceListPage.tsx +1 -1
- package/examples/todo-app.workflow.tsx +1 -1
- package/examples/uber-app/actions/matching.server.ts +1 -1
- package/examples/uber-app/actions/notifications.server.ts +1 -1
- package/examples/uber-app/actions/payments.server.ts +1 -1
- package/examples/uber-app/actions/pricing.server.ts +1 -1
- package/examples/uber-app/app/admin/analytics.tsx +2 -2
- package/examples/uber-app/app/admin/fleet.tsx +2 -2
- package/examples/uber-app/app/admin/surge-pricing.tsx +2 -2
- package/examples/uber-app/app/driver/dashboard.tsx +2 -2
- package/examples/uber-app/app/driver/earnings.tsx +2 -2
- package/examples/uber-app/app/driver/navigation.tsx +2 -2
- package/examples/uber-app/app/driver/ride-acceptance.tsx +2 -2
- package/examples/uber-app/app/rider/home.tsx +2 -2
- package/examples/uber-app/app/rider/payment-methods.tsx +2 -2
- package/examples/uber-app/app/rider/ride-history.tsx +2 -2
- package/examples/uber-app/app/rider/ride-tracking.tsx +2 -2
- package/examples/uber-app/components/DriverCard.tsx +1 -1
- package/examples/uber-app/components/MapView.tsx +3 -3
- package/examples/uber-app/components/RatingStars.tsx +2 -2
- package/examples/uber-app/components/RideCard.tsx +1 -1
- package/examples/uber-app/mm.config.ts +1 -1
- package/examples/uber-app/workflows/dispute-resolution.workflow.tsx +2 -2
- package/examples/uber-app/workflows/driver-onboarding.workflow.tsx +2 -2
- package/examples/uber-app/workflows/payment-processing.workflow.tsx +2 -2
- package/examples/uber-app/workflows/ride-request.workflow.tsx +2 -2
- package/package.json +7 -14
package/dist/dev-server.js
CHANGED
|
@@ -4387,7 +4387,7 @@ function extractImperativeWorkflow(path, state) {
|
|
|
4387
4387
|
const source = node.source.value;
|
|
4388
4388
|
for (const spec of node.specifiers) {
|
|
4389
4389
|
const localName = spec.local.name;
|
|
4390
|
-
if (source.includes("@mmapp/react") || source.includes("@
|
|
4390
|
+
if (source.includes("@mmapp/react") || source.includes("@mmapp/react")) {
|
|
4391
4391
|
stdLibImports.add(localName);
|
|
4392
4392
|
} else {
|
|
4393
4393
|
importedFns.set(localName, source);
|
|
@@ -6227,18 +6227,6 @@ var init_actor_extractor = __esm({
|
|
|
6227
6227
|
}
|
|
6228
6228
|
});
|
|
6229
6229
|
|
|
6230
|
-
// ../player-core/dist/index.mjs
|
|
6231
|
-
function normalizeCategory(primary, ...tags) {
|
|
6232
|
-
const uniqueTags = [...new Set(tags.filter((t23) => t23 !== primary))];
|
|
6233
|
-
uniqueTags.sort();
|
|
6234
|
-
return [primary, ...uniqueTags];
|
|
6235
|
-
}
|
|
6236
|
-
var init_dist = __esm({
|
|
6237
|
-
"../player-core/dist/index.mjs"() {
|
|
6238
|
-
"use strict";
|
|
6239
|
-
}
|
|
6240
|
-
});
|
|
6241
|
-
|
|
6242
6230
|
// src/babel/emitters/experience-transform.ts
|
|
6243
6231
|
function transformToFrontend(node) {
|
|
6244
6232
|
const result = {
|
|
@@ -6615,7 +6603,7 @@ function liftAction(action) {
|
|
|
6615
6603
|
}
|
|
6616
6604
|
return {
|
|
6617
6605
|
slug: action.id,
|
|
6618
|
-
category: normalizeCategory("expression", "mutation", action.type),
|
|
6606
|
+
category: (0, import_player_core.normalizeCategory)("expression", "mutation", action.type),
|
|
6619
6607
|
parts: parts.length > 0 ? parts : void 0
|
|
6620
6608
|
};
|
|
6621
6609
|
}
|
|
@@ -6645,7 +6633,7 @@ function liftSchedule(during) {
|
|
|
6645
6633
|
for (const action of during.actions) {
|
|
6646
6634
|
parts.push({
|
|
6647
6635
|
slug: "do",
|
|
6648
|
-
category: normalizeCategory("expression", "mutation", action.type),
|
|
6636
|
+
category: (0, import_player_core.normalizeCategory)("expression", "mutation", action.type),
|
|
6649
6637
|
parts: Object.entries(action.config || {}).map(([key, value]) => ({
|
|
6650
6638
|
slug: key,
|
|
6651
6639
|
category: ["atom"],
|
|
@@ -6655,7 +6643,7 @@ function liftSchedule(during) {
|
|
|
6655
6643
|
}
|
|
6656
6644
|
return {
|
|
6657
6645
|
slug: during.id,
|
|
6658
|
-
category: normalizeCategory("schedule", during.type),
|
|
6646
|
+
category: (0, import_player_core.normalizeCategory)("schedule", during.type),
|
|
6659
6647
|
parts
|
|
6660
6648
|
};
|
|
6661
6649
|
}
|
|
@@ -6668,14 +6656,14 @@ function liftState(state) {
|
|
|
6668
6656
|
if (state.on_enter && state.on_enter.length > 0) {
|
|
6669
6657
|
parts.push({
|
|
6670
6658
|
slug: "on_enter",
|
|
6671
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6659
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
6672
6660
|
parts: state.on_enter.map(liftAction)
|
|
6673
6661
|
});
|
|
6674
6662
|
}
|
|
6675
6663
|
if (state.on_exit && state.on_exit.length > 0) {
|
|
6676
6664
|
parts.push({
|
|
6677
6665
|
slug: "on_exit",
|
|
6678
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6666
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
6679
6667
|
parts: state.on_exit.map(liftAction)
|
|
6680
6668
|
});
|
|
6681
6669
|
}
|
|
@@ -6686,7 +6674,7 @@ function liftState(state) {
|
|
|
6686
6674
|
}
|
|
6687
6675
|
return {
|
|
6688
6676
|
slug: state.name,
|
|
6689
|
-
category: normalizeCategory("state", ...tags),
|
|
6677
|
+
category: (0, import_player_core.normalizeCategory)("state", ...tags),
|
|
6690
6678
|
parts: parts.length > 0 ? parts : void 0
|
|
6691
6679
|
};
|
|
6692
6680
|
}
|
|
@@ -6709,17 +6697,17 @@ function liftTransition(transition) {
|
|
|
6709
6697
|
if (transition.actions && transition.actions.length > 0) {
|
|
6710
6698
|
parts.push({
|
|
6711
6699
|
slug: "actions",
|
|
6712
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6700
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
6713
6701
|
parts: transition.actions.map(liftAction)
|
|
6714
6702
|
});
|
|
6715
6703
|
}
|
|
6716
6704
|
if (transition.conditions && transition.conditions.length > 0) {
|
|
6717
6705
|
parts.push({
|
|
6718
6706
|
slug: "conditions",
|
|
6719
|
-
category: normalizeCategory("expression", "guard"),
|
|
6707
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
6720
6708
|
parts: transition.conditions.map((c, i) => ({
|
|
6721
6709
|
slug: `condition_${i}`,
|
|
6722
|
-
category: normalizeCategory("expression", c.type || "condition"),
|
|
6710
|
+
category: (0, import_player_core.normalizeCategory)("expression", c.type || "condition"),
|
|
6723
6711
|
parts: c.expression ? [{ slug: c.expression, category: ["binding"] }] : void 0
|
|
6724
6712
|
}))
|
|
6725
6713
|
});
|
|
@@ -6758,7 +6746,7 @@ function liftField(field) {
|
|
|
6758
6746
|
}
|
|
6759
6747
|
return {
|
|
6760
6748
|
slug: field.name,
|
|
6761
|
-
category: normalizeCategory("field", field.type),
|
|
6749
|
+
category: (0, import_player_core.normalizeCategory)("field", field.type),
|
|
6762
6750
|
parts: parts.length > 0 ? parts : void 0
|
|
6763
6751
|
};
|
|
6764
6752
|
}
|
|
@@ -6781,20 +6769,20 @@ function liftView(node) {
|
|
|
6781
6769
|
if (match) {
|
|
6782
6770
|
parts.push({
|
|
6783
6771
|
slug: key,
|
|
6784
|
-
category: normalizeCategory("expression", "effect", "transition"),
|
|
6772
|
+
category: (0, import_player_core.normalizeCategory)("expression", "effect", "transition"),
|
|
6785
6773
|
parts: [{ slug: match[1], category: ["ref"] }]
|
|
6786
6774
|
});
|
|
6787
6775
|
} else {
|
|
6788
6776
|
parts.push({
|
|
6789
6777
|
slug: key,
|
|
6790
|
-
category: normalizeCategory("expression", "binding"),
|
|
6778
|
+
category: (0, import_player_core.normalizeCategory)("expression", "binding"),
|
|
6791
6779
|
parts: [{ slug: String(expr), category: ["binding"] }]
|
|
6792
6780
|
});
|
|
6793
6781
|
}
|
|
6794
6782
|
} else {
|
|
6795
6783
|
parts.push({
|
|
6796
6784
|
slug: key,
|
|
6797
|
-
category: normalizeCategory("expression", "binding"),
|
|
6785
|
+
category: (0, import_player_core.normalizeCategory)("expression", "binding"),
|
|
6798
6786
|
parts: [{ slug: String(expr), category: ["binding"] }]
|
|
6799
6787
|
});
|
|
6800
6788
|
}
|
|
@@ -6805,20 +6793,20 @@ function liftView(node) {
|
|
|
6805
6793
|
if (eqMatch) {
|
|
6806
6794
|
parts.push({
|
|
6807
6795
|
slug: "visible_when",
|
|
6808
|
-
category: normalizeCategory("expression", "guard"),
|
|
6796
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
6809
6797
|
parts: [{
|
|
6810
6798
|
slug: "body",
|
|
6811
|
-
category: normalizeCategory("expression", "eq"),
|
|
6799
|
+
category: (0, import_player_core.normalizeCategory)("expression", "eq"),
|
|
6812
6800
|
parts: [
|
|
6813
|
-
{ slug: "lhs", category: normalizeCategory("expression", "path"), parts: [{ slug: eqMatch[1], category: ["binding"] }] },
|
|
6814
|
-
{ slug: "rhs", category: normalizeCategory("expression", "literal"), parts: [{ slug: eqMatch[2], category: ["literal"] }] }
|
|
6801
|
+
{ slug: "lhs", category: (0, import_player_core.normalizeCategory)("expression", "path"), parts: [{ slug: eqMatch[1], category: ["binding"] }] },
|
|
6802
|
+
{ slug: "rhs", category: (0, import_player_core.normalizeCategory)("expression", "literal"), parts: [{ slug: eqMatch[2], category: ["literal"] }] }
|
|
6815
6803
|
]
|
|
6816
6804
|
}]
|
|
6817
6805
|
});
|
|
6818
6806
|
} else {
|
|
6819
6807
|
parts.push({
|
|
6820
6808
|
slug: "visible_when",
|
|
6821
|
-
category: normalizeCategory("expression", "guard"),
|
|
6809
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
6822
6810
|
parts: [{ slug: node.visible_when, category: ["binding"] }]
|
|
6823
6811
|
});
|
|
6824
6812
|
}
|
|
@@ -6830,7 +6818,7 @@ function liftView(node) {
|
|
|
6830
6818
|
}
|
|
6831
6819
|
return {
|
|
6832
6820
|
slug: node.id,
|
|
6833
|
-
category: normalizeCategory("view", componentTag),
|
|
6821
|
+
category: (0, import_player_core.normalizeCategory)("view", componentTag),
|
|
6834
6822
|
parts: parts.length > 0 ? parts : void 0
|
|
6835
6823
|
};
|
|
6836
6824
|
}
|
|
@@ -6851,7 +6839,7 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
6851
6839
|
}
|
|
6852
6840
|
parts.push({
|
|
6853
6841
|
slug: "manifest",
|
|
6854
|
-
category: normalizeCategory("meta", "manifest"),
|
|
6842
|
+
category: (0, import_player_core.normalizeCategory)("meta", "manifest"),
|
|
6855
6843
|
parts: [
|
|
6856
6844
|
{
|
|
6857
6845
|
slug: "workflows",
|
|
@@ -6872,7 +6860,7 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
6872
6860
|
let categoryArray;
|
|
6873
6861
|
if (category.includes("/")) {
|
|
6874
6862
|
const [primary, ...tags] = category.split("/");
|
|
6875
|
-
categoryArray = normalizeCategory(primary, ...tags);
|
|
6863
|
+
categoryArray = (0, import_player_core.normalizeCategory)(primary, ...tags);
|
|
6876
6864
|
} else {
|
|
6877
6865
|
categoryArray = [category];
|
|
6878
6866
|
}
|
|
@@ -7035,11 +7023,11 @@ function compilerStateToWorkflow(state, metadata) {
|
|
|
7035
7023
|
extraMetadata: Object.keys(extraMetadata).length > 0 ? extraMetadata : void 0
|
|
7036
7024
|
};
|
|
7037
7025
|
}
|
|
7038
|
-
var PROP_RULES, COMPONENT_RENAMES, RENAME_EXTRA_CONFIG;
|
|
7026
|
+
var import_player_core, PROP_RULES, COMPONENT_RENAMES, RENAME_EXTRA_CONFIG;
|
|
7039
7027
|
var init_pure_form_emitter = __esm({
|
|
7040
7028
|
"src/babel/emitters/pure-form-emitter.ts"() {
|
|
7041
7029
|
"use strict";
|
|
7042
|
-
|
|
7030
|
+
import_player_core = require("@mmapp/player-core");
|
|
7043
7031
|
init_transition_extractor();
|
|
7044
7032
|
init_experience_transform();
|
|
7045
7033
|
PROP_RULES = {
|
|
@@ -7418,7 +7406,7 @@ function createVisitor(options = {}) {
|
|
|
7418
7406
|
if (mode === "strict" && STRICT_BANNED_HOOKS[hookName]) {
|
|
7419
7407
|
const error = {
|
|
7420
7408
|
code: STRICT_BANNED_HOOKS[hookName],
|
|
7421
|
-
message: `${hookName}() is not allowed in strict mode. Use @
|
|
7409
|
+
message: `${hookName}() is not allowed in strict mode. Use @mmapp/react effect hooks instead.`,
|
|
7422
7410
|
line: path.node.loc?.start.line,
|
|
7423
7411
|
column: path.node.loc?.start.column,
|
|
7424
7412
|
severity: "error"
|
|
@@ -7510,12 +7498,12 @@ function createVisitor(options = {}) {
|
|
|
7510
7498
|
}
|
|
7511
7499
|
}
|
|
7512
7500
|
if (mode !== "strict") return;
|
|
7513
|
-
if (source.startsWith("@
|
|
7501
|
+
if (source.startsWith("@mmapp/") || source.startsWith("@mmapp/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
|
|
7514
7502
|
return;
|
|
7515
7503
|
}
|
|
7516
7504
|
const error = {
|
|
7517
7505
|
code: "STRICT_FORBIDDEN_IMPORT",
|
|
7518
|
-
message: `Import from '${source}' is not allowed in strict mode. Only @
|
|
7506
|
+
message: `Import from '${source}' is not allowed in strict mode. Only @mmapp/* and relative imports are permitted.`,
|
|
7519
7507
|
line: path.node.loc?.start.line,
|
|
7520
7508
|
column: path.node.loc?.start.column,
|
|
7521
7509
|
severity: "error"
|
|
@@ -10601,6 +10589,552 @@ var init_project_compiler = __esm({
|
|
|
10601
10589
|
}
|
|
10602
10590
|
});
|
|
10603
10591
|
|
|
10592
|
+
// src/cli/auth.ts
|
|
10593
|
+
var auth_exports = {};
|
|
10594
|
+
__export(auth_exports, {
|
|
10595
|
+
loadCredentials: () => loadCredentials,
|
|
10596
|
+
login: () => login,
|
|
10597
|
+
logout: () => logout,
|
|
10598
|
+
resolveToken: () => resolveToken,
|
|
10599
|
+
saveCredentials: () => saveCredentials,
|
|
10600
|
+
whoami: () => whoami
|
|
10601
|
+
});
|
|
10602
|
+
function loadCredentials() {
|
|
10603
|
+
if (!(0, import_fs4.existsSync)(CREDENTIALS_PATH)) return {};
|
|
10604
|
+
try {
|
|
10605
|
+
return JSON.parse((0, import_fs4.readFileSync)(CREDENTIALS_PATH, "utf-8"));
|
|
10606
|
+
} catch {
|
|
10607
|
+
return {};
|
|
10608
|
+
}
|
|
10609
|
+
}
|
|
10610
|
+
function saveCredentials(apiUrl, token) {
|
|
10611
|
+
(0, import_fs4.mkdirSync)(MMRC_DIR, { recursive: true, mode: 448 });
|
|
10612
|
+
const creds = loadCredentials();
|
|
10613
|
+
creds[apiUrl] = { token, savedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
10614
|
+
(0, import_fs4.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
10615
|
+
try {
|
|
10616
|
+
const { chmodSync } = require("fs");
|
|
10617
|
+
chmodSync(CREDENTIALS_PATH, 384);
|
|
10618
|
+
} catch {
|
|
10619
|
+
}
|
|
10620
|
+
}
|
|
10621
|
+
function removeCredentials(apiUrl) {
|
|
10622
|
+
if (!(0, import_fs4.existsSync)(CREDENTIALS_PATH)) return;
|
|
10623
|
+
if (!apiUrl) {
|
|
10624
|
+
(0, import_fs4.unlinkSync)(CREDENTIALS_PATH);
|
|
10625
|
+
return;
|
|
10626
|
+
}
|
|
10627
|
+
const creds = loadCredentials();
|
|
10628
|
+
delete creds[apiUrl];
|
|
10629
|
+
if (Object.keys(creds).length === 0) {
|
|
10630
|
+
(0, import_fs4.unlinkSync)(CREDENTIALS_PATH);
|
|
10631
|
+
} else {
|
|
10632
|
+
(0, import_fs4.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
10633
|
+
}
|
|
10634
|
+
}
|
|
10635
|
+
function resolveToken(apiUrl, explicitToken) {
|
|
10636
|
+
if (explicitToken) return explicitToken;
|
|
10637
|
+
const envToken = process.env.MMRC_TOKEN;
|
|
10638
|
+
if (envToken) return envToken;
|
|
10639
|
+
const creds = loadCredentials();
|
|
10640
|
+
const entry = creds[apiUrl];
|
|
10641
|
+
if (entry?.token) return entry.token;
|
|
10642
|
+
return null;
|
|
10643
|
+
}
|
|
10644
|
+
function prompt(question, hidden = false) {
|
|
10645
|
+
return new Promise((resolve2) => {
|
|
10646
|
+
const rl = (0, import_readline.createInterface)({
|
|
10647
|
+
input: process.stdin,
|
|
10648
|
+
output: process.stdout
|
|
10649
|
+
});
|
|
10650
|
+
if (hidden && process.stdin.isTTY) {
|
|
10651
|
+
const origWrite = process.stdout.write.bind(process.stdout);
|
|
10652
|
+
process.stdout.write = ((chunk, encodingOrCb, cb) => {
|
|
10653
|
+
if (typeof chunk === "string" && chunk.includes(question)) {
|
|
10654
|
+
return origWrite(chunk, encodingOrCb, cb);
|
|
10655
|
+
}
|
|
10656
|
+
if (typeof chunk === "string" && !chunk.includes("\n")) {
|
|
10657
|
+
return true;
|
|
10658
|
+
}
|
|
10659
|
+
return origWrite(chunk, encodingOrCb, cb);
|
|
10660
|
+
});
|
|
10661
|
+
rl.question(question, (answer) => {
|
|
10662
|
+
process.stdout.write = origWrite;
|
|
10663
|
+
console.log();
|
|
10664
|
+
rl.close();
|
|
10665
|
+
resolve2(answer.trim());
|
|
10666
|
+
});
|
|
10667
|
+
} else {
|
|
10668
|
+
rl.question(question, (answer) => {
|
|
10669
|
+
rl.close();
|
|
10670
|
+
resolve2(answer.trim());
|
|
10671
|
+
});
|
|
10672
|
+
}
|
|
10673
|
+
});
|
|
10674
|
+
}
|
|
10675
|
+
async function login(apiUrl, email, password) {
|
|
10676
|
+
if (!email) {
|
|
10677
|
+
email = await prompt("Email: ");
|
|
10678
|
+
}
|
|
10679
|
+
if (!password) {
|
|
10680
|
+
password = await prompt("Password: ", true);
|
|
10681
|
+
}
|
|
10682
|
+
if (!email || !password) {
|
|
10683
|
+
throw new Error("Email and password are required");
|
|
10684
|
+
}
|
|
10685
|
+
console.log(`[mmrc] Logging in to ${apiUrl}...`);
|
|
10686
|
+
const res = await fetch(`${apiUrl}/auth/login`, {
|
|
10687
|
+
method: "POST",
|
|
10688
|
+
headers: { "Content-Type": "application/json" },
|
|
10689
|
+
body: JSON.stringify({ email, password })
|
|
10690
|
+
});
|
|
10691
|
+
if (!res.ok) {
|
|
10692
|
+
const text = await res.text();
|
|
10693
|
+
throw new Error(`Login failed: ${res.status} ${text}`);
|
|
10694
|
+
}
|
|
10695
|
+
const data = await res.json();
|
|
10696
|
+
const token = data.token ?? data.access_token ?? data.accessToken;
|
|
10697
|
+
if (!token) {
|
|
10698
|
+
throw new Error("Login succeeded but no token in response");
|
|
10699
|
+
}
|
|
10700
|
+
saveCredentials(apiUrl, token);
|
|
10701
|
+
const userName = data.name ?? data.user?.name ?? data.user?.email ?? email;
|
|
10702
|
+
console.log(`[mmrc] Logged in as ${userName}`);
|
|
10703
|
+
console.log(`[mmrc] Token saved to ${CREDENTIALS_PATH}`);
|
|
10704
|
+
return token;
|
|
10705
|
+
}
|
|
10706
|
+
function logout(apiUrl) {
|
|
10707
|
+
if (apiUrl) {
|
|
10708
|
+
removeCredentials(apiUrl);
|
|
10709
|
+
console.log(`[mmrc] Credentials removed for ${apiUrl}`);
|
|
10710
|
+
} else {
|
|
10711
|
+
removeCredentials();
|
|
10712
|
+
console.log("[mmrc] All saved credentials removed");
|
|
10713
|
+
}
|
|
10714
|
+
}
|
|
10715
|
+
async function whoami(apiUrl) {
|
|
10716
|
+
const token = resolveToken(apiUrl);
|
|
10717
|
+
if (!token) {
|
|
10718
|
+
console.log("[mmrc] Not logged in. Run `mmrc login` to authenticate.");
|
|
10719
|
+
return;
|
|
10720
|
+
}
|
|
10721
|
+
try {
|
|
10722
|
+
const res = await fetch(`${apiUrl}/auth/me`, {
|
|
10723
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
10724
|
+
});
|
|
10725
|
+
if (!res.ok) {
|
|
10726
|
+
if (res.status === 401) {
|
|
10727
|
+
console.log("[mmrc] Token is expired or invalid. Run `mmrc login` to re-authenticate.");
|
|
10728
|
+
return;
|
|
10729
|
+
}
|
|
10730
|
+
console.log(`[mmrc] Failed to fetch user info: ${res.status}`);
|
|
10731
|
+
return;
|
|
10732
|
+
}
|
|
10733
|
+
const user = await res.json();
|
|
10734
|
+
console.log(`[mmrc] Logged in to ${apiUrl}`);
|
|
10735
|
+
console.log(` Name: ${user.name ?? "(unknown)"}`);
|
|
10736
|
+
console.log(` Email: ${user.email ?? "(unknown)"}`);
|
|
10737
|
+
if (user.id) console.log(` ID: ${user.id}`);
|
|
10738
|
+
if (user.role) console.log(` Role: ${user.role}`);
|
|
10739
|
+
} catch (error) {
|
|
10740
|
+
console.log(`[mmrc] Could not connect to ${apiUrl}: ${error.message}`);
|
|
10741
|
+
}
|
|
10742
|
+
}
|
|
10743
|
+
var import_fs4, import_path3, import_os, import_readline, MMRC_DIR, CREDENTIALS_PATH;
|
|
10744
|
+
var init_auth = __esm({
|
|
10745
|
+
"src/cli/auth.ts"() {
|
|
10746
|
+
"use strict";
|
|
10747
|
+
import_fs4 = require("fs");
|
|
10748
|
+
import_path3 = require("path");
|
|
10749
|
+
import_os = require("os");
|
|
10750
|
+
import_readline = require("readline");
|
|
10751
|
+
MMRC_DIR = (0, import_path3.join)((0, import_os.homedir)(), ".mmrc");
|
|
10752
|
+
CREDENTIALS_PATH = (0, import_path3.join)(MMRC_DIR, "credentials.json");
|
|
10753
|
+
}
|
|
10754
|
+
});
|
|
10755
|
+
|
|
10756
|
+
// src/cli/deploy.ts
|
|
10757
|
+
var deploy_exports = {};
|
|
10758
|
+
__export(deploy_exports, {
|
|
10759
|
+
deploy: () => deploy,
|
|
10760
|
+
syncServices: () => syncServices
|
|
10761
|
+
});
|
|
10762
|
+
async function deploy(options) {
|
|
10763
|
+
const dir = options.dir ?? "dist/workflows";
|
|
10764
|
+
const targetLabel = options.targetName ? ` (target: ${options.targetName})` : "";
|
|
10765
|
+
console.log(`[mindmatrix-react] Deploying workflows from ${dir} to ${options.apiUrl}${targetLabel}...`);
|
|
10766
|
+
const files = await (0, import_glob2.glob)(`${dir}/**/*.workflow.json`);
|
|
10767
|
+
if (files.length === 0) {
|
|
10768
|
+
console.log(`[mindmatrix-react] No workflow files found in ${dir}`);
|
|
10769
|
+
return { created: [], updated: [], versioned: [], skipped: [], failed: [] };
|
|
10770
|
+
}
|
|
10771
|
+
const result = {
|
|
10772
|
+
created: [],
|
|
10773
|
+
updated: [],
|
|
10774
|
+
versioned: [],
|
|
10775
|
+
skipped: [],
|
|
10776
|
+
failed: []
|
|
10777
|
+
};
|
|
10778
|
+
const deployedIRs = [];
|
|
10779
|
+
for (const file of files) {
|
|
10780
|
+
try {
|
|
10781
|
+
const ir = JSON.parse((0, import_fs5.readFileSync)(file, "utf-8"));
|
|
10782
|
+
const slug = ir.slug;
|
|
10783
|
+
if (options.dryRun) {
|
|
10784
|
+
console.log(` [dry-run] Would deploy ${slug} (${(0, import_path4.basename)(file)})`);
|
|
10785
|
+
continue;
|
|
10786
|
+
}
|
|
10787
|
+
const existing = await fetchExistingDefinition(options.apiUrl, options.token, slug);
|
|
10788
|
+
if (!existing) {
|
|
10789
|
+
await createDefinition(options.apiUrl, options.token, ir);
|
|
10790
|
+
console.log(` \u2713 ${slug} (created)`);
|
|
10791
|
+
result.created.push(slug);
|
|
10792
|
+
} else if (existing.instanceCount === 0 || options.force) {
|
|
10793
|
+
await updateDefinition(options.apiUrl, options.token, existing.id, ir);
|
|
10794
|
+
console.log(` \u2713 ${slug} (updated)`);
|
|
10795
|
+
result.updated.push(slug);
|
|
10796
|
+
} else {
|
|
10797
|
+
const newVersion = bumpVersion(existing.version);
|
|
10798
|
+
ir.version = newVersion;
|
|
10799
|
+
await createDefinition(options.apiUrl, options.token, ir);
|
|
10800
|
+
console.log(` \u2713 ${slug} v${newVersion} (new version, ${existing.instanceCount} instances on v${existing.version})`);
|
|
10801
|
+
result.versioned.push(slug);
|
|
10802
|
+
}
|
|
10803
|
+
deployedIRs.push(ir);
|
|
10804
|
+
} catch (error) {
|
|
10805
|
+
const slug = (0, import_path4.basename)(file).replace(".workflow.json", "");
|
|
10806
|
+
const msg = error.message;
|
|
10807
|
+
console.error(` \u2717 ${slug}: ${msg}`);
|
|
10808
|
+
result.failed.push({ slug, error: msg });
|
|
10809
|
+
}
|
|
10810
|
+
}
|
|
10811
|
+
if (!options.dryRun) {
|
|
10812
|
+
for (const ir of deployedIRs) {
|
|
10813
|
+
const serviceResult = await syncServices(options.apiUrl, options.token, ir);
|
|
10814
|
+
if (serviceResult) {
|
|
10815
|
+
if (!result.services) {
|
|
10816
|
+
result.services = { registered: [], updated: [], failed: [] };
|
|
10817
|
+
}
|
|
10818
|
+
result.services.registered.push(...serviceResult.registered);
|
|
10819
|
+
result.services.updated.push(...serviceResult.updated);
|
|
10820
|
+
result.services.failed.push(...serviceResult.failed);
|
|
10821
|
+
}
|
|
10822
|
+
}
|
|
10823
|
+
}
|
|
10824
|
+
if (options.reportFile) {
|
|
10825
|
+
(0, import_fs5.writeFileSync)(options.reportFile, JSON.stringify(result, null, 2), "utf-8");
|
|
10826
|
+
console.log(`
|
|
10827
|
+
Report written to ${options.reportFile}`);
|
|
10828
|
+
}
|
|
10829
|
+
const total = result.created.length + result.updated.length + result.versioned.length;
|
|
10830
|
+
console.log(
|
|
10831
|
+
`
|
|
10832
|
+
[mindmatrix-react] Deployed ${total} workflows (${result.created.length} created, ${result.updated.length} updated, ${result.versioned.length} versioned, ${result.failed.length} failed)`
|
|
10833
|
+
);
|
|
10834
|
+
if (result.services) {
|
|
10835
|
+
const svcTotal = result.services.registered.length + result.services.updated.length;
|
|
10836
|
+
if (svcTotal > 0 || result.services.failed.length > 0) {
|
|
10837
|
+
console.log(
|
|
10838
|
+
`[mindmatrix-react] Synced ${svcTotal} services (${result.services.registered.length} registered, ${result.services.updated.length} updated, ${result.services.failed.length} failed)`
|
|
10839
|
+
);
|
|
10840
|
+
}
|
|
10841
|
+
}
|
|
10842
|
+
return result;
|
|
10843
|
+
}
|
|
10844
|
+
async function fetchExistingDefinition(apiUrl, token, slug) {
|
|
10845
|
+
try {
|
|
10846
|
+
const res = await fetch(`${apiUrl}/workflow/definitions?slug=${encodeURIComponent(slug)}`, {
|
|
10847
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
10848
|
+
});
|
|
10849
|
+
if (!res.ok) return null;
|
|
10850
|
+
const data = await res.json();
|
|
10851
|
+
const definitions = Array.isArray(data) ? data : data.items ?? data.data;
|
|
10852
|
+
if (!definitions || definitions.length === 0) return null;
|
|
10853
|
+
const def = definitions[0];
|
|
10854
|
+
return {
|
|
10855
|
+
id: def.id,
|
|
10856
|
+
slug: def.slug,
|
|
10857
|
+
version: def.version || "0.1.0",
|
|
10858
|
+
instanceCount: def.instanceCount ?? def.instance_count ?? 0
|
|
10859
|
+
};
|
|
10860
|
+
} catch {
|
|
10861
|
+
return null;
|
|
10862
|
+
}
|
|
10863
|
+
}
|
|
10864
|
+
async function createDefinition(apiUrl, token, ir) {
|
|
10865
|
+
const res = await fetch(`${apiUrl}/workflow/definitions`, {
|
|
10866
|
+
method: "POST",
|
|
10867
|
+
headers: {
|
|
10868
|
+
"Content-Type": "application/json",
|
|
10869
|
+
Authorization: `Bearer ${token}`
|
|
10870
|
+
},
|
|
10871
|
+
body: JSON.stringify(ir)
|
|
10872
|
+
});
|
|
10873
|
+
if (!res.ok) {
|
|
10874
|
+
const errorText = await res.text();
|
|
10875
|
+
throw new Error(`Create failed: ${res.status} ${errorText}`);
|
|
10876
|
+
}
|
|
10877
|
+
}
|
|
10878
|
+
async function updateDefinition(apiUrl, token, id, ir) {
|
|
10879
|
+
const { slug: _slug, ...updatePayload } = ir;
|
|
10880
|
+
const res = await fetch(`${apiUrl}/workflow/definitions/${id}`, {
|
|
10881
|
+
method: "PATCH",
|
|
10882
|
+
headers: {
|
|
10883
|
+
"Content-Type": "application/json",
|
|
10884
|
+
Authorization: `Bearer ${token}`
|
|
10885
|
+
},
|
|
10886
|
+
body: JSON.stringify(updatePayload)
|
|
10887
|
+
});
|
|
10888
|
+
if (!res.ok) {
|
|
10889
|
+
const errorText = await res.text();
|
|
10890
|
+
throw new Error(`Update failed: ${res.status} ${errorText}`);
|
|
10891
|
+
}
|
|
10892
|
+
}
|
|
10893
|
+
function bumpVersion(version) {
|
|
10894
|
+
const parts = version.split(".");
|
|
10895
|
+
if (parts.length !== 3) return `${version}.1`;
|
|
10896
|
+
const patch = parseInt(parts[2], 10) || 0;
|
|
10897
|
+
return `${parts[0]}.${parts[1]}.${patch + 1}`;
|
|
10898
|
+
}
|
|
10899
|
+
async function syncServices(apiUrl, token, ir) {
|
|
10900
|
+
const metadata = ir.metadata;
|
|
10901
|
+
const orchestration = metadata?.orchestration;
|
|
10902
|
+
const services = orchestration?.services;
|
|
10903
|
+
if (!services || Object.keys(services).length === 0) return null;
|
|
10904
|
+
const result = { registered: [], updated: [], failed: [] };
|
|
10905
|
+
for (const [name, config] of Object.entries(services)) {
|
|
10906
|
+
try {
|
|
10907
|
+
const registration = {
|
|
10908
|
+
name,
|
|
10909
|
+
connection: {
|
|
10910
|
+
type: config.type || "webhook",
|
|
10911
|
+
url: config.url,
|
|
10912
|
+
queue: config.queue
|
|
10913
|
+
},
|
|
10914
|
+
actions: config.actions || [],
|
|
10915
|
+
labels: config.labels || {}
|
|
10916
|
+
};
|
|
10917
|
+
const existing = await fetchExistingService(apiUrl, token, name);
|
|
10918
|
+
if (existing) {
|
|
10919
|
+
await fetch(`${apiUrl}/services/${existing.id}`, {
|
|
10920
|
+
method: "PATCH",
|
|
10921
|
+
headers: {
|
|
10922
|
+
"Content-Type": "application/json",
|
|
10923
|
+
Authorization: `Bearer ${token}`
|
|
10924
|
+
},
|
|
10925
|
+
body: JSON.stringify(registration)
|
|
10926
|
+
});
|
|
10927
|
+
console.log(` \u2713 service: ${name} (updated)`);
|
|
10928
|
+
result.updated.push(name);
|
|
10929
|
+
} else {
|
|
10930
|
+
const res = await fetch(`${apiUrl}/services`, {
|
|
10931
|
+
method: "POST",
|
|
10932
|
+
headers: {
|
|
10933
|
+
"Content-Type": "application/json",
|
|
10934
|
+
Authorization: `Bearer ${token}`
|
|
10935
|
+
},
|
|
10936
|
+
body: JSON.stringify(registration)
|
|
10937
|
+
});
|
|
10938
|
+
if (!res.ok) {
|
|
10939
|
+
const errorText = await res.text();
|
|
10940
|
+
throw new Error(`Register failed: ${res.status} ${errorText}`);
|
|
10941
|
+
}
|
|
10942
|
+
console.log(` \u2713 service: ${name} (registered)`);
|
|
10943
|
+
result.registered.push(name);
|
|
10944
|
+
}
|
|
10945
|
+
} catch (error) {
|
|
10946
|
+
const msg = error.message;
|
|
10947
|
+
console.error(` \u2717 service: ${name}: ${msg}`);
|
|
10948
|
+
result.failed.push(name);
|
|
10949
|
+
}
|
|
10950
|
+
}
|
|
10951
|
+
return result;
|
|
10952
|
+
}
|
|
10953
|
+
async function fetchExistingService(apiUrl, token, name) {
|
|
10954
|
+
try {
|
|
10955
|
+
const res = await fetch(`${apiUrl}/services?name=${encodeURIComponent(name)}`, {
|
|
10956
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
10957
|
+
});
|
|
10958
|
+
if (!res.ok) return null;
|
|
10959
|
+
const data = await res.json();
|
|
10960
|
+
const servicesList = Array.isArray(data) ? data : data.services ?? data.items ?? data.data;
|
|
10961
|
+
if (!servicesList || servicesList.length === 0) return null;
|
|
10962
|
+
const found = servicesList.find((s) => s.name === name);
|
|
10963
|
+
return found ? { id: found.id, name: found.name } : null;
|
|
10964
|
+
} catch {
|
|
10965
|
+
return null;
|
|
10966
|
+
}
|
|
10967
|
+
}
|
|
10968
|
+
var import_glob2, import_fs5, import_path4;
|
|
10969
|
+
var init_deploy = __esm({
|
|
10970
|
+
"src/cli/deploy.ts"() {
|
|
10971
|
+
"use strict";
|
|
10972
|
+
import_glob2 = require("glob");
|
|
10973
|
+
import_fs5 = require("fs");
|
|
10974
|
+
import_path4 = require("path");
|
|
10975
|
+
}
|
|
10976
|
+
});
|
|
10977
|
+
|
|
10978
|
+
// src/cli/seed.ts
|
|
10979
|
+
var seed_exports = {};
|
|
10980
|
+
__export(seed_exports, {
|
|
10981
|
+
generateFieldValue: () => generateFieldValue,
|
|
10982
|
+
generateInstanceData: () => generateInstanceData,
|
|
10983
|
+
seedInstances: () => seedInstances
|
|
10984
|
+
});
|
|
10985
|
+
function randomInt(min, max) {
|
|
10986
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
10987
|
+
}
|
|
10988
|
+
function randomPick(arr) {
|
|
10989
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
10990
|
+
}
|
|
10991
|
+
function loremSentence(words = 5) {
|
|
10992
|
+
const result = [];
|
|
10993
|
+
for (let i = 0; i < words; i++) result.push(randomPick(LOREM_WORDS));
|
|
10994
|
+
const s = result.join(" ");
|
|
10995
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
10996
|
+
}
|
|
10997
|
+
function generateFieldValue(field, index) {
|
|
10998
|
+
if (field.default_value !== void 0 && field.default_value !== null) {
|
|
10999
|
+
return field.default_value;
|
|
11000
|
+
}
|
|
11001
|
+
if (field.options && field.options.length > 0) {
|
|
11002
|
+
return field.options[index % field.options.length].value;
|
|
11003
|
+
}
|
|
11004
|
+
const ft = (field.field_type ?? field.type ?? "text").toLowerCase();
|
|
11005
|
+
switch (ft) {
|
|
11006
|
+
case "text":
|
|
11007
|
+
case "string":
|
|
11008
|
+
case "textarea":
|
|
11009
|
+
case "rich_text": {
|
|
11010
|
+
const name = field.name.toLowerCase();
|
|
11011
|
+
if (name.includes("email")) return `${randomPick(FIRST_NAMES).toLowerCase()}${++_counter}@${randomPick(DOMAINS)}`;
|
|
11012
|
+
if (name.includes("name") && name.includes("first")) return randomPick(FIRST_NAMES);
|
|
11013
|
+
if (name.includes("name") && name.includes("last")) return randomPick(LAST_NAMES);
|
|
11014
|
+
if (name.includes("name") || name === "title") return `${randomPick(FIRST_NAMES)} ${randomPick(LAST_NAMES)}`;
|
|
11015
|
+
if (name.includes("company") || name.includes("org")) return randomPick(COMPANIES);
|
|
11016
|
+
if (name.includes("phone")) return `+1-555-${randomInt(100, 999)}-${randomInt(1e3, 9999)}`;
|
|
11017
|
+
if (name.includes("url") || name.includes("website")) return `https://${randomPick(DOMAINS)}/${field.name}`;
|
|
11018
|
+
if (name.includes("description") || name.includes("note") || name.includes("comment")) return loremSentence(randomInt(8, 15));
|
|
11019
|
+
if (name.includes("address")) return `${randomInt(100, 9999)} ${loremSentence(2)} St`;
|
|
11020
|
+
return loremSentence(randomInt(2, 5));
|
|
11021
|
+
}
|
|
11022
|
+
case "number":
|
|
11023
|
+
case "numeric":
|
|
11024
|
+
case "integer":
|
|
11025
|
+
case "int": {
|
|
11026
|
+
const name = field.name.toLowerCase();
|
|
11027
|
+
if (name.includes("price") || name.includes("amount") || name.includes("cost") || name.includes("salary"))
|
|
11028
|
+
return randomInt(1e3, 99999) / 100;
|
|
11029
|
+
if (name.includes("age")) return randomInt(18, 65);
|
|
11030
|
+
if (name.includes("quantity") || name.includes("count") || name.includes("qty")) return randomInt(1, 100);
|
|
11031
|
+
if (name.includes("percent") || name.includes("rate")) return randomInt(1, 100);
|
|
11032
|
+
return randomInt(1, 1e3);
|
|
11033
|
+
}
|
|
11034
|
+
case "currency":
|
|
11035
|
+
case "decimal":
|
|
11036
|
+
return randomInt(100, 999999) / 100;
|
|
11037
|
+
case "boolean":
|
|
11038
|
+
case "bool":
|
|
11039
|
+
case "checkbox":
|
|
11040
|
+
case "toggle":
|
|
11041
|
+
return index % 2 === 0;
|
|
11042
|
+
case "date":
|
|
11043
|
+
case "datetime":
|
|
11044
|
+
case "timestamptz": {
|
|
11045
|
+
const d = /* @__PURE__ */ new Date();
|
|
11046
|
+
d.setDate(d.getDate() - randomInt(0, 365));
|
|
11047
|
+
return d.toISOString().split("T")[0];
|
|
11048
|
+
}
|
|
11049
|
+
case "select":
|
|
11050
|
+
case "enum":
|
|
11051
|
+
case "multi_select":
|
|
11052
|
+
return field.options?.[index % (field.options?.length || 1)]?.value ?? "option_1";
|
|
11053
|
+
case "email":
|
|
11054
|
+
return `${randomPick(FIRST_NAMES).toLowerCase()}${++_counter}@${randomPick(DOMAINS)}`;
|
|
11055
|
+
case "url":
|
|
11056
|
+
return `https://${randomPick(DOMAINS)}/${field.name}`;
|
|
11057
|
+
case "json":
|
|
11058
|
+
case "object":
|
|
11059
|
+
return {};
|
|
11060
|
+
case "array":
|
|
11061
|
+
return [];
|
|
11062
|
+
default:
|
|
11063
|
+
return loremSentence(3);
|
|
11064
|
+
}
|
|
11065
|
+
}
|
|
11066
|
+
function generateInstanceData(fields, index) {
|
|
11067
|
+
const data = {};
|
|
11068
|
+
for (const field of fields) {
|
|
11069
|
+
if (field.name === "id" || field.name === "created_at" || field.name === "updated_at") continue;
|
|
11070
|
+
data[field.name] = generateFieldValue(field, index);
|
|
11071
|
+
}
|
|
11072
|
+
return data;
|
|
11073
|
+
}
|
|
11074
|
+
async function seedInstances(options) {
|
|
11075
|
+
const dir = options.dir ?? "dist/workflows";
|
|
11076
|
+
const count = options.count ?? 7;
|
|
11077
|
+
const result = { created: 0, definitions: 0, errors: [] };
|
|
11078
|
+
const files = await (0, import_glob3.glob)(`${dir}/**/*.workflow.json`);
|
|
11079
|
+
if (files.length === 0) return result;
|
|
11080
|
+
for (const file of files) {
|
|
11081
|
+
let def;
|
|
11082
|
+
try {
|
|
11083
|
+
def = JSON.parse((0, import_fs6.readFileSync)(file, "utf-8"));
|
|
11084
|
+
} catch {
|
|
11085
|
+
continue;
|
|
11086
|
+
}
|
|
11087
|
+
if (!def.slug || !def.fields || def.fields.length === 0) continue;
|
|
11088
|
+
const startState = def.states?.find((s) => s.state_type === "START")?.name ?? def.states?.[0]?.name ?? "initial";
|
|
11089
|
+
let defCreated = 0;
|
|
11090
|
+
for (let i = 0; i < count; i++) {
|
|
11091
|
+
const stateData = generateInstanceData(def.fields, i);
|
|
11092
|
+
try {
|
|
11093
|
+
const resp = await fetch(`${options.apiUrl}/workflow/instances`, {
|
|
11094
|
+
method: "POST",
|
|
11095
|
+
headers: {
|
|
11096
|
+
"Content-Type": "application/json",
|
|
11097
|
+
"Authorization": `Bearer ${options.token}`
|
|
11098
|
+
},
|
|
11099
|
+
body: JSON.stringify({
|
|
11100
|
+
definition_slug: def.slug,
|
|
11101
|
+
initial_state: startState,
|
|
11102
|
+
state_data: stateData
|
|
11103
|
+
})
|
|
11104
|
+
});
|
|
11105
|
+
if (resp.ok) {
|
|
11106
|
+
defCreated++;
|
|
11107
|
+
} else {
|
|
11108
|
+
const errText = await resp.text().catch(() => resp.statusText);
|
|
11109
|
+
result.errors.push(`${def.slug}[${i}]: ${resp.status} ${errText}`);
|
|
11110
|
+
}
|
|
11111
|
+
} catch (e) {
|
|
11112
|
+
result.errors.push(`${def.slug}[${i}]: ${e instanceof Error ? e.message : String(e)}`);
|
|
11113
|
+
}
|
|
11114
|
+
}
|
|
11115
|
+
if (defCreated > 0) {
|
|
11116
|
+
result.definitions++;
|
|
11117
|
+
result.created += defCreated;
|
|
11118
|
+
console.log(` [seed] ${def.slug}: ${defCreated} instances created`);
|
|
11119
|
+
}
|
|
11120
|
+
}
|
|
11121
|
+
return result;
|
|
11122
|
+
}
|
|
11123
|
+
var import_fs6, import_glob3, FIRST_NAMES, LAST_NAMES, COMPANIES, LOREM_WORDS, DOMAINS, _counter;
|
|
11124
|
+
var init_seed = __esm({
|
|
11125
|
+
"src/cli/seed.ts"() {
|
|
11126
|
+
"use strict";
|
|
11127
|
+
import_fs6 = require("fs");
|
|
11128
|
+
import_glob3 = require("glob");
|
|
11129
|
+
FIRST_NAMES = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank", "Grace", "Henry"];
|
|
11130
|
+
LAST_NAMES = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis"];
|
|
11131
|
+
COMPANIES = ["Acme Corp", "TechStart Inc", "GlobalTrade Ltd", "DataFlow Systems", "CloudPeak"];
|
|
11132
|
+
LOREM_WORDS = ["lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit", "sed", "do", "eiusmod", "tempor"];
|
|
11133
|
+
DOMAINS = ["example.com", "test.org", "demo.io", "sample.net"];
|
|
11134
|
+
_counter = 0;
|
|
11135
|
+
}
|
|
11136
|
+
});
|
|
11137
|
+
|
|
10604
11138
|
// src/dev-server.ts
|
|
10605
11139
|
var dev_server_exports = {};
|
|
10606
11140
|
__export(dev_server_exports, {
|
|
@@ -11167,7 +11701,560 @@ async function startWatchMode(options) {
|
|
|
11167
11701
|
});
|
|
11168
11702
|
}
|
|
11169
11703
|
|
|
11704
|
+
// src/cli/local-server.ts
|
|
11705
|
+
var http = __toESM(require("http"));
|
|
11706
|
+
var import_node_crypto = require("crypto");
|
|
11707
|
+
var MemoryStore = class {
|
|
11708
|
+
constructor() {
|
|
11709
|
+
this.definitions = /* @__PURE__ */ new Map();
|
|
11710
|
+
this.instances = /* @__PURE__ */ new Map();
|
|
11711
|
+
this.slugIndex = /* @__PURE__ */ new Map();
|
|
11712
|
+
}
|
|
11713
|
+
// slug → id
|
|
11714
|
+
// ── Definitions ──────────────────────────────────────────────────────
|
|
11715
|
+
createDefinition(input) {
|
|
11716
|
+
if (this.slugIndex.has(input.slug)) {
|
|
11717
|
+
const existing = this.definitions.get(this.slugIndex.get(input.slug));
|
|
11718
|
+
if (existing) return existing;
|
|
11719
|
+
}
|
|
11720
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11721
|
+
const def = {
|
|
11722
|
+
id: input.id ?? (0, import_node_crypto.randomUUID)(),
|
|
11723
|
+
slug: input.slug,
|
|
11724
|
+
name: input.name,
|
|
11725
|
+
version: input.version ?? "1.0.0",
|
|
11726
|
+
description: input.description ?? null,
|
|
11727
|
+
category: input.category ?? "workflow",
|
|
11728
|
+
fields: input.fields ?? [],
|
|
11729
|
+
states: input.states ?? [],
|
|
11730
|
+
transitions: input.transitions ?? [],
|
|
11731
|
+
roles: input.roles ?? [],
|
|
11732
|
+
experience: input.experience ?? null,
|
|
11733
|
+
metadata: input.metadata ?? {},
|
|
11734
|
+
child_definitions: input.child_definitions ?? [],
|
|
11735
|
+
is_immutable: input.is_immutable ?? false,
|
|
11736
|
+
tags: input.tags ?? [],
|
|
11737
|
+
inline_tags: input.inline_tags ?? [],
|
|
11738
|
+
created_at: now,
|
|
11739
|
+
updated_at: now
|
|
11740
|
+
};
|
|
11741
|
+
this.definitions.set(def.id, def);
|
|
11742
|
+
this.slugIndex.set(def.slug, def.id);
|
|
11743
|
+
return def;
|
|
11744
|
+
}
|
|
11745
|
+
getDefinition(idOrSlug) {
|
|
11746
|
+
const byId = this.definitions.get(idOrSlug);
|
|
11747
|
+
if (byId) return byId;
|
|
11748
|
+
const id = this.slugIndex.get(idOrSlug);
|
|
11749
|
+
if (id) return this.definitions.get(id);
|
|
11750
|
+
return void 0;
|
|
11751
|
+
}
|
|
11752
|
+
listDefinitions(opts) {
|
|
11753
|
+
let items = Array.from(this.definitions.values());
|
|
11754
|
+
if (opts?.category) {
|
|
11755
|
+
items = items.filter((d) => d.category === opts.category);
|
|
11756
|
+
}
|
|
11757
|
+
const total = items.length;
|
|
11758
|
+
const offset = opts?.offset ?? 0;
|
|
11759
|
+
const limit = opts?.limit ?? 50;
|
|
11760
|
+
items = items.slice(offset, offset + limit);
|
|
11761
|
+
return { items, total };
|
|
11762
|
+
}
|
|
11763
|
+
patchDefinition(id, patch) {
|
|
11764
|
+
const def = this.definitions.get(id);
|
|
11765
|
+
if (!def) return void 0;
|
|
11766
|
+
Object.assign(def, patch, { updated_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11767
|
+
return def;
|
|
11768
|
+
}
|
|
11769
|
+
deleteDefinition(id) {
|
|
11770
|
+
const def = this.definitions.get(id);
|
|
11771
|
+
if (!def) return false;
|
|
11772
|
+
this.slugIndex.delete(def.slug);
|
|
11773
|
+
this.definitions.delete(id);
|
|
11774
|
+
return true;
|
|
11775
|
+
}
|
|
11776
|
+
// ── Instances ────────────────────────────────────────────────────────
|
|
11777
|
+
createInstance(input) {
|
|
11778
|
+
const def = this.getDefinition(input.definition_id) ?? this.getDefinition(input.definition_slug);
|
|
11779
|
+
if (!def) return null;
|
|
11780
|
+
const initialState = def.states.find((s) => s.type === "START" || s.type === "initial");
|
|
11781
|
+
const stateName = initialState?.name ?? "initial";
|
|
11782
|
+
const stateData = {};
|
|
11783
|
+
for (const field of def.fields) {
|
|
11784
|
+
if (field.default_value !== void 0) {
|
|
11785
|
+
stateData[field.name] = field.default_value;
|
|
11786
|
+
}
|
|
11787
|
+
}
|
|
11788
|
+
Object.assign(stateData, input.state_data ?? {});
|
|
11789
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11790
|
+
const inst = {
|
|
11791
|
+
id: (0, import_node_crypto.randomUUID)(),
|
|
11792
|
+
definition_id: def.id,
|
|
11793
|
+
definition_slug: def.slug,
|
|
11794
|
+
current_state: stateName,
|
|
11795
|
+
state_data: stateData,
|
|
11796
|
+
execution_lock_version: 0,
|
|
11797
|
+
event_log: [{
|
|
11798
|
+
event_type: "transition",
|
|
11799
|
+
message: `Instance created in state '${stateName}'`,
|
|
11800
|
+
timestamp: now
|
|
11801
|
+
}],
|
|
11802
|
+
created_at: now,
|
|
11803
|
+
updated_at: now
|
|
11804
|
+
};
|
|
11805
|
+
this.instances.set(inst.id, inst);
|
|
11806
|
+
return inst;
|
|
11807
|
+
}
|
|
11808
|
+
getInstance(id) {
|
|
11809
|
+
return this.instances.get(id);
|
|
11810
|
+
}
|
|
11811
|
+
listInstances(opts) {
|
|
11812
|
+
let items = Array.from(this.instances.values());
|
|
11813
|
+
if (opts?.definition_id) {
|
|
11814
|
+
items = items.filter((i) => i.definition_id === opts.definition_id);
|
|
11815
|
+
}
|
|
11816
|
+
const total = items.length;
|
|
11817
|
+
const offset = opts?.offset ?? 0;
|
|
11818
|
+
const limit = opts?.limit ?? 50;
|
|
11819
|
+
items = items.slice(offset, offset + limit);
|
|
11820
|
+
return { items, total };
|
|
11821
|
+
}
|
|
11822
|
+
// ── Execute Action (Transition) ──────────────────────────────────────
|
|
11823
|
+
executeAction(input) {
|
|
11824
|
+
const def = this.getDefinition(input.definition_id);
|
|
11825
|
+
if (!def) return { success: false, error: "Definition not found" };
|
|
11826
|
+
let inst;
|
|
11827
|
+
if (input.instance_id) {
|
|
11828
|
+
const existing = this.instances.get(input.instance_id);
|
|
11829
|
+
if (!existing) return { success: false, error: "Instance not found" };
|
|
11830
|
+
inst = existing;
|
|
11831
|
+
} else {
|
|
11832
|
+
const created = this.createInstance({
|
|
11833
|
+
definition_id: def.id,
|
|
11834
|
+
definition_slug: def.slug,
|
|
11835
|
+
state_data: input.payload
|
|
11836
|
+
});
|
|
11837
|
+
if (!created) return { success: false, error: "Failed to create instance" };
|
|
11838
|
+
inst = created;
|
|
11839
|
+
}
|
|
11840
|
+
if (input.payload && input.instance_id) {
|
|
11841
|
+
Object.assign(inst.state_data, input.payload);
|
|
11842
|
+
}
|
|
11843
|
+
const transition = def.transitions.find((t23) => t23.name === input.action_name && t23.from.includes(inst.current_state));
|
|
11844
|
+
if (!transition) {
|
|
11845
|
+
return {
|
|
11846
|
+
success: false,
|
|
11847
|
+
instance_id: inst.id,
|
|
11848
|
+
from_state: inst.current_state,
|
|
11849
|
+
to_state: null,
|
|
11850
|
+
state_data: inst.state_data,
|
|
11851
|
+
error: `No transition '${input.action_name}' from state '${inst.current_state}'`
|
|
11852
|
+
};
|
|
11853
|
+
}
|
|
11854
|
+
const fromState = inst.current_state;
|
|
11855
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11856
|
+
const events = [];
|
|
11857
|
+
let lastEvalResult = null;
|
|
11858
|
+
events.push({ event_type: "transition", message: `Transition '${transition.name}' started: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
11859
|
+
for (const action of transition.actions ?? []) {
|
|
11860
|
+
try {
|
|
11861
|
+
if (action.type === "set_field") {
|
|
11862
|
+
const field = action.config?.field;
|
|
11863
|
+
if (action.config?.expression) {
|
|
11864
|
+
const expr = action.config.expression;
|
|
11865
|
+
const result = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
11866
|
+
inst.state_data[field] = result;
|
|
11867
|
+
} else if (action.config?.value !== void 0) {
|
|
11868
|
+
inst.state_data[field] = action.config.value;
|
|
11869
|
+
}
|
|
11870
|
+
events.push({ event_type: "action_executed", message: `transition action 'set_field' succeeded`, timestamp: now });
|
|
11871
|
+
} else if (action.type === "eval") {
|
|
11872
|
+
const expr = action.config?.expression;
|
|
11873
|
+
lastEvalResult = this.evaluateSimpleExpression(expr, inst.state_data);
|
|
11874
|
+
events.push({ event_type: "action_executed", message: `transition action 'eval' succeeded`, timestamp: now });
|
|
11875
|
+
} else {
|
|
11876
|
+
events.push({ event_type: "action_executed", message: `transition action '${action.type}' succeeded (no-op in local mode)`, timestamp: now });
|
|
11877
|
+
}
|
|
11878
|
+
} catch (err) {
|
|
11879
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
11880
|
+
events.push({ event_type: "action_failed", message: `transition action '${action.type}' failed: ${msg}`, timestamp: now });
|
|
11881
|
+
return {
|
|
11882
|
+
success: false,
|
|
11883
|
+
instance_id: inst.id,
|
|
11884
|
+
from_state: fromState,
|
|
11885
|
+
to_state: null,
|
|
11886
|
+
state_data: inst.state_data,
|
|
11887
|
+
event_log: events,
|
|
11888
|
+
error: `transition action failed: ${msg}`
|
|
11889
|
+
};
|
|
11890
|
+
}
|
|
11891
|
+
}
|
|
11892
|
+
inst.current_state = transition.to;
|
|
11893
|
+
inst.execution_lock_version++;
|
|
11894
|
+
inst.updated_at = now;
|
|
11895
|
+
events.push({ event_type: "transition", message: `State changed: ${fromState} \u2192 ${transition.to}`, timestamp: now });
|
|
11896
|
+
inst.event_log.push(...events);
|
|
11897
|
+
return {
|
|
11898
|
+
success: true,
|
|
11899
|
+
instance_id: inst.id,
|
|
11900
|
+
from_state: fromState,
|
|
11901
|
+
to_state: transition.to,
|
|
11902
|
+
state_data: inst.state_data,
|
|
11903
|
+
result: lastEvalResult,
|
|
11904
|
+
event_log: events
|
|
11905
|
+
};
|
|
11906
|
+
}
|
|
11907
|
+
/**
|
|
11908
|
+
* Minimal expression evaluator for local dev mode.
|
|
11909
|
+
* Handles: field references, arithmetic, string literals, simple comparisons.
|
|
11910
|
+
* Does NOT handle: while loops, if/else, function calls, multi-statement blocks.
|
|
11911
|
+
* For full evaluation, use mm-napi when available.
|
|
11912
|
+
*/
|
|
11913
|
+
evaluateSimpleExpression(expr, context) {
|
|
11914
|
+
if (context[expr] !== void 0) return context[expr];
|
|
11915
|
+
const arithMatch = expr.match(/^(\w+)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/);
|
|
11916
|
+
if (arithMatch) {
|
|
11917
|
+
const [, field, op, numStr] = arithMatch;
|
|
11918
|
+
const left = Number(context[field] ?? 0);
|
|
11919
|
+
const right = Number(numStr);
|
|
11920
|
+
switch (op) {
|
|
11921
|
+
case "+":
|
|
11922
|
+
return left + right;
|
|
11923
|
+
case "-":
|
|
11924
|
+
return left - right;
|
|
11925
|
+
case "*":
|
|
11926
|
+
return left * right;
|
|
11927
|
+
case "/":
|
|
11928
|
+
return right !== 0 ? left / right : 0;
|
|
11929
|
+
}
|
|
11930
|
+
}
|
|
11931
|
+
if (/^\d+(\.\d+)?$/.test(expr.trim())) {
|
|
11932
|
+
return Number(expr.trim());
|
|
11933
|
+
}
|
|
11934
|
+
const strMatch = expr.match(/^["'](.*)["']$/);
|
|
11935
|
+
if (strMatch) return strMatch[1];
|
|
11936
|
+
try {
|
|
11937
|
+
const keys = Object.keys(context);
|
|
11938
|
+
const values = Object.values(context);
|
|
11939
|
+
const fn = new Function(...keys, `"use strict"; return (${expr});`);
|
|
11940
|
+
return fn(...values);
|
|
11941
|
+
} catch {
|
|
11942
|
+
return null;
|
|
11943
|
+
}
|
|
11944
|
+
}
|
|
11945
|
+
};
|
|
11946
|
+
async function startLocalServer(options = {}) {
|
|
11947
|
+
const { port = 4200, noAuth = true } = options;
|
|
11948
|
+
const store = new MemoryStore();
|
|
11949
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11950
|
+
function json(res, status, body) {
|
|
11951
|
+
const data = JSON.stringify(body);
|
|
11952
|
+
res.writeHead(status, {
|
|
11953
|
+
"Content-Type": "application/json",
|
|
11954
|
+
"Access-Control-Allow-Origin": "*",
|
|
11955
|
+
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
11956
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
11957
|
+
"Content-Length": Buffer.byteLength(data)
|
|
11958
|
+
});
|
|
11959
|
+
res.end(data);
|
|
11960
|
+
}
|
|
11961
|
+
function readBody(req) {
|
|
11962
|
+
return new Promise((resolve2, reject) => {
|
|
11963
|
+
const chunks = [];
|
|
11964
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
11965
|
+
req.on("end", () => resolve2(Buffer.concat(chunks).toString()));
|
|
11966
|
+
req.on("error", reject);
|
|
11967
|
+
});
|
|
11968
|
+
}
|
|
11969
|
+
function parseQuery(url) {
|
|
11970
|
+
const idx = url.indexOf("?");
|
|
11971
|
+
if (idx === -1) return {};
|
|
11972
|
+
const params = {};
|
|
11973
|
+
const qs = url.slice(idx + 1);
|
|
11974
|
+
for (const pair of qs.split("&")) {
|
|
11975
|
+
const [k, v] = pair.split("=");
|
|
11976
|
+
if (k) params[decodeURIComponent(k)] = decodeURIComponent(v ?? "");
|
|
11977
|
+
}
|
|
11978
|
+
return params;
|
|
11979
|
+
}
|
|
11980
|
+
const server = http.createServer(async (req, res) => {
|
|
11981
|
+
const method = req.method?.toUpperCase() ?? "GET";
|
|
11982
|
+
const rawUrl = req.url ?? "/";
|
|
11983
|
+
const queryStart = rawUrl.indexOf("?");
|
|
11984
|
+
const path = queryStart >= 0 ? rawUrl.slice(0, queryStart) : rawUrl;
|
|
11985
|
+
const query = parseQuery(rawUrl);
|
|
11986
|
+
if (method === "OPTIONS") {
|
|
11987
|
+
res.writeHead(204, {
|
|
11988
|
+
"Access-Control-Allow-Origin": "*",
|
|
11989
|
+
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
|
11990
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
11991
|
+
"Access-Control-Max-Age": "86400"
|
|
11992
|
+
});
|
|
11993
|
+
res.end();
|
|
11994
|
+
return;
|
|
11995
|
+
}
|
|
11996
|
+
try {
|
|
11997
|
+
if (path === "/health" && method === "GET") {
|
|
11998
|
+
return json(res, 200, {
|
|
11999
|
+
status: "ok",
|
|
12000
|
+
service: "mm-local-dev",
|
|
12001
|
+
mode: "in-memory",
|
|
12002
|
+
started_at: startedAt,
|
|
12003
|
+
definitions: store.definitions.size,
|
|
12004
|
+
instances: store.instances.size
|
|
12005
|
+
});
|
|
12006
|
+
}
|
|
12007
|
+
if (path === "/api/v1/auth/login" && (method === "POST" || method === "GET")) {
|
|
12008
|
+
return json(res, 200, {
|
|
12009
|
+
token: "dev-token-local",
|
|
12010
|
+
user: {
|
|
12011
|
+
id: "dev-user-001",
|
|
12012
|
+
email: "dev@localhost",
|
|
12013
|
+
role: "admin",
|
|
12014
|
+
name: "Local Developer"
|
|
12015
|
+
}
|
|
12016
|
+
});
|
|
12017
|
+
}
|
|
12018
|
+
if (path === "/api/v1/workflow/definitions" && method === "GET") {
|
|
12019
|
+
const result = store.listDefinitions({
|
|
12020
|
+
category: query.category,
|
|
12021
|
+
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
12022
|
+
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
12023
|
+
});
|
|
12024
|
+
if (query.slug) {
|
|
12025
|
+
const def = store.getDefinition(query.slug);
|
|
12026
|
+
return json(res, 200, { items: def ? [def] : [], total: def ? 1 : 0 });
|
|
12027
|
+
}
|
|
12028
|
+
return json(res, 200, result);
|
|
12029
|
+
}
|
|
12030
|
+
const defMatch = path.match(/^\/api\/v1\/workflow\/definitions\/([^/]+)$/);
|
|
12031
|
+
if (defMatch && method === "GET") {
|
|
12032
|
+
const def = store.getDefinition(defMatch[1]);
|
|
12033
|
+
if (!def) return json(res, 404, { error: "Not found" });
|
|
12034
|
+
return json(res, 200, def);
|
|
12035
|
+
}
|
|
12036
|
+
if (path === "/api/v1/workflow/definitions" && method === "POST") {
|
|
12037
|
+
const body = JSON.parse(await readBody(req));
|
|
12038
|
+
const def = store.createDefinition(body);
|
|
12039
|
+
return json(res, 201, def);
|
|
12040
|
+
}
|
|
12041
|
+
if (defMatch && method === "PATCH") {
|
|
12042
|
+
const body = JSON.parse(await readBody(req));
|
|
12043
|
+
const updated = store.patchDefinition(defMatch[1], body);
|
|
12044
|
+
if (!updated) return json(res, 404, { error: "Not found" });
|
|
12045
|
+
return json(res, 200, updated);
|
|
12046
|
+
}
|
|
12047
|
+
if (defMatch && method === "DELETE") {
|
|
12048
|
+
const deleted = store.deleteDefinition(defMatch[1]);
|
|
12049
|
+
if (!deleted) return json(res, 404, { error: "Not found" });
|
|
12050
|
+
return json(res, 204, null);
|
|
12051
|
+
}
|
|
12052
|
+
if (path === "/api/v1/workflow/instances" && method === "GET") {
|
|
12053
|
+
const result = store.listInstances({
|
|
12054
|
+
definition_id: query.definition_id,
|
|
12055
|
+
limit: query.limit ? parseInt(query.limit, 10) : void 0,
|
|
12056
|
+
offset: query.offset ? parseInt(query.offset, 10) : void 0
|
|
12057
|
+
});
|
|
12058
|
+
return json(res, 200, result);
|
|
12059
|
+
}
|
|
12060
|
+
if (path === "/api/v1/workflow/instances" && method === "POST") {
|
|
12061
|
+
const body = JSON.parse(await readBody(req));
|
|
12062
|
+
const inst = store.createInstance(body);
|
|
12063
|
+
if (!inst) return json(res, 404, { error: "Definition not found" });
|
|
12064
|
+
return json(res, 201, inst);
|
|
12065
|
+
}
|
|
12066
|
+
const instMatch = path.match(/^\/api\/v1\/workflow\/instances\/([^/]+)$/);
|
|
12067
|
+
if (instMatch && method === "GET") {
|
|
12068
|
+
const inst = store.getInstance(instMatch[1]);
|
|
12069
|
+
if (!inst) return json(res, 404, { error: "Not found" });
|
|
12070
|
+
return json(res, 200, inst);
|
|
12071
|
+
}
|
|
12072
|
+
if (path === "/api/v1/workflow/execute-action" && method === "POST") {
|
|
12073
|
+
const body = JSON.parse(await readBody(req));
|
|
12074
|
+
const result = store.executeAction(body);
|
|
12075
|
+
return json(res, 200, result);
|
|
12076
|
+
}
|
|
12077
|
+
const dataMatch = path.match(/^\/api\/v1\/data\/([^/]+)$/);
|
|
12078
|
+
if (dataMatch && method === "GET") {
|
|
12079
|
+
const def = store.getDefinition(dataMatch[1]);
|
|
12080
|
+
if (!def) return json(res, 404, { error: "Not found" });
|
|
12081
|
+
const instances = store.listInstances({ definition_id: def.id });
|
|
12082
|
+
return json(res, 200, instances);
|
|
12083
|
+
}
|
|
12084
|
+
if (path.startsWith("/api/v1/")) {
|
|
12085
|
+
return json(res, 501, { error: "Not implemented in local dev mode", path, method });
|
|
12086
|
+
}
|
|
12087
|
+
return json(res, 404, { error: "Not found", path });
|
|
12088
|
+
} catch (err) {
|
|
12089
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12090
|
+
console.error(`[mm-local] ${method} ${path} \u2014 Error: ${message}`);
|
|
12091
|
+
return json(res, 500, { error: message });
|
|
12092
|
+
}
|
|
12093
|
+
});
|
|
12094
|
+
return new Promise((resolve2, reject) => {
|
|
12095
|
+
server.on("error", (err) => {
|
|
12096
|
+
if (err.code === "EADDRINUSE") {
|
|
12097
|
+
reject(new Error(`Port ${port} is already in use. Is another server running?`));
|
|
12098
|
+
} else {
|
|
12099
|
+
reject(err);
|
|
12100
|
+
}
|
|
12101
|
+
});
|
|
12102
|
+
server.listen(port, () => {
|
|
12103
|
+
console.log(`[mm-local] Local API server running at http://localhost:${port}`);
|
|
12104
|
+
console.log(`[mm-local] Mode: in-memory (data lost on restart)`);
|
|
12105
|
+
console.log(`[mm-local] Auth: disabled (all requests accepted)`);
|
|
12106
|
+
resolve2({
|
|
12107
|
+
server,
|
|
12108
|
+
port,
|
|
12109
|
+
store,
|
|
12110
|
+
async close() {
|
|
12111
|
+
return new Promise((res) => {
|
|
12112
|
+
server.close(() => {
|
|
12113
|
+
console.log("[mm-local] Local API server stopped");
|
|
12114
|
+
res();
|
|
12115
|
+
});
|
|
12116
|
+
});
|
|
12117
|
+
}
|
|
12118
|
+
});
|
|
12119
|
+
});
|
|
12120
|
+
});
|
|
12121
|
+
}
|
|
12122
|
+
|
|
11170
12123
|
// src/dev-server.ts
|
|
12124
|
+
var currentErrors = null;
|
|
12125
|
+
function escapeHtml(s) {
|
|
12126
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
12127
|
+
}
|
|
12128
|
+
function renderErrorOverlay(errors) {
|
|
12129
|
+
const cards = errors.map((err) => {
|
|
12130
|
+
const loc = err.line ? `${err.file}:${err.line}${err.column ? ":" + err.column : ""}` : err.file;
|
|
12131
|
+
const snippet = err.snippet ? `<pre style="background:#1a1a2e;color:#e0e0e0;padding:12px 16px;border-radius:6px;overflow-x:auto;margin-top:8px;font-size:13px;line-height:1.5">${escapeHtml(err.snippet)}</pre>` : "";
|
|
12132
|
+
return `<div style="background:#2d1b1b;border:1px solid #5c2020;border-radius:8px;padding:16px 20px;margin-bottom:12px">
|
|
12133
|
+
<div style="color:#ff6b6b;font-family:monospace;font-size:13px;margin-bottom:6px">${escapeHtml(loc)}</div>
|
|
12134
|
+
<div style="color:#ffa0a0;font-size:15px;font-weight:500">${escapeHtml(err.message)}</div>${snippet}</div>`;
|
|
12135
|
+
}).join("\n");
|
|
12136
|
+
return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
12137
|
+
<title>Compile Error - MindMatrix Dev</title>
|
|
12138
|
+
<style>*{box-sizing:border-box;margin:0;padding:0}body{background:#1a1a2e;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;padding:40px 20px;min-height:100vh}</style></head>
|
|
12139
|
+
<body><div style="max-width:800px;margin:0 auto">
|
|
12140
|
+
<div style="display:flex;align-items:center;gap:12px;margin-bottom:24px">
|
|
12141
|
+
<div style="background:#5c2020;color:#ff6b6b;font-size:14px;font-weight:600;padding:4px 10px;border-radius:4px">COMPILE ERROR</div>
|
|
12142
|
+
<div style="color:#888;font-size:13px">${errors.length} error${errors.length !== 1 ? "s" : ""}</div></div>
|
|
12143
|
+
${cards}
|
|
12144
|
+
<div style="color:#666;font-size:12px;margin-top:24px;text-align:center">Fix the error and save -- the page will reload automatically.</div></div>
|
|
12145
|
+
<script>const ws=new WebSocket('ws://'+location.host+'/__mm_dev');ws.onmessage=e=>{const m=JSON.parse(e.data);if(m.type==='workflow:compiled'||m.type==='workflow:rebuild')location.reload()};ws.onclose=()=>setTimeout(()=>location.reload(),2000)</script>
|
|
12146
|
+
</body></html>`;
|
|
12147
|
+
}
|
|
12148
|
+
function errorOverlayMiddleware() {
|
|
12149
|
+
return (req, res, next) => {
|
|
12150
|
+
if (!currentErrors || !req.url) return next();
|
|
12151
|
+
const url = req.url;
|
|
12152
|
+
if (url.startsWith("/api") || url.startsWith("/health") || url.startsWith("/ws") || url.startsWith("/__mm_dev") || url.startsWith("/@") || url.startsWith("/node_modules")) return next();
|
|
12153
|
+
const accept = req.headers?.accept ?? "";
|
|
12154
|
+
if (!accept.includes("text/html")) return next();
|
|
12155
|
+
res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
|
|
12156
|
+
res.end(renderErrorOverlay(currentErrors));
|
|
12157
|
+
};
|
|
12158
|
+
}
|
|
12159
|
+
async function resolveDevToken(apiUrl, explicit) {
|
|
12160
|
+
if (explicit) return explicit;
|
|
12161
|
+
try {
|
|
12162
|
+
const { resolveToken: resolveToken2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
12163
|
+
const s = resolveToken2(apiUrl);
|
|
12164
|
+
if (s) return s;
|
|
12165
|
+
} catch {
|
|
12166
|
+
}
|
|
12167
|
+
try {
|
|
12168
|
+
const resp = await fetch(`${apiUrl}/auth/login`, {
|
|
12169
|
+
method: "POST",
|
|
12170
|
+
headers: { "Content-Type": "application/json" },
|
|
12171
|
+
body: JSON.stringify({ email: "admin@mindmatrix.com", password: "Admin123!" })
|
|
12172
|
+
});
|
|
12173
|
+
if (resp.ok) {
|
|
12174
|
+
const data = await resp.json();
|
|
12175
|
+
const token = data.token ?? data.access_token;
|
|
12176
|
+
if (token) {
|
|
12177
|
+
try {
|
|
12178
|
+
const { saveCredentials: saveCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
12179
|
+
saveCredentials2(apiUrl, token);
|
|
12180
|
+
} catch {
|
|
12181
|
+
}
|
|
12182
|
+
return token;
|
|
12183
|
+
}
|
|
12184
|
+
}
|
|
12185
|
+
} catch {
|
|
12186
|
+
}
|
|
12187
|
+
return process.env.MINDMATRIX_TOKEN;
|
|
12188
|
+
}
|
|
12189
|
+
async function checkBackendHealth(apiUrl) {
|
|
12190
|
+
try {
|
|
12191
|
+
const base = apiUrl.replace(/\/api\/v1\/?$/, "");
|
|
12192
|
+
const resp = await fetch(`${base}/health`, { signal: AbortSignal.timeout(5e3) });
|
|
12193
|
+
if (resp.ok) {
|
|
12194
|
+
const d = await resp.json();
|
|
12195
|
+
return { ok: true, version: d.version, db: d.database };
|
|
12196
|
+
}
|
|
12197
|
+
return { ok: resp.status < 500 };
|
|
12198
|
+
} catch {
|
|
12199
|
+
return { ok: false };
|
|
12200
|
+
}
|
|
12201
|
+
}
|
|
12202
|
+
async function initialBuildDeploy(src, outDir, mode, apiUrl, token) {
|
|
12203
|
+
console.log("[mm-dev] Compiling project...");
|
|
12204
|
+
const buildResult = await build({ src, outDir, mode, skipTypeCheck: true });
|
|
12205
|
+
if (buildResult.errors > 0) {
|
|
12206
|
+
currentErrors = buildResult.errorDetails.map((e) => ({ file: e.file, message: e.message, line: e.line }));
|
|
12207
|
+
console.error(`[mm-dev] Build failed with ${buildResult.errors} error(s) -- error overlay active`);
|
|
12208
|
+
return { buildResult, deployed: false, slug: void 0 };
|
|
12209
|
+
}
|
|
12210
|
+
currentErrors = null;
|
|
12211
|
+
if (buildResult.compiled === 0) return { buildResult, deployed: false, slug: void 0 };
|
|
12212
|
+
console.log(`[mm-dev] Compiled ${buildResult.compiled} definition(s)`);
|
|
12213
|
+
try {
|
|
12214
|
+
const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
|
|
12215
|
+
const result = await deploy2({ apiUrl, token, dir: outDir });
|
|
12216
|
+
const total = result.created.length + result.updated.length + result.versioned.length;
|
|
12217
|
+
if (total > 0) console.log(`[mm-dev] Deployed: ${result.created.length} created, ${result.updated.length} updated`);
|
|
12218
|
+
return { buildResult, deployed: true, slug: buildResult.definitions?.[0]?.slug };
|
|
12219
|
+
} catch (e) {
|
|
12220
|
+
console.warn(`[mm-dev] Deploy failed: ${e instanceof Error ? e.message : e}`);
|
|
12221
|
+
return { buildResult, deployed: false, slug: void 0 };
|
|
12222
|
+
}
|
|
12223
|
+
}
|
|
12224
|
+
function printBanner(o) {
|
|
12225
|
+
const l = "-".repeat(58);
|
|
12226
|
+
console.log(`
|
|
12227
|
+
${l}
|
|
12228
|
+
MindMatrix Dev Server
|
|
12229
|
+
${l}
|
|
12230
|
+
`);
|
|
12231
|
+
console.log(` Preview: http://localhost:${o.port}`);
|
|
12232
|
+
console.log(` API Proxy: /api/* -> ${o.apiUrl}`);
|
|
12233
|
+
console.log(` WebSocket: ws://localhost:${o.port}/__mm_dev`);
|
|
12234
|
+
console.log(` Watching: ${o.src} (${o.include.join(", ")})
|
|
12235
|
+
`);
|
|
12236
|
+
console.log(` Backend: ${o.health.ok ? "connected" : "unreachable"}${o.health.version ? ` (v${o.health.version})` : ""}`);
|
|
12237
|
+
if (o.health.db) console.log(` Database: ${o.health.db}`);
|
|
12238
|
+
console.log(` Auth: ${o.token ? "authenticated" : "no token"}`);
|
|
12239
|
+
if (o.compiled > 0) {
|
|
12240
|
+
console.log(` Blueprint: ${o.slug ?? "unknown"} (${o.compiled} defs)`);
|
|
12241
|
+
console.log(` Deploy: ${o.deployed ? "synced" : "pending"}`);
|
|
12242
|
+
}
|
|
12243
|
+
if (o.errors > 0) console.log(` Errors: ${o.errors} compile error(s) -- overlay active`);
|
|
12244
|
+
console.log(`
|
|
12245
|
+
${l}
|
|
12246
|
+
`);
|
|
12247
|
+
}
|
|
12248
|
+
function broadcast(clients, data) {
|
|
12249
|
+
const msg = JSON.stringify(data);
|
|
12250
|
+
for (const c of clients) {
|
|
12251
|
+
try {
|
|
12252
|
+
if (c.readyState === 1) c.send(msg);
|
|
12253
|
+
} catch {
|
|
12254
|
+
clients.delete(c);
|
|
12255
|
+
}
|
|
12256
|
+
}
|
|
12257
|
+
}
|
|
11171
12258
|
async function createDevServer(options = {}) {
|
|
11172
12259
|
const {
|
|
11173
12260
|
port = 5199,
|
|
@@ -11176,44 +12263,87 @@ async function createDevServer(options = {}) {
|
|
|
11176
12263
|
include = ["**/*.workflow.tsx"],
|
|
11177
12264
|
outDir = "dist/workflows",
|
|
11178
12265
|
seed = false,
|
|
11179
|
-
apiUrl = "
|
|
11180
|
-
authToken
|
|
12266
|
+
apiUrl: rawApiUrl = "auto",
|
|
12267
|
+
authToken: explicitToken,
|
|
11181
12268
|
ws: enableWs = true,
|
|
11182
12269
|
open = false
|
|
11183
12270
|
} = options;
|
|
11184
12271
|
const clients = /* @__PURE__ */ new Set();
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
apiUrl
|
|
11191
|
-
|
|
11192
|
-
}
|
|
11193
|
-
|
|
11194
|
-
|
|
12272
|
+
let localServer = null;
|
|
12273
|
+
let apiUrl;
|
|
12274
|
+
let isLocalMode = false;
|
|
12275
|
+
if (rawApiUrl === "local") {
|
|
12276
|
+
localServer = await startLocalServer({ port: 4200 });
|
|
12277
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
12278
|
+
isLocalMode = true;
|
|
12279
|
+
} else if (rawApiUrl === "auto") {
|
|
12280
|
+
const defaultRemote = "https://dev.mindmatrix.club/api/v1";
|
|
12281
|
+
const remoteHealth = await checkBackendHealth(defaultRemote);
|
|
12282
|
+
if (remoteHealth.ok) {
|
|
12283
|
+
apiUrl = defaultRemote;
|
|
12284
|
+
} else {
|
|
12285
|
+
const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
|
|
12286
|
+
if (localHealth.ok) {
|
|
12287
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
12288
|
+
} else {
|
|
12289
|
+
console.log("[mm-dev] No backend detected \u2014 starting local in-memory API server...");
|
|
12290
|
+
localServer = await startLocalServer({ port: 4200 });
|
|
12291
|
+
apiUrl = "http://localhost:4200/api/v1";
|
|
12292
|
+
isLocalMode = true;
|
|
12293
|
+
}
|
|
12294
|
+
}
|
|
12295
|
+
} else {
|
|
12296
|
+
apiUrl = rawApiUrl;
|
|
12297
|
+
}
|
|
12298
|
+
const token = isLocalMode ? "dev-token-local" : await resolveDevToken(apiUrl, explicitToken);
|
|
12299
|
+
const health = isLocalMode ? { ok: true, version: "local", db: "in-memory" } : await checkBackendHealth(apiUrl);
|
|
12300
|
+
let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
|
|
12301
|
+
if (token && health.ok) {
|
|
12302
|
+
const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
|
|
12303
|
+
initialCompiled = r.buildResult.compiled;
|
|
12304
|
+
initialDeployed = r.deployed;
|
|
12305
|
+
initialSlug = r.slug;
|
|
12306
|
+
initialErrors = r.buildResult.errors;
|
|
12307
|
+
}
|
|
12308
|
+
if (seed && token && initialDeployed) {
|
|
12309
|
+
try {
|
|
12310
|
+
const { seedInstances: seedInstances2 } = await Promise.resolve().then(() => (init_seed(), seed_exports));
|
|
12311
|
+
console.log("[mm-dev] Seeding sample instances...");
|
|
12312
|
+
const sr = await seedInstances2({ apiUrl, token, dir: outDir });
|
|
12313
|
+
console.log(`[mm-dev] Seeded ${sr.created} instance(s) across ${sr.definitions} definition(s)`);
|
|
12314
|
+
} catch (e) {
|
|
12315
|
+
console.warn(`[mm-dev] Seed failed: ${e instanceof Error ? e.message : e}`);
|
|
12316
|
+
}
|
|
12317
|
+
}
|
|
12318
|
+
const pluginOpts = { mode, include, outDir, seedOnCompile: seed, apiUrl, authToken: token };
|
|
12319
|
+
const proxyTarget = apiUrl.replace(/\/api\/v1\/?$/, "") || apiUrl;
|
|
12320
|
+
let deployInFlight = false;
|
|
12321
|
+
const compileDeployPlugin = {
|
|
12322
|
+
name: "mindmatrix-dev-compile-deploy",
|
|
11195
12323
|
enforce: "post",
|
|
11196
|
-
handleHotUpdate(ctx) {
|
|
11197
|
-
const
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
});
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
}
|
|
11207
|
-
|
|
12324
|
+
async handleHotUpdate(ctx) {
|
|
12325
|
+
const isWf = include.some((p) => new RegExp(p.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "<<G>>").replace(/\*/g, "[^/]*").replace(/<<G>>/g, ".*").replace(/\?/g, ".")).test(ctx.file));
|
|
12326
|
+
if (!isWf) return;
|
|
12327
|
+
const fn = ctx.file.split("/").pop() ?? ctx.file;
|
|
12328
|
+
console.log(`[mm-dev] Recompiling ${fn}...`);
|
|
12329
|
+
const br = await build({ src, outDir, mode, skipTypeCheck: true });
|
|
12330
|
+
if (br.errors > 0) {
|
|
12331
|
+
currentErrors = br.errorDetails.map((e) => ({ file: e.file, message: e.message, line: e.line }));
|
|
12332
|
+
broadcast(clients, { type: "workflow:error", errors: br.errors, timestamp: ctx.timestamp });
|
|
12333
|
+
return;
|
|
12334
|
+
}
|
|
12335
|
+
currentErrors = null;
|
|
12336
|
+
if (token && !deployInFlight) {
|
|
12337
|
+
deployInFlight = true;
|
|
11208
12338
|
try {
|
|
11209
|
-
|
|
11210
|
-
|
|
11211
|
-
}
|
|
12339
|
+
const { deploy: d } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
|
|
12340
|
+
await d({ apiUrl, token, dir: outDir });
|
|
11212
12341
|
} catch {
|
|
11213
|
-
|
|
12342
|
+
} finally {
|
|
12343
|
+
deployInFlight = false;
|
|
11214
12344
|
}
|
|
11215
12345
|
}
|
|
11216
|
-
|
|
12346
|
+
broadcast(clients, { type: "workflow:compiled", file: ctx.file, compiled: br.compiled, timestamp: ctx.timestamp });
|
|
11217
12347
|
}
|
|
11218
12348
|
};
|
|
11219
12349
|
const viteConfig = {
|
|
@@ -11221,86 +12351,76 @@ async function createDevServer(options = {}) {
|
|
|
11221
12351
|
server: {
|
|
11222
12352
|
port,
|
|
11223
12353
|
open,
|
|
11224
|
-
host: true
|
|
12354
|
+
host: true,
|
|
12355
|
+
proxy: {
|
|
12356
|
+
"/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
|
|
12357
|
+
"/health": { target: proxyTarget, changeOrigin: true, secure: true },
|
|
12358
|
+
"/ws": { target: proxyTarget.replace(/^http/, "ws"), changeOrigin: true, ws: true }
|
|
12359
|
+
}
|
|
11225
12360
|
},
|
|
11226
12361
|
plugins: [
|
|
11227
|
-
mindmatrixReact(
|
|
11228
|
-
|
|
12362
|
+
mindmatrixReact(pluginOpts),
|
|
12363
|
+
compileDeployPlugin,
|
|
12364
|
+
{ name: "mindmatrix-error-overlay", configureServer(server) {
|
|
12365
|
+
server.middlewares.use(errorOverlayMiddleware());
|
|
12366
|
+
} }
|
|
11229
12367
|
],
|
|
11230
|
-
logLevel: "
|
|
12368
|
+
logLevel: "warn"
|
|
11231
12369
|
};
|
|
11232
|
-
const { createServer } = await import("vite");
|
|
11233
|
-
const vite = await
|
|
12370
|
+
const { createServer: createServer2 } = await import("vite");
|
|
12371
|
+
const vite = await createServer2(viteConfig);
|
|
11234
12372
|
await vite.listen();
|
|
11235
12373
|
const resolvedPort = vite.config.server.port ?? port;
|
|
11236
12374
|
if (enableWs && vite.httpServer) {
|
|
11237
12375
|
try {
|
|
11238
|
-
const
|
|
11239
|
-
const
|
|
11240
|
-
if (
|
|
11241
|
-
const wss = new
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
clients.add(socket);
|
|
11247
|
-
console.log(`[mm-dev] Editor connected (${clients.size} total)`);
|
|
11248
|
-
socket.on("close", () => {
|
|
11249
|
-
clients.delete(socket);
|
|
11250
|
-
console.log(`[mm-dev] Editor disconnected (${clients.size} total)`);
|
|
11251
|
-
});
|
|
11252
|
-
socket.send(JSON.stringify({
|
|
11253
|
-
type: "mm:connected",
|
|
11254
|
-
version: "0.1.0",
|
|
11255
|
-
capabilities: ["compile", "seed", "notify"]
|
|
11256
|
-
}));
|
|
12376
|
+
const wsM = await Function('return import("ws")')();
|
|
12377
|
+
const WSS = wsM.WebSocketServer ?? wsM.default?.WebSocketServer;
|
|
12378
|
+
if (WSS) {
|
|
12379
|
+
const wss = new WSS({ server: vite.httpServer, path: "/__mm_dev" });
|
|
12380
|
+
wss.on("connection", (s) => {
|
|
12381
|
+
clients.add(s);
|
|
12382
|
+
s.on("close", () => clients.delete(s));
|
|
12383
|
+
s.send(JSON.stringify({ type: "mm:connected", version: "0.1.0", capabilities: ["compile", "deploy", "proxy", "notify", "error-overlay"] }));
|
|
11257
12384
|
});
|
|
11258
12385
|
}
|
|
11259
12386
|
} catch {
|
|
11260
|
-
console.warn("[mm-dev] ws package not available \u2014 WebSocket notifications disabled");
|
|
11261
12387
|
}
|
|
11262
12388
|
}
|
|
11263
|
-
|
|
11264
|
-
[mm-dev] MindMatrix Dev Server running`);
|
|
11265
|
-
console.log(` Local: http://localhost:${resolvedPort}`);
|
|
11266
|
-
console.log(` WebSocket: ws://localhost:${resolvedPort}/__mm_dev`);
|
|
11267
|
-
console.log(` Watching: ${src} (${include.join(", ")})`);
|
|
11268
|
-
if (seed) {
|
|
11269
|
-
console.log(` Seeding: ${apiUrl}`);
|
|
11270
|
-
}
|
|
11271
|
-
console.log();
|
|
12389
|
+
printBanner({ port: resolvedPort, apiUrl: isLocalMode ? `${apiUrl} (local in-memory)` : apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
|
|
11272
12390
|
return {
|
|
11273
12391
|
vite,
|
|
11274
12392
|
port: resolvedPort,
|
|
11275
12393
|
clients,
|
|
11276
12394
|
async rebuild() {
|
|
11277
|
-
|
|
11278
|
-
|
|
11279
|
-
|
|
11280
|
-
|
|
11281
|
-
|
|
11282
|
-
|
|
11283
|
-
|
|
11284
|
-
|
|
11285
|
-
|
|
11286
|
-
|
|
11287
|
-
|
|
11288
|
-
} catch {
|
|
11289
|
-
clients.delete(client);
|
|
12395
|
+
const r = await build({ src, outDir, mode });
|
|
12396
|
+
if (r.errors > 0) {
|
|
12397
|
+
currentErrors = r.errorDetails.map((e) => ({ file: e.file, message: e.message, line: e.line }));
|
|
12398
|
+
} else {
|
|
12399
|
+
currentErrors = null;
|
|
12400
|
+
if (token) {
|
|
12401
|
+
try {
|
|
12402
|
+
const { deploy: d } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
|
|
12403
|
+
await d({ apiUrl, token, dir: outDir });
|
|
12404
|
+
} catch {
|
|
12405
|
+
}
|
|
11290
12406
|
}
|
|
11291
12407
|
}
|
|
11292
|
-
|
|
12408
|
+
broadcast(clients, { type: "workflow:rebuild", compiled: r.compiled, errors: r.errors, timestamp: Date.now() });
|
|
12409
|
+
return r;
|
|
11293
12410
|
},
|
|
11294
12411
|
async close() {
|
|
11295
|
-
for (const
|
|
12412
|
+
for (const c of clients) {
|
|
11296
12413
|
try {
|
|
11297
|
-
|
|
12414
|
+
c.close();
|
|
11298
12415
|
} catch {
|
|
11299
12416
|
}
|
|
11300
12417
|
}
|
|
11301
12418
|
clients.clear();
|
|
12419
|
+
currentErrors = null;
|
|
11302
12420
|
await vite.close();
|
|
11303
|
-
|
|
12421
|
+
if (localServer) {
|
|
12422
|
+
await localServer.close();
|
|
12423
|
+
}
|
|
11304
12424
|
}
|
|
11305
12425
|
};
|
|
11306
12426
|
}
|