@lotics/cli 0.88.0 → 0.89.1

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 (87) hide show
  1. package/dist/render_page.js +100 -100
  2. package/dist/src/cli.js +162 -100
  3. package/dist/{client.d.ts → src/client.d.ts} +9 -1
  4. package/dist/src/package_content_types.d.ts +70 -0
  5. package/dist/src/package_content_types.js +12 -0
  6. package/package.json +2 -2
  7. package/dist/app_commands.d.ts +0 -401
  8. package/dist/app_commands.js +0 -1520
  9. package/dist/app_commands.test.d.ts +0 -1
  10. package/dist/app_commands.test.js +0 -898
  11. package/dist/app_workflow_check.d.ts +0 -77
  12. package/dist/app_workflow_check.js +0 -169
  13. package/dist/app_workflow_check.test.d.ts +0 -1
  14. package/dist/app_workflow_check.test.js +0 -166
  15. package/dist/args.d.ts +0 -42
  16. package/dist/args.js +0 -121
  17. package/dist/args.test.d.ts +0 -1
  18. package/dist/args.test.js +0 -88
  19. package/dist/child_env.d.ts +0 -13
  20. package/dist/child_env.js +0 -24
  21. package/dist/cli.d.ts +0 -2
  22. package/dist/cli.js +0 -1095
  23. package/dist/cli_dispatch.test.d.ts +0 -1
  24. package/dist/cli_dispatch.test.js +0 -89
  25. package/dist/client.test.d.ts +0 -1
  26. package/dist/client.test.js +0 -47
  27. package/dist/config.d.ts +0 -124
  28. package/dist/config.js +0 -315
  29. package/dist/config.test.d.ts +0 -1
  30. package/dist/config.test.js +0 -319
  31. package/dist/dev/file_relay.d.ts +0 -39
  32. package/dist/dev/file_relay.js +0 -87
  33. package/dist/dev/file_relay.test.d.ts +0 -1
  34. package/dist/dev/file_relay.test.js +0 -87
  35. package/dist/dev/rpc_handler.d.ts +0 -21
  36. package/dist/dev/rpc_handler.js +0 -166
  37. package/dist/dev/rpc_handler.test.d.ts +0 -1
  38. package/dist/dev/rpc_handler.test.js +0 -107
  39. package/dist/dev/server.d.ts +0 -75
  40. package/dist/dev/server.js +0 -443
  41. package/dist/dev/upload_relay.d.ts +0 -36
  42. package/dist/dev/upload_relay.js +0 -61
  43. package/dist/dev/upload_relay.test.d.ts +0 -1
  44. package/dist/dev/upload_relay.test.js +0 -76
  45. package/dist/dev/wrapper_page.d.ts +0 -40
  46. package/dist/dev/wrapper_page.js +0 -335
  47. package/dist/docx.d.ts +0 -2
  48. package/dist/docx.js +0 -341
  49. package/dist/docx.test.d.ts +0 -1
  50. package/dist/docx.test.js +0 -145
  51. package/dist/file_command_io.d.ts +0 -12
  52. package/dist/file_command_io.js +0 -34
  53. package/dist/generate_app_agents_dts.d.ts +0 -16
  54. package/dist/generate_app_agents_dts.js +0 -62
  55. package/dist/generate_app_agents_dts.test.d.ts +0 -1
  56. package/dist/generate_app_agents_dts.test.js +0 -45
  57. package/dist/generate_app_fields.d.ts +0 -56
  58. package/dist/generate_app_fields.js +0 -148
  59. package/dist/generate_app_fields.test.d.ts +0 -1
  60. package/dist/generate_app_fields.test.js +0 -108
  61. package/dist/generate_app_queries_dts.d.ts +0 -21
  62. package/dist/generate_app_queries_dts.js +0 -57
  63. package/dist/generate_app_workflows_dts.d.ts +0 -39
  64. package/dist/generate_app_workflows_dts.js +0 -229
  65. package/dist/generate_app_workflows_dts.test.d.ts +0 -1
  66. package/dist/generate_app_workflows_dts.test.js +0 -109
  67. package/dist/generate_package_fields.d.ts +0 -49
  68. package/dist/generate_package_fields.js +0 -157
  69. package/dist/generate_package_fields.test.d.ts +0 -1
  70. package/dist/generate_package_fields.test.js +0 -59
  71. package/dist/inputs.d.ts +0 -38
  72. package/dist/inputs.js +0 -50
  73. package/dist/inputs.test.d.ts +0 -1
  74. package/dist/inputs.test.js +0 -89
  75. package/dist/preview.d.ts +0 -3
  76. package/dist/preview.js +0 -233
  77. package/dist/starter_template.d.ts +0 -64
  78. package/dist/starter_template.js +0 -753
  79. package/dist/starter_template.test.d.ts +0 -1
  80. package/dist/starter_template.test.js +0 -115
  81. package/dist/version.d.ts +0 -1
  82. package/dist/version.js +0 -6
  83. package/dist/xlsx.d.ts +0 -2
  84. package/dist/xlsx.js +0 -489
  85. package/dist/xlsx.test.d.ts +0 -1
  86. package/dist/xlsx.test.js +0 -131
  87. /package/dist/{client.js → src/client.js} +0 -0
