@mmapp/react-compiler 0.1.0-alpha.4 → 0.1.0-alpha.6

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.
Files changed (103) hide show
  1. package/dist/babel/index.d.mts +2 -2
  2. package/dist/babel/index.d.ts +2 -2
  3. package/dist/babel/index.js +5 -5
  4. package/dist/babel/index.mjs +1 -1
  5. package/dist/cli/index.js +797 -1941
  6. package/dist/cli/index.mjs +179 -77
  7. package/dist/codemod/cli.js +1 -1
  8. package/dist/codemod/cli.mjs +1 -1
  9. package/dist/codemod/index.d.mts +3 -3
  10. package/dist/codemod/index.d.ts +3 -3
  11. package/dist/codemod/index.js +1 -1
  12. package/dist/codemod/index.mjs +1 -1
  13. package/dist/dev-server.d.mts +2 -2
  14. package/dist/dev-server.d.ts +2 -2
  15. package/dist/dev-server.js +86 -1218
  16. package/dist/dev-server.mjs +4 -4
  17. package/dist/envelope.d.mts +2 -2
  18. package/dist/envelope.d.ts +2 -2
  19. package/dist/envelope.js +5 -5
  20. package/dist/envelope.mjs +2 -2
  21. package/dist/index.d.mts +8 -8
  22. package/dist/index.d.ts +8 -8
  23. package/dist/index.js +342 -1266
  24. package/dist/index.mjs +8 -8
  25. package/dist/testing/index.d.mts +8 -8
  26. package/dist/testing/index.d.ts +8 -8
  27. package/dist/testing/index.js +5 -5
  28. package/dist/testing/index.mjs +1 -1
  29. package/dist/vite/index.d.mts +1 -1
  30. package/dist/vite/index.d.ts +1 -1
  31. package/dist/vite/index.js +5 -5
  32. package/dist/vite/index.mjs +2 -2
  33. package/examples/authentication/main.workflow.tsx +1 -1
  34. package/examples/authentication/mm.config.ts +1 -1
  35. package/examples/authentication/pages/LoginPage.tsx +2 -2
  36. package/examples/authentication/pages/SignupPage.tsx +2 -2
  37. package/examples/counter.workflow.tsx +1 -1
  38. package/examples/dashboard.workflow.tsx +1 -1
  39. package/examples/invoice-approval/actions/invoice.server.ts +1 -1
  40. package/examples/invoice-approval/main.workflow.tsx +1 -1
  41. package/examples/invoice-approval/mm.config.ts +1 -1
  42. package/examples/invoice-approval/pages/InvoiceDetailPage.tsx +1 -1
  43. package/examples/invoice-approval/pages/InvoiceFormPage.tsx +1 -1
  44. package/examples/invoice-approval/pages/InvoiceListPage.tsx +1 -1
  45. package/examples/todo-app.workflow.tsx +1 -1
  46. package/examples/uber-app/actions/matching.server.ts +1 -1
  47. package/examples/uber-app/actions/notifications.server.ts +1 -1
  48. package/examples/uber-app/actions/payments.server.ts +1 -1
  49. package/examples/uber-app/actions/pricing.server.ts +1 -1
  50. package/examples/uber-app/app/admin/analytics.tsx +2 -2
  51. package/examples/uber-app/app/admin/fleet.tsx +2 -2
  52. package/examples/uber-app/app/admin/surge-pricing.tsx +2 -2
  53. package/examples/uber-app/app/driver/dashboard.tsx +2 -2
  54. package/examples/uber-app/app/driver/earnings.tsx +2 -2
  55. package/examples/uber-app/app/driver/navigation.tsx +2 -2
  56. package/examples/uber-app/app/driver/ride-acceptance.tsx +2 -2
  57. package/examples/uber-app/app/rider/home.tsx +2 -2
  58. package/examples/uber-app/app/rider/payment-methods.tsx +2 -2
  59. package/examples/uber-app/app/rider/ride-history.tsx +2 -2
  60. package/examples/uber-app/app/rider/ride-tracking.tsx +2 -2
  61. package/examples/uber-app/components/DriverCard.tsx +1 -1
  62. package/examples/uber-app/components/MapView.tsx +3 -3
  63. package/examples/uber-app/components/RatingStars.tsx +2 -2
  64. package/examples/uber-app/components/RideCard.tsx +1 -1
  65. package/examples/uber-app/mm.config.ts +1 -1
  66. package/examples/uber-app/workflows/dispute-resolution.workflow.tsx +2 -2
  67. package/examples/uber-app/workflows/driver-onboarding.workflow.tsx +2 -2
  68. package/examples/uber-app/workflows/payment-processing.workflow.tsx +2 -2
  69. package/examples/uber-app/workflows/ride-request.workflow.tsx +2 -2
  70. package/package.json +13 -9
  71. package/dist/auth-3UK75242.mjs +0 -17
  72. package/dist/chunk-5FTDWKHH.mjs +0 -244
  73. package/dist/chunk-7JRAEFRB.mjs +0 -7510
  74. package/dist/chunk-7T6Q5KAA.mjs +0 -7506
  75. package/dist/chunk-ABYPKRSB.mjs +0 -215
  76. package/dist/chunk-BZEXUPDH.mjs +0 -175
  77. package/dist/chunk-HRYR54PT.mjs +0 -175
  78. package/dist/chunk-J3M4GUS7.mjs +0 -161
  79. package/dist/chunk-JRGFBWTN.mjs +0 -2918
  80. package/dist/chunk-O4AUS7EU.mjs +0 -148
  81. package/dist/chunk-R2DD5GTY.mjs +0 -186
  82. package/dist/chunk-UDDTWG5J.mjs +0 -734
  83. package/dist/chunk-VLTKQDJ3.mjs +0 -244
  84. package/dist/chunk-WVYY32LD.mjs +0 -939
  85. package/dist/chunk-XDVM4YHX.mjs +0 -3450
  86. package/dist/chunk-Z2G5RZ4H.mjs +0 -186
  87. package/dist/chunk-ZE3KCHBM.mjs +0 -2918
  88. package/dist/deploy-YAJGW6II.mjs +0 -9
  89. package/dist/dev-server-CrQ041KP.d.mts +0 -79
  90. package/dist/dev-server-CrQ041KP.d.ts +0 -79
  91. package/dist/envelope-ChEkuHij.d.mts +0 -265
  92. package/dist/envelope-ChEkuHij.d.ts +0 -265
  93. package/dist/index-CEKyyazf.d.mts +0 -104
  94. package/dist/index-CEKyyazf.d.ts +0 -104
  95. package/dist/init-7FJENUDK.mjs +0 -407
  96. package/dist/project-compiler-NNK32MPG.mjs +0 -10
  97. package/dist/project-compiler-ZB4RUYVL.mjs +0 -10
  98. package/dist/project-decompiler-U55HQUHW.mjs +0 -7
  99. package/dist/pull-KOL2QAYQ.mjs +0 -109
  100. package/dist/seed-KOGEPGOJ.mjs +0 -154
  101. package/dist/server-VW6UPCHO.mjs +0 -277
  102. package/dist/verify-BYHUKARQ.mjs +0 -1833
  103. package/dist/verify-OQDEQYMS.mjs +0 -1833
