@cimplify/cli 0.15.2 → 0.16.0

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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -2
  3. package/dist/add-SXC6RUPQ.mjs +140 -0
  4. package/dist/{add-KRIIKAS4.mjs → add-XQVQLD3F.mjs} +4 -4
  5. package/dist/ai-NQH5L4I6.mjs +17 -0
  6. package/dist/{assets-CWB72PZG.mjs → assets-FZGVOQXH.mjs} +12 -7
  7. package/dist/{auth-step-up-Z6KOTTV7.mjs → auth-step-up-67LCPDNL.mjs} +5 -5
  8. package/dist/build-J4ZUIOPX.mjs +625 -0
  9. package/dist/{cancel-ZHVVILOU.mjs → cancel-VGJHZJ4J.mjs} +4 -4
  10. package/dist/capture-RAJ2B3BH.mjs +69 -0
  11. package/dist/chunk-25ZPFHLF.mjs +51 -0
  12. package/dist/chunk-47ZXSY47.mjs +52 -0
  13. package/dist/{chunk-NK6VC264.mjs → chunk-54J3XR4T.mjs} +2 -2
  14. package/dist/chunk-5HP2INMY.mjs +10631 -0
  15. package/dist/chunk-7JR6JCFF.mjs +32 -0
  16. package/dist/chunk-7PQL7E7K.mjs +68 -0
  17. package/dist/chunk-AKACUJ3W.mjs +81 -0
  18. package/dist/chunk-BYNE553A.mjs +2945 -0
  19. package/dist/{chunk-NYXA6X56.mjs → chunk-CLQYPTJ2.mjs} +31 -11
  20. package/dist/chunk-CNZAOVSK.mjs +104 -0
  21. package/dist/chunk-CPBESPWK.mjs +5576 -0
  22. package/dist/{chunk-GRR5U2M5.mjs → chunk-DYWUPHV3.mjs} +11 -7
  23. package/dist/chunk-EAV2P4N3.mjs +1941 -0
  24. package/dist/{chunk-KN2YSKXZ.mjs → chunk-EDZSOL5O.mjs} +14 -6
  25. package/dist/chunk-EGQIPYUN.mjs +696 -0
  26. package/dist/{chunk-DMLQBAGC.mjs → chunk-EOO4UOQD.mjs} +1 -1
  27. package/dist/chunk-EYEMPIMP.mjs +74 -0
  28. package/dist/chunk-G2ZEFSQJ.mjs +46 -0
  29. package/dist/{chunk-TH4XENKH.mjs → chunk-I4HNHPEM.mjs} +1 -1
  30. package/dist/chunk-JEVSFNPT.mjs +363 -0
  31. package/dist/chunk-JKECUAAV.mjs +2169 -0
  32. package/dist/chunk-KMHORI4Y.mjs +638 -0
  33. package/dist/chunk-KNPYBZ6B.mjs +502 -0
  34. package/dist/{chunk-3QUK5BPY.mjs → chunk-KOD4GBQ5.mjs} +8 -1
  35. package/dist/chunk-KQNZKV6E.mjs +535 -0
  36. package/dist/{chunk-MXYUAJEW.mjs → chunk-LLRUOIMU.mjs} +5 -2
  37. package/dist/{chunk-F2UI225N.mjs → chunk-LNMITJ4Z.mjs} +6 -6
  38. package/dist/chunk-MEM3MDV4.mjs +6463 -0
  39. package/dist/chunk-NY4YT7O6.mjs +84 -0
  40. package/dist/{chunk-A6WHBSXZ.mjs → chunk-Q6CF4C3E.mjs} +15 -13
  41. package/dist/chunk-RP66A52P.mjs +86 -0
  42. package/dist/{chunk-I2UP7YTG.mjs → chunk-SAXGWS2K.mjs} +1 -1
  43. package/dist/chunk-SCKQ4XSD.mjs +41 -0
  44. package/dist/chunk-SF44L2OD.mjs +1152 -0
  45. package/dist/chunk-SGT5IJVW.mjs +28 -0
  46. package/dist/{chunk-WEAB6HHQ.mjs → chunk-SS4JTMIV.mjs} +8 -8
  47. package/dist/chunk-T4MW3PD4.mjs +1456 -0
  48. package/dist/chunk-THATLMEX.mjs +1227 -0
  49. package/dist/{chunk-MLE4MVYC.mjs → chunk-TT4YI33G.mjs} +2 -2
  50. package/dist/chunk-TYV2SVFN.mjs +101 -0
  51. package/dist/chunk-VHK7WBO3.mjs +189 -0
  52. package/dist/chunk-VSA44UKR.mjs +391 -0
  53. package/dist/chunk-XL54SQJ3.mjs +42 -0
  54. package/dist/{chunk-5KYR6WJB.mjs → chunk-XQAHREKO.mjs} +17 -1
  55. package/dist/chunk-ZUCDXRFI.mjs +2011 -0
  56. package/dist/create-4S2EAUR3.mjs +10 -0
  57. package/dist/credits-NJOAOPPW.mjs +33 -0
  58. package/dist/{deploy-JE6TUYCL.mjs → deploy-26Y4UGZZ.mjs} +14 -14
  59. package/dist/dev-MOYURRWQ.mjs +401 -0
  60. package/dist/dev-WL43Q7VD.mjs +8 -0
  61. package/dist/dispatcher.mjs +131 -30
  62. package/dist/{doctor-HFB4IBYK.mjs → doctor-E6ETD2GJ.mjs} +12 -19
  63. package/dist/{domains-BZKGIDF4.mjs → domains-LOTQMVOR.mjs} +6 -6
  64. package/dist/engine-runtime-fetch-CIE7S7PB.mjs +10 -0
  65. package/dist/{env-FZNXKLGL.mjs → env-3PDFC5XF.mjs} +7 -7
  66. package/dist/env-MOTYOPM5.mjs +19 -0
  67. package/dist/explain-K5QEVWCD.mjs +251 -0
  68. package/dist/{inspect-X3M7WSTL.mjs → inspect-Q3E2DHYY.mjs} +3 -3
  69. package/dist/inspect-SJ4WBAXO.mjs +86 -0
  70. package/dist/introspect-7F34YN5V.mjs +9 -0
  71. package/dist/kernel-DEGWMHFL.mjs +662 -0
  72. package/dist/kernel-plugin.js +6862 -0
  73. package/dist/keys-W5SN3DPK.mjs +71 -0
  74. package/dist/lines-XGJYTQ7P.mjs +56 -0
  75. package/dist/{link-4NM2QMI5.mjs → link-NKUAVNM2.mjs} +6 -5
  76. package/dist/{lint-DDZ7HUQN.mjs → lint-G4YPQSSO.mjs} +2 -2
  77. package/dist/{list-2MFOQKKQ.mjs → list-TDR7K2JB.mjs} +3 -3
  78. package/dist/lock-EJPW2LM3.mjs +57 -0
  79. package/dist/{login-RLMDEWAL.mjs → login-AYLU7JU7.mjs} +10 -8
  80. package/dist/{logout-Z57X6HPE.mjs → logout-3M6VMHLH.mjs} +2 -2
  81. package/dist/{logs-36BLYJHJ.mjs → logs-4EL5SOXN.mjs} +5 -5
  82. package/dist/logs-4QQGG2XY.mjs +44 -0
  83. package/dist/mcp-4R2R6E5M.mjs +1077 -0
  84. package/dist/{mock-EVER34IX.mjs → mock-AK24GSP2.mjs} +2 -2
  85. package/dist/outdated-JEKCVLTG.mjs +58 -0
  86. package/dist/port-SBZ7X3EH.mjs +2408 -0
  87. package/dist/{projects-4XRNHJAH.mjs → projects-7JKTC5WJ.mjs} +9 -7
  88. package/dist/publish-QQCX47HK.mjs +20 -0
  89. package/dist/remix-NLLYD3BI.mjs +125 -0
  90. package/dist/repo-Z4G4EW3N.mjs +9 -0
  91. package/dist/report-M7F4ZYP7.mjs +2 -0
  92. package/dist/rollback-2WQ2CW7T.mjs +43 -0
  93. package/dist/{rollback-WCRWXSE3.mjs → rollback-ZGU32HGT.mjs} +6 -6
  94. package/dist/scene-HXARHUM7.mjs +324 -0
  95. package/dist/{status-VA326DWD.mjs → status-C3ZSLZ7Q.mjs} +5 -5
  96. package/dist/status-WEQOC25K.mjs +18 -0
  97. package/dist/test-ZPBWV4VX.mjs +233 -0
  98. package/dist/testers-A3LMXOJJ.mjs +49 -0
  99. package/dist/{unlink-H3BO3DOQ.mjs → unlink-4G4FE4RJ.mjs} +2 -2
  100. package/dist/{update-YYOTN7MG.mjs → update-GHKKM5FS.mjs} +4 -4
  101. package/dist/{whoami-CQPPARRS.mjs → whoami-3QQN6G2A.mjs} +3 -3
  102. package/dist/workshop-CD74D2LK.mjs +1703 -0
  103. package/package.json +11 -7
  104. package/templates/storefront-auto/app/products/[slug]/page.tsx +1 -1
  105. package/templates/storefront-auto/package.json +1 -1
  106. package/templates/storefront-bakery/package.json +1 -1
  107. package/templates/storefront-fashion/app/products/[slug]/page.tsx +1 -1
  108. package/templates/storefront-fashion/package.json +1 -1
  109. package/templates/storefront-grocery/package.json +1 -1
  110. package/templates/storefront-pharmacy/app/products/[slug]/page.tsx +1 -1
  111. package/templates/storefront-pharmacy/package.json +1 -1
  112. package/templates/storefront-restaurant/package.json +1 -1
  113. package/templates/storefront-retail/app/products/[slug]/page.tsx +1 -1
  114. package/templates/storefront-retail/package.json +1 -1
  115. package/templates/storefront-services/package.json +1 -1
  116. package/dist/chunk-ARIDYKLO.mjs +0 -6463
  117. package/dist/dev-V7JSUVOI.mjs +0 -8
  118. package/dist/explain-O5AC73EE.mjs +0 -251
  119. package/dist/introspect-2NGESQZE.mjs +0 -8
  120. package/dist/repo-X3KZ5R64.mjs +0 -9
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ export { createProject, run as default, parseTemplate } from './chunk-EAV2P4N3.mjs';
3
+ import './chunk-CNZAOVSK.mjs';
4
+ import './chunk-T4MW3PD4.mjs';
5
+ import './chunk-KQNZKV6E.mjs';
6
+ import './chunk-AKACUJ3W.mjs';
7
+ import './chunk-25ZPFHLF.mjs';
8
+ import './chunk-SGT5IJVW.mjs';
9
+ import './chunk-XQAHREKO.mjs';
10
+ import './chunk-KOD4GBQ5.mjs';
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ import { requireInteractiveProject, buildLocal, renderDiagnostics } from './chunk-CPBESPWK.mjs';
3
+ import './chunk-VHK7WBO3.mjs';
4
+ import './chunk-5HP2INMY.mjs';
5
+ import './chunk-JKECUAAV.mjs';
6
+ import './chunk-T4MW3PD4.mjs';
7
+ import './chunk-KQNZKV6E.mjs';
8
+ import './chunk-ZUCDXRFI.mjs';
9
+ import './chunk-EYEMPIMP.mjs';
10
+ import './chunk-AKACUJ3W.mjs';
11
+ import './chunk-25ZPFHLF.mjs';
12
+ import './chunk-SGT5IJVW.mjs';
13
+ import './chunk-TT4YI33G.mjs';
14
+ import { info, dim, result } from './chunk-KOD4GBQ5.mjs';
15
+
16
+ // src/interactives/commands/credits.ts
17
+ async function run() {
18
+ const root = process.cwd();
19
+ requireInteractiveProject(root, "credits");
20
+ const { result: built } = await buildLocal(root);
21
+ const credits = built.package?.credits ?? [];
22
+ if (built.package === null) {
23
+ for (const line of renderDiagnostics(built.diagnostics)) info(line);
24
+ }
25
+ for (const credit of credits) {
26
+ const tags = [credit.modified ? "modified" : null, credit.ai === void 0 ? null : credit.ai === "generated" ? "made with AI" : "AI-assisted"].filter((t) => t !== null);
27
+ info(`${credit.title} by ${credit.authors.join(", ")} ${dim(`(${credit.licence}${tags.length > 0 ? `; ${tags.join(", ")}` : ""})`)}`);
28
+ }
29
+ if (credits.length === 0) info(dim("no credits; add [[credits]] to interactive.toml or Workshop content with cimplify add"));
30
+ result(credits);
31
+ }
32
+
33
+ export { run as default };
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { detectPackageManager } from './chunk-F2UI225N.mjs';
3
- import { fetchRepoRecord, fetchCloneToken } from './chunk-A6WHBSXZ.mjs';
4
- import { pollDeployment } from './chunk-NK6VC264.mjs';
5
- import './chunk-I2UP7YTG.mjs';
6
- import { promptYesNo } from './chunk-TH4XENKH.mjs';
7
- import { REPO_PROVIDER, ENV_SCOPE, DEPLOY_TRIGGER, DEPLOYMENT_STATUS, TOKEN_PURPOSE } from './chunk-MXYUAJEW.mjs';
8
- import { isFreestyleRemote, gitDetectRoot, gitStatusPorcelain, gitCurrentBranch, gitCurrentSha, gitGetRemoteUrl, gitPushToUrl, gitPush } from './chunk-KN2YSKXZ.mjs';
9
- import { parseArgs, flagBool, flagString } from './chunk-5KYR6WJB.mjs';
10
- import { ApiClient } from './chunk-NYXA6X56.mjs';
11
- import { readAuth, readProjectLink, writeProjectState } from './chunk-MLE4MVYC.mjs';
12
- import { info, dim, step, CliError, CLI_ERROR_CODE, success, result, EXIT_CODE } from './chunk-3QUK5BPY.mjs';
2
+ import { detectPackageManager } from './chunk-LNMITJ4Z.mjs';
3
+ import { fetchRepoRecord, fetchCloneToken } from './chunk-Q6CF4C3E.mjs';
4
+ import { pollDeployment } from './chunk-54J3XR4T.mjs';
5
+ import './chunk-SAXGWS2K.mjs';
6
+ import { promptYesNo } from './chunk-I4HNHPEM.mjs';
7
+ import { isManagedRemote, gitDetectRoot, gitStatusPorcelain, gitCurrentBranch, gitCurrentSha, gitGetRemoteUrl, gitPushToUrl, gitPush } from './chunk-EDZSOL5O.mjs';
8
+ import { isManagedRepoProvider, ENV_SCOPE, DEPLOY_TRIGGER, DEPLOYMENT_STATUS, TOKEN_PURPOSE } from './chunk-LLRUOIMU.mjs';
9
+ import { parseArgs, flagBool, flagString } from './chunk-XQAHREKO.mjs';
10
+ import { ApiClient } from './chunk-CLQYPTJ2.mjs';
11
+ import { readAuth, readProjectLink, writeProjectState } from './chunk-TT4YI33G.mjs';
12
+ import { info, dim, step, CliError, CLI_ERROR_CODE, success, result, EXIT_CODE } from './chunk-KOD4GBQ5.mjs';
13
13
  import { spawn } from 'child_process';
