@lotics/cli 0.64.0 → 0.66.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.
- package/README.md +8 -2
- package/dist/app_commands.d.ts +34 -9
- package/dist/app_commands.js +121 -45
- package/dist/app_commands.test.js +51 -13
- package/dist/args.d.ts +2 -0
- package/dist/args.js +4 -0
- package/dist/cli.js +35 -8
- package/dist/client.d.ts +20 -0
- package/dist/client.js +15 -0
- package/dist/generate_app_workflows_dts.js +1 -1
- package/dist/generate_app_workflows_dts.test.js +10 -0
- package/dist/src/cli.js +528 -33
- package/package.json +1 -1
package/dist/src/cli.js
CHANGED
|
@@ -3387,7 +3387,7 @@ var require_jstat = __commonJS({
|
|
|
3387
3387
|
}
|
|
3388
3388
|
})(exports2, function() {
|
|
3389
3389
|
var jStat = (function(Math2, undefined2) {
|
|
3390
|
-
var
|
|
3390
|
+
var concat2 = Array.prototype.concat;
|
|
3391
3391
|
var slice = Array.prototype.slice;
|
|
3392
3392
|
var toString = Object.prototype.toString;
|
|
3393
3393
|
function calcRdx(n, m) {
|
|
@@ -3407,7 +3407,7 @@ var require_jstat = __commonJS({
|
|
|
3407
3407
|
return typeof num === "number" ? num - num === 0 : false;
|
|
3408
3408
|
}
|
|
3409
3409
|
function toVector(arr) {
|
|
3410
|
-
return
|
|
3410
|
+
return concat2.apply([], arr);
|
|
3411
3411
|
}
|
|
3412
3412
|
function jStat2() {
|
|
3413
3413
|
return new jStat2._init(arguments);
|
|
@@ -20136,7 +20136,7 @@ var require_BufferList = __commonJS({
|
|
|
20136
20136
|
}
|
|
20137
20137
|
return ret;
|
|
20138
20138
|
};
|
|
20139
|
-
BufferList.prototype.concat = function
|
|
20139
|
+
BufferList.prototype.concat = function concat2(n) {
|
|
20140
20140
|
if (this.length === 0) return Buffer2.alloc(0);
|
|
20141
20141
|
var ret = Buffer2.allocUnsafe(n >>> 0);
|
|
20142
20142
|
var p = this.head;
|
|
@@ -23322,7 +23322,7 @@ var require_StreamHelper = __commonJS({
|
|
|
23322
23322
|
return utils.transformTo(type, content);
|
|
23323
23323
|
}
|
|
23324
23324
|
}
|
|
23325
|
-
function
|
|
23325
|
+
function concat2(type, dataArray) {
|
|
23326
23326
|
var i2, index = 0, res = null, totalLength = 0;
|
|
23327
23327
|
for (i2 = 0; i2 < dataArray.length; i2++) {
|
|
23328
23328
|
totalLength += dataArray[i2].length;
|
|
@@ -23359,7 +23359,7 @@ var require_StreamHelper = __commonJS({
|
|
|
23359
23359
|
reject2(err2);
|
|
23360
23360
|
}).on("end", function() {
|
|
23361
23361
|
try {
|
|
23362
|
-
var result = transformZipOutput(resultType,
|
|
23362
|
+
var result = transformZipOutput(resultType, concat2(chunkType, dataArray), mimeType);
|
|
23363
23363
|
resolve(result);
|
|
23364
23364
|
} catch (e) {
|
|
23365
23365
|
reject2(e);
|
|
@@ -29881,6 +29881,17 @@ var LoticsClient = class {
|
|
|
29881
29881
|
...body.description ? { description: body.description } : {}
|
|
29882
29882
|
});
|
|
29883
29883
|
}
|
|
29884
|
+
/**
|
|
29885
|
+
* Bind (create or replace) an app query by alias via the `set_app_query` tool
|
|
29886
|
+
* — the deploy-free authoring path for `apps.queries`, parallel to
|
|
29887
|
+
* `setAppWorkflow`. `declaration` is the `{ ast, params? }` from
|
|
29888
|
+
* `package.json#lotics.queries.<alias>`. The server validates it exactly as a
|
|
29889
|
+
* deploy validates the manifest. Note: `apps.queries` is manifest-authoritative,
|
|
29890
|
+
* so the next `lotics app deploy` overwrites this from the manifest.
|
|
29891
|
+
*/
|
|
29892
|
+
async setAppQuery(app_id, alias, declaration) {
|
|
29893
|
+
return this.execute("set_app_query", { app_id, alias, declaration });
|
|
29894
|
+
}
|
|
29884
29895
|
/**
|
|
29885
29896
|
* Fetch one app workflow's faithful source + bound input/output schemas via
|
|
29886
29897
|
* `get_app_workflow`. `source` is the JS-subset body re-rendered from the
|
|
@@ -30004,6 +30015,7 @@ var LoticsClient = class {
|
|
|
30004
30015
|
if (args.capabilities !== void 0) {
|
|
30005
30016
|
formData.append("capabilities", JSON.stringify(args.capabilities));
|
|
30006
30017
|
}
|
|
30018
|
+
formData.append("workflow_aliases", JSON.stringify(args.workflow_aliases ?? []));
|
|
30007
30019
|
const url = `${this.baseUrl}/v1/apps/${encodeURIComponent(args.app_id)}/versions`;
|
|
30008
30020
|
const response = await fetch(url, {
|
|
30009
30021
|
method: "POST",
|
|
@@ -31803,7 +31815,7 @@ function inputDeclToTsType(decl) {
|
|
|
31803
31815
|
case "date_range":
|
|
31804
31816
|
return "{ start: string; end: string }";
|
|
31805
31817
|
case "file":
|
|
31806
|
-
return "string";
|
|
31818
|
+
return decl.multi === true ? "ReadonlyArray<string>" : "string";
|
|
31807
31819
|
case "object": {
|
|
31808
31820
|
const fields = decl.fields !== null && typeof decl.fields === "object" ? decl.fields : {};
|
|
31809
31821
|
return inputsToType(fields);
|
|
@@ -32219,6 +32231,8 @@ async function fetchLatestNpmVersion(packageName) {
|
|
|
32219
32231
|
var WORKFLOWS_DIR = path5.join("src", "workflows");
|
|
32220
32232
|
var WORKFLOW_GLOBALS_DIR = path5.join(".lotics", "workflows");
|
|
32221
32233
|
var WORKFLOW_TSCONFIG_EXCLUDES = ["src/workflows", ".lotics/workflows"];
|
|
32234
|
+
var LOTICS_INCLUDE_GLOB = ".lotics/**/*";
|
|
32235
|
+
var STALE_LOTICS_INCLUDES = /* @__PURE__ */ new Set([".lotics", "./.lotics", ".lotics/"]);
|
|
32222
32236
|
var FALLBACK_ENVELOPE_PREFIX = "async function __workflow(): Promise<__WorkflowReturn | void> {\n";
|
|
32223
32237
|
var FALLBACK_ENVELOPE_SUFFIX = "\n}";
|
|
32224
32238
|
function workflowFileHeader(alias) {
|
|
@@ -32362,11 +32376,11 @@ function writeAppMeta(projectDir, meta) {
|
|
|
32362
32376
|
pkg2.lotics = meta;
|
|
32363
32377
|
fs4.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
|
|
32364
32378
|
}
|
|
32365
|
-
function
|
|
32379
|
+
function ensureAppTsconfig(projectDir) {
|
|
32366
32380
|
const tsconfigPath = path5.join(projectDir, "tsconfig.json");
|
|
32367
32381
|
if (!fs4.existsSync(tsconfigPath)) {
|
|
32368
32382
|
console.error(
|
|
32369
|
-
`\u26A0 No tsconfig.json at ${projectDir} \u2014 could not ensure
|
|
32383
|
+
`\u26A0 No tsconfig.json at ${projectDir} \u2014 could not ensure "include" has "${LOTICS_INCLUDE_GLOB}" (a bare .lotics loads none of the generated types) or "exclude" has ${WORKFLOW_TSCONFIG_EXCLUDES.join(", ")}.`
|
|
32370
32384
|
);
|
|
32371
32385
|
return;
|
|
32372
32386
|
}
|
|
@@ -32375,20 +32389,29 @@ function ensureWorkflowTsconfigExcludes(projectDir) {
|
|
|
32375
32389
|
parsed = JSON.parse(fs4.readFileSync(tsconfigPath, "utf-8"));
|
|
32376
32390
|
} catch (err2) {
|
|
32377
32391
|
console.error(
|
|
32378
|
-
`\u26A0 Could not parse tsconfig.json (${err2 instanceof Error ? err2.message : String(err2)}) \u2014
|
|
32392
|
+
`\u26A0 Could not parse tsconfig.json (${err2 instanceof Error ? err2.message : String(err2)}) \u2014 ensure "include" has "${LOTICS_INCLUDE_GLOB}" and "exclude" has ${WORKFLOW_TSCONFIG_EXCLUDES.join(", ")} manually.`
|
|
32379
32393
|
);
|
|
32380
32394
|
return;
|
|
32381
32395
|
}
|
|
32382
32396
|
if (!parsed || typeof parsed !== "object") return;
|
|
32383
|
-
const
|
|
32384
|
-
|
|
32385
|
-
|
|
32386
|
-
|
|
32387
|
-
|
|
32397
|
+
const changes = [];
|
|
32398
|
+
if (Array.isArray(parsed.include)) {
|
|
32399
|
+
const inc = parsed.include.filter((e) => typeof e === "string");
|
|
32400
|
+
if (inc.some((e) => STALE_LOTICS_INCLUDES.has(e))) {
|
|
32401
|
+
const healed = inc.map((e) => STALE_LOTICS_INCLUDES.has(e) ? LOTICS_INCLUDE_GLOB : e);
|
|
32402
|
+
parsed.include = healed.filter((e, i2) => healed.indexOf(e) === i2);
|
|
32403
|
+
changes.push(`rewrote a bare ".lotics" to "${LOTICS_INCLUDE_GLOB}" in "include" (a dot-dir loads zero generated types)`);
|
|
32404
|
+
}
|
|
32405
|
+
}
|
|
32406
|
+
const currentEx = Array.isArray(parsed.exclude) ? parsed.exclude.filter((e) => typeof e === "string") : [];
|
|
32407
|
+
const toAdd = WORKFLOW_TSCONFIG_EXCLUDES.filter((g) => !currentEx.includes(g));
|
|
32408
|
+
if (toAdd.length > 0) {
|
|
32409
|
+
parsed.exclude = [...currentEx, ...toAdd];
|
|
32410
|
+
changes.push(`added ${toAdd.join(", ")} to "exclude"`);
|
|
32411
|
+
}
|
|
32412
|
+
if (changes.length === 0) return;
|
|
32388
32413
|
fs4.writeFileSync(tsconfigPath, JSON.stringify(parsed, null, 2) + "\n");
|
|
32389
|
-
console.error(
|
|
32390
|
-
`Patched tsconfig.json: added ${toAdd.join(", ")} to "exclude" so npm run typecheck skips the workflow bodies (check them with: lotics app workflow check).`
|
|
32391
|
-
);
|
|
32414
|
+
console.error(`Patched tsconfig.json: ${changes.join("; ")}.`);
|
|
32392
32415
|
}
|
|
32393
32416
|
function writeAppDts(projectDir, manifest) {
|
|
32394
32417
|
const dotLotics = path5.join(projectDir, ".lotics");
|
|
@@ -32399,6 +32422,7 @@ function writeAppDts(projectDir, manifest) {
|
|
|
32399
32422
|
[path5.join(dotLotics, "app_agents.d.ts"), generateAppAgentsDts(manifest.agents)]
|
|
32400
32423
|
];
|
|
32401
32424
|
for (const [file, content] of written) fs4.writeFileSync(file, content);
|
|
32425
|
+
ensureAppTsconfig(projectDir);
|
|
32402
32426
|
return written.map(([file]) => file);
|
|
32403
32427
|
}
|
|
32404
32428
|
function readCodegenTablesAllowlist(projectDir) {
|
|
@@ -32447,7 +32471,6 @@ async function appCodegen(args) {
|
|
|
32447
32471
|
);
|
|
32448
32472
|
}
|
|
32449
32473
|
await refreshWorkflowGlobals(args.client, projectDir, meta.app_id, Object.keys(meta.workflows ?? {}));
|
|
32450
|
-
if (Object.keys(meta.workflows ?? {}).length > 0) ensureWorkflowTsconfigExcludes(projectDir);
|
|
32451
32474
|
}
|
|
32452
32475
|
async function refreshWorkflowGlobals(client, projectDir, app_id, aliases) {
|
|
32453
32476
|
for (const alias of aliases) {
|
|
@@ -32630,7 +32653,6 @@ async function appPull(client, args) {
|
|
|
32630
32653
|
`Wrote ${written.length} workflow ${written.length === 1 ? "body" : "bodies"} to ${WORKFLOWS_DIR}/ (${written.join(", ")})`
|
|
32631
32654
|
);
|
|
32632
32655
|
}
|
|
32633
|
-
ensureWorkflowTsconfigExcludes(targetPath);
|
|
32634
32656
|
}
|
|
32635
32657
|
console.error(`Installing npm dependencies...`);
|
|
32636
32658
|
await runNpm(["install"], targetPath);
|
|
@@ -32720,10 +32742,14 @@ async function appDeploy(client, args) {
|
|
|
32720
32742
|
// defaulting to `{}` when the manifest declares none — so deleting the
|
|
32721
32743
|
// `capabilities` block turns every capability OFF on the next deploy
|
|
32722
32744
|
// (fail-safe; the declaration is the grant).
|
|
32723
|
-
capabilities: meta.capabilities ?? {}
|
|
32724
|
-
// Workflow
|
|
32725
|
-
// remove_app_workflow own apps.workflows.
|
|
32726
|
-
//
|
|
32745
|
+
capabilities: meta.capabilities ?? {},
|
|
32746
|
+
// Workflow BINDINGS are NOT a deploy concern — set_app_workflow /
|
|
32747
|
+
// remove_app_workflow own apps.workflows. But the alias KEYS of the
|
|
32748
|
+
// manifest's `workflows` map ARE sent (never the bindings): they record
|
|
32749
|
+
// which aliases this bundle declares, so remove_app_workflow can refuse
|
|
32750
|
+
// to unbind an alias the served version still calls. Drop an alias from
|
|
32751
|
+
// the manifest + redeploy to lift that guard before removing its binding.
|
|
32752
|
+
workflow_aliases: Object.keys(meta.workflows ?? {})
|
|
32727
32753
|
});
|
|
32728
32754
|
writeAppMeta(projectDir, {
|
|
32729
32755
|
...meta,
|
|
@@ -32932,6 +32958,25 @@ async function appWorkflowSet(client, args) {
|
|
|
32932
32958
|
console.error(` result.data schema: ${JSON.stringify(result.outputs)}`);
|
|
32933
32959
|
}
|
|
32934
32960
|
}
|
|
32961
|
+
async function appQuerySet(client, args) {
|
|
32962
|
+
const projectDir = process.cwd();
|
|
32963
|
+
const meta = readAppMeta(projectDir);
|
|
32964
|
+
const declaration = meta.queries?.[args.alias];
|
|
32965
|
+
if (!declaration) {
|
|
32966
|
+
console.error(
|
|
32967
|
+
`No query "${args.alias}" in package.json#lotics.queries. Declare it there (alias \u2192 { ast, params? }) first.`
|
|
32968
|
+
);
|
|
32969
|
+
process.exit(1);
|
|
32970
|
+
}
|
|
32971
|
+
const res = await client.setAppQuery(meta.app_id, args.alias, declaration);
|
|
32972
|
+
if (res.error) {
|
|
32973
|
+
console.error(`Failed to set query "${args.alias}": ${res.error}`);
|
|
32974
|
+
process.exit(1);
|
|
32975
|
+
}
|
|
32976
|
+
console.error(
|
|
32977
|
+
`Set query "${args.alias}" on ${meta.app_id}. (apps.queries is manifest-authoritative \u2014 the next 'lotics app deploy' re-syncs it.)`
|
|
32978
|
+
);
|
|
32979
|
+
}
|
|
32935
32980
|
async function appWorkflowPull(client) {
|
|
32936
32981
|
const projectDir = process.cwd();
|
|
32937
32982
|
const meta = readAppMeta(projectDir);
|
|
@@ -32945,7 +32990,7 @@ async function appWorkflowPull(client) {
|
|
|
32945
32990
|
console.error(
|
|
32946
32991
|
`Wrote ${written.length} workflow ${written.length === 1 ? "body" : "bodies"} to ${WORKFLOWS_DIR}/` + (written.length > 0 ? ` (${written.join(", ")})` : "")
|
|
32947
32992
|
);
|
|
32948
|
-
|
|
32993
|
+
ensureAppTsconfig(projectDir);
|
|
32949
32994
|
}
|
|
32950
32995
|
async function appWorkflowCheck(args) {
|
|
32951
32996
|
const projectDir = process.cwd();
|
|
@@ -33040,10 +33085,11 @@ function appUiLink(args) {
|
|
|
33040
33085
|
`No vite.config.ts at ${projectDir}. Run inside a 'lotics app' project directory.`
|
|
33041
33086
|
);
|
|
33042
33087
|
}
|
|
33043
|
-
const
|
|
33044
|
-
|
|
33088
|
+
const explicit = args.uiSrc ?? process.env.LOTICS_UI_SRC;
|
|
33089
|
+
const uiSrc = explicit ? path5.resolve(explicit) : findUiSrcDir(projectDir);
|
|
33090
|
+
if (!uiSrc || !fs4.existsSync(uiSrc) || !fs4.statSync(uiSrc).isDirectory()) {
|
|
33045
33091
|
throw new Error(
|
|
33046
|
-
"Cannot find packages/ui/src by walking up from this directory
|
|
33092
|
+
explicit ? `--ui-src / LOTICS_UI_SRC points at '${explicit}', which is not a directory. Pass the absolute path to the monorepo's packages/ui/src.` : "Cannot find packages/ui/src by walking up from this directory. For an EXTERNAL app (consuming @lotics/ui from npm), pass --ui-src=<abs path to packages/ui/src> or set LOTICS_UI_SRC; inside a monorepo checkout it is found automatically."
|
|
33047
33093
|
);
|
|
33048
33094
|
}
|
|
33049
33095
|
const hasComponent = fs4.existsSync(path5.join(uiSrc, `${args.component}.tsx`)) || fs4.existsSync(path5.join(uiSrc, `${args.component}.ts`)) || fs4.existsSync(path5.join(uiSrc, args.component));
|
|
@@ -33098,6 +33144,7 @@ function parseArgs(argv) {
|
|
|
33098
33144
|
apiKey: void 0,
|
|
33099
33145
|
workspace: void 0,
|
|
33100
33146
|
viewAs: void 0,
|
|
33147
|
+
uiSrc: void 0,
|
|
33101
33148
|
name: void 0,
|
|
33102
33149
|
timezone: void 0,
|
|
33103
33150
|
message: void 0,
|
|
@@ -33139,6 +33186,9 @@ function parseArgs(argv) {
|
|
|
33139
33186
|
case "--view-as":
|
|
33140
33187
|
flags.viewAs = argv[++i2];
|
|
33141
33188
|
break;
|
|
33189
|
+
case "--ui-src":
|
|
33190
|
+
flags.uiSrc = argv[++i2];
|
|
33191
|
+
break;
|
|
33142
33192
|
case "--name":
|
|
33143
33193
|
flags.name = argv[++i2];
|
|
33144
33194
|
break;
|
|
@@ -42644,8 +42694,426 @@ function ensureVmlArray(val) {
|
|
|
42644
42694
|
return Array.isArray(val) ? val : [val];
|
|
42645
42695
|
}
|
|
42646
42696
|
|
|
42697
|
+
// ../xlsx/src/biff8_reader.ts
|
|
42698
|
+
var OLE2_MAGIC2 = [208, 207, 17, 224, 161, 177, 26, 225];
|
|
42699
|
+
var ENDOFCHAIN = 4294967294;
|
|
42700
|
+
var FREESECT = 4294967295;
|
|
42701
|
+
var DEFAULT_MAX_ROWS = 1e4;
|
|
42702
|
+
function isOle2(bytes) {
|
|
42703
|
+
return bytes.length >= 8 && OLE2_MAGIC2.every((b, i2) => bytes[i2] === b);
|
|
42704
|
+
}
|
|
42705
|
+
function readCfbStreams(bytes) {
|
|
42706
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
42707
|
+
const u162 = (o) => dv.getUint16(o, true);
|
|
42708
|
+
const u32 = (o) => dv.getUint32(o, true);
|
|
42709
|
+
const sectorSize = 1 << u162(30);
|
|
42710
|
+
const miniSectorSize = 1 << u162(32);
|
|
42711
|
+
const firstDirSector = u32(48);
|
|
42712
|
+
const miniCutoff = u32(56);
|
|
42713
|
+
const firstMiniFatSector = u32(60);
|
|
42714
|
+
const firstDifatSector = u32(68);
|
|
42715
|
+
if (sectorSize < 512 || sectorSize > 1 << 20) {
|
|
42716
|
+
throw new Error("Unsupported .xls: invalid OLE2 sector size");
|
|
42717
|
+
}
|
|
42718
|
+
const sectorOffset = (n) => sectorSize * (n + 1);
|
|
42719
|
+
const difat = [];
|
|
42720
|
+
for (let i2 = 0; i2 < 109; i2++) {
|
|
42721
|
+
const v = u32(76 + i2 * 4);
|
|
42722
|
+
if (v !== FREESECT) difat.push(v);
|
|
42723
|
+
}
|
|
42724
|
+
let ds = firstDifatSector;
|
|
42725
|
+
const entriesPerSector = sectorSize / 4;
|
|
42726
|
+
for (let guard = 0; ds !== ENDOFCHAIN && ds !== FREESECT && guard < 1 << 20; guard++) {
|
|
42727
|
+
const base = sectorOffset(ds);
|
|
42728
|
+
for (let i2 = 0; i2 < entriesPerSector - 1; i2++) {
|
|
42729
|
+
const v = u32(base + i2 * 4);
|
|
42730
|
+
if (v !== FREESECT) difat.push(v);
|
|
42731
|
+
}
|
|
42732
|
+
ds = u32(base + (entriesPerSector - 1) * 4);
|
|
42733
|
+
}
|
|
42734
|
+
const fat = [];
|
|
42735
|
+
for (const fatSector of difat) {
|
|
42736
|
+
const base = sectorOffset(fatSector);
|
|
42737
|
+
for (let i2 = 0; i2 < entriesPerSector; i2++) fat.push(u32(base + i2 * 4));
|
|
42738
|
+
}
|
|
42739
|
+
const readChain = (src, start, size, ss, offOf, chain) => {
|
|
42740
|
+
const maxSectors = Math.floor(src.length / ss) + 2;
|
|
42741
|
+
const parts = [];
|
|
42742
|
+
let s = start;
|
|
42743
|
+
for (let guard = 0; s !== ENDOFCHAIN && s !== FREESECT && s < chain.length && guard < maxSectors; guard++) {
|
|
42744
|
+
const o = offOf(s);
|
|
42745
|
+
parts.push(src.subarray(o, o + ss));
|
|
42746
|
+
s = chain[s];
|
|
42747
|
+
}
|
|
42748
|
+
const merged = concat(parts);
|
|
42749
|
+
return size != null ? merged.subarray(0, size) : merged;
|
|
42750
|
+
};
|
|
42751
|
+
const readBig = (start, size) => readChain(bytes, start, size, sectorSize, sectorOffset, fat);
|
|
42752
|
+
const dirBytes = readBig(firstDirSector, null);
|
|
42753
|
+
const ddv = new DataView(dirBytes.buffer, dirBytes.byteOffset, dirBytes.byteLength);
|
|
42754
|
+
const dir = [];
|
|
42755
|
+
for (let off = 0; off + 128 <= dirBytes.length; off += 128) {
|
|
42756
|
+
const nameLen = ddv.getUint16(off + 64, true);
|
|
42757
|
+
const type = ddv.getUint8(off + 66);
|
|
42758
|
+
if (nameLen < 2 || type === 0) continue;
|
|
42759
|
+
const name = utf16le(dirBytes.subarray(off, off + nameLen - 2));
|
|
42760
|
+
dir.push({ name, type, start: ddv.getUint32(off + 116, true), size: Number(ddv.getBigUint64(off + 120, true)) });
|
|
42761
|
+
}
|
|
42762
|
+
const root = dir.find((e) => e.type === 5);
|
|
42763
|
+
const miniStream = root ? readBig(root.start, root.size) : new Uint8Array(0);
|
|
42764
|
+
const miniFatBytes = readBig(firstMiniFatSector, null);
|
|
42765
|
+
const miniFat = [];
|
|
42766
|
+
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);
|
|
42767
|
+
const readMini = (start, size) => readChain(miniStream, start, size, miniSectorSize, (n) => n * miniSectorSize, miniFat);
|
|
42768
|
+
const readStream = (e) => e.size >= miniCutoff ? readBig(e.start, e.size) : readMini(e.start, e.size);
|
|
42769
|
+
return dir.filter((e) => e.type === 2).map((e) => ({ name: e.name, bytes: readStream(e) }));
|
|
42770
|
+
}
|
|
42771
|
+
var REC = {
|
|
42772
|
+
FORMULA: 6,
|
|
42773
|
+
EOF: 10,
|
|
42774
|
+
CONTINUE: 60,
|
|
42775
|
+
DATEMODE: 34,
|
|
42776
|
+
FILEPASS: 47,
|
|
42777
|
+
BLANK: 513,
|
|
42778
|
+
NUMBER: 515,
|
|
42779
|
+
LABEL: 516,
|
|
42780
|
+
STRING: 519,
|
|
42781
|
+
BOOLERR: 517,
|
|
42782
|
+
BOUNDSHEET: 133,
|
|
42783
|
+
FORMAT: 1054,
|
|
42784
|
+
XF: 224,
|
|
42785
|
+
RK: 638,
|
|
42786
|
+
MULRK: 189,
|
|
42787
|
+
MULBLANK: 190,
|
|
42788
|
+
LABELSST: 253,
|
|
42789
|
+
SST: 252,
|
|
42790
|
+
BOF: 2057
|
|
42791
|
+
};
|
|
42792
|
+
function* iterRecords(stream, from, to) {
|
|
42793
|
+
const dv = new DataView(stream.buffer, stream.byteOffset, stream.byteLength);
|
|
42794
|
+
let p = from;
|
|
42795
|
+
while (p + 4 <= to) {
|
|
42796
|
+
const type = dv.getUint16(p, true);
|
|
42797
|
+
const len = dv.getUint16(p + 2, true);
|
|
42798
|
+
const bodyStart = p + 4;
|
|
42799
|
+
if (bodyStart + len > stream.length) break;
|
|
42800
|
+
yield { type, body: stream.subarray(bodyStart, bodyStart + len), offset: p };
|
|
42801
|
+
p = bodyStart + len;
|
|
42802
|
+
}
|
|
42803
|
+
}
|
|
42804
|
+
function parseGlobals(stream) {
|
|
42805
|
+
const sstChunks = [];
|
|
42806
|
+
const formats = /* @__PURE__ */ new Map();
|
|
42807
|
+
const xfFormatIds = [];
|
|
42808
|
+
const boundsheets = [];
|
|
42809
|
+
let date1904 = false;
|
|
42810
|
+
let sawSst = false;
|
|
42811
|
+
let sstUnique = 0;
|
|
42812
|
+
let end = stream.length;
|
|
42813
|
+
let started = false;
|
|
42814
|
+
const dv = new DataView(stream.buffer, stream.byteOffset, stream.byteLength);
|
|
42815
|
+
for (const r of iterRecords(stream, 0, stream.length)) {
|
|
42816
|
+
if (r.type === REC.BOF) {
|
|
42817
|
+
if (started) {
|
|
42818
|
+
end = r.offset;
|
|
42819
|
+
break;
|
|
42820
|
+
}
|
|
42821
|
+
started = true;
|
|
42822
|
+
continue;
|
|
42823
|
+
}
|
|
42824
|
+
if (r.type === REC.EOF) {
|
|
42825
|
+
end = r.offset;
|
|
42826
|
+
break;
|
|
42827
|
+
}
|
|
42828
|
+
}
|
|
42829
|
+
for (const r of iterRecords(stream, 0, end)) {
|
|
42830
|
+
switch (r.type) {
|
|
42831
|
+
case REC.FILEPASS:
|
|
42832
|
+
throw new PasswordProtectedError();
|
|
42833
|
+
case REC.DATEMODE:
|
|
42834
|
+
date1904 = readU16(r.body, 0) === 1;
|
|
42835
|
+
break;
|
|
42836
|
+
case REC.SST:
|
|
42837
|
+
sawSst = true;
|
|
42838
|
+
sstUnique = readU32(r.body, 4);
|
|
42839
|
+
sstChunks.push(r.body.subarray(8));
|
|
42840
|
+
break;
|
|
42841
|
+
case REC.CONTINUE:
|
|
42842
|
+
if (sawSst) sstChunks.push(r.body);
|
|
42843
|
+
break;
|
|
42844
|
+
case REC.FORMAT: {
|
|
42845
|
+
const id = readU16(r.body, 0);
|
|
42846
|
+
formats.set(id, readUnicodeShort(r.body, 2, 2));
|
|
42847
|
+
break;
|
|
42848
|
+
}
|
|
42849
|
+
case REC.XF: {
|
|
42850
|
+
xfFormatIds.push(readU16(r.body, 2));
|
|
42851
|
+
break;
|
|
42852
|
+
}
|
|
42853
|
+
case REC.BOUNDSHEET: {
|
|
42854
|
+
const pos = dv.getUint32(r.offset + 4, true);
|
|
42855
|
+
boundsheets.push({ name: readUnicodeShort(r.body, 6, 1), pos });
|
|
42856
|
+
break;
|
|
42857
|
+
}
|
|
42858
|
+
default:
|
|
42859
|
+
break;
|
|
42860
|
+
}
|
|
42861
|
+
}
|
|
42862
|
+
const sst = parseSst(sstChunks, sstUnique);
|
|
42863
|
+
const xfFormats = xfFormatIds.map((id) => formats.get(id) ?? builtinFormat(id));
|
|
42864
|
+
return { sst, date1904, xfFormats, boundsheets };
|
|
42865
|
+
}
|
|
42866
|
+
function parseSst(chunks, count) {
|
|
42867
|
+
const out = [];
|
|
42868
|
+
if (chunks.length === 0) return out;
|
|
42869
|
+
let ci = 0;
|
|
42870
|
+
let off = 0;
|
|
42871
|
+
const atEnd = () => ci >= chunks.length;
|
|
42872
|
+
const cur = () => chunks[ci];
|
|
42873
|
+
const advanceChunk = () => {
|
|
42874
|
+
ci++;
|
|
42875
|
+
off = 0;
|
|
42876
|
+
};
|
|
42877
|
+
const rawU8 = () => {
|
|
42878
|
+
while (!atEnd() && off >= cur().length) advanceChunk();
|
|
42879
|
+
if (atEnd()) return 0;
|
|
42880
|
+
return cur()[off++];
|
|
42881
|
+
};
|
|
42882
|
+
const rawU16 = () => rawU8() | rawU8() << 8;
|
|
42883
|
+
const rawU32 = () => rawU8() | rawU8() << 8 | rawU8() << 16 | rawU8() << 24;
|
|
42884
|
+
const skip = (n) => {
|
|
42885
|
+
for (let i2 = 0; i2 < n; i2++) rawU8();
|
|
42886
|
+
};
|
|
42887
|
+
for (let s = 0; s < count && !atEnd(); s++) {
|
|
42888
|
+
const cch = rawU16();
|
|
42889
|
+
const grbit = rawU8();
|
|
42890
|
+
let high = (grbit & 1) !== 0;
|
|
42891
|
+
const rich = (grbit & 8) !== 0 ? rawU16() : 0;
|
|
42892
|
+
const ext = (grbit & 4) !== 0 ? rawU32() : 0;
|
|
42893
|
+
let str = "";
|
|
42894
|
+
let read = 0;
|
|
42895
|
+
while (read < cch) {
|
|
42896
|
+
if (off >= cur().length) {
|
|
42897
|
+
advanceChunk();
|
|
42898
|
+
if (atEnd()) break;
|
|
42899
|
+
high = (cur()[off++] & 1) !== 0;
|
|
42900
|
+
}
|
|
42901
|
+
if (high) {
|
|
42902
|
+
const code = cur()[off] | cur()[off + 1] << 8;
|
|
42903
|
+
off += 2;
|
|
42904
|
+
str += String.fromCharCode(code);
|
|
42905
|
+
} else {
|
|
42906
|
+
str += String.fromCharCode(cur()[off++]);
|
|
42907
|
+
}
|
|
42908
|
+
read++;
|
|
42909
|
+
}
|
|
42910
|
+
skip(rich * 4 + ext);
|
|
42911
|
+
out.push(str);
|
|
42912
|
+
}
|
|
42913
|
+
return out;
|
|
42914
|
+
}
|
|
42915
|
+
function parseSheet2(stream, start, name, g, maxRows) {
|
|
42916
|
+
const sheet = emptySheet(name);
|
|
42917
|
+
const grid = /* @__PURE__ */ new Map();
|
|
42918
|
+
let maxRow = -1;
|
|
42919
|
+
let truncated = false;
|
|
42920
|
+
const put = (row, col, cell) => {
|
|
42921
|
+
if (row >= maxRows) {
|
|
42922
|
+
truncated = true;
|
|
42923
|
+
return;
|
|
42924
|
+
}
|
|
42925
|
+
let r = grid.get(row);
|
|
42926
|
+
if (!r) {
|
|
42927
|
+
r = /* @__PURE__ */ new Map();
|
|
42928
|
+
grid.set(row, r);
|
|
42929
|
+
}
|
|
42930
|
+
r.set(col, cell);
|
|
42931
|
+
if (row > maxRow) maxRow = row;
|
|
42932
|
+
};
|
|
42933
|
+
let end = stream.length;
|
|
42934
|
+
let seenBof = false;
|
|
42935
|
+
for (const r of iterRecords(stream, start, stream.length)) {
|
|
42936
|
+
if (r.type === REC.BOF) {
|
|
42937
|
+
if (seenBof) {
|
|
42938
|
+
end = r.offset;
|
|
42939
|
+
break;
|
|
42940
|
+
}
|
|
42941
|
+
seenBof = true;
|
|
42942
|
+
continue;
|
|
42943
|
+
}
|
|
42944
|
+
if (r.type === REC.EOF) {
|
|
42945
|
+
end = r.offset;
|
|
42946
|
+
break;
|
|
42947
|
+
}
|
|
42948
|
+
}
|
|
42949
|
+
for (const r of iterRecords(stream, start, end)) {
|
|
42950
|
+
switch (r.type) {
|
|
42951
|
+
case REC.LABELSST: {
|
|
42952
|
+
const row = readU16(r.body, 0), col = readU16(r.body, 2), isst = readU32(r.body, 6);
|
|
42953
|
+
put(row, col, textCell(col, g.sst[isst] ?? ""));
|
|
42954
|
+
break;
|
|
42955
|
+
}
|
|
42956
|
+
case REC.LABEL: {
|
|
42957
|
+
const row = readU16(r.body, 0), col = readU16(r.body, 2);
|
|
42958
|
+
put(row, col, textCell(col, readUnicodeShort(r.body, 6, 2)));
|
|
42959
|
+
break;
|
|
42960
|
+
}
|
|
42961
|
+
case REC.NUMBER: {
|
|
42962
|
+
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4);
|
|
42963
|
+
put(row, col, numberCell(col, readF64(r.body, 6), g.xfFormats[xf]));
|
|
42964
|
+
break;
|
|
42965
|
+
}
|
|
42966
|
+
case REC.RK: {
|
|
42967
|
+
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4);
|
|
42968
|
+
put(row, col, numberCell(col, decodeRk(readU32(r.body, 6)), g.xfFormats[xf]));
|
|
42969
|
+
break;
|
|
42970
|
+
}
|
|
42971
|
+
case REC.MULRK: {
|
|
42972
|
+
const row = readU16(r.body, 0), first2 = readU16(r.body, 2);
|
|
42973
|
+
const n = (r.body.length - 6) / 6;
|
|
42974
|
+
for (let i2 = 0; i2 < n; i2++) {
|
|
42975
|
+
const xf = readU16(r.body, 4 + i2 * 6);
|
|
42976
|
+
const rk = readU32(r.body, 6 + i2 * 6);
|
|
42977
|
+
put(row, first2 + i2, numberCell(first2 + i2, decodeRk(rk), g.xfFormats[xf]));
|
|
42978
|
+
}
|
|
42979
|
+
break;
|
|
42980
|
+
}
|
|
42981
|
+
case REC.FORMULA: {
|
|
42982
|
+
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4);
|
|
42983
|
+
const cell = formulaCell(col, r.body, g.xfFormats[xf]);
|
|
42984
|
+
if (cell) put(row, col, cell);
|
|
42985
|
+
break;
|
|
42986
|
+
}
|
|
42987
|
+
// BLANK / MULBLANK / BOOLERR carry no data value we surface — skipped.
|
|
42988
|
+
default:
|
|
42989
|
+
break;
|
|
42990
|
+
}
|
|
42991
|
+
}
|
|
42992
|
+
const rows = [];
|
|
42993
|
+
for (let ri = 0; ri <= maxRow; ri++) {
|
|
42994
|
+
const r = grid.get(ri);
|
|
42995
|
+
if (!r) continue;
|
|
42996
|
+
const cells = [...r.values()].sort((a, b) => a.column - b.column);
|
|
42997
|
+
rows.push({ index: ri, height: sheet.defaultRowHeight, cells, hidden: false });
|
|
42998
|
+
}
|
|
42999
|
+
sheet.rows = rows;
|
|
43000
|
+
sheet.totalRowCount = maxRow + 1;
|
|
43001
|
+
sheet.truncated = truncated;
|
|
43002
|
+
return sheet;
|
|
43003
|
+
}
|
|
43004
|
+
function textCell(column, text) {
|
|
43005
|
+
return { column, value: text, typedValue: text, content: { type: "plain", text }, style: {} };
|
|
43006
|
+
}
|
|
43007
|
+
function numberCell(column, num, numFmt) {
|
|
43008
|
+
const value = Number.isFinite(num) ? String(num) : "";
|
|
43009
|
+
return {
|
|
43010
|
+
column,
|
|
43011
|
+
value,
|
|
43012
|
+
rawValue: num,
|
|
43013
|
+
typedValue: num,
|
|
43014
|
+
numFmtCode: numFmt && numFmt !== "General" ? numFmt : void 0,
|
|
43015
|
+
content: { type: "plain", text: value },
|
|
43016
|
+
style: {}
|
|
43017
|
+
};
|
|
43018
|
+
}
|
|
43019
|
+
function formulaCell(column, body, numFmt) {
|
|
43020
|
+
if (readU16(body, 12) === 65535) {
|
|
43021
|
+
const kind = body[6];
|
|
43022
|
+
if (kind === 1) {
|
|
43023
|
+
const b = body[8] !== 0;
|
|
43024
|
+
return { column, value: b ? "TRUE" : "FALSE", typedValue: b, content: { type: "plain", text: b ? "TRUE" : "FALSE" }, style: {} };
|
|
43025
|
+
}
|
|
43026
|
+
return null;
|
|
43027
|
+
}
|
|
43028
|
+
return numberCell(column, readF64(body, 6), numFmt);
|
|
43029
|
+
}
|
|
43030
|
+
function decodeRk(rk) {
|
|
43031
|
+
const div100 = (rk & 1) !== 0;
|
|
43032
|
+
const isInt = (rk & 2) !== 0;
|
|
43033
|
+
let n;
|
|
43034
|
+
if (isInt) {
|
|
43035
|
+
n = rk >> 2;
|
|
43036
|
+
} else {
|
|
43037
|
+
const buf = new ArrayBuffer(8);
|
|
43038
|
+
new DataView(buf).setUint32(4, rk & 4294967292, true);
|
|
43039
|
+
n = new DataView(buf).getFloat64(0, true);
|
|
43040
|
+
}
|
|
43041
|
+
return div100 ? n / 100 : n;
|
|
43042
|
+
}
|
|
43043
|
+
function readU16(b, o) {
|
|
43044
|
+
return b[o] | b[o + 1] << 8;
|
|
43045
|
+
}
|
|
43046
|
+
function readU32(b, o) {
|
|
43047
|
+
return (b[o] | b[o + 1] << 8 | b[o + 2] << 16 | b[o + 3] << 24) >>> 0;
|
|
43048
|
+
}
|
|
43049
|
+
function readF64(b, o) {
|
|
43050
|
+
return new DataView(b.buffer, b.byteOffset + o, 8).getFloat64(0, true);
|
|
43051
|
+
}
|
|
43052
|
+
function readUnicodeShort(b, offset, lenBytes) {
|
|
43053
|
+
const cch = lenBytes === 1 ? b[offset] : readU16(b, offset);
|
|
43054
|
+
const grbit = b[offset + lenBytes];
|
|
43055
|
+
const high = (grbit & 1) !== 0;
|
|
43056
|
+
let p = offset + lenBytes + 1;
|
|
43057
|
+
let s = "";
|
|
43058
|
+
for (let i2 = 0; i2 < cch; i2++) {
|
|
43059
|
+
if (high) {
|
|
43060
|
+
s += String.fromCharCode(b[p] | b[p + 1] << 8);
|
|
43061
|
+
p += 2;
|
|
43062
|
+
} else {
|
|
43063
|
+
s += String.fromCharCode(b[p]);
|
|
43064
|
+
p += 1;
|
|
43065
|
+
}
|
|
43066
|
+
}
|
|
43067
|
+
return s;
|
|
43068
|
+
}
|
|
43069
|
+
function utf16le(b) {
|
|
43070
|
+
let s = "";
|
|
43071
|
+
for (let i2 = 0; i2 + 1 < b.length; i2 += 2) s += String.fromCharCode(b[i2] | b[i2 + 1] << 8);
|
|
43072
|
+
return s;
|
|
43073
|
+
}
|
|
43074
|
+
function concat(parts) {
|
|
43075
|
+
let total = 0;
|
|
43076
|
+
for (const p of parts) total += p.length;
|
|
43077
|
+
const out = new Uint8Array(total);
|
|
43078
|
+
let o = 0;
|
|
43079
|
+
for (const p of parts) {
|
|
43080
|
+
out.set(p, o);
|
|
43081
|
+
o += p.length;
|
|
43082
|
+
}
|
|
43083
|
+
return out;
|
|
43084
|
+
}
|
|
43085
|
+
function builtinFormat(id) {
|
|
43086
|
+
const DATES = {
|
|
43087
|
+
14: "m/d/yyyy",
|
|
43088
|
+
15: "d-mmm-yy",
|
|
43089
|
+
16: "d-mmm",
|
|
43090
|
+
17: "mmm-yy",
|
|
43091
|
+
18: "h:mm AM/PM",
|
|
43092
|
+
19: "h:mm:ss AM/PM",
|
|
43093
|
+
20: "h:mm",
|
|
43094
|
+
21: "h:mm:ss",
|
|
43095
|
+
22: "m/d/yyyy h:mm",
|
|
43096
|
+
45: "mm:ss",
|
|
43097
|
+
46: "[h]:mm:ss",
|
|
43098
|
+
47: "mm:ss.0"
|
|
43099
|
+
};
|
|
43100
|
+
return DATES[id] ?? "General";
|
|
43101
|
+
}
|
|
43102
|
+
function parseBiff8(bytes, options) {
|
|
43103
|
+
const streams = readCfbStreams(bytes);
|
|
43104
|
+
if (streams.some((s) => /^EncryptedPackage$/i.test(s.name))) throw new PasswordProtectedError();
|
|
43105
|
+
const wb = streams.find((s) => /^workbook$/i.test(s.name)) ?? streams.find((s) => /^book$/i.test(s.name));
|
|
43106
|
+
if (!wb) throw new Error("Not a valid .xls: no Workbook stream in the OLE2 container");
|
|
43107
|
+
const g = parseGlobals(wb.bytes);
|
|
43108
|
+
const maxRows = options?.maxRowsPerSheet ?? DEFAULT_MAX_ROWS;
|
|
43109
|
+
const sheets = g.boundsheets.length > 0 ? g.boundsheets.map((bs) => parseSheet2(wb.bytes, bs.pos, bs.name, g, maxRows)) : [emptySheet("Sheet1")];
|
|
43110
|
+
return { sheets, activeSheetIndex: 0 };
|
|
43111
|
+
}
|
|
43112
|
+
|
|
42647
43113
|
// ../xlsx/src/excel_parser.ts
|
|
42648
43114
|
function parseExcelBuffer(arrayBuffer, options) {
|
|
43115
|
+
const bytes = new Uint8Array(arrayBuffer);
|
|
43116
|
+
if (isOle2(bytes)) return parseBiff8(bytes, options);
|
|
42649
43117
|
const zip = unzipXlsx(arrayBuffer);
|
|
42650
43118
|
return parseExcelFromZip(zip, options);
|
|
42651
43119
|
}
|
|
@@ -49222,11 +49690,16 @@ COMMANDS
|
|
|
49222
49690
|
lotics app workflow pull Rewrite src/workflows/*.ts from the server
|
|
49223
49691
|
lotics app workflow check [alias] Typecheck src/workflows bodies locally (one
|
|
49224
49692
|
isolated program per alias; the app's own tsc)
|
|
49693
|
+
lotics app query set <alias> Push package.json#lotics.queries.<alias> to
|
|
49694
|
+
apps.queries via set_app_query (no deploy;
|
|
49695
|
+
re-synced by the next deploy from the manifest)
|
|
49225
49696
|
lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address
|
|
49226
49697
|
lotics app rename "<new name>" Rename the app's display name (launcher title)
|
|
49227
49698
|
lotics app dev [path] Run the app locally with HMR (RPC forwarded to prod)
|
|
49228
|
-
lotics ui link <component> [--
|
|
49229
|
-
packages/ui/src
|
|
49699
|
+
lotics ui link <component> [--ui-src <path>] [--remove]
|
|
49700
|
+
Dev-link @lotics/ui to packages/ui/src (Vite alias
|
|
49701
|
+
+ tsc paths) for live HMR + typecheck. Monorepo apps
|
|
49702
|
+
auto-find it; external apps pass --ui-src / LOTICS_UI_SRC
|
|
49230
49703
|
lotics xlsx <subcommand> ... Read/write/edit .xlsx files on your local filesystem
|
|
49231
49704
|
(uses the bundled Lotics xlsx engine; prefer over
|
|
49232
49705
|
npm xlsx/exceljs for round-trip fidelity)
|
|
@@ -49590,15 +50063,16 @@ async function main() {
|
|
|
49590
50063
|
if (subcommand === "link") {
|
|
49591
50064
|
const component = toolArgs;
|
|
49592
50065
|
if (!component) {
|
|
49593
|
-
console.error("Usage: lotics ui link <component> [--remove]");
|
|
49594
|
-
console.error("Dev-links @lotics/ui to
|
|
50066
|
+
console.error("Usage: lotics ui link <component> [--ui-src <abs path>] [--remove]");
|
|
50067
|
+
console.error("Dev-links @lotics/ui to packages/ui/src (Vite + tsc) for live HMR + typecheck.");
|
|
50068
|
+
console.error("Monorepo apps find packages/ui/src automatically; external apps pass --ui-src / LOTICS_UI_SRC.");
|
|
49595
50069
|
process.exit(1);
|
|
49596
50070
|
}
|
|
49597
|
-
appUiLink({ component, remove: restArgs.includes("--remove") });
|
|
50071
|
+
appUiLink({ component, uiSrc: flags.uiSrc, remove: restArgs.includes("--remove") });
|
|
49598
50072
|
return;
|
|
49599
50073
|
}
|
|
49600
50074
|
console.error(`Unknown ui subcommand: ${subcommand ?? "(none)"}`);
|
|
49601
|
-
console.error("Usage: lotics ui link <component> [--remove]");
|
|
50075
|
+
console.error("Usage: lotics ui link <component> [--ui-src <abs path>] [--remove]");
|
|
49602
50076
|
process.exit(1);
|
|
49603
50077
|
}
|
|
49604
50078
|
if (command === "app" && subcommand === "workflow" && toolArgs === "check") {
|
|
@@ -49691,6 +50165,7 @@ async function main() {
|
|
|
49691
50165
|
console.error(" lotics app workflow set <alias> Push the edited src/workflows/<alias>.ts body");
|
|
49692
50166
|
console.error(" lotics app workflow pull Rewrite src/workflows/*.ts from the server");
|
|
49693
50167
|
console.error(" lotics app workflow check [alias] Typecheck src/workflows bodies locally");
|
|
50168
|
+
console.error(" lotics app query set <alias> Push lotics.queries.<alias> to apps.queries (no deploy)");
|
|
49694
50169
|
console.error(" lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address");
|
|
49695
50170
|
console.error(` lotics app rename "<new name>" Rename the app's display name (launcher title)`);
|
|
49696
50171
|
console.error(" lotics app dev [path] Run the app locally with HMR + RPC forwarding");
|
|
@@ -49896,6 +50371,26 @@ Available workspaces:`);
|
|
|
49896
50371
|
}
|
|
49897
50372
|
workflowUsage();
|
|
49898
50373
|
}
|
|
50374
|
+
if (subcommand === "query") {
|
|
50375
|
+
const action = toolArgs;
|
|
50376
|
+
if (action === "set") {
|
|
50377
|
+
const alias = restArgs[0];
|
|
50378
|
+
if (!alias) {
|
|
50379
|
+
console.error("Usage: lotics app query set <alias>");
|
|
50380
|
+
console.error(
|
|
50381
|
+
"Pushes package.json#lotics.queries.<alias> to apps.queries via set_app_query (no deploy)."
|
|
50382
|
+
);
|
|
50383
|
+
process.exit(1);
|
|
50384
|
+
}
|
|
50385
|
+
await appQuerySet(client, { alias });
|
|
50386
|
+
return;
|
|
50387
|
+
}
|
|
50388
|
+
console.error("Usage:");
|
|
50389
|
+
console.error(
|
|
50390
|
+
" lotics app query set <alias> Push package.json#lotics.queries.<alias> to apps.queries (no deploy)"
|
|
50391
|
+
);
|
|
50392
|
+
process.exit(1);
|
|
50393
|
+
}
|
|
49899
50394
|
if (subcommand === "dev") {
|
|
49900
50395
|
const projectDir = toolArgs;
|
|
49901
50396
|
let port;
|