@cimplify/cli 0.15.3 → 0.17.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-C3DPTVH3.mjs +140 -0
  4. package/dist/{add-KRIIKAS4.mjs → add-JX2GXWXU.mjs} +4 -4
  5. package/dist/ai-HUZTVJIQ.mjs +17 -0
  6. package/dist/{assets-CWB72PZG.mjs → assets-MPESJSUV.mjs} +12 -7
  7. package/dist/{auth-step-up-Z6KOTTV7.mjs → auth-step-up-VJAFGSW6.mjs} +5 -5
  8. package/dist/build-E7RRQWVF.mjs +616 -0
  9. package/dist/{cancel-ZHVVILOU.mjs → cancel-UMKR274A.mjs} +4 -4
  10. package/dist/capture-TK4NIUYM.mjs +69 -0
  11. package/dist/chunk-25ZPFHLF.mjs +51 -0
  12. package/dist/{chunk-OLZKNUMK.mjs → chunk-3LJG22FS.mjs} +6 -6
  13. package/dist/chunk-454RQ6NR.mjs +10614 -0
  14. package/dist/{chunk-O2TO2J4I.mjs → chunk-6CQMRZ2W.mjs} +2 -2
  15. package/dist/chunk-6KKLF5KG.mjs +32 -0
  16. package/dist/chunk-74QZQSCL.mjs +84 -0
  17. package/dist/chunk-BGM7CH5G.mjs +81 -0
  18. package/dist/chunk-BTNVYAC4.mjs +5557 -0
  19. package/dist/{chunk-I2UP7YTG.mjs → chunk-ECGDRU56.mjs} +1 -1
  20. package/dist/{chunk-UTD34C2H.mjs → chunk-EOOOXVHR.mjs} +2 -4
  21. package/dist/chunk-EYEMPIMP.mjs +74 -0
  22. package/dist/{chunk-3RPR33MO.mjs → chunk-FV273ECI.mjs} +11 -7
  23. package/dist/{chunk-MLE4MVYC.mjs → chunk-GGPN4QYQ.mjs} +2 -2
  24. package/dist/chunk-HQPZQIWW.mjs +1456 -0
  25. package/dist/{chunk-3QUK5BPY.mjs → chunk-I7GEHLDD.mjs} +16 -1
  26. package/dist/chunk-ITDAICBY.mjs +363 -0
  27. package/dist/chunk-JKECUAAV.mjs +2169 -0
  28. package/dist/chunk-JNCEKW2Y.mjs +41 -0
  29. package/dist/chunk-JTYVGORV.mjs +101 -0
  30. package/dist/chunk-KQNZKV6E.mjs +535 -0
  31. package/dist/chunk-LJDIQ4PF.mjs +6463 -0
  32. package/dist/{chunk-2MKZKUVH.mjs → chunk-LLRUOIMU.mjs} +1 -2
  33. package/dist/chunk-MJMRIMR7.mjs +86 -0
  34. package/dist/chunk-N2WZJX5P.mjs +1989 -0
  35. package/dist/chunk-NEB372WD.mjs +1152 -0
  36. package/dist/chunk-OPX7KPOU.mjs +68 -0
  37. package/dist/chunk-PHUBMRAS.mjs +623 -0
  38. package/dist/chunk-PQBALZUH.mjs +1941 -0
  39. package/dist/chunk-PVW5D5AW.mjs +42 -0
  40. package/dist/{chunk-LZEG3FEY.mjs → chunk-QQWYQ2HS.mjs} +7 -7
  41. package/dist/chunk-QVR6V6QP.mjs +46 -0
  42. package/dist/chunk-SGT5IJVW.mjs +28 -0
  43. package/dist/chunk-SZXO6YSX.mjs +502 -0
  44. package/dist/chunk-THATLMEX.mjs +1227 -0
  45. package/dist/chunk-TYR4Q37L.mjs +391 -0
  46. package/dist/{chunk-DMLQBAGC.mjs → chunk-V3R2NYQR.mjs} +1 -1
  47. package/dist/chunk-VHK7WBO3.mjs +189 -0
  48. package/dist/{chunk-TH4XENKH.mjs → chunk-XASDB7YS.mjs} +1 -1
  49. package/dist/{chunk-NYXA6X56.mjs → chunk-XBQ4LO2N.mjs} +31 -11
  50. package/dist/chunk-XF3MGADK.mjs +2946 -0
  51. package/dist/{chunk-5KYR6WJB.mjs → chunk-XQAHREKO.mjs} +17 -1
  52. package/dist/chunk-XZG3DTXV.mjs +696 -0
  53. package/dist/chunk-Y4YGR2NY.mjs +52 -0
  54. package/dist/{chunk-LJEKKFC7.mjs → chunk-YS2JUNSQ.mjs} +19 -11
  55. package/dist/chunk-ZG7NJLXN.mjs +104 -0
  56. package/dist/create-3TGG7B3X.mjs +10 -0
  57. package/dist/credits-MEG7V5DI.mjs +33 -0
  58. package/dist/{deploy-STWZ3OSM.mjs → deploy-CNRORHJ7.mjs} +11 -11
  59. package/dist/dev-RXSBY7U4.mjs +8 -0
  60. package/dist/dev-YLYC6B7R.mjs +401 -0
  61. package/dist/dispatcher.mjs +131 -30
  62. package/dist/{doctor-3RW3OGZJ.mjs → doctor-XRTNG2IT.mjs} +13 -21
  63. package/dist/{domains-FTNK4IKY.mjs → domains-JIHFKDWR.mjs} +6 -6
  64. package/dist/engine-runtime-fetch-QVKJVC3W.mjs +10 -0
  65. package/dist/{env-TNCYUAMT.mjs → env-LJ3DCAA5.mjs} +7 -7
  66. package/dist/env-R72AHBT2.mjs +19 -0
  67. package/dist/explain-32RSXEXC.mjs +251 -0
  68. package/dist/inspect-PYLYN45K.mjs +86 -0
  69. package/dist/{inspect-X3M7WSTL.mjs → inspect-ZOLZHNSZ.mjs} +28 -13
  70. package/dist/introspect-27MMTACH.mjs +9 -0
  71. package/dist/kernel-IC4ZC54Z.mjs +662 -0
  72. package/dist/kernel-plugin.js +6862 -0
  73. package/dist/keys-WKOQ4KQE.mjs +71 -0
  74. package/dist/lines-I6ZB2IOU.mjs +56 -0
  75. package/dist/{link-76Z6V6CJ.mjs → link-TE2FUX74.mjs} +6 -6
  76. package/dist/{lint-DDZ7HUQN.mjs → lint-735IPMC6.mjs} +2 -2
  77. package/dist/{list-2MFOQKKQ.mjs → list-CHYY2P4T.mjs} +7 -11
  78. package/dist/lock-XVR3RRZ6.mjs +57 -0
  79. package/dist/{login-RLMDEWAL.mjs → login-LW7CHZDZ.mjs} +10 -8
  80. package/dist/{logout-Z57X6HPE.mjs → logout-6U6OP5DM.mjs} +2 -2
  81. package/dist/{logs-TNDM4RFE.mjs → logs-HKH4H6PT.mjs} +5 -5
  82. package/dist/logs-SCQC5HNO.mjs +44 -0
  83. package/dist/mcp-VRHQOEGG.mjs +1077 -0
  84. package/dist/{mock-EVER34IX.mjs → mock-5H3CVPHC.mjs} +2 -2
  85. package/dist/outdated-T7QW6F3Z.mjs +58 -0
  86. package/dist/port-24R7ZNP4.mjs +2408 -0
  87. package/dist/{projects-YL4T24VV.mjs → projects-HYITVEXS.mjs} +6 -6
  88. package/dist/publish-DZRR5A5X.mjs +20 -0
  89. package/dist/remix-4HVXRIEB.mjs +125 -0
  90. package/dist/repo-FG3CMZQS.mjs +9 -0
  91. package/dist/report-M7F4ZYP7.mjs +2 -0
  92. package/dist/rollback-H7Q4XYGX.mjs +43 -0
  93. package/dist/{rollback-47VQ4HJK.mjs → rollback-OM64O67F.mjs} +6 -6
  94. package/dist/scene-QTHT3ZPL.mjs +324 -0
  95. package/dist/{status-TWPOMWNA.mjs → status-5D4RR3MM.mjs} +5 -5
  96. package/dist/status-AKI6E3JK.mjs +18 -0
  97. package/dist/test-W6MURUGZ.mjs +233 -0
  98. package/dist/testers-EI32JB5F.mjs +49 -0
  99. package/dist/{unlink-H3BO3DOQ.mjs → unlink-BND47IWW.mjs} +2 -2
  100. package/dist/{update-FLY46XI3.mjs → update-XKKFREKH.mjs} +4 -4
  101. package/dist/{whoami-CQPPARRS.mjs → whoami-WHLGCVRC.mjs} +3 -3
  102. package/dist/workshop-F2T4IDOU.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-7O65HY6C.mjs +0 -8
  118. package/dist/explain-DLRUUCNS.mjs +0 -251
  119. package/dist/introspect-RC265ACF.mjs +0 -9
  120. package/dist/repo-UUT3AZ3L.mjs +0 -9
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { managedProviderForHost } from './chunk-UTD34C2H.mjs';
3
- import { REPO_PROVIDER, isManagedRepoProvider } from './chunk-2MKZKUVH.mjs';
4
- import { parseArgs, flagString, flagBool } from './chunk-5KYR6WJB.mjs';
5
- import { ApiClient } from './chunk-NYXA6X56.mjs';
6
- import { readAuth } from './chunk-MLE4MVYC.mjs';
7
- import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-3QUK5BPY.mjs';
2
+ import { managedProviderForHost } from './chunk-EOOOXVHR.mjs';
3
+ import { REPO_PROVIDER, isManagedRepoProvider } from './chunk-LLRUOIMU.mjs';
4
+ import { parseArgs, flagString, flagBool } from './chunk-XQAHREKO.mjs';
5
+ import { ApiClient } from './chunk-XBQ4LO2N.mjs';
6
+ import { readAuth } from './chunk-GGPN4QYQ.mjs';
7
+ import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-I7GEHLDD.mjs';
8
8
 