14
14
  import { promises } from 'fs';
15
15
  import path from 'path';
@@ -90,11 +90,11 @@ Or deploy anyway with --${FLAG_SKIP_ENV_CHECK}.`
90
90
  );
91
91
  }
92
92
  function resolvePushStrategy(originUrl, linkRemoteUrl, repo) {
93
- if (isFreestyleRemote(originUrl) || isFreestyleRemote(linkRemoteUrl)) {
93
+ if (isManagedRemote(originUrl) || isManagedRemote(linkRemoteUrl)) {
94
94
  return { kind: "managed" };
95
95
  }
96
96
  if (repo) {
97
- if (repo.provider === REPO_PROVIDER.FREESTYLE || isFreestyleRemote(repo.remote_url)) {
97
+ if (isManagedRepoProvider(repo.provider) || isManagedRemote(repo.remote_url)) {
98
98
  return { kind: "managed" };
99
99
  }
100
100
  if (!originUrl) {
@@ -117,7 +117,7 @@ Then re-run cimplify deploy.`
117
117
  }
118
118
  async function pushForDeploy(client, businessId, projectId, root, branch, linkRemoteUrl) {
119
119
  const originUrl = await gitGetRemoteUrl(root);
120
- const repo = isFreestyleRemote(originUrl) || isFreestyleRemote(linkRemoteUrl) ? null : await fetchRepoRecord(client, businessId, projectId);
120
+ const repo = isManagedRemote(originUrl) || isManagedRemote(linkRemoteUrl) ? null : await fetchRepoRecord(client, businessId, projectId);
121
121
  const strategy = resolvePushStrategy(originUrl, linkRemoteUrl, repo);
122
122
  if (strategy.kind === "error") {
123
123
  throw new CliError(CLI_ERROR_CODE.GIT_ERROR, strategy.message);
@@ -0,0 +1,401 @@
1
+ #!/usr/bin/env node
2
+ import { FRAME_MS, DEFAULT_EPOCH_MS, DEFAULT_SEED, SCRIPT_SCHEMA, DEVICES, DEFAULT_HOLD_FRAMES, DEFAULT_DRAG_FRAMES } from './chunk-KNPYBZ6B.mjs';
3
+ import { startDevServer, devLocale, probeScript } from './chunk-BYNE553A.mjs';
4
+ import './chunk-NY4YT7O6.mjs';
5
+ import { localEnvironmentName } from './chunk-JEVSFNPT.mjs';
6
+ import { localDataDir } from './chunk-SF44L2OD.mjs';
7
+ import './chunk-VSA44UKR.mjs';
8
+ import './chunk-EGQIPYUN.mjs';
9
+ import './chunk-SCKQ4XSD.mjs';
10
+ import './chunk-CPBESPWK.mjs';
11
+ import './chunk-VHK7WBO3.mjs';
12
+ import './chunk-5HP2INMY.mjs';
13
+ import './chunk-JKECUAAV.mjs';
14
+ import './chunk-THATLMEX.mjs';
15
+ import './chunk-T4MW3PD4.mjs';
16
+ import './chunk-KQNZKV6E.mjs';
17
+ import { refreshEngineRuntime } from './chunk-G2ZEFSQJ.mjs';
18
+ import './chunk-ZUCDXRFI.mjs';
19
+ import './chunk-EYEMPIMP.mjs';
20
+ import './chunk-AKACUJ3W.mjs';
21
+ import './chunk-25ZPFHLF.mjs';
22
+ import { formatDiagnostic } from './chunk-SGT5IJVW.mjs';
23
+ import { parseArgs, flagBool, flagString } from './chunk-XQAHREKO.mjs';
24
+ import { ApiClient } from './chunk-CLQYPTJ2.mjs';
25
+ import { readAuthOrNull } from './chunk-TT4YI33G.mjs';
26
+ import { info, bold, dim, CliError, CLI_ERROR_CODE, warn, failure, success } from './chunk-KOD4GBQ5.mjs';
27
+ import path2 from 'path';
28
+ import { promises } from 'fs';
29
+ import { randomInt } from 'crypto';
30
+ import { networkInterfaces } from 'os';
31
+
32
+ var LINEAR_TOLERANCE = 0.01;
33
+ function deviceName(start) {
34
+ const width = Math.round(start.width);
35
+ const height = Math.round(start.height);
36
+ const scale = Math.round(start.scale * 100) / 100;
37
+ for (const device of Object.values(DEVICES)) if (device.width === width && device.height === height && device.scale === scale) return device.name;
38
+ return `${width}x${height}@${scale}`;
39
+ }
40
+ function isPointer(event, kind) {
41
+ return event !== void 0 && event.kind === kind;
42
+ }
43
+ function at(event) {
44
+ return [event.x, event.y];
45
+ }
46
+ function same(a, b) {
47
+ return Math.abs(a[0] - b[0]) <= LINEAR_TOLERANCE && Math.abs(a[1] - b[1]) <= LINEAR_TOLERANCE;
48
+ }
49
+ function coalesce(events) {
50
+ const out = [];
51
+ for (const event of events) {
52
+ const last = out[out.length - 1];
53
+ if (event.kind === "move" && last !== void 0 && last.kind === "move" && last.frame === event.frame) out[out.length - 1] = event;
54
+ else if (event.kind === "text" && last !== void 0 && last.kind === "text" && last.frame === event.frame) out[out.length - 1] = { kind: "text", frame: event.frame, text: last.text + event.text };
55
+ else out.push(event);
56
+ }
57
+ return out;
58
+ }
59
+ function freeFrom(events, index, frame) {
60
+ const next = events[index];
61
+ return next === void 0 || next.frame >= frame;
62
+ }
63
+ function tap(events, i) {
64
+ const down = events[i];
65
+ const up = events[i + 1];
66
+ if (!isPointer(down, "down") || !isPointer(up, "up")) return null;
67
+ const hold = up.frame - down.frame;
68
+ if (!freeFrom(events, i + 2, up.frame + 1)) return null;
69
+ return { step: hold === DEFAULT_HOLD_FRAMES ? { tap: at(down) } : { tap: at(down), hold }, used: 2, frames: hold + 1 };
70
+ }
71
+ function drag(events, i) {
72
+ const down = events[i];
73
+ if (!isPointer(down, "down")) return null;
74
+ const path3 = [];
75
+ let j = i + 1;
76
+ for (; ; ) {
77
+ const move = events[j];
78
+ if (!isPointer(move, "move") || move.frame !== down.frame + path3.length + 1) break;
79
+ path3.push(at(move));
80
+ j++;
81
+ }
82
+ const up = events[j];
83
+ const n = path3.length;
84
+ if (n === 0 || !isPointer(up, "up") || up.frame !== down.frame + n + 1) return null;
85
+ if (!freeFrom(events, j + 1, up.frame + 1)) return null;
86
+ const from = at(down);
87
+ const to = path3[n - 1];
88
+ const linear = path3.every((p, k) => same(p, [from[0] + (to[0] - from[0]) * (k + 1) / n, from[1] + (to[1] - from[1]) * (k + 1) / n]));
89
+ const step = linear ? { drag: n === DEFAULT_DRAG_FRAMES ? { from, to } : { from, to, frames: n } } : { drag: { from, to, path: path3 } };
90
+ return { step, used: j + 1 - i, frames: n + 2 };
91
+ }
92
+ function key(events, i) {
93
+ const down = events[i];
94
+ const up = events[i + 1];
95
+ if (down === void 0 || up === void 0 || down.kind !== "key_down" || up.kind !== "key_up" || up.key !== down.key) return null;
96
+ const hold = up.frame - down.frame;
97
+ if (!freeFrom(events, i + 2, up.frame + 1)) return null;
98
+ return { step: hold === DEFAULT_HOLD_FRAMES ? { key: down.key } : { key: down.key, hold }, used: 2, frames: hold + 1 };
99
+ }
100
+ function typed(events, i) {
101
+ const event = events[i];
102
+ if (event === void 0 || event.kind !== "text" || !freeFrom(events, i + 1, event.frame + 1)) return null;
103
+ return { step: { type: event.text }, used: 1, frames: 1 };
104
+ }
105
+ function primitive(event) {
106
+ switch (event.kind) {
107
+ case "down":
108
+ return { down: [event.x, event.y] };
109
+ case "move":
110
+ return { move: [event.x, event.y] };
111
+ case "up":
112
+ return { up: true };
113
+ case "key_down":
114
+ return { key_down: event.key };
115
+ case "key_up":
116
+ return { key_up: event.key };
117
+ case "text":
118
+ return { text: event.text };
119
+ }
120
+ }
121
+ function stepsFrom(recorded) {
122
+ const events = coalesce([...recorded].sort((a, b) => a.frame - b.frame));
123
+ const steps = [];
124
+ let cursor = 0;
125
+ let i = 0;
126
+ while (i < events.length) {
127
+ const event = events[i];
128
+ if (event.frame > cursor) {
129
+ steps.push({ wait: event.frame - cursor });
130
+ cursor = event.frame;
131
+ }
132
+ const match = tap(events, i) ?? drag(events, i) ?? key(events, i) ?? typed(events, i);
133
+ if (match === null) {
134
+ steps.push(primitive(event));
135
+ i++;
136
+ continue;
137
+ }
138
+ steps.push(match.step);
139
+ cursor += match.frames;
140
+ i += match.used;
141
+ }
142
+ return steps;
143
+ }
144
+ function recordedScript(start, events) {
145
+ return { schema: SCRIPT_SCHEMA, devices: [deviceName(start)], seed: start.seed, steps: stepsFrom(events) };
146
+ }
147
+ function isRecordedInput(value) {
148
+ if (typeof value !== "object" || value === null) return false;
149
+ const v = value;
150
+ const finite = (x) => typeof x === "number" && Number.isFinite(x);
151
+ const frame = finite(v.frame) && Number.isInteger(v.frame) && v.frame >= 0;
152
+ switch (v.kind) {
153
+ case "start":
154
+ return finite(v.width) && finite(v.height) && finite(v.scale) && finite(v.seed);
155
+ case "down":
156
+ case "move":
157
+ case "up":
158
+ return frame && finite(v.x) && finite(v.y);
159
+ case "key_down":
160
+ case "key_up":
161
+ return frame && typeof v.key === "string" && v.key.length > 0;
162
+ case "text":
163
+ return frame && typeof v.text === "string";
164
+ default:
165
+ return false;
166
+ }
167
+ }
168
+ var RECORD_MAX_NODES = 4096;
169
+ function recordPrelude(seed) {
170
+ return `${probeScript({ seed, epoch: DEFAULT_EPOCH_MS, frame_ms: FRAME_MS, insets: null, bare: false, scene: null, max_nodes: RECORD_MAX_NODES, record: true })}
171
+ `;
172
+ }
173
+ var InputRecorder = class {
174
+ constructor(file) {
175
+ this.file = file;
176
+ }
177
+ file;
178
+ start = null;
179
+ events = [];
180
+ writing = Promise.resolve();
181
+ dirty = false;
182
+ starts = 0;
183
+ get recording() {
184
+ return this.start !== null;
185
+ }
186
+ get count() {
187
+ return this.events.length;
188
+ }
189
+ add(inputs) {
190
+ let accepted = 0;
191
+ for (const input of inputs) {
192
+ if (!isRecordedInput(input)) continue;
193
+ accepted++;
194
+ if (input.kind === "start") {
195
+ this.start = input;
196
+ this.events = [];
197
+ this.starts++;
198
+ } else if (this.start !== null) this.events.push(input);
199
+ }
200
+ if (accepted > 0) this.dirty = true;
201
+ return accepted;
202
+ }
203
+ script() {
204
+ return this.start === null ? null : recordedScript(this.start, this.events);
205
+ }
206
+ flush() {
207
+ if (!this.dirty) return this.writing;
208
+ this.dirty = false;
209
+ const script = this.script();
210
+ if (script === null) return this.writing;
211
+ const text = `${JSON.stringify(script, null, 2)}
212
+ `;
213
+ this.writing = this.writing.then(async () => {
214
+ await promises.mkdir(path2.dirname(this.file), { recursive: true });
215
+ await promises.writeFile(this.file, text);
216
+ });
217
+ return this.writing;
218
+ }
219
+ };
220
+
221
+ // src/interactives/dev/engine-session.ts
222
+ var ENGINE_SESSIONS_ROUTE = "/v1/interactives/engine/sessions";
223
+ var CLI_AUDIENCE = "cli";
224
+ var CLI_ORIGIN = "cli";
225
+ var REFRESH_MARGIN_MS = 5 * 60 * 1e3;
226
+ var RETRY_AFTER_FAILURE_MS = 5 * 60 * 1e3;
227
+ async function signedInClient() {
228
+ const auth = await readAuthOrNull();
229
+ return auth === null ? null : ApiClient.fromAuth(auth);
230
+ }
231
+ var DevEngineSessions = class {
232
+ constructor(client = signedInClient, now = Date.now, report2 = (message) => info(dim(message))) {
233
+ this.client = client;
234
+ this.now = now;
235
+ this.report = report2;
236
+ }
237
+ client;
238
+ now;
239
+ report;
240
+ held = null;
241
+ retryAt = 0;
242
+ reported = false;
243
+ async session() {
244
+ const at2 = this.now();
245
+ if (this.held !== null && this.held.expiresAt - REFRESH_MARGIN_MS > at2) return this.held.session;
246
+ if (at2 < this.retryAt) return null;
247
+ try {
248
+ const client = await this.client();
249
+ if (client === null) throw new Error("not signed in; run `cimplify login`");
250
+ const body = await client.post(ENGINE_SESSIONS_ROUTE, { audience: CLI_AUDIENCE });
251
+ const expiresAt = Date.parse(body.expires_at);
252
+ if (typeof body.token !== "string" || body.token.length === 0 || Number.isNaN(expiresAt)) throw new Error("the registry returned an unusable engine session");
253
+ this.held = { session: { token: body.token, audience: CLI_AUDIENCE, origin: CLI_ORIGIN }, expiresAt };
254
+ return this.held.session;
255
+ } catch (error) {
256
+ this.held = null;
257
+ this.retryAt = at2 + RETRY_AFTER_FAILURE_MS;
258
+ if (!this.reported) {
259
+ this.reported = true;
260
+ this.report(`Previewing without an engine session token: ${error instanceof Error ? error.message : String(error)}`);
261
+ }
262
+ return null;
263
+ }
264
+ }
265
+ };
266
+ var CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
267
+ var CODE_HALF = 3;
268
+ function lanAddress() {
269
+ const nets = networkInterfaces();
270
+ for (const name of Object.keys(nets).sort()) {
271
+ for (const net of nets[name] ?? []) {
272
+ if (net.family === "IPv4" && !net.internal) return net.address;
273
+ }
274
+ }
275
+ return null;
276
+ }
277
+ function pairingCode() {
278
+ let out = "";
279
+ for (let i = 0; i < CODE_HALF * 2; i++) {
280
+ if (i === CODE_HALF) out += "-";
281
+ out += CODE_ALPHABET[randomInt(CODE_ALPHABET.length)];
282
+ }
283
+ return out;
284
+ }
285
+ var LAN_PREVIEW_RELAY = {
286
+ async register(localUrl, port) {
287
+ const address = lanAddress();
288
+ const code = pairingCode();
289
+ return { code, url: address === null ? localUrl : `http://${address}:${port}/?code=${code}`, relayed: false };
290
+ }
291
+ };
292
+
293
+ // src/interactives/commands/dev.ts
294
+ var DEFAULT_PORT = 4300;
295
+ var LOOPBACK = "127.0.0.1";
296
+ var ALL_INTERFACES = "0.0.0.0";
297
+ function parsePort(value) {
298
+ if (value === void 0) return DEFAULT_PORT;
299
+ const port = Number(value);
300
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
301
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `--port must be a port number, got '${value}'`);
302
+ }
303
+ return port;
304
+ }
305
+ function report(build) {
306
+ if (build.lockUpdated) info(dim("Pinned newly used libraries in cimplify.lock"));
307
+ for (const d of build.result.diagnostics) (d.severity === "error" ? failure : warn)(formatDiagnostic(d));
308
+ if (build.result.ok) success(`Rebuilt ${dim(build.result.sourceDigest)}`);
309
+ }
310
+ function reportTick(event) {
311
+ switch (event.type) {
312
+ case "ready":
313
+ info(dim(`Tick room running ${event.seats} seats at ${event.rate_hz} Hz with ${event.state_bytes} state bytes`));
314
+ return;
315
+ case "log":
316
+ info(dim(`[tick ${event.tick}] ${event.message}`));
317
+ return;
318
+ case "error":
319
+ failure(`Tick room ${event.kind.replaceAll("_", " ")} at tick ${event.tick}: ${event.message}${event.source === null ? "" : ` (${event.source})`}`);
320
+ return;
321
+ case "unavailable":
322
+ warn(event.message);
323
+ return;
324
+ default:
325
+ return;
326
+ }
327
+ }
328
+ function parseSeed(value) {
329
+ if (value === void 0) return DEFAULT_SEED;
330
+ const seed = Number(value);
331
+ if (!Number.isInteger(seed)) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `--seed takes an integer, got '${value}'`);
332
+ return seed;
333
+ }
334
+ function recording(file, seed) {
335
+ if (file === void 0) {
336
+ if (seed !== void 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "--seed applies to --record; pass --record <file> too");
337
+ return null;
338
+ }
339
+ const target = path2.resolve(process.cwd(), file);
340
+ let last = 0;
341
+ return {
342
+ recorder: new InputRecorder(target),
343
+ prelude: recordPrelude(parseSeed(seed)),
344
+ onInput: (recorder) => {
345
+ if (recorder.starts === last) return;
346
+ last = recorder.starts;
347
+ info(dim(`Recording engine started; inputs go to ${path2.relative(process.cwd(), target) || target}`));
348
+ }
349
+ };
350
+ }
351
+ async function run(argv) {
352
+ const args = parseArgs(argv);
353
+ const lan = flagBool(args, "lan");
354
+ const environment = localEnvironmentName(flagString(args, "env"));
355
+ const record = recording(flagString(args, "record"), flagString(args, "seed"));
356
+ await refreshEngineRuntime(process.cwd());
357
+ const server = await startDevServer({
358
+ root: process.cwd(),
359
+ host: lan ? ALL_INTERFACES : LOOPBACK,
360
+ port: parsePort(flagString(args, "port")),
361
+ contentOrigin: flagString(args, "content-origin"),
362
+ watch: true,
363
+ onRebuild: report,
364
+ tick: { onEvent: reportTick },
365
+ engineSessions: new DevEngineSessions(),
366
+ environment,
367
+ record,
368
+ locale: devLocale({
369
+ language: flagString(args, "locale"),
370
+ currency: flagString(args, "currency"),
371
+ timeZone: flagString(args, "time-zone")
372
+ })
373
+ });
374
+ report(server.current());
375
+ info("");
376
+ info(`Simulator ${bold(server.url)}`);
377
+ if (record !== null) {
378
+ info(`Recording ${bold(path2.relative(process.cwd(), record.recorder.file) || record.recorder.file)} taps, drags, keys and text by frame, with a fixed clock and seed`);
379
+ info(dim(" replay it with cimplify capture --script <file>; a reload starts a new recording"));
380
+ }
381
+ info(dim(`Data ${localDataDir(process.cwd(), environment)} (cimplify env reset ${environment} clears it)`));
382
+ if (lan) {
383
+ const link = await LAN_PREVIEW_RELAY.register(server.url, server.port);
384
+ info(`Phone ${bold(link.url)} code ${bold(link.code)}`);
385
+ info(dim(" open it on a phone on the same network; the hosted preview relay is not live yet"));
386
+ } else {
387
+ info(dim("Phone run with --lan to preview on a phone on the same network"));
388
+ }
389
+ info(dim("Watching for changes. Press Ctrl+C to stop."));
390
+ await new Promise((resolve) => {
391
+ const stop = () => {
392
+ process.off("SIGINT", stop);
393
+ process.off("SIGTERM", stop);
394
+ void server.close().then(resolve);
395
+ };
396
+ process.on("SIGINT", stop);
397
+ process.on("SIGTERM", stop);
398
+ });
399
+ }
400
+
401
+ export { run as default };
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ export { run as default, detectPackageManager, mergeEnvEntries } from './chunk-LNMITJ4Z.mjs';
3
+ import './chunk-SAXGWS2K.mjs';
4
+ import './chunk-LLRUOIMU.mjs';
5
+ import './chunk-XQAHREKO.mjs';
6
+ import './chunk-CLQYPTJ2.mjs';
7
+ import './chunk-TT4YI33G.mjs';
8
+ import './chunk-KOD4GBQ5.mjs';