package/dist/index.js CHANGED
@@ -2680,7 +2680,7 @@ var import_player_core, PROP_RULES, COMPONENT_RENAMES, RENAME_EXTRA_CONFIG, emit
2680
2680
  var init_pure_form_emitter = __esm({
2681
2681
  "src/babel/emitters/pure-form-emitter.ts"() {
2682
2682
  "use strict";
2683
- import_player_core = require("@mmapp/player-core");
2683
+ import_player_core = require("@mindmatrix/player-core");
2684
2684
  init_transition_extractor();
2685
2685
  init_experience_transform();
2686
2686
  PROP_RULES = {
@@ -5220,7 +5220,7 @@ function extractImperativeWorkflow(path, state) {
5220
5220
  const source = node.source.value;
5221
5221
  for (const spec of node.specifiers) {
5222
5222
  const localName = spec.local.name;
5223
- if (source.includes("@mmapp/react") || source.includes("@mmapp/react")) {
5223
+ if (source.includes("@mmapp/react") || source.includes("@mindmatrix/react")) {
5224
5224
  stdLibImports.add(localName);
5225
5225
  } else {
5226
5226
  importedFns.set(localName, source);
@@ -7413,7 +7413,7 @@ function createVisitor(options = {}) {
7413
7413
  if (mode === "strict" && STRICT_BANNED_HOOKS[hookName]) {
7414
7414
  const error = {
7415
7415
  code: STRICT_BANNED_HOOKS[hookName],
7416
- message: `${hookName}() is not allowed in strict mode. Use @mmapp/react effect hooks instead.`,
7416
+ message: `${hookName}() is not allowed in strict mode. Use @mindmatrix/react effect hooks instead.`,
7417
7417
  line: path.node.loc?.start.line,
7418
7418
  column: path.node.loc?.start.column,
7419
7419
  severity: "error"
@@ -7505,12 +7505,12 @@ function createVisitor(options = {}) {
7505
7505
  }
7506
7506
  }
7507
7507
  if (mode !== "strict") return;
7508
- if (source.startsWith("@mmapp/") || source.startsWith("@mmapp/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
7508
+ if (source.startsWith("@mindmatrix/") || source.startsWith("@mmapp/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
7509
7509
  return;
7510
7510
  }
7511
7511
  const error = {
7512
7512
  code: "STRICT_FORBIDDEN_IMPORT",
7513
- message: `Import from '${source}' is not allowed in strict mode. Only @mmapp/* and relative imports are permitted.`,
7513
+ message: `Import from '${source}' is not allowed in strict mode. Only @mindmatrix/* and relative imports are permitted.`,
7514
7514
  line: path.node.loc?.start.line,
7515
7515
  column: path.node.loc?.start.column,
7516
7516
  severity: "error"
@@ -10616,552 +10616,6 @@ var init_project_compiler = __esm({
10616
10616
  }
10617
10617
  });
10618
10618
 
10619
- // src/cli/auth.ts
10620
- var auth_exports = {};
10621
- __export(auth_exports, {
10622
- loadCredentials: () => loadCredentials,
10623
- login: () => login,
10624
- logout: () => logout,
10625
- resolveToken: () => resolveToken,
10626
- saveCredentials: () => saveCredentials,
10627
- whoami: () => whoami
10628
- });
10629
- function loadCredentials() {
10630
- if (!(0, import_fs4.existsSync)(CREDENTIALS_PATH)) return {};
10631
- try {
10632
- return JSON.parse((0, import_fs4.readFileSync)(CREDENTIALS_PATH, "utf-8"));
10633
- } catch {
10634
- return {};
10635
- }
10636
- }
10637
- function saveCredentials(apiUrl, token) {
10638
- (0, import_fs4.mkdirSync)(MMRC_DIR, { recursive: true, mode: 448 });
10639
- const creds = loadCredentials();
10640
- creds[apiUrl] = { token, savedAt: (/* @__PURE__ */ new Date()).toISOString() };
10641
- (0, import_fs4.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
10642
- try {
10643
- const { chmodSync } = require("fs");
10644
- chmodSync(CREDENTIALS_PATH, 384);
10645
- } catch {
10646
- }
10647
- }
10648
- function removeCredentials(apiUrl) {
10649
- if (!(0, import_fs4.existsSync)(CREDENTIALS_PATH)) return;
10650
- if (!apiUrl) {
10651
- (0, import_fs4.unlinkSync)(CREDENTIALS_PATH);
10652
- return;
10653
- }
10654
- const creds = loadCredentials();
10655
- delete creds[apiUrl];
10656
- if (Object.keys(creds).length === 0) {
10657
- (0, import_fs4.unlinkSync)(CREDENTIALS_PATH);
10658
- } else {
10659
- (0, import_fs4.writeFileSync)(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
10660
- }
10661
- }
10662
- function resolveToken(apiUrl, explicitToken) {
10663
- if (explicitToken) return explicitToken;
10664
- const envToken = process.env.MMRC_TOKEN;
10665
- if (envToken) return envToken;
10666
- const creds = loadCredentials();
10667
- const entry = creds[apiUrl];
10668
- if (entry?.token) return entry.token;
10669
- return null;
10670
- }
10671
- function prompt(question, hidden = false) {
10672
- return new Promise((resolve3) => {
10673
- const rl = (0, import_readline.createInterface)({
10674
- input: process.stdin,
10675
- output: process.stdout
10676
- });
10677
- if (hidden && process.stdin.isTTY) {
10678
- const origWrite = process.stdout.write.bind(process.stdout);
10679
- process.stdout.write = ((chunk, encodingOrCb, cb) => {
10680
- if (typeof chunk === "string" && chunk.includes(question)) {
10681
- return origWrite(chunk, encodingOrCb, cb);
10682
- }
10683
- if (typeof chunk === "string" && !chunk.includes("\n")) {
10684
- return true;
10685
- }
10686
- return origWrite(chunk, encodingOrCb, cb);
10687
- });
10688
- rl.question(question, (answer) => {
10689
- process.stdout.write = origWrite;
10690
- console.log();
10691
- rl.close();
10692
- resolve3(answer.trim());
10693
- });
10694
- } else {
10695
- rl.question(question, (answer) => {
10696
- rl.close();
10697
- resolve3(answer.trim());
10698
- });
10699
- }
10700
- });
10701
- }
10702
- async function login(apiUrl, email, password) {
10703
- if (!email) {
10704
- email = await prompt("Email: ");
10705
- }
10706
- if (!password) {
10707
- password = await prompt("Password: ", true);
10708
- }
10709
- if (!email || !password) {
10710
- throw new Error("Email and password are required");
10711
- }
10712
- console.log(`[mmrc] Logging in to ${apiUrl}...`);
10713
- const res = await fetch(`${apiUrl}/auth/login`, {
10714
- method: "POST",
10715
- headers: { "Content-Type": "application/json" },
10716
- body: JSON.stringify({ email, password })
10717
- });
10718
- if (!res.ok) {
10719
- const text = await res.text();
10720
- throw new Error(`Login failed: ${res.status} ${text}`);
10721
- }
10722
- const data = await res.json();
10723
- const token = data.token ?? data.access_token ?? data.accessToken;
10724
- if (!token) {
10725
- throw new Error("Login succeeded but no token in response");
10726
- }
10727
- saveCredentials(apiUrl, token);
10728
- const userName = data.name ?? data.user?.name ?? data.user?.email ?? email;
10729
- console.log(`[mmrc] Logged in as ${userName}`);
10730
- console.log(`[mmrc] Token saved to ${CREDENTIALS_PATH}`);
10731
- return token;
10732
- }
10733
- function logout(apiUrl) {
10734
- if (apiUrl) {
10735
- removeCredentials(apiUrl);
10736
- console.log(`[mmrc] Credentials removed for ${apiUrl}`);
10737
- } else {
10738
- removeCredentials();
10739
- console.log("[mmrc] All saved credentials removed");
10740
- }
10741
- }
10742
- async function whoami(apiUrl) {
10743
- const token = resolveToken(apiUrl);
10744
- if (!token) {
10745
- console.log("[mmrc] Not logged in. Run `mmrc login` to authenticate.");
10746
- return;
10747
- }
10748
- try {
10749
- const res = await fetch(`${apiUrl}/auth/me`, {
10750
- headers: { Authorization: `Bearer ${token}` }
10751
- });
10752
- if (!res.ok) {
10753
- if (res.status === 401) {
10754
- console.log("[mmrc] Token is expired or invalid. Run `mmrc login` to re-authenticate.");
10755
- return;
10756
- }
10757
- console.log(`[mmrc] Failed to fetch user info: ${res.status}`);
10758
- return;
10759
- }
10760
- const user = await res.json();
10761
- console.log(`[mmrc] Logged in to ${apiUrl}`);
10762
- console.log(` Name: ${user.name ?? "(unknown)"}`);
10763
- console.log(` Email: ${user.email ?? "(unknown)"}`);
10764
- if (user.id) console.log(` ID: ${user.id}`);
10765
- if (user.role) console.log(` Role: ${user.role}`);
10766
- } catch (error) {
10767
- console.log(`[mmrc] Could not connect to ${apiUrl}: ${error.message}`);
10768
- }
10769
- }
10770
- var import_fs4, import_path3, import_os, import_readline, MMRC_DIR, CREDENTIALS_PATH;
10771
- var init_auth = __esm({
10772
- "src/cli/auth.ts"() {
10773
- "use strict";
10774
- import_fs4 = require("fs");
10775
- import_path3 = require("path");
10776
- import_os = require("os");
10777
- import_readline = require("readline");
10778
- MMRC_DIR = (0, import_path3.join)((0, import_os.homedir)(), ".mmrc");
10779
- CREDENTIALS_PATH = (0, import_path3.join)(MMRC_DIR, "credentials.json");
10780
- }
10781
- });
10782
-
10783
- // src/cli/deploy.ts
10784
- var deploy_exports = {};
10785
- __export(deploy_exports, {
10786
- deploy: () => deploy,
10787
- syncServices: () => syncServices
10788
- });
10789
- async function deploy(options) {
10790
- const dir = options.dir ?? "dist/workflows";
10791
- const targetLabel = options.targetName ? ` (target: ${options.targetName})` : "";
10792
- console.log(`[mindmatrix-react] Deploying workflows from ${dir} to ${options.apiUrl}${targetLabel}...`);
10793
- const files = await (0, import_glob2.glob)(`${dir}/**/*.workflow.json`);
10794
- if (files.length === 0) {
10795
- console.log(`[mindmatrix-react] No workflow files found in ${dir}`);
10796
- return { created: [], updated: [], versioned: [], skipped: [], failed: [] };
10797
- }
10798
- const result = {
10799
- created: [],
10800
- updated: [],
10801
- versioned: [],
10802
- skipped: [],
10803
- failed: []
10804
- };
10805
- const deployedIRs = [];
10806
- for (const file2 of files) {
10807
- try {
10808
- const ir = JSON.parse((0, import_fs5.readFileSync)(file2, "utf-8"));
10809
- const slug = ir.slug;
10810
- if (options.dryRun) {
10811
- console.log(` [dry-run] Would deploy ${slug} (${(0, import_path4.basename)(file2)})`);
10812
- continue;
10813
- }
10814
- const existing = await fetchExistingDefinition(options.apiUrl, options.token, slug);
10815
- if (!existing) {
10816
- await createDefinition(options.apiUrl, options.token, ir);
10817
- console.log(` \u2713 ${slug} (created)`);
10818
- result.created.push(slug);
10819
- } else if (existing.instanceCount === 0 || options.force) {
10820
- await updateDefinition(options.apiUrl, options.token, existing.id, ir);
10821
- console.log(` \u2713 ${slug} (updated)`);
10822
- result.updated.push(slug);
10823
- } else {
10824
- const newVersion = bumpVersion(existing.version);
10825
- ir.version = newVersion;
10826
- await createDefinition(options.apiUrl, options.token, ir);
10827
- console.log(` \u2713 ${slug} v${newVersion} (new version, ${existing.instanceCount} instances on v${existing.version})`);
10828
- result.versioned.push(slug);
10829
- }
10830
- deployedIRs.push(ir);
10831
- } catch (error) {
10832
- const slug = (0, import_path4.basename)(file2).replace(".workflow.json", "");
10833
- const msg = error.message;
10834
- console.error(` \u2717 ${slug}: ${msg}`);
10835
- result.failed.push({ slug, error: msg });
10836
- }
10837
- }
10838
- if (!options.dryRun) {
10839
- for (const ir of deployedIRs) {
10840
- const serviceResult = await syncServices(options.apiUrl, options.token, ir);
10841
- if (serviceResult) {
10842
- if (!result.services) {
10843
- result.services = { registered: [], updated: [], failed: [] };
10844
- }
10845
- result.services.registered.push(...serviceResult.registered);
10846
- result.services.updated.push(...serviceResult.updated);
10847
- result.services.failed.push(...serviceResult.failed);
10848
- }
10849
- }
10850
- }
10851
- if (options.reportFile) {
10852
- (0, import_fs5.writeFileSync)(options.reportFile, JSON.stringify(result, null, 2), "utf-8");
10853
- console.log(`
10854
- Report written to ${options.reportFile}`);
10855
- }
10856
- const total = result.created.length + result.updated.length + result.versioned.length;
10857
- console.log(
10858
- `
10859
- [mindmatrix-react] Deployed ${total} workflows (${result.created.length} created, ${result.updated.length} updated, ${result.versioned.length} versioned, ${result.failed.length} failed)`
10860
- );
10861
- if (result.services) {
10862
- const svcTotal = result.services.registered.length + result.services.updated.length;
10863
- if (svcTotal > 0 || result.services.failed.length > 0) {
10864
- console.log(
10865
- `[mindmatrix-react] Synced ${svcTotal} services (${result.services.registered.length} registered, ${result.services.updated.length} updated, ${result.services.failed.length} failed)`
10866
- );
10867
- }
10868
- }
10869
- return result;
10870
- }
10871
- async function fetchExistingDefinition(apiUrl, token, slug) {
10872
- try {
10873
- const res = await fetch(`${apiUrl}/workflow/definitions?slug=${encodeURIComponent(slug)}`, {
10874
- headers: { Authorization: `Bearer ${token}` }
10875
- });
10876
- if (!res.ok) return null;
10877
- const data = await res.json();
10878
- const definitions = Array.isArray(data) ? data : data.items ?? data.data;
10879
- if (!definitions || definitions.length === 0) return null;
10880
- const def = definitions[0];
10881
- return {
10882
- id: def.id,
10883
- slug: def.slug,
10884
- version: def.version || "0.1.0",
10885
- instanceCount: def.instanceCount ?? def.instance_count ?? 0
10886
- };
10887
- } catch {
10888
- return null;
10889
- }
10890
- }
10891
- async function createDefinition(apiUrl, token, ir) {
10892
- const res = await fetch(`${apiUrl}/workflow/definitions`, {
10893
- method: "POST",
10894
- headers: {
10895
- "Content-Type": "application/json",
10896
- Authorization: `Bearer ${token}`
10897
- },
10898
- body: JSON.stringify(ir)
10899
- });
10900
- if (!res.ok) {
10901
- const errorText = await res.text();
10902
- throw new Error(`Create failed: ${res.status} ${errorText}`);
10903
- }
10904
- }
10905
- async function updateDefinition(apiUrl, token, id, ir) {
10906
- const { slug: _slug, ...updatePayload } = ir;
10907
- const res = await fetch(`${apiUrl}/workflow/definitions/${id}`, {
10908
- method: "PATCH",
10909
- headers: {
10910
- "Content-Type": "application/json",
10911
- Authorization: `Bearer ${token}`
10912
- },
10913
- body: JSON.stringify(updatePayload)
10914
- });
10915
- if (!res.ok) {
10916
- const errorText = await res.text();
10917
- throw new Error(`Update failed: ${res.status} ${errorText}`);
10918
- }
10919
- }
10920
- function bumpVersion(version) {
10921
- const parts = version.split(".");
10922
- if (parts.length !== 3) return `${version}.1`;
10923
- const patch = parseInt(parts[2], 10) || 0;
10924
- return `${parts[0]}.${parts[1]}.${patch + 1}`;
10925
- }
10926
- async function syncServices(apiUrl, token, ir) {
10927
- const metadata = ir.metadata;
10928
- const orchestration = metadata?.orchestration;
10929
- const services = orchestration?.services;
10930
- if (!services || Object.keys(services).length === 0) return null;
10931
- const result = { registered: [], updated: [], failed: [] };
10932
- for (const [name, config] of Object.entries(services)) {
10933
- try {
10934
- const registration = {
10935
- name,
10936
- connection: {
10937
- type: config.type || "webhook",
10938
- url: config.url,
10939
- queue: config.queue
10940
- },
10941
- actions: config.actions || [],
10942
- labels: config.labels || {}
10943
- };
10944
- const existing = await fetchExistingService(apiUrl, token, name);
10945
- if (existing) {
10946
- await fetch(`${apiUrl}/services/${existing.id}`, {
10947
- method: "PATCH",
10948
- headers: {
10949
- "Content-Type": "application/json",
10950
- Authorization: `Bearer ${token}`
10951
- },
10952
- body: JSON.stringify(registration)
10953
- });
10954
- console.log(` \u2713 service: ${name} (updated)`);
10955
- result.updated.push(name);
10956
- } else {
10957
- const res = await fetch(`${apiUrl}/services`, {
10958
- method: "POST",
10959
- headers: {
10960
- "Content-Type": "application/json",
10961
- Authorization: `Bearer ${token}`
10962
- },
10963
- body: JSON.stringify(registration)
10964
- });
10965
- if (!res.ok) {
10966
- const errorText = await res.text();
10967
- throw new Error(`Register failed: ${res.status} ${errorText}`);
10968
- }
10969
- console.log(` \u2713 service: ${name} (registered)`);
10970
- result.registered.push(name);
10971
- }
10972
- } catch (error) {
10973
- const msg = error.message;
10974
- console.error(` \u2717 service: ${name}: ${msg}`);
10975
- result.failed.push(name);
10976
- }
10977
- }
10978
- return result;
10979
- }
10980
- async function fetchExistingService(apiUrl, token, name) {
10981
- try {
10982
- const res = await fetch(`${apiUrl}/services?name=${encodeURIComponent(name)}`, {
10983
- headers: { Authorization: `Bearer ${token}` }
10984
- });
10985
- if (!res.ok) return null;
10986
- const data = await res.json();
10987
- const servicesList = Array.isArray(data) ? data : data.services ?? data.items ?? data.data;
10988
- if (!servicesList || servicesList.length === 0) return null;
10989
- const found = servicesList.find((s) => s.name === name);
10990
- return found ? { id: found.id, name: found.name } : null;
10991
- } catch {
10992
- return null;
10993
- }
10994
- }
10995
- var import_glob2, import_fs5, import_path4;
10996
- var init_deploy = __esm({
10997
- "src/cli/deploy.ts"() {
10998
- "use strict";
10999
- import_glob2 = require("glob");
11000
- import_fs5 = require("fs");
11001
- import_path4 = require("path");
11002
- }
11003
- });
11004
-
11005
- // src/cli/seed.ts
11006
- var seed_exports = {};
11007
- __export(seed_exports, {
11008
- generateFieldValue: () => generateFieldValue,
11009
- generateInstanceData: () => generateInstanceData,
11010
- seedInstances: () => seedInstances
11011
- });
11012
- function randomInt(min, max) {
11013
- return Math.floor(Math.random() * (max - min + 1)) + min;
11014
- }
11015
- function randomPick(arr) {
11016
- return arr[Math.floor(Math.random() * arr.length)];
11017
- }
11018
- function loremSentence(words = 5) {
11019
- const result = [];
11020
- for (let i = 0; i < words; i++) result.push(randomPick(LOREM_WORDS));
11021
- const s = result.join(" ");
11022
- return s.charAt(0).toUpperCase() + s.slice(1);
11023
- }
11024
- function generateFieldValue(field, index) {
11025
- if (field.default_value !== void 0 && field.default_value !== null) {
11026
- return field.default_value;
11027
- }
11028
- if (field.options && field.options.length > 0) {
11029
- return field.options[index % field.options.length].value;
11030
- }
11031
- const ft = (field.field_type ?? field.type ?? "text").toLowerCase();
11032
- switch (ft) {
11033
- case "text":
11034
- case "string":
11035
- case "textarea":
11036
- case "rich_text": {
11037
- const name = field.name.toLowerCase();
11038
- if (name.includes("email")) return `${randomPick(FIRST_NAMES).toLowerCase()}${++_counter}@${randomPick(DOMAINS)}`;
11039
- if (name.includes("name") && name.includes("first")) return randomPick(FIRST_NAMES);
11040
- if (name.includes("name") && name.includes("last")) return randomPick(LAST_NAMES);
11041
- if (name.includes("name") || name === "title") return `${randomPick(FIRST_NAMES)} ${randomPick(LAST_NAMES)}`;
11042
- if (name.includes("company") || name.includes("org")) return randomPick(COMPANIES);
11043
- if (name.includes("phone")) return `+1-555-${randomInt(100, 999)}-${randomInt(1e3, 9999)}`;
11044
- if (name.includes("url") || name.includes("website")) return `https://${randomPick(DOMAINS)}/${field.name}`;
11045
- if (name.includes("description") || name.includes("note") || name.includes("comment")) return loremSentence(randomInt(8, 15));
11046
- if (name.includes("address")) return `${randomInt(100, 9999)} ${loremSentence(2)} St`;
11047
- return loremSentence(randomInt(2, 5));
11048
- }
11049
- case "number":
11050
- case "numeric":
11051
- case "integer":
11052
- case "int": {
11053
- const name = field.name.toLowerCase();
11054
- if (name.includes("price") || name.includes("amount") || name.includes("cost") || name.includes("salary"))
11055
- return randomInt(1e3, 99999) / 100;
11056
- if (name.includes("age")) return randomInt(18, 65);
11057
- if (name.includes("quantity") || name.includes("count") || name.includes("qty")) return randomInt(1, 100);
11058
- if (name.includes("percent") || name.includes("rate")) return randomInt(1, 100);
11059
- return randomInt(1, 1e3);
11060
- }
11061
- case "currency":
11062
- case "decimal":
11063
- return randomInt(100, 999999) / 100;
11064
- case "boolean":
11065
- case "bool":
11066
- case "checkbox":
11067
- case "toggle":
11068
- return index % 2 === 0;
11069
- case "date":
11070
- case "datetime":
11071
- case "timestamptz": {
11072
- const d = /* @__PURE__ */ new Date();
11073
- d.setDate(d.getDate() - randomInt(0, 365));
11074
- return d.toISOString().split("T")[0];
11075
- }
11076
- case "select":
11077
- case "enum":
11078
- case "multi_select":
11079
- return field.options?.[index % (field.options?.length || 1)]?.value ?? "option_1";
11080
- case "email":
11081
- return `${randomPick(FIRST_NAMES).toLowerCase()}${++_counter}@${randomPick(DOMAINS)}`;
11082
- case "url":
11083
- return `https://${randomPick(DOMAINS)}/${field.name}`;
11084
- case "json":
11085
- case "object":
11086
- return {};
11087
- case "array":
11088
- return [];
11089
- default:
11090
- return loremSentence(3);
11091
- }
11092
- }
11093
- function generateInstanceData(fields, index) {
11094
- const data = {};
11095
- for (const field of fields) {
11096
- if (field.name === "id" || field.name === "created_at" || field.name === "updated_at") continue;
11097
- data[field.name] = generateFieldValue(field, index);
11098
- }
11099
- return data;
11100
- }
11101
- async function seedInstances(options) {
11102
- const dir = options.dir ?? "dist/workflows";
11103
- const count = options.count ?? 7;
11104
- const result = { created: 0, definitions: 0, errors: [] };
11105
- const files = await (0, import_glob3.glob)(`${dir}/**/*.workflow.json`);
11106
- if (files.length === 0) return result;
11107
- for (const file2 of files) {
11108
- let def;
11109
- try {
11110
- def = JSON.parse((0, import_fs6.readFileSync)(file2, "utf-8"));
11111
- } catch {
11112
- continue;
11113
- }
11114
- if (!def.slug || !def.fields || def.fields.length === 0) continue;
11115
- const startState = def.states?.find((s) => s.state_type === "START")?.name ?? def.states?.[0]?.name ?? "initial";
11116
- let defCreated = 0;
11117
- for (let i = 0; i < count; i++) {
11118
- const stateData = generateInstanceData(def.fields, i);
11119
- try {
11120
- const resp = await fetch(`${options.apiUrl}/workflow/instances`, {
11121
- method: "POST",
11122
- headers: {
11123
- "Content-Type": "application/json",
11124
- "Authorization": `Bearer ${options.token}`
11125
- },
11126
- body: JSON.stringify({
11127
- definition_slug: def.slug,
11128
- initial_state: startState,
11129
- state_data: stateData
11130
- })
11131
- });
11132
- if (resp.ok) {
11133
- defCreated++;
11134
- } else {
11135
- const errText = await resp.text().catch(() => resp.statusText);
11136
- result.errors.push(`${def.slug}[${i}]: ${resp.status} ${errText}`);
11137
- }
11138
- } catch (e) {
11139
- result.errors.push(`${def.slug}[${i}]: ${e instanceof Error ? e.message : String(e)}`);
11140
- }
11141
- }
11142
- if (defCreated > 0) {
11143
- result.definitions++;
11144
- result.created += defCreated;
11145
- console.log(` [seed] ${def.slug}: ${defCreated} instances created`);
11146
- }
11147
- }
11148
- return result;
11149
- }
11150
- var import_fs6, import_glob3, FIRST_NAMES, LAST_NAMES, COMPANIES, LOREM_WORDS, DOMAINS, _counter;
11151
- var init_seed = __esm({
11152
- "src/cli/seed.ts"() {
11153
- "use strict";
11154
- import_fs6 = require("fs");
11155
- import_glob3 = require("glob");
11156
- FIRST_NAMES = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank", "Grace", "Henry"];
11157
- LAST_NAMES = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis"];
11158
- COMPANIES = ["Acme Corp", "TechStart Inc", "GlobalTrade Ltd", "DataFlow Systems", "CloudPeak"];
11159
- LOREM_WORDS = ["lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit", "sed", "do", "eiusmod", "tempor"];
11160
- DOMAINS = ["example.com", "test.org", "demo.io", "sample.net"];
11161
- _counter = 0;
11162
- }
11163
- });
11164
-
11165
10619
  // src/index.ts
11166
10620
  var index_exports = {};
11167
10621
  __export(index_exports, {
@@ -11662,7 +11116,7 @@ function buildJSXTree(node, imports, symbols) {
11662
11116
  }
11663
11117
  const componentName = node.component;
11664
11118
  if (REACT_ATOMS.has(componentName)) {
11665
- addImport(imports, "@mmapp/react", componentName);
11119
+ addImport(imports, "@mindmatrix/react", componentName);
11666
11120
  }
11667
11121
  const attributes = [];
11668
11122
  if (node.config) {
@@ -11707,7 +11161,7 @@ function buildJSXTree(node, imports, symbols) {
11707
11161
  isSelfClosing
11708
11162
  );
11709
11163
  if (node.visible_when) {
11710
- addImport(imports, "@mmapp/react", "Show");
11164
+ addImport(imports, "@mindmatrix/react", "Show");
11711
11165
  return t8.jsxElement(
11712
11166
  t8.jsxOpeningElement(
11713
11167
  t8.jsxIdentifier("Show"),
@@ -11788,7 +11242,7 @@ function fieldTypeAnnotation(field) {
11788
11242
  }
11789
11243
  function emitFieldDeclarations(fields, imports) {
11790
11244
  if (fields.length === 0) return [];
11791
- addImport2(imports, "@mmapp/react", "useState");
11245
+ addImport2(imports, "@mindmatrix/react", "useState");
11792
11246
  const statements = [];
11793
11247
  for (const field of fields) {
11794
11248
  if (field.computed) continue;
@@ -11852,7 +11306,7 @@ function emitStateEffects(states, imports) {
11852
11306
  const statements = [];
11853
11307
  for (const state of states) {
11854
11308
  if (state.on_enter.length > 0) {
11855
- addImport2(imports, "@mmapp/react", "useOnEnter");
11309
+ addImport2(imports, "@mindmatrix/react", "useOnEnter");
11856
11310
  statements.push(
11857
11311
  t9.expressionStatement(
11858
11312
  t9.callExpression(t9.identifier("useOnEnter"), [
@@ -11863,7 +11317,7 @@ function emitStateEffects(states, imports) {
11863
11317
  );
11864
11318
  }
11865
11319
  if (state.on_exit.length > 0) {
11866
- addImport2(imports, "@mmapp/react", "useOnExit");
11320
+ addImport2(imports, "@mindmatrix/react", "useOnExit");
11867
11321
  statements.push(
11868
11322
  t9.expressionStatement(
11869
11323
  t9.callExpression(t9.identifier("useOnExit"), [
@@ -11874,7 +11328,7 @@ function emitStateEffects(states, imports) {
11874
11328
  );
11875
11329
  }
11876
11330
  if (state.during.length > 0) {
11877
- addImport2(imports, "@mmapp/react", "useWhileIn");
11331
+ addImport2(imports, "@mindmatrix/react", "useWhileIn");
11878
11332
  for (const during of state.during) {
11879
11333
  const args = [
11880
11334
  t9.stringLiteral(state.name)
@@ -11895,7 +11349,7 @@ function emitStateEffects(states, imports) {
11895
11349
  }
11896
11350
  function emitTransitionDeclarations(transitions, imports) {
11897
11351
  if (transitions.length === 0) return [];
11898
- addImport2(imports, "@mmapp/react", "useTransition");
11352
+ addImport2(imports, "@mindmatrix/react", "useTransition");
11899
11353
  const correctedTransitions = correctFromFields(transitions);
11900
11354
  const statements = [];
11901
11355
  for (const transition of correctedTransitions) {
@@ -12130,7 +11584,7 @@ function emitSingleCondition(cond) {
12130
11584
  function emitRoleDeclarations(metadata, imports) {
12131
11585
  const roleDeps = metadata?.roleDependencies;
12132
11586
  if (!roleDeps || roleDeps.length === 0) return [];
12133
- addImport2(imports, "@mmapp/react", "useRole");
11587
+ addImport2(imports, "@mindmatrix/react", "useRole");
12134
11588
  const statements = [];
12135
11589
  for (const role of roleDeps) {
12136
11590
  const varName = `is${toPascalCase(role)}`;
@@ -12151,7 +11605,7 @@ function emitQueryDeclarations(metadata, imports) {
12151
11605
  const modelImports = metadata?.modelImports;
12152
11606
  const addedModelImports = /* @__PURE__ */ new Set();
12153
11607
  if (dataSources && dataSources.length > 0) {
12154
- addImport2(imports, "@mmapp/react", "useQuery");
11608
+ addImport2(imports, "@mindmatrix/react", "useQuery");
12155
11609
  const usedVarNames = /* @__PURE__ */ new Set();
12156
11610
  for (const ds of dataSources) {
12157
11611
  if (ds.type !== "workflow") continue;
@@ -12218,7 +11672,7 @@ function emitQueryDeclarations(metadata, imports) {
12218
11672
  }
12219
11673
  const mutationTargets = metadata?.mutationTargets;
12220
11674
  if (mutationTargets && mutationTargets.length > 0) {
12221
- addImport2(imports, "@mmapp/react", "useMutation");
11675
+ addImport2(imports, "@mindmatrix/react", "useMutation");
12222
11676
  for (const slug of mutationTargets) {
12223
11677
  const modelPath = modelImports?.[slug];
12224
11678
  const modelVarName2 = modelPath ? `${toCamelCase2(slug.replace(/-/g, "_"))}Model` : void 0;
@@ -12243,7 +11697,7 @@ function emitQueryDeclarations(metadata, imports) {
12243
11697
  function emitChangeWatchers(metadata, imports) {
12244
11698
  const watchers = metadata?.fieldWatchers;
12245
11699
  if (!watchers || watchers.length === 0) return [];
12246
- addImport2(imports, "@mmapp/react", "useOnChange");
11700
+ addImport2(imports, "@mindmatrix/react", "useOnChange");
12247
11701
  const statements = [];
12248
11702
  for (const watcher of watchers) {
12249
11703
  statements.push(
@@ -12259,7 +11713,7 @@ function emitChangeWatchers(metadata, imports) {
12259
11713
  }
12260
11714
  function emitEventSubscriptions(onEvent, imports) {
12261
11715
  if (!onEvent || onEvent.length === 0) return [];
12262
- addImport2(imports, "@mmapp/react", "useOnEvent");
11716
+ addImport2(imports, "@mindmatrix/react", "useOnEvent");
12263
11717
  const statements = [];
12264
11718
  for (const sub of onEvent) {
12265
11719
  const actions = sub.actions.map((a, i) => ({
@@ -12286,7 +11740,7 @@ function emitEventSubscriptions(onEvent, imports) {
12286
11740
  function emitTransitionEffects(metadata, imports) {
12287
11741
  const effects = metadata?.transitionEffects;
12288
11742
  if (!effects || effects.length === 0) return [];
12289
- addImport2(imports, "@mmapp/react", "useOnTransition");
11743
+ addImport2(imports, "@mindmatrix/react", "useOnTransition");
12290
11744
  const statements = [];
12291
11745
  for (const effect of effects) {
12292
11746
  statements.push(
@@ -12317,7 +11771,7 @@ function emitLocalDefaultDeclarations(experience, existingFields, imports) {
12317
11771
  const camelName = toCamelCase2(key);
12318
11772
  if (emittedCamelNames.has(camelName)) continue;
12319
11773
  emittedCamelNames.add(camelName);
12320
- addImport2(imports, "@mmapp/react", "useState");
11774
+ addImport2(imports, "@mindmatrix/react", "useState");
12321
11775
  const setter = `set${toPascalCase(key)}`;
12322
11776
  let defaultExpr;
12323
11777
  if (value === void 0 || value === null) {
@@ -12530,7 +11984,7 @@ function generateServerActionFile(actions) {
12530
11984
  ` * Each receives a TransitionContext with instance data and utilities.`,
12531
11985
  ` */`,
12532
11986
  ``,
12533
- `import type { TransitionContext } from '@mmapp/react';`,
11987
+ `import type { TransitionContext } from '@mindmatrix/react';`,
12534
11988
  ``
12535
11989
  ];
12536
11990
  for (const action of actions) {
@@ -12603,7 +12057,7 @@ function generateConfigFile(def) {
12603
12057
  ` * Blueprint configuration for "${def.name || pascalCase(def.slug)}".`,
12604
12058
  ` */`,
12605
12059
  ``,
12606
- `import { defineBlueprint } from '@mmapp/react';`,
12060
+ `import { defineBlueprint } from '@mindmatrix/react';`,
12607
12061
  ``,
12608
12062
  `export default defineBlueprint({`,
12609
12063
  ` slug: '${def.slug}',`,
@@ -12698,7 +12152,7 @@ function generateMainFile(def, pages, hasModel, serverActionNames, options) {
12698
12152
  reactImports.add("Stack");
12699
12153
  if (reactImports.size > 0) {
12700
12154
  const sorted = [...reactImports].sort();
12701
- importLines.push(`import { ${sorted.join(", ")} } from '@mmapp/react';`);
12155
+ importLines.push(`import { ${sorted.join(", ")} } from '@mindmatrix/react';`);
12702
12156
  }
12703
12157
  if (hasModel) {
12704
12158
  const typeName = pascalCase(slug);
@@ -13895,580 +13349,27 @@ async function startWatchMode(options) {
13895
13349
  console.log(`
13896
13350
  [mindmatrix-react] Watching ${srcDir} for changes... (Ctrl+C to stop)
13897
13351
  `);
13898
- fsWatch(srcDir, { recursive: true }, (_event, filename) => {
13899
- if (!filename) return;
13900
- if (!filename.match(/\.(tsx?|jsx?)$/)) return;
13901
- if (filename.includes("node_modules") || filename.includes("dist")) return;
13902
- if (debounce) clearTimeout(debounce);
13903
- debounce = setTimeout(async () => {
13904
- const ts = (/* @__PURE__ */ new Date()).toLocaleTimeString();
13905
- console.log(`
13906
- [${ts}] Change detected: ${filename} \u2014 recompiling...`);
13907
- try {
13908
- await build({ ...options, watch: false, skipTypeCheck: true });
13909
- } catch (e) {
13910
- console.error(`[mindmatrix-react] Rebuild failed:`, e.message);
13911
- }
13912
- }, 300);
13913
- });
13914
- return new Promise(() => {
13915
- });
13916
- }
13917
-
13918
- // src/cli/local-server.ts
13919
- var http = __toESM(require("http"));
13920
- var import_node_crypto = require("crypto");
13921
- var MemoryStore = class {
13922
- constructor() {
13923
- this.definitions = /* @__PURE__ */ new Map();
13924
- this.instances = /* @__PURE__ */ new Map();
13925
- this.slugIndex = /* @__PURE__ */ new Map();
13926
- }
13927
- // slug → id
13928
- // ── Definitions ──────────────────────────────────────────────────────
13929
- createDefinition(input) {
13930
- if (this.slugIndex.has(input.slug)) {
13931
- const existing = this.definitions.get(this.slugIndex.get(input.slug));
13932
- if (existing) return existing;
13933
- }
13934
- const now = (/* @__PURE__ */ new Date()).toISOString();
13935
- const def = {
13936
- id: input.id ?? (0, import_node_crypto.randomUUID)(),
13937
- slug: input.slug,
13938
- name: input.name,
13939
- version: input.version ?? "1.0.0",
13940
- description: input.description ?? null,
13941
- category: input.category ?? "workflow",
13942
- fields: input.fields ?? [],
13943
- states: input.states ?? [],
13944
- transitions: input.transitions ?? [],
13945
- roles: input.roles ?? [],
13946
- experience: input.experience ?? null,
13947
- metadata: input.metadata ?? {},
13948
- child_definitions: input.child_definitions ?? [],
13949
- is_immutable: input.is_immutable ?? false,
13950
- tags: input.tags ?? [],
13951
- inline_tags: input.inline_tags ?? [],
13952
- created_at: now,
13953
- updated_at: now
13954
- };
13955
- this.definitions.set(def.id, def);
13956
- this.slugIndex.set(def.slug, def.id);
13957
- return def;
13958
- }
13959
- getDefinition(idOrSlug) {
13960
- const byId = this.definitions.get(idOrSlug);
13961
- if (byId) return byId;
13962
- const id = this.slugIndex.get(idOrSlug);
13963
- if (id) return this.definitions.get(id);
13964
- return void 0;
13965
- }
13966
- listDefinitions(opts) {
13967
- let items = Array.from(this.definitions.values());
13968
- if (opts?.category) {
13969
- items = items.filter((d) => d.category === opts.category);
13970
- }
13971
- const total = items.length;
13972
- const offset = opts?.offset ?? 0;
13973
- const limit = opts?.limit ?? 50;
13974
- items = items.slice(offset, offset + limit);
13975
- return { items, total };
13976
- }
13977
- patchDefinition(id, patch) {
13978
- const def = this.definitions.get(id);
13979
- if (!def) return void 0;
13980
- Object.assign(def, patch, { updated_at: (/* @__PURE__ */ new Date()).toISOString() });
13981
- return def;
13982
- }
13983
- deleteDefinition(id) {
13984
- const def = this.definitions.get(id);
13985
- if (!def) return false;
13986
- this.slugIndex.delete(def.slug);
13987
- this.definitions.delete(id);
13988
- return true;
13989
- }
13990
- // ── Instances ────────────────────────────────────────────────────────
13991
- createInstance(input) {
13992
- const def = this.getDefinition(input.definition_id) ?? this.getDefinition(input.definition_slug);
13993
- if (!def) return null;
13994
- const initialState = def.states.find((s) => s.type === "START" || s.type === "initial");
13995
- const stateName = initialState?.name ?? "initial";
13996
- const stateData = {};
13997
- for (const field of def.fields) {
13998
- if (field.default_value !== void 0) {
13999
- stateData[field.name] = field.default_value;
14000
- }
14001
- }
14002
- Object.assign(stateData, input.state_data ?? {});
14003
- const now = (/* @__PURE__ */ new Date()).toISOString();
14004
- const inst = {
14005
- id: (0, import_node_crypto.randomUUID)(),
14006
- definition_id: def.id,
14007
- definition_slug: def.slug,
14008
- current_state: stateName,
14009
- state_data: stateData,
14010
- execution_lock_version: 0,
14011
- event_log: [{
14012
- event_type: "transition",
14013
- message: `Instance created in state '${stateName}'`,
14014
- timestamp: now
14015
- }],
14016
- created_at: now,
14017
- updated_at: now
14018
- };
14019
- this.instances.set(inst.id, inst);
14020
- return inst;
14021
- }
14022
- getInstance(id) {
14023
- return this.instances.get(id);
14024
- }
14025
- listInstances(opts) {
14026
- let items = Array.from(this.instances.values());
14027
- if (opts?.definition_id) {
14028
- items = items.filter((i) => i.definition_id === opts.definition_id);
14029
- }
14030
- const total = items.length;
14031
- const offset = opts?.offset ?? 0;
14032
- const limit = opts?.limit ?? 50;
14033
- items = items.slice(offset, offset + limit);
14034
- return { items, total };
14035
- }
14036
- // ── Execute Action (Transition) ──────────────────────────────────────
14037
- executeAction(input) {
14038
- const def = this.getDefinition(input.definition_id);
14039
- if (!def) return { success: false, error: "Definition not found" };
14040
- let inst;
14041
- if (input.instance_id) {
14042
- const existing = this.instances.get(input.instance_id);
14043
- if (!existing) return { success: false, error: "Instance not found" };
14044
- inst = existing;
14045
- } else {
14046
- const created = this.createInstance({
14047
- definition_id: def.id,
14048
- definition_slug: def.slug,
14049
- state_data: input.payload
14050
- });
14051
- if (!created) return { success: false, error: "Failed to create instance" };
14052
- inst = created;
14053
- }
14054
- if (input.payload && input.instance_id) {
14055
- Object.assign(inst.state_data, input.payload);
14056
- }
14057
- const transition = def.transitions.find((t27) => t27.name === input.action_name && t27.from.includes(inst.current_state));
14058
- if (!transition) {
14059
- return {
14060
- success: false,
14061
- instance_id: inst.id,
14062
- from_state: inst.current_state,
14063
- to_state: null,
14064
- state_data: inst.state_data,
14065
- error: `No transition '${input.action_name}' from state '${inst.current_state}'`
14066
- };
14067
- }
14068
- const fromState = inst.current_state;
14069
- const now = (/* @__PURE__ */ new Date()).toISOString();
14070
- const events = [];
14071
- let lastEvalResult = null;
14072
- events.push({ event_type: "transition", message: `Transition '${transition.name}' started: ${fromState} \u2192 ${transition.to}`, timestamp: now });
14073
- for (const action of transition.actions ?? []) {
14074
- try {
14075
- if (action.type === "set_field") {
14076
- const field = action.config?.field;
14077
- if (action.config?.expression) {
14078
- const expr = action.config.expression;
14079
- const result = this.evaluateSimpleExpression(expr, inst.state_data);
14080
- inst.state_data[field] = result;
14081
- } else if (action.config?.value !== void 0) {
14082
- inst.state_data[field] = action.config.value;
14083
- }
14084
- events.push({ event_type: "action_executed", message: `transition action 'set_field' succeeded`, timestamp: now });
14085
- } else if (action.type === "eval") {
14086
- const expr = action.config?.expression;
14087
- lastEvalResult = this.evaluateSimpleExpression(expr, inst.state_data);
14088
- events.push({ event_type: "action_executed", message: `transition action 'eval' succeeded`, timestamp: now });
14089
- } else {
14090
- events.push({ event_type: "action_executed", message: `transition action '${action.type}' succeeded (no-op in local mode)`, timestamp: now });
14091
- }
14092
- } catch (err) {
14093
- const msg = err instanceof Error ? err.message : String(err);
14094
- events.push({ event_type: "action_failed", message: `transition action '${action.type}' failed: ${msg}`, timestamp: now });
14095
- return {
14096
- success: false,
14097
- instance_id: inst.id,
14098
- from_state: fromState,
14099
- to_state: null,
14100
- state_data: inst.state_data,
14101
- event_log: events,
14102
- error: `transition action failed: ${msg}`
14103
- };
14104
- }
14105
- }
14106
- inst.current_state = transition.to;
14107
- inst.execution_lock_version++;
14108
- inst.updated_at = now;
14109
- events.push({ event_type: "transition", message: `State changed: ${fromState} \u2192 ${transition.to}`, timestamp: now });
14110
- inst.event_log.push(...events);
14111
- return {
14112
- success: true,
14113
- instance_id: inst.id,
14114
- from_state: fromState,
14115
- to_state: transition.to,
14116
- state_data: inst.state_data,
14117
- result: lastEvalResult,
14118
- event_log: events
14119
- };
14120
- }
14121
- /**
14122
- * Minimal expression evaluator for local dev mode.
14123
- * Handles: field references, arithmetic, string literals, simple comparisons.
14124
- * Does NOT handle: while loops, if/else, function calls, multi-statement blocks.
14125
- * For full evaluation, use mm-napi when available.
14126
- */
14127
- evaluateSimpleExpression(expr, context) {
14128
- if (context[expr] !== void 0) return context[expr];
14129
- const arithMatch = expr.match(/^(\w+)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/);
14130
- if (arithMatch) {
14131
- const [, field, op, numStr] = arithMatch;
14132
- const left = Number(context[field] ?? 0);
14133
- const right = Number(numStr);
14134
- switch (op) {
14135
- case "+":
14136
- return left + right;
14137
- case "-":
14138
- return left - right;
14139
- case "*":
14140
- return left * right;
14141
- case "/":
14142
- return right !== 0 ? left / right : 0;
14143
- }
14144
- }
14145
- if (/^\d+(\.\d+)?$/.test(expr.trim())) {
14146
- return Number(expr.trim());
14147
- }
14148
- const strMatch = expr.match(/^["'](.*)["']$/);
14149
- if (strMatch) return strMatch[1];
14150
- try {
14151
- const keys = Object.keys(context);
14152
- const values = Object.values(context);
14153
- const fn = new Function(...keys, `"use strict"; return (${expr});`);
14154
- return fn(...values);
14155
- } catch {
14156
- return null;
14157
- }
14158
- }
14159
- };
14160
- async function startLocalServer(options = {}) {
14161
- const { port = 4200, noAuth = true } = options;
14162
- const store = new MemoryStore();
14163
- const startedAt = (/* @__PURE__ */ new Date()).toISOString();
14164
- function json(res, status, body) {
14165
- const data = JSON.stringify(body);
14166
- res.writeHead(status, {
14167
- "Content-Type": "application/json",
14168
- "Access-Control-Allow-Origin": "*",
14169
- "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
14170
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
14171
- "Content-Length": Buffer.byteLength(data)
14172
- });
14173
- res.end(data);
14174
- }
14175
- function readBody(req) {
14176
- return new Promise((resolve3, reject) => {
14177
- const chunks = [];
14178
- req.on("data", (chunk) => chunks.push(chunk));
14179
- req.on("end", () => resolve3(Buffer.concat(chunks).toString()));
14180
- req.on("error", reject);
14181
- });
14182
- }
14183
- function parseQuery(url) {
14184
- const idx = url.indexOf("?");
14185
- if (idx === -1) return {};
14186
- const params = {};
14187
- const qs = url.slice(idx + 1);
14188
- for (const pair of qs.split("&")) {
14189
- const [k, v] = pair.split("=");
14190
- if (k) params[decodeURIComponent(k)] = decodeURIComponent(v ?? "");
14191
- }
14192
- return params;
14193
- }
14194
- const server = http.createServer(async (req, res) => {
14195
- const method = req.method?.toUpperCase() ?? "GET";
14196
- const rawUrl = req.url ?? "/";
14197
- const queryStart = rawUrl.indexOf("?");
14198
- const path = queryStart >= 0 ? rawUrl.slice(0, queryStart) : rawUrl;
14199
- const query = parseQuery(rawUrl);
14200
- if (method === "OPTIONS") {
14201
- res.writeHead(204, {
14202
- "Access-Control-Allow-Origin": "*",
14203
- "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
14204
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
14205
- "Access-Control-Max-Age": "86400"
14206
- });
14207
- res.end();
14208
- return;
14209
- }
14210
- try {
14211
- if (path === "/health" && method === "GET") {
14212
- return json(res, 200, {
14213
- status: "ok",
14214
- service: "mm-local-dev",
14215
- mode: "in-memory",
14216
- started_at: startedAt,
14217
- definitions: store.definitions.size,
14218
- instances: store.instances.size
14219
- });
14220
- }
14221
- if (path === "/api/v1/auth/login" && (method === "POST" || method === "GET")) {
14222
- return json(res, 200, {
14223
- token: "dev-token-local",
14224
- user: {
14225
- id: "dev-user-001",
14226
- email: "dev@localhost",
14227
- role: "admin",
14228
- name: "Local Developer"
14229
- }
14230
- });
14231
- }
14232
- if (path === "/api/v1/workflow/definitions" && method === "GET") {
14233
- const result = store.listDefinitions({
14234
- category: query.category,
14235
- limit: query.limit ? parseInt(query.limit, 10) : void 0,
14236
- offset: query.offset ? parseInt(query.offset, 10) : void 0
14237
- });
14238
- if (query.slug) {
14239
- const def = store.getDefinition(query.slug);
14240
- return json(res, 200, { items: def ? [def] : [], total: def ? 1 : 0 });
14241
- }
14242
- return json(res, 200, result);
14243
- }
14244
- const defMatch = path.match(/^\/api\/v1\/workflow\/definitions\/([^/]+)$/);
14245
- if (defMatch && method === "GET") {
14246
- const def = store.getDefinition(defMatch[1]);
14247
- if (!def) return json(res, 404, { error: "Not found" });
14248
- return json(res, 200, def);
14249
- }
14250
- if (path === "/api/v1/workflow/definitions" && method === "POST") {
14251
- const body = JSON.parse(await readBody(req));
14252
- const def = store.createDefinition(body);
14253
- return json(res, 201, def);
14254
- }
14255
- if (defMatch && method === "PATCH") {
14256
- const body = JSON.parse(await readBody(req));
14257
- const updated = store.patchDefinition(defMatch[1], body);
14258
- if (!updated) return json(res, 404, { error: "Not found" });
14259
- return json(res, 200, updated);
14260
- }
14261
- if (defMatch && method === "DELETE") {
14262
- const deleted = store.deleteDefinition(defMatch[1]);
14263
- if (!deleted) return json(res, 404, { error: "Not found" });
14264
- return json(res, 204, null);
14265
- }
14266
- if (path === "/api/v1/workflow/instances" && method === "GET") {
14267
- const result = store.listInstances({
14268
- definition_id: query.definition_id,
14269
- limit: query.limit ? parseInt(query.limit, 10) : void 0,
14270
- offset: query.offset ? parseInt(query.offset, 10) : void 0
14271
- });
14272
- return json(res, 200, result);
14273
- }
14274
- if (path === "/api/v1/workflow/instances" && method === "POST") {
14275
- const body = JSON.parse(await readBody(req));
14276
- const inst = store.createInstance(body);
14277
- if (!inst) return json(res, 404, { error: "Definition not found" });
14278
- return json(res, 201, inst);
14279
- }
14280
- const instMatch = path.match(/^\/api\/v1\/workflow\/instances\/([^/]+)$/);
14281
- if (instMatch && method === "GET") {
14282
- const inst = store.getInstance(instMatch[1]);
14283
- if (!inst) return json(res, 404, { error: "Not found" });
14284
- return json(res, 200, inst);
14285
- }
14286
- if (path === "/api/v1/workflow/execute-action" && method === "POST") {
14287
- const body = JSON.parse(await readBody(req));
14288
- const result = store.executeAction(body);
14289
- return json(res, 200, result);
14290
- }
14291
- const dataMatch = path.match(/^\/api\/v1\/data\/([^/]+)$/);
14292
- if (dataMatch && method === "GET") {
14293
- const def = store.getDefinition(dataMatch[1]);
14294
- if (!def) return json(res, 404, { error: "Not found" });
14295
- const instances = store.listInstances({ definition_id: def.id });
14296
- return json(res, 200, instances);
14297
- }
14298
- if (path.startsWith("/api/v1/")) {
14299
- return json(res, 501, { error: "Not implemented in local dev mode", path, method });
14300
- }
14301
- return json(res, 404, { error: "Not found", path });
14302
- } catch (err) {
14303
- const message = err instanceof Error ? err.message : String(err);
14304
- console.error(`[mm-local] ${method} ${path} \u2014 Error: ${message}`);
14305
- return json(res, 500, { error: message });
14306
- }
14307
- });
14308
- return new Promise((resolve3, reject) => {
14309
- server.on("error", (err) => {
14310
- if (err.code === "EADDRINUSE") {
14311
- reject(new Error(`Port ${port} is already in use. Is another server running?`));
14312
- } else {
14313
- reject(err);
14314
- }
14315
- });
14316
- server.listen(port, () => {
14317
- console.log(`[mm-local] Local API server running at http://localhost:${port}`);
14318
- console.log(`[mm-local] Mode: in-memory (data lost on restart)`);
14319
- console.log(`[mm-local] Auth: disabled (all requests accepted)`);
14320
- resolve3({
14321
- server,
14322
- port,
14323
- store,
14324
- async close() {
14325
- return new Promise((res) => {
14326
- server.close(() => {
14327
- console.log("[mm-local] Local API server stopped");
14328
- res();
14329
- });
14330
- });
14331
- }
14332
- });
14333
- });
14334
- });
14335
- }
14336
-
14337
- // src/dev-server.ts
14338
- var currentErrors = null;
14339
- function escapeHtml(s) {
14340
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
14341
- }
14342
- function renderErrorOverlay(errors) {
14343
- const cards = errors.map((err) => {
14344
- const loc = err.line ? `${err.file}:${err.line}${err.column ? ":" + err.column : ""}` : err.file;
14345
- 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>` : "";
14346
- return `<div style="background:#2d1b1b;border:1px solid #5c2020;border-radius:8px;padding:16px 20px;margin-bottom:12px">
14347
- <div style="color:#ff6b6b;font-family:monospace;font-size:13px;margin-bottom:6px">${escapeHtml(loc)}</div>
14348
- <div style="color:#ffa0a0;font-size:15px;font-weight:500">${escapeHtml(err.message)}</div>${snippet}</div>`;
14349
- }).join("\n");
14350
- return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
14351
- <title>Compile Error - MindMatrix Dev</title>
14352
- <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>
14353
- <body><div style="max-width:800px;margin:0 auto">
14354
- <div style="display:flex;align-items:center;gap:12px;margin-bottom:24px">
14355
- <div style="background:#5c2020;color:#ff6b6b;font-size:14px;font-weight:600;padding:4px 10px;border-radius:4px">COMPILE ERROR</div>
14356
- <div style="color:#888;font-size:13px">${errors.length} error${errors.length !== 1 ? "s" : ""}</div></div>
14357
- ${cards}
14358
- <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>
14359
- <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>
14360
- </body></html>`;
14361
- }
14362
- function errorOverlayMiddleware() {
14363
- return (req, res, next) => {
14364
- if (!currentErrors || !req.url) return next();
14365
- const url = req.url;
14366
- if (url.startsWith("/api") || url.startsWith("/health") || url.startsWith("/ws") || url.startsWith("/__mm_dev") || url.startsWith("/@") || url.startsWith("/node_modules")) return next();
14367
- const accept = req.headers?.accept ?? "";
14368
- if (!accept.includes("text/html")) return next();
14369
- res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
14370
- res.end(renderErrorOverlay(currentErrors));
14371
- };
14372
- }
14373
- async function resolveDevToken(apiUrl, explicit) {
14374
- if (explicit) return explicit;
14375
- try {
14376
- const { resolveToken: resolveToken2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
14377
- const s = resolveToken2(apiUrl);
14378
- if (s) return s;
14379
- } catch {
14380
- }
14381
- try {
14382
- const resp = await fetch(`${apiUrl}/auth/login`, {
14383
- method: "POST",
14384
- headers: { "Content-Type": "application/json" },
14385
- body: JSON.stringify({ email: "admin@mindmatrix.com", password: "Admin123!" })
14386
- });
14387
- if (resp.ok) {
14388
- const data = await resp.json();
14389
- const token = data.token ?? data.access_token;
14390
- if (token) {
14391
- try {
14392
- const { saveCredentials: saveCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
14393
- saveCredentials2(apiUrl, token);
14394
- } catch {
14395
- }
14396
- return token;
14397
- }
14398
- }
14399
- } catch {
14400
- }
14401
- return process.env.MINDMATRIX_TOKEN;
14402
- }
14403
- async function checkBackendHealth(apiUrl) {
14404
- try {
14405
- const base = apiUrl.replace(/\/api\/v1\/?$/, "");
14406
- const resp = await fetch(`${base}/health`, { signal: AbortSignal.timeout(5e3) });
14407
- if (resp.ok) {
14408
- const d = await resp.json();
14409
- return { ok: true, version: d.version, db: d.database };
14410
- }
14411
- return { ok: resp.status < 500 };
14412
- } catch {
14413
- return { ok: false };
14414
- }
14415
- }
14416
- async function initialBuildDeploy(src, outDir, mode, apiUrl, token) {
14417
- console.log("[mm-dev] Compiling project...");
14418
- const buildResult = await build({ src, outDir, mode, skipTypeCheck: true });
14419
- if (buildResult.errors > 0) {
14420
- currentErrors = buildResult.errorDetails.map((e) => ({ file: e.file, message: e.message, line: e.line }));
14421
- console.error(`[mm-dev] Build failed with ${buildResult.errors} error(s) -- error overlay active`);
14422
- return { buildResult, deployed: false, slug: void 0 };
14423
- }
14424
- currentErrors = null;
14425
- if (buildResult.compiled === 0) return { buildResult, deployed: false, slug: void 0 };
14426
- console.log(`[mm-dev] Compiled ${buildResult.compiled} definition(s)`);
14427
- try {
14428
- const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
14429
- const result = await deploy2({ apiUrl, token, dir: outDir });
14430
- const total = result.created.length + result.updated.length + result.versioned.length;
14431
- if (total > 0) console.log(`[mm-dev] Deployed: ${result.created.length} created, ${result.updated.length} updated`);
14432
- return { buildResult, deployed: true, slug: buildResult.definitions?.[0]?.slug };
14433
- } catch (e) {
14434
- console.warn(`[mm-dev] Deploy failed: ${e instanceof Error ? e.message : e}`);
14435
- return { buildResult, deployed: false, slug: void 0 };
14436
- }
14437
- }
14438
- function printBanner(o) {
14439
- const l = "-".repeat(58);
14440
- console.log(`
14441
- ${l}
14442
- MindMatrix Dev Server
14443
- ${l}
14444
- `);
14445
- console.log(` Preview: http://localhost:${o.port}`);
14446
- console.log(` API Proxy: /api/* -> ${o.apiUrl}`);
14447
- console.log(` WebSocket: ws://localhost:${o.port}/__mm_dev`);
14448
- console.log(` Watching: ${o.src} (${o.include.join(", ")})
14449
- `);
14450
- console.log(` Backend: ${o.health.ok ? "connected" : "unreachable"}${o.health.version ? ` (v${o.health.version})` : ""}`);
14451
- if (o.health.db) console.log(` Database: ${o.health.db}`);
14452
- console.log(` Auth: ${o.token ? "authenticated" : "no token"}`);
14453
- if (o.compiled > 0) {
14454
- console.log(` Blueprint: ${o.slug ?? "unknown"} (${o.compiled} defs)`);
14455
- console.log(` Deploy: ${o.deployed ? "synced" : "pending"}`);
14456
- }
14457
- if (o.errors > 0) console.log(` Errors: ${o.errors} compile error(s) -- overlay active`);
14458
- console.log(`
14459
- ${l}
14460
- `);
14461
- }
14462
- function broadcast(clients, data) {
14463
- const msg = JSON.stringify(data);
14464
- for (const c of clients) {
14465
- try {
14466
- if (c.readyState === 1) c.send(msg);
14467
- } catch {
14468
- clients.delete(c);
14469
- }
14470
- }
13352
+ fsWatch(srcDir, { recursive: true }, (_event, filename) => {
13353
+ if (!filename) return;
13354
+ if (!filename.match(/\.(tsx?|jsx?)$/)) return;
13355
+ if (filename.includes("node_modules") || filename.includes("dist")) return;
13356
+ if (debounce) clearTimeout(debounce);
13357
+ debounce = setTimeout(async () => {
13358
+ const ts = (/* @__PURE__ */ new Date()).toLocaleTimeString();
13359
+ console.log(`
13360
+ [${ts}] Change detected: ${filename} \u2014 recompiling...`);
13361
+ try {
13362
+ await build({ ...options, watch: false, skipTypeCheck: true });
13363
+ } catch (e) {
13364
+ console.error(`[mindmatrix-react] Rebuild failed:`, e.message);
13365
+ }
13366
+ }, 300);
13367
+ });
13368
+ return new Promise(() => {
13369
+ });
14471
13370
  }
13371
+
13372
+ // src/dev-server.ts
14472
13373
  async function createDevServer(options = {}) {
14473
13374
  const {
14474
13375
  port = 5199,
@@ -14477,87 +13378,44 @@ async function createDevServer(options = {}) {
14477
13378
  include = ["**/*.workflow.tsx"],
14478
13379
  outDir = "dist/workflows",
14479
13380
  seed = false,
14480
- apiUrl: rawApiUrl = "auto",
14481
- authToken: explicitToken,
13381
+ apiUrl = "http://localhost:4200/api/v1",
13382
+ authToken = process.env.MINDMATRIX_TOKEN,
14482
13383
  ws: enableWs = true,
14483
13384
  open = false
14484
13385
  } = options;
14485
13386
  const clients = /* @__PURE__ */ new Set();
14486
- let localServer = null;
14487
- let apiUrl;
14488
- let isLocalMode = false;
14489
- if (rawApiUrl === "local") {
14490
- localServer = await startLocalServer({ port: 4200 });
14491
- apiUrl = "http://localhost:4200/api/v1";
14492
- isLocalMode = true;
14493
- } else if (rawApiUrl === "auto") {
14494
- const defaultRemote = "https://dev.mindmatrix.club/api/v1";
14495
- const remoteHealth = await checkBackendHealth(defaultRemote);
14496
- if (remoteHealth.ok) {
14497
- apiUrl = defaultRemote;
14498
- } else {
14499
- const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
14500
- if (localHealth.ok) {
14501
- apiUrl = "http://localhost:4200/api/v1";
14502
- } else {
14503
- console.log("[mm-dev] No backend detected \u2014 starting local in-memory API server...");
14504
- localServer = await startLocalServer({ port: 4200 });
14505
- apiUrl = "http://localhost:4200/api/v1";
14506
- isLocalMode = true;
14507
- }
14508
- }
14509
- } else {
14510
- apiUrl = rawApiUrl;
14511
- }
14512
- const token = isLocalMode ? "dev-token-local" : await resolveDevToken(apiUrl, explicitToken);
14513
- const health = isLocalMode ? { ok: true, version: "local", db: "in-memory" } : await checkBackendHealth(apiUrl);
14514
- let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
14515
- if (token && health.ok) {
14516
- const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
14517
- initialCompiled = r.buildResult.compiled;
14518
- initialDeployed = r.deployed;
14519
- initialSlug = r.slug;
14520
- initialErrors = r.buildResult.errors;
14521
- }
14522
- if (seed && token && initialDeployed) {
14523
- try {
14524
- const { seedInstances: seedInstances2 } = await Promise.resolve().then(() => (init_seed(), seed_exports));
14525
- console.log("[mm-dev] Seeding sample instances...");
14526
- const sr = await seedInstances2({ apiUrl, token, dir: outDir });
14527
- console.log(`[mm-dev] Seeded ${sr.created} instance(s) across ${sr.definitions} definition(s)`);
14528
- } catch (e) {
14529
- console.warn(`[mm-dev] Seed failed: ${e instanceof Error ? e.message : e}`);
14530
- }
14531
- }
14532
- const pluginOpts = { mode, include, outDir, seedOnCompile: seed, apiUrl, authToken: token };
14533
- const proxyTarget = apiUrl.replace(/\/api\/v1\/?$/, "") || apiUrl;
14534
- let deployInFlight = false;
14535
- const compileDeployPlugin = {
14536
- name: "mindmatrix-dev-compile-deploy",
13387
+ const pluginOptions = {
13388
+ mode,
13389
+ include,
13390
+ outDir,
13391
+ seedOnCompile: seed,
13392
+ apiUrl,
13393
+ authToken
13394
+ };
13395
+ const notifyPlugin = {
13396
+ name: "mindmatrix-dev-notify",
14537
13397
  enforce: "post",
14538
- async handleHotUpdate(ctx) {
14539
- const isWf = include.some((p) => new RegExp(p.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "<<G>>").replace(/\*/g, "[^/]*").replace(/<<G>>/g, ".*").replace(/\?/g, ".")).test(ctx.file));
14540
- if (!isWf) return;
14541
- const fn = ctx.file.split("/").pop() ?? ctx.file;
14542
- console.log(`[mm-dev] Recompiling ${fn}...`);
14543
- const br = await build({ src, outDir, mode, skipTypeCheck: true });
14544
- if (br.errors > 0) {
14545
- currentErrors = br.errorDetails.map((e) => ({ file: e.file, message: e.message, line: e.line }));
14546
- broadcast(clients, { type: "workflow:error", errors: br.errors, timestamp: ctx.timestamp });
14547
- return;
14548
- }
14549
- currentErrors = null;
14550
- if (token && !deployInFlight) {
14551
- deployInFlight = true;
13398
+ handleHotUpdate(ctx) {
13399
+ const isWorkflow = include.some((pattern) => {
13400
+ const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "<<GLOBSTAR>>").replace(/\*/g, "[^/]*").replace(/<<GLOBSTAR>>/g, ".*").replace(/\?/g, ".");
13401
+ return new RegExp(regex).test(ctx.file);
13402
+ });
13403
+ if (!isWorkflow) return;
13404
+ const message = JSON.stringify({
13405
+ type: "workflow:compiled",
13406
+ file: ctx.file,
13407
+ timestamp: ctx.timestamp
13408
+ });
13409
+ for (const client of clients) {
14552
13410
  try {
14553
- const { deploy: d } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
14554
- await d({ apiUrl, token, dir: outDir });
13411
+ if (client.readyState === 1) {
13412
+ client.send(message);
13413
+ }
14555
13414
  } catch {
14556
- } finally {
14557
- deployInFlight = false;
13415
+ clients.delete(client);
14558
13416
  }
14559
13417
  }
14560
- broadcast(clients, { type: "workflow:compiled", file: ctx.file, compiled: br.compiled, timestamp: ctx.timestamp });
13418
+ console.log(`[mm-dev] Compiled ${ctx.file.split("/").pop()} \u2014 notified ${clients.size} client(s)`);
14561
13419
  }
14562
13420
  };
14563
13421
  const viteConfig = {
@@ -14565,93 +13423,311 @@ async function createDevServer(options = {}) {
14565
13423
  server: {
14566
13424
  port,
14567
13425
  open,
14568
- host: true,
14569
- proxy: {
14570
- "/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
14571
- "/health": { target: proxyTarget, changeOrigin: true, secure: true },
14572
- "/ws": { target: proxyTarget.replace(/^http/, "ws"), changeOrigin: true, ws: true }
14573
- }
13426
+ host: true
14574
13427
  },
14575
13428
  plugins: [
14576
- mindmatrixReact(pluginOpts),
14577
- compileDeployPlugin,
14578
- { name: "mindmatrix-error-overlay", configureServer(server) {
14579
- server.middlewares.use(errorOverlayMiddleware());
14580
- } }
13429
+ mindmatrixReact(pluginOptions),
13430
+ notifyPlugin
14581
13431
  ],
14582
- logLevel: "warn"
13432
+ logLevel: "info"
14583
13433
  };
14584
- const { createServer: createServer2 } = await import("vite");
14585
- const vite = await createServer2(viteConfig);
13434
+ const { createServer } = await import("vite");
13435
+ const vite = await createServer(viteConfig);
14586
13436
  await vite.listen();
14587
13437
  const resolvedPort = vite.config.server.port ?? port;
14588
13438
  if (enableWs && vite.httpServer) {
14589
13439
  try {
14590
- const wsM = await Function('return import("ws")')();
14591
- const WSS = wsM.WebSocketServer ?? wsM.default?.WebSocketServer;
14592
- if (WSS) {
14593
- const wss = new WSS({ server: vite.httpServer, path: "/__mm_dev" });
14594
- wss.on("connection", (s) => {
14595
- clients.add(s);
14596
- s.on("close", () => clients.delete(s));
14597
- s.send(JSON.stringify({ type: "mm:connected", version: "0.1.0", capabilities: ["compile", "deploy", "proxy", "notify", "error-overlay"] }));
13440
+ const wsModule = await Function('return import("ws")')();
13441
+ const WebSocketServer = wsModule.WebSocketServer ?? wsModule.default?.WebSocketServer;
13442
+ if (WebSocketServer) {
13443
+ const wss = new WebSocketServer({
13444
+ server: vite.httpServer,
13445
+ path: "/__mm_dev"
13446
+ });
13447
+ wss.on("connection", (socket) => {
13448
+ clients.add(socket);
13449
+ console.log(`[mm-dev] Editor connected (${clients.size} total)`);
13450
+ socket.on("close", () => {
13451
+ clients.delete(socket);
13452
+ console.log(`[mm-dev] Editor disconnected (${clients.size} total)`);
13453
+ });
13454
+ socket.send(JSON.stringify({
13455
+ type: "mm:connected",
13456
+ version: "0.1.0",
13457
+ capabilities: ["compile", "seed", "notify"]
13458
+ }));
14598
13459
  });
14599
13460
  }
14600
13461
  } catch {
13462
+ console.warn("[mm-dev] ws package not available \u2014 WebSocket notifications disabled");
14601
13463
  }
14602
13464
  }
14603
- printBanner({ port: resolvedPort, apiUrl: isLocalMode ? `${apiUrl} (local in-memory)` : apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
13465
+ console.log(`
13466
+ [mm-dev] MindMatrix Dev Server running`);
13467
+ console.log(` Local: http://localhost:${resolvedPort}`);
13468
+ console.log(` WebSocket: ws://localhost:${resolvedPort}/__mm_dev`);
13469
+ console.log(` Watching: ${src} (${include.join(", ")})`);
13470
+ if (seed) {
13471
+ console.log(` Seeding: ${apiUrl}`);
13472
+ }
13473
+ console.log();
14604
13474
  return {
14605
13475
  vite,
14606
13476
  port: resolvedPort,
14607
13477
  clients,
14608
13478
  async rebuild() {
14609
- const r = await build({ src, outDir, mode });
14610
- if (r.errors > 0) {
14611
- currentErrors = r.errorDetails.map((e) => ({ file: e.file, message: e.message, line: e.line }));
14612
- } else {
14613
- currentErrors = null;
14614
- if (token) {
14615
- try {
14616
- const { deploy: d } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
14617
- await d({ apiUrl, token, dir: outDir });
14618
- } catch {
14619
- }
13479
+ console.log("[mm-dev] Full rebuild triggered...");
13480
+ const result = await build({ src, outDir, mode });
13481
+ const message = JSON.stringify({
13482
+ type: "workflow:rebuild",
13483
+ compiled: result.compiled,
13484
+ errors: result.errors,
13485
+ timestamp: Date.now()
13486
+ });
13487
+ for (const client of clients) {
13488
+ try {
13489
+ if (client.readyState === 1) client.send(message);
13490
+ } catch {
13491
+ clients.delete(client);
14620
13492
  }
14621
13493
  }
14622
- broadcast(clients, { type: "workflow:rebuild", compiled: r.compiled, errors: r.errors, timestamp: Date.now() });
14623
- return r;
13494
+ return result;
14624
13495
  },
14625
13496
  async close() {
14626
- for (const c of clients) {
13497
+ for (const client of clients) {
14627
13498
  try {
14628
- c.close();
13499
+ client.close();
14629
13500
  } catch {
14630
13501
  }
14631
13502
  }
14632
13503
  clients.clear();
14633
- currentErrors = null;
14634
13504
  await vite.close();
14635
- if (localServer) {
14636
- await localServer.close();
14637
- }
13505
+ console.log("[mm-dev] Server stopped");
14638
13506
  }
14639
13507
  };
14640
13508
  }
14641
13509
 
14642
- // src/index.ts
14643
- init_deploy();
13510
+ // src/cli/deploy.ts
13511
+ var import_glob2 = require("glob");
13512
+ var import_fs4 = require("fs");
13513
+ var import_path3 = require("path");
13514
+ async function deploy(options) {
13515
+ const dir = options.dir ?? "dist/workflows";
13516
+ const targetLabel = options.targetName ? ` (target: ${options.targetName})` : "";
13517
+ console.log(`[mindmatrix-react] Deploying workflows from ${dir} to ${options.apiUrl}${targetLabel}...`);
13518
+ const files = await (0, import_glob2.glob)(`${dir}/**/*.workflow.json`);
13519
+ if (files.length === 0) {
13520
+ console.log(`[mindmatrix-react] No workflow files found in ${dir}`);
13521
+ return { created: [], updated: [], versioned: [], skipped: [], failed: [] };
13522
+ }
13523
+ const result = {
13524
+ created: [],
13525
+ updated: [],
13526
+ versioned: [],
13527
+ skipped: [],
13528
+ failed: []
13529
+ };
13530
+ const deployedIRs = [];
13531
+ for (const file2 of files) {
13532
+ try {
13533
+ const ir = JSON.parse((0, import_fs4.readFileSync)(file2, "utf-8"));
13534
+ const slug = ir.slug;
13535
+ if (options.dryRun) {
13536
+ console.log(` [dry-run] Would deploy ${slug} (${(0, import_path3.basename)(file2)})`);
13537
+ continue;
13538
+ }
13539
+ const existing = await fetchExistingDefinition(options.apiUrl, options.token, slug);
13540
+ if (!existing) {
13541
+ await createDefinition(options.apiUrl, options.token, ir);
13542
+ console.log(` \u2713 ${slug} (created)`);
13543
+ result.created.push(slug);
13544
+ } else if (existing.instanceCount === 0 || options.force) {
13545
+ await updateDefinition(options.apiUrl, options.token, existing.id, ir);
13546
+ console.log(` \u2713 ${slug} (updated)`);
13547
+ result.updated.push(slug);
13548
+ } else {
13549
+ const newVersion = bumpVersion(existing.version);
13550
+ ir.version = newVersion;
13551
+ await createDefinition(options.apiUrl, options.token, ir);
13552
+ console.log(` \u2713 ${slug} v${newVersion} (new version, ${existing.instanceCount} instances on v${existing.version})`);
13553
+ result.versioned.push(slug);
13554
+ }
13555
+ deployedIRs.push(ir);
13556
+ } catch (error) {
13557
+ const slug = (0, import_path3.basename)(file2).replace(".workflow.json", "");
13558
+ const msg = error.message;
13559
+ console.error(` \u2717 ${slug}: ${msg}`);
13560
+ result.failed.push({ slug, error: msg });
13561
+ }
13562
+ }
13563
+ if (!options.dryRun) {
13564
+ for (const ir of deployedIRs) {
13565
+ const serviceResult = await syncServices(options.apiUrl, options.token, ir);
13566
+ if (serviceResult) {
13567
+ if (!result.services) {
13568
+ result.services = { registered: [], updated: [], failed: [] };
13569
+ }
13570
+ result.services.registered.push(...serviceResult.registered);
13571
+ result.services.updated.push(...serviceResult.updated);
13572
+ result.services.failed.push(...serviceResult.failed);
13573
+ }
13574
+ }
13575
+ }
13576
+ if (options.reportFile) {
13577
+ (0, import_fs4.writeFileSync)(options.reportFile, JSON.stringify(result, null, 2), "utf-8");
13578
+ console.log(`
13579
+ Report written to ${options.reportFile}`);
13580
+ }
13581
+ const total = result.created.length + result.updated.length + result.versioned.length;
13582
+ console.log(
13583
+ `
13584
+ [mindmatrix-react] Deployed ${total} workflows (${result.created.length} created, ${result.updated.length} updated, ${result.versioned.length} versioned, ${result.failed.length} failed)`
13585
+ );
13586
+ if (result.services) {
13587
+ const svcTotal = result.services.registered.length + result.services.updated.length;
13588
+ if (svcTotal > 0 || result.services.failed.length > 0) {
13589
+ console.log(
13590
+ `[mindmatrix-react] Synced ${svcTotal} services (${result.services.registered.length} registered, ${result.services.updated.length} updated, ${result.services.failed.length} failed)`
13591
+ );
13592
+ }
13593
+ }
13594
+ return result;
13595
+ }
13596
+ async function fetchExistingDefinition(apiUrl, token, slug) {
13597
+ try {
13598
+ const res = await fetch(`${apiUrl}/workflow/definitions?slug=${encodeURIComponent(slug)}`, {
13599
+ headers: { Authorization: `Bearer ${token}` }
13600
+ });
13601
+ if (!res.ok) return null;
13602
+ const data = await res.json();
13603
+ const definitions = Array.isArray(data) ? data : data.items ?? data.data;
13604
+ if (!definitions || definitions.length === 0) return null;
13605
+ const def = definitions[0];
13606
+ return {
13607
+ id: def.id,
13608
+ slug: def.slug,
13609
+ version: def.version || "0.1.0",
13610
+ instanceCount: def.instanceCount ?? def.instance_count ?? 0
13611
+ };
13612
+ } catch {
13613
+ return null;
13614
+ }
13615
+ }
13616
+ async function createDefinition(apiUrl, token, ir) {
13617
+ const res = await fetch(`${apiUrl}/workflow/definitions`, {
13618
+ method: "POST",
13619
+ headers: {
13620
+ "Content-Type": "application/json",
13621
+ Authorization: `Bearer ${token}`
13622
+ },
13623
+ body: JSON.stringify(ir)
13624
+ });
13625
+ if (!res.ok) {
13626
+ const errorText = await res.text();
13627
+ throw new Error(`Create failed: ${res.status} ${errorText}`);
13628
+ }
13629
+ }
13630
+ async function updateDefinition(apiUrl, token, id, ir) {
13631
+ const { slug: _slug, ...updatePayload } = ir;
13632
+ const res = await fetch(`${apiUrl}/workflow/definitions/${id}`, {
13633
+ method: "PATCH",
13634
+ headers: {
13635
+ "Content-Type": "application/json",
13636
+ Authorization: `Bearer ${token}`
13637
+ },
13638
+ body: JSON.stringify(updatePayload)
13639
+ });
13640
+ if (!res.ok) {
13641
+ const errorText = await res.text();
13642
+ throw new Error(`Update failed: ${res.status} ${errorText}`);
13643
+ }
13644
+ }
13645
+ function bumpVersion(version) {
13646
+ const parts = version.split(".");
13647
+ if (parts.length !== 3) return `${version}.1`;
13648
+ const patch = parseInt(parts[2], 10) || 0;
13649
+ return `${parts[0]}.${parts[1]}.${patch + 1}`;
13650
+ }
13651
+ async function syncServices(apiUrl, token, ir) {
13652
+ const metadata = ir.metadata;
13653
+ const orchestration = metadata?.orchestration;
13654
+ const services = orchestration?.services;
13655
+ if (!services || Object.keys(services).length === 0) return null;
13656
+ const result = { registered: [], updated: [], failed: [] };
13657
+ for (const [name, config] of Object.entries(services)) {
13658
+ try {
13659
+ const registration = {
13660
+ name,
13661
+ connection: {
13662
+ type: config.type || "webhook",
13663
+ url: config.url,
13664
+ queue: config.queue
13665
+ },
13666
+ actions: config.actions || [],
13667
+ labels: config.labels || {}
13668
+ };
13669
+ const existing = await fetchExistingService(apiUrl, token, name);
13670
+ if (existing) {
13671
+ await fetch(`${apiUrl}/services/${existing.id}`, {
13672
+ method: "PATCH",
13673
+ headers: {
13674
+ "Content-Type": "application/json",
13675
+ Authorization: `Bearer ${token}`
13676
+ },
13677
+ body: JSON.stringify(registration)
13678
+ });
13679
+ console.log(` \u2713 service: ${name} (updated)`);
13680
+ result.updated.push(name);
13681
+ } else {
13682
+ const res = await fetch(`${apiUrl}/services`, {
13683
+ method: "POST",
13684
+ headers: {
13685
+ "Content-Type": "application/json",
13686
+ Authorization: `Bearer ${token}`
13687
+ },
13688
+ body: JSON.stringify(registration)
13689
+ });
13690
+ if (!res.ok) {
13691
+ const errorText = await res.text();
13692
+ throw new Error(`Register failed: ${res.status} ${errorText}`);
13693
+ }
13694
+ console.log(` \u2713 service: ${name} (registered)`);
13695
+ result.registered.push(name);
13696
+ }
13697
+ } catch (error) {
13698
+ const msg = error.message;
13699
+ console.error(` \u2717 service: ${name}: ${msg}`);
13700
+ result.failed.push(name);
13701
+ }
13702
+ }
13703
+ return result;
13704
+ }
13705
+ async function fetchExistingService(apiUrl, token, name) {
13706
+ try {
13707
+ const res = await fetch(`${apiUrl}/services?name=${encodeURIComponent(name)}`, {
13708
+ headers: { Authorization: `Bearer ${token}` }
13709
+ });
13710
+ if (!res.ok) return null;
13711
+ const data = await res.json();
13712
+ const servicesList = Array.isArray(data) ? data : data.services ?? data.items ?? data.data;
13713
+ if (!servicesList || servicesList.length === 0) return null;
13714
+ const found = servicesList.find((s) => s.name === name);
13715
+ return found ? { id: found.id, name: found.name } : null;
13716
+ } catch {
13717
+ return null;
13718
+ }
13719
+ }
14644
13720
 
14645
13721
  // src/envelope.ts
14646
13722
  var import_crypto3 = require("crypto");
14647
- var import_fs7 = require("fs");
14648
- var import_path5 = require("path");
14649
- var import_glob4 = require("glob");
13723
+ var import_fs5 = require("fs");
13724
+ var import_path4 = require("path");
13725
+ var import_glob3 = require("glob");
14650
13726
  var import_core7 = require("@babel/core");
14651
13727
  init_babel();
14652
13728
  async function buildEnvelope(projectDir, options = {}) {
14653
- const root = (0, import_path5.resolve)(projectDir);
14654
- const slug = options.slug ?? (0, import_path5.basename)(root);
13729
+ const root = (0, import_path4.resolve)(projectDir);
13730
+ const slug = options.slug ?? (0, import_path4.basename)(root);
14655
13731
  const version = options.version ?? "0.1.0";
14656
13732
  const mode = options.mode ?? "infer";
14657
13733
  const patterns = options.include ?? [
@@ -14661,11 +13737,11 @@ async function buildEnvelope(projectDir, options = {}) {
14661
13737
  ];
14662
13738
  const discoveredFiles = [];
14663
13739
  for (const pattern of patterns) {
14664
- const matches = await (0, import_glob4.glob)(pattern, { absolute: true });
13740
+ const matches = await (0, import_glob3.glob)(pattern, { absolute: true });
14665
13741
  discoveredFiles.push(...matches);
14666
13742
  }
14667
13743
  const uniqueFiles = [...new Set(discoveredFiles)];
14668
- const allSourceFiles = await (0, import_glob4.glob)(`${root}/**/*.{ts,tsx,js,jsx,css,json}`, {
13744
+ const allSourceFiles = await (0, import_glob3.glob)(`${root}/**/*.{ts,tsx,js,jsx,css,json}`, {
14669
13745
  absolute: true,
14670
13746
  ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
14671
13747
  });
@@ -14675,10 +13751,10 @@ async function buildEnvelope(projectDir, options = {}) {
14675
13751
  const errors = [];
14676
13752
  const sourceBindings = [];
14677
13753
  for (const file2 of uniqueFiles) {
14678
- const relativePath = (0, import_path5.relative)(root, file2);
13754
+ const relativePath = (0, import_path4.relative)(root, file2);
14679
13755
  let fileContent;
14680
13756
  try {
14681
- fileContent = (0, import_fs7.readFileSync)(file2);
13757
+ fileContent = (0, import_fs5.readFileSync)(file2);
14682
13758
  } catch {
14683
13759
  errors.push({ file: relativePath, message: "Could not read file" });
14684
13760
  continue;