@@ -55769,7 +55769,104 @@ ${e.toString()}`);
55769
55769
  return files;
55770
55770
  }
55771
55771
 
55772
- // ../xlsx/src/types.ts
55772
+ // ../office-io/src/ole.ts
55773
+ var OLE2_MAGIC = [208, 207, 17, 224, 161, 177, 26, 225];
55774
+ var ENDOFCHAIN = 4294967294;
55775
+ var FREESECT = 4294967295;
55776
+ function isOle2(bytes) {
55777
+ return bytes.length >= 8 && OLE2_MAGIC.every((b, i3) => bytes[i3] === b);
55778
+ }
55779
+ function readCfbStreams(bytes) {
55780
+ const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
55781
+ const u162 = (o) => dv.getUint16(o, true);
55782
+ const u32 = (o) => dv.getUint32(o, true);
55783
+ const sectorSize = 1 << u162(30);
55784
+ const miniSectorSize = 1 << u162(32);
55785
+ const firstDirSector = u32(48);
55786
+ const miniCutoff = u32(56);
55787
+ const firstMiniFatSector = u32(60);
55788
+ const firstDifatSector = u32(68);
55789
+ if (sectorSize < 512 || sectorSize > 1 << 20) {
55790
+ throw new Error("Unsupported OLE2 file: invalid sector size");
55791
+ }
55792
+ const sectorOffset = (n) => sectorSize * (n + 1);
55793
+ const maxSectors = Math.ceil(bytes.length / sectorSize) + 1;
55794
+ const difat = [];
55795
+ for (let i3 = 0; i3 < 109; i3++) {
55796
+ const v = u32(76 + i3 * 4);
55797
+ if (v !== FREESECT) difat.push(v);
55798
+ }
55799
+ let ds = firstDifatSector;
55800
+ const entriesPerSector = sectorSize / 4;
55801
+ const seenDifat = /* @__PURE__ */ new Set();
55802
+ while (ds !== ENDOFCHAIN && ds !== FREESECT && ds < maxSectors && !seenDifat.has(ds)) {
55803
+ seenDifat.add(ds);
55804
+ const base2 = sectorOffset(ds);
55805
+ for (let i3 = 0; i3 < entriesPerSector - 1; i3++) {
55806
+ const v = u32(base2 + i3 * 4);
55807
+ if (v !== FREESECT) difat.push(v);
55808
+ }
55809
+ ds = u32(base2 + (entriesPerSector - 1) * 4);
55810
+ }
55811
+ const fat = [];
55812
+ for (const fatSector of difat) {
55813
+ if (fat.length >= maxSectors) break;
55814
+ if (fatSector >= maxSectors) continue;
55815
+ const base2 = sectorOffset(fatSector);
55816
+ for (let i3 = 0; i3 < entriesPerSector && fat.length < maxSectors; i3++) {
55817
+ fat.push(u32(base2 + i3 * 4));
55818
+ }
55819
+ }
55820
+ const readChain = (src, start, size, ss, offOf, chain) => {
55821
+ const maxSectors2 = Math.floor(src.length / ss) + 2;
55822
+ const parts = [];
55823
+ let s = start;
55824
+ for (let guard = 0; s !== ENDOFCHAIN && s !== FREESECT && s < chain.length && guard < maxSectors2; guard++) {
55825
+ const o = offOf(s);
55826
+ parts.push(src.subarray(o, o + ss));
55827
+ s = chain[s];
55828
+ }
55829
+ const merged = concat(parts);
55830
+ return size != null ? merged.subarray(0, size) : merged;
55831
+ };
55832
+ const readBig = (start, size) => readChain(bytes, start, size, sectorSize, sectorOffset, fat);
55833
+ const dirBytes = readBig(firstDirSector, null);
55834
+ const ddv = new DataView(dirBytes.buffer, dirBytes.byteOffset, dirBytes.byteLength);
55835
+ const dir = [];
55836
+ for (let off = 0; off + 128 <= dirBytes.length; off += 128) {
55837
+ const nameLen = ddv.getUint16(off + 64, true);
55838
+ const type = ddv.getUint8(off + 66);
55839
+ if (nameLen < 2 || type === 0) continue;
55840
+ const name = utf16le(dirBytes.subarray(off, off + nameLen - 2));
55841
+ dir.push({ name, type, start: ddv.getUint32(off + 116, true), size: Number(ddv.getBigUint64(off + 120, true)) });
55842
+ }
55843
+ const root = dir.find((e) => e.type === 5);
55844
+ const miniStream = root ? readBig(root.start, root.size) : new Uint8Array(0);
55845
+ const miniFatBytes = readBig(firstMiniFatSector, null);
55846
+ const miniFat = [];
55847
+ for (let i3 = 0; i3 + 4 <= miniFatBytes.length; i3 += 4) miniFat.push(miniFatBytes[i3] | miniFatBytes[i3 + 1] << 8 | miniFatBytes[i3 + 2] << 16 | miniFatBytes[i3 + 3] << 24);
55848
+ const readMini = (start, size) => readChain(miniStream, start, size, miniSectorSize, (n) => n * miniSectorSize, miniFat);
55849
+ const readStream = (e) => e.size >= miniCutoff ? readBig(e.start, e.size) : readMini(e.start, e.size);
55850
+ return dir.filter((e) => e.type === 2).map((e) => ({ name: e.name, bytes: readStream(e) }));
55851
+ }
55852
+ function utf16le(b) {
55853
+ let s = "";
55854
+ for (let i3 = 0; i3 + 1 < b.length; i3 += 2) s += String.fromCharCode(b[i3] | b[i3 + 1] << 8);
55855
+ return s;
55856
+ }
55857
+ function concat(parts) {
55858
+ let total = 0;
55859
+ for (const p of parts) total += p.length;
55860
+ const out = new Uint8Array(total);
55861
+ let o = 0;
55862
+ for (const p of parts) {
55863
+ out.set(p, o);
55864
+ o += p.length;
55865
+ }
55866
+ return out;
55867
+ }
55868
+
55869
+ // ../office-io/src/password_protected_error.ts
55773
55870
  var PasswordProtectedError = class extends Error {
55774
55871
  constructor() {
55775
55872
  super("This file is password-protected and cannot be previewed");
@@ -55778,10 +55875,10 @@ ${e.toString()}`);
55778
55875
  };