9
9
  // src/commands/projects.ts
10
10
  var SUB_LS = "ls";
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ export { checkAllowance, run as default, keyLabel, parseChannel, progressPrinter, publishProject, registeredSigningKey } from './chunk-TYR4Q37L.mjs';
3
+ import './chunk-XZG3DTXV.mjs';
4
+ import './chunk-JNCEKW2Y.mjs';
5
+ import './chunk-BTNVYAC4.mjs';
6
+ import './chunk-VHK7WBO3.mjs';
7
+ import './chunk-454RQ6NR.mjs';
8
+ import './chunk-JKECUAAV.mjs';
9
+ import './chunk-HQPZQIWW.mjs';
10
+ import './chunk-KQNZKV6E.mjs';
11
+ import './chunk-QVR6V6QP.mjs';
12
+ import './chunk-N2WZJX5P.mjs';
13
+ import './chunk-EYEMPIMP.mjs';
14
+ import './chunk-BGM7CH5G.mjs';
15
+ import './chunk-25ZPFHLF.mjs';
16
+ import './chunk-SGT5IJVW.mjs';
17
+ import './chunk-XQAHREKO.mjs';
18
+ import './chunk-XBQ4LO2N.mjs';
19
+ import './chunk-GGPN4QYQ.mjs';
20
+ import './chunk-I7GEHLDD.mjs';
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ import { CliError, CLI_ERROR_CODE, info, bold, result, success, dim } from './chunk-I7GEHLDD.mjs';
3
+ import { existsSync, statSync, readFileSync, writeFileSync } from 'fs';
4
+ import path from 'path';
5
+ import { SLOT_TEMPLATES, templateFromSchema, decodeRemix, remixDigest, memoryRemixSources, assignSlots, remix, slotChoices, templateSlotsEnabled, TemplateSlotError, describeIssue, TEMPLATE_SLOTS_FLAG } from '@cimplify/sdk/game/kit/slots';
6
+
7
+ var SCHEMA_FILE = "template.json";
8
+ var SET_FLAG = "--set";
9
+ var PARENT_FLAG = "--parent";
10
+ var OUT_FLAG = "--out";
11
+ var GLOBAL_FLAGS = /* @__PURE__ */ new Set(["--json", "--yes", "-y"]);
12
+ var UTF8 = "utf8";
13
+ var DIGEST_PREVIEW = 19;
14
+ function invalid(message, remediation) {
15
+ return new CliError(CLI_ERROR_CODE.INVALID_INPUT, message, remediation === void 0 ? {} : { remediation });
16
+ }
17
+ function parseRemixArgs(argv) {
18
+ const sets = [];
19
+ let template = null;
20
+ let parent = null;
21
+ let out = null;
22
+ for (let i = 0; i < argv.length; i++) {
23
+ const arg = argv[i];
24
+ const [flag, inline] = arg.startsWith("--") && arg.includes("=") && !arg.startsWith(`${SET_FLAG}=`) ? [arg.slice(0, arg.indexOf("=")), arg.slice(arg.indexOf("=") + 1)] : [arg, null];
25
+ const value = () => {
26
+ if (inline !== null) return inline;
27
+ const next = argv[++i];
28
+ if (next === void 0) throw invalid(`${flag} needs a value`);
29
+ return next;
30
+ };
31
+ if (GLOBAL_FLAGS.has(arg)) continue;
32
+ if (arg.startsWith(`${SET_FLAG}=`)) sets.push(arg.slice(SET_FLAG.length + 1));
33
+ else if (flag === SET_FLAG) sets.push(value());
34
+ else if (flag === PARENT_FLAG) parent = value();
35
+ else if (flag === OUT_FLAG) out = value();
36
+ else if (arg.startsWith("--")) throw invalid(`unknown flag ${flag}`, "cimplify remix <template> [--set slot=value]... [--parent <remix.json>] [--out <remix.json>]");
37
+ else if (template === null) template = arg;
38
+ else throw invalid(`unexpected argument ${arg}`);
39
+ }
40
+ return { template, sets, parent, out };
41
+ }
42
+ function readJson(file, what) {
43
+ try {
44
+ return JSON.parse(readFileSync(file, UTF8));
45
+ } catch (error) {
46
+ throw invalid(`could not read ${what} ${file}: ${error.message}`);
47
+ }
48
+ }
49
+ function slotError(error) {
50
+ if (error instanceof TemplateSlotError || error instanceof Error && error.name === "TemplateSlotError") return invalid(error.issues.map(describeIssue).join("\n"), "run cimplify remix <template> without --set to list each slot and what fits it");
51
+ if (error instanceof Error && error.name === "RemixError") return invalid(error.message);
52
+ return error;
53
+ }
54
+ function loadTemplate(name, cwd) {
55
+ if (name !== null && SLOT_TEMPLATES[name] !== void 0) return SLOT_TEMPLATES[name];
56
+ const target = path.resolve(cwd, name ?? ".");
57
+ const file = existsSync(target) && statSync(target).isDirectory() ? path.join(target, SCHEMA_FILE) : target;
58
+ if (!existsSync(file)) {
59
+ const known = Object.keys(SLOT_TEMPLATES).join(", ");
60
+ throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `${name ?? "this folder"} is not a slotted template: not one of ${known} and no ${SCHEMA_FILE} at ${file}`, {
61
+ remediation: `name a built-in template (${known}) or a folder with ${SCHEMA_FILE}`
62
+ });
63
+ }
64
+ try {
65
+ return templateFromSchema(readJson(file, "template schema"));
66
+ } catch (error) {
67
+ throw slotError(error);
68
+ }
69
+ }
70
+ function loadParent(file) {
71
+ const raw = readJson(file, "parent remix");
72
+ if (raw === null || typeof raw !== "object" || raw.manifest === void 0) throw invalid(`${file} is not a remix written by cimplify remix --out`);
73
+ try {
74
+ const manifest = decodeRemix(raw.manifest);
75
+ const lineage = (raw.lineage ?? []).map((m) => decodeRemix(m));
76
+ return { template: manifest.template, digest: remixDigest(manifest), manifest, lineage, content: raw.content ?? {} };
77
+ } catch (error) {
78
+ throw slotError(error);
79
+ }
80
+ }
81
+ function remixBundle(t, sets, parent, readFile) {
82
+ const sources = memoryRemixSources();
83
+ if (parent !== null) for (const manifest of [parent.manifest, ...parent.lineage]) sources.add({ manifest, digest: remixDigest(manifest), content: parent.content });
84
+ try {
85
+ const set = assignSlots(t, sets, { readFile });
86
+ const made = remix(t, set, { parent: parent?.manifest ?? null, sources });
87
+ return {
88
+ template: t.ref,
89
+ digest: made.digest,
90
+ manifest: made.manifest,
91
+ lineage: parent === null ? [] : [parent.manifest, ...parent.lineage],
92
+ content: { ...parent?.content ?? {}, ...made.content }
93
+ };
94
+ } catch (error) {
95
+ throw slotError(error);
96
+ }
97
+ }
98
+ function describeSlots(t) {
99
+ return Object.keys(t.slots).map((slot) => `${slot.padEnd(8)} ${slotChoices(t, slot)}`);
100
+ }
101
+ async function run(argv) {
102
+ if (!templateSlotsEnabled(process.env)) {
103
+ throw invalid(`cimplify remix is switched off by ${TEMPLATE_SLOTS_FLAG}`, `unset ${TEMPLATE_SLOTS_FLAG} to use template slots`);
104
+ }
105
+ const args = parseRemixArgs(argv);
106
+ const cwd = process.cwd();
107
+ const t = loadTemplate(args.template, cwd);
108
+ if (args.sets.length === 0 && args.parent === null) {
109
+ info(bold(`${t.title} (${t.ref})`));
110
+ for (const line of describeSlots(t)) info(line);
111
+ result({ template: t.ref, slots: Object.fromEntries(Object.keys(t.slots).map((slot) => [slot, slotChoices(t, slot)])) });
112
+ return;
113
+ }
114
+ const parent = args.parent === null ? null : loadParent(path.resolve(cwd, args.parent));
115
+ const bundle = remixBundle(t, args.sets, parent, (file) => readFileSync(path.resolve(cwd, file), UTF8));
116
+ if (args.out !== null) writeFileSync(path.resolve(cwd, args.out), `${JSON.stringify(bundle, null, 2)}
117
+ `);
118
+ success(`remix ${bundle.digest.slice(0, DIGEST_PREVIEW)} of ${bundle.template}`);
119
+ for (const [slot, ref] of Object.entries(bundle.manifest.slots)) info(`${slot.padEnd(8)} ${typeof ref === "string" ? ref : JSON.stringify(ref)}`);
120
+ if (bundle.lineage.length > 0) info(dim(`remixes ${bundle.lineage.map((m) => remixDigest(m).slice(0, DIGEST_PREVIEW)).join(" <- ")}`));
121
+ if (args.out !== null) info(dim(`wrote ${args.out}`));
122
+ result(bundle);
123
+ }
124
+
125
+ export { run as default, describeSlots, loadParent, loadTemplate, parseRemixArgs, remixBundle };
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ export { run as default, fetchCloneToken, fetchRepoRecord } from './chunk-QQWYQ2HS.mjs';
3
+ import './chunk-XASDB7YS.mjs';
4
+ import './chunk-EOOOXVHR.mjs';
5
+ import './chunk-LLRUOIMU.mjs';
6
+ import './chunk-XQAHREKO.mjs';
7
+ import './chunk-XBQ4LO2N.mjs';
8
+ import './chunk-GGPN4QYQ.mjs';
9
+ import './chunk-I7GEHLDD.mjs';
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export { compactReport, inspectSnapshot, patchesOf } from './chunk-THATLMEX.mjs';
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+ import { parseChannel } from './chunk-TYR4Q37L.mjs';
3
+ import { renderStatus } from './chunk-6KKLF5KG.mjs';
4
+ import { remoteFromEnv } from './chunk-XZG3DTXV.mjs';
5
+ import { readInteractiveId, remoteCall } from './chunk-JNCEKW2Y.mjs';
6
+ import { requireInteractiveProject } from './chunk-BTNVYAC4.mjs';
7
+ import './chunk-VHK7WBO3.mjs';
8
+ import './chunk-454RQ6NR.mjs';
9
+ import './chunk-JKECUAAV.mjs';
10
+ import './chunk-HQPZQIWW.mjs';
11
+ import './chunk-KQNZKV6E.mjs';
12
+ import './chunk-QVR6V6QP.mjs';
13
+ import './chunk-N2WZJX5P.mjs';
14
+ import './chunk-EYEMPIMP.mjs';
15
+ import './chunk-BGM7CH5G.mjs';
16
+ import './chunk-25ZPFHLF.mjs';
17
+ import './chunk-SGT5IJVW.mjs';
18
+ import { parseArgs, flagString } from './chunk-XQAHREKO.mjs';
19
+ import './chunk-XBQ4LO2N.mjs';
20
+ import './chunk-GGPN4QYQ.mjs';
21
+ import { CliError, CLI_ERROR_CODE, success, info, result } from './chunk-I7GEHLDD.mjs';
22
+
23
+ // src/interactives/commands/rollback.ts
24
+ async function rollbackInteractive(root, remote, revision, channel) {
25
+ const id = await readInteractiveId(root);
26
+ return remoteCall(() => remote.rollback(id, revision, channel));
27
+ }
28
+ async function run(argv) {
29
+ const args = parseArgs(argv);
30
+ const revision = args.positional[0];
31
+ if (!revision) {
32
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "usage: cimplify rollback <revision> [--channel live|test]");
33
+ }
34
+ const root = process.cwd();
35
+ requireInteractiveProject(root, "rollback");
36
+ const channel = parseChannel(flagString(args, "channel"));
37
+ const status = await rollbackInteractive(root, await remoteFromEnv(), revision, channel);
38
+ success(`${channel} now points at ${revision}`);
39
+ for (const line of renderStatus(status)) info(line);
40
+ result(status);
41
+ }
42
+
43
+ export { run as default, rollbackInteractive };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { pollDeployment } from './chunk-O2TO2J4I.mjs';
3
- import { DEPLOYMENT_STATUS, DEPLOY_TRIGGER } from './chunk-2MKZKUVH.mjs';
4
- import { parseArgs, flagBool } from './chunk-5KYR6WJB.mjs';
5
- import { ApiClient } from './chunk-NYXA6X56.mjs';
6
- import { readAuth, readProjectLink, writeProjectState } from './chunk-MLE4MVYC.mjs';
7
- import { CliError, CLI_ERROR_CODE, step, success, info, dim, result, EXIT_CODE } from './chunk-3QUK5BPY.mjs';
2
+ import { pollDeployment } from './chunk-6CQMRZ2W.mjs';
3
+ import { DEPLOYMENT_STATUS, DEPLOY_TRIGGER } from './chunk-LLRUOIMU.mjs';
4
+ import { parseArgs, flagBool } from './chunk-XQAHREKO.mjs';
5
+ import { ApiClient } from './chunk-XBQ4LO2N.mjs';
6
+ import { readAuth, readProjectLink, writeProjectState } from './chunk-GGPN4QYQ.mjs';
7
+ import { CliError, CLI_ERROR_CODE, step, success, info, dim, result, EXIT_CODE } from './chunk-I7GEHLDD.mjs';
8
8
 
