@lotics/cli 0.186.0 → 0.187.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 +4 -4
- package/dist/src/cli.js +1819 -1372
- package/dist/src/client.js +1 -1
- package/docs/building_an_app.md +3 -1
- package/docs/cli_reference.md +3 -3
- package/package.json +1 -1
package/dist/src/cli.js
CHANGED
|
@@ -45218,7 +45218,7 @@ var LoticsClient = class {
|
|
|
45218
45218
|
while (filled < length2) {
|
|
45219
45219
|
const { bytesRead } = await handle.read(buffer, filled, length2 - filled, offset + filled);
|
|
45220
45220
|
if (bytesRead === 0) {
|
|
45221
|
-
throw new
|
|
45221
|
+
throw new PermanentPartError(
|
|
45222
45222
|
`${input.filename} ended after ${offset + filled} bytes, short of the ${input.size} it reported \u2014 it changed while uploading`
|
|
45223
45223
|
);
|
|
45224
45224
|
}
|
|
@@ -45875,7 +45875,7 @@ function resultSideEffects(result) {
|
|
|
45875
45875
|
}
|
|
45876
45876
|
|
|
45877
45877
|
// src/version.ts
|
|
45878
|
-
var VERSION = "0.
|
|
45878
|
+
var VERSION = "0.187.0";
|
|
45879
45879
|
|
|
45880
45880
|
// src/timezone.ts
|
|
45881
45881
|
function machineTimezone() {
|
|
@@ -46146,7 +46146,7 @@ var COMMANDS = [
|
|
|
46146
46146
|
help: [
|
|
46147
46147
|
" lotics app create <name> [path] Create a new custom-code app + scaffold locally",
|
|
46148
46148
|
" lotics app pull <app_id> [path] Bootstrap full local env (source + npm install + types)",
|
|
46149
|
-
" lotics app deploy [--prune] -m <msg>
|
|
46149
|
+
" lotics app deploy [--prune] -m <msg> Typecheck + build + upload current dir as a new version \u2014 COMMIT",
|
|
46150
46150
|
" (-m is required \u2014 it's the version's audit trail;",
|
|
46151
46151
|
" carries code + queries only \u2014 workflow bindings are",
|
|
46152
46152
|
" managed by set_app_workflow / remove_app_workflow.",
|
|
@@ -46159,7 +46159,8 @@ var COMMANDS = [
|
|
|
46159
46159
|
" lotics app codegen [path] Regenerate .lotics/* (types + field/option ids)",
|
|
46160
46160
|
" from the manifest + workspace schema \u2014 no deploy",
|
|
46161
46161
|
" lotics app check Run every deploy pre-flight WITHOUT building or",
|
|
46162
|
-
" shipping:
|
|
46162
|
+
" shipping: the app's own typecheck over regenerated",
|
|
46163
|
+
" .lotics types, agent schemas vs the live app, workflow",
|
|
46163
46164
|
" declarations and BODIES vs what is live, aliases",
|
|
46164
46165
|
" the code calls but nothing bound, undeclared",
|
|
46165
46166
|
" capabilities, query drift. Plus two rules no",
|
|
@@ -46174,8 +46175,9 @@ var COMMANDS = [
|
|
|
46174
46175
|
" lotics app workflow check [alias] Typecheck src/workflows bodies locally (one",
|
|
46175
46176
|
" isolated program per alias; the app's own tsc)",
|
|
46176
46177
|
" lotics app query set <alias> Push package.json#lotics.queries.<alias> to",
|
|
46177
|
-
" apps.queries via set_app_query
|
|
46178
|
-
" re-synced by
|
|
46178
|
+
" apps.queries via set_app_query and regenerate",
|
|
46179
|
+
" .lotics/app_queries.d.ts (no deploy; re-synced by",
|
|
46180
|
+
" the next deploy from the manifest)",
|
|
46179
46181
|
" lotics app agent set <alias> Push the edited src/agents/<alias>.md instructions,",
|
|
46180
46182
|
" and ONLY those \u2014 the server merges, so the typed",
|
|
46181
46183
|
" fields keep whatever is bound (a manifest is a",
|
|
@@ -48177,605 +48179,6 @@ function flushPendingWarnings() {
|
|
|
48177
48179
|
collectedWarnings.length = 0;
|
|
48178
48180
|
}
|
|
48179
48181
|
|
|
48180
|
-
// ../shared/src/app_dts.ts
|
|
48181
|
-
var IDENTIFIER_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
48182
|
-
function isValidIdentifier(name2) {
|
|
48183
|
-
return IDENTIFIER_REGEX.test(name2);
|
|
48184
|
-
}
|
|
48185
|
-
function inputsToType(inputs, opts) {
|
|
48186
|
-
const nullableOptional = opts?.nullableOptional === true;
|
|
48187
|
-
const fields = [];
|
|
48188
|
-
for (const [key, decl] of Object.entries(inputs)) {
|
|
48189
|
-
if (decl === null || typeof decl !== "object") continue;
|
|
48190
|
-
const d = decl;
|
|
48191
|
-
const tsType = inputDeclToTsType(d);
|
|
48192
|
-
const isOptional = d.required === false;
|
|
48193
|
-
const fieldType = isOptional && nullableOptional ? `${tsType} | null` : tsType;
|
|
48194
|
-
const optional2 = isOptional ? "?" : "";
|
|
48195
|
-
const fieldKey = isValidIdentifier(key) ? key : JSON.stringify(key);
|
|
48196
|
-
fields.push(` ${fieldKey}${optional2}: ${fieldType};`);
|
|
48197
|
-
}
|
|
48198
|
-
if (fields.length === 0) return "Record<string, never>";
|
|
48199
|
-
return `{
|
|
48200
|
-
${fields.join("\n")}
|
|
48201
|
-
}`;
|
|
48202
|
-
}
|
|
48203
|
-
function inputDeclToTsType(decl) {
|
|
48204
|
-
const type = decl.type;
|
|
48205
|
-
switch (type) {
|
|
48206
|
-
case "text":
|
|
48207
|
-
case "email":
|
|
48208
|
-
case "date":
|
|
48209
|
-
case "datetime":
|
|
48210
|
-
return "string";
|
|
48211
|
-
case "number":
|
|
48212
|
-
return "number";
|
|
48213
|
-
case "boolean":
|
|
48214
|
-
return "boolean";
|
|
48215
|
-
case "record_link":
|
|
48216
|
-
case "member": {
|
|
48217
|
-
const inner = "string";
|
|
48218
|
-
return decl.multi === true ? `ReadonlyArray<${inner}>` : inner;
|
|
48219
|
-
}
|
|
48220
|
-
case "select": {
|
|
48221
|
-
const options = Array.isArray(decl.options) ? decl.options : [];
|
|
48222
|
-
const literals = options.map((o) => {
|
|
48223
|
-
if (o !== null && typeof o === "object" && "value" in o && typeof o.value === "string") {
|
|
48224
|
-
return JSON.stringify(o.value);
|
|
48225
|
-
}
|
|
48226
|
-
return null;
|
|
48227
|
-
}).filter((v) => v !== null);
|
|
48228
|
-
const inner = literals.length > 0 ? `${literals.join(" | ")} | (string & {})` : "string";
|
|
48229
|
-
return decl.multi === true ? `ReadonlyArray<${inner}>` : inner;
|
|
48230
|
-
}
|
|
48231
|
-
case "date_range":
|
|
48232
|
-
return "{ start: string; end: string }";
|
|
48233
|
-
case "file":
|
|
48234
|
-
return decl.multi === true ? "ReadonlyArray<string>" : "string";
|
|
48235
|
-
case "object": {
|
|
48236
|
-
const fields = decl.fields !== null && typeof decl.fields === "object" ? decl.fields : {};
|
|
48237
|
-
return inputsToType(fields);
|
|
48238
|
-
}
|
|
48239
|
-
case "array": {
|
|
48240
|
-
const items = decl.items !== null && typeof decl.items === "object" ? decl.items : null;
|
|
48241
|
-
return items ? `ReadonlyArray<${inputDeclToTsType(items)}>` : "ReadonlyArray<unknown>";
|
|
48242
|
-
}
|
|
48243
|
-
case "json":
|
|
48244
|
-
return "unknown";
|
|
48245
|
-
default:
|
|
48246
|
-
return "unknown";
|
|
48247
|
-
}
|
|
48248
|
-
}
|
|
48249
|
-
function objectFieldsToType(fields) {
|
|
48250
|
-
const parts = [];
|
|
48251
|
-
for (const [key, decl] of Object.entries(fields)) {
|
|
48252
|
-
if (decl === null || typeof decl !== "object") continue;
|
|
48253
|
-
const d = decl;
|
|
48254
|
-
const optional2 = d.required === false ? "?" : "";
|
|
48255
|
-
const fieldKey = isValidIdentifier(key) ? key : JSON.stringify(key);
|
|
48256
|
-
parts.push(`${fieldKey}${optional2}: ${outputDeclToTsType(d)}`);
|
|
48257
|
-
}
|
|
48258
|
-
if (parts.length === 0) return "Record<string, never>";
|
|
48259
|
-
return `{ ${parts.join("; ")} }`;
|
|
48260
|
-
}
|
|
48261
|
-
function outputDeclToTsType(decl) {
|
|
48262
|
-
const type = decl.type;
|
|
48263
|
-
switch (type) {
|
|
48264
|
-
case "text":
|
|
48265
|
-
case "email":
|
|
48266
|
-
case "date":
|
|
48267
|
-
case "datetime":
|
|
48268
|
-
return "string";
|
|
48269
|
-
case "number":
|
|
48270
|
-
return "number";
|
|
48271
|
-
case "boolean":
|
|
48272
|
-
return "boolean";
|
|
48273
|
-
case "record_link":
|
|
48274
|
-
return decl.multi === true ? "ReadonlyArray<string>" : "string";
|
|
48275
|
-
case "select": {
|
|
48276
|
-
const options = Array.isArray(decl.options) ? decl.options : [];
|
|
48277
|
-
const literals = options.map(
|
|
48278
|
-
(o) => o !== null && typeof o === "object" && "value" in o && typeof o.value === "string" ? JSON.stringify(o.value) : null
|
|
48279
|
-
).filter((v) => v !== null);
|
|
48280
|
-
const inner = literals.length > 0 ? `${literals.join(" | ")} | (string & {})` : "string";
|
|
48281
|
-
return decl.multi === true ? `ReadonlyArray<${inner}>` : inner;
|
|
48282
|
-
}
|
|
48283
|
-
case "object": {
|
|
48284
|
-
const fields = decl.fields !== null && typeof decl.fields === "object" ? decl.fields : {};
|
|
48285
|
-
return objectFieldsToType(fields);
|
|
48286
|
-
}
|
|
48287
|
-
case "array": {
|
|
48288
|
-
const items = decl.items !== null && typeof decl.items === "object" ? decl.items : null;
|
|
48289
|
-
return items ? `ReadonlyArray<${outputDeclToTsType(items)}>` : "ReadonlyArray<unknown>";
|
|
48290
|
-
}
|
|
48291
|
-
case "json":
|
|
48292
|
-
return "unknown";
|
|
48293
|
-
default:
|
|
48294
|
-
return "unknown";
|
|
48295
|
-
}
|
|
48296
|
-
}
|
|
48297
|
-
var QUERIES_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
48298
|
-
// DO NOT EDIT \u2014 regenerated from package.json#lotics.queries.
|
|
48299
|
-
//
|
|
48300
|
-
// This file gives \`useQuery("alias", params)\` typed params at call sites by
|
|
48301
|
-
// augmenting the @lotics/app-sdk \`AppQueries\` interface.
|
|
48302
|
-
|
|
48303
|
-
import "@lotics/app-sdk";
|
|
48304
|
-
`;
|
|
48305
|
-
function generateAppQueriesDts(queries) {
|
|
48306
|
-
const entries2 = Object.entries(queries ?? {});
|
|
48307
|
-
if (entries2.length === 0) {
|
|
48308
|
-
return `${QUERIES_HEADER}
|
|
48309
|
-
// No queries declared in package.json#lotics.queries.
|
|
48310
|
-
// Add an entry to enable typed useQuery("alias", params) at call sites.
|
|
48311
|
-
declare module "@lotics/app-sdk" {
|
|
48312
|
-
interface AppQueries {}
|
|
48313
|
-
}
|
|
48314
|
-
`;
|
|
48315
|
-
}
|
|
48316
|
-
entries2.sort(([a], [b]) => a.localeCompare(b));
|
|
48317
|
-
const lines = [];
|
|
48318
|
-
for (const [alias, declaration] of entries2) {
|
|
48319
|
-
const valueType = inputsToType(declaration.params ?? {});
|
|
48320
|
-
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
48321
|
-
lines.push(` ${aliasKey}: ${valueType};`);
|
|
48322
|
-
}
|
|
48323
|
-
return `${QUERIES_HEADER}
|
|
48324
|
-
declare module "@lotics/app-sdk" {
|
|
48325
|
-
interface AppQueries {
|
|
48326
|
-
${lines.join("\n")}
|
|
48327
|
-
}
|
|
48328
|
-
}
|
|
48329
|
-
`;
|
|
48330
|
-
}
|
|
48331
|
-
var WORKFLOWS_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
48332
|
-
// DO NOT EDIT \u2014 regenerated from package.json#lotics.workflows.
|
|
48333
|
-
//
|
|
48334
|
-
// This file gives \`useWorkflow("alias")\` a typed input parameter at call
|
|
48335
|
-
// sites by augmenting the @lotics/app-sdk \`AppWorkflows\` interface.
|
|
48336
|
-
|
|
48337
|
-
import "@lotics/app-sdk";
|
|
48338
|
-
`;
|
|
48339
|
-
function generateAppWorkflowsDts(workflows) {
|
|
48340
|
-
const entries2 = Object.entries(workflows ?? {});
|
|
48341
|
-
if (entries2.length === 0) {
|
|
48342
|
-
return `${WORKFLOWS_HEADER}
|
|
48343
|
-
// No workflows declared in package.json#lotics.workflows.
|
|
48344
|
-
// Add an entry to enable typed useWorkflow<"alias"> at call sites.
|
|
48345
|
-
declare module "@lotics/app-sdk" {
|
|
48346
|
-
interface AppWorkflows {}
|
|
48347
|
-
}
|
|
48348
|
-
`;
|
|
48349
|
-
}
|
|
48350
|
-
entries2.sort(([a], [b]) => a.localeCompare(b));
|
|
48351
|
-
const inputLines = [];
|
|
48352
|
-
const resultLines = [];
|
|
48353
|
-
for (const [alias, declaration] of entries2) {
|
|
48354
|
-
const valueType = declaration.inputs ? inputsToType(declaration.inputs, { nullableOptional: true }) : "Record<string, unknown>";
|
|
48355
|
-
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
48356
|
-
inputLines.push(` ${aliasKey}: ${valueType};`);
|
|
48357
|
-
if (declaration.outputs) {
|
|
48358
|
-
resultLines.push(` ${aliasKey}: ${objectFieldsToType(declaration.outputs)};`);
|
|
48359
|
-
}
|
|
48360
|
-
}
|
|
48361
|
-
const resultsBlock = resultLines.length > 0 ? `
|
|
48362
|
-
interface AppWorkflowResults {
|
|
48363
|
-
${resultLines.join("\n")}
|
|
48364
|
-
}` : "";
|
|
48365
|
-
return `${WORKFLOWS_HEADER}
|
|
48366
|
-
declare module "@lotics/app-sdk" {
|
|
48367
|
-
interface AppWorkflows {
|
|
48368
|
-
${inputLines.join("\n")}
|
|
48369
|
-
}${resultsBlock}
|
|
48370
|
-
}
|
|
48371
|
-
`;
|
|
48372
|
-
}
|
|
48373
|
-
var AGENTS_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
48374
|
-
// DO NOT EDIT \u2014 regenerated from package.json#lotics.agents.
|
|
48375
|
-
//
|
|
48376
|
-
// This file gives \`useAgentRun("alias")\` typed input + output at call sites by
|
|
48377
|
-
// augmenting the @lotics/app-sdk \`AppAgents\` / \`AppAgentResults\` interfaces.
|
|
48378
|
-
|
|
48379
|
-
import "@lotics/app-sdk";
|
|
48380
|
-
`;
|
|
48381
|
-
function generateAppAgentsDts(agents) {
|
|
48382
|
-
const entries2 = Object.entries(agents ?? {});
|
|
48383
|
-
if (entries2.length === 0) {
|
|
48384
|
-
return `${AGENTS_HEADER}
|
|
48385
|
-
// No agents declared in package.json#lotics.agents.
|
|
48386
|
-
// Add an entry to enable typed useAgentRun<"alias"> at call sites.
|
|
48387
|
-
declare module "@lotics/app-sdk" {
|
|
48388
|
-
interface AppAgents {}
|
|
48389
|
-
}
|
|
48390
|
-
`;
|
|
48391
|
-
}
|
|
48392
|
-
entries2.sort(([a], [b]) => a.localeCompare(b));
|
|
48393
|
-
const inputLines = [];
|
|
48394
|
-
const resultLines = [];
|
|
48395
|
-
for (const [alias, declaration] of entries2) {
|
|
48396
|
-
const valueType = declaration.inputs ? inputsToType(declaration.inputs) : "Record<string, unknown>";
|
|
48397
|
-
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
48398
|
-
inputLines.push(` ${aliasKey}: ${valueType};`);
|
|
48399
|
-
if (declaration.outputs) {
|
|
48400
|
-
resultLines.push(` ${aliasKey}: ${objectFieldsToType(declaration.outputs)};`);
|
|
48401
|
-
}
|
|
48402
|
-
}
|
|
48403
|
-
const resultsBlock = resultLines.length > 0 ? `
|
|
48404
|
-
interface AppAgentResults {
|
|
48405
|
-
${resultLines.join("\n")}
|
|
48406
|
-
}` : "";
|
|
48407
|
-
return `${AGENTS_HEADER}
|
|
48408
|
-
declare module "@lotics/app-sdk" {
|
|
48409
|
-
interface AppAgents {
|
|
48410
|
-
${inputLines.join("\n")}
|
|
48411
|
-
}${resultsBlock}
|
|
48412
|
-
}
|
|
48413
|
-
`;
|
|
48414
|
-
}
|
|
48415
|
-
var LINK_TSCONFIG_PATH = ".lotics/tsconfig.link.json";
|
|
48416
|
-
function generateLinkTsconfig(paths) {
|
|
48417
|
-
const header = Object.keys(paths).length > 0 ? `// GENERATED by \`lotics app codegen\` \u2014 do not edit.
|
|
48418
|
-
// LOTICS_UI_SRC is set, so @lotics/ui resolves to your working copy for tsc,
|
|
48419
|
-
// vitest, eslint and your editor \u2014 the same copy Vite is bundling. The peer
|
|
48420
|
-
// pins keep ONE react / react-native in the program; without them the kit's
|
|
48421
|
-
// source resolves its own copies and every shared type stops matching.
|
|
48422
|
-
// Unset LOTICS_UI_SRC and re-run to go back to the published kit.
|
|
48423
|
-
` : `// GENERATED by \`lotics app codegen\` \u2014 do not edit.
|
|
48424
|
-
// @lotics/ui resolves from node_modules as normal, so this is inert. It still
|
|
48425
|
-
// has to exist: tsconfig.json extends it, and a missing extends target fails
|
|
48426
|
-
// the build outright.
|
|
48427
|
-
`;
|
|
48428
|
-
return `${header}${JSON.stringify({ compilerOptions: { paths } }, null, 2)}
|
|
48429
|
-
`;
|
|
48430
|
-
}
|
|
48431
|
-
var CAPABILITY_GATED_CALLS = {
|
|
48432
|
-
comments: ["useComments", "createComment", "updateComment", "deleteComment"]
|
|
48433
|
-
};
|
|
48434
|
-
function undeclaredCapabilities(sourceText, declared) {
|
|
48435
|
-
const code = codeWithoutComments(sourceText);
|
|
48436
|
-
const used = [];
|
|
48437
|
-
for (const [capability, calls] of Object.entries(CAPABILITY_GATED_CALLS)) {
|
|
48438
|
-
const isCalled = calls.some((call) => new RegExp(`\\b${call}\\b`).test(code));
|
|
48439
|
-
if (isCalled && declared?.[capability] !== true) used.push(capability);
|
|
48440
|
-
}
|
|
48441
|
-
return used;
|
|
48442
|
-
}
|
|
48443
|
-
function driftedQueryAliases(a, b) {
|
|
48444
|
-
const left = a ?? {};
|
|
48445
|
-
const right = b ?? {};
|
|
48446
|
-
return [.../* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])].filter((alias) => canonicalJson(left[alias]) !== canonicalJson(right[alias])).sort();
|
|
48447
|
-
}
|
|
48448
|
-
function canonicalJson(value2) {
|
|
48449
|
-
const normalize = (v) => {
|
|
48450
|
-
if (Array.isArray(v)) return v.map(normalize);
|
|
48451
|
-
if (v === null || typeof v !== "object") return v;
|
|
48452
|
-
const entries2 = Object.entries(v).sort(
|
|
48453
|
-
([x2], [y]) => x2 < y ? -1 : x2 > y ? 1 : 0
|
|
48454
|
-
);
|
|
48455
|
-
return entries2.map(([key, val]) => [key, normalize(val)]);
|
|
48456
|
-
};
|
|
48457
|
-
return JSON.stringify(normalize(value2));
|
|
48458
|
-
}
|
|
48459
|
-
var REGEX_MAY_FOLLOW = /* @__PURE__ */ new Set([
|
|
48460
|
-
"return",
|
|
48461
|
-
"typeof",
|
|
48462
|
-
"case",
|
|
48463
|
-
"in",
|
|
48464
|
-
"of",
|
|
48465
|
-
"delete",
|
|
48466
|
-
"void",
|
|
48467
|
-
"instanceof",
|
|
48468
|
-
"new",
|
|
48469
|
-
"do",
|
|
48470
|
-
"else",
|
|
48471
|
-
"yield",
|
|
48472
|
-
"await",
|
|
48473
|
-
"throw"
|
|
48474
|
-
]);
|
|
48475
|
-
function opensRegex(out, at2) {
|
|
48476
|
-
let k = at2 - 1;
|
|
48477
|
-
while (k >= 0 && (out[k] === " " || out[k] === "\n" || out[k] === " " || out[k] === "\r")) k--;
|
|
48478
|
-
if (k < 0) return true;
|
|
48479
|
-
const prev = out[k];
|
|
48480
|
-
if ("=(,:[!&|?{;+-*%>~^".includes(prev)) return true;
|
|
48481
|
-
if (/[A-Za-z0-9_$]/.test(prev)) {
|
|
48482
|
-
let s = k;
|
|
48483
|
-
while (s >= 0 && /[A-Za-z0-9_$]/.test(out[s])) s--;
|
|
48484
|
-
return REGEX_MAY_FOLLOW.has(out.slice(s + 1, k + 1).join(""));
|
|
48485
|
-
}
|
|
48486
|
-
return false;
|
|
48487
|
-
}
|
|
48488
|
-
function codeWithoutComments(sourceText) {
|
|
48489
|
-
const out = sourceText.split("");
|
|
48490
|
-
const n = sourceText.length;
|
|
48491
|
-
const blank = (from, to) => {
|
|
48492
|
-
for (let k = from; k < to; k++) if (out[k] !== "\n") out[k] = " ";
|
|
48493
|
-
};
|
|
48494
|
-
let i2 = 0;
|
|
48495
|
-
while (i2 < n) {
|
|
48496
|
-
const c = sourceText[i2];
|
|
48497
|
-
const next = sourceText[i2 + 1];
|
|
48498
|
-
if (c === "/" && next === "/") {
|
|
48499
|
-
let j = i2;
|
|
48500
|
-
while (j < n && sourceText[j] !== "\n") j++;
|
|
48501
|
-
blank(i2, j);
|
|
48502
|
-
i2 = j;
|
|
48503
|
-
continue;
|
|
48504
|
-
}
|
|
48505
|
-
if (c === "/" && next === "*") {
|
|
48506
|
-
let j = i2 + 2;
|
|
48507
|
-
while (j < n && !(sourceText[j] === "*" && sourceText[j + 1] === "/")) j++;
|
|
48508
|
-
j = j < n ? j + 2 : n;
|
|
48509
|
-
blank(i2, j);
|
|
48510
|
-
i2 = j;
|
|
48511
|
-
continue;
|
|
48512
|
-
}
|
|
48513
|
-
if (c === '"' || c === "'") {
|
|
48514
|
-
let j = i2 + 1;
|
|
48515
|
-
while (j < n && sourceText[j] !== c && sourceText[j] !== "\n") {
|
|
48516
|
-
j += sourceText[j] === "\\" ? 2 : 1;
|
|
48517
|
-
}
|
|
48518
|
-
i2 = j < n && sourceText[j] === c ? j + 1 : j;
|
|
48519
|
-
continue;
|
|
48520
|
-
}
|
|
48521
|
-
if (c === "`") {
|
|
48522
|
-
let j = i2 + 1;
|
|
48523
|
-
while (j < n && sourceText[j] !== "`") {
|
|
48524
|
-
j += sourceText[j] === "\\" ? 2 : 1;
|
|
48525
|
-
}
|
|
48526
|
-
i2 = j < n ? j + 1 : n;
|
|
48527
|
-
continue;
|
|
48528
|
-
}
|
|
48529
|
-
if (c === "/" && opensRegex(out, i2)) {
|
|
48530
|
-
let j = i2 + 1;
|
|
48531
|
-
let inClass = false;
|
|
48532
|
-
while (j < n) {
|
|
48533
|
-
const ch = sourceText[j];
|
|
48534
|
-
if (ch === "\\") {
|
|
48535
|
-
j += 2;
|
|
48536
|
-
continue;
|
|
48537
|
-
}
|
|
48538
|
-
if (ch === "\n") break;
|
|
48539
|
-
if (ch === "[") inClass = true;
|
|
48540
|
-
else if (ch === "]") inClass = false;
|
|
48541
|
-
else if (ch === "/" && !inClass) {
|
|
48542
|
-
j++;
|
|
48543
|
-
break;
|
|
48544
|
-
}
|
|
48545
|
-
j++;
|
|
48546
|
-
}
|
|
48547
|
-
i2 = j;
|
|
48548
|
-
continue;
|
|
48549
|
-
}
|
|
48550
|
-
i2++;
|
|
48551
|
-
}
|
|
48552
|
-
return out.join("");
|
|
48553
|
-
}
|
|
48554
|
-
var ALIAS_CALL_HOOKS = {
|
|
48555
|
-
queries: ["useQuery", "usePaginatedQuery", "useInfiniteQuery", "useCount", "useFieldOptions"],
|
|
48556
|
-
workflows: ["useWorkflow"],
|
|
48557
|
-
agents: ["useAgentRun"]
|
|
48558
|
-
};
|
|
48559
|
-
var LITERAL_ALIAS_ARG = `["'\`]([A-Za-z_$][A-Za-z0-9_$]*)["'\`]`;
|
|
48560
|
-
function isAppSourcePath(projectRelativePath) {
|
|
48561
|
-
const normalized = projectRelativePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
48562
|
-
return normalized.startsWith("src/") && /\.(ts|tsx|js|jsx)$/.test(normalized);
|
|
48563
|
-
}
|
|
48564
|
-
function calledAppAliases(sourceText) {
|
|
48565
|
-
const code = codeWithoutComments(sourceText);
|
|
48566
|
-
const out = {
|
|
48567
|
-
queries: [],
|
|
48568
|
-
workflows: [],
|
|
48569
|
-
agents: [],
|
|
48570
|
-
dynamic: []
|
|
48571
|
-
};
|
|
48572
|
-
for (const [kind, hooks] of Object.entries(ALIAS_CALL_HOOKS)) {
|
|
48573
|
-
const seen = /* @__PURE__ */ new Set();
|
|
48574
|
-
for (const hook of hooks) {
|
|
48575
|
-
let isDynamic = false;
|
|
48576
|
-
for (const call of code.matchAll(new RegExp(`\\b${hook}\\s*\\(`, "g"))) {
|
|
48577
|
-
const rest2 = code.slice(call.index + call[0].length);
|
|
48578
|
-
const literal2 = new RegExp(`^\\s*${LITERAL_ALIAS_ARG}`).exec(rest2);
|
|
48579
|
-
if (literal2) seen.add(literal2[1]);
|
|
48580
|
-
else isDynamic = true;
|
|
48581
|
-
}
|
|
48582
|
-
if (isDynamic) out.dynamic.push(hook);
|
|
48583
|
-
}
|
|
48584
|
-
out[kind] = [...seen];
|
|
48585
|
-
}
|
|
48586
|
-
return out;
|
|
48587
|
-
}
|
|
48588
|
-
function orphanedAliases(bound, called) {
|
|
48589
|
-
return unboundAliases(bound, called);
|
|
48590
|
-
}
|
|
48591
|
-
function unboundAliases(called, bound) {
|
|
48592
|
-
const missing = (from, against) => {
|
|
48593
|
-
const have = new Set(against ?? []);
|
|
48594
|
-
return [...from ?? []].filter((alias) => !have.has(alias));
|
|
48595
|
-
};
|
|
48596
|
-
return {
|
|
48597
|
-
queries: missing(called.queries, bound.queries),
|
|
48598
|
-
workflows: missing(called.workflows, bound.workflows),
|
|
48599
|
-
agents: missing(called.agents, bound.agents)
|
|
48600
|
-
};
|
|
48601
|
-
}
|
|
48602
|
-
|
|
48603
|
-
// ../shared/src/app_query_ast.ts
|
|
48604
|
-
function collectQueryTableIds(node) {
|
|
48605
|
-
const result = /* @__PURE__ */ new Set();
|
|
48606
|
-
walk(node, (n) => {
|
|
48607
|
-
if (n.kind === "from_table") result.add(n.table_id);
|
|
48608
|
-
});
|
|
48609
|
-
return result;
|
|
48610
|
-
}
|
|
48611
|
-
function walk(node, visit) {
|
|
48612
|
-
visit(node);
|
|
48613
|
-
switch (node.kind) {
|
|
48614
|
-
case "from_table":
|
|
48615
|
-
return;
|
|
48616
|
-
case "project":
|
|
48617
|
-
case "filter":
|
|
48618
|
-
case "group":
|
|
48619
|
-
case "window":
|
|
48620
|
-
case "sort":
|
|
48621
|
-
case "limit":
|
|
48622
|
-
case "unpivot":
|
|
48623
|
-
case "unnest":
|
|
48624
|
-
walk(node.from, visit);
|
|
48625
|
-
return;
|
|
48626
|
-
case "join":
|
|
48627
|
-
walk(node.left, visit);
|
|
48628
|
-
walk(node.right, visit);
|
|
48629
|
-
return;
|
|
48630
|
-
case "union":
|
|
48631
|
-
for (const child of node.sources) walk(child, visit);
|
|
48632
|
-
return;
|
|
48633
|
-
default: {
|
|
48634
|
-
const _exhaustive = node;
|
|
48635
|
-
void _exhaustive;
|
|
48636
|
-
return;
|
|
48637
|
-
}
|
|
48638
|
-
}
|
|
48639
|
-
}
|
|
48640
|
-
|
|
48641
|
-
// ../shared/src/generate_app_fields.ts
|
|
48642
|
-
var HEADER = `// Auto-generated by 'lotics app codegen' and 'lotics app pull'.
|
|
48643
|
-
// DO NOT EDIT \u2014 regenerated from the workspace schema.
|
|
48644
|
-
//
|
|
48645
|
-
// Runtime field + option ids addressed by stable display-name aliases:
|
|
48646
|
-
// record.data[F.<TABLE>.<field>] \u2192 "fld_\u2026"
|
|
48647
|
-
// value === OPT.<TABLE>.<field>.<option> \u2192 "opt_\u2026"
|
|
48648
|
-
// A rename on the platform re-runs codegen and moves these in lockstep.
|
|
48649
|
-
`;
|
|
48650
|
-
function slugifyAlias(name2, upper2) {
|
|
48651
|
-
const stripped = name2.normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/đ/g, "d").replace(/Đ/g, "D");
|
|
48652
|
-
const cased = upper2 ? stripped.toUpperCase() : stripped.toLowerCase();
|
|
48653
|
-
const slug = cased.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
48654
|
-
if (slug === "") return "_";
|
|
48655
|
-
return /^[0-9]/.test(slug) ? `_${slug}` : slug;
|
|
48656
|
-
}
|
|
48657
|
-
function dedupeAliases(names, upper2) {
|
|
48658
|
-
const used = /* @__PURE__ */ new Map();
|
|
48659
|
-
return names.map((name2) => {
|
|
48660
|
-
const base = slugifyAlias(name2, upper2);
|
|
48661
|
-
const seen = used.get(base);
|
|
48662
|
-
if (seen === void 0) {
|
|
48663
|
-
used.set(base, 1);
|
|
48664
|
-
return base;
|
|
48665
|
-
}
|
|
48666
|
-
let n = seen + 1;
|
|
48667
|
-
while (used.has(`${base}_${n}`)) n++;
|
|
48668
|
-
used.set(base, n);
|
|
48669
|
-
used.set(`${base}_${n}`, 1);
|
|
48670
|
-
return `${base}_${n}`;
|
|
48671
|
-
});
|
|
48672
|
-
}
|
|
48673
|
-
function propKey(alias) {
|
|
48674
|
-
return isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
48675
|
-
}
|
|
48676
|
-
function aliasTables(tables) {
|
|
48677
|
-
const tableAliases = dedupeAliases(
|
|
48678
|
-
tables.map((t) => t.name),
|
|
48679
|
-
true
|
|
48680
|
-
);
|
|
48681
|
-
return tables.map((table, i2) => {
|
|
48682
|
-
const fieldAliases = dedupeAliases(
|
|
48683
|
-
table.fields.map((f) => f.name),
|
|
48684
|
-
false
|
|
48685
|
-
);
|
|
48686
|
-
return {
|
|
48687
|
-
alias: tableAliases[i2],
|
|
48688
|
-
table,
|
|
48689
|
-
fields: table.fields.map((field, j) => ({ alias: fieldAliases[j], field }))
|
|
48690
|
-
};
|
|
48691
|
-
});
|
|
48692
|
-
}
|
|
48693
|
-
function emitFieldMap(aliased) {
|
|
48694
|
-
const tableBlocks = aliased.map(({ alias, fields }) => {
|
|
48695
|
-
const fieldLines = fields.map(
|
|
48696
|
-
({ alias: fieldAlias, field }) => ` ${propKey(fieldAlias)}: ${JSON.stringify(field.id)},`
|
|
48697
|
-
);
|
|
48698
|
-
return ` ${propKey(alias)}: {
|
|
48699
|
-
${fieldLines.join("\n")}
|
|
48700
|
-
},`;
|
|
48701
|
-
});
|
|
48702
|
-
return `export const F = {
|
|
48703
|
-
${tableBlocks.join("\n")}
|
|
48704
|
-
} as const;`;
|
|
48705
|
-
}
|
|
48706
|
-
function emitOptionMap(aliased) {
|
|
48707
|
-
const tableBlocks = [];
|
|
48708
|
-
for (const { alias, fields } of aliased) {
|
|
48709
|
-
const fieldBlocks = [];
|
|
48710
|
-
for (const { alias: fieldAlias, field } of fields) {
|
|
48711
|
-
const options = field.options ?? [];
|
|
48712
|
-
if (options.length === 0) continue;
|
|
48713
|
-
const optionAliases = dedupeAliases(
|
|
48714
|
-
options.map((o) => o.label),
|
|
48715
|
-
false
|
|
48716
|
-
);
|
|
48717
|
-
const optionLines = options.map(
|
|
48718
|
-
(option, i2) => ` ${propKey(optionAliases[i2])}: ${JSON.stringify(option.id)},`
|
|
48719
|
-
);
|
|
48720
|
-
fieldBlocks.push(` ${propKey(fieldAlias)}: {
|
|
48721
|
-
${optionLines.join("\n")}
|
|
48722
|
-
},`);
|
|
48723
|
-
}
|
|
48724
|
-
if (fieldBlocks.length === 0) continue;
|
|
48725
|
-
tableBlocks.push(` ${propKey(alias)}: {
|
|
48726
|
-
${fieldBlocks.join("\n")}
|
|
48727
|
-
},`);
|
|
48728
|
-
}
|
|
48729
|
-
if (tableBlocks.length === 0) return `export const OPT = {} as const;`;
|
|
48730
|
-
return `export const OPT = {
|
|
48731
|
-
${tableBlocks.join("\n")}
|
|
48732
|
-
} as const;`;
|
|
48733
|
-
}
|
|
48734
|
-
function generateAppFields(tables) {
|
|
48735
|
-
if (tables.length === 0) {
|
|
48736
|
-
return `${HEADER}
|
|
48737
|
-
export const F = {} as const;
|
|
48738
|
-
|
|
48739
|
-
export const OPT = {} as const;
|
|
48740
|
-
|
|
48741
|
-
/** Field-id alias map (empty \u2014 no tables in scope). */
|
|
48742
|
-
export type AppFields = typeof F;
|
|
48743
|
-
/** Select-option alias map (empty \u2014 no tables in scope). */
|
|
48744
|
-
export type AppOptions = typeof OPT;
|
|
48745
|
-
`;
|
|
48746
|
-
}
|
|
48747
|
-
const aliased = aliasTables(tables);
|
|
48748
|
-
return `${HEADER}
|
|
48749
|
-
${emitFieldMap(aliased)}
|
|
48750
|
-
|
|
48751
|
-
${emitOptionMap(aliased)}
|
|
48752
|
-
|
|
48753
|
-
/** Field-id alias map: \`F[<TABLE>][<field>]\` is the \`fld_\u2026\` id (literal-typed). */
|
|
48754
|
-
export type AppFields = typeof F;
|
|
48755
|
-
/** Select-option alias map: \`OPT[<TABLE>][<field>][<option>]\` is the \`opt_\u2026\` id. */
|
|
48756
|
-
export type AppOptions = typeof OPT;
|
|
48757
|
-
`;
|
|
48758
|
-
}
|
|
48759
|
-
function codegenTableIds(queries, allowlist) {
|
|
48760
|
-
const ids = new Set(allowlist);
|
|
48761
|
-
for (const declaration of Object.values(queries)) {
|
|
48762
|
-
for (const id of collectQueryTableIds(declaration.ast)) ids.add(id);
|
|
48763
|
-
}
|
|
48764
|
-
return [...ids];
|
|
48765
|
-
}
|
|
48766
|
-
function readCodegenTablesAllowlist(pkg) {
|
|
48767
|
-
const tables = pkg?.lotics?.codegen?.tables;
|
|
48768
|
-
return Array.isArray(tables) ? tables.filter((t) => typeof t === "string") : [];
|
|
48769
|
-
}
|
|
48770
|
-
|
|
48771
|
-
// src/app_workflow_check.ts
|
|
48772
|
-
import fs7 from "node:fs";
|
|
48773
|
-
import path8 from "node:path";
|
|
48774
|
-
import { createRequire } from "node:module";
|
|
48775
|
-
|
|
48776
|
-
// ../shared/src/parse_workflow_js.ts
|
|
48777
|
-
var import_parser = __toESM(require_lib(), 1);
|
|
48778
|
-
|
|
48779
48182
|
// ../../node_modules/zod/v4/classic/external.js
|
|
48780
48183
|
var external_exports = {};
|
|
48781
48184
|
__export(external_exports, {
|
|
@@ -63270,218 +62673,28 @@ __export(coerce_exports, {
|
|
|
63270
62673
|
date: () => date4,
|
|
63271
62674
|
number: () => number3,
|
|
63272
62675
|
string: () => string3
|
|
63273
|
-
});
|
|
63274
|
-
function string3(params) {
|
|
63275
|
-
return _coercedString(ZodString, params);
|
|
63276
|
-
}
|
|
63277
|
-
function number3(params) {
|
|
63278
|
-
return _coercedNumber(ZodNumber, params);
|
|
63279
|
-
}
|
|
63280
|
-
function boolean3(params) {
|
|
63281
|
-
return _coercedBoolean(ZodBoolean, params);
|
|
63282
|
-
}
|
|
63283
|
-
function bigint3(params) {
|
|
63284
|
-
return _coercedBigint(ZodBigInt, params);
|
|
63285
|
-
}
|
|
63286
|
-
function date4(params) {
|
|
63287
|
-
return _coercedDate(ZodDate, params);
|
|
63288
|
-
}
|
|
63289
|
-
|
|
63290
|
-
// ../../node_modules/zod/v4/classic/external.js
|
|
63291
|
-
config(en_default());
|
|
63292
|
-
|
|
63293
|
-
// ../../node_modules/zod/index.js
|
|
63294
|
-
var zod_default = external_exports;
|
|
63295
|
-
|
|
63296
|
-
// ../shared/src/schemas/workflow_expressions.ts
|
|
63297
|
-
var runtimeKeySchema = zod_default.enum([
|
|
63298
|
-
"timezone",
|
|
63299
|
-
"workflow_id",
|
|
63300
|
-
"execution_id",
|
|
63301
|
-
"workspace_id",
|
|
63302
|
-
"organization_id",
|
|
63303
|
-
"now",
|
|
63304
|
-
"change_origin",
|
|
63305
|
-
// PARKED — accepted in stored ASTs, rejected for new saves at parse (see
|
|
63306
|
-
// `PARKED_RUNTIME_KEYS` in walk_workflow_expression.ts). It is the OWNER's
|
|
63307
|
-
// principal (a workflow runs under owner authority), so it can't answer the
|
|
63308
|
-
// caller-authorization question anyone reads it for; the generated `.d.ts`
|
|
63309
|
-
// omits it and the docs point at `current_member_in_any_group` /
|
|
63310
|
-
// `runtime.triggered_by_member_id` instead. The entry stays so any stored
|
|
63311
|
-
// AST keeps validating and executing — drop it only once a prod probe shows
|
|
63312
|
-
// zero references (`workflows.steps_v2::text LIKE '%execution_principal%'`).
|
|
63313
|
-
"execution_principal",
|
|
63314
|
-
"triggered_by_member_id"
|
|
63315
|
-
]);
|
|
63316
|
-
var readSourceSchema = zod_default.discriminatedUnion("from", [
|
|
63317
|
-
zod_default.object({ from: zod_default.literal("trigger") }),
|
|
63318
|
-
zod_default.object({ from: zod_default.literal("trigger_record") }),
|
|
63319
|
-
zod_default.object({ from: zod_default.literal("trigger_record_prev") }),
|
|
63320
|
-
zod_default.object({ from: zod_default.literal("trigger_changes") }),
|
|
63321
|
-
// `name` is the loop's bind name, and it is OPTIONAL for one reason: every
|
|
63322
|
-
// body stored before names existed emits the bare form, and those resolve to
|
|
63323
|
-
// the innermost frame — today's behaviour, and correct for any loop that is
|
|
63324
|
-
// not nested. Without a name a read inside a NESTED loop cannot say which
|
|
63325
|
-
// loop it means, so both binds resolve to the inner item and a join between
|
|
63326
|
-
// two collections silently matches nothing. The parser emits the name now, so
|
|
63327
|
-
// a body gets correct nesting the first time it is saved through it.
|
|
63328
|
-
zod_default.object({ from: zod_default.literal("foreach_item"), name: zod_default.string().min(1).optional() }),
|
|
63329
|
-
// No `name` here, deliberately: the JS surface spells the index as one
|
|
63330
|
-
// reserved `index` keyword with no per-loop form, so the innermost loop is
|
|
63331
|
-
// the only thing a read can mean. A name would be representable, honoured at
|
|
63332
|
-
// run time, and silently rewritten to the innermost by the renderer — which
|
|
63333
|
-
// prints every index as `index` — reintroducing the corruption above for a
|
|
63334
|
-
// case nothing can author.
|
|
63335
|
-
zod_default.object({ from: zod_default.literal("foreach_index") }),
|
|
63336
|
-
zod_default.object({
|
|
63337
|
-
from: zod_default.literal("step_output"),
|
|
63338
|
-
step_id: zod_default.string().min(1)
|
|
63339
|
-
}),
|
|
63340
|
-
zod_default.object({
|
|
63341
|
-
from: zod_default.literal("runtime"),
|
|
63342
|
-
key: runtimeKeySchema
|
|
63343
|
-
}),
|
|
63344
|
-
// Lambda parameter — names a positional parameter on the innermost
|
|
63345
|
-
// enclosing `lambda` expression. The walker emits this only inside
|
|
63346
|
-
// higher-order helper callbacks (`filter(arr, x => x.Status == "open")`).
|
|
63347
|
-
// The evaluator pushes a `lambda_params` frame each time it invokes a
|
|
63348
|
-
// lambda, popping it after the body finishes. Outside a lambda body,
|
|
63349
|
-
// these reads have no meaning and fail loudly.
|
|
63350
|
-
zod_default.object({
|
|
63351
|
-
from: zod_default.literal("lambda_param"),
|
|
63352
|
-
name: zod_default.string().min(1)
|
|
63353
|
-
}),
|
|
63354
|
-
// Lexical (`let`) binding — names a block-scoped mutable variable
|
|
63355
|
-
// declared by `let_declare` or assigned by `assign` somewhere in an
|
|
63356
|
-
// enclosing block. The walker registers names on a per-block stack
|
|
63357
|
-
// and emits this read source when a bare identifier matches. The
|
|
63358
|
-
// evaluator maintains the matching frame stack on
|
|
63359
|
-
// `WorkflowEvalContext.lexical_bindings`; reading walks it
|
|
63360
|
-
// innermost-outward.
|
|
63361
|
-
zod_default.object({
|
|
63362
|
-
from: zod_default.literal("lexical"),
|
|
63363
|
-
name: zod_default.string().min(1)
|
|
63364
|
-
})
|
|
63365
|
-
]);
|
|
63366
|
-
var indexExpressionSchema = zod_default.lazy(
|
|
63367
|
-
() => workflowExpressionSchema
|
|
63368
|
-
);
|
|
63369
|
-
var pathSegmentSchema = zod_default.discriminatedUnion("at", [
|
|
63370
|
-
zod_default.object({ at: zod_default.literal("key"), key: zod_default.string().min(1) }),
|
|
63371
|
-
zod_default.object({
|
|
63372
|
-
at: zod_default.literal("index"),
|
|
63373
|
-
/**
|
|
63374
|
-
* Numeric literal indices stay as `number`; computed indices (e.g.
|
|
63375
|
-
* `arr[i]` where `i` is a lambda param or `let` binding) carry a
|
|
63376
|
-
* WorkflowExpression that the evaluator resolves at runtime. Authors
|
|
63377
|
-
* who write `arr[<expr>]` get a working iteration pattern over arrays
|
|
63378
|
-
* without forcing the parser to pre-evaluate the index.
|
|
63379
|
-
*/
|
|
63380
|
-
index: zod_default.union([zod_default.number().int().nonnegative(), indexExpressionSchema])
|
|
63381
|
-
}),
|
|
63382
|
-
zod_default.object({ at: zod_default.literal("field"), key: zod_default.string().min(1) }),
|
|
63383
|
-
zod_default.object({
|
|
63384
|
-
at: zod_default.literal("linked"),
|
|
63385
|
-
via: zod_default.string().min(1),
|
|
63386
|
-
/**
|
|
63387
|
-
* `number` — pick a single linked record by literal index.
|
|
63388
|
-
* `"each"` — fan out; legal only inside foreach.items (validator-enforced).
|
|
63389
|
-
* `WorkflowExpression` — computed index, resolved at runtime to pick a
|
|
63390
|
-
* single linked record (same descent semantics as the numeric form).
|
|
63391
|
-
*/
|
|
63392
|
-
index: zod_default.union([
|
|
63393
|
-
zod_default.number().int().nonnegative(),
|
|
63394
|
-
zod_default.literal("each"),
|
|
63395
|
-
indexExpressionSchema
|
|
63396
|
-
])
|
|
63397
|
-
})
|
|
63398
|
-
]);
|
|
63399
|
-
var binaryOpSchema = zod_default.enum([
|
|
63400
|
-
"eq",
|
|
63401
|
-
"neq",
|
|
63402
|
-
"seq",
|
|
63403
|
-
"sneq",
|
|
63404
|
-
"gt",
|
|
63405
|
-
"lt",
|
|
63406
|
-
"gte",
|
|
63407
|
-
"lte",
|
|
63408
|
-
"and",
|
|
63409
|
-
"or",
|
|
63410
|
-
"add",
|
|
63411
|
-
"sub",
|
|
63412
|
-
"mul",
|
|
63413
|
-
"div",
|
|
63414
|
-
"mod"
|
|
63415
|
-
]);
|
|
63416
|
-
var unaryOpSchema = zod_default.enum(["not", "neg"]);
|
|
63417
|
-
var coerceSchema = zod_default.enum(["raw", "display"]);
|
|
63418
|
-
var literalValueSchema = zod_default.union([
|
|
63419
|
-
zod_default.string(),
|
|
63420
|
-
zod_default.number(),
|
|
63421
|
-
zod_default.boolean(),
|
|
63422
|
-
zod_default.null()
|
|
63423
|
-
]);
|
|
63424
|
-
var workflowExpressionSchema = zod_default.lazy(
|
|
63425
|
-
() => zod_default.discriminatedUnion("kind", [
|
|
63426
|
-
zod_default.object({ kind: zod_default.literal("lit"), value: literalValueSchema }),
|
|
63427
|
-
zod_default.object({
|
|
63428
|
-
kind: zod_default.literal("read"),
|
|
63429
|
-
source: readSourceSchema,
|
|
63430
|
-
path: zod_default.array(pathSegmentSchema),
|
|
63431
|
-
coerce: coerceSchema.optional()
|
|
63432
|
-
}),
|
|
63433
|
-
zod_default.object({
|
|
63434
|
-
kind: zod_default.literal("call"),
|
|
63435
|
-
fn: zod_default.string().min(1),
|
|
63436
|
-
args: zod_default.array(workflowExpressionSchema)
|
|
63437
|
-
}),
|
|
63438
|
-
zod_default.object({
|
|
63439
|
-
kind: zod_default.literal("binary"),
|
|
63440
|
-
op: binaryOpSchema,
|
|
63441
|
-
left: workflowExpressionSchema,
|
|
63442
|
-
right: workflowExpressionSchema
|
|
63443
|
-
}),
|
|
63444
|
-
zod_default.object({
|
|
63445
|
-
kind: zod_default.literal("unary"),
|
|
63446
|
-
op: unaryOpSchema,
|
|
63447
|
-
arg: workflowExpressionSchema
|
|
63448
|
-
}),
|
|
63449
|
-
zod_default.object({
|
|
63450
|
-
kind: zod_default.literal("ternary"),
|
|
63451
|
-
cond: workflowExpressionSchema,
|
|
63452
|
-
then: workflowExpressionSchema,
|
|
63453
|
-
else: workflowExpressionSchema
|
|
63454
|
-
}),
|
|
63455
|
-
zod_default.object({
|
|
63456
|
-
kind: zod_default.literal("template"),
|
|
63457
|
-
parts: zod_default.array(templatePartSchema)
|
|
63458
|
-
}),
|
|
63459
|
-
zod_default.object({
|
|
63460
|
-
kind: zod_default.literal("lambda"),
|
|
63461
|
-
params: zod_default.array(zod_default.string().min(1)),
|
|
63462
|
-
body: workflowExpressionSchema
|
|
63463
|
-
}),
|
|
63464
|
-
zod_default.object({
|
|
63465
|
-
kind: zod_default.literal("array_literal"),
|
|
63466
|
-
elements: zod_default.array(workflowExpressionSchema)
|
|
63467
|
-
}),
|
|
63468
|
-
zod_default.object({
|
|
63469
|
-
kind: zod_default.literal("object_literal"),
|
|
63470
|
-
entries: zod_default.array(
|
|
63471
|
-
zod_default.object({
|
|
63472
|
-
key: zod_default.string().min(1),
|
|
63473
|
-
value: workflowExpressionSchema
|
|
63474
|
-
})
|
|
63475
|
-
)
|
|
63476
|
-
})
|
|
63477
|
-
])
|
|
63478
|
-
);
|
|
63479
|
-
var templatePartSchema = zod_default.lazy(
|
|
63480
|
-
() => zod_default.discriminatedUnion("t", [
|
|
63481
|
-
zod_default.object({ t: zod_default.literal("text"), s: zod_default.string() }),
|
|
63482
|
-
zod_default.object({ t: zod_default.literal("ex"), e: workflowExpressionSchema })
|
|
63483
|
-
])
|
|
63484
|
-
);
|
|
62676
|
+
});
|
|
62677
|
+
function string3(params) {
|
|
62678
|
+
return _coercedString(ZodString, params);
|
|
62679
|
+
}
|
|
62680
|
+
function number3(params) {
|
|
62681
|
+
return _coercedNumber(ZodNumber, params);
|
|
62682
|
+
}
|
|
62683
|
+
function boolean3(params) {
|
|
62684
|
+
return _coercedBoolean(ZodBoolean, params);
|
|
62685
|
+
}
|
|
62686
|
+
function bigint3(params) {
|
|
62687
|
+
return _coercedBigint(ZodBigInt, params);
|
|
62688
|
+
}
|
|
62689
|
+
function date4(params) {
|
|
62690
|
+
return _coercedDate(ZodDate, params);
|
|
62691
|
+
}
|
|
62692
|
+
|
|
62693
|
+
// ../../node_modules/zod/v4/classic/external.js
|
|
62694
|
+
config(en_default());
|
|
62695
|
+
|
|
62696
|
+
// ../../node_modules/zod/index.js
|
|
62697
|
+
var zod_default = external_exports;
|
|
63485
62698
|
|
|
63486
62699
|
// ../../node_modules/date-fns/constants.js
|
|
63487
62700
|
var daysInYear = 365.2425;
|
|
@@ -65766,7 +64979,7 @@ var queryOutputColumnSchema = zod_default.object({
|
|
|
65766
64979
|
var queryOutputSchemaSchema = zod_default.object({
|
|
65767
64980
|
columns: zod_default.array(queryOutputColumnSchema)
|
|
65768
64981
|
});
|
|
65769
|
-
var
|
|
64982
|
+
var literalValueSchema = zod_default.union([
|
|
65770
64983
|
zod_default.string(),
|
|
65771
64984
|
zod_default.number(),
|
|
65772
64985
|
zod_default.boolean(),
|
|
@@ -65775,7 +64988,7 @@ var literalValueSchema2 = zod_default.union([
|
|
|
65775
64988
|
var querySourceSchema = zod_default.lazy(
|
|
65776
64989
|
() => zod_default.union([
|
|
65777
64990
|
zod_default.string(),
|
|
65778
|
-
zod_default.object({ literal:
|
|
64991
|
+
zod_default.object({ literal: literalValueSchema }),
|
|
65779
64992
|
zod_default.object({ eq: zod_default.tuple([querySourceSchema, querySourceSchema]) }),
|
|
65780
64993
|
zod_default.object({ neq: zod_default.tuple([querySourceSchema, querySourceSchema]) }),
|
|
65781
64994
|
zod_default.object({ isEmpty: querySourceSchema }),
|
|
@@ -65846,14 +65059,14 @@ var queryWindowFunctionColumnSchema = zod_default.discriminatedUnion("fn", [
|
|
|
65846
65059
|
fn: zod_default.literal("lag"),
|
|
65847
65060
|
input_column: zod_default.string().describe("Input column whose earlier-row value to read."),
|
|
65848
65061
|
offset: zod_default.number().int().positive().optional().describe("Rows back. Defaults to 1."),
|
|
65849
|
-
default:
|
|
65062
|
+
default: literalValueSchema.optional().describe("Value at the partition's leading edge. Type must match the input column. Omit for NULL.")
|
|
65850
65063
|
}).strict(),
|
|
65851
65064
|
zod_default.object({
|
|
65852
65065
|
output: zod_default.string().describe("Output column name"),
|
|
65853
65066
|
fn: zod_default.literal("lead"),
|
|
65854
65067
|
input_column: zod_default.string().describe("Input column whose later-row value to read."),
|
|
65855
65068
|
offset: zod_default.number().int().positive().optional().describe("Rows forward. Defaults to 1."),
|
|
65856
|
-
default:
|
|
65069
|
+
default: literalValueSchema.optional().describe("Value at the partition's trailing edge. Type must match the input column. Omit for NULL.")
|
|
65857
65070
|
}).strict()
|
|
65858
65071
|
]);
|
|
65859
65072
|
var queryJoinPredicateSchema = zod_default.object({
|
|
@@ -65927,360 +65140,1445 @@ var queryGroupNodeSchema = zod_default.object({
|
|
|
65927
65140
|
by: zod_default.array(queryGroupKeySchema).describe(
|
|
65928
65141
|
"Group keys: input column names, or `{ bucket: { source, granularity, output } }` date buckets. A bucket truncates a date/datetime column to the bucket START as a `date` column (wall-clock semantics; `week` starts on ISO Monday; null source \u2192 null bucket). Empty = single-row aggregate."
|
|
65929
65142
|
),
|
|
65930
|
-
aggregates: zod_default.array(queryAggregateColumnSchema).min(1)
|
|
65931
|
-
});
|
|
65932
|
-
var queryWindowNodeSchema = zod_default.object({
|
|
65933
|
-
kind: zod_default.literal("window"),
|
|
65934
|
-
from: zod_default.lazy(() => queryNodeSchema),
|
|
65935
|
-
partition_by: zod_default.array(zod_default.string()).describe("Input columns to partition by. Empty = single window over input."),
|
|
65936
|
-
order_by: tableRecordSortSchema,
|
|
65937
|
-
frame: queryWindowFrameSchema.optional(),
|
|
65938
|
-
aggregates: zod_default.array(queryAggregateColumnSchema).optional().describe(
|
|
65939
|
-
"Frame aggregates (running totals: sum/avg/min/max/count over a ROWS frame). Each becomes a new column on every input row, preserving input columns alongside. `frame` applies only to these."
|
|
65143
|
+
aggregates: zod_default.array(queryAggregateColumnSchema).min(1)
|
|
65144
|
+
});
|
|
65145
|
+
var queryWindowNodeSchema = zod_default.object({
|
|
65146
|
+
kind: zod_default.literal("window"),
|
|
65147
|
+
from: zod_default.lazy(() => queryNodeSchema),
|
|
65148
|
+
partition_by: zod_default.array(zod_default.string()).describe("Input columns to partition by. Empty = single window over input."),
|
|
65149
|
+
order_by: tableRecordSortSchema,
|
|
65150
|
+
frame: queryWindowFrameSchema.optional(),
|
|
65151
|
+
aggregates: zod_default.array(queryAggregateColumnSchema).optional().describe(
|
|
65152
|
+
"Frame aggregates (running totals: sum/avg/min/max/count over a ROWS frame). Each becomes a new column on every input row, preserving input columns alongside. `frame` applies only to these."
|
|
65153
|
+
),
|
|
65154
|
+
functions: zod_default.array(queryWindowFunctionColumnSchema).optional().describe(
|
|
65155
|
+
"Ranking / navigation window functions (row_number, rank, dense_rank, percent_rank, cume_dist, ntile, lag, lead). Never framed; require a non-empty order_by."
|
|
65156
|
+
)
|
|
65157
|
+
});
|
|
65158
|
+
var querySortNodeSchema = zod_default.object({
|
|
65159
|
+
kind: zod_default.literal("sort"),
|
|
65160
|
+
from: zod_default.lazy(() => queryNodeSchema),
|
|
65161
|
+
by: tableRecordSortSchema
|
|
65162
|
+
});
|
|
65163
|
+
var queryKeysetSchema = zod_default.object({
|
|
65164
|
+
// The single sort key the cursor seeks on (0 or 1 — multi-key sorts fall back
|
|
65165
|
+
// to OFFSET). `__source_record_id` ASC is always appended as the tiebreaker,
|
|
65166
|
+
// so the order is total and pages never skip/duplicate on ties.
|
|
65167
|
+
by: tableRecordSortSchema.max(1),
|
|
65168
|
+
// The seek position — absent on the FIRST page (ordering only, no predicate).
|
|
65169
|
+
after: zod_default.object({
|
|
65170
|
+
// The sort key's value on the last row of the previous page (one per `by`
|
|
65171
|
+
// entry), and that row's record id — together the seek position.
|
|
65172
|
+
values: zod_default.array(zod_default.union([zod_default.string(), zod_default.number(), zod_default.boolean(), zod_default.null()])),
|
|
65173
|
+
id: zod_default.string()
|
|
65174
|
+
}).optional()
|
|
65175
|
+
});
|
|
65176
|
+
var queryLimitNodeSchema = zod_default.object({
|
|
65177
|
+
kind: zod_default.literal("limit"),
|
|
65178
|
+
from: zod_default.lazy(() => queryNodeSchema),
|
|
65179
|
+
n: zod_default.number().int().positive(),
|
|
65180
|
+
offset: zod_default.number().int().nonnegative().optional(),
|
|
65181
|
+
// Keyset (seek) pagination — mutually exclusive with `offset`. When present,
|
|
65182
|
+
// the node applies the ORDER BY (`by` + id tiebreaker) and a seek predicate
|
|
65183
|
+
// itself, so `from` must NOT be pre-wrapped in a sort node.
|
|
65184
|
+
keyset: queryKeysetSchema.optional()
|
|
65185
|
+
});
|
|
65186
|
+
var queryUnpivotPassthroughColumnSchema = zod_default.object({
|
|
65187
|
+
output: zod_default.string(),
|
|
65188
|
+
type: queryColumnTypeSchema,
|
|
65189
|
+
source: querySourceSchema
|
|
65190
|
+
});
|
|
65191
|
+
var queryUnpivotRowColumnSchema = zod_default.object({
|
|
65192
|
+
output: zod_default.string(),
|
|
65193
|
+
type: queryColumnTypeSchema
|
|
65194
|
+
});
|
|
65195
|
+
var queryUnpivotNodeSchema = zod_default.object({
|
|
65196
|
+
kind: zod_default.literal("unpivot"),
|
|
65197
|
+
from: zod_default.lazy(() => queryNodeSchema),
|
|
65198
|
+
passthrough: zod_default.array(queryUnpivotPassthroughColumnSchema).describe(
|
|
65199
|
+
"Columns projected once from the source row and replicated across every fanned-out row. May be empty."
|
|
65200
|
+
),
|
|
65201
|
+
row_columns: zod_default.array(queryUnpivotRowColumnSchema).min(1).describe(
|
|
65202
|
+
"Schema of the row columns produced per fanned-out row. Types declared once; per-row sources live in `rows`."
|
|
65203
|
+
),
|
|
65204
|
+
rows: zod_default.array(zod_default.record(zod_default.string(), querySourceSchema)).min(1).describe(
|
|
65205
|
+
"Each entry produces one output row per source input row. Each entry must provide a source keyed by every `row_columns[*].output`."
|
|
65206
|
+
)
|
|
65207
|
+
});
|
|
65208
|
+
var queryUnnestNodeSchema = zod_default.object({
|
|
65209
|
+
kind: zod_default.literal("unnest"),
|
|
65210
|
+
from: zod_default.lazy(() => queryNodeSchema),
|
|
65211
|
+
source: zod_default.string().describe(
|
|
65212
|
+
"Array-valued input column to fan out (select / select_member / select_record_link / files, incl. array-valued lookups)."
|
|
65213
|
+
),
|
|
65214
|
+
output: zod_default.string().describe(
|
|
65215
|
+
"New text column holding each element's identity: option key / member id / link id / file id, by the source column's type."
|
|
65216
|
+
),
|
|
65217
|
+
display_output: zod_default.string().optional().describe(
|
|
65218
|
+
"Links only: additional text column carrying the element's cached display text."
|
|
65219
|
+
),
|
|
65220
|
+
keep_empty: zod_default.boolean().optional().describe(
|
|
65221
|
+
"Keep source rows whose cell is NULL / empty as one output row with NULL element columns. Defaults to false (such rows are dropped)."
|
|
65222
|
+
)
|
|
65223
|
+
});
|
|
65224
|
+
var appWorkflowInputBaseSchema = zod_default.object({
|
|
65225
|
+
description: zod_default.string().optional().describe("Human-readable description of this input \u2014 surfaces in agent + CLI tooling"),
|
|
65226
|
+
required: zod_default.boolean().optional().describe("Whether the input must be provided. Defaults to true.")
|
|
65227
|
+
});
|
|
65228
|
+
var appWorkflowInputTextSchema = appWorkflowInputBaseSchema.extend({
|
|
65229
|
+
type: zod_default.literal("text")
|
|
65230
|
+
});
|
|
65231
|
+
var appWorkflowInputNumberSchema = appWorkflowInputBaseSchema.extend({
|
|
65232
|
+
type: zod_default.literal("number")
|
|
65233
|
+
});
|
|
65234
|
+
var appWorkflowInputBooleanSchema = appWorkflowInputBaseSchema.extend({
|
|
65235
|
+
type: zod_default.literal("boolean")
|
|
65236
|
+
});
|
|
65237
|
+
var appWorkflowInputDateSchema = appWorkflowInputBaseSchema.extend({
|
|
65238
|
+
type: zod_default.literal("date")
|
|
65239
|
+
});
|
|
65240
|
+
var appWorkflowInputDatetimeSchema = appWorkflowInputBaseSchema.extend({
|
|
65241
|
+
type: zod_default.literal("datetime")
|
|
65242
|
+
});
|
|
65243
|
+
var appWorkflowInputEmailSchema = appWorkflowInputBaseSchema.extend({
|
|
65244
|
+
type: zod_default.literal("email")
|
|
65245
|
+
});
|
|
65246
|
+
var appWorkflowInputRecordLinkSchema = appWorkflowInputBaseSchema.extend({
|
|
65247
|
+
type: zod_default.literal("record_link"),
|
|
65248
|
+
table_id: zod_default.string().describe("Records must belong to this table. Validated at execute time + workflow save."),
|
|
65249
|
+
multi: zod_default.boolean().optional().describe("When true, accept an array of record_ids. Defaults to single.")
|
|
65250
|
+
});
|
|
65251
|
+
var selectOptionSourceShape = {
|
|
65252
|
+
options: zod_default.array(
|
|
65253
|
+
zod_default.object({
|
|
65254
|
+
label: zod_default.string(),
|
|
65255
|
+
value: zod_default.string()
|
|
65256
|
+
})
|
|
65257
|
+
).min(1).optional().describe("Inline option set. Provide EITHER `options` OR `field`, never both."),
|
|
65258
|
+
field: zod_default.string().optional().describe(
|
|
65259
|
+
"A select field's key (fld_\u2026) whose CURRENT options back this declaration \u2014 resolved at type-gen, validated at run time, drift-proof. Provide EITHER `field` OR `options`, never both."
|
|
65260
|
+
),
|
|
65261
|
+
multi: zod_default.boolean().optional()
|
|
65262
|
+
};
|
|
65263
|
+
function checkExactlyOneOptionSource(kind) {
|
|
65264
|
+
return (ctx) => {
|
|
65265
|
+
const hasOptions = ctx.value.options !== void 0;
|
|
65266
|
+
const hasField = ctx.value.field !== void 0;
|
|
65267
|
+
if (hasOptions === hasField) {
|
|
65268
|
+
ctx.issues.push({
|
|
65269
|
+
code: "custom",
|
|
65270
|
+
input: ctx.value,
|
|
65271
|
+
message: `select ${kind} must declare exactly one of \`options\` (inline) or \`field\` (a fld_\u2026 key resolved to the field's current options) \u2014 not both, not neither`
|
|
65272
|
+
});
|
|
65273
|
+
}
|
|
65274
|
+
};
|
|
65275
|
+
}
|
|
65276
|
+
var appWorkflowInputSelectSchema = appWorkflowInputBaseSchema.extend({
|
|
65277
|
+
type: zod_default.literal("select"),
|
|
65278
|
+
...selectOptionSourceShape
|
|
65279
|
+
}).check(checkExactlyOneOptionSource("input"));
|
|
65280
|
+
var appWorkflowInputDateRangeSchema = appWorkflowInputBaseSchema.extend({
|
|
65281
|
+
type: zod_default.literal("date_range"),
|
|
65282
|
+
include_time: zod_default.boolean().optional().describe("When true, the range includes time components (datetime). Defaults to false.")
|
|
65283
|
+
});
|
|
65284
|
+
var appWorkflowInputMemberSchema = appWorkflowInputBaseSchema.extend({
|
|
65285
|
+
type: zod_default.literal("member"),
|
|
65286
|
+
multi: zod_default.boolean().optional(),
|
|
65287
|
+
group: zod_default.string().optional().describe(
|
|
65288
|
+
"Member group ID this input draws from. Gates `useMembers({ group })` to declared groups (an app can only list a group it declares here) and constrains the submitted member(s) to that group at execution."
|
|
65289
|
+
)
|
|
65290
|
+
});
|
|
65291
|
+
var appWorkflowInputJsonSchema = appWorkflowInputBaseSchema.extend({
|
|
65292
|
+
type: zod_default.literal("json")
|
|
65293
|
+
});
|
|
65294
|
+
var appWorkflowInputFileSchema = appWorkflowInputBaseSchema.extend({
|
|
65295
|
+
type: zod_default.literal("file"),
|
|
65296
|
+
// `multi` mirrors record_link/select/member: a single `file` → `FileId`, a
|
|
65297
|
+
// `multi` file → `ReadonlyArray<FileId>` (directly assignable to a files field,
|
|
65298
|
+
// so a workflow can attach several uploads to one record's files field).
|
|
65299
|
+
multi: zod_default.boolean().optional()
|
|
65300
|
+
});
|
|
65301
|
+
var appWorkflowInputObjectSchema = appWorkflowInputBaseSchema.extend({
|
|
65302
|
+
type: zod_default.literal("object"),
|
|
65303
|
+
fields: zod_default.record(
|
|
65304
|
+
zod_default.string(),
|
|
65305
|
+
zod_default.lazy(() => appWorkflowInputSchema)
|
|
65306
|
+
)
|
|
65307
|
+
});
|
|
65308
|
+
var appWorkflowInputArraySchema = appWorkflowInputBaseSchema.extend({
|
|
65309
|
+
type: zod_default.literal("array"),
|
|
65310
|
+
items: zod_default.lazy(() => appWorkflowInputSchema)
|
|
65311
|
+
});
|
|
65312
|
+
var appWorkflowInputSchema = zod_default.lazy(
|
|
65313
|
+
() => zod_default.discriminatedUnion("type", [
|
|
65314
|
+
appWorkflowInputTextSchema,
|
|
65315
|
+
appWorkflowInputNumberSchema,
|
|
65316
|
+
appWorkflowInputBooleanSchema,
|
|
65317
|
+
appWorkflowInputDateSchema,
|
|
65318
|
+
appWorkflowInputDatetimeSchema,
|
|
65319
|
+
appWorkflowInputEmailSchema,
|
|
65320
|
+
appWorkflowInputRecordLinkSchema,
|
|
65321
|
+
appWorkflowInputSelectSchema,
|
|
65322
|
+
appWorkflowInputDateRangeSchema,
|
|
65323
|
+
appWorkflowInputMemberSchema,
|
|
65324
|
+
appWorkflowInputJsonSchema,
|
|
65325
|
+
appWorkflowInputFileSchema,
|
|
65326
|
+
appWorkflowInputObjectSchema,
|
|
65327
|
+
appWorkflowInputArraySchema
|
|
65328
|
+
])
|
|
65329
|
+
);
|
|
65330
|
+
var MAX_APP_WORKFLOW_OUTPUT_DEPTH = 8;
|
|
65331
|
+
var appWorkflowOutputBaseSchema = zod_default.object({
|
|
65332
|
+
description: zod_default.string().optional(),
|
|
65333
|
+
/** Whether this field is always present in the returned data. Defaults to true. */
|
|
65334
|
+
required: zod_default.boolean().optional()
|
|
65335
|
+
});
|
|
65336
|
+
var appWorkflowOutputSchema = zod_default.lazy(
|
|
65337
|
+
() => zod_default.discriminatedUnion("type", [
|
|
65338
|
+
appWorkflowOutputBaseSchema.extend({ type: zod_default.literal("text") }),
|
|
65339
|
+
appWorkflowOutputBaseSchema.extend({ type: zod_default.literal("number") }),
|
|
65340
|
+
appWorkflowOutputBaseSchema.extend({ type: zod_default.literal("boolean") }),
|
|
65341
|
+
appWorkflowOutputBaseSchema.extend({ type: zod_default.literal("date") }),
|
|
65342
|
+
appWorkflowOutputBaseSchema.extend({ type: zod_default.literal("datetime") }),
|
|
65343
|
+
appWorkflowOutputBaseSchema.extend({ type: zod_default.literal("email") }),
|
|
65344
|
+
appWorkflowOutputBaseSchema.extend({ type: zod_default.literal("json") }),
|
|
65345
|
+
appWorkflowOutputBaseSchema.extend({
|
|
65346
|
+
type: zod_default.literal("record_link"),
|
|
65347
|
+
table_id: zod_default.string(),
|
|
65348
|
+
multi: zod_default.boolean().optional()
|
|
65349
|
+
}),
|
|
65350
|
+
// The SAME shape and the SAME check as the select INPUT, not a copy of
|
|
65351
|
+
// them: the two surfaces declare one vocabulary (GAP-294), so accepting
|
|
65352
|
+
// `field` on one and not the other — or validating it differently — just
|
|
65353
|
+
// moves the drift somewhere nobody looks.
|
|
65354
|
+
appWorkflowOutputBaseSchema.extend({
|
|
65355
|
+
type: zod_default.literal("select"),
|
|
65356
|
+
...selectOptionSourceShape
|
|
65357
|
+
}).check(checkExactlyOneOptionSource("output")),
|
|
65358
|
+
appWorkflowOutputBaseSchema.extend({
|
|
65359
|
+
type: zod_default.literal("object"),
|
|
65360
|
+
fields: zod_default.record(zod_default.string(), appWorkflowOutputSchema)
|
|
65361
|
+
}),
|
|
65362
|
+
appWorkflowOutputBaseSchema.extend({
|
|
65363
|
+
type: zod_default.literal("array"),
|
|
65364
|
+
items: appWorkflowOutputSchema
|
|
65365
|
+
})
|
|
65366
|
+
])
|
|
65367
|
+
);
|
|
65368
|
+
function appWorkflowOutputDepth(output) {
|
|
65369
|
+
if (output.type === "object") {
|
|
65370
|
+
const fields = Object.values(output.fields);
|
|
65371
|
+
return 1 + (fields.length === 0 ? 0 : Math.max(...fields.map(appWorkflowOutputDepth)));
|
|
65372
|
+
}
|
|
65373
|
+
if (output.type === "array") return 1 + appWorkflowOutputDepth(output.items);
|
|
65374
|
+
return 1;
|
|
65375
|
+
}
|
|
65376
|
+
var appWorkflowDeclarationSchema = zod_default.object({
|
|
65377
|
+
workflow_id: zod_default.string().describe("ID of the workflow this alias resolves to"),
|
|
65378
|
+
inputs: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe(
|
|
65379
|
+
"Typed input schema for the workflow alias. Keys are input names; values declare type + constraints. The server validates payloads against this schema before invoking the workflow; CLI codegen emits typed `useWorkflow<alias>` signatures for the app side. Omit `inputs` for workflows that accept no inputs or whose shape isn't worth declaring."
|
|
65380
|
+
),
|
|
65381
|
+
outputs: zod_default.record(zod_default.string(), appWorkflowOutputSchema).optional().describe(
|
|
65382
|
+
"Typed output schema for the data the workflow returns via `return({ data })`. Keys are field names; values declare type + (nested object/array) shape. The server validates the returned data against this schema at the app boundary and the workflow won't save unless its `return({ data })` matches; CLI codegen types `result.data`. Omit when the workflow returns no data, or pass it through untyped."
|
|
65383
|
+
).refine(
|
|
65384
|
+
(outputs) => outputs === void 0 || Object.values(outputs).every((o) => appWorkflowOutputDepth(o) <= MAX_APP_WORKFLOW_OUTPUT_DEPTH),
|
|
65385
|
+
{ message: `output schema nesting exceeds the max depth of ${MAX_APP_WORKFLOW_OUTPUT_DEPTH}` }
|
|
65940
65386
|
),
|
|
65941
|
-
|
|
65942
|
-
"
|
|
65387
|
+
description: zod_default.string().optional().describe(
|
|
65388
|
+
"What this workflow does, in one line \u2014 read by an agent choosing between the app's aliases, the same job a query's `description` does. `lotics app workflow set` sends it, so it lives beside the body in version control; omitted, the workflow keeps the description already on it."
|
|
65389
|
+
),
|
|
65390
|
+
body_sha: zod_default.string().optional().describe(
|
|
65391
|
+
"Fingerprint of the body currently bound to this alias, written by the server on every accepted `set_app_workflow`. Never sent by a caller \u2014 it is the value a caller's `expected_body_sha` is checked against, so that a push built on a stale copy of the body is refused instead of silently overwriting whatever replaced it. Absent on a binding last written before the field existed, where no comparison is possible."
|
|
65943
65392
|
)
|
|
65944
65393
|
});
|
|
65945
|
-
var
|
|
65946
|
-
|
|
65947
|
-
|
|
65948
|
-
by: tableRecordSortSchema
|
|
65949
|
-
});
|
|
65950
|
-
var queryKeysetSchema = zod_default.object({
|
|
65951
|
-
// The single sort key the cursor seeks on (0 or 1 — multi-key sorts fall back
|
|
65952
|
-
// to OFFSET). `__source_record_id` ASC is always appended as the tiebreaker,
|
|
65953
|
-
// so the order is total and pages never skip/duplicate on ties.
|
|
65954
|
-
by: tableRecordSortSchema.max(1),
|
|
65955
|
-
// The seek position — absent on the FIRST page (ordering only, no predicate).
|
|
65956
|
-
after: zod_default.object({
|
|
65957
|
-
// The sort key's value on the last row of the previous page (one per `by`
|
|
65958
|
-
// entry), and that row's record id — together the seek position.
|
|
65959
|
-
values: zod_default.array(zod_default.union([zod_default.string(), zod_default.number(), zod_default.boolean(), zod_default.null()])),
|
|
65960
|
-
id: zod_default.string()
|
|
65961
|
-
}).optional()
|
|
65962
|
-
});
|
|
65963
|
-
var queryLimitNodeSchema = zod_default.object({
|
|
65964
|
-
kind: zod_default.literal("limit"),
|
|
65965
|
-
from: zod_default.lazy(() => queryNodeSchema),
|
|
65966
|
-
n: zod_default.number().int().positive(),
|
|
65967
|
-
offset: zod_default.number().int().nonnegative().optional(),
|
|
65968
|
-
// Keyset (seek) pagination — mutually exclusive with `offset`. When present,
|
|
65969
|
-
// the node applies the ORDER BY (`by` + id tiebreaker) and a seek predicate
|
|
65970
|
-
// itself, so `from` must NOT be pre-wrapped in a sort node.
|
|
65971
|
-
keyset: queryKeysetSchema.optional()
|
|
65972
|
-
});
|
|
65973
|
-
var queryUnpivotPassthroughColumnSchema = zod_default.object({
|
|
65974
|
-
output: zod_default.string(),
|
|
65975
|
-
type: queryColumnTypeSchema,
|
|
65976
|
-
source: querySourceSchema
|
|
65977
|
-
});
|
|
65978
|
-
var queryUnpivotRowColumnSchema = zod_default.object({
|
|
65979
|
-
output: zod_default.string(),
|
|
65980
|
-
type: queryColumnTypeSchema
|
|
65394
|
+
var appWorkflowContractSchema = zod_default.object({
|
|
65395
|
+
inputs: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional(),
|
|
65396
|
+
outputs: zod_default.record(zod_default.string(), appWorkflowOutputSchema).optional()
|
|
65981
65397
|
});
|
|
65982
|
-
var
|
|
65983
|
-
|
|
65984
|
-
|
|
65985
|
-
|
|
65986
|
-
"Columns projected once from the source row and replicated across every fanned-out row. May be empty."
|
|
65398
|
+
var MAX_APP_CAPABILITY_DESCRIPTION = 300;
|
|
65399
|
+
var appQueryDeclarationSchema = zod_default.object({
|
|
65400
|
+
ast: zod_default.unknown().describe(
|
|
65401
|
+
"Query AST template (a QueryNode). Validated server-side via parseQueryNode at deploy. May embed {{params.<name>}} tokens in filter value positions."
|
|
65987
65402
|
),
|
|
65988
|
-
|
|
65989
|
-
"
|
|
65403
|
+
params: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe(
|
|
65404
|
+
"Typed param schema. Keys are param names referenced as {{params.<name>}} in the ast; values declare type + constraints. The server validates the caller's params payload against this before interpolating. Omit for queries that take no params."
|
|
65990
65405
|
),
|
|
65991
|
-
|
|
65992
|
-
|
|
65406
|
+
description: zod_default.string().optional().describe(
|
|
65407
|
+
`What this query returns, in one line \u2014 read by an agent choosing between the app's aliases. An alias is a JS identifier, which names a query without saying what it covers. Capped at ${MAX_APP_CAPABILITY_DESCRIPTION} characters.`
|
|
65993
65408
|
)
|
|
65994
65409
|
});
|
|
65995
|
-
var
|
|
65996
|
-
|
|
65997
|
-
|
|
65998
|
-
|
|
65999
|
-
"Array-valued input column to fan out (select / select_member / select_record_link / files, incl. array-valued lookups)."
|
|
65410
|
+
var appAgentDeclarationSchema = zod_default.object({
|
|
65411
|
+
instructions: zod_default.string().min(1).describe("System instructions for the agent \u2014 the task it performs per run."),
|
|
65412
|
+
tool_names: zod_default.array(zod_default.string().min(1)).describe(
|
|
65413
|
+
"Tools the agent may call, resolved against the shared registry minus the automation blacklist. The capability boundary \u2014 the run can use nothing else. May be empty for a pure-reasoning agent."
|
|
66000
65414
|
),
|
|
66001
|
-
|
|
66002
|
-
"
|
|
65415
|
+
knowledge_doc_ids: zod_default.array(zod_default.string().min(1)).optional().describe(
|
|
65416
|
+
"Knowledge docs the agent may read, validated at declare time against the app owner's `use` access. Small docs are inlined into the agent's system prompt each run; a doc too large to inline requires the code tools (code_exec) in tool_names and is read by staging it into a code run. Omit for an agent that needs no knowledge."
|
|
66003
65417
|
),
|
|
66004
|
-
|
|
66005
|
-
"
|
|
65418
|
+
query_aliases: zod_default.array(zod_default.string().min(1)).optional().describe(
|
|
65419
|
+
"Named queries from this app's manifest the agent may run via `run_app_query`, validated at declare time against the app's own queries. This is the agent's ENTIRE read surface over workspace data \u2014 a template fixes the tables, filters, and projection, so it bounds rows and columns, not just tables. Omit for an agent that reads no records."
|
|
66006
65420
|
),
|
|
66007
|
-
|
|
66008
|
-
"
|
|
65421
|
+
workflow_aliases: zod_default.array(zod_default.string().min(1)).optional().describe(
|
|
65422
|
+
"Workflows from this app's manifest the agent may invoke via `run_app_workflow`, validated at declare time against the app's own workflows. This is the agent's ENTIRE write surface \u2014 the same declared mutation path the app's UI uses, so table hooks and side-effect harvesting apply. Omit for a read-only agent."
|
|
65423
|
+
),
|
|
65424
|
+
model_tier: zod_default.enum(MODEL_TIERS).optional().describe(
|
|
65425
|
+
"Model tier the agent runs on \u2014 `haiku`, `sonnet`, or `opus`. Omit to follow the platform default tier, resolved at run time: the preferred choice. A tier names capability, not a version, so the generation behind it moves with the platform and this declaration never needs a rewrite. Pin only a deliberate, tested choice."
|
|
65426
|
+
),
|
|
65427
|
+
effort_level: zod_default.enum(EFFORT_LEVELS).optional().describe(
|
|
65428
|
+
"Reasoning depth for adaptive-thinking tiers \u2014 one of the chosen tier's supported levels (validated against model_tier at declare time). Omit to use the model default; ignored on tiers without adaptive thinking."
|
|
65429
|
+
),
|
|
65430
|
+
prefix_cache_ttl: zod_default.enum(PREFIX_CACHE_TTLS).optional().describe(
|
|
65431
|
+
`How long this agent's prompt-cache prefix (tools + system block) is kept warm. Omit \u2014 the default (5m, Anthropic's own) is right for essentially every agent. "1h" doubles the write price (2x the input rate against 1.25x) to buy only the 5m..1h band, and an entry nothing re-reads inside the hour is paid for twice over; declining it still leaves the prefix cached at the default. Set it only from measured cadence, never a guess.`
|
|
65432
|
+
),
|
|
65433
|
+
inputs: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe(
|
|
65434
|
+
"Typed input schema for one run. Keys are input names; values declare type + constraints. The server validates the run payload against this before invoking; CLI codegen emits a typed `useAgentRun<alias>` signature. Omit for an untyped payload."
|
|
65435
|
+
),
|
|
65436
|
+
outputs: zod_default.record(zod_default.string(), appWorkflowOutputSchema).optional().describe(
|
|
65437
|
+
"Typed output schema for the structured result the agent emits. Keys are field names; values declare type + (nested object/array) shape. When declared, the run must emit a result matching it \u2014 the server validates before persisting and the SDK types `run.output`. Omit for a free-text run whose output is the final message."
|
|
65438
|
+
).refine(
|
|
65439
|
+
(outputs) => outputs === void 0 || Object.values(outputs).every((o) => appWorkflowOutputDepth(o) <= MAX_APP_WORKFLOW_OUTPUT_DEPTH),
|
|
65440
|
+
{ message: `output schema nesting exceeds the max depth of ${MAX_APP_WORKFLOW_OUTPUT_DEPTH}` }
|
|
66009
65441
|
)
|
|
66010
65442
|
});
|
|
66011
|
-
var
|
|
66012
|
-
|
|
66013
|
-
required: zod_default.boolean().optional().describe("Whether the input must be provided. Defaults to true.")
|
|
66014
|
-
});
|
|
66015
|
-
var appWorkflowInputTextSchema = appWorkflowInputBaseSchema.extend({
|
|
66016
|
-
type: zod_default.literal("text")
|
|
66017
|
-
});
|
|
66018
|
-
var appWorkflowInputNumberSchema = appWorkflowInputBaseSchema.extend({
|
|
66019
|
-
type: zod_default.literal("number")
|
|
66020
|
-
});
|
|
66021
|
-
var appWorkflowInputBooleanSchema = appWorkflowInputBaseSchema.extend({
|
|
66022
|
-
type: zod_default.literal("boolean")
|
|
66023
|
-
});
|
|
66024
|
-
var appWorkflowInputDateSchema = appWorkflowInputBaseSchema.extend({
|
|
66025
|
-
type: zod_default.literal("date")
|
|
65443
|
+
var appThemeSchema = zod_default.object({
|
|
65444
|
+
color: optionColorSchema.nullable().optional().describe("Theme color for the app")
|
|
66026
65445
|
});
|
|
66027
|
-
var
|
|
66028
|
-
|
|
65446
|
+
var appCapabilitiesSchema = zod_default.object({
|
|
65447
|
+
comments: zod_default.boolean().optional().describe(
|
|
65448
|
+
"Enable the members-only `useComments` primitive. When true, the app may read/write record comments \u2014 each operation under the VIEWING member's own table access, row-scope, and author identity (never the app owner's). Default off."
|
|
65449
|
+
)
|
|
66029
65450
|
});
|
|
66030
|
-
var
|
|
66031
|
-
|
|
65451
|
+
var appSchema = zod_default.object({
|
|
65452
|
+
id: zod_default.string().describe("Unique identifier for the app"),
|
|
65453
|
+
name: zod_default.string().describe("Display name of the app"),
|
|
65454
|
+
description: zod_default.string().nullable().optional().describe("Optional description of the app's purpose"),
|
|
65455
|
+
icon: zod_default.string().nullable().optional().describe("Icon name for the app (e.g., 'home', 'chart-bar')"),
|
|
65456
|
+
workspace_id: zod_default.string().describe("ID of the workspace this app belongs to"),
|
|
65457
|
+
current_version_id: zod_default.string().nullable().optional().describe(
|
|
65458
|
+
"Pointer to the currently-published app_versions row in R2. Set once the app has been deployed at least once via `lotics app deploy`; null before the first deploy."
|
|
65459
|
+
),
|
|
65460
|
+
public_subdomain: zod_default.string().describe(
|
|
65461
|
+
"DNS label for the app's public origin: `<public_subdomain>.lotics.app`. Server-generated, high-entropy, and distinct from `id` (app_ids are not valid DNS labels). Assigned at creation for every app."
|
|
65462
|
+
),
|
|
65463
|
+
public_password_set: zod_default.boolean().optional().describe(
|
|
65464
|
+
"Whether a shared password gates the public binding. True \u2192 anonymous visitors must authenticate at `/v1/apps/{app_id}/public/authenticate` before any publicAppAccess endpoint resolves. The hash itself is never sent over the wire; only this flag is exposed (and only on authenticated owner-side reads \u2014 the public by-subdomain response surfaces the same fact as `requires_password`)."
|
|
65465
|
+
),
|
|
65466
|
+
workflows: zod_default.record(zod_default.string(), appWorkflowDeclarationSchema).nullable().optional().describe(
|
|
65467
|
+
"Alias \u2192 workflow declaration map. Each alias resolves to a workflow_id and an optional typed inputs schema. Authored solely by `set_app_workflow` / `remove_app_workflow` (NOT by `lotics app deploy`, which never touches this map). The iframe SDK's useWorkflow(alias) resolves through this map; when an inputs schema is declared, the server validates payloads against it before invocation and the CLI codegen emits typed call-site signatures. The workflow always executes under the app's IAM principal."
|
|
65468
|
+
),
|
|
65469
|
+
queries: zod_default.record(zod_default.string(), appQueryDeclarationSchema).nullable().optional().describe(
|
|
65470
|
+
"Alias \u2192 query declaration map. Each alias resolves to a fixed query AST template with a typed param schema. Synced from the app's lotics.queries manifest on every `lotics app deploy`. The iframe SDK's useQuery(alias, params) resolves through this map; custom-code apps never send a raw AST. The query runs under the app's IAM principal."
|
|
65471
|
+
),
|
|
65472
|
+
capabilities: appCapabilitiesSchema.nullable().optional().describe(
|
|
65473
|
+
"Opt-in app capabilities, declared in the manifest's `lotics.capabilities` and synced on every deploy. Capabilities are off unless declared \u2014 least ambient authority. `comments` gates the members-only `useComments` primitive: only an app that declares it can read/write record comments (each under the VIEWING member's own authority)."
|
|
65474
|
+
),
|
|
65475
|
+
agents: zod_default.record(zod_default.string(), appAgentDeclarationSchema).nullable().optional().describe(
|
|
65476
|
+
"Alias \u2192 agent declaration map. Each alias binds a streaming tool-loop agent the app runs via `useAgentRun(alias)` (an SSE stream), with declared tools, model, and typed inputs/outputs. Synced from the app's `lotics.agents` manifest on every deploy. The agent runs under the app's IAM principal; runs persist a flat history per session."
|
|
65477
|
+
),
|
|
65478
|
+
theme: appThemeSchema.nullable().optional().describe("Theme settings for the app"),
|
|
65479
|
+
/**
|
|
65480
|
+
* The starter this app is the ORIGIN of, when it is one — list enrichment,
|
|
65481
|
+
* read from the registry rather than stored on the app.
|
|
65482
|
+
*
|
|
65483
|
+
* This is provenance in the only direction that exists under one-way copies:
|
|
65484
|
+
* an app can have PUBLISHED a starter, but an app that was COPIED FROM one
|
|
65485
|
+
* records nothing, because it owns everything it received outright. Null for
|
|
65486
|
+
* every app that has published nothing.
|
|
65487
|
+
*/
|
|
65488
|
+
starter_origin: zod_default.object({
|
|
65489
|
+
starter_id: zod_default.string(),
|
|
65490
|
+
/** The highest version published from this app. */
|
|
65491
|
+
version: zod_default.number().int(),
|
|
65492
|
+
is_official: zod_default.boolean()
|
|
65493
|
+
}).nullable().optional(),
|
|
65494
|
+
created_at: zod_default.string().describe("Timestamp when app was created"),
|
|
65495
|
+
updated_at: zod_default.string().describe("Timestamp of last update")
|
|
66032
65496
|
});
|
|
66033
|
-
|
|
66034
|
-
|
|
66035
|
-
|
|
66036
|
-
|
|
65497
|
+
|
|
65498
|
+
// ../../node_modules/@date-fns/tz/tzName/index.js
|
|
65499
|
+
function tzName(timeZone, date6, format2 = "long") {
|
|
65500
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
65501
|
+
// Enforces engine to render the time. Without the option JavaScriptCore omits it.
|
|
65502
|
+
hour: "numeric",
|
|
65503
|
+
timeZone,
|
|
65504
|
+
timeZoneName: format2
|
|
65505
|
+
}).format(date6).split(/\s/g).slice(2).join(" ");
|
|
65506
|
+
}
|
|
65507
|
+
|
|
65508
|
+
// ../../node_modules/@date-fns/tz/tzOffset/index.js
|
|
65509
|
+
var offsetFormatCache = {};
|
|
65510
|
+
var offsetCache = {};
|
|
65511
|
+
function tzOffset(timeZone, date6) {
|
|
65512
|
+
try {
|
|
65513
|
+
const format2 = offsetFormatCache[timeZone] ||= new Intl.DateTimeFormat("en-US", {
|
|
65514
|
+
timeZone,
|
|
65515
|
+
timeZoneName: "longOffset"
|
|
65516
|
+
}).format;
|
|
65517
|
+
const offsetStr = format2(date6).split("GMT")[1];
|
|
65518
|
+
if (offsetStr in offsetCache) return offsetCache[offsetStr];
|
|
65519
|
+
return calcOffset(offsetStr, offsetStr.split(":"));
|
|
65520
|
+
} catch {
|
|
65521
|
+
if (timeZone in offsetCache) return offsetCache[timeZone];
|
|
65522
|
+
const captures = timeZone?.match(offsetRe);
|
|
65523
|
+
if (captures) return calcOffset(timeZone, captures.slice(1));
|
|
65524
|
+
return NaN;
|
|
65525
|
+
}
|
|
65526
|
+
}
|
|
65527
|
+
var offsetRe = /([+-]\d\d):?(\d\d)?/;
|
|
65528
|
+
function calcOffset(cacheStr, values3) {
|
|
65529
|
+
const hours = +(values3[0] || 0);
|
|
65530
|
+
const minutes = +(values3[1] || 0);
|
|
65531
|
+
const seconds = +(values3[2] || 0) / 60;
|
|
65532
|
+
return offsetCache[cacheStr] = hours * 60 + minutes > 0 ? hours * 60 + minutes + seconds : hours * 60 - minutes - seconds;
|
|
65533
|
+
}
|
|
65534
|
+
|
|
65535
|
+
// ../../node_modules/@date-fns/tz/date/mini.js
|
|
65536
|
+
var TZDateMini = class _TZDateMini extends Date {
|
|
65537
|
+
//#region static
|
|
65538
|
+
constructor(...args) {
|
|
65539
|
+
super();
|
|
65540
|
+
if (args.length > 1 && typeof args[args.length - 1] === "string") {
|
|
65541
|
+
this.timeZone = args.pop();
|
|
65542
|
+
}
|
|
65543
|
+
this.internal = /* @__PURE__ */ new Date();
|
|
65544
|
+
if (isNaN(tzOffset(this.timeZone, this))) {
|
|
65545
|
+
this.setTime(NaN);
|
|
65546
|
+
} else {
|
|
65547
|
+
if (!args.length) {
|
|
65548
|
+
this.setTime(Date.now());
|
|
65549
|
+
} else if (typeof args[0] === "number" && (args.length === 1 || args.length === 2 && typeof args[1] !== "number")) {
|
|
65550
|
+
this.setTime(args[0]);
|
|
65551
|
+
} else if (typeof args[0] === "string") {
|
|
65552
|
+
this.setTime(+new Date(args[0]));
|
|
65553
|
+
} else if (args[0] instanceof Date) {
|
|
65554
|
+
this.setTime(+args[0]);
|
|
65555
|
+
} else {
|
|
65556
|
+
this.setTime(+new Date(...args));
|
|
65557
|
+
adjustToSystemTZ(this, NaN);
|
|
65558
|
+
syncToInternal(this);
|
|
65559
|
+
}
|
|
65560
|
+
}
|
|
65561
|
+
}
|
|
65562
|
+
static tz(tz, ...args) {
|
|
65563
|
+
return args.length ? new _TZDateMini(...args, tz) : new _TZDateMini(Date.now(), tz);
|
|
65564
|
+
}
|
|
65565
|
+
//#endregion
|
|
65566
|
+
//#region time zone
|
|
65567
|
+
withTimeZone(timeZone) {
|
|
65568
|
+
return new _TZDateMini(+this, timeZone);
|
|
65569
|
+
}
|
|
65570
|
+
getTimezoneOffset() {
|
|
65571
|
+
const offset = -tzOffset(this.timeZone, this);
|
|
65572
|
+
return offset > 0 ? Math.floor(offset) : Math.ceil(offset);
|
|
65573
|
+
}
|
|
65574
|
+
//#endregion
|
|
65575
|
+
//#region time
|
|
65576
|
+
setTime(time3) {
|
|
65577
|
+
Date.prototype.setTime.apply(this, arguments);
|
|
65578
|
+
syncToInternal(this);
|
|
65579
|
+
return +this;
|
|
65580
|
+
}
|
|
65581
|
+
//#endregion
|
|
65582
|
+
//#region date-fns integration
|
|
65583
|
+
[/* @__PURE__ */ Symbol.for("constructDateFrom")](date6) {
|
|
65584
|
+
return new _TZDateMini(+new Date(date6), this.timeZone);
|
|
65585
|
+
}
|
|
65586
|
+
//#endregion
|
|
65587
|
+
};
|
|
65588
|
+
var re = /^(get|set)(?!UTC)/;
|
|
65589
|
+
Object.getOwnPropertyNames(Date.prototype).forEach((method) => {
|
|
65590
|
+
if (!re.test(method)) return;
|
|
65591
|
+
const utcMethod = method.replace(re, "$1UTC");
|
|
65592
|
+
if (!TZDateMini.prototype[utcMethod]) return;
|
|
65593
|
+
if (method.startsWith("get")) {
|
|
65594
|
+
TZDateMini.prototype[method] = function() {
|
|
65595
|
+
return this.internal[utcMethod]();
|
|
65596
|
+
};
|
|
65597
|
+
} else {
|
|
65598
|
+
TZDateMini.prototype[method] = function() {
|
|
65599
|
+
Date.prototype[utcMethod].apply(this.internal, arguments);
|
|
65600
|
+
syncFromInternal(this);
|
|
65601
|
+
return +this;
|
|
65602
|
+
};
|
|
65603
|
+
TZDateMini.prototype[utcMethod] = function() {
|
|
65604
|
+
Date.prototype[utcMethod].apply(this, arguments);
|
|
65605
|
+
syncToInternal(this);
|
|
65606
|
+
return +this;
|
|
65607
|
+
};
|
|
65608
|
+
}
|
|
66037
65609
|
});
|
|
66038
|
-
|
|
66039
|
-
|
|
66040
|
-
|
|
66041
|
-
|
|
66042
|
-
|
|
66043
|
-
|
|
66044
|
-
|
|
66045
|
-
|
|
66046
|
-
|
|
66047
|
-
|
|
66048
|
-
|
|
65610
|
+
function syncToInternal(date6) {
|
|
65611
|
+
date6.internal.setTime(+date6);
|
|
65612
|
+
date6.internal.setUTCSeconds(date6.internal.getUTCSeconds() - Math.round(-tzOffset(date6.timeZone, date6) * 60));
|
|
65613
|
+
}
|
|
65614
|
+
function syncFromInternal(date6) {
|
|
65615
|
+
Date.prototype.setFullYear.call(date6, date6.internal.getUTCFullYear(), date6.internal.getUTCMonth(), date6.internal.getUTCDate());
|
|
65616
|
+
Date.prototype.setHours.call(date6, date6.internal.getUTCHours(), date6.internal.getUTCMinutes(), date6.internal.getUTCSeconds(), date6.internal.getUTCMilliseconds());
|
|
65617
|
+
adjustToSystemTZ(date6);
|
|
65618
|
+
}
|
|
65619
|
+
function adjustToSystemTZ(date6) {
|
|
65620
|
+
const baseOffset = tzOffset(date6.timeZone, date6);
|
|
65621
|
+
const offset = baseOffset > 0 ? Math.floor(baseOffset) : Math.ceil(baseOffset);
|
|
65622
|
+
const prevHour = /* @__PURE__ */ new Date(+date6);
|
|
65623
|
+
prevHour.setUTCHours(prevHour.getUTCHours() - 1);
|
|
65624
|
+
const systemOffset = -(/* @__PURE__ */ new Date(+date6)).getTimezoneOffset();
|
|
65625
|
+
const prevHourSystemOffset = -(/* @__PURE__ */ new Date(+prevHour)).getTimezoneOffset();
|
|
65626
|
+
const systemDSTChange = systemOffset - prevHourSystemOffset;
|
|
65627
|
+
const dstShift = Date.prototype.getHours.apply(date6) !== date6.internal.getUTCHours();
|
|
65628
|
+
if (systemDSTChange && dstShift) date6.internal.setUTCMinutes(date6.internal.getUTCMinutes() + systemDSTChange);
|
|
65629
|
+
const offsetDiff = systemOffset - offset;
|
|
65630
|
+
if (offsetDiff) Date.prototype.setUTCMinutes.call(date6, Date.prototype.getUTCMinutes.call(date6) + offsetDiff);
|
|
65631
|
+
const systemDate = /* @__PURE__ */ new Date(+date6);
|
|
65632
|
+
systemDate.setUTCSeconds(0);
|
|
65633
|
+
const systemSecondsOffset = systemOffset > 0 ? systemDate.getSeconds() : (systemDate.getSeconds() - 60) % 60;
|
|
65634
|
+
const secondsOffset = Math.round(-(tzOffset(date6.timeZone, date6) * 60)) % 60;
|
|
65635
|
+
if (secondsOffset || systemSecondsOffset) {
|
|
65636
|
+
date6.internal.setUTCSeconds(date6.internal.getUTCSeconds() + secondsOffset);
|
|
65637
|
+
Date.prototype.setUTCSeconds.call(date6, Date.prototype.getUTCSeconds.call(date6) + secondsOffset + systemSecondsOffset);
|
|
65638
|
+
}
|
|
65639
|
+
const postBaseOffset = tzOffset(date6.timeZone, date6);
|
|
65640
|
+
const postOffset = postBaseOffset > 0 ? Math.floor(postBaseOffset) : Math.ceil(postBaseOffset);
|
|
65641
|
+
const postSystemOffset = -(/* @__PURE__ */ new Date(+date6)).getTimezoneOffset();
|
|
65642
|
+
const postOffsetDiff = postSystemOffset - postOffset;
|
|
65643
|
+
const offsetChanged = postOffset !== offset;
|
|
65644
|
+
const postDiff = postOffsetDiff - offsetDiff;
|
|
65645
|
+
if (offsetChanged && postDiff) {
|
|
65646
|
+
Date.prototype.setUTCMinutes.call(date6, Date.prototype.getUTCMinutes.call(date6) + postDiff);
|
|
65647
|
+
const newBaseOffset = tzOffset(date6.timeZone, date6);
|
|
65648
|
+
const newOffset = newBaseOffset > 0 ? Math.floor(newBaseOffset) : Math.ceil(newBaseOffset);
|
|
65649
|
+
const offsetChange = postOffset - newOffset;
|
|
65650
|
+
if (offsetChange) {
|
|
65651
|
+
date6.internal.setUTCMinutes(date6.internal.getUTCMinutes() + offsetChange);
|
|
65652
|
+
Date.prototype.setUTCMinutes.call(date6, Date.prototype.getUTCMinutes.call(date6) + offsetChange);
|
|
65653
|
+
}
|
|
65654
|
+
}
|
|
65655
|
+
}
|
|
65656
|
+
|
|
65657
|
+
// ../../node_modules/@date-fns/tz/date/index.js
|
|
65658
|
+
var TZDate = class _TZDate extends TZDateMini {
|
|
65659
|
+
//#region static
|
|
65660
|
+
static tz(tz, ...args) {
|
|
65661
|
+
return args.length ? new _TZDate(...args, tz) : new _TZDate(Date.now(), tz);
|
|
65662
|
+
}
|
|
65663
|
+
//#endregion
|
|
65664
|
+
//#region representation
|
|
65665
|
+
toISOString() {
|
|
65666
|
+
const [sign, hours, minutes] = this.tzComponents();
|
|
65667
|
+
const tz = `${sign}${hours}:${minutes}`;
|
|
65668
|
+
return this.internal.toISOString().slice(0, -1) + tz;
|
|
65669
|
+
}
|
|
65670
|
+
toString() {
|
|
65671
|
+
return `${this.toDateString()} ${this.toTimeString()}`;
|
|
65672
|
+
}
|
|
65673
|
+
toDateString() {
|
|
65674
|
+
const [day, date6, month, year] = this.internal.toUTCString().split(" ");
|
|
65675
|
+
return `${day?.slice(0, -1)} ${month} ${date6} ${year}`;
|
|
65676
|
+
}
|
|
65677
|
+
toTimeString() {
|
|
65678
|
+
const time3 = this.internal.toUTCString().split(" ")[4];
|
|
65679
|
+
const [sign, hours, minutes] = this.tzComponents();
|
|
65680
|
+
return `${time3} GMT${sign}${hours}${minutes} (${tzName(this.timeZone, this)})`;
|
|
65681
|
+
}
|
|
65682
|
+
toLocaleString(locales, options) {
|
|
65683
|
+
return Date.prototype.toLocaleString.call(this, locales, {
|
|
65684
|
+
...options,
|
|
65685
|
+
timeZone: options?.timeZone || this.timeZone
|
|
65686
|
+
});
|
|
65687
|
+
}
|
|
65688
|
+
toLocaleDateString(locales, options) {
|
|
65689
|
+
return Date.prototype.toLocaleDateString.call(this, locales, {
|
|
65690
|
+
...options,
|
|
65691
|
+
timeZone: options?.timeZone || this.timeZone
|
|
65692
|
+
});
|
|
65693
|
+
}
|
|
65694
|
+
toLocaleTimeString(locales, options) {
|
|
65695
|
+
return Date.prototype.toLocaleTimeString.call(this, locales, {
|
|
65696
|
+
...options,
|
|
65697
|
+
timeZone: options?.timeZone || this.timeZone
|
|
65698
|
+
});
|
|
65699
|
+
}
|
|
65700
|
+
//#endregion
|
|
65701
|
+
//#region private
|
|
65702
|
+
tzComponents() {
|
|
65703
|
+
const offset = this.getTimezoneOffset();
|
|
65704
|
+
const sign = offset > 0 ? "-" : "+";
|
|
65705
|
+
const hours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, "0");
|
|
65706
|
+
const minutes = String(Math.abs(offset) % 60).padStart(2, "0");
|
|
65707
|
+
return [sign, hours, minutes];
|
|
65708
|
+
}
|
|
65709
|
+
//#endregion
|
|
65710
|
+
withTimeZone(timeZone) {
|
|
65711
|
+
return new _TZDate(+this, timeZone);
|
|
65712
|
+
}
|
|
65713
|
+
//#region date-fns integration
|
|
65714
|
+
[/* @__PURE__ */ Symbol.for("constructDateFrom")](date6) {
|
|
65715
|
+
return new _TZDate(+new Date(date6), this.timeZone);
|
|
65716
|
+
}
|
|
65717
|
+
//#endregion
|
|
65718
|
+
};
|
|
65719
|
+
|
|
65720
|
+
// ../shared/src/app_query_ast.ts
|
|
65721
|
+
function collectQueryTableIds(node) {
|
|
65722
|
+
const result = /* @__PURE__ */ new Set();
|
|
65723
|
+
walk(node, (n) => {
|
|
65724
|
+
if (n.kind === "from_table") result.add(n.table_id);
|
|
65725
|
+
});
|
|
65726
|
+
return result;
|
|
65727
|
+
}
|
|
65728
|
+
function walk(node, visit) {
|
|
65729
|
+
visit(node);
|
|
65730
|
+
switch (node.kind) {
|
|
65731
|
+
case "from_table":
|
|
65732
|
+
return;
|
|
65733
|
+
case "project":
|
|
65734
|
+
case "filter":
|
|
65735
|
+
case "group":
|
|
65736
|
+
case "window":
|
|
65737
|
+
case "sort":
|
|
65738
|
+
case "limit":
|
|
65739
|
+
case "unpivot":
|
|
65740
|
+
case "unnest":
|
|
65741
|
+
walk(node.from, visit);
|
|
65742
|
+
return;
|
|
65743
|
+
case "join":
|
|
65744
|
+
walk(node.left, visit);
|
|
65745
|
+
walk(node.right, visit);
|
|
65746
|
+
return;
|
|
65747
|
+
case "union":
|
|
65748
|
+
for (const child of node.sources) walk(child, visit);
|
|
65749
|
+
return;
|
|
65750
|
+
default: {
|
|
65751
|
+
const _exhaustive = node;
|
|
65752
|
+
void _exhaustive;
|
|
65753
|
+
return;
|
|
65754
|
+
}
|
|
65755
|
+
}
|
|
65756
|
+
}
|
|
65757
|
+
|
|
65758
|
+
// ../shared/src/app_query_output_schema.ts
|
|
65759
|
+
function normalizeProjectionColumn(proj) {
|
|
65760
|
+
return typeof proj === "string" ? { source: proj } : proj;
|
|
65761
|
+
}
|
|
65762
|
+
function resolveProjectionOutput(proj) {
|
|
65763
|
+
const col = normalizeProjectionColumn(proj);
|
|
65764
|
+
if (col.output !== void 0) return col.output;
|
|
65765
|
+
return typeof col.source === "string" ? col.source : void 0;
|
|
65766
|
+
}
|
|
65767
|
+
function queryOutputNames(node) {
|
|
65768
|
+
switch (node.kind) {
|
|
65769
|
+
case "from_table":
|
|
65770
|
+
return void 0;
|
|
65771
|
+
case "project": {
|
|
65772
|
+
const names = [];
|
|
65773
|
+
for (const proj of node.columns) {
|
|
65774
|
+
const output = resolveProjectionOutput(proj);
|
|
65775
|
+
if (output === void 0) return void 0;
|
|
65776
|
+
names.push(output);
|
|
65777
|
+
}
|
|
65778
|
+
return names;
|
|
65779
|
+
}
|
|
65780
|
+
case "filter":
|
|
65781
|
+
case "sort":
|
|
65782
|
+
case "limit":
|
|
65783
|
+
return queryOutputNames(node.from);
|
|
65784
|
+
case "join": {
|
|
65785
|
+
const left = queryOutputNames(node.left);
|
|
65786
|
+
const right = queryOutputNames(node.right);
|
|
65787
|
+
return left && right ? [...left, ...right] : void 0;
|
|
65788
|
+
}
|
|
65789
|
+
case "union":
|
|
65790
|
+
return node.sources.length > 0 ? queryOutputNames(node.sources[0]) : void 0;
|
|
65791
|
+
case "group":
|
|
65792
|
+
return [
|
|
65793
|
+
...node.by.map((key) => typeof key === "string" ? key : key.bucket.output),
|
|
65794
|
+
...node.aggregates.map((agg) => agg.output)
|
|
65795
|
+
];
|
|
65796
|
+
case "window": {
|
|
65797
|
+
const input = queryOutputNames(node.from);
|
|
65798
|
+
if (input === void 0) return void 0;
|
|
65799
|
+
return [
|
|
65800
|
+
...input,
|
|
65801
|
+
...(node.aggregates ?? []).map((a) => a.output),
|
|
65802
|
+
...(node.functions ?? []).map((f) => f.output)
|
|
65803
|
+
];
|
|
65804
|
+
}
|
|
65805
|
+
case "unpivot":
|
|
65806
|
+
return [...node.passthrough.map((p) => p.output), ...node.row_columns.map((c) => c.output)];
|
|
65807
|
+
case "unnest": {
|
|
65808
|
+
const input = queryOutputNames(node.from);
|
|
65809
|
+
if (input === void 0) return void 0;
|
|
65810
|
+
return [...input, node.output, ...node.display_output !== void 0 ? [node.display_output] : []];
|
|
65811
|
+
}
|
|
65812
|
+
default: {
|
|
65813
|
+
const _exhaustive = node;
|
|
65814
|
+
return _exhaustive;
|
|
65815
|
+
}
|
|
65816
|
+
}
|
|
65817
|
+
}
|
|
65818
|
+
|
|
65819
|
+
// ../shared/src/app_dts.ts
|
|
65820
|
+
var IDENTIFIER_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
65821
|
+
function isValidIdentifier(name2) {
|
|
65822
|
+
return IDENTIFIER_REGEX.test(name2);
|
|
65823
|
+
}
|
|
65824
|
+
function inputsToType(inputs, opts) {
|
|
65825
|
+
const nullableOptional = opts?.nullableOptional === true;
|
|
65826
|
+
const fields = [];
|
|
65827
|
+
for (const [key, decl] of Object.entries(inputs)) {
|
|
65828
|
+
if (decl === null || typeof decl !== "object") continue;
|
|
65829
|
+
const d = decl;
|
|
65830
|
+
const tsType = inputDeclToTsType(d);
|
|
65831
|
+
const isOptional = d.required === false;
|
|
65832
|
+
const fieldType = isOptional && nullableOptional ? `${tsType} | null` : tsType;
|
|
65833
|
+
const optional2 = isOptional ? "?" : "";
|
|
65834
|
+
const fieldKey = isValidIdentifier(key) ? key : JSON.stringify(key);
|
|
65835
|
+
fields.push(` ${fieldKey}${optional2}: ${fieldType};`);
|
|
65836
|
+
}
|
|
65837
|
+
if (fields.length === 0) return "Record<string, never>";
|
|
65838
|
+
return `{
|
|
65839
|
+
${fields.join("\n")}
|
|
65840
|
+
}`;
|
|
65841
|
+
}
|
|
65842
|
+
function inputDeclToTsType(decl) {
|
|
65843
|
+
const type = decl.type;
|
|
65844
|
+
switch (type) {
|
|
65845
|
+
case "text":
|
|
65846
|
+
case "email":
|
|
65847
|
+
case "date":
|
|
65848
|
+
case "datetime":
|
|
65849
|
+
return "string";
|
|
65850
|
+
case "number":
|
|
65851
|
+
return "number";
|
|
65852
|
+
case "boolean":
|
|
65853
|
+
return "boolean";
|
|
65854
|
+
case "record_link":
|
|
65855
|
+
case "member": {
|
|
65856
|
+
const inner = "string";
|
|
65857
|
+
return decl.multi === true ? `ReadonlyArray<${inner}>` : inner;
|
|
65858
|
+
}
|
|
65859
|
+
case "select": {
|
|
65860
|
+
const options = Array.isArray(decl.options) ? decl.options : [];
|
|
65861
|
+
const literals = options.map((o) => {
|
|
65862
|
+
if (o !== null && typeof o === "object" && "value" in o && typeof o.value === "string") {
|
|
65863
|
+
return JSON.stringify(o.value);
|
|
65864
|
+
}
|
|
65865
|
+
return null;
|
|
65866
|
+
}).filter((v) => v !== null);
|
|
65867
|
+
const inner = literals.length > 0 ? `${literals.join(" | ")} | (string & {})` : "string";
|
|
65868
|
+
return decl.multi === true ? `ReadonlyArray<${inner}>` : inner;
|
|
65869
|
+
}
|
|
65870
|
+
case "date_range":
|
|
65871
|
+
return "{ start: string; end: string }";
|
|
65872
|
+
case "file":
|
|
65873
|
+
return decl.multi === true ? "ReadonlyArray<string>" : "string";
|
|
65874
|
+
case "object": {
|
|
65875
|
+
const fields = decl.fields !== null && typeof decl.fields === "object" ? decl.fields : {};
|
|
65876
|
+
return inputsToType(fields);
|
|
65877
|
+
}
|
|
65878
|
+
case "array": {
|
|
65879
|
+
const items = decl.items !== null && typeof decl.items === "object" ? decl.items : null;
|
|
65880
|
+
return items ? `ReadonlyArray<${inputDeclToTsType(items)}>` : "ReadonlyArray<unknown>";
|
|
65881
|
+
}
|
|
65882
|
+
case "json":
|
|
65883
|
+
return "unknown";
|
|
65884
|
+
default:
|
|
65885
|
+
return "unknown";
|
|
65886
|
+
}
|
|
65887
|
+
}
|
|
65888
|
+
function objectFieldsToType(fields) {
|
|
65889
|
+
const parts = [];
|
|
65890
|
+
for (const [key, decl] of Object.entries(fields)) {
|
|
65891
|
+
if (decl === null || typeof decl !== "object") continue;
|
|
65892
|
+
const d = decl;
|
|
65893
|
+
const optional2 = d.required === false ? "?" : "";
|
|
65894
|
+
const fieldKey = isValidIdentifier(key) ? key : JSON.stringify(key);
|
|
65895
|
+
parts.push(`${fieldKey}${optional2}: ${outputDeclToTsType(d)}`);
|
|
65896
|
+
}
|
|
65897
|
+
if (parts.length === 0) return "Record<string, never>";
|
|
65898
|
+
return `{ ${parts.join("; ")} }`;
|
|
65899
|
+
}
|
|
65900
|
+
function outputDeclToTsType(decl) {
|
|
65901
|
+
const type = decl.type;
|
|
65902
|
+
switch (type) {
|
|
65903
|
+
case "text":
|
|
65904
|
+
case "email":
|
|
65905
|
+
case "date":
|
|
65906
|
+
case "datetime":
|
|
65907
|
+
return "string";
|
|
65908
|
+
case "number":
|
|
65909
|
+
return "number";
|
|
65910
|
+
case "boolean":
|
|
65911
|
+
return "boolean";
|
|
65912
|
+
case "record_link":
|
|
65913
|
+
return decl.multi === true ? "ReadonlyArray<string>" : "string";
|
|
65914
|
+
case "select": {
|
|
65915
|
+
const options = Array.isArray(decl.options) ? decl.options : [];
|
|
65916
|
+
const literals = options.map(
|
|
65917
|
+
(o) => o !== null && typeof o === "object" && "value" in o && typeof o.value === "string" ? JSON.stringify(o.value) : null
|
|
65918
|
+
).filter((v) => v !== null);
|
|
65919
|
+
const inner = literals.length > 0 ? `${literals.join(" | ")} | (string & {})` : "string";
|
|
65920
|
+
return decl.multi === true ? `ReadonlyArray<${inner}>` : inner;
|
|
65921
|
+
}
|
|
65922
|
+
case "object": {
|
|
65923
|
+
const fields = decl.fields !== null && typeof decl.fields === "object" ? decl.fields : {};
|
|
65924
|
+
return objectFieldsToType(fields);
|
|
65925
|
+
}
|
|
65926
|
+
case "array": {
|
|
65927
|
+
const items = decl.items !== null && typeof decl.items === "object" ? decl.items : null;
|
|
65928
|
+
return items ? `ReadonlyArray<${outputDeclToTsType(items)}>` : "ReadonlyArray<unknown>";
|
|
65929
|
+
}
|
|
65930
|
+
case "json":
|
|
65931
|
+
return "unknown";
|
|
65932
|
+
default:
|
|
65933
|
+
return "unknown";
|
|
65934
|
+
}
|
|
65935
|
+
}
|
|
65936
|
+
var QUERIES_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
65937
|
+
// DO NOT EDIT \u2014 regenerated from package.json#lotics.queries.
|
|
65938
|
+
//
|
|
65939
|
+
// This file gives \`useQuery("alias", params)\` typed params at call sites by
|
|
65940
|
+
// augmenting the @lotics/app-sdk \`AppQueries\` interface.
|
|
65941
|
+
|
|
65942
|
+
import "@lotics/app-sdk";
|
|
65943
|
+
`;
|
|
65944
|
+
function generateAppQueriesDts(queries) {
|
|
65945
|
+
const entries2 = Object.entries(queries ?? {});
|
|
65946
|
+
if (entries2.length === 0) {
|
|
65947
|
+
return `${QUERIES_HEADER}
|
|
65948
|
+
// No queries declared in package.json#lotics.queries.
|
|
65949
|
+
// Add an entry to enable typed useQuery("alias", params) at call sites.
|
|
65950
|
+
declare module "@lotics/app-sdk" {
|
|
65951
|
+
interface AppQueries {}
|
|
65952
|
+
}
|
|
65953
|
+
`;
|
|
65954
|
+
}
|
|
65955
|
+
entries2.sort(([a], [b]) => a.localeCompare(b));
|
|
65956
|
+
const lines = [];
|
|
65957
|
+
const columnLines = [];
|
|
65958
|
+
for (const [alias, declaration] of entries2) {
|
|
65959
|
+
const valueType = inputsToType(declaration.params ?? {});
|
|
65960
|
+
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
65961
|
+
lines.push(` ${aliasKey}: ${valueType};`);
|
|
65962
|
+
const parsed = declaration.ast === void 0 ? void 0 : queryNodeSchema.safeParse(declaration.ast);
|
|
65963
|
+
if (parsed && !parsed.success) {
|
|
65964
|
+
columnLines.push(` // ${aliasKey}: query AST not readable by this CLI version \u2014 keys stay string`);
|
|
65965
|
+
continue;
|
|
65966
|
+
}
|
|
65967
|
+
const names = parsed?.success ? queryOutputNames(parsed.data) : void 0;
|
|
65968
|
+
if (names && names.length > 0) {
|
|
65969
|
+
columnLines.push(` ${aliasKey}: ${names.map((n) => JSON.stringify(n)).join(" | ")};`);
|
|
65970
|
+
}
|
|
65971
|
+
}
|
|
65972
|
+
return `${QUERIES_HEADER}
|
|
65973
|
+
declare module "@lotics/app-sdk" {
|
|
65974
|
+
interface AppQueries {
|
|
65975
|
+
${lines.join("\n")}
|
|
65976
|
+
}
|
|
65977
|
+
interface AppQueryColumns {
|
|
65978
|
+
${columnLines.join("\n")}
|
|
65979
|
+
}
|
|
65980
|
+
}
|
|
65981
|
+
`;
|
|
65982
|
+
}
|
|
65983
|
+
var WORKFLOWS_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
65984
|
+
// DO NOT EDIT \u2014 regenerated from package.json#lotics.workflows.
|
|
65985
|
+
//
|
|
65986
|
+
// This file gives \`useWorkflow("alias")\` a typed input parameter at call
|
|
65987
|
+
// sites by augmenting the @lotics/app-sdk \`AppWorkflows\` interface.
|
|
65988
|
+
|
|
65989
|
+
import "@lotics/app-sdk";
|
|
65990
|
+
`;
|
|
65991
|
+
function generateAppWorkflowsDts(workflows) {
|
|
65992
|
+
const entries2 = Object.entries(workflows ?? {});
|
|
65993
|
+
if (entries2.length === 0) {
|
|
65994
|
+
return `${WORKFLOWS_HEADER}
|
|
65995
|
+
// No workflows declared in package.json#lotics.workflows.
|
|
65996
|
+
// Add an entry to enable typed useWorkflow<"alias"> at call sites.
|
|
65997
|
+
declare module "@lotics/app-sdk" {
|
|
65998
|
+
interface AppWorkflows {}
|
|
65999
|
+
}
|
|
66000
|
+
`;
|
|
66001
|
+
}
|
|
66002
|
+
entries2.sort(([a], [b]) => a.localeCompare(b));
|
|
66003
|
+
const inputLines = [];
|
|
66004
|
+
const resultLines = [];
|
|
66005
|
+
for (const [alias, declaration] of entries2) {
|
|
66006
|
+
const valueType = declaration.inputs ? inputsToType(declaration.inputs, { nullableOptional: true }) : "Record<string, unknown>";
|
|
66007
|
+
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
66008
|
+
inputLines.push(` ${aliasKey}: ${valueType};`);
|
|
66009
|
+
if (declaration.outputs) {
|
|
66010
|
+
resultLines.push(` ${aliasKey}: ${objectFieldsToType(declaration.outputs)};`);
|
|
66011
|
+
}
|
|
66012
|
+
}
|
|
66013
|
+
const resultsBlock = resultLines.length > 0 ? `
|
|
66014
|
+
interface AppWorkflowResults {
|
|
66015
|
+
${resultLines.join("\n")}
|
|
66016
|
+
}` : "";
|
|
66017
|
+
return `${WORKFLOWS_HEADER}
|
|
66018
|
+
declare module "@lotics/app-sdk" {
|
|
66019
|
+
interface AppWorkflows {
|
|
66020
|
+
${inputLines.join("\n")}
|
|
66021
|
+
}${resultsBlock}
|
|
66022
|
+
}
|
|
66023
|
+
`;
|
|
66024
|
+
}
|
|
66025
|
+
var AGENTS_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
66026
|
+
// DO NOT EDIT \u2014 regenerated from package.json#lotics.agents.
|
|
66027
|
+
//
|
|
66028
|
+
// This file gives \`useAgentRun("alias")\` typed input + output at call sites by
|
|
66029
|
+
// augmenting the @lotics/app-sdk \`AppAgents\` / \`AppAgentResults\` interfaces.
|
|
66030
|
+
|
|
66031
|
+
import "@lotics/app-sdk";
|
|
66032
|
+
`;
|
|
66033
|
+
function generateAppAgentsDts(agents) {
|
|
66034
|
+
const entries2 = Object.entries(agents ?? {});
|
|
66035
|
+
if (entries2.length === 0) {
|
|
66036
|
+
return `${AGENTS_HEADER}
|
|
66037
|
+
// No agents declared in package.json#lotics.agents.
|
|
66038
|
+
// Add an entry to enable typed useAgentRun<"alias"> at call sites.
|
|
66039
|
+
declare module "@lotics/app-sdk" {
|
|
66040
|
+
interface AppAgents {}
|
|
66041
|
+
}
|
|
66042
|
+
`;
|
|
66043
|
+
}
|
|
66044
|
+
entries2.sort(([a], [b]) => a.localeCompare(b));
|
|
66045
|
+
const inputLines = [];
|
|
66046
|
+
const resultLines = [];
|
|
66047
|
+
for (const [alias, declaration] of entries2) {
|
|
66048
|
+
const valueType = declaration.inputs ? inputsToType(declaration.inputs) : "Record<string, unknown>";
|
|
66049
|
+
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
66050
|
+
inputLines.push(` ${aliasKey}: ${valueType};`);
|
|
66051
|
+
if (declaration.outputs) {
|
|
66052
|
+
resultLines.push(` ${aliasKey}: ${objectFieldsToType(declaration.outputs)};`);
|
|
66053
|
+
}
|
|
66054
|
+
}
|
|
66055
|
+
const resultsBlock = resultLines.length > 0 ? `
|
|
66056
|
+
interface AppAgentResults {
|
|
66057
|
+
${resultLines.join("\n")}
|
|
66058
|
+
}` : "";
|
|
66059
|
+
return `${AGENTS_HEADER}
|
|
66060
|
+
declare module "@lotics/app-sdk" {
|
|
66061
|
+
interface AppAgents {
|
|
66062
|
+
${inputLines.join("\n")}
|
|
66063
|
+
}${resultsBlock}
|
|
66064
|
+
}
|
|
66065
|
+
`;
|
|
66066
|
+
}
|
|
66067
|
+
var LINK_TSCONFIG_PATH = ".lotics/tsconfig.link.json";
|
|
66068
|
+
function generateLinkTsconfig(paths) {
|
|
66069
|
+
const header = Object.keys(paths).length > 0 ? `// GENERATED by \`lotics app codegen\` \u2014 do not edit.
|
|
66070
|
+
// LOTICS_UI_SRC is set, so @lotics/ui resolves to your working copy for tsc,
|
|
66071
|
+
// vitest, eslint and your editor \u2014 the same copy Vite is bundling. The peer
|
|
66072
|
+
// pins keep ONE react / react-native in the program; without them the kit's
|
|
66073
|
+
// source resolves its own copies and every shared type stops matching.
|
|
66074
|
+
// Unset LOTICS_UI_SRC and re-run to go back to the published kit.
|
|
66075
|
+
` : `// GENERATED by \`lotics app codegen\` \u2014 do not edit.
|
|
66076
|
+
// @lotics/ui resolves from node_modules as normal, so this is inert. It still
|
|
66077
|
+
// has to exist: tsconfig.json extends it, and a missing extends target fails
|
|
66078
|
+
// the build outright.
|
|
66079
|
+
`;
|
|
66080
|
+
return `${header}${JSON.stringify({ compilerOptions: { paths } }, null, 2)}
|
|
66081
|
+
`;
|
|
66082
|
+
}
|
|
66083
|
+
var CAPABILITY_GATED_CALLS = {
|
|
66084
|
+
comments: ["useComments", "createComment", "updateComment", "deleteComment"]
|
|
66085
|
+
};
|
|
66086
|
+
function undeclaredCapabilities(sourceText, declared) {
|
|
66087
|
+
const code = codeWithoutComments(sourceText);
|
|
66088
|
+
const used = [];
|
|
66089
|
+
for (const [capability, calls] of Object.entries(CAPABILITY_GATED_CALLS)) {
|
|
66090
|
+
const isCalled = calls.some((call) => new RegExp(`\\b${call}\\b`).test(code));
|
|
66091
|
+
if (isCalled && declared?.[capability] !== true) used.push(capability);
|
|
66092
|
+
}
|
|
66093
|
+
return used;
|
|
66094
|
+
}
|
|
66095
|
+
function driftedQueryAliases(a, b) {
|
|
66096
|
+
const left = a ?? {};
|
|
66097
|
+
const right = b ?? {};
|
|
66098
|
+
return [.../* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])].filter((alias) => canonicalJson(left[alias]) !== canonicalJson(right[alias])).sort();
|
|
66099
|
+
}
|
|
66100
|
+
function canonicalJson(value2) {
|
|
66101
|
+
const normalize = (v) => {
|
|
66102
|
+
if (Array.isArray(v)) return v.map(normalize);
|
|
66103
|
+
if (v === null || typeof v !== "object") return v;
|
|
66104
|
+
const entries2 = Object.entries(v).sort(
|
|
66105
|
+
([x2], [y]) => x2 < y ? -1 : x2 > y ? 1 : 0
|
|
66106
|
+
);
|
|
66107
|
+
return entries2.map(([key, val]) => [key, normalize(val)]);
|
|
66108
|
+
};
|
|
66109
|
+
return JSON.stringify(normalize(value2));
|
|
66110
|
+
}
|
|
66111
|
+
var REGEX_MAY_FOLLOW = /* @__PURE__ */ new Set([
|
|
66112
|
+
"return",
|
|
66113
|
+
"typeof",
|
|
66114
|
+
"case",
|
|
66115
|
+
"in",
|
|
66116
|
+
"of",
|
|
66117
|
+
"delete",
|
|
66118
|
+
"void",
|
|
66119
|
+
"instanceof",
|
|
66120
|
+
"new",
|
|
66121
|
+
"do",
|
|
66122
|
+
"else",
|
|
66123
|
+
"yield",
|
|
66124
|
+
"await",
|
|
66125
|
+
"throw"
|
|
66126
|
+
]);
|
|
66127
|
+
function opensRegex(out, at2) {
|
|
66128
|
+
let k = at2 - 1;
|
|
66129
|
+
while (k >= 0 && (out[k] === " " || out[k] === "\n" || out[k] === " " || out[k] === "\r")) k--;
|
|
66130
|
+
if (k < 0) return true;
|
|
66131
|
+
const prev = out[k];
|
|
66132
|
+
if ("=(,:[!&|?{;+-*%>~^".includes(prev)) return true;
|
|
66133
|
+
if (/[A-Za-z0-9_$]/.test(prev)) {
|
|
66134
|
+
let s = k;
|
|
66135
|
+
while (s >= 0 && /[A-Za-z0-9_$]/.test(out[s])) s--;
|
|
66136
|
+
return REGEX_MAY_FOLLOW.has(out.slice(s + 1, k + 1).join(""));
|
|
66137
|
+
}
|
|
66138
|
+
return false;
|
|
66139
|
+
}
|
|
66140
|
+
function codeWithoutComments(sourceText) {
|
|
66141
|
+
const out = sourceText.split("");
|
|
66142
|
+
const n = sourceText.length;
|
|
66143
|
+
const blank = (from, to) => {
|
|
66144
|
+
for (let k = from; k < to; k++) if (out[k] !== "\n") out[k] = " ";
|
|
66145
|
+
};
|
|
66146
|
+
let i2 = 0;
|
|
66147
|
+
while (i2 < n) {
|
|
66148
|
+
const c = sourceText[i2];
|
|
66149
|
+
const next = sourceText[i2 + 1];
|
|
66150
|
+
if (c === "/" && next === "/") {
|
|
66151
|
+
let j = i2;
|
|
66152
|
+
while (j < n && sourceText[j] !== "\n") j++;
|
|
66153
|
+
blank(i2, j);
|
|
66154
|
+
i2 = j;
|
|
66155
|
+
continue;
|
|
66156
|
+
}
|
|
66157
|
+
if (c === "/" && next === "*") {
|
|
66158
|
+
let j = i2 + 2;
|
|
66159
|
+
while (j < n && !(sourceText[j] === "*" && sourceText[j + 1] === "/")) j++;
|
|
66160
|
+
j = j < n ? j + 2 : n;
|
|
66161
|
+
blank(i2, j);
|
|
66162
|
+
i2 = j;
|
|
66163
|
+
continue;
|
|
66164
|
+
}
|
|
66165
|
+
if (c === '"' || c === "'") {
|
|
66166
|
+
let j = i2 + 1;
|
|
66167
|
+
while (j < n && sourceText[j] !== c && sourceText[j] !== "\n") {
|
|
66168
|
+
j += sourceText[j] === "\\" ? 2 : 1;
|
|
66169
|
+
}
|
|
66170
|
+
i2 = j < n && sourceText[j] === c ? j + 1 : j;
|
|
66171
|
+
continue;
|
|
66172
|
+
}
|
|
66173
|
+
if (c === "`") {
|
|
66174
|
+
let j = i2 + 1;
|
|
66175
|
+
while (j < n && sourceText[j] !== "`") {
|
|
66176
|
+
j += sourceText[j] === "\\" ? 2 : 1;
|
|
66177
|
+
}
|
|
66178
|
+
i2 = j < n ? j + 1 : n;
|
|
66179
|
+
continue;
|
|
66180
|
+
}
|
|
66181
|
+
if (c === "/" && opensRegex(out, i2)) {
|
|
66182
|
+
let j = i2 + 1;
|
|
66183
|
+
let inClass = false;
|
|
66184
|
+
while (j < n) {
|
|
66185
|
+
const ch = sourceText[j];
|
|
66186
|
+
if (ch === "\\") {
|
|
66187
|
+
j += 2;
|
|
66188
|
+
continue;
|
|
66189
|
+
}
|
|
66190
|
+
if (ch === "\n") break;
|
|
66191
|
+
if (ch === "[") inClass = true;
|
|
66192
|
+
else if (ch === "]") inClass = false;
|
|
66193
|
+
else if (ch === "/" && !inClass) {
|
|
66194
|
+
j++;
|
|
66195
|
+
break;
|
|
66196
|
+
}
|
|
66197
|
+
j++;
|
|
66198
|
+
}
|
|
66199
|
+
i2 = j;
|
|
66200
|
+
continue;
|
|
66201
|
+
}
|
|
66202
|
+
i2++;
|
|
66203
|
+
}
|
|
66204
|
+
return out.join("");
|
|
66205
|
+
}
|
|
66206
|
+
var ALIAS_CALL_HOOKS = {
|
|
66207
|
+
queries: ["useQuery", "usePaginatedQuery", "useInfiniteQuery", "useCount", "useFieldOptions"],
|
|
66208
|
+
workflows: ["useWorkflow"],
|
|
66209
|
+
agents: ["useAgentRun"]
|
|
66049
66210
|
};
|
|
66050
|
-
|
|
66051
|
-
|
|
66052
|
-
|
|
66053
|
-
|
|
66054
|
-
|
|
66055
|
-
|
|
66056
|
-
|
|
66057
|
-
|
|
66058
|
-
|
|
66059
|
-
|
|
66211
|
+
var LITERAL_ALIAS_ARG = `["'\`]([A-Za-z_$][A-Za-z0-9_$]*)["'\`]`;
|
|
66212
|
+
function isAppSourcePath(projectRelativePath) {
|
|
66213
|
+
const normalized = projectRelativePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
66214
|
+
return normalized.startsWith("src/") && /\.(ts|tsx|js|jsx)$/.test(normalized);
|
|
66215
|
+
}
|
|
66216
|
+
function calledAppAliases(sourceText) {
|
|
66217
|
+
const code = codeWithoutComments(sourceText);
|
|
66218
|
+
const out = {
|
|
66219
|
+
queries: [],
|
|
66220
|
+
workflows: [],
|
|
66221
|
+
agents: [],
|
|
66222
|
+
dynamic: []
|
|
66223
|
+
};
|
|
66224
|
+
for (const [kind, hooks] of Object.entries(ALIAS_CALL_HOOKS)) {
|
|
66225
|
+
const seen = /* @__PURE__ */ new Set();
|
|
66226
|
+
for (const hook of hooks) {
|
|
66227
|
+
let isDynamic = false;
|
|
66228
|
+
for (const call of code.matchAll(new RegExp(`\\b${hook}\\s*\\(`, "g"))) {
|
|
66229
|
+
const rest2 = code.slice(call.index + call[0].length);
|
|
66230
|
+
const literal2 = new RegExp(`^\\s*${LITERAL_ALIAS_ARG}`).exec(rest2);
|
|
66231
|
+
if (literal2) seen.add(literal2[1]);
|
|
66232
|
+
else isDynamic = true;
|
|
66233
|
+
}
|
|
66234
|
+
if (isDynamic) out.dynamic.push(hook);
|
|
66060
66235
|
}
|
|
66236
|
+
out[kind] = [...seen];
|
|
66237
|
+
}
|
|
66238
|
+
return out;
|
|
66239
|
+
}
|
|
66240
|
+
function orphanedAliases(bound, called) {
|
|
66241
|
+
return unboundAliases(bound, called);
|
|
66242
|
+
}
|
|
66243
|
+
function unboundAliases(called, bound) {
|
|
66244
|
+
const missing = (from, against) => {
|
|
66245
|
+
const have = new Set(against ?? []);
|
|
66246
|
+
return [...from ?? []].filter((alias) => !have.has(alias));
|
|
66247
|
+
};
|
|
66248
|
+
return {
|
|
66249
|
+
queries: missing(called.queries, bound.queries),
|
|
66250
|
+
workflows: missing(called.workflows, bound.workflows),
|
|
66251
|
+
agents: missing(called.agents, bound.agents)
|
|
66061
66252
|
};
|
|
66062
66253
|
}
|
|
66063
|
-
|
|
66064
|
-
|
|
66065
|
-
|
|
66066
|
-
|
|
66067
|
-
|
|
66068
|
-
|
|
66069
|
-
|
|
66070
|
-
|
|
66071
|
-
|
|
66072
|
-
|
|
66073
|
-
|
|
66074
|
-
|
|
66075
|
-
|
|
66076
|
-
)
|
|
66077
|
-
|
|
66078
|
-
|
|
66079
|
-
|
|
66080
|
-
|
|
66081
|
-
|
|
66082
|
-
|
|
66083
|
-
|
|
66084
|
-
|
|
66085
|
-
|
|
66086
|
-
|
|
66087
|
-
|
|
66088
|
-
|
|
66089
|
-
|
|
66090
|
-
|
|
66091
|
-
|
|
66092
|
-
|
|
66093
|
-
|
|
66094
|
-
});
|
|
66095
|
-
|
|
66096
|
-
|
|
66097
|
-
|
|
66098
|
-
}
|
|
66099
|
-
|
|
66100
|
-
|
|
66101
|
-
|
|
66102
|
-
|
|
66103
|
-
|
|
66104
|
-
|
|
66105
|
-
|
|
66106
|
-
|
|
66107
|
-
|
|
66108
|
-
|
|
66109
|
-
|
|
66110
|
-
|
|
66111
|
-
|
|
66112
|
-
|
|
66113
|
-
|
|
66114
|
-
|
|
66115
|
-
|
|
66254
|
+
|
|
66255
|
+
// ../shared/src/generate_app_fields.ts
|
|
66256
|
+
var HEADER = `// Auto-generated by 'lotics app codegen' and 'lotics app pull'.
|
|
66257
|
+
// DO NOT EDIT \u2014 regenerated from the workspace schema.
|
|
66258
|
+
//
|
|
66259
|
+
// Runtime field + option ids addressed by stable display-name aliases:
|
|
66260
|
+
// record.data[F.<TABLE>.<field>] \u2192 "fld_\u2026"
|
|
66261
|
+
// value === OPT.<TABLE>.<field>.<option> \u2192 "opt_\u2026"
|
|
66262
|
+
// A rename on the platform re-runs codegen and moves these in lockstep.
|
|
66263
|
+
`;
|
|
66264
|
+
function slugifyAlias(name2, upper2) {
|
|
66265
|
+
const stripped = name2.normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/đ/g, "d").replace(/Đ/g, "D");
|
|
66266
|
+
const cased = upper2 ? stripped.toUpperCase() : stripped.toLowerCase();
|
|
66267
|
+
const slug = cased.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
66268
|
+
if (slug === "") return "_";
|
|
66269
|
+
return /^[0-9]/.test(slug) ? `_${slug}` : slug;
|
|
66270
|
+
}
|
|
66271
|
+
function dedupeAliases(names, upper2) {
|
|
66272
|
+
const used = /* @__PURE__ */ new Map();
|
|
66273
|
+
return names.map((name2) => {
|
|
66274
|
+
const base = slugifyAlias(name2, upper2);
|
|
66275
|
+
const seen = used.get(base);
|
|
66276
|
+
if (seen === void 0) {
|
|
66277
|
+
used.set(base, 1);
|
|
66278
|
+
return base;
|
|
66279
|
+
}
|
|
66280
|
+
let n = seen + 1;
|
|
66281
|
+
while (used.has(`${base}_${n}`)) n++;
|
|
66282
|
+
used.set(base, n);
|
|
66283
|
+
used.set(`${base}_${n}`, 1);
|
|
66284
|
+
return `${base}_${n}`;
|
|
66285
|
+
});
|
|
66286
|
+
}
|
|
66287
|
+
function propKey(alias) {
|
|
66288
|
+
return isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
66289
|
+
}
|
|
66290
|
+
function aliasTables(tables) {
|
|
66291
|
+
const tableAliases = dedupeAliases(
|
|
66292
|
+
tables.map((t) => t.name),
|
|
66293
|
+
true
|
|
66294
|
+
);
|
|
66295
|
+
return tables.map((table, i2) => {
|
|
66296
|
+
const fieldAliases = dedupeAliases(
|
|
66297
|
+
table.fields.map((f) => f.name),
|
|
66298
|
+
false
|
|
66299
|
+
);
|
|
66300
|
+
return {
|
|
66301
|
+
alias: tableAliases[i2],
|
|
66302
|
+
table,
|
|
66303
|
+
fields: table.fields.map((field, j) => ({ alias: fieldAliases[j], field }))
|
|
66304
|
+
};
|
|
66305
|
+
});
|
|
66306
|
+
}
|
|
66307
|
+
function emitFieldMap(aliased) {
|
|
66308
|
+
const tableBlocks = aliased.map(({ alias, fields }) => {
|
|
66309
|
+
const fieldLines = fields.map(
|
|
66310
|
+
({ alias: fieldAlias, field }) => ` ${propKey(fieldAlias)}: ${JSON.stringify(field.id)},`
|
|
66311
|
+
);
|
|
66312
|
+
return ` ${propKey(alias)}: {
|
|
66313
|
+
${fieldLines.join("\n")}
|
|
66314
|
+
},`;
|
|
66315
|
+
});
|
|
66316
|
+
return `export const F = {
|
|
66317
|
+
${tableBlocks.join("\n")}
|
|
66318
|
+
} as const;`;
|
|
66319
|
+
}
|
|
66320
|
+
function emitOptionMap(aliased) {
|
|
66321
|
+
const tableBlocks = [];
|
|
66322
|
+
for (const { alias, fields } of aliased) {
|
|
66323
|
+
const fieldBlocks = [];
|
|
66324
|
+
for (const { alias: fieldAlias, field } of fields) {
|
|
66325
|
+
const options = field.options ?? [];
|
|
66326
|
+
if (options.length === 0) continue;
|
|
66327
|
+
const optionAliases = dedupeAliases(
|
|
66328
|
+
options.map((o) => o.label),
|
|
66329
|
+
false
|
|
66330
|
+
);
|
|
66331
|
+
const optionLines = options.map(
|
|
66332
|
+
(option, i2) => ` ${propKey(optionAliases[i2])}: ${JSON.stringify(option.id)},`
|
|
66333
|
+
);
|
|
66334
|
+
fieldBlocks.push(` ${propKey(fieldAlias)}: {
|
|
66335
|
+
${optionLines.join("\n")}
|
|
66336
|
+
},`);
|
|
66337
|
+
}
|
|
66338
|
+
if (fieldBlocks.length === 0) continue;
|
|
66339
|
+
tableBlocks.push(` ${propKey(alias)}: {
|
|
66340
|
+
${fieldBlocks.join("\n")}
|
|
66341
|
+
},`);
|
|
66342
|
+
}
|
|
66343
|
+
if (tableBlocks.length === 0) return `export const OPT = {} as const;`;
|
|
66344
|
+
return `export const OPT = {
|
|
66345
|
+
${tableBlocks.join("\n")}
|
|
66346
|
+
} as const;`;
|
|
66347
|
+
}
|
|
66348
|
+
function generateAppFields(tables) {
|
|
66349
|
+
if (tables.length === 0) {
|
|
66350
|
+
return `${HEADER}
|
|
66351
|
+
export const F = {} as const;
|
|
66352
|
+
|
|
66353
|
+
export const OPT = {} as const;
|
|
66354
|
+
|
|
66355
|
+
/** Field-id alias map (empty \u2014 no tables in scope). */
|
|
66356
|
+
export type AppFields = typeof F;
|
|
66357
|
+
/** Select-option alias map (empty \u2014 no tables in scope). */
|
|
66358
|
+
export type AppOptions = typeof OPT;
|
|
66359
|
+
`;
|
|
66360
|
+
}
|
|
66361
|
+
const aliased = aliasTables(tables);
|
|
66362
|
+
return `${HEADER}
|
|
66363
|
+
${emitFieldMap(aliased)}
|
|
66364
|
+
|
|
66365
|
+
${emitOptionMap(aliased)}
|
|
66366
|
+
|
|
66367
|
+
/** Field-id alias map: \`F[<TABLE>][<field>]\` is the \`fld_\u2026\` id (literal-typed). */
|
|
66368
|
+
export type AppFields = typeof F;
|
|
66369
|
+
/** Select-option alias map: \`OPT[<TABLE>][<field>][<option>]\` is the \`opt_\u2026\` id. */
|
|
66370
|
+
export type AppOptions = typeof OPT;
|
|
66371
|
+
`;
|
|
66372
|
+
}
|
|
66373
|
+
function codegenTableIds(queries, allowlist) {
|
|
66374
|
+
const ids = new Set(allowlist);
|
|
66375
|
+
for (const declaration of Object.values(queries)) {
|
|
66376
|
+
for (const id of collectQueryTableIds(declaration.ast)) ids.add(id);
|
|
66377
|
+
}
|
|
66378
|
+
return [...ids];
|
|
66379
|
+
}
|
|
66380
|
+
function readCodegenTablesAllowlist(pkg) {
|
|
66381
|
+
const tables = pkg?.lotics?.codegen?.tables;
|
|
66382
|
+
return Array.isArray(tables) ? tables.filter((t) => typeof t === "string") : [];
|
|
66383
|
+
}
|
|
66384
|
+
|
|
66385
|
+
// src/app_workflow_check.ts
|
|
66386
|
+
import fs7 from "node:fs";
|
|
66387
|
+
import path8 from "node:path";
|
|
66388
|
+
import { createRequire } from "node:module";
|
|
66389
|
+
|
|
66390
|
+
// ../shared/src/parse_workflow_js.ts
|
|
66391
|
+
var import_parser = __toESM(require_lib(), 1);
|
|
66392
|
+
|
|
66393
|
+
// ../shared/src/schemas/workflow_expressions.ts
|
|
66394
|
+
var runtimeKeySchema = zod_default.enum([
|
|
66395
|
+
"timezone",
|
|
66396
|
+
"workflow_id",
|
|
66397
|
+
"execution_id",
|
|
66398
|
+
"workspace_id",
|
|
66399
|
+
"organization_id",
|
|
66400
|
+
"now",
|
|
66401
|
+
"change_origin",
|
|
66402
|
+
// PARKED — accepted in stored ASTs, rejected for new saves at parse (see
|
|
66403
|
+
// `PARKED_RUNTIME_KEYS` in walk_workflow_expression.ts). It is the OWNER's
|
|
66404
|
+
// principal (a workflow runs under owner authority), so it can't answer the
|
|
66405
|
+
// caller-authorization question anyone reads it for; the generated `.d.ts`
|
|
66406
|
+
// omits it and the docs point at `current_member_in_any_group` /
|
|
66407
|
+
// `runtime.triggered_by_member_id` instead. The entry stays so any stored
|
|
66408
|
+
// AST keeps validating and executing — drop it only once a prod probe shows
|
|
66409
|
+
// zero references (`workflows.steps_v2::text LIKE '%execution_principal%'`).
|
|
66410
|
+
"execution_principal",
|
|
66411
|
+
"triggered_by_member_id"
|
|
66412
|
+
]);
|
|
66413
|
+
var readSourceSchema = zod_default.discriminatedUnion("from", [
|
|
66414
|
+
zod_default.object({ from: zod_default.literal("trigger") }),
|
|
66415
|
+
zod_default.object({ from: zod_default.literal("trigger_record") }),
|
|
66416
|
+
zod_default.object({ from: zod_default.literal("trigger_record_prev") }),
|
|
66417
|
+
zod_default.object({ from: zod_default.literal("trigger_changes") }),
|
|
66418
|
+
// `name` is the loop's bind name, and it is OPTIONAL for one reason: every
|
|
66419
|
+
// body stored before names existed emits the bare form, and those resolve to
|
|
66420
|
+
// the innermost frame — today's behaviour, and correct for any loop that is
|
|
66421
|
+
// not nested. Without a name a read inside a NESTED loop cannot say which
|
|
66422
|
+
// loop it means, so both binds resolve to the inner item and a join between
|
|
66423
|
+
// two collections silently matches nothing. The parser emits the name now, so
|
|
66424
|
+
// a body gets correct nesting the first time it is saved through it.
|
|
66425
|
+
zod_default.object({ from: zod_default.literal("foreach_item"), name: zod_default.string().min(1).optional() }),
|
|
66426
|
+
// No `name` here, deliberately: the JS surface spells the index as one
|
|
66427
|
+
// reserved `index` keyword with no per-loop form, so the innermost loop is
|
|
66428
|
+
// the only thing a read can mean. A name would be representable, honoured at
|
|
66429
|
+
// run time, and silently rewritten to the innermost by the renderer — which
|
|
66430
|
+
// prints every index as `index` — reintroducing the corruption above for a
|
|
66431
|
+
// case nothing can author.
|
|
66432
|
+
zod_default.object({ from: zod_default.literal("foreach_index") }),
|
|
66433
|
+
zod_default.object({
|
|
66434
|
+
from: zod_default.literal("step_output"),
|
|
66435
|
+
step_id: zod_default.string().min(1)
|
|
66436
|
+
}),
|
|
66437
|
+
zod_default.object({
|
|
66438
|
+
from: zod_default.literal("runtime"),
|
|
66439
|
+
key: runtimeKeySchema
|
|
66440
|
+
}),
|
|
66441
|
+
// Lambda parameter — names a positional parameter on the innermost
|
|
66442
|
+
// enclosing `lambda` expression. The walker emits this only inside
|
|
66443
|
+
// higher-order helper callbacks (`filter(arr, x => x.Status == "open")`).
|
|
66444
|
+
// The evaluator pushes a `lambda_params` frame each time it invokes a
|
|
66445
|
+
// lambda, popping it after the body finishes. Outside a lambda body,
|
|
66446
|
+
// these reads have no meaning and fail loudly.
|
|
66447
|
+
zod_default.object({
|
|
66448
|
+
from: zod_default.literal("lambda_param"),
|
|
66449
|
+
name: zod_default.string().min(1)
|
|
66450
|
+
}),
|
|
66451
|
+
// Lexical (`let`) binding — names a block-scoped mutable variable
|
|
66452
|
+
// declared by `let_declare` or assigned by `assign` somewhere in an
|
|
66453
|
+
// enclosing block. The walker registers names on a per-block stack
|
|
66454
|
+
// and emits this read source when a bare identifier matches. The
|
|
66455
|
+
// evaluator maintains the matching frame stack on
|
|
66456
|
+
// `WorkflowEvalContext.lexical_bindings`; reading walks it
|
|
66457
|
+
// innermost-outward.
|
|
66458
|
+
zod_default.object({
|
|
66459
|
+
from: zod_default.literal("lexical"),
|
|
66460
|
+
name: zod_default.string().min(1)
|
|
66461
|
+
})
|
|
66462
|
+
]);
|
|
66463
|
+
var indexExpressionSchema = zod_default.lazy(
|
|
66464
|
+
() => workflowExpressionSchema
|
|
66116
66465
|
);
|
|
66117
|
-
var
|
|
66118
|
-
|
|
66119
|
-
|
|
66120
|
-
|
|
66121
|
-
|
|
66122
|
-
|
|
66123
|
-
|
|
66124
|
-
|
|
66125
|
-
|
|
66126
|
-
|
|
66127
|
-
|
|
66128
|
-
|
|
66129
|
-
|
|
66130
|
-
|
|
66131
|
-
|
|
66132
|
-
|
|
66133
|
-
|
|
66134
|
-
|
|
66135
|
-
|
|
66466
|
+
var pathSegmentSchema = zod_default.discriminatedUnion("at", [
|
|
66467
|
+
zod_default.object({ at: zod_default.literal("key"), key: zod_default.string().min(1) }),
|
|
66468
|
+
zod_default.object({
|
|
66469
|
+
at: zod_default.literal("index"),
|
|
66470
|
+
/**
|
|
66471
|
+
* Numeric literal indices stay as `number`; computed indices (e.g.
|
|
66472
|
+
* `arr[i]` where `i` is a lambda param or `let` binding) carry a
|
|
66473
|
+
* WorkflowExpression that the evaluator resolves at runtime. Authors
|
|
66474
|
+
* who write `arr[<expr>]` get a working iteration pattern over arrays
|
|
66475
|
+
* without forcing the parser to pre-evaluate the index.
|
|
66476
|
+
*/
|
|
66477
|
+
index: zod_default.union([zod_default.number().int().nonnegative(), indexExpressionSchema])
|
|
66478
|
+
}),
|
|
66479
|
+
zod_default.object({ at: zod_default.literal("field"), key: zod_default.string().min(1) }),
|
|
66480
|
+
zod_default.object({
|
|
66481
|
+
at: zod_default.literal("linked"),
|
|
66482
|
+
via: zod_default.string().min(1),
|
|
66483
|
+
/**
|
|
66484
|
+
* `number` — pick a single linked record by literal index.
|
|
66485
|
+
* `"each"` — fan out; legal only inside foreach.items (validator-enforced).
|
|
66486
|
+
* `WorkflowExpression` — computed index, resolved at runtime to pick a
|
|
66487
|
+
* single linked record (same descent semantics as the numeric form).
|
|
66488
|
+
*/
|
|
66489
|
+
index: zod_default.union([
|
|
66490
|
+
zod_default.number().int().nonnegative(),
|
|
66491
|
+
zod_default.literal("each"),
|
|
66492
|
+
indexExpressionSchema
|
|
66493
|
+
])
|
|
66494
|
+
})
|
|
66495
|
+
]);
|
|
66496
|
+
var binaryOpSchema = zod_default.enum([
|
|
66497
|
+
"eq",
|
|
66498
|
+
"neq",
|
|
66499
|
+
"seq",
|
|
66500
|
+
"sneq",
|
|
66501
|
+
"gt",
|
|
66502
|
+
"lt",
|
|
66503
|
+
"gte",
|
|
66504
|
+
"lte",
|
|
66505
|
+
"and",
|
|
66506
|
+
"or",
|
|
66507
|
+
"add",
|
|
66508
|
+
"sub",
|
|
66509
|
+
"mul",
|
|
66510
|
+
"div",
|
|
66511
|
+
"mod"
|
|
66512
|
+
]);
|
|
66513
|
+
var unaryOpSchema = zod_default.enum(["not", "neg"]);
|
|
66514
|
+
var coerceSchema = zod_default.enum(["raw", "display"]);
|
|
66515
|
+
var literalValueSchema2 = zod_default.union([
|
|
66516
|
+
zod_default.string(),
|
|
66517
|
+
zod_default.number(),
|
|
66518
|
+
zod_default.boolean(),
|
|
66519
|
+
zod_default.null()
|
|
66520
|
+
]);
|
|
66521
|
+
var workflowExpressionSchema = zod_default.lazy(
|
|
66522
|
+
() => zod_default.discriminatedUnion("kind", [
|
|
66523
|
+
zod_default.object({ kind: zod_default.literal("lit"), value: literalValueSchema2 }),
|
|
66524
|
+
zod_default.object({
|
|
66525
|
+
kind: zod_default.literal("read"),
|
|
66526
|
+
source: readSourceSchema,
|
|
66527
|
+
path: zod_default.array(pathSegmentSchema),
|
|
66528
|
+
coerce: coerceSchema.optional()
|
|
66529
|
+
}),
|
|
66530
|
+
zod_default.object({
|
|
66531
|
+
kind: zod_default.literal("call"),
|
|
66532
|
+
fn: zod_default.string().min(1),
|
|
66533
|
+
args: zod_default.array(workflowExpressionSchema)
|
|
66534
|
+
}),
|
|
66535
|
+
zod_default.object({
|
|
66536
|
+
kind: zod_default.literal("binary"),
|
|
66537
|
+
op: binaryOpSchema,
|
|
66538
|
+
left: workflowExpressionSchema,
|
|
66539
|
+
right: workflowExpressionSchema
|
|
66136
66540
|
}),
|
|
66137
|
-
|
|
66138
|
-
|
|
66139
|
-
|
|
66140
|
-
|
|
66141
|
-
appWorkflowOutputBaseSchema.extend({
|
|
66142
|
-
type: zod_default.literal("select"),
|
|
66143
|
-
...selectOptionSourceShape
|
|
66144
|
-
}).check(checkExactlyOneOptionSource("output")),
|
|
66145
|
-
appWorkflowOutputBaseSchema.extend({
|
|
66146
|
-
type: zod_default.literal("object"),
|
|
66147
|
-
fields: zod_default.record(zod_default.string(), appWorkflowOutputSchema)
|
|
66541
|
+
zod_default.object({
|
|
66542
|
+
kind: zod_default.literal("unary"),
|
|
66543
|
+
op: unaryOpSchema,
|
|
66544
|
+
arg: workflowExpressionSchema
|
|
66148
66545
|
}),
|
|
66149
|
-
|
|
66150
|
-
|
|
66151
|
-
|
|
66546
|
+
zod_default.object({
|
|
66547
|
+
kind: zod_default.literal("ternary"),
|
|
66548
|
+
cond: workflowExpressionSchema,
|
|
66549
|
+
then: workflowExpressionSchema,
|
|
66550
|
+
else: workflowExpressionSchema
|
|
66551
|
+
}),
|
|
66552
|
+
zod_default.object({
|
|
66553
|
+
kind: zod_default.literal("template"),
|
|
66554
|
+
parts: zod_default.array(templatePartSchema)
|
|
66555
|
+
}),
|
|
66556
|
+
zod_default.object({
|
|
66557
|
+
kind: zod_default.literal("lambda"),
|
|
66558
|
+
params: zod_default.array(zod_default.string().min(1)),
|
|
66559
|
+
body: workflowExpressionSchema
|
|
66560
|
+
}),
|
|
66561
|
+
zod_default.object({
|
|
66562
|
+
kind: zod_default.literal("array_literal"),
|
|
66563
|
+
elements: zod_default.array(workflowExpressionSchema)
|
|
66564
|
+
}),
|
|
66565
|
+
zod_default.object({
|
|
66566
|
+
kind: zod_default.literal("object_literal"),
|
|
66567
|
+
entries: zod_default.array(
|
|
66568
|
+
zod_default.object({
|
|
66569
|
+
key: zod_default.string().min(1),
|
|
66570
|
+
value: workflowExpressionSchema
|
|
66571
|
+
})
|
|
66572
|
+
)
|
|
66152
66573
|
})
|
|
66153
66574
|
])
|
|
66154
66575
|
);
|
|
66155
|
-
|
|
66156
|
-
|
|
66157
|
-
|
|
66158
|
-
|
|
66159
|
-
|
|
66160
|
-
|
|
66161
|
-
return 1;
|
|
66162
|
-
}
|
|
66163
|
-
var appWorkflowDeclarationSchema = zod_default.object({
|
|
66164
|
-
workflow_id: zod_default.string().describe("ID of the workflow this alias resolves to"),
|
|
66165
|
-
inputs: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe(
|
|
66166
|
-
"Typed input schema for the workflow alias. Keys are input names; values declare type + constraints. The server validates payloads against this schema before invoking the workflow; CLI codegen emits typed `useWorkflow<alias>` signatures for the app side. Omit `inputs` for workflows that accept no inputs or whose shape isn't worth declaring."
|
|
66167
|
-
),
|
|
66168
|
-
outputs: zod_default.record(zod_default.string(), appWorkflowOutputSchema).optional().describe(
|
|
66169
|
-
"Typed output schema for the data the workflow returns via `return({ data })`. Keys are field names; values declare type + (nested object/array) shape. The server validates the returned data against this schema at the app boundary and the workflow won't save unless its `return({ data })` matches; CLI codegen types `result.data`. Omit when the workflow returns no data, or pass it through untyped."
|
|
66170
|
-
).refine(
|
|
66171
|
-
(outputs) => outputs === void 0 || Object.values(outputs).every((o) => appWorkflowOutputDepth(o) <= MAX_APP_WORKFLOW_OUTPUT_DEPTH),
|
|
66172
|
-
{ message: `output schema nesting exceeds the max depth of ${MAX_APP_WORKFLOW_OUTPUT_DEPTH}` }
|
|
66173
|
-
),
|
|
66174
|
-
description: zod_default.string().optional().describe(
|
|
66175
|
-
"What this workflow does, in one line \u2014 read by an agent choosing between the app's aliases, the same job a query's `description` does. `lotics app workflow set` sends it, so it lives beside the body in version control; omitted, the workflow keeps the description already on it."
|
|
66176
|
-
),
|
|
66177
|
-
body_sha: zod_default.string().optional().describe(
|
|
66178
|
-
"Fingerprint of the body currently bound to this alias, written by the server on every accepted `set_app_workflow`. Never sent by a caller \u2014 it is the value a caller's `expected_body_sha` is checked against, so that a push built on a stale copy of the body is refused instead of silently overwriting whatever replaced it. Absent on a binding last written before the field existed, where no comparison is possible."
|
|
66179
|
-
)
|
|
66180
|
-
});
|
|
66181
|
-
var appWorkflowContractSchema = zod_default.object({
|
|
66182
|
-
inputs: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional(),
|
|
66183
|
-
outputs: zod_default.record(zod_default.string(), appWorkflowOutputSchema).optional()
|
|
66184
|
-
});
|
|
66185
|
-
var MAX_APP_CAPABILITY_DESCRIPTION = 300;
|
|
66186
|
-
var appQueryDeclarationSchema = zod_default.object({
|
|
66187
|
-
ast: zod_default.unknown().describe(
|
|
66188
|
-
"Query AST template (a QueryNode). Validated server-side via parseQueryNode at deploy. May embed {{params.<name>}} tokens in filter value positions."
|
|
66189
|
-
),
|
|
66190
|
-
params: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe(
|
|
66191
|
-
"Typed param schema. Keys are param names referenced as {{params.<name>}} in the ast; values declare type + constraints. The server validates the caller's params payload against this before interpolating. Omit for queries that take no params."
|
|
66192
|
-
),
|
|
66193
|
-
description: zod_default.string().optional().describe(
|
|
66194
|
-
`What this query returns, in one line \u2014 read by an agent choosing between the app's aliases. An alias is a JS identifier, which names a query without saying what it covers. Capped at ${MAX_APP_CAPABILITY_DESCRIPTION} characters.`
|
|
66195
|
-
)
|
|
66196
|
-
});
|
|
66197
|
-
var appAgentDeclarationSchema = zod_default.object({
|
|
66198
|
-
instructions: zod_default.string().min(1).describe("System instructions for the agent \u2014 the task it performs per run."),
|
|
66199
|
-
tool_names: zod_default.array(zod_default.string().min(1)).describe(
|
|
66200
|
-
"Tools the agent may call, resolved against the shared registry minus the automation blacklist. The capability boundary \u2014 the run can use nothing else. May be empty for a pure-reasoning agent."
|
|
66201
|
-
),
|
|
66202
|
-
knowledge_doc_ids: zod_default.array(zod_default.string().min(1)).optional().describe(
|
|
66203
|
-
"Knowledge docs the agent may read, validated at declare time against the app owner's `use` access. Small docs are inlined into the agent's system prompt each run; a doc too large to inline requires the code tools (code_exec) in tool_names and is read by staging it into a code run. Omit for an agent that needs no knowledge."
|
|
66204
|
-
),
|
|
66205
|
-
query_aliases: zod_default.array(zod_default.string().min(1)).optional().describe(
|
|
66206
|
-
"Named queries from this app's manifest the agent may run via `run_app_query`, validated at declare time against the app's own queries. This is the agent's ENTIRE read surface over workspace data \u2014 a template fixes the tables, filters, and projection, so it bounds rows and columns, not just tables. Omit for an agent that reads no records."
|
|
66207
|
-
),
|
|
66208
|
-
workflow_aliases: zod_default.array(zod_default.string().min(1)).optional().describe(
|
|
66209
|
-
"Workflows from this app's manifest the agent may invoke via `run_app_workflow`, validated at declare time against the app's own workflows. This is the agent's ENTIRE write surface \u2014 the same declared mutation path the app's UI uses, so table hooks and side-effect harvesting apply. Omit for a read-only agent."
|
|
66210
|
-
),
|
|
66211
|
-
model_tier: zod_default.enum(MODEL_TIERS).optional().describe(
|
|
66212
|
-
"Model tier the agent runs on \u2014 `haiku`, `sonnet`, or `opus`. Omit to follow the platform default tier, resolved at run time: the preferred choice. A tier names capability, not a version, so the generation behind it moves with the platform and this declaration never needs a rewrite. Pin only a deliberate, tested choice."
|
|
66213
|
-
),
|
|
66214
|
-
effort_level: zod_default.enum(EFFORT_LEVELS).optional().describe(
|
|
66215
|
-
"Reasoning depth for adaptive-thinking tiers \u2014 one of the chosen tier's supported levels (validated against model_tier at declare time). Omit to use the model default; ignored on tiers without adaptive thinking."
|
|
66216
|
-
),
|
|
66217
|
-
prefix_cache_ttl: zod_default.enum(PREFIX_CACHE_TTLS).optional().describe(
|
|
66218
|
-
`How long this agent's prompt-cache prefix (tools + system block) is kept warm. Omit \u2014 the default (5m, Anthropic's own) is right for essentially every agent. "1h" doubles the write price (2x the input rate against 1.25x) to buy only the 5m..1h band, and an entry nothing re-reads inside the hour is paid for twice over; declining it still leaves the prefix cached at the default. Set it only from measured cadence, never a guess.`
|
|
66219
|
-
),
|
|
66220
|
-
inputs: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe(
|
|
66221
|
-
"Typed input schema for one run. Keys are input names; values declare type + constraints. The server validates the run payload against this before invoking; CLI codegen emits a typed `useAgentRun<alias>` signature. Omit for an untyped payload."
|
|
66222
|
-
),
|
|
66223
|
-
outputs: zod_default.record(zod_default.string(), appWorkflowOutputSchema).optional().describe(
|
|
66224
|
-
"Typed output schema for the structured result the agent emits. Keys are field names; values declare type + (nested object/array) shape. When declared, the run must emit a result matching it \u2014 the server validates before persisting and the SDK types `run.output`. Omit for a free-text run whose output is the final message."
|
|
66225
|
-
).refine(
|
|
66226
|
-
(outputs) => outputs === void 0 || Object.values(outputs).every((o) => appWorkflowOutputDepth(o) <= MAX_APP_WORKFLOW_OUTPUT_DEPTH),
|
|
66227
|
-
{ message: `output schema nesting exceeds the max depth of ${MAX_APP_WORKFLOW_OUTPUT_DEPTH}` }
|
|
66228
|
-
)
|
|
66229
|
-
});
|
|
66230
|
-
var appThemeSchema = zod_default.object({
|
|
66231
|
-
color: optionColorSchema.nullable().optional().describe("Theme color for the app")
|
|
66232
|
-
});
|
|
66233
|
-
var appCapabilitiesSchema = zod_default.object({
|
|
66234
|
-
comments: zod_default.boolean().optional().describe(
|
|
66235
|
-
"Enable the members-only `useComments` primitive. When true, the app may read/write record comments \u2014 each operation under the VIEWING member's own table access, row-scope, and author identity (never the app owner's). Default off."
|
|
66236
|
-
)
|
|
66237
|
-
});
|
|
66238
|
-
var appSchema = zod_default.object({
|
|
66239
|
-
id: zod_default.string().describe("Unique identifier for the app"),
|
|
66240
|
-
name: zod_default.string().describe("Display name of the app"),
|
|
66241
|
-
description: zod_default.string().nullable().optional().describe("Optional description of the app's purpose"),
|
|
66242
|
-
icon: zod_default.string().nullable().optional().describe("Icon name for the app (e.g., 'home', 'chart-bar')"),
|
|
66243
|
-
workspace_id: zod_default.string().describe("ID of the workspace this app belongs to"),
|
|
66244
|
-
current_version_id: zod_default.string().nullable().optional().describe(
|
|
66245
|
-
"Pointer to the currently-published app_versions row in R2. Set once the app has been deployed at least once via `lotics app deploy`; null before the first deploy."
|
|
66246
|
-
),
|
|
66247
|
-
public_subdomain: zod_default.string().describe(
|
|
66248
|
-
"DNS label for the app's public origin: `<public_subdomain>.lotics.app`. Server-generated, high-entropy, and distinct from `id` (app_ids are not valid DNS labels). Assigned at creation for every app."
|
|
66249
|
-
),
|
|
66250
|
-
public_password_set: zod_default.boolean().optional().describe(
|
|
66251
|
-
"Whether a shared password gates the public binding. True \u2192 anonymous visitors must authenticate at `/v1/apps/{app_id}/public/authenticate` before any publicAppAccess endpoint resolves. The hash itself is never sent over the wire; only this flag is exposed (and only on authenticated owner-side reads \u2014 the public by-subdomain response surfaces the same fact as `requires_password`)."
|
|
66252
|
-
),
|
|
66253
|
-
workflows: zod_default.record(zod_default.string(), appWorkflowDeclarationSchema).nullable().optional().describe(
|
|
66254
|
-
"Alias \u2192 workflow declaration map. Each alias resolves to a workflow_id and an optional typed inputs schema. Authored solely by `set_app_workflow` / `remove_app_workflow` (NOT by `lotics app deploy`, which never touches this map). The iframe SDK's useWorkflow(alias) resolves through this map; when an inputs schema is declared, the server validates payloads against it before invocation and the CLI codegen emits typed call-site signatures. The workflow always executes under the app's IAM principal."
|
|
66255
|
-
),
|
|
66256
|
-
queries: zod_default.record(zod_default.string(), appQueryDeclarationSchema).nullable().optional().describe(
|
|
66257
|
-
"Alias \u2192 query declaration map. Each alias resolves to a fixed query AST template with a typed param schema. Synced from the app's lotics.queries manifest on every `lotics app deploy`. The iframe SDK's useQuery(alias, params) resolves through this map; custom-code apps never send a raw AST. The query runs under the app's IAM principal."
|
|
66258
|
-
),
|
|
66259
|
-
capabilities: appCapabilitiesSchema.nullable().optional().describe(
|
|
66260
|
-
"Opt-in app capabilities, declared in the manifest's `lotics.capabilities` and synced on every deploy. Capabilities are off unless declared \u2014 least ambient authority. `comments` gates the members-only `useComments` primitive: only an app that declares it can read/write record comments (each under the VIEWING member's own authority)."
|
|
66261
|
-
),
|
|
66262
|
-
agents: zod_default.record(zod_default.string(), appAgentDeclarationSchema).nullable().optional().describe(
|
|
66263
|
-
"Alias \u2192 agent declaration map. Each alias binds a streaming tool-loop agent the app runs via `useAgentRun(alias)` (an SSE stream), with declared tools, model, and typed inputs/outputs. Synced from the app's `lotics.agents` manifest on every deploy. The agent runs under the app's IAM principal; runs persist a flat history per session."
|
|
66264
|
-
),
|
|
66265
|
-
theme: appThemeSchema.nullable().optional().describe("Theme settings for the app"),
|
|
66266
|
-
/**
|
|
66267
|
-
* The starter this app is the ORIGIN of, when it is one — list enrichment,
|
|
66268
|
-
* read from the registry rather than stored on the app.
|
|
66269
|
-
*
|
|
66270
|
-
* This is provenance in the only direction that exists under one-way copies:
|
|
66271
|
-
* an app can have PUBLISHED a starter, but an app that was COPIED FROM one
|
|
66272
|
-
* records nothing, because it owns everything it received outright. Null for
|
|
66273
|
-
* every app that has published nothing.
|
|
66274
|
-
*/
|
|
66275
|
-
starter_origin: zod_default.object({
|
|
66276
|
-
starter_id: zod_default.string(),
|
|
66277
|
-
/** The highest version published from this app. */
|
|
66278
|
-
version: zod_default.number().int(),
|
|
66279
|
-
is_official: zod_default.boolean()
|
|
66280
|
-
}).nullable().optional(),
|
|
66281
|
-
created_at: zod_default.string().describe("Timestamp when app was created"),
|
|
66282
|
-
updated_at: zod_default.string().describe("Timestamp of last update")
|
|
66283
|
-
});
|
|
66576
|
+
var templatePartSchema = zod_default.lazy(
|
|
66577
|
+
() => zod_default.discriminatedUnion("t", [
|
|
66578
|
+
zod_default.object({ t: zod_default.literal("text"), s: zod_default.string() }),
|
|
66579
|
+
zod_default.object({ t: zod_default.literal("ex"), e: workflowExpressionSchema })
|
|
66580
|
+
])
|
|
66581
|
+
);
|
|
66284
66582
|
|
|
66285
66583
|
// ../shared/src/schemas/workflow_steps.ts
|
|
66286
66584
|
var toolInputExpressionSchema = zod_default.lazy(
|
|
@@ -67799,6 +68097,358 @@ __export(expression_type_exports, {
|
|
|
67799
68097
|
typeOf: () => typeOf
|
|
67800
68098
|
});
|
|
67801
68099
|
|
|
68100
|
+
// ../shared/src/schemas/table_fields.ts
|
|
68101
|
+
var tableFieldTypeNameSchema = zod_default.enum([
|
|
68102
|
+
"text",
|
|
68103
|
+
"number",
|
|
68104
|
+
"date",
|
|
68105
|
+
"boolean",
|
|
68106
|
+
"select",
|
|
68107
|
+
"select_member",
|
|
68108
|
+
"select_record_link",
|
|
68109
|
+
"files",
|
|
68110
|
+
"formula",
|
|
68111
|
+
"rollup",
|
|
68112
|
+
"lookup",
|
|
68113
|
+
"button",
|
|
68114
|
+
"autonumber"
|
|
68115
|
+
]);
|
|
68116
|
+
var tableFieldBaseSchema = zod_default.object({
|
|
68117
|
+
key: zod_default.string().describe("Unique field key"),
|
|
68118
|
+
name: zod_default.string().describe("Display name"),
|
|
68119
|
+
description: zod_default.string().describe("Field description"),
|
|
68120
|
+
confirm_before_update: zod_default.boolean().optional().describe("Show confirmation before AI updates")
|
|
68121
|
+
});
|
|
68122
|
+
var numberFormatSchema = zod_default.enum(["number", "currency", "percentage"]);
|
|
68123
|
+
var textFormatSchema = zod_default.enum(["text", "link", "markdown"]);
|
|
68124
|
+
var dateFormatSchema = zod_default.enum(["date", "datetime", "date_range", "datetime_range"]);
|
|
68125
|
+
var DEFAULT_VALUE_DESC = "Value pre-filled into a new record when none is supplied for this field. Applied on create only \u2014 existing records are never backfilled. null clears it.";
|
|
68126
|
+
var textDefaultValueSchema = zod_default.string().nullish().describe(DEFAULT_VALUE_DESC);
|
|
68127
|
+
var numberDefaultValueSchema = zod_default.number().nullish().describe(DEFAULT_VALUE_DESC);
|
|
68128
|
+
var booleanDefaultValueSchema = zod_default.boolean().nullish().describe(DEFAULT_VALUE_DESC);
|
|
68129
|
+
var dateDefaultValueSchema = zod_default.string().nullish().describe(`${DEFAULT_VALUE_DESC} A date string in the field's format.`);
|
|
68130
|
+
var selectDefaultValueSchema = zod_default.array(zod_default.string()).nullish().describe(`${DEFAULT_VALUE_DESC} Option key(s) \u2014 one for single-select.`);
|
|
68131
|
+
var memberDefaultValueSchema = zod_default.array(zod_default.string()).nullish().describe(`${DEFAULT_VALUE_DESC} Member ID(s) \u2014 one for single-select.`);
|
|
68132
|
+
var tableNumberFieldSchema = tableFieldBaseSchema.extend({
|
|
68133
|
+
type: zod_default.literal("number"),
|
|
68134
|
+
format: numberFormatSchema,
|
|
68135
|
+
currency: zod_default.string().optional().describe("ISO 4217 code"),
|
|
68136
|
+
default_value: numberDefaultValueSchema
|
|
68137
|
+
});
|
|
68138
|
+
var tableTextFieldSchema = tableFieldBaseSchema.extend({
|
|
68139
|
+
type: zod_default.literal("text"),
|
|
68140
|
+
unique: zod_default.boolean().optional().describe("Unique values required"),
|
|
68141
|
+
// it's `optional` only for backward compatibility
|
|
68142
|
+
format: textFormatSchema.optional(),
|
|
68143
|
+
default_value: textDefaultValueSchema
|
|
68144
|
+
});
|
|
68145
|
+
var tableDateFieldSchema = tableFieldBaseSchema.extend({
|
|
68146
|
+
type: zod_default.literal("date"),
|
|
68147
|
+
format: dateFormatSchema.optional(),
|
|
68148
|
+
timezone: zod_default.string().optional().describe("IANA timezone"),
|
|
68149
|
+
derive_from: zod_default.enum(["created_at", "updated_at"]).optional().describe(
|
|
68150
|
+
"Auto-populate from the row's system timestamp. `created_at` stamps once at insert time; `updated_at` re-stamps on every record edit. Derived fields are read-only \u2014 user-supplied values are silently ignored at write time, matching the formula/rollup/lookup pattern. Replaces the per-table after_create workflow pattern."
|
|
68151
|
+
),
|
|
68152
|
+
// A derived date is read-only, so derive_from and default_value are mutually
|
|
68153
|
+
// exclusive — enforced in validateFieldDefaultValue.
|
|
68154
|
+
default_value: dateDefaultValueSchema
|
|
68155
|
+
});
|
|
68156
|
+
var tableBooleanFieldSchema = tableFieldBaseSchema.extend({
|
|
68157
|
+
type: zod_default.literal("boolean"),
|
|
68158
|
+
default_value: booleanDefaultValueSchema
|
|
68159
|
+
});
|
|
68160
|
+
var tableSelectFieldOptionSchema = zod_default.object({
|
|
68161
|
+
key: zod_default.string(),
|
|
68162
|
+
name: zod_default.string(),
|
|
68163
|
+
color: optionColorSchema
|
|
68164
|
+
});
|
|
68165
|
+
var tableSelectFieldSchema = tableFieldBaseSchema.extend({
|
|
68166
|
+
type: zod_default.literal("select"),
|
|
68167
|
+
options: zod_default.array(tableSelectFieldOptionSchema),
|
|
68168
|
+
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
68169
|
+
default_value: selectDefaultValueSchema
|
|
68170
|
+
});
|
|
68171
|
+
var tableSelectMemberFieldSchema = tableFieldBaseSchema.extend({
|
|
68172
|
+
type: zod_default.literal("select_member"),
|
|
68173
|
+
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
68174
|
+
default_value: memberDefaultValueSchema
|
|
68175
|
+
});
|
|
68176
|
+
var recordLinkItemSchema = zod_default.object({
|
|
68177
|
+
id: zod_default.string(),
|
|
68178
|
+
display: zod_default.string()
|
|
68179
|
+
});
|
|
68180
|
+
var selectRecordLinkValueSchema = zod_default.array(recordLinkItemSchema);
|
|
68181
|
+
var tableSelectRecordLinkFieldInputSchema = tableFieldBaseSchema.extend({
|
|
68182
|
+
type: zod_default.literal("select_record_link"),
|
|
68183
|
+
table_id: zod_default.string().describe("Linked table ID"),
|
|
68184
|
+
display_field_keys: zod_default.array(zod_default.string()).optional().describe(
|
|
68185
|
+
"Field keys of the linked table shown as the link's display text and as the columns in the record picker. If omitted, auto-selects the first text field."
|
|
68186
|
+
),
|
|
68187
|
+
display_field_widths: zod_default.record(zod_default.string(), zod_default.number().int().positive()).optional().describe(
|
|
68188
|
+
"Per-column widths in pixels for the record picker, keyed by linked-table field key. Missing keys fall back to the default column width."
|
|
68189
|
+
),
|
|
68190
|
+
sync_both_ways: zod_default.boolean().optional().describe("Enable bidirectional link sync. If the target table has exactly one existing unpaired link field pointing back, pairs with it instead of creating a new field."),
|
|
68191
|
+
paired_field_display_field_keys: zod_default.array(zod_default.string()).optional().describe("Display fields for paired link"),
|
|
68192
|
+
paired_field_name: zod_default.string().optional().describe(
|
|
68193
|
+
"Name for the auto-created paired field on the target table when sync_both_ways=true. If omitted, falls back to the source table's name (auto-uniquified with a numeric suffix on collision). Rejected as a conflict if a field with this name already exists on the target."
|
|
68194
|
+
),
|
|
68195
|
+
cardinality: zod_default.enum(["one", "many"]).optional().describe(
|
|
68196
|
+
"How many linked records this field can hold. Default 'many' (multi-select). 'one' = single-select; this side holds exactly one link to the partner. Requires sync_both_ways/paired_field_key. Setting 'one' on both paired sides is rejected."
|
|
68197
|
+
)
|
|
68198
|
+
});
|
|
68199
|
+
var tableSelectRecordLinkFieldSchema = tableFieldBaseSchema.extend({
|
|
68200
|
+
type: zod_default.literal("select_record_link").describe("Field type for linking to records in another table"),
|
|
68201
|
+
table_id: zod_default.string().describe("ID of the target table that records can be linked to"),
|
|
68202
|
+
display_field_keys: zod_default.array(zod_default.string()).optional().default([]).describe(
|
|
68203
|
+
"Field keys of the linked table shown as the link's display text and as the columns in the record picker. If empty, the picker shows all fields."
|
|
68204
|
+
),
|
|
68205
|
+
display_field_widths: zod_default.record(zod_default.string(), zod_default.number().int().positive()).optional().describe(
|
|
68206
|
+
"Per-column widths in pixels for the record picker, keyed by linked-table field key. Missing keys fall back to the default column width."
|
|
68207
|
+
),
|
|
68208
|
+
paired_field_key: zod_default.string().optional().describe(
|
|
68209
|
+
"Key of the paired link field in the linked table. If set to a string, this indicates a bidirectional link where both tables can reference each other and data synchronizes in both directions. Both fields have paired_field_key pointing to each other. If set to null, explicitly disconnects the bidirectional link (clears paired_field_key on both sides). If undefined, no change is made to the existing paired_field_key."
|
|
68210
|
+
),
|
|
68211
|
+
cardinality: zod_default.enum(["one", "many"]).optional().describe(
|
|
68212
|
+
"How many linked records this field can hold. Default 'many' (multi-select). 'one' = single-select; this side holds exactly one link to the partner. Requires paired_field_key. Two paired sides cannot both be 'one'."
|
|
68213
|
+
)
|
|
68214
|
+
});
|
|
68215
|
+
var tableRollupFieldSchema = tableFieldBaseSchema.extend({
|
|
68216
|
+
type: zod_default.literal("rollup").describe(
|
|
68217
|
+
"Field type for aggregating values from linked records (sum, avg, filled, earliest, etc.)"
|
|
68218
|
+
),
|
|
68219
|
+
source_field_key: zod_default.string().describe("The field key of the select_record_link field to rollup from"),
|
|
68220
|
+
aggregate_option: aggregateOptionSchema.describe(
|
|
68221
|
+
"The field aggregation function to apply (e.g., sum, avg, filled, earliest)"
|
|
68222
|
+
),
|
|
68223
|
+
filter: tableRecordFiltersGroupNodeSchema.optional().describe(
|
|
68224
|
+
"Optional filter to apply to linked records before aggregation. Only records matching the filter conditions will be included in the rollup calculation."
|
|
68225
|
+
),
|
|
68226
|
+
aggregate_field_type: tableFieldTypeNameSchema.optional().describe(
|
|
68227
|
+
"What this rollup's CELL holds \u2014 'date' for earliest/latest, 'number' for every other operation (counts, sums, percentages). Derived from the operation, not from the aggregated field: a 'filled' count over a files column is a number. Server-derived at write time; ignored on input."
|
|
68228
|
+
),
|
|
68229
|
+
aggregate_field_format: zod_default.string().optional().describe(
|
|
68230
|
+
"The format of this rollup's own value. Operations that preserve the aggregated value's unit (sum/avg/median/min/max/range/earliest/latest) inherit the target field's format; counting operations are 'number', percentages 'percentage'. Server-derived at write time; ignored on input."
|
|
68231
|
+
),
|
|
68232
|
+
aggregate_field_currency: zod_default.string().optional().describe(
|
|
68233
|
+
"The currency code of this rollup's own value (e.g. 'USD', 'VND'), inherited from the aggregated field only when the operation preserves its unit \u2014 a COUNT of a currency column carries no currency. Server-derived at write time; ignored on input."
|
|
68234
|
+
)
|
|
68235
|
+
});
|
|
68236
|
+
var lookupOrderBySchema = zod_default.object({
|
|
68237
|
+
field_key: zod_default.string(),
|
|
68238
|
+
direction: zod_default.enum(["asc", "desc"])
|
|
68239
|
+
});
|
|
68240
|
+
var tableLookupFieldSchema = tableFieldBaseSchema.extend({
|
|
68241
|
+
type: zod_default.literal("lookup").describe("Field type for displaying values from fields in linked records"),
|
|
68242
|
+
source_field_key: zod_default.string().describe("The field key of the select_record_link field to lookup from"),
|
|
68243
|
+
lookup_field_key: zod_default.string().describe("The field key from the linked records to display"),
|
|
68244
|
+
lookup_field_type: tableFieldTypeNameSchema.optional().describe(
|
|
68245
|
+
"The type of the target lookup field (e.g. 'text', 'number', 'date'). Resolved from the linked table's field definition at read time."
|
|
68246
|
+
),
|
|
68247
|
+
lookup_field_format: zod_default.string().optional().describe(
|
|
68248
|
+
"The format of the target lookup field (e.g. 'currency', 'percentage', 'datetime'). Resolved from the linked table's field definition at read time."
|
|
68249
|
+
),
|
|
68250
|
+
lookup_field_currency: zod_default.string().optional().describe(
|
|
68251
|
+
"The currency code of the target lookup field (e.g. 'USD', 'VND'). Resolved from the linked table's field definition at read time."
|
|
68252
|
+
),
|
|
68253
|
+
lookup_field_options: zod_default.array(zod_default.object({ key: zod_default.string(), name: zod_default.string(), color: zod_default.string().optional() })).optional().describe(
|
|
68254
|
+
"Options for select-type lookup fields. Synced from the source select field's options."
|
|
68255
|
+
),
|
|
68256
|
+
order_by: lookupOrderBySchema.optional().describe(
|
|
68257
|
+
"When set, sort the linked records by this field on the linked table and return ONLY the picked field from the single extreme record (desc=latest, asc=earliest), as a one-element array. Omit to return every linked record's value as an array. field_key must be a field on the linked table."
|
|
68258
|
+
)
|
|
68259
|
+
});
|
|
68260
|
+
var tableFilesFieldSchema = tableFieldBaseSchema.extend({
|
|
68261
|
+
type: zod_default.literal("files").describe("Field type for file attachments (images, PDFs, documents)")
|
|
68262
|
+
});
|
|
68263
|
+
var formulaInputSchema = zod_default.object({
|
|
68264
|
+
expression: zod_default.string().describe(
|
|
68265
|
+
"JavaScript expression. Uses {Field Name} for field references."
|
|
68266
|
+
),
|
|
68267
|
+
format: zod_default.enum(["number", "currency", "percentage", "link"]).optional().describe(
|
|
68268
|
+
"Display format. 'number' / 'currency' / 'percentage' for numeric results; 'link' for text-output formulas that return a URL \u2014 renders the result as a clickable link."
|
|
68269
|
+
),
|
|
68270
|
+
currency: zod_default.string().optional().describe("ISO 4217 currency code, e.g. USD, VND, EUR")
|
|
68271
|
+
});
|
|
68272
|
+
var formulaSchema = formulaInputSchema.extend({
|
|
68273
|
+
output_type: zod_default.enum(["number", "text", "date", "datetime", "boolean"]).optional().describe("Output type of the formula. Inferred by the backend from the expression \u2014 read-only on input. `datetime` when the result carries a time of day (references a datetime field or a time-bearing helper)."),
|
|
68274
|
+
volatile: zod_default.boolean().optional().describe("Whether the formula's result depends on `now()` or other non-deterministic helpers. Inferred by the backend \u2014 read-only on input.")
|
|
68275
|
+
});
|
|
68276
|
+
var tableFormulaFieldSchema = tableFieldBaseSchema.extend({
|
|
68277
|
+
type: zod_default.literal("formula").describe("Field type for calculated values based on expressions"),
|
|
68278
|
+
formula: formulaSchema.describe("Formula configuration and expression")
|
|
68279
|
+
});
|
|
68280
|
+
var workflowMetadataSchema = zod_default.object({
|
|
68281
|
+
table_ids: zod_default.array(zod_default.string()).describe("IDs of the tables this workflow affects"),
|
|
68282
|
+
staged_for_app_id: zod_default.string().optional().describe(
|
|
68283
|
+
"Present while the row is a draft-staged fork for this app; cleared when the app publishes the binding. Marked rows left unbound are archived at publish/discard."
|
|
68284
|
+
)
|
|
68285
|
+
});
|
|
68286
|
+
var workflowSchema = zod_default.object({
|
|
68287
|
+
id: zod_default.string().describe("Unique identifier for the workflow"),
|
|
68288
|
+
name: zod_default.string().describe("Display name of the workflow"),
|
|
68289
|
+
description: zod_default.string().describe("Human-readable description of what this workflow does"),
|
|
68290
|
+
steps: zod_default.unknown().describe(
|
|
68291
|
+
"AST-valued step tree (tool calls, conditionals, loops)."
|
|
68292
|
+
),
|
|
68293
|
+
metadata: workflowMetadataSchema.nullable().optional().describe("Metadata for the workflow"),
|
|
68294
|
+
current_version: zod_default.number().int().describe("Current version number"),
|
|
68295
|
+
enabled: zod_default.boolean().describe("Whether this workflow is active"),
|
|
68296
|
+
workspace_id: zod_default.string().describe("ID of the workspace this workflow belongs to"),
|
|
68297
|
+
created_at: zod_default.string().describe("Timestamp when workflow was created"),
|
|
68298
|
+
updated_at: zod_default.string().describe("Timestamp of last update")
|
|
68299
|
+
});
|
|
68300
|
+
var tableButtonFieldSchema = tableFieldBaseSchema.extend({
|
|
68301
|
+
type: zod_default.literal("button").describe("Field type for action buttons"),
|
|
68302
|
+
text: zod_default.string().describe("Button label text displayed to users"),
|
|
68303
|
+
workflow_id: zod_default.string().nullable().optional().describe(
|
|
68304
|
+
"ID of the workflow the button presses trigger. Null means no action configured \u2014 pressing the button is a no-op. Button authoring is retired: existing bindings keep running, but nothing sets a new one."
|
|
68305
|
+
)
|
|
68306
|
+
});
|
|
68307
|
+
var tableAutonumberFieldSchema = tableFieldBaseSchema.extend({
|
|
68308
|
+
type: zod_default.literal("autonumber"),
|
|
68309
|
+
prefix: zod_default.string().optional().describe(
|
|
68310
|
+
"Literal prefix prepended to every display value (e.g. 'KH-' \u2192 'KH-001'). Ignored when `template` is set."
|
|
68311
|
+
),
|
|
68312
|
+
padding: zod_default.number().int().min(1).max(20).optional().describe(
|
|
68313
|
+
"Zero-pad the integer to this width. Default 1 (no padding). 3 \u2192 '001', '012', '123', '1234' (overflow uses the actual width). Ignored when `template` is set."
|
|
68314
|
+
),
|
|
68315
|
+
template: zod_default.string().optional().describe(
|
|
68316
|
+
"Format template with placeholder tokens evaluated at insert time. Tokens: {N} (raw integer), {N:W} (zero-padded to width W, e.g. {N:3} \u2192 001), {YEAR} (4-digit year), {YEAR:2} (2-digit year), {MONTH} (2-digit month), {DAY} (2-digit day). Date tokens use the workspace timezone. Example: 'HM-{YEAR}-{N:3}' yields 'HM-2026-001'. Stored as the composed string; subsequent template edits do NOT re-format existing rows (date tokens would lose the original creation date)."
|
|
68317
|
+
)
|
|
68318
|
+
});
|
|
68319
|
+
var tableFieldSchema = zod_default.discriminatedUnion("type", [
|
|
68320
|
+
tableNumberFieldSchema,
|
|
68321
|
+
tableTextFieldSchema,
|
|
68322
|
+
tableDateFieldSchema,
|
|
68323
|
+
tableBooleanFieldSchema,
|
|
68324
|
+
tableSelectFieldSchema,
|
|
68325
|
+
tableSelectMemberFieldSchema,
|
|
68326
|
+
tableSelectRecordLinkFieldSchema,
|
|
68327
|
+
tableRollupFieldSchema,
|
|
68328
|
+
tableLookupFieldSchema,
|
|
68329
|
+
tableFilesFieldSchema,
|
|
68330
|
+
tableFormulaFieldSchema,
|
|
68331
|
+
tableButtonFieldSchema,
|
|
68332
|
+
tableAutonumberFieldSchema
|
|
68333
|
+
]);
|
|
68334
|
+
var tableFieldInputSchema = zod_default.discriminatedUnion("type", [
|
|
68335
|
+
tableNumberFieldSchema,
|
|
68336
|
+
tableTextFieldSchema,
|
|
68337
|
+
tableDateFieldSchema,
|
|
68338
|
+
tableBooleanFieldSchema,
|
|
68339
|
+
tableSelectFieldSchema,
|
|
68340
|
+
tableSelectMemberFieldSchema,
|
|
68341
|
+
tableSelectRecordLinkFieldInputSchema,
|
|
68342
|
+
tableRollupFieldSchema,
|
|
68343
|
+
tableLookupFieldSchema,
|
|
68344
|
+
tableFilesFieldSchema,
|
|
68345
|
+
tableFormulaFieldSchema,
|
|
68346
|
+
tableButtonFieldSchema,
|
|
68347
|
+
tableAutonumberFieldSchema
|
|
68348
|
+
]);
|
|
68349
|
+
var tableFieldsSchema = zod_default.array(tableFieldSchema);
|
|
68350
|
+
var tableFieldCreateBaseSchema = zod_default.object({
|
|
68351
|
+
name: zod_default.string().describe("Display name"),
|
|
68352
|
+
description: zod_default.string().describe("Field description"),
|
|
68353
|
+
confirm_before_update: zod_default.boolean().optional().describe("Show confirmation before AI updates")
|
|
68354
|
+
});
|
|
68355
|
+
var tableSelectFieldOptionCreateSchema = zod_default.object({
|
|
68356
|
+
name: zod_default.string(),
|
|
68357
|
+
color: optionColorSchema
|
|
68358
|
+
});
|
|
68359
|
+
var tableFieldTypeConfigSchema = zod_default.discriminatedUnion("type", [
|
|
68360
|
+
zod_default.object({
|
|
68361
|
+
type: zod_default.literal("number"),
|
|
68362
|
+
format: numberFormatSchema.default("number"),
|
|
68363
|
+
currency: zod_default.string().optional().describe("ISO 4217 code"),
|
|
68364
|
+
default_value: numberDefaultValueSchema
|
|
68365
|
+
}),
|
|
68366
|
+
zod_default.object({
|
|
68367
|
+
type: zod_default.literal("text"),
|
|
68368
|
+
unique: zod_default.boolean().optional().describe("Unique values required"),
|
|
68369
|
+
format: textFormatSchema.default("text"),
|
|
68370
|
+
default_value: textDefaultValueSchema
|
|
68371
|
+
}),
|
|
68372
|
+
zod_default.object({
|
|
68373
|
+
type: zod_default.literal("date"),
|
|
68374
|
+
format: dateFormatSchema.optional(),
|
|
68375
|
+
timezone: zod_default.string().optional().describe("IANA timezone"),
|
|
68376
|
+
derive_from: zod_default.enum(["created_at", "updated_at"]).nullable().optional().describe("Auto-populate from row system timestamp; field becomes read-only. Only valid for date/datetime formats. Pass null to clear and revert to a manual date field."),
|
|
68377
|
+
default_value: dateDefaultValueSchema
|
|
68378
|
+
}),
|
|
68379
|
+
zod_default.object({
|
|
68380
|
+
type: zod_default.literal("boolean"),
|
|
68381
|
+
default_value: booleanDefaultValueSchema
|
|
68382
|
+
}),
|
|
68383
|
+
zod_default.object({
|
|
68384
|
+
type: zod_default.literal("select"),
|
|
68385
|
+
options: zod_default.array(tableSelectFieldOptionCreateSchema),
|
|
68386
|
+
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
68387
|
+
default_value: selectDefaultValueSchema
|
|
68388
|
+
}),
|
|
68389
|
+
zod_default.object({
|
|
68390
|
+
type: zod_default.literal("select_member"),
|
|
68391
|
+
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
68392
|
+
default_value: memberDefaultValueSchema
|
|
68393
|
+
}),
|
|
68394
|
+
zod_default.object({
|
|
68395
|
+
type: zod_default.literal("select_record_link"),
|
|
68396
|
+
table_id: zod_default.string().describe("Linked table ID"),
|
|
68397
|
+
display_field_keys: zod_default.array(zod_default.string()).optional().describe(
|
|
68398
|
+
"Field keys of the linked table shown as the link's display text and as the columns in the record picker. If omitted, auto-selects the first text field."
|
|
68399
|
+
),
|
|
68400
|
+
display_field_widths: zod_default.record(zod_default.string(), zod_default.number().int().positive()).optional().describe(
|
|
68401
|
+
"Per-column widths in pixels for the record picker, keyed by linked-table field key. Missing keys fall back to the default column width."
|
|
68402
|
+
),
|
|
68403
|
+
sync_both_ways: zod_default.boolean().optional().describe("Enable bidirectional link sync. If the target table has exactly one existing unpaired link field pointing back, pairs with it instead of creating a new field."),
|
|
68404
|
+
paired_field_display_field_keys: zod_default.array(zod_default.string()).optional().describe("Paired field display"),
|
|
68405
|
+
paired_field_name: zod_default.string().optional().describe(
|
|
68406
|
+
"Name for the auto-created paired field on the target table when sync_both_ways=true. Omit to default to the source table's name (auto-uniquified on collision). If supplied and a field with the same name already exists on the target, the create is rejected."
|
|
68407
|
+
),
|
|
68408
|
+
cardinality: zod_default.enum(["one", "many"]).optional().describe(
|
|
68409
|
+
"How many linked records this field can hold. Default 'many' (multi-select). 'one' = single-select; this side holds exactly one link to the partner. Requires sync_both_ways. Two paired sides cannot both be 'one'."
|
|
68410
|
+
)
|
|
68411
|
+
}),
|
|
68412
|
+
zod_default.object({
|
|
68413
|
+
type: zod_default.literal("rollup"),
|
|
68414
|
+
source_field_key: zod_default.string().describe("Source link field key"),
|
|
68415
|
+
aggregate_option: aggregateOptionSchema,
|
|
68416
|
+
filter: tableRecordFiltersGroupNodeSchema.optional().describe("Filter linked records")
|
|
68417
|
+
}),
|
|
68418
|
+
zod_default.object({
|
|
68419
|
+
type: zod_default.literal("lookup"),
|
|
68420
|
+
source_field_key: zod_default.string().describe("Source link field key"),
|
|
68421
|
+
lookup_field_key: zod_default.string().describe("Field to display"),
|
|
68422
|
+
order_by: lookupOrderBySchema.optional().describe("Ordered lookup: pick only the extreme linked record's field (desc=latest, asc=earliest)")
|
|
68423
|
+
}),
|
|
68424
|
+
zod_default.object({
|
|
68425
|
+
type: zod_default.literal("files")
|
|
68426
|
+
}),
|
|
68427
|
+
zod_default.object({
|
|
68428
|
+
type: zod_default.literal("formula"),
|
|
68429
|
+
formula: formulaInputSchema
|
|
68430
|
+
}),
|
|
68431
|
+
// `button` is deliberately absent: button fields are legacy — this union
|
|
68432
|
+
// shapes CREATE input only, and new buttons can no longer be created
|
|
68433
|
+
// (see LEGACY_FIELD_TYPES). Stored button fields still parse via the
|
|
68434
|
+
// stored-field union above, and update paths keep accepting text edits.
|
|
68435
|
+
zod_default.object({
|
|
68436
|
+
type: zod_default.literal("autonumber"),
|
|
68437
|
+
prefix: zod_default.string().optional().describe("Literal prefix prepended to display (ignored when template is set)"),
|
|
68438
|
+
padding: zod_default.number().int().min(1).max(20).optional().describe("Zero-pad the integer to this width (default 1) (ignored when template is set)"),
|
|
68439
|
+
template: zod_default.string().optional().describe(
|
|
68440
|
+
"Format template \u2014 tokens evaluate at insert time: {N}, {N:W} (padded), {YEAR}, {YEAR:2}, {MONTH}, {DAY}. Date tokens use workspace timezone. Example: 'HM-{YEAR}-{N:3}' \u2192 'HM-2026-001'."
|
|
68441
|
+
)
|
|
68442
|
+
})
|
|
68443
|
+
]);
|
|
68444
|
+
var tableFieldCreateInputSchema = zod_default.intersection(
|
|
68445
|
+
tableFieldCreateBaseSchema,
|
|
68446
|
+
tableFieldTypeConfigSchema
|
|
68447
|
+
);
|
|
68448
|
+
var fieldVisibilitySchema = zod_default.enum(["visible", "hidden"]).describe(
|
|
68449
|
+
"Field visibility state: 'visible' = shown to everyone, 'hidden' = not shown by default but members can toggle"
|
|
68450
|
+
);
|
|
68451
|
+
|
|
67802
68452
|
// ../shared/src/schemas/database_types.ts
|
|
67803
68453
|
function isEmptyFieldValue(value2) {
|
|
67804
68454
|
if (value2 === null || value2 === void 0) {
|
|
@@ -67880,228 +68530,6 @@ function typeOf(value2) {
|
|
|
67880
68530
|
return typeof value2;
|
|
67881
68531
|
}
|
|
67882
68532
|
|
|
67883
|
-
// ../../node_modules/@date-fns/tz/tzName/index.js
|
|
67884
|
-
function tzName(timeZone, date6, format2 = "long") {
|
|
67885
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
67886
|
-
// Enforces engine to render the time. Without the option JavaScriptCore omits it.
|
|
67887
|
-
hour: "numeric",
|
|
67888
|
-
timeZone,
|
|
67889
|
-
timeZoneName: format2
|
|
67890
|
-
}).format(date6).split(/\s/g).slice(2).join(" ");
|
|
67891
|
-
}
|
|
67892
|
-
|
|
67893
|
-
// ../../node_modules/@date-fns/tz/tzOffset/index.js
|
|
67894
|
-
var offsetFormatCache = {};
|
|
67895
|
-
var offsetCache = {};
|
|
67896
|
-
function tzOffset(timeZone, date6) {
|
|
67897
|
-
try {
|
|
67898
|
-
const format2 = offsetFormatCache[timeZone] ||= new Intl.DateTimeFormat("en-US", {
|
|
67899
|
-
timeZone,
|
|
67900
|
-
timeZoneName: "longOffset"
|
|
67901
|
-
}).format;
|
|
67902
|
-
const offsetStr = format2(date6).split("GMT")[1];
|
|
67903
|
-
if (offsetStr in offsetCache) return offsetCache[offsetStr];
|
|
67904
|
-
return calcOffset(offsetStr, offsetStr.split(":"));
|
|
67905
|
-
} catch {
|
|
67906
|
-
if (timeZone in offsetCache) return offsetCache[timeZone];
|
|
67907
|
-
const captures = timeZone?.match(offsetRe);
|
|
67908
|
-
if (captures) return calcOffset(timeZone, captures.slice(1));
|
|
67909
|
-
return NaN;
|
|
67910
|
-
}
|
|
67911
|
-
}
|
|
67912
|
-
var offsetRe = /([+-]\d\d):?(\d\d)?/;
|
|
67913
|
-
function calcOffset(cacheStr, values3) {
|
|
67914
|
-
const hours = +(values3[0] || 0);
|
|
67915
|
-
const minutes = +(values3[1] || 0);
|
|
67916
|
-
const seconds = +(values3[2] || 0) / 60;
|
|
67917
|
-
return offsetCache[cacheStr] = hours * 60 + minutes > 0 ? hours * 60 + minutes + seconds : hours * 60 - minutes - seconds;
|
|
67918
|
-
}
|
|
67919
|
-
|
|
67920
|
-
// ../../node_modules/@date-fns/tz/date/mini.js
|
|
67921
|
-
var TZDateMini = class _TZDateMini extends Date {
|
|
67922
|
-
//#region static
|
|
67923
|
-
constructor(...args) {
|
|
67924
|
-
super();
|
|
67925
|
-
if (args.length > 1 && typeof args[args.length - 1] === "string") {
|
|
67926
|
-
this.timeZone = args.pop();
|
|
67927
|
-
}
|
|
67928
|
-
this.internal = /* @__PURE__ */ new Date();
|
|
67929
|
-
if (isNaN(tzOffset(this.timeZone, this))) {
|
|
67930
|
-
this.setTime(NaN);
|
|
67931
|
-
} else {
|
|
67932
|
-
if (!args.length) {
|
|
67933
|
-
this.setTime(Date.now());
|
|
67934
|
-
} else if (typeof args[0] === "number" && (args.length === 1 || args.length === 2 && typeof args[1] !== "number")) {
|
|
67935
|
-
this.setTime(args[0]);
|
|
67936
|
-
} else if (typeof args[0] === "string") {
|
|
67937
|
-
this.setTime(+new Date(args[0]));
|
|
67938
|
-
} else if (args[0] instanceof Date) {
|
|
67939
|
-
this.setTime(+args[0]);
|
|
67940
|
-
} else {
|
|
67941
|
-
this.setTime(+new Date(...args));
|
|
67942
|
-
adjustToSystemTZ(this, NaN);
|
|
67943
|
-
syncToInternal(this);
|
|
67944
|
-
}
|
|
67945
|
-
}
|
|
67946
|
-
}
|
|
67947
|
-
static tz(tz, ...args) {
|
|
67948
|
-
return args.length ? new _TZDateMini(...args, tz) : new _TZDateMini(Date.now(), tz);
|
|
67949
|
-
}
|
|
67950
|
-
//#endregion
|
|
67951
|
-
//#region time zone
|
|
67952
|
-
withTimeZone(timeZone) {
|
|
67953
|
-
return new _TZDateMini(+this, timeZone);
|
|
67954
|
-
}
|
|
67955
|
-
getTimezoneOffset() {
|
|
67956
|
-
const offset = -tzOffset(this.timeZone, this);
|
|
67957
|
-
return offset > 0 ? Math.floor(offset) : Math.ceil(offset);
|
|
67958
|
-
}
|
|
67959
|
-
//#endregion
|
|
67960
|
-
//#region time
|
|
67961
|
-
setTime(time3) {
|
|
67962
|
-
Date.prototype.setTime.apply(this, arguments);
|
|
67963
|
-
syncToInternal(this);
|
|
67964
|
-
return +this;
|
|
67965
|
-
}
|
|
67966
|
-
//#endregion
|
|
67967
|
-
//#region date-fns integration
|
|
67968
|
-
[/* @__PURE__ */ Symbol.for("constructDateFrom")](date6) {
|
|
67969
|
-
return new _TZDateMini(+new Date(date6), this.timeZone);
|
|
67970
|
-
}
|
|
67971
|
-
//#endregion
|
|
67972
|
-
};
|
|
67973
|
-
var re = /^(get|set)(?!UTC)/;
|
|
67974
|
-
Object.getOwnPropertyNames(Date.prototype).forEach((method) => {
|
|
67975
|
-
if (!re.test(method)) return;
|
|
67976
|
-
const utcMethod = method.replace(re, "$1UTC");
|
|
67977
|
-
if (!TZDateMini.prototype[utcMethod]) return;
|
|
67978
|
-
if (method.startsWith("get")) {
|
|
67979
|
-
TZDateMini.prototype[method] = function() {
|
|
67980
|
-
return this.internal[utcMethod]();
|
|
67981
|
-
};
|
|
67982
|
-
} else {
|
|
67983
|
-
TZDateMini.prototype[method] = function() {
|
|
67984
|
-
Date.prototype[utcMethod].apply(this.internal, arguments);
|
|
67985
|
-
syncFromInternal(this);
|
|
67986
|
-
return +this;
|
|
67987
|
-
};
|
|
67988
|
-
TZDateMini.prototype[utcMethod] = function() {
|
|
67989
|
-
Date.prototype[utcMethod].apply(this, arguments);
|
|
67990
|
-
syncToInternal(this);
|
|
67991
|
-
return +this;
|
|
67992
|
-
};
|
|
67993
|
-
}
|
|
67994
|
-
});
|
|
67995
|
-
function syncToInternal(date6) {
|
|
67996
|
-
date6.internal.setTime(+date6);
|
|
67997
|
-
date6.internal.setUTCSeconds(date6.internal.getUTCSeconds() - Math.round(-tzOffset(date6.timeZone, date6) * 60));
|
|
67998
|
-
}
|
|
67999
|
-
function syncFromInternal(date6) {
|
|
68000
|
-
Date.prototype.setFullYear.call(date6, date6.internal.getUTCFullYear(), date6.internal.getUTCMonth(), date6.internal.getUTCDate());
|
|
68001
|
-
Date.prototype.setHours.call(date6, date6.internal.getUTCHours(), date6.internal.getUTCMinutes(), date6.internal.getUTCSeconds(), date6.internal.getUTCMilliseconds());
|
|
68002
|
-
adjustToSystemTZ(date6);
|
|
68003
|
-
}
|
|
68004
|
-
function adjustToSystemTZ(date6) {
|
|
68005
|
-
const baseOffset = tzOffset(date6.timeZone, date6);
|
|
68006
|
-
const offset = baseOffset > 0 ? Math.floor(baseOffset) : Math.ceil(baseOffset);
|
|
68007
|
-
const prevHour = /* @__PURE__ */ new Date(+date6);
|
|
68008
|
-
prevHour.setUTCHours(prevHour.getUTCHours() - 1);
|
|
68009
|
-
const systemOffset = -(/* @__PURE__ */ new Date(+date6)).getTimezoneOffset();
|
|
68010
|
-
const prevHourSystemOffset = -(/* @__PURE__ */ new Date(+prevHour)).getTimezoneOffset();
|
|
68011
|
-
const systemDSTChange = systemOffset - prevHourSystemOffset;
|
|
68012
|
-
const dstShift = Date.prototype.getHours.apply(date6) !== date6.internal.getUTCHours();
|
|
68013
|
-
if (systemDSTChange && dstShift) date6.internal.setUTCMinutes(date6.internal.getUTCMinutes() + systemDSTChange);
|
|
68014
|
-
const offsetDiff = systemOffset - offset;
|
|
68015
|
-
if (offsetDiff) Date.prototype.setUTCMinutes.call(date6, Date.prototype.getUTCMinutes.call(date6) + offsetDiff);
|
|
68016
|
-
const systemDate = /* @__PURE__ */ new Date(+date6);
|
|
68017
|
-
systemDate.setUTCSeconds(0);
|
|
68018
|
-
const systemSecondsOffset = systemOffset > 0 ? systemDate.getSeconds() : (systemDate.getSeconds() - 60) % 60;
|
|
68019
|
-
const secondsOffset = Math.round(-(tzOffset(date6.timeZone, date6) * 60)) % 60;
|
|
68020
|
-
if (secondsOffset || systemSecondsOffset) {
|
|
68021
|
-
date6.internal.setUTCSeconds(date6.internal.getUTCSeconds() + secondsOffset);
|
|
68022
|
-
Date.prototype.setUTCSeconds.call(date6, Date.prototype.getUTCSeconds.call(date6) + secondsOffset + systemSecondsOffset);
|
|
68023
|
-
}
|
|
68024
|
-
const postBaseOffset = tzOffset(date6.timeZone, date6);
|
|
68025
|
-
const postOffset = postBaseOffset > 0 ? Math.floor(postBaseOffset) : Math.ceil(postBaseOffset);
|
|
68026
|
-
const postSystemOffset = -(/* @__PURE__ */ new Date(+date6)).getTimezoneOffset();
|
|
68027
|
-
const postOffsetDiff = postSystemOffset - postOffset;
|
|
68028
|
-
const offsetChanged = postOffset !== offset;
|
|
68029
|
-
const postDiff = postOffsetDiff - offsetDiff;
|
|
68030
|
-
if (offsetChanged && postDiff) {
|
|
68031
|
-
Date.prototype.setUTCMinutes.call(date6, Date.prototype.getUTCMinutes.call(date6) + postDiff);
|
|
68032
|
-
const newBaseOffset = tzOffset(date6.timeZone, date6);
|
|
68033
|
-
const newOffset = newBaseOffset > 0 ? Math.floor(newBaseOffset) : Math.ceil(newBaseOffset);
|
|
68034
|
-
const offsetChange = postOffset - newOffset;
|
|
68035
|
-
if (offsetChange) {
|
|
68036
|
-
date6.internal.setUTCMinutes(date6.internal.getUTCMinutes() + offsetChange);
|
|
68037
|
-
Date.prototype.setUTCMinutes.call(date6, Date.prototype.getUTCMinutes.call(date6) + offsetChange);
|
|
68038
|
-
}
|
|
68039
|
-
}
|
|
68040
|
-
}
|
|
68041
|
-
|
|
68042
|
-
// ../../node_modules/@date-fns/tz/date/index.js
|
|
68043
|
-
var TZDate = class _TZDate extends TZDateMini {
|
|
68044
|
-
//#region static
|
|
68045
|
-
static tz(tz, ...args) {
|
|
68046
|
-
return args.length ? new _TZDate(...args, tz) : new _TZDate(Date.now(), tz);
|
|
68047
|
-
}
|
|
68048
|
-
//#endregion
|
|
68049
|
-
//#region representation
|
|
68050
|
-
toISOString() {
|
|
68051
|
-
const [sign, hours, minutes] = this.tzComponents();
|
|
68052
|
-
const tz = `${sign}${hours}:${minutes}`;
|
|
68053
|
-
return this.internal.toISOString().slice(0, -1) + tz;
|
|
68054
|
-
}
|
|
68055
|
-
toString() {
|
|
68056
|
-
return `${this.toDateString()} ${this.toTimeString()}`;
|
|
68057
|
-
}
|
|
68058
|
-
toDateString() {
|
|
68059
|
-
const [day, date6, month, year] = this.internal.toUTCString().split(" ");
|
|
68060
|
-
return `${day?.slice(0, -1)} ${month} ${date6} ${year}`;
|
|
68061
|
-
}
|
|
68062
|
-
toTimeString() {
|
|
68063
|
-
const time3 = this.internal.toUTCString().split(" ")[4];
|
|
68064
|
-
const [sign, hours, minutes] = this.tzComponents();
|
|
68065
|
-
return `${time3} GMT${sign}${hours}${minutes} (${tzName(this.timeZone, this)})`;
|
|
68066
|
-
}
|
|
68067
|
-
toLocaleString(locales, options) {
|
|
68068
|
-
return Date.prototype.toLocaleString.call(this, locales, {
|
|
68069
|
-
...options,
|
|
68070
|
-
timeZone: options?.timeZone || this.timeZone
|
|
68071
|
-
});
|
|
68072
|
-
}
|
|
68073
|
-
toLocaleDateString(locales, options) {
|
|
68074
|
-
return Date.prototype.toLocaleDateString.call(this, locales, {
|
|
68075
|
-
...options,
|
|
68076
|
-
timeZone: options?.timeZone || this.timeZone
|
|
68077
|
-
});
|
|
68078
|
-
}
|
|
68079
|
-
toLocaleTimeString(locales, options) {
|
|
68080
|
-
return Date.prototype.toLocaleTimeString.call(this, locales, {
|
|
68081
|
-
...options,
|
|
68082
|
-
timeZone: options?.timeZone || this.timeZone
|
|
68083
|
-
});
|
|
68084
|
-
}
|
|
68085
|
-
//#endregion
|
|
68086
|
-
//#region private
|
|
68087
|
-
tzComponents() {
|
|
68088
|
-
const offset = this.getTimezoneOffset();
|
|
68089
|
-
const sign = offset > 0 ? "-" : "+";
|
|
68090
|
-
const hours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, "0");
|
|
68091
|
-
const minutes = String(Math.abs(offset) % 60).padStart(2, "0");
|
|
68092
|
-
return [sign, hours, minutes];
|
|
68093
|
-
}
|
|
68094
|
-
//#endregion
|
|
68095
|
-
withTimeZone(timeZone) {
|
|
68096
|
-
return new _TZDate(+this, timeZone);
|
|
68097
|
-
}
|
|
68098
|
-
//#region date-fns integration
|
|
68099
|
-
[/* @__PURE__ */ Symbol.for("constructDateFrom")](date6) {
|
|
68100
|
-
return new _TZDate(+new Date(date6), this.timeZone);
|
|
68101
|
-
}
|
|
68102
|
-
//#endregion
|
|
68103
|
-
};
|
|
68104
|
-
|
|
68105
68533
|
// ../shared/src/expression_date.ts
|
|
68106
68534
|
function hasTimezone(dateStr) {
|
|
68107
68535
|
return /[Zz]|[+-]\d{2}:\d{2}$/.test(dateStr);
|
|
@@ -72226,6 +72654,15 @@ ${tail}`)
|
|
|
72226
72654
|
});
|
|
72227
72655
|
}
|
|
72228
72656
|
var NPM_LOG_TAIL_BYTES = 8e3;
|
|
72657
|
+
async function runAppTypecheck(projectDir) {
|
|
72658
|
+
const pkg = JSON.parse(fs8.readFileSync(path9.join(projectDir, "package.json"), "utf-8"));
|
|
72659
|
+
if (!pkg.scripts?.typecheck) {
|
|
72660
|
+
warn("package.json has no `typecheck` script \u2014 the app's types were not checked.");
|
|
72661
|
+
return;
|
|
72662
|
+
}
|
|
72663
|
+
note("Typechecking...");
|
|
72664
|
+
await runNpm(["run", "typecheck"], projectDir);
|
|
72665
|
+
}
|
|
72229
72666
|
function npmInstallArgs(hasLockfile) {
|
|
72230
72667
|
return [hasLockfile ? "ci" : "install", "--ignore-scripts"];
|
|
72231
72668
|
}
|
|
@@ -73060,6 +73497,7 @@ async function appDeploy(client, args) {
|
|
|
73060
73497
|
The build will use whatever is on disk \u2014 run 'lotics app codegen' if this app is published.`
|
|
73061
73498
|
);
|
|
73062
73499
|
}
|
|
73500
|
+
await runAppTypecheck(projectDir);
|
|
73063
73501
|
note("Building...");
|
|
73064
73502
|
await runNpm(["run", "build"], projectDir);
|
|
73065
73503
|
const distDir = path9.join(projectDir, "dist");
|
|
@@ -73229,6 +73667,7 @@ async function appCheck(client, args = {}) {
|
|
|
73229
73667
|
const meta3 = readAppMeta(projectDir);
|
|
73230
73668
|
const app = await client.getApp(meta3.app_id);
|
|
73231
73669
|
assertProjectIsCurrent(meta3, app);
|
|
73670
|
+
writeAppDts(projectDir, { workflows: meta3.workflows, queries: meta3.queries, agents: meta3.agents });
|
|
73232
73671
|
const sourceText = readAppSourceText(projectDir);
|
|
73233
73672
|
const called = calledAppAliases(sourceText);
|
|
73234
73673
|
warnAboutDevLink(projectDir, "deploy");
|
|
@@ -73251,11 +73690,18 @@ async function appCheck(client, args = {}) {
|
|
|
73251
73690
|
const unportable = scanProjectForIds(projectDir);
|
|
73252
73691
|
reportPortabilityIds(unportable);
|
|
73253
73692
|
const bodiesFailing = await countFailingWorkflowBodies(client, projectDir, meta3);
|
|
73254
|
-
|
|
73693
|
+
let typesFailing = false;
|
|
73694
|
+
try {
|
|
73695
|
+
await runAppTypecheck(projectDir);
|
|
73696
|
+
} catch (err2) {
|
|
73697
|
+
console.error(err2 instanceof Error ? err2.message : String(err2));
|
|
73698
|
+
typesFailing = true;
|
|
73699
|
+
}
|
|
73700
|
+
if (!nothingPending(pending) || unportable.length > 0 || bodiesFailing > 0 || typesFailing) {
|
|
73255
73701
|
process.exit(1);
|
|
73256
73702
|
}
|
|
73257
73703
|
console.error(
|
|
73258
|
-
"Checked the app's bindings, capabilities, agent schemas, workflow bodies and id portability \u2014 nothing blocking."
|
|
73704
|
+
"Checked the app's types, bindings, capabilities, agent schemas, workflow bodies and id portability \u2014 nothing blocking."
|
|
73259
73705
|
);
|
|
73260
73706
|
}
|
|
73261
73707
|
async function countFailingWorkflowBodies(client, projectDir, meta3) {
|
|
@@ -74119,6 +74565,7 @@ async function appQuerySet(client, args) {
|
|
|
74119
74565
|
writeSynced(projectDir, "queries", alias, { content: querySha, live: querySha });
|
|
74120
74566
|
pushed.push(alias);
|
|
74121
74567
|
}
|
|
74568
|
+
writeAppDts(projectDir, { workflows: meta3.workflows, queries: meta3.queries, agents: meta3.agents });
|
|
74122
74569
|
console.error(
|
|
74123
74570
|
`Set ${pushed.length} quer${pushed.length === 1 ? "y" : "ies"} on ${meta3.app_id}: ${pushed.join(", ")}.`
|
|
74124
74571
|
);
|