55779
55876
 
55780
55877
  // ../xlsx/src/ooxml_zip.ts
55781
- var OLE2_MAGIC = [208, 207, 17, 224, 161, 177, 26, 225];
55878
+ var OLE2_MAGIC2 = [208, 207, 17, 224, 161, 177, 26, 225];
55782
55879
  function unzipXlsx(buffer) {
55783
55880
  const bytes = new Uint8Array(buffer);
55784
- if (bytes.length >= 8 && OLE2_MAGIC.every((b, i3) => bytes[i3] === b)) {
55881
+ if (bytes.length >= 8 && OLE2_MAGIC2.every((b, i3) => bytes[i3] === b)) {
55785
55882
  throw new PasswordProtectedError();
55786
55883
  }
55787
55884
  try {
@@ -58303,103 +58400,6 @@ ${e.toString()}`);
58303
58400
  return val && typeof val === "object" ? val : {};
58304
58401
  }
58305
58402
 
58306
- // ../shared/src/ole.ts
58307
- var OLE2_MAGIC2 = [208, 207, 17, 224, 161, 177, 26, 225];
58308
- var ENDOFCHAIN = 4294967294;
58309
- var FREESECT = 4294967295;
58310
- function isOle2(bytes) {
58311
- return bytes.length >= 8 && OLE2_MAGIC2.every((b, i3) => bytes[i3] === b);
58312
- }
58313
- function readCfbStreams(bytes) {
58314
- const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
58315
- const u162 = (o) => dv.getUint16(o, true);
58316
- const u32 = (o) => dv.getUint32(o, true);
58317
- const sectorSize = 1 << u162(30);
58318
- const miniSectorSize = 1 << u162(32);
58319
- const firstDirSector = u32(48);
58320
- const miniCutoff = u32(56);
58321
- const firstMiniFatSector = u32(60);
58322
- const firstDifatSector = u32(68);
58323
- if (sectorSize < 512 || sectorSize > 1 << 20) {
58324
- throw new Error("Unsupported OLE2 file: invalid sector size");
58325
- }
58326
- const sectorOffset = (n) => sectorSize * (n + 1);
58327
- const maxSectors = Math.ceil(bytes.length / sectorSize) + 1;
58328
- const difat = [];
58329
- for (let i3 = 0; i3 < 109; i3++) {
58330
- const v = u32(76 + i3 * 4);
58331
- if (v !== FREESECT) difat.push(v);
58332
- }
58333
- let ds = firstDifatSector;
58334
- const entriesPerSector = sectorSize / 4;
58335
- const seenDifat = /* @__PURE__ */ new Set();
58336
- while (ds !== ENDOFCHAIN && ds !== FREESECT && ds < maxSectors && !seenDifat.has(ds)) {
58337
- seenDifat.add(ds);
58338
- const base2 = sectorOffset(ds);
58339
- for (let i3 = 0; i3 < entriesPerSector - 1; i3++) {
58340
- const v = u32(base2 + i3 * 4);
58341
- if (v !== FREESECT) difat.push(v);
58342
- }
58343
- ds = u32(base2 + (entriesPerSector - 1) * 4);
58344
- }
58345
- const fat = [];
58346
- for (const fatSector of difat) {
58347
- if (fat.length >= maxSectors) break;
58348
- if (fatSector >= maxSectors) continue;
58349
- const base2 = sectorOffset(fatSector);
58350
- for (let i3 = 0; i3 < entriesPerSector && fat.length < maxSectors; i3++) {
58351
- fat.push(u32(base2 + i3 * 4));
58352
- }
58353
- }
58354
- const readChain = (src, start, size, ss, offOf, chain) => {
58355
- const maxSectors2 = Math.floor(src.length / ss) + 2;
58356
- const parts = [];
58357
- let s = start;
58358
- for (let guard = 0; s !== ENDOFCHAIN && s !== FREESECT && s < chain.length && guard < maxSectors2; guard++) {
58359
- const o = offOf(s);
58360
- parts.push(src.subarray(o, o + ss));
58361
- s = chain[s];
58362
- }
58363
- const merged = concat(parts);
58364
- return size != null ? merged.subarray(0, size) : merged;
58365
- };
58366
- const readBig = (start, size) => readChain(bytes, start, size, sectorSize, sectorOffset, fat);
58367
- const dirBytes = readBig(firstDirSector, null);
58368
- const ddv = new DataView(dirBytes.buffer, dirBytes.byteOffset, dirBytes.byteLength);
58369
- const dir = [];
58370
- for (let off = 0; off + 128 <= dirBytes.length; off += 128) {
58371
- const nameLen = ddv.getUint16(off + 64, true);
58372
- const type = ddv.getUint8(off + 66);
58373
- if (nameLen < 2 || type === 0) continue;
58374
- const name = utf16le(dirBytes.subarray(off, off + nameLen - 2));
58375
- dir.push({ name, type, start: ddv.getUint32(off + 116, true), size: Number(ddv.getBigUint64(off + 120, true)) });
58376
- }
58377
- const root = dir.find((e) => e.type === 5);
58378
- const miniStream = root ? readBig(root.start, root.size) : new Uint8Array(0);
58379
- const miniFatBytes = readBig(firstMiniFatSector, null);
58380
- const miniFat = [];
58381
- for (let i3 = 0; i3 + 4 <= miniFatBytes.length; i3 += 4) miniFat.push(miniFatBytes[i3] | miniFatBytes[i3 + 1] << 8 | miniFatBytes[i3 + 2] << 16 | miniFatBytes[i3 + 3] << 24);
58382
- const readMini = (start, size) => readChain(miniStream, start, size, miniSectorSize, (n) => n * miniSectorSize, miniFat);
58383
- const readStream = (e) => e.size >= miniCutoff ? readBig(e.start, e.size) : readMini(e.start, e.size);
58384
- return dir.filter((e) => e.type === 2).map((e) => ({ name: e.name, bytes: readStream(e) }));
58385
- }
58386
- function utf16le(b) {
58387
- let s = "";
58388
- for (let i3 = 0; i3 + 1 < b.length; i3 += 2) s += String.fromCharCode(b[i3] | b[i3 + 1] << 8);
58389
- return s;
58390
- }
58391
- function concat(parts) {
58392
- let total = 0;
58393
- for (const p of parts) total += p.length;
58394
- const out = new Uint8Array(total);
58395
- let o = 0;
58396
- for (const p of parts) {
58397
- out.set(p, o);
58398
- o += p.length;
58399
- }
58400
- return out;
58401
- }
58402
-
58403
58403
  // ../xlsx/src/biff8_reader.ts
58404
58404
  var DEFAULT_MAX_ROWS = 1e4;
58405
58405
  var REC = {
package/dist/src/cli.js CHANGED
@@ -30645,6 +30645,38 @@ import { tmpdir } from "node:os";
30645
30645
  var STARTER_FALLBACK_UI_VERSION = "6.1.0";
30646
30646
  var STARTER_FALLBACK_SDK_VERSION = "0.51.0";
30647
30647
  var STARTER_REACT_NATIVE_VERSION = "0.85.3";
30648
+ var VITEST_SETUP_FILENAME = "vitest.setup.ts";
30649
+ var VITEST_SETUP_CONTENT = `import { vi } from "vitest";
30650
+
30651
+ // A package-linked app's generated .lotics/app_fields.ts resolves F/OPT/ROLE
30652
+ // from the installation's live binding at module load (\`await getAppBinding()\`,
30653
+ // a network call over the host bridge). Under vitest/jsdom there is no host, so
30654
+ // that call throws while a test is still COLLECTING \u2014 failing every test that
30655
+ // imports the app graph, even pure logic tests. getAppBinding is the network
30656
+ // boundary; mock it (and only it) so the module graph evaluates in tests.
30657
+ //
30658
+ // The stub returns an ECHO binding: any alias resolves to a synthetic,
30659
+ // self-identifying id (fld:test:<entity>.<field>, opt:test:\u2026, grp:test:\u2026). Echo,
30660
+ // not empty maps \u2014 app_fields's bound() throws on a missing key, so empty maps
30661
+ // would just re-break collection; and a ':test:' id can never be confused with a
30662
+ // real fld_\u2026/opt_\u2026/grp_\u2026 id, so a test that depends on a concrete binding fails
30663
+ // loud instead of silently reading undefined.
30664
+ vi.mock("@lotics/app-sdk", async (importOriginal) => {
30665
+ const actual = await importOriginal<typeof import("@lotics/app-sdk")>();
30666
+ const echoIds = (prefix: string): Record<string, string> =>
30667
+ new Proxy(
30668
+ {},
30669
+ {
30670
+ get: (_target, key) => (typeof key === "string" ? \`\${prefix}:test:\${key}\` : undefined),
30671
+ },
30672
+ ) as Record<string, string>;
30673
+ return {
30674
+ ...actual,
30675
+ getAppBinding: () =>
30676
+ Promise.resolve({ fields: echoIds("fld"), options: echoIds("opt"), roles: echoIds("grp") }),
30677
+ };
30678
+ });
30679
+ `;
30648
30680
  function buildStarterTemplate(args) {
30649
30681
  const uiVersion = args.ui_version ?? `^${STARTER_FALLBACK_UI_VERSION}`;
30650
30682
  const sdkVersion = args.sdk_version ?? `^${STARTER_FALLBACK_SDK_VERSION}`;
@@ -30883,6 +30915,11 @@ export default defineConfig({
30883
30915
  },
30884
30916
  test: {
30885
30917
  environment: "jsdom",
30918
+ // Stub @lotics/app-sdk's getAppBinding (the network boundary) before any test
30919
+ // collects. A package-linked app's generated .lotics/app_fields.ts awaits it
30920
+ // at module load; without the stub that network call throws under jsdom and
30921
+ // every test that imports the app graph fails to collect. See vitest.setup.ts.
30922
+ setupFiles: ["./${VITEST_SETUP_FILENAME}"],
30886
30923
  // RN packages ship Flow (\`import typeof\`) in their native source, reached
30887
30924
  // transitively by RN-Web components (pickers, calendars, anything touching
30888
30925
  // Animated). Vitest's web optimizer is OFF by default and ignores the
@@ -31248,6 +31285,10 @@ describe("App", () => {
31248
31285
  });
31249
31286
  `
31250
31287
  },
31288
+ {
31289
+ path: VITEST_SETUP_FILENAME,
31290
+ content: VITEST_SETUP_CONTENT
31291
+ },
31251
31292
  {
31252
31293
  path: ".github/workflows/ci.yml",
31253
31294
  content: `name: CI
@@ -33070,8 +33111,29 @@ function writeBindingAppFields(projectDir, binding) {
33070
33111
  fs4.mkdirSync(dotLotics, { recursive: true });
33071
33112
  const file = path5.join(dotLotics, "app_fields.ts");
33072
33113
  fs4.writeFileSync(file, generatePackageAppFields(binding));
33114
+ ensureAppVitestSetup(projectDir);
33073
33115
  return file;
33074
33116
  }
33117
+ function ensureAppVitestSetup(projectDir) {
33118
+ const setupPath = path5.join(projectDir, VITEST_SETUP_FILENAME);
33119
+ if (!fs4.existsSync(setupPath)) {
33120
+ fs4.writeFileSync(setupPath, VITEST_SETUP_CONTENT);
33121
+ console.error(`Wrote ${VITEST_SETUP_FILENAME} (stubs getAppBinding so \`npm test\` collects).`);
33122
+ } else if (!fs4.readFileSync(setupPath, "utf-8").includes("getAppBinding")) {
33123
+ console.error(
33124
+ `\u26A0 ${VITEST_SETUP_FILENAME} exists but does not stub getAppBinding \u2014 \`npm test\` will fail to collect any test that imports the app graph (the binding-form .lotics/app_fields.ts awaits a network call). Add the stub to it:
33125
+ ${VITEST_SETUP_CONTENT}`
33126
+ );
33127
+ }
33128
+ const viteConfigPath = path5.join(projectDir, "vite.config.ts");
33129
+ if (!fs4.existsSync(viteConfigPath)) return;
33130
+ const viteConfig = fs4.readFileSync(viteConfigPath, "utf-8");
33131
+ if (/setupFiles\s*:/.test(viteConfig) && viteConfig.includes(VITEST_SETUP_FILENAME)) return;
33132
+ console.error(
33133
+ `\u26A0 vite.config.ts does not wire ${VITEST_SETUP_FILENAME} \u2014 \`npm test\` will fail to collect any test that imports the app graph (the binding-form .lotics/app_fields.ts awaits a network call). Add it to the \`test\` block:
33134
+ setupFiles: ["./${VITEST_SETUP_FILENAME}"],`
33135
+ );
33136
+ }
33075
33137
  async function appCodegen(args) {
33076
33138
  const projectDir = path5.resolve(args.projectDir ?? process.cwd());
33077
33139
  const meta = readAppMeta(projectDir);
@@ -39600,7 +39662,104 @@ function unzipSync(data, opts) {
39600
39662
  return files;
39601
39663
  }
39602
39664
 
39603
- // ../xlsx/src/types.ts
39665
+ // ../office-io/src/ole.ts
39666
+ var OLE2_MAGIC = [208, 207, 17, 224, 161, 177, 26, 225];
39667
+ var ENDOFCHAIN = 4294967294;
39668
+ var FREESECT = 4294967295;
39669
+ function isOle2(bytes) {
39670
+ return bytes.length >= 8 && OLE2_MAGIC.every((b, i2) => bytes[i2] === b);
39671
+ }
39672
+ function readCfbStreams(bytes) {
39673
+ const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
39674
+ const u162 = (o) => dv.getUint16(o, true);
39675
+ const u32 = (o) => dv.getUint32(o, true);
39676
+ const sectorSize = 1 << u162(30);
39677
+ const miniSectorSize = 1 << u162(32);
39678
+ const firstDirSector = u32(48);
39679
+ const miniCutoff = u32(56);
39680
+ const firstMiniFatSector = u32(60);
39681
+ const firstDifatSector = u32(68);
39682
+ if (sectorSize < 512 || sectorSize > 1 << 20) {
39683
+ throw new Error("Unsupported OLE2 file: invalid sector size");
39684
+ }
39685
+ const sectorOffset = (n) => sectorSize * (n + 1);
39686
+ const maxSectors = Math.ceil(bytes.length / sectorSize) + 1;
39687
+ const difat = [];
39688
+ for (let i2 = 0; i2 < 109; i2++) {
39689
+ const v = u32(76 + i2 * 4);
39690
+ if (v !== FREESECT) difat.push(v);
39691
+ }
39692
+ let ds = firstDifatSector;
39693
+ const entriesPerSector = sectorSize / 4;
39694
+ const seenDifat = /* @__PURE__ */ new Set();
39695
+ while (ds !== ENDOFCHAIN && ds !== FREESECT && ds < maxSectors && !seenDifat.has(ds)) {
39696
+ seenDifat.add(ds);
39697
+ const base = sectorOffset(ds);
39698
+ for (let i2 = 0; i2 < entriesPerSector - 1; i2++) {
39699
+ const v = u32(base + i2 * 4);
39700
+ if (v !== FREESECT) difat.push(v);
39701
+ }
39702
+ ds = u32(base + (entriesPerSector - 1) * 4);
39703
+ }
39704
+ const fat = [];
39705
+ for (const fatSector of difat) {
39706
+ if (fat.length >= maxSectors) break;
39707
+ if (fatSector >= maxSectors) continue;
39708
+ const base = sectorOffset(fatSector);
39709
+ for (let i2 = 0; i2 < entriesPerSector && fat.length < maxSectors; i2++) {
39710
+ fat.push(u32(base + i2 * 4));
39711
+ }
39712
+ }
39713
+ const readChain = (src, start, size, ss, offOf, chain) => {
39714
+ const maxSectors2 = Math.floor(src.length / ss) + 2;
39715
+ const parts = [];
39716
+ let s = start;
39717
+ for (let guard = 0; s !== ENDOFCHAIN && s !== FREESECT && s < chain.length && guard < maxSectors2; guard++) {
39718
+ const o = offOf(s);
39719
+ parts.push(src.subarray(o, o + ss));
39720
+ s = chain[s];
39721
+ }
39722
+ const merged = concat(parts);
39723
+ return size != null ? merged.subarray(0, size) : merged;
39724
+ };
39725
+ const readBig = (start, size) => readChain(bytes, start, size, sectorSize, sectorOffset, fat);
39726
+ const dirBytes = readBig(firstDirSector, null);
39727
+ const ddv = new DataView(dirBytes.buffer, dirBytes.byteOffset, dirBytes.byteLength);
39728
+ const dir = [];
39729
+ for (let off = 0; off + 128 <= dirBytes.length; off += 128) {
39730
+ const nameLen = ddv.getUint16(off + 64, true);
39731
+ const type = ddv.getUint8(off + 66);
39732
+ if (nameLen < 2 || type === 0) continue;
39733
+ const name = utf16le(dirBytes.subarray(off, off + nameLen - 2));
39734
+ dir.push({ name, type, start: ddv.getUint32(off + 116, true), size: Number(ddv.getBigUint64(off + 120, true)) });
39735
+ }
39736
+ const root = dir.find((e) => e.type === 5);
39737
+ const miniStream = root ? readBig(root.start, root.size) : new Uint8Array(0);
39738
+ const miniFatBytes = readBig(firstMiniFatSector, null);
39739
+ const miniFat = [];
39740
+ for (let i2 = 0; i2 + 4 <= miniFatBytes.length; i2 += 4) miniFat.push(miniFatBytes[i2] | miniFatBytes[i2 + 1] << 8 | miniFatBytes[i2 + 2] << 16 | miniFatBytes[i2 + 3] << 24);
39741
+ const readMini = (start, size) => readChain(miniStream, start, size, miniSectorSize, (n) => n * miniSectorSize, miniFat);
39742
+ const readStream = (e) => e.size >= miniCutoff ? readBig(e.start, e.size) : readMini(e.start, e.size);
39743
+ return dir.filter((e) => e.type === 2).map((e) => ({ name: e.name, bytes: readStream(e) }));
39744
+ }
39745
+ function utf16le(b) {
39746
+ let s = "";
39747
+ for (let i2 = 0; i2 + 1 < b.length; i2 += 2) s += String.fromCharCode(b[i2] | b[i2 + 1] << 8);
39748
+ return s;
39749
+ }
39750
+ function concat(parts) {
39751
+ let total = 0;
39752
+ for (const p of parts) total += p.length;
39753
+ const out = new Uint8Array(total);
39754
+ let o = 0;
39755
+ for (const p of parts) {
39756
+ out.set(p, o);
39757
+ o += p.length;
39758
+ }
39759
+ return out;
39760
+ }
39761
+
39762
+ // ../office-io/src/password_protected_error.ts
39604
39763
  var PasswordProtectedError = class extends Error {
39605
39764
  constructor() {
39606
39765
  super("This file is password-protected and cannot be previewed");
@@ -39609,10 +39768,10 @@ var PasswordProtectedError = class extends Error {
39609
39768
  };
39610
39769
 
39611
39770
  // ../xlsx/src/ooxml_zip.ts
39612
- var OLE2_MAGIC = [208, 207, 17, 224, 161, 177, 26, 225];
39771
+ var OLE2_MAGIC2 = [208, 207, 17, 224, 161, 177, 26, 225];
39613
39772
  function unzipXlsx(buffer) {
39614
39773
  const bytes = new Uint8Array(buffer);
39615
- if (bytes.length >= 8 && OLE2_MAGIC.every((b, i2) => bytes[i2] === b)) {
39774
+ if (bytes.length >= 8 && OLE2_MAGIC2.every((b, i2) => bytes[i2] === b)) {
39616
39775
  throw new PasswordProtectedError();
39617
39776
  }
39618
39777
  try {
@@ -43352,103 +43511,6 @@ function ensureVmlArray(val) {
43352
43511
  return Array.isArray(val) ? val : [val];
43353
43512
  }
43354
43513
 
43355
- // ../shared/src/ole.ts
43356
- var OLE2_MAGIC2 = [208, 207, 17, 224, 161, 177, 26, 225];
43357
- var ENDOFCHAIN = 4294967294;
43358
- var FREESECT = 4294967295;
43359
- function isOle2(bytes) {
43360
- return bytes.length >= 8 && OLE2_MAGIC2.every((b, i2) => bytes[i2] === b);
43361
- }
43362
- function readCfbStreams(bytes) {
43363
- const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
43364
- const u162 = (o) => dv.getUint16(o, true);
43365
- const u32 = (o) => dv.getUint32(o, true);
43366
- const sectorSize = 1 << u162(30);
43367
- const miniSectorSize = 1 << u162(32);
43368
- const firstDirSector = u32(48);
43369
- const miniCutoff = u32(56);
43370
- const firstMiniFatSector = u32(60);
43371
- const firstDifatSector = u32(68);
43372
- if (sectorSize < 512 || sectorSize > 1 << 20) {
43373
- throw new Error("Unsupported OLE2 file: invalid sector size");
43374
- }
43375
- const sectorOffset = (n) => sectorSize * (n + 1);
43376
- const maxSectors = Math.ceil(bytes.length / sectorSize) + 1;
43377
- const difat = [];
43378
- for (let i2 = 0; i2 < 109; i2++) {
43379
- const v = u32(76 + i2 * 4);
43380
- if (v !== FREESECT) difat.push(v);
43381
- }
43382
- let ds = firstDifatSector;
43383
- const entriesPerSector = sectorSize / 4;
43384
- const seenDifat = /* @__PURE__ */ new Set();
43385
- while (ds !== ENDOFCHAIN && ds !== FREESECT && ds < maxSectors && !seenDifat.has(ds)) {
43386
- seenDifat.add(ds);
43387
- const base = sectorOffset(ds);
43388
- for (let i2 = 0; i2 < entriesPerSector - 1; i2++) {
43389
- const v = u32(base + i2 * 4);
43390
- if (v !== FREESECT) difat.push(v);
43391
- }
43392
- ds = u32(base + (entriesPerSector - 1) * 4);
43393
- }
43394
- const fat = [];
43395
- for (const fatSector of difat) {
43396
- if (fat.length >= maxSectors) break;
43397
- if (fatSector >= maxSectors) continue;
43398
- const base = sectorOffset(fatSector);
43399
- for (let i2 = 0; i2 < entriesPerSector && fat.length < maxSectors; i2++) {
43400
- fat.push(u32(base + i2 * 4));
43401
- }
43402
- }
43403
- const readChain = (src, start, size, ss, offOf, chain) => {
43404
- const maxSectors2 = Math.floor(src.length / ss) + 2;
43405
- const parts = [];
43406
- let s = start;
43407
- for (let guard = 0; s !== ENDOFCHAIN && s !== FREESECT && s < chain.length && guard < maxSectors2; guard++) {
43408
- const o = offOf(s);
43409
- parts.push(src.subarray(o, o + ss));
43410
- s = chain[s];
43411
- }
43412
- const merged = concat(parts);
43413
- return size != null ? merged.subarray(0, size) : merged;
43414
- };
43415
- const readBig = (start, size) => readChain(bytes, start, size, sectorSize, sectorOffset, fat);
43416
- const dirBytes = readBig(firstDirSector, null);
43417
- const ddv = new DataView(dirBytes.buffer, dirBytes.byteOffset, dirBytes.byteLength);
43418
- const dir = [];
43419
- for (let off = 0; off + 128 <= dirBytes.length; off += 128) {
43420
- const nameLen = ddv.getUint16(off + 64, true);
43421
- const type = ddv.getUint8(off + 66);
43422
- if (nameLen < 2 || type === 0) continue;
43423
- const name = utf16le(dirBytes.subarray(off, off + nameLen - 2));
43424
- dir.push({ name, type, start: ddv.getUint32(off + 116, true), size: Number(ddv.getBigUint64(off + 120, true)) });
43425
- }
43426
- const root = dir.find((e) => e.type === 5);
43427
- const miniStream = root ? readBig(root.start, root.size) : new Uint8Array(0);
43428
- const miniFatBytes = readBig(firstMiniFatSector, null);
43429
- const miniFat = [];
43430
- for (let i2 = 0; i2 + 4 <= miniFatBytes.length; i2 += 4) miniFat.push(miniFatBytes[i2] | miniFatBytes[i2 + 1] << 8 | miniFatBytes[i2 + 2] << 16 | miniFatBytes[i2 + 3] << 24);
43431
- const readMini = (start, size) => readChain(miniStream, start, size, miniSectorSize, (n) => n * miniSectorSize, miniFat);
43432
- const readStream = (e) => e.size >= miniCutoff ? readBig(e.start, e.size) : readMini(e.start, e.size);
43433
- return dir.filter((e) => e.type === 2).map((e) => ({ name: e.name, bytes: readStream(e) }));
43434
- }
43435
- function utf16le(b) {
43436
- let s = "";
43437
- for (let i2 = 0; i2 + 1 < b.length; i2 += 2) s += String.fromCharCode(b[i2] | b[i2 + 1] << 8);
43438
- return s;
43439
- }
43440
- function concat(parts) {
43441
- let total = 0;
43442
- for (const p of parts) total += p.length;
43443
- const out = new Uint8Array(total);
43444
- let o = 0;
43445
- for (const p of parts) {
43446
- out.set(p, o);
43447
- o += p.length;
43448
- }
43449
- return out;
43450
- }
43451
-
43452
43514
  // ../xlsx/src/biff8_reader.ts
43453
43515
  var DEFAULT_MAX_ROWS = 1e4;
43454
43516
  var REC = {
@@ -1,4 +1,4 @@
1
- import type { ContractConfigEntry, KnowledgeUpgradeEntry, ModifiedArtifact, PackageContentBinding, UpgradeResolutions } from "@lotics/shared/schemas/packages";
1
+ import type { ContractConfigEntry, KnowledgeUpgradeEntry, ModifiedArtifact, PackageContentBinding, UpgradeResolutions } from "./package_content_types";
2
2
  /**
3
3
  * The error message for a non-ok response. A genuine JSON error (a 4xx carrying
4
4
  * a `message`) surfaces verbatim; a non-JSON body (a gateway HTML page), any
@@ -539,6 +539,14 @@ export declare class LoticsClient {
539
539
  }>;
540
540
  /** `knowledge_expects` names the package's agents route to but it does not own (advisory). */
541
541
  missing_expected_docs: string[];
542
+ /** Orphan duplicate link fields (unbound links between binding-covered tables). Always empty on an origin. */
543
+ orphan_duplicate_links: Array<{
544
+ field_id: string;
545
+ field_name: string;
546
+ table_id: string;
547
+ table_name: string;
548
+ target_table_id: string;
549
+ }>;
542
550
  }>;
543
551
  /**
544
552
  * Preview a release — the dry run behind `opctl app release`. Runs the
@@ -0,0 +1,70 @@
1
+ /** Theme colors an app config `color` entry may default to (Tailwind palette). */
2
+ export type ContractConfigColor = "red" | "orange" | "amber" | "yellow" | "lime" | "green" | "emerald" | "teal" | "cyan" | "sky" | "blue" | "indigo" | "violet" | "purple" | "fuchsia" | "pink" | "rose" | "slate" | "gray" | "zinc" | "neutral" | "stone";
3
+ /** A customization knob a package exposes; discriminated on `type`, each with a
4
+ * typed `default` an installation may override. Variants are written flat (not
5
+ * a shared base intersection) to match the zod schema's inferred shape exactly. */
6
+ export type ContractConfigEntry = {
7
+ alias: string;
8
+ label: string;
9
+ description?: string;
10
+ type: "text";
11
+ default: string;
12
+ } | {
13
+ alias: string;
14
+ label: string;
15
+ description?: string;
16
+ type: "boolean";
17
+ default: boolean;
18
+ } | {
19
+ alias: string;
20
+ label: string;
21
+ description?: string;
22
+ type: "color";
23
+ default: ContractConfigColor;
24
+ } | {
25
+ alias: string;
26
+ label: string;
27
+ description?: string;
28
+ type: "number";
29
+ default: number;
30
+ } | {
31
+ alias: string;
32
+ label: string;
33
+ description?: string;
34
+ type: "select";
35
+ options: {
36
+ value: string;
37
+ label: string;
38
+ }[];
39
+ default: string;
40
+ };
41
+ /** Per-installation content binding: stable content alias → concrete workspace
42
+ * id, per namespace. Absent namespaces default to `{}`. */
43
+ export interface PackageContentBinding {
44
+ knowledge: Record<string, string>;
45
+ templates: Record<string, string>;
46
+ }
47
+ /** A package artifact edited in the workspace since install, flagged on upgrade
48
+ * so the re-materialize doesn't silently revert the local edit. */
49
+ export interface ModifiedArtifact {
50
+ kind: "queries" | "workflows" | "agents" | "template";
51
+ alias: string;
52
+ /** Templates only: the OLD pinned contract carried no `content_sha256`, so a
53
+ * local edit vs. older upstream content can't be attributed — a one-time consent. */
54
+ baseline_unknown?: boolean;
55
+ }
56
+ /** One entry in a package-managed knowledge upgrade diff. */
57
+ export interface KnowledgeUpgradeEntry {
58
+ alias: string;
59
+ name: string;
60
+ change: "added" | "changed" | "removed" | "drifted";
61
+ /** `changed`/`removed` only: the live doc diverged from the OLD pinned sha. */
62
+ modified: boolean;
63
+ /** The bound live doc id; null for `added`, or a `drifted` doc that is gone. */
64
+ doc_id: string | null;
65
+ }
66
+ /** The upgrade resolutions map: a namespaced key (`<namespace|kind>.<alias>` or
67
+ * `knowledge.<alias>`) → the resolution for the entry it names. */
68
+ export type UpgradeResolutions = Record<string, {
69
+ bind_to: string;
70
+ } | "recreate" | "revert" | "keep" | "apply" | "archive" | "unbind">;
@@ -0,0 +1,12 @@
1
+ // Published-safe copies of the package-content types the `LoticsClient` SDK
2
+ // surface exposes. Their source of truth is the zod schemas in the PRIVATE,
3
+ // unpublished `@lotics/shared/schemas/packages`; importing them here would leak
4
+ // an unresolvable `@lotics/shared` specifier into the published `client.d.ts`
5
+ // (an external `import { LoticsClient } from "@lotics/cli"` cannot resolve it —
6
+ // `@lotics/shared` is `private`, never on npm). We mirror them BY VALUE — the
7
+ // same "no shared dep" parity the transport strings keep with `@lotics/app-sdk`.
8
+ //
9
+ // `package_content_types.test.ts` asserts these stay structurally identical to
10
+ // the shared schemas' `z.infer` at typecheck time, so any drift is a build
11
+ // failure — never a silent skew.
12
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/cli",
3
- "version": "0.88.0",
3
+ "version": "0.89.1",
4
4
  "description": "Lotics SDK and CLI for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,7 +15,7 @@
15
15
  "docs"
16
16
  ],
17
17
  "scripts": {
18
- "build": "tsgo && node scripts/build_cli.mjs",
18
+ "build": "tsgo -p tsconfig.build.json && node scripts/build_cli.mjs",
19
19
  "typecheck": "tsgo --noEmit",
20
20
  "test": "vitest run",
21
21
  "prepublishOnly": "npm run build"