9
9
  // src/commands/rollback.ts
10
10
  var FLAG_NO_POLL = "no-poll";
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env node
2
+ import { scenesEnabled, SCENES_FLAG, compileSites, formatSceneDiagnostic } from './chunk-VHK7WBO3.mjs';
3
+ import './chunk-SGT5IJVW.mjs';
4
+ import { parseArgs, flagString, flagBool } from './chunk-XQAHREKO.mjs';
5
+ import { ApiClient, isServiceUnavailable } from './chunk-XBQ4LO2N.mjs';
6
+ import { readAuthOrNull } from './chunk-GGPN4QYQ.mjs';
7
+ import { CliError, CLI_ERROR_CODE, result, info, dim, warn, success, failure, bold } from './chunk-I7GEHLDD.mjs';
8
+ import { existsSync, promises } from 'fs';
9
+ import path2 from 'path';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ var RESOLVE_PATH = "/v1/content/scenes/resolve";
13
+ var RESOLVE_USAGE = "cimplify scene resolve <file> [--json] [--out <assets.json>] [--tier low|mid|high] [--no-generate] [--wait <seconds>] [--export name]";
14
+ var ASSETS_SUFFIX = ".assets.json";
15
+ var DEFAULT_WAIT_MS = 15 * 60 * 1e3;
16
+ var POLL_MS = 5e3;
17
+ var ASSETS_VERSION = 1;
18
+ var BUSY_ATTEMPTS = 5;
19
+ var BUSY_PAUSE_MS = 1e3;
20
+ var MM_PER_METRE = 1e3;
21
+ var MS_PER_SECOND = 1e3;
22
+ var DEFAULT_STYLE = "default";
23
+ var STYLE_SHAPE = /^[a-z0-9_-]+$/;
24
+ var TIERS = ["low", "mid", "high"];
25
+ var SIZE_CEILINGS = [
26
+ ["tiny", 0.5],
27
+ ["small", 1.5],
28
+ ["medium", 4],
29
+ ["large", 12]
30
+ ];
31
+ var UNRESOLVED_EXIT = 1;
32
+ var HttpSceneAssetsRemote = class {
33
+ client;
34
+ constructor(client) {
35
+ this.client = client;
36
+ }
37
+ async resolve(requests, retry) {
38
+ for (let attempt = 1; ; attempt++) {
39
+ try {
40
+ const body = await this.client.post(RESOLVE_PATH, { requests, retry });
41
+ return body.resolutions;
42
+ } catch (error) {
43
+ if (!isServiceUnavailable(error) || attempt >= BUSY_ATTEMPTS) throw error;
44
+ await new Promise((done) => setTimeout(done, BUSY_PAUSE_MS * attempt));
45
+ }
46
+ }
47
+ }
48
+ };
49
+ function sizeClassOf(footprintMm) {
50
+ const metres = Math.max(footprintMm[0], footprintMm[1]) / MM_PER_METRE;
51
+ for (const [size, ceiling] of SIZE_CEILINGS) if (metres < ceiling) return size;
52
+ return "huge";
53
+ }
54
+ function styleOf(style) {
55
+ const trimmed = style.trim().toLowerCase();
56
+ return trimmed.length > 0 && STYLE_SHAPE.test(trimmed) ? trimmed : DEFAULT_STYLE;
57
+ }
58
+ function kindsOfWire(wire) {
59
+ return {
60
+ scene: wire.name,
61
+ style: styleOf(wire.style),
62
+ kinds: wire.kinds.map((k) => ({ name: k.name, footprint_mm: [k.footprint[0], k.footprint[1]], height_mm: k.height }))
63
+ };
64
+ }
65
+ function kindsOfReport(report, catalogue) {
66
+ const names = [...new Set(report.placements.map((p) => p.kind))].sort();
67
+ const kinds = names.map((name) => {
68
+ const meta = catalogue[name];
69
+ if (meta === void 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `the report names ${name}, which is not in the catalogue`, { remediation: "resolve from the scene source or its wire IR instead" });
70
+ return {
71
+ name,
72
+ footprint_mm: [Math.round(meta.footprint[0] * MM_PER_METRE), Math.round(meta.footprint[1] * MM_PER_METRE)],
73
+ height_mm: Math.round(meta.height * MM_PER_METRE)
74
+ };
75
+ });
76
+ return { scene: report.scene, style: styleOf(report.style), kinds };
77
+ }
78
+ function requestsOf(kinds, options) {
79
+ return kinds.kinds.map((k) => ({
80
+ kind: k.name,
81
+ style: kinds.style,
82
+ size_class: sizeClassOf(k.footprint_mm),
83
+ dimensions: { footprint_mm: k.footprint_mm, height_mm: k.height_mm },
84
+ constraints: {
85
+ ...options.tier === void 0 ? {} : { tier: options.tier },
86
+ allow_generation: options.allowGeneration,
87
+ human_made_only: false
88
+ }
89
+ }));
90
+ }
91
+ async function resolveAll(requests, remote, options) {
92
+ const resolutions = [...await remote.resolve(requests, true)];
93
+ const deadline = options.now() + options.waitMs;
94
+ for (; ; ) {
95
+ const open = resolutions.map((r, i) => r.status === "pending" ? i : -1).filter((i) => i >= 0);
96
+ if (open.length === 0 || options.now() >= deadline) return resolutions;
97
+ options.onPending?.(open.length);
98
+ await options.sleep(options.pollMs);
99
+ const again = await remote.resolve(
100
+ open.map((i) => requests[i]),
101
+ false
102
+ );
103
+ open.forEach((at, i) => {
104
+ const earlier = resolutions[at];
105
+ const next = again[i];
106
+ resolutions[at] = { ...next, units_charged: earlier.units_charged + next.units_charged };
107
+ });
108
+ }
109
+ }
110
+ function assetsReport(kinds, resolutions) {
111
+ const assets = kinds.kinds.map((k, i) => {
112
+ const r = resolutions[i];
113
+ return {
114
+ kind: k.name,
115
+ status: r.status,
116
+ cached: r.cached,
117
+ units_charged: r.units_charged,
118
+ ...r.asset === void 0 ? {} : { asset: r.asset },
119
+ ...r.reason === void 0 ? {} : { reason: r.reason }
120
+ };
121
+ });
122
+ const unresolved = assets.filter((a) => a.status !== "resolved").map((a) => a.kind);
123
+ return {
124
+ version: ASSETS_VERSION,
125
+ scene: kinds.scene,
126
+ style: kinds.style,
127
+ status: unresolved.length === 0 ? "resolved" : "partial",
128
+ units_charged: assets.reduce((sum, a) => sum + a.units_charged, 0),
129
+ assets,
130
+ models: assets.flatMap((a) => a.asset === void 0 ? [] : [{ name: a.kind, item: `${a.asset.item}@${a.asset.version}`, version_digest: a.asset.version_digest }]),
131
+ unresolved
132
+ };
133
+ }
134
+ function isWire(value) {
135
+ return typeof value === "object" && value !== null && Array.isArray(value.kinds) && typeof value.name === "string";
136
+ }
137
+ function isReport(value) {
138
+ return typeof value === "object" && value !== null && Array.isArray(value.placements) && typeof value.scene === "string";
139
+ }
140
+ async function sceneKindsOf(file, exportName) {
141
+ const absolute = path2.resolve(file);
142
+ const text = await promises.readFile(absolute, "utf8").catch(() => {
143
+ throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `cannot read ${file}`);
144
+ });
145
+ const sdk = await import('@cimplify/sdk/game');
146
+ if (absolute.endsWith(".json")) {
147
+ let parsed;
148
+ try {
149
+ parsed = JSON.parse(text);
150
+ } catch {
151
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `${file} is not JSON`);
152
+ }
153
+ if (isWire(parsed)) return kindsOfWire(parsed);
154
+ if (isReport(parsed)) return kindsOfReport(parsed, sdk.STARTER_CATALOGUE);
155
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `${file} is neither a scene wire IR nor a placement report`);
156
+ }
157
+ const relative = path2.relative(process.cwd(), absolute) || file;
158
+ const compiled = compileSites(relative, text, (def) => sdk.compileScene(def));
159
+ const { pickSite: pickSite2 } = await import('./scene-QTHT3ZPL.mjs');
160
+ const site = pickSite2(compiled.sites, exportName);
161
+ const wire = compiled.compiled[compiled.sites.indexOf(site)]?.wire ?? null;
162
+ if (wire === null) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `${relative}: the scene does not compile; run cimplify scene solve for its diagnostics`);
163
+ return kindsOfWire(wire);
164
+ }
165
+ function tierOf(raw) {
166
+ if (raw === void 0) return void 0;
167
+ if (!TIERS.includes(raw)) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `--tier must be one of ${TIERS.join(", ")}`);
168
+ return raw;
169
+ }
170
+ function waitOf(raw) {
171
+ if (raw === void 0) return DEFAULT_WAIT_MS;
172
+ const seconds = Number(raw);
173
+ if (!Number.isFinite(seconds) || seconds < 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "--wait must be a number of seconds");
174
+ return seconds * MS_PER_SECOND;
175
+ }
176
+ function describe(a) {
177
+ if (a.asset !== void 0) {
178
+ const origin = a.asset.from === "generated" ? "generated" : "library";
179
+ return `${a.asset.item}@${a.asset.version} ${dim(`${origin}, fit ${a.asset.fit}${a.cached ? ", cached" : ""}`)}`;
180
+ }
181
+ return a.status === "pending" ? "still generating" : `unresolved${a.reason === void 0 ? "" : `: ${a.reason}`}`;
182
+ }
183
+ async function runSceneResolve(argv, remote) {
184
+ const args = parseArgs(argv);
185
+ const [file] = args.positional;
186
+ if (file === void 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `usage: ${RESOLVE_USAGE}`);
187
+ const kinds = await sceneKindsOf(file, flagString(args, "export"));
188
+ const requests = requestsOf(kinds, { tier: tierOf(flagString(args, "tier")), allowGeneration: !flagBool(args, "no-generate") });
189
+ if (requests.length === 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `${file} places no objects`);
190
+ let assets = remote;
191
+ if (assets === void 0) {
192
+ const auth = await readAuthOrNull();
193
+ if (auth === null) throw new CliError(CLI_ERROR_CODE.NOT_LOGGED_IN, "resolving scene assets needs a signed-in account; run cimplify login");
194
+ assets = new HttpSceneAssetsRemote(ApiClient.fromAuth(auth));
195
+ }
196
+ const resolutions = await resolveAll(requests, assets, {
197
+ waitMs: waitOf(flagString(args, "wait")),
198
+ pollMs: POLL_MS,
199
+ sleep: (ms) => new Promise((done) => setTimeout(done, ms)),
200
+ now: () => Date.now(),
201
+ onPending: (pending) => info(dim(`${pending} asset${pending === 1 ? "" : "s"} still generating`))
202
+ });
203
+ const report = assetsReport(kinds, resolutions);
204
+ const out = flagString(args, "out") ?? `${file.replace(/\.[^./]+$/, "")}${ASSETS_SUFFIX}`;
205
+ await promises.writeFile(out, `${JSON.stringify(report, null, 2)}
206
+ `);
207
+ for (const a of report.assets) (a.asset === void 0 ? warn : info)(` ${a.kind.padEnd(16)}${describe(a)}`);
208
+ const head = `${report.scene}: ${report.models.length}/${report.assets.length} kinds resolved, ${report.units_charged} AI units charged, written to ${out}`;
209
+ if (report.status === "resolved") success(head);
210
+ else failure(head);
211
+ result(report);
212
+ if (report.status !== "resolved") process.exitCode = UNRESOLVED_EXIT;
213
+ return report;
214
+ }
215
+
216
+ // src/interactives/commands/scene.ts
217
+ var SOLVER_ENV = "CIMPLIFY_SCENE_SOLVER_WASM";
218
+ var SOLVER_ARTIFACT = path2.join("target", "wasm32-unknown-unknown", "release", "engine_scene.wasm");
219
+ var BUILD_HINT = "cargo build -p engine_scene --features wasm --target wasm32-unknown-unknown --release";
220
+ var USAGE = "cimplify scene solve <file> [--json] [--seed n] [--export name]";
221
+ var SOLVE = "solve";
222
+ var RESOLVE = "resolve";
223
+ var UNSATISFIED_EXIT = 1;
224
+ var MS_DIGITS = 3;
225
+ function upward(start) {
226
+ let dir = path2.resolve(start);
227
+ for (; ; ) {
228
+ const candidate = path2.join(dir, SOLVER_ARTIFACT);
229
+ if (existsSync(candidate)) return candidate;
230
+ const parent = path2.dirname(dir);
231
+ if (parent === dir) return null;
232
+ dir = parent;
233
+ }
234
+ }
235
+ function locateSolver(env = process.env, cwd = process.cwd()) {
236
+ const explicit = env[SOLVER_ENV];
237
+ if (explicit !== void 0 && explicit.length > 0) {
238
+ if (!existsSync(explicit)) throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `${SOLVER_ENV} points at ${explicit}, which does not exist`, { remediation: BUILD_HINT });
239
+ return explicit;
240
+ }
241
+ const found = upward(cwd) ?? upward(path2.dirname(fileURLToPath(import.meta.url)));
242
+ if (found === null) throw new CliError(CLI_ERROR_CODE.NOT_FOUND, "the scene solver module was not found", { remediation: `${BUILD_HINT}, or set ${SOLVER_ENV}` });
243
+ return found;
244
+ }
245
+ function pickSite(sites, wanted) {
246
+ const named = sites.filter((s) => s.definition !== null);
247
+ if (wanted !== void 0) {
248
+ const hit = sites.find((s) => s.binding === wanted || s.definition?.name === wanted);
249
+ if (hit === void 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `no scene named ${wanted}`, { remediation: `scenes here: ${named.map((s) => s.binding ?? s.definition?.name).join(", ") || "none"}` });
250
+ return hit;
251
+ }
252
+ if (sites.length === 1) return sites[0];
253
+ if (sites.length === 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "the file declares no scene(...)", { remediation: 'import { scene } from "@cimplify/sdk/game" and export a scene' });
254
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `the file declares ${sites.length} scenes`, { remediation: `pick one with --export ${named.map((s) => s.binding ?? s.definition?.name).join(" | ")}` });
255
+ }
256
+ function renderReport(report) {
257
+ const head = `${report.scene}: ${report.status}, ${report.placements.length} placements, seed ${report.seed}, try ${report.try}, score ${report.score}`;
258
+ if (report.status === "solved") success(head);
259
+ else failure(head);
260
+ const width = Math.max(4, ...report.placements.map((p) => p.name.length)) + 2;
261
+ for (const p of report.placements) {
262
+ const at = p.at.map((v) => v.toFixed(2)).join(", ");
263
+ const flag = p.violations.length > 0 ? ` ${p.violations.join(", ")}` : "";
264
+ info(` ${p.name.padEnd(width)}${dim(p.kind)} [${at}] ${p.yaw} deg${p.support === null ? "" : ` on ${p.support}`}${flag}`);
265
+ }
266
+ for (const v of report.violations) warn(`${v.object}: ${v.code}${v.relation === "" ? "" : ` (${v.relation})`}${v.amount > 0 ? ` by ${v.amount} m` : ""}`);
267
+ if (report.conflicts !== void 0) {
268
+ failure(`minimal conflicting set: ${bold(report.conflicts.objects.join(", "))}`);
269
+ for (const r of report.conflicts.reasons) info(` ${r}`);
270
+ }
271
+ info(dim(`digest ${report.digest}`));
272
+ }
273
+ function reportDiagnostics(diagnostics) {
274
+ for (const d of diagnostics) (d.severity === "error" ? failure : warn)(formatSceneDiagnostic(d));
275
+ }
276
+ async function run(argv) {
277
+ if (!scenesEnabled()) {
278
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `generative scenes are switched off by ${SCENES_FLAG}`, { remediation: `unset ${SCENES_FLAG}` });
279
+ }
280
+ const args = parseArgs(argv);
281
+ const [action, file] = args.positional;
282
+ if (action === RESOLVE) {
283
+ await runSceneResolve(argv.slice(argv.indexOf(RESOLVE) + 1));
284
+ return;
285
+ }
286
+ if (action !== SOLVE || file === void 0) throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `usage: ${USAGE}
287
+ ${RESOLVE_USAGE}`);
288
+ const seedFlag = flagString(args, "seed");
289
+ const seed = seedFlag === void 0 ? void 0 : Number(seedFlag);
290
+ if (seed !== void 0 && (!Number.isInteger(seed) || seed < 0 || seed > 4294967295)) {
291
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "--seed must be an integer from 0 to 4294967295");
292
+ }
293
+ const absolute = path2.resolve(file);
294
+ const text = await promises.readFile(absolute, "utf8").catch(() => {
295
+ throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `cannot read ${file}`);
296
+ });
297
+ const sdk = await import('@cimplify/sdk/game');
298
+ const started = performance.now();
299
+ const relative = path2.relative(process.cwd(), absolute) || file;
300
+ const compiled = compileSites(relative, text, (def) => sdk.compileScene(def));
301
+ const site = pickSite(compiled.sites, flagString(args, "export"));
302
+ const index = compiled.sites.indexOf(site);
303
+ const mine = compiled.diagnostics.filter((d) => d.scene === (site.definition?.name ?? site.binding ?? "scene"));
304
+ reportDiagnostics(mine);
305
+ const wire = compiled.compiled[index]?.wire ?? null;
306
+ if (wire === null || mine.some((d) => d.severity === "error")) {
307
+ result({ status: "invalid", diagnostics: mine });
308
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `${relative}: the scene does not compile`, { details: mine });
309
+ }
310
+ const solver = await sdk.createSceneSolver(await promises.readFile(locateSolver()));
311
+ const setup = performance.now();
312
+ const solved = solver.solve(wire, seed);
313
+ const done = performance.now();
314
+ const report = {
315
+ ...solved.report,
316
+ timings: { setup_ms: Number((setup - started).toFixed(MS_DIGITS)), solve_ms: Number((done - setup).toFixed(MS_DIGITS)) }
317
+ };
318
+ renderReport(report);
319
+ info(dim(`setup ${report.timings.setup_ms} ms, solve ${report.timings.solve_ms} ms`));
320
+ result(report);
321
+ if (report.status !== "solved") process.exitCode = UNSATISFIED_EXIT;
322
+ }
323
+
324
+ export { SOLVER_ENV, run as default, locateSolver, pickSite };
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { DEPLOYMENT_STATUS } from './chunk-2MKZKUVH.mjs';
3
- import { parseArgs } from './chunk-5KYR6WJB.mjs';
4
- import { ApiClient } from './chunk-NYXA6X56.mjs';
5
- import { readAuth, readProjectLink, readProjectState } from './chunk-MLE4MVYC.mjs';
6
- import { bold, dim, info, result } from './chunk-3QUK5BPY.mjs';
2
+ import { DEPLOYMENT_STATUS } from './chunk-LLRUOIMU.mjs';
3
+ import { parseArgs } from './chunk-XQAHREKO.mjs';
4
+ import { ApiClient } from './chunk-XBQ4LO2N.mjs';
5
+ import { readAuth, readProjectLink, readProjectState } from './chunk-GGPN4QYQ.mjs';
6
+ import { bold, dim, info, result } from './chunk-I7GEHLDD.mjs';
7
7
 
8
8
  // src/commands/status.ts
9
9
  var QUERY_LIMIT = "limit";
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ export { run as default, interactiveStatus, renderStatus } from './chunk-6KKLF5KG.mjs';
3
+ import './chunk-XZG3DTXV.mjs';
4
+ import './chunk-JNCEKW2Y.mjs';
5
+ import './chunk-BTNVYAC4.mjs';
6
+ import './chunk-VHK7WBO3.mjs';
7
+ import './chunk-454RQ6NR.mjs';
8
+ import './chunk-JKECUAAV.mjs';
9
+ import './chunk-HQPZQIWW.mjs';
10
+ import './chunk-KQNZKV6E.mjs';
11
+ import './chunk-N2WZJX5P.mjs';
12
+ import './chunk-EYEMPIMP.mjs';
13
+ import './chunk-BGM7CH5G.mjs';
14
+ import './chunk-25ZPFHLF.mjs';
15
+ import './chunk-SGT5IJVW.mjs';
16
+ import './chunk-XBQ4LO2N.mjs';
17
+ import './chunk-GGPN4QYQ.mjs';
18
+ import './chunk-I7GEHLDD.mjs';