@lotics/cli 0.157.0 → 0.163.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/AGENTS.md +2 -2
- package/dist/render_page.js +299 -30
- package/dist/src/cli.js +1461 -1899
- package/dist/src/client.d.ts +77 -330
- package/dist/src/client.js +48 -132
- package/docs/cli_reference.md +8 -6
- package/docs/knowledge_docs.md +5 -5
- package/package.json +1 -1
- package/dist/src/package_content_types.d.ts +0 -70
- package/dist/src/package_content_types.js +0 -12
package/dist/src/cli.js
CHANGED
|
@@ -26822,12 +26822,12 @@ var require_tokens = __commonJS({
|
|
|
26822
26822
|
});
|
|
26823
26823
|
}
|
|
26824
26824
|
exports2.assignCategoriesMapProp = assignCategoriesMapProp;
|
|
26825
|
-
function singleAssignCategoriesToksMap(
|
|
26826
|
-
utils_1.forEach(
|
|
26825
|
+
function singleAssignCategoriesToksMap(path14, nextNode) {
|
|
26826
|
+
utils_1.forEach(path14, function(pathNode) {
|
|
26827
26827
|
nextNode.categoryMatchesMap[pathNode.tokenTypeIdx] = true;
|
|
26828
26828
|
});
|
|
26829
26829
|
utils_1.forEach(nextNode.CATEGORIES, function(nextCategory) {
|
|
26830
|
-
var newPath =
|
|
26830
|
+
var newPath = path14.concat(nextNode);
|
|
26831
26831
|
if (!utils_1.contains(newPath, nextCategory)) {
|
|
26832
26832
|
singleAssignCategoriesToksMap(newPath, nextCategory);
|
|
26833
26833
|
}
|
|
@@ -28590,10 +28590,10 @@ var require_interpreter = __commonJS({
|
|
|
28590
28590
|
/** @class */
|
|
28591
28591
|
(function(_super) {
|
|
28592
28592
|
__extends(AbstractNextPossibleTokensWalker2, _super);
|
|
28593
|
-
function AbstractNextPossibleTokensWalker2(topProd,
|
|
28593
|
+
function AbstractNextPossibleTokensWalker2(topProd, path14) {
|
|
28594
28594
|
var _this = _super.call(this) || this;
|
|
28595
28595
|
_this.topProd = topProd;
|
|
28596
|
-
_this.path =
|
|
28596
|
+
_this.path = path14;
|
|
28597
28597
|
_this.possibleTokTypes = [];
|
|
28598
28598
|
_this.nextProductionName = "";
|
|
28599
28599
|
_this.nextProductionOccurrence = 0;
|
|
@@ -28647,9 +28647,9 @@ var require_interpreter = __commonJS({
|
|
|
28647
28647
|
/** @class */
|
|
28648
28648
|
(function(_super) {
|
|
28649
28649
|
__extends(NextAfterTokenWalker2, _super);
|
|
28650
|
-
function NextAfterTokenWalker2(topProd,
|
|
28651
|
-
var _this = _super.call(this, topProd,
|
|
28652
|
-
_this.path =
|
|
28650
|
+
function NextAfterTokenWalker2(topProd, path14) {
|
|
28651
|
+
var _this = _super.call(this, topProd, path14) || this;
|
|
28652
|
+
_this.path = path14;
|
|
28653
28653
|
_this.nextTerminalName = "";
|
|
28654
28654
|
_this.nextTerminalOccurrence = 0;
|
|
28655
28655
|
_this.nextTerminalName = _this.path.lastTok.name;
|
|
@@ -29346,10 +29346,10 @@ var require_lookahead = __commonJS({
|
|
|
29346
29346
|
}
|
|
29347
29347
|
return result;
|
|
29348
29348
|
}
|
|
29349
|
-
function pathToHashKeys(
|
|
29349
|
+
function pathToHashKeys(path14) {
|
|
29350
29350
|
var keys3 = [""];
|
|
29351
|
-
for (var i2 = 0; i2 <
|
|
29352
|
-
var tokType =
|
|
29351
|
+
for (var i2 = 0; i2 < path14.length; i2++) {
|
|
29352
|
+
var tokType = path14[i2];
|
|
29353
29353
|
var longerKeys = [];
|
|
29354
29354
|
for (var j = 0; j < keys3.length; j++) {
|
|
29355
29355
|
var currShorterKey = keys3[j];
|
|
@@ -29661,9 +29661,9 @@ var require_checks = __commonJS({
|
|
|
29661
29661
|
return errors2;
|
|
29662
29662
|
}
|
|
29663
29663
|
exports2.validateRuleIsOverridden = validateRuleIsOverridden;
|
|
29664
|
-
function validateNoLeftRecursion(topRule, currRule, errMsgProvider,
|
|
29665
|
-
if (
|
|
29666
|
-
|
|
29664
|
+
function validateNoLeftRecursion(topRule, currRule, errMsgProvider, path14) {
|
|
29665
|
+
if (path14 === void 0) {
|
|
29666
|
+
path14 = [];
|
|
29667
29667
|
}
|
|
29668
29668
|
var errors2 = [];
|
|
29669
29669
|
var nextNonTerminals = getFirstNoneTerminal(currRule.definition);
|
|
@@ -29676,15 +29676,15 @@ var require_checks = __commonJS({
|
|
|
29676
29676
|
errors2.push({
|
|
29677
29677
|
message: errMsgProvider.buildLeftRecursionError({
|
|
29678
29678
|
topLevelRule: topRule,
|
|
29679
|
-
leftRecursionPath:
|
|
29679
|
+
leftRecursionPath: path14
|
|
29680
29680
|
}),
|
|
29681
29681
|
type: parser_1.ParserDefinitionErrorType.LEFT_RECURSION,
|
|
29682
29682
|
ruleName
|
|
29683
29683
|
});
|
|
29684
29684
|
}
|
|
29685
|
-
var validNextSteps = utils2.difference(nextNonTerminals,
|
|
29685
|
+
var validNextSteps = utils2.difference(nextNonTerminals, path14.concat([topRule]));
|
|
29686
29686
|
var errorsFromNextSteps = utils2.map(validNextSteps, function(currRefRule) {
|
|
29687
|
-
var newPath = utils2.cloneArr(
|
|
29687
|
+
var newPath = utils2.cloneArr(path14);
|
|
29688
29688
|
newPath.push(currRefRule);
|
|
29689
29689
|
return validateNoLeftRecursion(topRule, currRefRule, errMsgProvider, newPath);
|
|
29690
29690
|
});
|
|
@@ -37293,8 +37293,8 @@ var require_utils4 = __commonJS({
|
|
|
37293
37293
|
var result = transform2[inputType][outputType](input);
|
|
37294
37294
|
return result;
|
|
37295
37295
|
};
|
|
37296
|
-
exports2.resolve = function(
|
|
37297
|
-
var parts =
|
|
37296
|
+
exports2.resolve = function(path14) {
|
|
37297
|
+
var parts = path14.split("/");
|
|
37298
37298
|
var result = [];
|
|
37299
37299
|
for (var index = 0; index < parts.length; index++) {
|
|
37300
37300
|
var part = parts[index];
|
|
@@ -43147,18 +43147,18 @@ var require_object = __commonJS({
|
|
|
43147
43147
|
var object2 = new ZipObject(name2, zipObjectContent, o);
|
|
43148
43148
|
this.files[name2] = object2;
|
|
43149
43149
|
};
|
|
43150
|
-
var parentFolder = function(
|
|
43151
|
-
if (
|
|
43152
|
-
|
|
43150
|
+
var parentFolder = function(path14) {
|
|
43151
|
+
if (path14.slice(-1) === "/") {
|
|
43152
|
+
path14 = path14.substring(0, path14.length - 1);
|
|
43153
43153
|
}
|
|
43154
|
-
var lastSlash =
|
|
43155
|
-
return lastSlash > 0 ?
|
|
43154
|
+
var lastSlash = path14.lastIndexOf("/");
|
|
43155
|
+
return lastSlash > 0 ? path14.substring(0, lastSlash) : "";
|
|
43156
43156
|
};
|
|
43157
|
-
var forceTrailingSlash = function(
|
|
43158
|
-
if (
|
|
43159
|
-
|
|
43157
|
+
var forceTrailingSlash = function(path14) {
|
|
43158
|
+
if (path14.slice(-1) !== "/") {
|
|
43159
|
+
path14 += "/";
|
|
43160
43160
|
}
|
|
43161
|
-
return
|
|
43161
|
+
return path14;
|
|
43162
43162
|
};
|
|
43163
43163
|
var folderAdd = function(name2, createFolders) {
|
|
43164
43164
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults2.createFolders;
|
|
@@ -44160,9 +44160,9 @@ var require_lib4 = __commonJS({
|
|
|
44160
44160
|
// src/cli.ts
|
|
44161
44161
|
import dns from "node:dns";
|
|
44162
44162
|
import net2 from "node:net";
|
|
44163
|
-
import
|
|
44163
|
+
import fs14 from "node:fs";
|
|
44164
44164
|
import os4 from "node:os";
|
|
44165
|
-
import
|
|
44165
|
+
import path13 from "node:path";
|
|
44166
44166
|
import readline from "node:readline";
|
|
44167
44167
|
|
|
44168
44168
|
// ../shared/src/transport_error.ts
|
|
@@ -44177,7 +44177,9 @@ function gatewayErrorMessage(status) {
|
|
|
44177
44177
|
}
|
|
44178
44178
|
function transportErrorMessage(status, parsed) {
|
|
44179
44179
|
const jsonMessage = parsed && typeof parsed.message === "string" ? parsed.message : null;
|
|
44180
|
-
|
|
44180
|
+
if (jsonMessage === null) return gatewayErrorMessage(status);
|
|
44181
|
+
const authored = typeof parsed.code === "string" && parsed.code.length > 0;
|
|
44182
|
+
return status < 500 || authored ? jsonMessage : gatewayErrorMessage(status);
|
|
44181
44183
|
}
|
|
44182
44184
|
|
|
44183
44185
|
// src/client.ts
|
|
@@ -44356,8 +44358,8 @@ var LoticsClient = class {
|
|
|
44356
44358
|
}
|
|
44357
44359
|
return headers;
|
|
44358
44360
|
}
|
|
44359
|
-
async request(method,
|
|
44360
|
-
const url2 = `${this.baseUrl}${
|
|
44361
|
+
async request(method, path14, body) {
|
|
44362
|
+
const url2 = `${this.baseUrl}${path14}`;
|
|
44361
44363
|
const headers = this.buildHeaders();
|
|
44362
44364
|
const init = { method, headers };
|
|
44363
44365
|
if (body !== void 0) {
|
|
@@ -44400,8 +44402,8 @@ var LoticsClient = class {
|
|
|
44400
44402
|
async deleteWorkspace(id) {
|
|
44401
44403
|
return this.request("DELETE", `/v1/workspaces/${encodeURIComponent(id)}`);
|
|
44402
44404
|
}
|
|
44403
|
-
async login() {
|
|
44404
|
-
return this.request("POST", "/v1/cli/login");
|
|
44405
|
+
async login(body) {
|
|
44406
|
+
return this.request("POST", "/v1/cli/login", body ?? {});
|
|
44405
44407
|
}
|
|
44406
44408
|
async listTools() {
|
|
44407
44409
|
return this.request("GET", "/v1/tools");
|
|
@@ -44468,90 +44470,6 @@ var LoticsClient = class {
|
|
|
44468
44470
|
async createApp(body) {
|
|
44469
44471
|
return this.request("POST", "/v1/apps", body);
|
|
44470
44472
|
}
|
|
44471
|
-
/**
|
|
44472
|
-
* Install a package version into the current workspace — ONE endpoint,
|
|
44473
|
-
* kind-branched into a discriminated response (`kind`). An `app` package
|
|
44474
|
-
* scaffolds the data model / deploys / materializes and returns the installation
|
|
44475
|
-
* app (+ advisory knowledge warnings); a `content` package installs only its
|
|
44476
|
-
* doc corpus and returns the installation row. `bind_to` (content only)
|
|
44477
|
-
* resolves a name collision by adopting an existing same-named doc as
|
|
44478
|
-
* package-managed. `version` omitted installs the latest published version.
|
|
44479
|
-
*/
|
|
44480
|
-
async installPackage(package_id, body) {
|
|
44481
|
-
return this.request(
|
|
44482
|
-
"POST",
|
|
44483
|
-
`/v1/packages/${encodeURIComponent(package_id)}/installations`,
|
|
44484
|
-
body
|
|
44485
|
-
);
|
|
44486
|
-
}
|
|
44487
|
-
/**
|
|
44488
|
-
* Uninstall a standalone content package — delete the installation row. By
|
|
44489
|
-
* default the package-bound docs are ARCHIVED; `keep_content` retains them as
|
|
44490
|
-
* ordinary workspace docs. Admin-only. Backs `opctl uninstall`.
|
|
44491
|
-
*/
|
|
44492
|
-
async uninstallContentPackage(installation_id, opts = {}) {
|
|
44493
|
-
const qs = opts.keep_content ? "?keep_content=true" : "";
|
|
44494
|
-
return this.request(
|
|
44495
|
-
"DELETE",
|
|
44496
|
-
`/v1/content-installations/${encodeURIComponent(installation_id)}${qs}`
|
|
44497
|
-
);
|
|
44498
|
-
}
|
|
44499
|
-
/**
|
|
44500
|
-
* Preview upgrading a standalone content installation — the knowledge namespace's
|
|
44501
|
-
* per-alias `entries` (added/changed/removed/drifted + a `modified` flag) plus the
|
|
44502
|
-
* consent-requiring `templates` (a template the target changed whose live content
|
|
44503
|
-
* was locally edited; a clean one auto-updates and is absent). No writes.
|
|
44504
|
-
* Admin-only.
|
|
44505
|
-
*/
|
|
44506
|
-
async previewContentInstallationUpgrade(installation_id, opts = {}) {
|
|
44507
|
-
const qs = opts.version !== void 0 ? `?version=${opts.version}` : "";
|
|
44508
|
-
return this.request(
|
|
44509
|
-
"GET",
|
|
44510
|
-
`/v1/content-installations/${encodeURIComponent(installation_id)}/upgrade${qs}`
|
|
44511
|
-
);
|
|
44512
|
-
}
|
|
44513
|
-
/**
|
|
44514
|
-
* Apply a standalone content upgrade — propagate the target version's content per
|
|
44515
|
-
* the resolutions (`knowledge`: a modified change/removal or drift needs consent;
|
|
44516
|
-
* `templates`: a locally-edited changed template takes revert|keep), then advance
|
|
44517
|
-
* the pin + binding. Returns the updated installation row. Admin-only.
|
|
44518
|
-
*/
|
|
44519
|
-
async applyContentInstallationUpgrade(installation_id, body) {
|
|
44520
|
-
return this.request(
|
|
44521
|
-
"POST",
|
|
44522
|
-
`/v1/content-installations/${encodeURIComponent(installation_id)}/upgrade`,
|
|
44523
|
-
body
|
|
44524
|
-
);
|
|
44525
|
-
}
|
|
44526
|
-
/**
|
|
44527
|
-
* List a workspace's package-managed knowledge installations, each folded with
|
|
44528
|
-
* registry status (name, kind, official badge, latest version, update-available).
|
|
44529
|
-
* Member-accessible (workspace-scoped); backs the settings "Managed by" badge.
|
|
44530
|
-
*/
|
|
44531
|
-
async listContentInstallations(workspace_id) {
|
|
44532
|
-
return this.request(
|
|
44533
|
-
"GET",
|
|
44534
|
-
`/v1/workspaces/${encodeURIComponent(workspace_id)}/content-installations`
|
|
44535
|
-
);
|
|
44536
|
-
}
|
|
44537
|
-
/**
|
|
44538
|
-
* Uninstall a package installation (backs `opctl uninstall`). Does
|
|
44539
|
-
* everything DELETE does plus archives the installation's lifecycle
|
|
44540
|
-
* artifacts; with `archive_tables` it also archives the scaffolded entity
|
|
44541
|
-
* tables — refused server-side unless this installation created them
|
|
44542
|
-
* (provenance) and nothing else references them. Admin-only.
|
|
44543
|
-
*/
|
|
44544
|
-
async uninstallAppPackage(app_id, body) {
|
|
44545
|
-
return this.request("POST", `/v1/apps/${encodeURIComponent(app_id)}/uninstall`, body);
|
|
44546
|
-
}
|
|
44547
|
-
/**
|
|
44548
|
-
* Partial-merge a package installation's config (backs `opctl package config
|
|
44549
|
-
* --set`). Only the provided keys change; validated against the installed
|
|
44550
|
-
* contract. Returns the full effective config. Admin-only.
|
|
44551
|
-
*/
|
|
44552
|
-
async updateAppPackageConfig(app_id, body) {
|
|
44553
|
-
return this.request("PATCH", `/v1/apps/${encodeURIComponent(app_id)}/package-config`, body);
|
|
44554
|
-
}
|
|
44555
44473
|
/**
|
|
44556
44474
|
* Retire (or `undo` un-retire) a registry package (backs `lotics app
|
|
44557
44475
|
* unpublish` — the endpoint/audit action keep the `retire` name to avoid API
|
|
@@ -44562,83 +44480,75 @@ var LoticsClient = class {
|
|
|
44562
44480
|
async retirePackage(package_id, body) {
|
|
44563
44481
|
return this.request("POST", `/v1/packages/${encodeURIComponent(package_id)}/retire`, body);
|
|
44564
44482
|
}
|
|
44483
|
+
// --- Packages (registry reads + installations) ---
|
|
44484
|
+
// Authoring is server-side: apps via `POST /v1/apps/{id}/package-publish|release`,
|
|
44485
|
+
// content packages via the `publish_content`/`release_content` tools. There is no
|
|
44486
|
+
// client-side create-package / upload-bundle path.
|
|
44565
44487
|
/**
|
|
44566
|
-
*
|
|
44567
|
-
*
|
|
44568
|
-
*
|
|
44569
|
-
* app becomes a normal bespoke app and can no longer be upgraded. Returns the
|
|
44570
|
-
* resulting app.
|
|
44488
|
+
* The starters this organization can copy — Lotics-reviewed ones plus its own,
|
|
44489
|
+
* never a catalogue of everything published. The server returns exactly what
|
|
44490
|
+
* instantiate would accept, so the list cannot offer a refusal. Admin-only.
|
|
44571
44491
|
*/
|
|
44572
|
-
async
|
|
44573
|
-
return this.request("
|
|
44492
|
+
async listStarters() {
|
|
44493
|
+
return this.request("GET", "/v1/starters");
|
|
44574
44494
|
}
|
|
44575
44495
|
/**
|
|
44576
|
-
*
|
|
44577
|
-
*
|
|
44578
|
-
*
|
|
44579
|
-
*
|
|
44580
|
-
*
|
|
44581
|
-
*
|
|
44582
|
-
|
|
44583
|
-
|
|
44584
|
-
* Yank / unyank a published package version — refuses NEW installs/upgrades/
|
|
44585
|
-
* adopts targeting it; pinned installations keep running. Owner-org
|
|
44586
|
-
* admin-only. Backs `opctl package yank`.
|
|
44496
|
+
* Copy a starter into the current workspace.
|
|
44497
|
+
*
|
|
44498
|
+
* Server-side this scaffolds the schema, creates the templates, docs and
|
|
44499
|
+
* sample records, creates a BESPOKE app and materializes onto it — then stops.
|
|
44500
|
+
* It deploys nothing: a starter ships source only, and the source has to be
|
|
44501
|
+
* built where codegen can bake THIS workspace's field ids. `bundle_url` is a
|
|
44502
|
+
* presigned GET of that source, and finishing the job is the caller's half.
|
|
44503
|
+
* Admin-only.
|
|
44587
44504
|
*/
|
|
44588
|
-
async
|
|
44505
|
+
async instantiateStarter(starter_id, body) {
|
|
44589
44506
|
return this.request(
|
|
44590
44507
|
"POST",
|
|
44591
|
-
`/v1/
|
|
44592
|
-
{ yanked }
|
|
44593
|
-
);
|
|
44594
|
-
}
|
|
44595
|
-
async fleetUpgradePackage(package_id, body) {
|
|
44596
|
-
return this.request(
|
|
44597
|
-
"POST",
|
|
44598
|
-
`/v1/packages/${encodeURIComponent(package_id)}/fleet-upgrade`,
|
|
44508
|
+
`/v1/starters/${encodeURIComponent(starter_id)}/instantiate`,
|
|
44599
44509
|
body
|
|
44600
44510
|
);
|
|
44601
44511
|
}
|
|
44602
|
-
// --- Packages (registry reads + installations) ---
|
|
44603
|
-
// Authoring is server-side: apps via `POST /v1/apps/{id}/package-publish|release`,
|
|
44604
|
-
// content packages via the `publish_content`/`release_content` tools. There is no
|
|
44605
|
-
// client-side create-package / upload-bundle path.
|
|
44606
44512
|
/**
|
|
44607
|
-
*
|
|
44608
|
-
*
|
|
44513
|
+
* Which starter this app is the origin of. 404 when it has published none.
|
|
44514
|
+
*
|
|
44515
|
+
* The app row carries no pin, so this is the only app→starter direction there
|
|
44516
|
+
* is — provenance lives on the published version. Admin-only.
|
|
44609
44517
|
*/
|
|
44610
|
-
async
|
|
44611
|
-
return this.request("GET", `/v1/
|
|
44612
|
-
}
|
|
44613
|
-
/** Version history newest-first (no contract payloads) — backs `opctl package show`. Admin-only. */
|
|
44614
|
-
async listPackageVersions(package_id) {
|
|
44615
|
-
return this.request("GET", `/v1/packages/${encodeURIComponent(package_id)}/versions`);
|
|
44518
|
+
async getAppOriginStarter(app_id) {
|
|
44519
|
+
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/origin-starter`);
|
|
44616
44520
|
}
|
|
44617
44521
|
/**
|
|
44618
|
-
*
|
|
44619
|
-
*
|
|
44620
|
-
*
|
|
44621
|
-
*
|
|
44622
|
-
*
|
|
44522
|
+
* Capture live records from this workspace as a starter's sample data.
|
|
44523
|
+
*
|
|
44524
|
+
* The alias-keyed shape is produced SERVER-side, because the contract alias
|
|
44525
|
+
* space is minted by extract and exists nowhere a project can read it. Pure
|
|
44526
|
+
* read — the caller writes the returned files into the project and reviews
|
|
44527
|
+
* them, which matters: these rows are copied verbatim into every workspace
|
|
44528
|
+
* that takes the starter. Admin-only.
|
|
44623
44529
|
*/
|
|
44624
|
-
async
|
|
44530
|
+
async captureStarterFixtures(app_id, opts = {}) {
|
|
44531
|
+
const params = new URLSearchParams();
|
|
44532
|
+
if (opts.entities !== void 0 && opts.entities.length > 0) {
|
|
44533
|
+
params.set("entities", opts.entities.join(","));
|
|
44534
|
+
}
|
|
44535
|
+
if (opts.limit !== void 0) params.set("limit", String(opts.limit));
|
|
44536
|
+
const qs = params.toString();
|
|
44625
44537
|
return this.request(
|
|
44626
|
-
"
|
|
44627
|
-
`/v1/apps/${encodeURIComponent(app_id)}/
|
|
44628
|
-
body
|
|
44538
|
+
"GET",
|
|
44539
|
+
`/v1/apps/${encodeURIComponent(app_id)}/fixtures-capture${qs ? `?${qs}` : ""}`
|
|
44629
44540
|
);
|
|
44630
44541
|
}
|
|
44631
44542
|
/**
|
|
44632
|
-
*
|
|
44633
|
-
*
|
|
44634
|
-
* report — with no writes. Admin-only.
|
|
44543
|
+
* Fetch a registry starter's metadata (`latest_version` and the Lotics-backed
|
|
44544
|
+
* `is_official` trust badge). Admin-only; cross-tenant by id.
|
|
44635
44545
|
*/
|
|
44636
|
-
async
|
|
44637
|
-
|
|
44638
|
-
|
|
44639
|
-
|
|
44640
|
-
|
|
44641
|
-
);
|
|
44546
|
+
async getPackage(package_id) {
|
|
44547
|
+
return this.request("GET", `/v1/packages/${encodeURIComponent(package_id)}`);
|
|
44548
|
+
}
|
|
44549
|
+
/** Version history newest-first (no contract payloads) — backs `opctl package show`. Admin-only. */
|
|
44550
|
+
async listPackageVersions(package_id) {
|
|
44551
|
+
return this.request("GET", `/v1/packages/${encodeURIComponent(package_id)}/versions`);
|
|
44642
44552
|
}
|
|
44643
44553
|
/**
|
|
44644
44554
|
* Workspace-wide dangling-reference sweep — active app/workflow artifacts
|
|
@@ -44648,14 +44558,6 @@ var LoticsClient = class {
|
|
|
44648
44558
|
async getWorkspaceDanglingReferences() {
|
|
44649
44559
|
return this.request("GET", "/v1/workspaces/dangling-references");
|
|
44650
44560
|
}
|
|
44651
|
-
/**
|
|
44652
|
-
* Health check for a package installation — version pin vs. registry latest,
|
|
44653
|
-
* binding drift, and locally modified core artifacts. Read-only; backs
|
|
44654
|
-
* `opctl package doctor`. Admin-only.
|
|
44655
|
-
*/
|
|
44656
|
-
async getPackageHealth(app_id) {
|
|
44657
|
-
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/package-health`);
|
|
44658
|
-
}
|
|
44659
44561
|
/**
|
|
44660
44562
|
* Preview a release — the dry run behind `opctl app release`. Runs the
|
|
44661
44563
|
* binding-aware extract of the origin (aliases stable through the app's current
|
|
@@ -44671,9 +44573,6 @@ var LoticsClient = class {
|
|
|
44671
44573
|
if (opts.knowledge !== void 0 && opts.knowledge.length > 0) {
|
|
44672
44574
|
params.set("knowledge", JSON.stringify(opts.knowledge));
|
|
44673
44575
|
}
|
|
44674
|
-
if (opts.config !== void 0) {
|
|
44675
|
-
params.set("config", JSON.stringify(opts.config));
|
|
44676
|
-
}
|
|
44677
44576
|
const query = params.toString();
|
|
44678
44577
|
return this.request(
|
|
44679
44578
|
"GET",
|
|
@@ -44706,9 +44605,6 @@ var LoticsClient = class {
|
|
|
44706
44605
|
if (opts.knowledge !== void 0 && opts.knowledge.length > 0) {
|
|
44707
44606
|
params.set("knowledge", JSON.stringify(opts.knowledge));
|
|
44708
44607
|
}
|
|
44709
|
-
if (opts.config !== void 0 && opts.config.length > 0) {
|
|
44710
|
-
params.set("config", JSON.stringify(opts.config));
|
|
44711
|
-
}
|
|
44712
44608
|
if (opts.renames !== void 0 && opts.renames.length > 0) {
|
|
44713
44609
|
params.set("renames", JSON.stringify(opts.renames));
|
|
44714
44610
|
}
|
|
@@ -44812,10 +44708,6 @@ var LoticsClient = class {
|
|
|
44812
44708
|
const qs = group_id ? `?group_id=${encodeURIComponent(group_id)}` : "";
|
|
44813
44709
|
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/members${qs}`);
|
|
44814
44710
|
}
|
|
44815
|
-
/** A package installation's alias→id maps (fields/options/roles) — the app's runtime F/OPT resolution. */
|
|
44816
|
-
async appBinding(app_id) {
|
|
44817
|
-
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/binding`);
|
|
44818
|
-
}
|
|
44819
44711
|
/**
|
|
44820
44712
|
* Resolve the full option set (key, label, color) of a named query's select
|
|
44821
44713
|
* columns — the picker companion to `appQuery`. Mirrors
|
|
@@ -45955,12 +45847,23 @@ var COMMANDS = [
|
|
|
45955
45847
|
]
|
|
45956
45848
|
},
|
|
45957
45849
|
{
|
|
45958
|
-
verbs: ["
|
|
45959
|
-
help: [
|
|
45960
|
-
|
|
45961
|
-
|
|
45962
|
-
|
|
45963
|
-
|
|
45850
|
+
verbs: ["starter"],
|
|
45851
|
+
help: [
|
|
45852
|
+
" lotics starter list Starters you can copy into this workspace",
|
|
45853
|
+
" lotics starter show <starter_id> What one carries: tables, docs, templates, sample data",
|
|
45854
|
+
" lotics starter init <starter_id> [path]",
|
|
45855
|
+
" Copy it in \u2014 schema, templates, knowledge docs,",
|
|
45856
|
+
" sample records and an editable app project. A COPY:",
|
|
45857
|
+
" everything it creates is yours outright, with no",
|
|
45858
|
+
" link back and nothing to upgrade. Builds and deploys",
|
|
45859
|
+
" locally, so it needs node + a few minutes.",
|
|
45860
|
+
" --no-sample-data skips the sample records;",
|
|
45861
|
+
" --adopt allows a workspace that is not empty",
|
|
45862
|
+
" lotics starter fixtures capture --entity <alias> --limit <n>",
|
|
45863
|
+
" (authoring) Write reviewable sample records into the",
|
|
45864
|
+
" app project. READ WHAT IT WROTE before committing \u2014",
|
|
45865
|
+
" these rows ship to everyone who copies the starter"
|
|
45866
|
+
]
|
|
45964
45867
|
},
|
|
45965
45868
|
{
|
|
45966
45869
|
verbs: ["docs"],
|
|
@@ -46063,6 +45966,7 @@ var COMMANDS = [
|
|
|
46063
45966
|
},
|
|
46064
45967
|
{
|
|
46065
45968
|
verbs: ["xlsx"],
|
|
45969
|
+
ownsTail: true,
|
|
46066
45970
|
help: [
|
|
46067
45971
|
" lotics xlsx <subcommand> ... Read/write/edit .xlsx files on your local filesystem",
|
|
46068
45972
|
" (uses the bundled Lotics xlsx engine; prefer over",
|
|
@@ -46071,6 +45975,7 @@ var COMMANDS = [
|
|
|
46071
45975
|
},
|
|
46072
45976
|
{
|
|
46073
45977
|
verbs: ["docx"],
|
|
45978
|
+
ownsTail: true,
|
|
46074
45979
|
help: [
|
|
46075
45980
|
" lotics docx <subcommand> ... Read/write/edit .docx files on your local filesystem",
|
|
46076
45981
|
" (uses the bundled Lotics OOXML engine; preserves",
|
|
@@ -46102,6 +46007,32 @@ function renderCommandsHelp() {
|
|
|
46102
46007
|
function knownVerbs() {
|
|
46103
46008
|
return new Set(COMMANDS.flatMap((group) => [...group.verbs, ...group.aliases ?? []]));
|
|
46104
46009
|
}
|
|
46010
|
+
var SUBCOMMAND_ARGS = /* @__PURE__ */ new Map([
|
|
46011
|
+
["xlsx read", { valueFlags: ["--sheet", "--range"], flags: ["--with-format"] }],
|
|
46012
|
+
["xlsx set-cell", { content: true }],
|
|
46013
|
+
["docx read", { flags: ["--include-opaque"] }],
|
|
46014
|
+
["docx append-paragraph", { flags: ["--style="], content: true }],
|
|
46015
|
+
["docx insert-paragraph", { flags: ["--style=", "--at="], content: true }],
|
|
46016
|
+
["docx delete-block", { flags: ["--at="] }],
|
|
46017
|
+
["docx replace-text", { content: true }]
|
|
46018
|
+
]);
|
|
46019
|
+
function commandOwnsTail(command) {
|
|
46020
|
+
if (command === void 0) return false;
|
|
46021
|
+
return COMMANDS.some(
|
|
46022
|
+
(group) => group.ownsTail === true && [...group.verbs, ...group.aliases ?? []].includes(command)
|
|
46023
|
+
);
|
|
46024
|
+
}
|
|
46025
|
+
function subcommandArgs(command, subcommand) {
|
|
46026
|
+
if (command === void 0 || subcommand === void 0) return void 0;
|
|
46027
|
+
return SUBCOMMAND_ARGS.get(`${command} ${subcommand}`);
|
|
46028
|
+
}
|
|
46029
|
+
function knownSubcommandFlags(command, subcommand) {
|
|
46030
|
+
const spec = subcommandArgs(command, subcommand);
|
|
46031
|
+
return [...spec?.valueFlags ?? [], ...spec?.flags ?? []];
|
|
46032
|
+
}
|
|
46033
|
+
function matchesKnownFlag(known, arg) {
|
|
46034
|
+
return known.some((k) => k.endsWith("=") ? arg.startsWith(k) : arg === k);
|
|
46035
|
+
}
|
|
46105
46036
|
|
|
46106
46037
|
// src/report_command.ts
|
|
46107
46038
|
import fs6 from "node:fs";
|
|
@@ -46214,36 +46145,10 @@ import { tmpdir } from "node:os";
|
|
|
46214
46145
|
// src/starter_template.ts
|
|
46215
46146
|
var STARTER_REACT_NATIVE_VERSION = "0.85.3";
|
|
46216
46147
|
var VITEST_SETUP_FILENAME = "vitest.setup.ts";
|
|
46217
|
-
var VITEST_SETUP_CONTENT =
|
|
46218
|
-
|
|
46219
|
-
//
|
|
46220
|
-
|
|
46221
|
-
// a network call over the host bridge). Under vitest/jsdom there is no host, so
|
|
46222
|
-
// that call throws while a test is still COLLECTING \u2014 failing every test that
|
|
46223
|
-
// imports the app graph, even pure logic tests. getAppBinding is the network
|
|
46224
|
-
// boundary; mock it (and only it) so the module graph evaluates in tests.
|
|
46225
|
-
//
|
|
46226
|
-
// The stub returns an ECHO binding: any alias resolves to a synthetic,
|
|
46227
|
-
// self-identifying id (fld:test:<entity>.<field>, opt:test:\u2026, grp:test:\u2026). Echo,
|
|
46228
|
-
// not empty maps \u2014 app_fields's bound() throws on a missing key, so empty maps
|
|
46229
|
-
// would just re-break collection; and a ':test:' id can never be confused with a
|
|
46230
|
-
// real fld_\u2026/opt_\u2026/grp_\u2026 id, so a test that depends on a concrete binding fails
|
|
46231
|
-
// loud instead of silently reading undefined.
|
|
46232
|
-
vi.mock("@lotics/app-sdk", async (importOriginal) => {
|
|
46233
|
-
const actual = await importOriginal<typeof import("@lotics/app-sdk")>();
|
|
46234
|
-
const echoIds = (prefix: string): Record<string, string> =>
|
|
46235
|
-
new Proxy(
|
|
46236
|
-
{},
|
|
46237
|
-
{
|
|
46238
|
-
get: (_target, key) => (typeof key === "string" ? \`\${prefix}:test:\${key}\` : undefined),
|
|
46239
|
-
},
|
|
46240
|
-
) as Record<string, string>;
|
|
46241
|
-
return {
|
|
46242
|
-
...actual,
|
|
46243
|
-
getAppBinding: () =>
|
|
46244
|
-
Promise.resolve({ fields: echoIds("fld"), options: echoIds("opt"), roles: echoIds("grp") }),
|
|
46245
|
-
};
|
|
46246
|
-
});
|
|
46148
|
+
var VITEST_SETUP_CONTENT = `// Runs before every test file (wired by vite.config.ts \`test.setupFiles\`).
|
|
46149
|
+
// Empty by default \u2014 put global test setup here: custom matchers, a fetch stub,
|
|
46150
|
+
// timezone pinning, anything your suite needs before it collects.
|
|
46151
|
+
export {};
|
|
46247
46152
|
`;
|
|
46248
46153
|
function buildStarterTemplate(args) {
|
|
46249
46154
|
const uiVersion = args.ui_version;
|
|
@@ -46266,6 +46171,22 @@ function buildStarterTemplate(args) {
|
|
|
46266
46171
|
typecheck: "tsc --noEmit",
|
|
46267
46172
|
// Scope to src/ — oxlint's default scan walks node_modules too.
|
|
46268
46173
|
lint: "oxlint src",
|
|
46174
|
+
// No `--passWithNoTests`, deliberately. It would be justified by a
|
|
46175
|
+
// TEMPORARY condition ("the scaffold seeds nothing") and then ship
|
|
46176
|
+
// forever in every app's package.json and CI, where its only
|
|
46177
|
+
// remaining effect is to turn "vitest discovered no test files" into
|
|
46178
|
+
// success — a green suite over a renamed `src/`, a changed `include`
|
|
46179
|
+
// or a broken vitest config, indefinitely. A detector that cannot
|
|
46180
|
+
// fire when the thing is ABSENT rather than excessive is not one.
|
|
46181
|
+
//
|
|
46182
|
+
// What the scaffold seeds instead is `src/harness.test.ts`, which
|
|
46183
|
+
// asserts the HARNESS and nothing else. The file it replaces
|
|
46184
|
+
// (`src/App.test.tsx`) asserted the scaffold's placeholder copy
|
|
46185
|
+
// ("First item"), so it failed the moment the author did the very
|
|
46186
|
+
// thing the closing instructions tell them to do — edit
|
|
46187
|
+
// `src/App.tsx` — and a smoke test that renders `<App/>` would fail
|
|
46188
|
+
// the same way for any real app whose first screen reaches the host
|
|
46189
|
+
// bridge on mount. The harness test touches neither.
|
|
46269
46190
|
test: "vitest run"
|
|
46270
46191
|
},
|
|
46271
46192
|
dependencies: {
|
|
@@ -46472,7 +46393,7 @@ export default defineConfig({
|
|
|
46472
46393
|
},
|
|
46473
46394
|
test: {
|
|
46474
46395
|
environment: "jsdom",
|
|
46475
|
-
//
|
|
46396
|
+
// Global test setup, run before every test file (empty until an author fills it)
|
|
46476
46397
|
// collects. A package-linked app's generated .lotics/app_fields.ts awaits it
|
|
46477
46398
|
// at module load; without the stub that network call throws under jsdom and
|
|
46478
46399
|
// every test that imports the app graph fails to collect. See vitest.setup.ts.
|
|
@@ -46841,15 +46762,33 @@ declare module "*.css";
|
|
|
46841
46762
|
`
|
|
46842
46763
|
},
|
|
46843
46764
|
{
|
|
46844
|
-
path: "src/
|
|
46765
|
+
path: "src/harness.test.ts",
|
|
46845
46766
|
content: `import { describe, test, expect } from "vitest";
|
|
46846
|
-
import {
|
|
46847
|
-
|
|
46767
|
+
import { getAppBinding } from "@lotics/app-sdk";
|
|
46768
|
+
|
|
46769
|
+
/**
|
|
46770
|
+
* The one test the scaffold seeds, and it is about the TEST SETUP rather than
|
|
46771
|
+
* about your app \u2014 so editing src/App.tsx can never break it, and \`npm test\`
|
|
46772
|
+
* never has to be green over zero tests.
|
|
46773
|
+
*
|
|
46774
|
+
* What it pins: tests run under jsdom, and vitest.setup.ts's echo stub answers
|
|
46775
|
+
* for \`getAppBinding\`. That second one is the whole reason the setup file
|
|
46776
|
+
* exists: a package-linked app's generated .lotics/app_fields.ts awaits it while
|
|
46777
|
+
* a test file is still COLLECTING, so without the stub every test fails before
|
|
46778
|
+
* any of them runs \u2014 including pure logic tests that never touch a field id.
|
|
46779
|
+
*
|
|
46780
|
+
* Delete it once you have tests of your own, or keep it; it costs nothing.
|
|
46781
|
+
*/
|
|
46782
|
+
describe("test harness", () => {
|
|
46783
|
+
test("runs in a DOM", () => {
|
|
46784
|
+
expect(typeof document).toBe("object");
|
|
46785
|
+
});
|
|
46848
46786
|
|
|
46849
|
-
|
|
46850
|
-
|
|
46851
|
-
|
|
46852
|
-
|
|
46787
|
+
test("resolves the app binding from the setup stub, so the app graph collects", async () => {
|
|
46788
|
+
const binding = await getAppBinding();
|
|
46789
|
+
// The echo stub answers any alias with a self-identifying ':test:' id \u2014 one
|
|
46790
|
+
// that can never be mistaken for a real fld_\u2026 from the workspace.
|
|
46791
|
+
expect(binding.fields["anything.at.all"]).toContain(":test:");
|
|
46853
46792
|
});
|
|
46854
46793
|
});
|
|
46855
46794
|
`
|
|
@@ -46987,7 +46926,6 @@ var SUPPORTED_OPS = /* @__PURE__ */ new Set([
|
|
|
46987
46926
|
"workflow",
|
|
46988
46927
|
"members",
|
|
46989
46928
|
"context",
|
|
46990
|
-
"binding",
|
|
46991
46929
|
"upload_url",
|
|
46992
46930
|
"upload_complete",
|
|
46993
46931
|
"agentRuns",
|
|
@@ -47008,11 +46946,10 @@ async function dispatchRpc(client, body, opts) {
|
|
|
47008
46946
|
}
|
|
47009
46947
|
switch (body.op) {
|
|
47010
46948
|
case "context": {
|
|
47011
|
-
const
|
|
46949
|
+
const who = await client.whoami();
|
|
47012
46950
|
return {
|
|
47013
46951
|
member_id: who.member_id,
|
|
47014
|
-
comments_enabled: opts?.commentsEnabled ?? false
|
|
47015
|
-
config: app.config ?? {}
|
|
46952
|
+
comments_enabled: opts?.commentsEnabled ?? false
|
|
47016
46953
|
};
|
|
47017
46954
|
}
|
|
47018
46955
|
case "query": {
|
|
@@ -47048,8 +46985,6 @@ async function dispatchRpc(client, body, opts) {
|
|
|
47048
46985
|
const p = body.payload;
|
|
47049
46986
|
return client.appMembers(body.app_id, p?.group);
|
|
47050
46987
|
}
|
|
47051
|
-
case "binding":
|
|
47052
|
-
return client.appBinding(body.app_id);
|
|
47053
46988
|
case "upload_url": {
|
|
47054
46989
|
const p = body.payload;
|
|
47055
46990
|
if (!p || typeof p.filename !== "string" || typeof p.mime_type !== "string" || typeof p.file_size !== "number") {
|
|
@@ -48490,123 +48425,6 @@ export type AppOptions = typeof OPT;
|
|
|
48490
48425
|
`;
|
|
48491
48426
|
}
|
|
48492
48427
|
|
|
48493
|
-
// src/generate_package_fields.ts
|
|
48494
|
-
var HEADER2 = `// Auto-generated by 'lotics app codegen' and 'lotics app pull' (linked/published app).
|
|
48495
|
-
// DO NOT EDIT \u2014 regenerated from the installation's live binding.
|
|
48496
|
-
//
|
|
48497
|
-
// A package installation resolves F/OPT/ROLE at MODULE LOAD from its binding
|
|
48498
|
-
// (contract alias \u2192 THIS workspace's concrete id) via the SDK's \`binding\` RPC.
|
|
48499
|
-
// Top-level await: the module graph waits for the binding before any importer
|
|
48500
|
-
// evaluates, so every entry is a plain string.
|
|
48501
|
-
import { getAppBinding } from "@lotics/app-sdk";
|
|
48502
|
-
|
|
48503
|
-
const binding = await getAppBinding();
|
|
48504
|
-
|
|
48505
|
-
function bound(map: Record<string, string>, key: string, kind: string): string {
|
|
48506
|
-
const id = map[key];
|
|
48507
|
-
if (id === undefined) {
|
|
48508
|
-
throw new Error(
|
|
48509
|
-
\`app_fields: \${kind} "\${key}" is not in this installation's binding \u2014 \` +
|
|
48510
|
-
\`the generated app_fields.ts is stale relative to the installed contract version.\`,
|
|
48511
|
-
);
|
|
48512
|
-
}
|
|
48513
|
-
return id;
|
|
48514
|
-
}
|
|
48515
|
-
`;
|
|
48516
|
-
function parseBinding(binding) {
|
|
48517
|
-
const entities = [];
|
|
48518
|
-
const entityByAlias = /* @__PURE__ */ new Map();
|
|
48519
|
-
const fieldByKey = /* @__PURE__ */ new Map();
|
|
48520
|
-
for (const key of Object.keys(binding.fields)) {
|
|
48521
|
-
const dot = key.indexOf(".");
|
|
48522
|
-
if (dot <= 0 || dot >= key.length - 1) continue;
|
|
48523
|
-
const entityAlias = key.slice(0, dot);
|
|
48524
|
-
const fieldAlias = key.slice(dot + 1);
|
|
48525
|
-
let entity = entityByAlias.get(entityAlias);
|
|
48526
|
-
if (entity === void 0) {
|
|
48527
|
-
entity = { alias: entityAlias, fields: [] };
|
|
48528
|
-
entityByAlias.set(entityAlias, entity);
|
|
48529
|
-
entities.push(entity);
|
|
48530
|
-
}
|
|
48531
|
-
const field = { alias: fieldAlias, key, options: [] };
|
|
48532
|
-
entity.fields.push(field);
|
|
48533
|
-
fieldByKey.set(key, field);
|
|
48534
|
-
}
|
|
48535
|
-
for (const key of Object.keys(binding.options)) {
|
|
48536
|
-
const colon = key.indexOf(":");
|
|
48537
|
-
if (colon <= 0 || colon >= key.length - 1) continue;
|
|
48538
|
-
const fieldKey = key.slice(0, colon);
|
|
48539
|
-
const optionAlias = key.slice(colon + 1);
|
|
48540
|
-
const field = fieldByKey.get(fieldKey);
|
|
48541
|
-
if (field === void 0) continue;
|
|
48542
|
-
field.options.push({ alias: optionAlias, key });
|
|
48543
|
-
}
|
|
48544
|
-
return { entities, roles: Object.keys(binding.roles) };
|
|
48545
|
-
}
|
|
48546
|
-
function emitFieldMap2(entities) {
|
|
48547
|
-
if (entities.length === 0) return `export const F = {} as const;`;
|
|
48548
|
-
const blocks = entities.map((entity) => {
|
|
48549
|
-
const lines = entity.fields.map(
|
|
48550
|
-
(field) => ` ${propKey(field.alias)}: bound(binding.fields, ${JSON.stringify(field.key)}, "field"),`
|
|
48551
|
-
);
|
|
48552
|
-
return ` ${propKey(entity.alias.toUpperCase())}: {
|
|
48553
|
-
${lines.join("\n")}
|
|
48554
|
-
},`;
|
|
48555
|
-
});
|
|
48556
|
-
return `export const F = {
|
|
48557
|
-
${blocks.join("\n")}
|
|
48558
|
-
} as const;`;
|
|
48559
|
-
}
|
|
48560
|
-
function emitOptionMap2(entities) {
|
|
48561
|
-
const entityBlocks = [];
|
|
48562
|
-
for (const entity of entities) {
|
|
48563
|
-
const fieldBlocks = [];
|
|
48564
|
-
for (const field of entity.fields) {
|
|
48565
|
-
if (field.options.length === 0) continue;
|
|
48566
|
-
const lines = field.options.map(
|
|
48567
|
-
(option) => ` ${propKey(option.alias)}: bound(binding.options, ${JSON.stringify(option.key)}, "option"),`
|
|
48568
|
-
);
|
|
48569
|
-
fieldBlocks.push(` ${propKey(field.alias)}: {
|
|
48570
|
-
${lines.join("\n")}
|
|
48571
|
-
},`);
|
|
48572
|
-
}
|
|
48573
|
-
if (fieldBlocks.length === 0) continue;
|
|
48574
|
-
entityBlocks.push(` ${propKey(entity.alias.toUpperCase())}: {
|
|
48575
|
-
${fieldBlocks.join("\n")}
|
|
48576
|
-
},`);
|
|
48577
|
-
}
|
|
48578
|
-
if (entityBlocks.length === 0) return `export const OPT = {} as const;`;
|
|
48579
|
-
return `export const OPT = {
|
|
48580
|
-
${entityBlocks.join("\n")}
|
|
48581
|
-
} as const;`;
|
|
48582
|
-
}
|
|
48583
|
-
function emitRoleMap(roles) {
|
|
48584
|
-
if (roles.length === 0) return `export const ROLE = {} as const;`;
|
|
48585
|
-
const lines = roles.map(
|
|
48586
|
-
(role) => ` ${propKey(role)}: bound(binding.roles, ${JSON.stringify(role)}, "role"),`
|
|
48587
|
-
);
|
|
48588
|
-
return `export const ROLE = {
|
|
48589
|
-
${lines.join("\n")}
|
|
48590
|
-
} as const;`;
|
|
48591
|
-
}
|
|
48592
|
-
function generatePackageAppFields(binding) {
|
|
48593
|
-
const { entities, roles } = parseBinding(binding);
|
|
48594
|
-
return `${HEADER2}
|
|
48595
|
-
${emitFieldMap2(entities)}
|
|
48596
|
-
|
|
48597
|
-
${emitOptionMap2(entities)}
|
|
48598
|
-
|
|
48599
|
-
${emitRoleMap(roles)}
|
|
48600
|
-
|
|
48601
|
-
/** Field-id alias map: \`F[<ENTITY>][<field>]\` is this installation's \`fld_\u2026\` id. */
|
|
48602
|
-
export type AppFields = typeof F;
|
|
48603
|
-
/** Select-option alias map: \`OPT[<ENTITY>][<field>][<option>]\` is this installation's \`opt_\u2026\` id. */
|
|
48604
|
-
export type AppOptions = typeof OPT;
|
|
48605
|
-
/** Role alias map: \`ROLE[<role>]\` is this installation's \`grp_\u2026\` id. */
|
|
48606
|
-
export type AppRoles = typeof ROLE;
|
|
48607
|
-
`;
|
|
48608
|
-
}
|
|
48609
|
-
|
|
48610
48428
|
// src/app_workflow_check.ts
|
|
48611
48429
|
import fs7 from "node:fs";
|
|
48612
48430
|
import path9 from "node:path";
|
|
@@ -49381,10 +49199,10 @@ function mergeDefs(...defs) {
|
|
|
49381
49199
|
function cloneDef(schema) {
|
|
49382
49200
|
return mergeDefs(schema._zod.def);
|
|
49383
49201
|
}
|
|
49384
|
-
function getElementAtPath(obj,
|
|
49385
|
-
if (!
|
|
49202
|
+
function getElementAtPath(obj, path14) {
|
|
49203
|
+
if (!path14)
|
|
49386
49204
|
return obj;
|
|
49387
|
-
return
|
|
49205
|
+
return path14.reduce((acc, key) => acc?.[key], obj);
|
|
49388
49206
|
}
|
|
49389
49207
|
function promiseAllObject(promisesObj) {
|
|
49390
49208
|
const keys3 = Object.keys(promisesObj);
|
|
@@ -49793,11 +49611,11 @@ function explicitlyAborted(x2, startIndex = 0) {
|
|
|
49793
49611
|
}
|
|
49794
49612
|
return false;
|
|
49795
49613
|
}
|
|
49796
|
-
function prefixIssues(
|
|
49614
|
+
function prefixIssues(path14, issues) {
|
|
49797
49615
|
return issues.map((iss) => {
|
|
49798
49616
|
var _a4;
|
|
49799
49617
|
(_a4 = iss).path ?? (_a4.path = []);
|
|
49800
|
-
iss.path.unshift(
|
|
49618
|
+
iss.path.unshift(path14);
|
|
49801
49619
|
return iss;
|
|
49802
49620
|
});
|
|
49803
49621
|
}
|
|
@@ -49944,16 +49762,16 @@ function flattenError(error52, mapper = (issue2) => issue2.message) {
|
|
|
49944
49762
|
}
|
|
49945
49763
|
function formatError(error52, mapper = (issue2) => issue2.message) {
|
|
49946
49764
|
const fieldErrors = { _errors: [] };
|
|
49947
|
-
const processError = (error53,
|
|
49765
|
+
const processError = (error53, path14 = []) => {
|
|
49948
49766
|
for (const issue2 of error53.issues) {
|
|
49949
49767
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
49950
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
49768
|
+
issue2.errors.map((issues) => processError({ issues }, [...path14, ...issue2.path]));
|
|
49951
49769
|
} else if (issue2.code === "invalid_key") {
|
|
49952
|
-
processError({ issues: issue2.issues }, [...
|
|
49770
|
+
processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
|
|
49953
49771
|
} else if (issue2.code === "invalid_element") {
|
|
49954
|
-
processError({ issues: issue2.issues }, [...
|
|
49772
|
+
processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
|
|
49955
49773
|
} else {
|
|
49956
|
-
const fullpath = [...
|
|
49774
|
+
const fullpath = [...path14, ...issue2.path];
|
|
49957
49775
|
if (fullpath.length === 0) {
|
|
49958
49776
|
fieldErrors._errors.push(mapper(issue2));
|
|
49959
49777
|
} else {
|
|
@@ -49980,17 +49798,17 @@ function formatError(error52, mapper = (issue2) => issue2.message) {
|
|
|
49980
49798
|
}
|
|
49981
49799
|
function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
49982
49800
|
const result = { errors: [] };
|
|
49983
|
-
const processError = (error53,
|
|
49801
|
+
const processError = (error53, path14 = []) => {
|
|
49984
49802
|
var _a4, _b2;
|
|
49985
49803
|
for (const issue2 of error53.issues) {
|
|
49986
49804
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
49987
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
49805
|
+
issue2.errors.map((issues) => processError({ issues }, [...path14, ...issue2.path]));
|
|
49988
49806
|
} else if (issue2.code === "invalid_key") {
|
|
49989
|
-
processError({ issues: issue2.issues }, [...
|
|
49807
|
+
processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
|
|
49990
49808
|
} else if (issue2.code === "invalid_element") {
|
|
49991
|
-
processError({ issues: issue2.issues }, [...
|
|
49809
|
+
processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
|
|
49992
49810
|
} else {
|
|
49993
|
-
const fullpath = [...
|
|
49811
|
+
const fullpath = [...path14, ...issue2.path];
|
|
49994
49812
|
if (fullpath.length === 0) {
|
|
49995
49813
|
result.errors.push(mapper(issue2));
|
|
49996
49814
|
continue;
|
|
@@ -50022,8 +49840,8 @@ function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
|
50022
49840
|
}
|
|
50023
49841
|
function toDotPath(_path) {
|
|
50024
49842
|
const segs = [];
|
|
50025
|
-
const
|
|
50026
|
-
for (const seg of
|
|
49843
|
+
const path14 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
49844
|
+
for (const seg of path14) {
|
|
50027
49845
|
if (typeof seg === "number")
|
|
50028
49846
|
segs.push(`[${seg}]`);
|
|
50029
49847
|
else if (typeof seg === "symbol")
|
|
@@ -62715,13 +62533,13 @@ function resolveRef(ref2, ctx) {
|
|
|
62715
62533
|
if (!ref2.startsWith("#")) {
|
|
62716
62534
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
62717
62535
|
}
|
|
62718
|
-
const
|
|
62719
|
-
if (
|
|
62536
|
+
const path14 = ref2.slice(1).split("/").filter(Boolean);
|
|
62537
|
+
if (path14.length === 0) {
|
|
62720
62538
|
return ctx.rootSchema;
|
|
62721
62539
|
}
|
|
62722
62540
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
62723
|
-
if (
|
|
62724
|
-
const key =
|
|
62541
|
+
if (path14[0] === defsKey) {
|
|
62542
|
+
const key = path14[1];
|
|
62725
62543
|
if (!key || !ctx.defs[key]) {
|
|
62726
62544
|
throw new Error(`Reference not found: ${ref2}`);
|
|
62727
62545
|
}
|
|
@@ -65056,7 +64874,14 @@ var formulaAggregateOperationSchema = external_exports.enum([
|
|
|
65056
64874
|
"median",
|
|
65057
64875
|
"min",
|
|
65058
64876
|
"max",
|
|
65059
|
-
"range"
|
|
64877
|
+
"range",
|
|
64878
|
+
"earliest",
|
|
64879
|
+
"latest",
|
|
64880
|
+
"date_range",
|
|
64881
|
+
"checked",
|
|
64882
|
+
"unchecked",
|
|
64883
|
+
"percent_checked",
|
|
64884
|
+
"percent_unchecked"
|
|
65060
64885
|
]);
|
|
65061
64886
|
var rollupAggregateOperationSchema = external_exports.enum([
|
|
65062
64887
|
"empty",
|
|
@@ -65156,25 +64981,25 @@ var aggregateOperationSchema = external_exports.enum([
|
|
|
65156
64981
|
"string_agg"
|
|
65157
64982
|
]);
|
|
65158
64983
|
var OPERATION_FIELD_TYPES = {
|
|
65159
|
-
empty: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup"],
|
|
65160
|
-
filled: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup"],
|
|
65161
|
-
percent_empty: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup"],
|
|
65162
|
-
percent_filled: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup"],
|
|
65163
|
-
unique: ["text", "number", "date", "select", "select_member", "files", "formula", "rollup"],
|
|
65164
|
-
percent_unique: ["text", "number", "date", "select", "select_member", "files", "formula", "rollup"],
|
|
64984
|
+
empty: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup", "autonumber"],
|
|
64985
|
+
filled: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup", "autonumber"],
|
|
64986
|
+
percent_empty: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup", "autonumber"],
|
|
64987
|
+
percent_filled: ["text", "number", "date", "select", "select_member", "select_record_link", "files", "formula", "rollup", "autonumber"],
|
|
64988
|
+
unique: ["text", "number", "date", "select", "select_member", "files", "formula", "rollup", "autonumber"],
|
|
64989
|
+
percent_unique: ["text", "number", "date", "select", "select_member", "files", "formula", "rollup", "autonumber"],
|
|
65165
64990
|
sum: ["number", "formula", "rollup"],
|
|
65166
64991
|
avg: ["number", "formula", "rollup"],
|
|
65167
64992
|
median: ["number", "formula", "rollup"],
|
|
65168
64993
|
min: ["number", "formula", "rollup"],
|
|
65169
64994
|
max: ["number", "formula", "rollup"],
|
|
65170
64995
|
range: ["number", "formula", "rollup"],
|
|
65171
|
-
earliest: ["date", "rollup"],
|
|
65172
|
-
latest: ["date", "rollup"],
|
|
65173
|
-
date_range: ["date", "rollup"],
|
|
65174
|
-
checked: ["boolean"],
|
|
65175
|
-
unchecked: ["boolean"],
|
|
65176
|
-
percent_checked: ["boolean"],
|
|
65177
|
-
percent_unchecked: ["boolean"]
|
|
64996
|
+
earliest: ["date", "formula", "rollup"],
|
|
64997
|
+
latest: ["date", "formula", "rollup"],
|
|
64998
|
+
date_range: ["date", "formula", "rollup"],
|
|
64999
|
+
checked: ["boolean", "formula"],
|
|
65000
|
+
unchecked: ["boolean", "formula"],
|
|
65001
|
+
percent_checked: ["boolean", "formula"],
|
|
65002
|
+
percent_unchecked: ["boolean", "formula"]
|
|
65178
65003
|
};
|
|
65179
65004
|
var FIELD_TYPE_OPERATIONS = /* @__PURE__ */ new Map();
|
|
65180
65005
|
for (const [operation, fieldTypes] of Object.entries(OPERATION_FIELD_TYPES)) {
|
|
@@ -65854,8 +65679,7 @@ var appWorkflowInputRecordLinkSchema = appWorkflowInputBaseSchema.extend({
|
|
|
65854
65679
|
table_id: zod_default.string().describe("Records must belong to this table. Validated at execute time + workflow save."),
|
|
65855
65680
|
multi: zod_default.boolean().optional().describe("When true, accept an array of record_ids. Defaults to single.")
|
|
65856
65681
|
});
|
|
65857
|
-
var
|
|
65858
|
-
type: zod_default.literal("select"),
|
|
65682
|
+
var selectOptionSourceShape = {
|
|
65859
65683
|
options: zod_default.array(
|
|
65860
65684
|
zod_default.object({
|
|
65861
65685
|
label: zod_default.string(),
|
|
@@ -65863,20 +65687,27 @@ var appWorkflowInputSelectSchema = appWorkflowInputBaseSchema.extend({
|
|
|
65863
65687
|
})
|
|
65864
65688
|
).min(1).optional().describe("Inline option set. Provide EITHER `options` OR `field`, never both."),
|
|
65865
65689
|
field: zod_default.string().optional().describe(
|
|
65866
|
-
"A select field's key (fld_\u2026) whose CURRENT options back this
|
|
65690
|
+
"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."
|
|
65867
65691
|
),
|
|
65868
65692
|
multi: zod_default.boolean().optional()
|
|
65869
|
-
}
|
|
65870
|
-
|
|
65871
|
-
|
|
65872
|
-
|
|
65873
|
-
ctx.
|
|
65874
|
-
|
|
65875
|
-
|
|
65876
|
-
|
|
65877
|
-
|
|
65878
|
-
|
|
65879
|
-
});
|
|
65693
|
+
};
|
|
65694
|
+
function checkExactlyOneOptionSource(kind) {
|
|
65695
|
+
return (ctx) => {
|
|
65696
|
+
const hasOptions = ctx.value.options !== void 0;
|
|
65697
|
+
const hasField = ctx.value.field !== void 0;
|
|
65698
|
+
if (hasOptions === hasField) {
|
|
65699
|
+
ctx.issues.push({
|
|
65700
|
+
code: "custom",
|
|
65701
|
+
input: ctx.value,
|
|
65702
|
+
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`
|
|
65703
|
+
});
|
|
65704
|
+
}
|
|
65705
|
+
};
|
|
65706
|
+
}
|
|
65707
|
+
var appWorkflowInputSelectSchema = appWorkflowInputBaseSchema.extend({
|
|
65708
|
+
type: zod_default.literal("select"),
|
|
65709
|
+
...selectOptionSourceShape
|
|
65710
|
+
}).check(checkExactlyOneOptionSource("input"));
|
|
65880
65711
|
var appWorkflowInputDateRangeSchema = appWorkflowInputBaseSchema.extend({
|
|
65881
65712
|
type: zod_default.literal("date_range"),
|
|
65882
65713
|
include_time: zod_default.boolean().optional().describe("When true, the range includes time components (datetime). Defaults to false.")
|
|
@@ -65947,11 +65778,14 @@ var appWorkflowOutputSchema = zod_default.lazy(
|
|
|
65947
65778
|
table_id: zod_default.string(),
|
|
65948
65779
|
multi: zod_default.boolean().optional()
|
|
65949
65780
|
}),
|
|
65781
|
+
// The SAME shape and the SAME check as the select INPUT, not a copy of
|
|
65782
|
+
// them: the two surfaces declare one vocabulary (GAP-294), so accepting
|
|
65783
|
+
// `field` on one and not the other — or validating it differently — just
|
|
65784
|
+
// moves the drift somewhere nobody looks.
|
|
65950
65785
|
appWorkflowOutputBaseSchema.extend({
|
|
65951
65786
|
type: zod_default.literal("select"),
|
|
65952
|
-
|
|
65953
|
-
|
|
65954
|
-
}),
|
|
65787
|
+
...selectOptionSourceShape
|
|
65788
|
+
}).check(checkExactlyOneOptionSource("output")),
|
|
65955
65789
|
appWorkflowOutputBaseSchema.extend({
|
|
65956
65790
|
type: zod_default.literal("object"),
|
|
65957
65791
|
fields: zod_default.record(zod_default.string(), appWorkflowOutputSchema)
|
|
@@ -66073,15 +65907,21 @@ var appSchema = zod_default.object({
|
|
|
66073
65907
|
"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."
|
|
66074
65908
|
),
|
|
66075
65909
|
theme: appThemeSchema.nullable().optional().describe("Theme settings for the app"),
|
|
66076
|
-
|
|
66077
|
-
|
|
66078
|
-
|
|
66079
|
-
|
|
66080
|
-
|
|
66081
|
-
|
|
66082
|
-
|
|
66083
|
-
|
|
66084
|
-
|
|
65910
|
+
/**
|
|
65911
|
+
* The starter this app is the ORIGIN of, when it is one — list enrichment,
|
|
65912
|
+
* read from the registry rather than stored on the app.
|
|
65913
|
+
*
|
|
65914
|
+
* This is provenance in the only direction that exists under one-way copies:
|
|
65915
|
+
* an app can have PUBLISHED a starter, but an app that was COPIED FROM one
|
|
65916
|
+
* records nothing, because it owns everything it received outright. Null for
|
|
65917
|
+
* every app that has published nothing.
|
|
65918
|
+
*/
|
|
65919
|
+
starter_origin: zod_default.object({
|
|
65920
|
+
starter_id: zod_default.string(),
|
|
65921
|
+
/** The highest version published from this app. */
|
|
65922
|
+
version: zod_default.number().int(),
|
|
65923
|
+
is_official: zod_default.boolean()
|
|
65924
|
+
}).nullable().optional(),
|
|
66085
65925
|
created_at: zod_default.string().describe("Timestamp when app was created"),
|
|
66086
65926
|
updated_at: zod_default.string().describe("Timestamp of last update")
|
|
66087
65927
|
});
|
|
@@ -66315,7 +66155,6 @@ __export(expression_array_exports, {
|
|
|
66315
66155
|
includes: () => includes,
|
|
66316
66156
|
intersection: () => intersection2,
|
|
66317
66157
|
intersectionBy: () => intersectionBy,
|
|
66318
|
-
isEmpty: () => isEmpty2,
|
|
66319
66158
|
last: () => last2,
|
|
66320
66159
|
list: () => list,
|
|
66321
66160
|
maxBy: () => maxBy,
|
|
@@ -66770,13 +66609,6 @@ function size(arr) {
|
|
|
66770
66609
|
}
|
|
66771
66610
|
return arr.length;
|
|
66772
66611
|
}
|
|
66773
|
-
function isEmpty2(arr) {
|
|
66774
|
-
if (arr == null) return true;
|
|
66775
|
-
if (!Array.isArray(arr)) {
|
|
66776
|
-
throw new Error("isEmpty: expected array, got " + typeof arr);
|
|
66777
|
-
}
|
|
66778
|
-
return arr.length === 0;
|
|
66779
|
-
}
|
|
66780
66612
|
function includes(collection, value2) {
|
|
66781
66613
|
if (collection == null) return false;
|
|
66782
66614
|
if (Array.isArray(collection)) return collection.includes(value2);
|
|
@@ -67047,6 +66879,7 @@ function capitalize(str) {
|
|
|
67047
66879
|
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
67048
66880
|
}
|
|
67049
66881
|
function replace(str, search, replacement) {
|
|
66882
|
+
if (str == null) return "";
|
|
67050
66883
|
if (typeof str !== "string") {
|
|
67051
66884
|
throw new Error("replace: expected string, got " + typeof str);
|
|
67052
66885
|
}
|
|
@@ -67059,6 +66892,7 @@ function replace(str, search, replacement) {
|
|
|
67059
66892
|
return str.replace(search, replacement);
|
|
67060
66893
|
}
|
|
67061
66894
|
function replaceAll(str, search, replacement) {
|
|
66895
|
+
if (str == null) return "";
|
|
67062
66896
|
if (typeof str !== "string") {
|
|
67063
66897
|
throw new Error("replaceAll: expected string, got " + typeof str);
|
|
67064
66898
|
}
|
|
@@ -67091,6 +66925,7 @@ function endsWith(str, suffix) {
|
|
|
67091
66925
|
return str.endsWith(suffix);
|
|
67092
66926
|
}
|
|
67093
66927
|
function substring(str, start, end) {
|
|
66928
|
+
if (str == null) return "";
|
|
67094
66929
|
if (typeof str !== "string") {
|
|
67095
66930
|
throw new Error("substring: expected string, got " + typeof str);
|
|
67096
66931
|
}
|
|
@@ -67103,6 +66938,7 @@ function substring(str, start, end) {
|
|
|
67103
66938
|
return str.substring(start, end);
|
|
67104
66939
|
}
|
|
67105
66940
|
function padStart(str, length2, char) {
|
|
66941
|
+
if (str == null) return "";
|
|
67106
66942
|
if (typeof str !== "string") {
|
|
67107
66943
|
throw new Error("padStart: expected string, got " + typeof str);
|
|
67108
66944
|
}
|
|
@@ -67115,6 +66951,7 @@ function padStart(str, length2, char) {
|
|
|
67115
66951
|
return str.padStart(length2, char);
|
|
67116
66952
|
}
|
|
67117
66953
|
function padEnd(str, length2, char) {
|
|
66954
|
+
if (str == null) return "";
|
|
67118
66955
|
if (typeof str !== "string") {
|
|
67119
66956
|
throw new Error("padEnd: expected string, got " + typeof str);
|
|
67120
66957
|
}
|
|
@@ -67220,6 +67057,7 @@ function numberToWords(value2) {
|
|
|
67220
67057
|
return negative ? "\xE2m " + result : result;
|
|
67221
67058
|
}
|
|
67222
67059
|
function formatNumber(value2, decimals) {
|
|
67060
|
+
if (value2 == null) return "";
|
|
67223
67061
|
if (typeof value2 !== "number" || Number.isNaN(value2)) {
|
|
67224
67062
|
throw new Error("formatNumber: expected number, got " + typeof value2);
|
|
67225
67063
|
}
|
|
@@ -67247,15 +67085,17 @@ __export(expression_math_exports, {
|
|
|
67247
67085
|
sum: () => sum
|
|
67248
67086
|
});
|
|
67249
67087
|
function mean(arr) {
|
|
67250
|
-
if (arr == null
|
|
67088
|
+
if (arr == null) return null;
|
|
67089
|
+
if (!Array.isArray(arr)) {
|
|
67251
67090
|
throw new Error("mean: expected array, got " + typeof arr);
|
|
67252
67091
|
}
|
|
67253
|
-
|
|
67254
|
-
|
|
67092
|
+
const present = arr.filter((item) => item != null);
|
|
67093
|
+
if (present.length === 0) {
|
|
67094
|
+
return null;
|
|
67255
67095
|
}
|
|
67256
|
-
const numArr =
|
|
67257
|
-
const
|
|
67258
|
-
const result =
|
|
67096
|
+
const numArr = present;
|
|
67097
|
+
const total = numArr.reduce((a, b) => a + b, 0);
|
|
67098
|
+
const result = total / numArr.length;
|
|
67259
67099
|
if (isNaN(result)) {
|
|
67260
67100
|
throw new Error("mean: array contains non-numeric values");
|
|
67261
67101
|
}
|
|
@@ -67268,7 +67108,7 @@ function min(...values3) {
|
|
|
67268
67108
|
if (values3.length === 1 && Array.isArray(values3[0])) {
|
|
67269
67109
|
const arr = values3[0];
|
|
67270
67110
|
if (arr.length === 0) {
|
|
67271
|
-
|
|
67111
|
+
return null;
|
|
67272
67112
|
}
|
|
67273
67113
|
return arr.reduce((minVal, item) => {
|
|
67274
67114
|
if (minVal == null) return item;
|
|
@@ -67277,9 +67117,9 @@ function min(...values3) {
|
|
|
67277
67117
|
return item < minVal ? item : minVal;
|
|
67278
67118
|
}
|
|
67279
67119
|
return String(item) < String(minVal) ? item : minVal;
|
|
67280
|
-
});
|
|
67120
|
+
}) ?? null;
|
|
67281
67121
|
}
|
|
67282
|
-
|
|
67122
|
+
const smallest = values3.reduce((minVal, item) => {
|
|
67283
67123
|
if (minVal == null) return item;
|
|
67284
67124
|
if (item == null) return minVal;
|
|
67285
67125
|
if (typeof minVal === "number" && typeof item === "number") {
|
|
@@ -67287,6 +67127,7 @@ function min(...values3) {
|
|
|
67287
67127
|
}
|
|
67288
67128
|
return String(item) < String(minVal) ? item : minVal;
|
|
67289
67129
|
});
|
|
67130
|
+
return smallest ?? null;
|
|
67290
67131
|
}
|
|
67291
67132
|
function max(...values3) {
|
|
67292
67133
|
if (values3.length === 0) {
|
|
@@ -67295,7 +67136,7 @@ function max(...values3) {
|
|
|
67295
67136
|
if (values3.length === 1 && Array.isArray(values3[0])) {
|
|
67296
67137
|
const arr = values3[0];
|
|
67297
67138
|
if (arr.length === 0) {
|
|
67298
|
-
|
|
67139
|
+
return null;
|
|
67299
67140
|
}
|
|
67300
67141
|
return arr.reduce((maxVal, item) => {
|
|
67301
67142
|
if (maxVal == null) return item;
|
|
@@ -67304,9 +67145,9 @@ function max(...values3) {
|
|
|
67304
67145
|
return item > maxVal ? item : maxVal;
|
|
67305
67146
|
}
|
|
67306
67147
|
return String(item) > String(maxVal) ? item : maxVal;
|
|
67307
|
-
});
|
|
67148
|
+
}) ?? null;
|
|
67308
67149
|
}
|
|
67309
|
-
|
|
67150
|
+
const largest = values3.reduce((maxVal, item) => {
|
|
67310
67151
|
if (maxVal == null) return item;
|
|
67311
67152
|
if (item == null) return maxVal;
|
|
67312
67153
|
if (typeof maxVal === "number" && typeof item === "number") {
|
|
@@ -67314,8 +67155,10 @@ function max(...values3) {
|
|
|
67314
67155
|
}
|
|
67315
67156
|
return String(item) > String(maxVal) ? item : maxVal;
|
|
67316
67157
|
});
|
|
67158
|
+
return largest ?? null;
|
|
67317
67159
|
}
|
|
67318
67160
|
function round(value2, precision) {
|
|
67161
|
+
if (value2 == null) return null;
|
|
67319
67162
|
if (typeof value2 !== "number") {
|
|
67320
67163
|
throw new Error("round: expected number, got " + typeof value2);
|
|
67321
67164
|
}
|
|
@@ -67334,24 +67177,28 @@ function sum(arr) {
|
|
|
67334
67177
|
return arr.reduce((a, b) => a + b, 0);
|
|
67335
67178
|
}
|
|
67336
67179
|
function abs(n) {
|
|
67180
|
+
if (n == null) return null;
|
|
67337
67181
|
if (typeof n !== "number") {
|
|
67338
67182
|
throw new Error("abs: expected number, got " + typeof n);
|
|
67339
67183
|
}
|
|
67340
67184
|
return Math.abs(n);
|
|
67341
67185
|
}
|
|
67342
67186
|
function ceil(n) {
|
|
67187
|
+
if (n == null) return null;
|
|
67343
67188
|
if (typeof n !== "number") {
|
|
67344
67189
|
throw new Error("ceil: expected number, got " + typeof n);
|
|
67345
67190
|
}
|
|
67346
67191
|
return Math.ceil(n);
|
|
67347
67192
|
}
|
|
67348
67193
|
function floor(n) {
|
|
67194
|
+
if (n == null) return null;
|
|
67349
67195
|
if (typeof n !== "number") {
|
|
67350
67196
|
throw new Error("floor: expected number, got " + typeof n);
|
|
67351
67197
|
}
|
|
67352
67198
|
return Math.floor(n);
|
|
67353
67199
|
}
|
|
67354
67200
|
function clamp(n, min2, max3) {
|
|
67201
|
+
if (n == null) return null;
|
|
67355
67202
|
if (typeof n !== "number") {
|
|
67356
67203
|
throw new Error("clamp: expected number, got " + typeof n);
|
|
67357
67204
|
}
|
|
@@ -67369,6 +67216,7 @@ function clamp(n, min2, max3) {
|
|
|
67369
67216
|
return n;
|
|
67370
67217
|
}
|
|
67371
67218
|
function percentage(part, total, decimals) {
|
|
67219
|
+
if (part == null || total == null) return null;
|
|
67372
67220
|
if (typeof part !== "number") {
|
|
67373
67221
|
throw new Error("percentage: part must be a number");
|
|
67374
67222
|
}
|
|
@@ -67389,6 +67237,7 @@ function percentage(part, total, decimals) {
|
|
|
67389
67237
|
return percent;
|
|
67390
67238
|
}
|
|
67391
67239
|
function pow(base, exponent) {
|
|
67240
|
+
if (base == null || exponent == null) return null;
|
|
67392
67241
|
if (typeof base !== "number") {
|
|
67393
67242
|
throw new Error("pow: base must be a number");
|
|
67394
67243
|
}
|
|
@@ -67398,6 +67247,7 @@ function pow(base, exponent) {
|
|
|
67398
67247
|
return Math.pow(base, exponent);
|
|
67399
67248
|
}
|
|
67400
67249
|
function sqrt(n) {
|
|
67250
|
+
if (n == null) return null;
|
|
67401
67251
|
if (typeof n !== "number") {
|
|
67402
67252
|
throw new Error("sqrt: expected number, got " + typeof n);
|
|
67403
67253
|
}
|
|
@@ -67407,6 +67257,7 @@ function sqrt(n) {
|
|
|
67407
67257
|
return Math.sqrt(n);
|
|
67408
67258
|
}
|
|
67409
67259
|
function mod(n, divisor) {
|
|
67260
|
+
if (n == null || divisor == null) return null;
|
|
67410
67261
|
if (typeof n !== "number") {
|
|
67411
67262
|
throw new Error("mod: expected number, got " + typeof n);
|
|
67412
67263
|
}
|
|
@@ -67431,9 +67282,9 @@ __export(expression_object_exports, {
|
|
|
67431
67282
|
pick: () => pick3,
|
|
67432
67283
|
values: () => values2
|
|
67433
67284
|
});
|
|
67434
|
-
function getNestedValue(obj,
|
|
67285
|
+
function getNestedValue(obj, path14) {
|
|
67435
67286
|
if (obj == null) return void 0;
|
|
67436
|
-
const parts =
|
|
67287
|
+
const parts = path14.split(".");
|
|
67437
67288
|
let value2 = obj;
|
|
67438
67289
|
for (const part of parts) {
|
|
67439
67290
|
if (value2 == null) return void 0;
|
|
@@ -67472,11 +67323,11 @@ function entries(obj) {
|
|
|
67472
67323
|
}
|
|
67473
67324
|
return Object.entries(obj);
|
|
67474
67325
|
}
|
|
67475
|
-
function get(obj,
|
|
67476
|
-
if (typeof
|
|
67326
|
+
function get(obj, path14, defaultValue) {
|
|
67327
|
+
if (typeof path14 !== "string") {
|
|
67477
67328
|
throw new Error("get: path must be a string");
|
|
67478
67329
|
}
|
|
67479
|
-
const value2 = getNestedValue(obj,
|
|
67330
|
+
const value2 = getNestedValue(obj, path14);
|
|
67480
67331
|
return value2 !== void 0 ? value2 : defaultValue;
|
|
67481
67332
|
}
|
|
67482
67333
|
function pick3(obj, fields) {
|
|
@@ -67579,7 +67430,7 @@ __export(expression_type_exports, {
|
|
|
67579
67430
|
coalesce: () => coalesce,
|
|
67580
67431
|
isArray: () => isArray2,
|
|
67581
67432
|
isBoolean: () => isBoolean,
|
|
67582
|
-
isEmpty: () =>
|
|
67433
|
+
isEmpty: () => isEmpty2,
|
|
67583
67434
|
isNotNull: () => isNotNull,
|
|
67584
67435
|
isNull: () => isNull,
|
|
67585
67436
|
isNumber: () => isNumber,
|
|
@@ -67591,6 +67442,22 @@ __export(expression_type_exports, {
|
|
|
67591
67442
|
toString: () => toString,
|
|
67592
67443
|
typeOf: () => typeOf
|
|
67593
67444
|
});
|
|
67445
|
+
|
|
67446
|
+
// ../shared/src/schemas/database_types.ts
|
|
67447
|
+
function isEmptyFieldValue(value2) {
|
|
67448
|
+
if (value2 === null || value2 === void 0) {
|
|
67449
|
+
return true;
|
|
67450
|
+
}
|
|
67451
|
+
if (typeof value2 === "string") {
|
|
67452
|
+
return value2 === "";
|
|
67453
|
+
}
|
|
67454
|
+
if (Array.isArray(value2)) {
|
|
67455
|
+
return value2.length === 0;
|
|
67456
|
+
}
|
|
67457
|
+
return false;
|
|
67458
|
+
}
|
|
67459
|
+
|
|
67460
|
+
// ../shared/src/expression_type.ts
|
|
67594
67461
|
function isArray2(val) {
|
|
67595
67462
|
return Array.isArray(val);
|
|
67596
67463
|
}
|
|
@@ -67613,6 +67480,7 @@ function coalesce(...values3) {
|
|
|
67613
67480
|
return void 0;
|
|
67614
67481
|
}
|
|
67615
67482
|
function toNumber(val) {
|
|
67483
|
+
if (val == null) return null;
|
|
67616
67484
|
if (typeof val === "number") return val;
|
|
67617
67485
|
if (typeof val === "string") {
|
|
67618
67486
|
const parsed = parseFloat(val);
|
|
@@ -67624,9 +67492,7 @@ function toNumber(val) {
|
|
|
67624
67492
|
throw new Error("toNumber: expected number or string, got " + typeof val);
|
|
67625
67493
|
}
|
|
67626
67494
|
function toString(val) {
|
|
67627
|
-
if (val == null)
|
|
67628
|
-
throw new Error("toString: cannot convert null or undefined to string");
|
|
67629
|
-
}
|
|
67495
|
+
if (val == null) return "";
|
|
67630
67496
|
return String(val);
|
|
67631
67497
|
}
|
|
67632
67498
|
function isNull(val) {
|
|
@@ -67635,13 +67501,11 @@ function isNull(val) {
|
|
|
67635
67501
|
function isNotNull(val) {
|
|
67636
67502
|
return !isNull(val);
|
|
67637
67503
|
}
|
|
67638
|
-
function
|
|
67639
|
-
|
|
67640
|
-
if (typeof val === "string") return val.length === 0;
|
|
67641
|
-
if (Array.isArray(val)) return val.length === 0;
|
|
67642
|
-
return false;
|
|
67504
|
+
function isEmpty2(val) {
|
|
67505
|
+
return isEmptyFieldValue(val);
|
|
67643
67506
|
}
|
|
67644
67507
|
function parseJson(value2) {
|
|
67508
|
+
if (value2 == null) return null;
|
|
67645
67509
|
if (typeof value2 !== "string") {
|
|
67646
67510
|
throw new Error("parseJson: expected a JSON string, got " + typeof value2);
|
|
67647
67511
|
}
|
|
@@ -69359,17 +69223,17 @@ function readFromChanges(chain2) {
|
|
|
69359
69223
|
if (first3.kind === "bracket-number" || first3.kind === "bracket-expr") {
|
|
69360
69224
|
fail(first3.node, "changes is keyed by field name, not numeric index.");
|
|
69361
69225
|
}
|
|
69362
|
-
const
|
|
69226
|
+
const path14 = [{ at: "key", key: first3.key }];
|
|
69363
69227
|
for (const seg of segments.slice(1)) {
|
|
69364
69228
|
if (seg.kind === "bracket-number") {
|
|
69365
|
-
|
|
69229
|
+
path14.push({ at: "index", index: seg.index });
|
|
69366
69230
|
} else if (seg.kind === "bracket-expr") {
|
|
69367
|
-
|
|
69231
|
+
path14.push({ at: "index", index: seg.expr });
|
|
69368
69232
|
} else {
|
|
69369
|
-
|
|
69233
|
+
path14.push({ at: "key", key: seg.key });
|
|
69370
69234
|
}
|
|
69371
69235
|
}
|
|
69372
|
-
return { kind: "read", source: { from: "trigger_changes" }, path:
|
|
69236
|
+
return { kind: "read", source: { from: "trigger_changes" }, path: path14 };
|
|
69373
69237
|
});
|
|
69374
69238
|
}
|
|
69375
69239
|
var TRIGGER_RECORD_VIEWS = /* @__PURE__ */ new Map([
|
|
@@ -69387,17 +69251,17 @@ function readFromTrigger(chain2) {
|
|
|
69387
69251
|
return view === "trigger_changes" ? readFromChanges(lowered) : readFromRecord(view, lowered);
|
|
69388
69252
|
}
|
|
69389
69253
|
return wrapOptionalGuards(chain2, (segments) => {
|
|
69390
|
-
const
|
|
69254
|
+
const path14 = [];
|
|
69391
69255
|
for (const seg of segments) {
|
|
69392
69256
|
if (seg.kind === "bracket-number") {
|
|
69393
|
-
|
|
69257
|
+
path14.push({ at: "index", index: seg.index });
|
|
69394
69258
|
} else if (seg.kind === "bracket-expr") {
|
|
69395
|
-
|
|
69259
|
+
path14.push({ at: "index", index: seg.expr });
|
|
69396
69260
|
} else {
|
|
69397
|
-
|
|
69261
|
+
path14.push({ at: "key", key: seg.key });
|
|
69398
69262
|
}
|
|
69399
69263
|
}
|
|
69400
|
-
return { kind: "read", source: { from: "trigger" }, path:
|
|
69264
|
+
return { kind: "read", source: { from: "trigger" }, path: path14 };
|
|
69401
69265
|
});
|
|
69402
69266
|
}
|
|
69403
69267
|
function readFromRuntime(chain2) {
|
|
@@ -69419,17 +69283,17 @@ function readFromRuntime(chain2) {
|
|
|
69419
69283
|
const parked = PARKED_RUNTIME_KEYS.get(key);
|
|
69420
69284
|
if (parked) fail(first3.node, parked, parkedRuntimeKeyConstruct(key));
|
|
69421
69285
|
const source = { from: "runtime", key };
|
|
69422
|
-
const
|
|
69286
|
+
const path14 = [];
|
|
69423
69287
|
for (const seg of segments.slice(1)) {
|
|
69424
69288
|
if (seg.kind === "bracket-number") {
|
|
69425
|
-
|
|
69289
|
+
path14.push({ at: "index", index: seg.index });
|
|
69426
69290
|
} else if (seg.kind === "bracket-expr") {
|
|
69427
|
-
|
|
69291
|
+
path14.push({ at: "index", index: seg.expr });
|
|
69428
69292
|
} else {
|
|
69429
|
-
|
|
69293
|
+
path14.push({ at: "key", key: seg.key });
|
|
69430
69294
|
}
|
|
69431
69295
|
}
|
|
69432
|
-
return { kind: "read", source, path:
|
|
69296
|
+
return { kind: "read", source, path: path14 };
|
|
69433
69297
|
});
|
|
69434
69298
|
}
|
|
69435
69299
|
function readFromForeachItem(chain2) {
|
|
@@ -69465,17 +69329,17 @@ function readFromLexical(name2, chain2) {
|
|
|
69465
69329
|
}
|
|
69466
69330
|
function readFromStepOutput(stepId, chain2) {
|
|
69467
69331
|
return wrapOptionalGuards(chain2, (segments) => {
|
|
69468
|
-
const
|
|
69332
|
+
const path14 = [];
|
|
69469
69333
|
for (const seg of segments) {
|
|
69470
69334
|
if (seg.kind === "bracket-number") {
|
|
69471
|
-
|
|
69335
|
+
path14.push({ at: "index", index: seg.index });
|
|
69472
69336
|
} else if (seg.kind === "bracket-expr") {
|
|
69473
|
-
|
|
69337
|
+
path14.push({ at: "index", index: seg.expr });
|
|
69474
69338
|
} else {
|
|
69475
|
-
|
|
69339
|
+
path14.push({ at: "key", key: seg.key });
|
|
69476
69340
|
}
|
|
69477
69341
|
}
|
|
69478
|
-
return { kind: "read", source: { from: "step_output", step_id: stepId }, path:
|
|
69342
|
+
return { kind: "read", source: { from: "step_output", step_id: stepId }, path: path14 };
|
|
69479
69343
|
});
|
|
69480
69344
|
}
|
|
69481
69345
|
function classifyRecordPath(segs) {
|
|
@@ -71226,1081 +71090,6 @@ function checkWorkflowBodies(tsApi, aliases) {
|
|
|
71226
71090
|
}));
|
|
71227
71091
|
}
|
|
71228
71092
|
|
|
71229
|
-
// ../shared/src/schemas/table_fields.ts
|
|
71230
|
-
var tableFieldTypeNameSchema = zod_default.enum([
|
|
71231
|
-
"text",
|
|
71232
|
-
"number",
|
|
71233
|
-
"date",
|
|
71234
|
-
"boolean",
|
|
71235
|
-
"select",
|
|
71236
|
-
"select_member",
|
|
71237
|
-
"select_record_link",
|
|
71238
|
-
"files",
|
|
71239
|
-
"formula",
|
|
71240
|
-
"rollup",
|
|
71241
|
-
"lookup",
|
|
71242
|
-
"button",
|
|
71243
|
-
"autonumber"
|
|
71244
|
-
]);
|
|
71245
|
-
var tableFieldBaseSchema = zod_default.object({
|
|
71246
|
-
key: zod_default.string().describe("Unique field key"),
|
|
71247
|
-
name: zod_default.string().describe("Display name"),
|
|
71248
|
-
description: zod_default.string().describe("Field description"),
|
|
71249
|
-
confirm_before_update: zod_default.boolean().optional().describe("Show confirmation before AI updates")
|
|
71250
|
-
});
|
|
71251
|
-
var numberFormatSchema = zod_default.enum(["number", "currency", "percentage"]);
|
|
71252
|
-
var textFormatSchema = zod_default.enum(["text", "link", "markdown"]);
|
|
71253
|
-
var dateFormatSchema = zod_default.enum(["date", "datetime", "date_range", "datetime_range"]);
|
|
71254
|
-
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.";
|
|
71255
|
-
var textDefaultValueSchema = zod_default.string().nullish().describe(DEFAULT_VALUE_DESC);
|
|
71256
|
-
var numberDefaultValueSchema = zod_default.number().nullish().describe(DEFAULT_VALUE_DESC);
|
|
71257
|
-
var booleanDefaultValueSchema = zod_default.boolean().nullish().describe(DEFAULT_VALUE_DESC);
|
|
71258
|
-
var dateDefaultValueSchema = zod_default.string().nullish().describe(`${DEFAULT_VALUE_DESC} A date string in the field's format.`);
|
|
71259
|
-
var selectDefaultValueSchema = zod_default.array(zod_default.string()).nullish().describe(`${DEFAULT_VALUE_DESC} Option key(s) \u2014 one for single-select.`);
|
|
71260
|
-
var memberDefaultValueSchema = zod_default.array(zod_default.string()).nullish().describe(`${DEFAULT_VALUE_DESC} Member ID(s) \u2014 one for single-select.`);
|
|
71261
|
-
var tableNumberFieldSchema = tableFieldBaseSchema.extend({
|
|
71262
|
-
type: zod_default.literal("number"),
|
|
71263
|
-
format: numberFormatSchema,
|
|
71264
|
-
currency: zod_default.string().optional().describe("ISO 4217 code"),
|
|
71265
|
-
default_value: numberDefaultValueSchema
|
|
71266
|
-
});
|
|
71267
|
-
var tableTextFieldSchema = tableFieldBaseSchema.extend({
|
|
71268
|
-
type: zod_default.literal("text"),
|
|
71269
|
-
unique: zod_default.boolean().optional().describe("Unique values required"),
|
|
71270
|
-
// it's `optional` only for backward compatibility
|
|
71271
|
-
format: textFormatSchema.optional(),
|
|
71272
|
-
default_value: textDefaultValueSchema
|
|
71273
|
-
});
|
|
71274
|
-
var tableDateFieldSchema = tableFieldBaseSchema.extend({
|
|
71275
|
-
type: zod_default.literal("date"),
|
|
71276
|
-
format: dateFormatSchema.optional(),
|
|
71277
|
-
timezone: zod_default.string().optional().describe("IANA timezone"),
|
|
71278
|
-
derive_from: zod_default.enum(["created_at", "updated_at"]).optional().describe(
|
|
71279
|
-
"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."
|
|
71280
|
-
),
|
|
71281
|
-
// A derived date is read-only, so derive_from and default_value are mutually
|
|
71282
|
-
// exclusive — enforced in validateFieldDefaultValue.
|
|
71283
|
-
default_value: dateDefaultValueSchema
|
|
71284
|
-
});
|
|
71285
|
-
var tableBooleanFieldSchema = tableFieldBaseSchema.extend({
|
|
71286
|
-
type: zod_default.literal("boolean"),
|
|
71287
|
-
default_value: booleanDefaultValueSchema
|
|
71288
|
-
});
|
|
71289
|
-
var tableSelectFieldOptionSchema = zod_default.object({
|
|
71290
|
-
key: zod_default.string(),
|
|
71291
|
-
name: zod_default.string(),
|
|
71292
|
-
color: optionColorSchema
|
|
71293
|
-
});
|
|
71294
|
-
var tableSelectFieldSchema = tableFieldBaseSchema.extend({
|
|
71295
|
-
type: zod_default.literal("select"),
|
|
71296
|
-
options: zod_default.array(tableSelectFieldOptionSchema),
|
|
71297
|
-
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
71298
|
-
default_value: selectDefaultValueSchema
|
|
71299
|
-
});
|
|
71300
|
-
var tableSelectMemberFieldSchema = tableFieldBaseSchema.extend({
|
|
71301
|
-
type: zod_default.literal("select_member"),
|
|
71302
|
-
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
71303
|
-
default_value: memberDefaultValueSchema
|
|
71304
|
-
});
|
|
71305
|
-
var recordLinkItemSchema = zod_default.object({
|
|
71306
|
-
id: zod_default.string(),
|
|
71307
|
-
display: zod_default.string()
|
|
71308
|
-
});
|
|
71309
|
-
var selectRecordLinkValueSchema = zod_default.array(recordLinkItemSchema);
|
|
71310
|
-
var tableSelectRecordLinkFieldInputSchema = tableFieldBaseSchema.extend({
|
|
71311
|
-
type: zod_default.literal("select_record_link"),
|
|
71312
|
-
table_id: zod_default.string().describe("Linked table ID"),
|
|
71313
|
-
display_field_keys: zod_default.array(zod_default.string()).optional().describe(
|
|
71314
|
-
"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."
|
|
71315
|
-
),
|
|
71316
|
-
display_field_widths: zod_default.record(zod_default.string(), zod_default.number().int().positive()).optional().describe(
|
|
71317
|
-
"Per-column widths in pixels for the record picker, keyed by linked-table field key. Missing keys fall back to the default column width."
|
|
71318
|
-
),
|
|
71319
|
-
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."),
|
|
71320
|
-
paired_field_display_field_keys: zod_default.array(zod_default.string()).optional().describe("Display fields for paired link"),
|
|
71321
|
-
paired_field_name: zod_default.string().optional().describe(
|
|
71322
|
-
"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."
|
|
71323
|
-
),
|
|
71324
|
-
cardinality: zod_default.enum(["one", "many"]).optional().describe(
|
|
71325
|
-
"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."
|
|
71326
|
-
)
|
|
71327
|
-
});
|
|
71328
|
-
var tableSelectRecordLinkFieldSchema = tableFieldBaseSchema.extend({
|
|
71329
|
-
type: zod_default.literal("select_record_link").describe("Field type for linking to records in another table"),
|
|
71330
|
-
table_id: zod_default.string().describe("ID of the target table that records can be linked to"),
|
|
71331
|
-
display_field_keys: zod_default.array(zod_default.string()).optional().default([]).describe(
|
|
71332
|
-
"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."
|
|
71333
|
-
),
|
|
71334
|
-
display_field_widths: zod_default.record(zod_default.string(), zod_default.number().int().positive()).optional().describe(
|
|
71335
|
-
"Per-column widths in pixels for the record picker, keyed by linked-table field key. Missing keys fall back to the default column width."
|
|
71336
|
-
),
|
|
71337
|
-
paired_field_key: zod_default.string().optional().describe(
|
|
71338
|
-
"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."
|
|
71339
|
-
),
|
|
71340
|
-
cardinality: zod_default.enum(["one", "many"]).optional().describe(
|
|
71341
|
-
"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'."
|
|
71342
|
-
)
|
|
71343
|
-
});
|
|
71344
|
-
var tableRollupFieldSchema = tableFieldBaseSchema.extend({
|
|
71345
|
-
type: zod_default.literal("rollup").describe(
|
|
71346
|
-
"Field type for aggregating values from linked records (sum, avg, filled, earliest, etc.)"
|
|
71347
|
-
),
|
|
71348
|
-
source_field_key: zod_default.string().describe("The field key of the select_record_link field to rollup from"),
|
|
71349
|
-
aggregate_option: aggregateOptionSchema.describe(
|
|
71350
|
-
"The field aggregation function to apply (e.g., sum, avg, filled, earliest)"
|
|
71351
|
-
),
|
|
71352
|
-
filter: tableRecordFiltersGroupNodeSchema.optional().describe(
|
|
71353
|
-
"Optional filter to apply to linked records before aggregation. Only records matching the filter conditions will be included in the rollup calculation."
|
|
71354
|
-
),
|
|
71355
|
-
aggregate_field_type: tableFieldTypeNameSchema.optional().describe(
|
|
71356
|
-
"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."
|
|
71357
|
-
),
|
|
71358
|
-
aggregate_field_format: zod_default.string().optional().describe(
|
|
71359
|
-
"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."
|
|
71360
|
-
),
|
|
71361
|
-
aggregate_field_currency: zod_default.string().optional().describe(
|
|
71362
|
-
"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."
|
|
71363
|
-
)
|
|
71364
|
-
});
|
|
71365
|
-
var lookupOrderBySchema = zod_default.object({
|
|
71366
|
-
field_key: zod_default.string(),
|
|
71367
|
-
direction: zod_default.enum(["asc", "desc"])
|
|
71368
|
-
});
|
|
71369
|
-
var tableLookupFieldSchema = tableFieldBaseSchema.extend({
|
|
71370
|
-
type: zod_default.literal("lookup").describe("Field type for displaying values from fields in linked records"),
|
|
71371
|
-
source_field_key: zod_default.string().describe("The field key of the select_record_link field to lookup from"),
|
|
71372
|
-
lookup_field_key: zod_default.string().describe("The field key from the linked records to display"),
|
|
71373
|
-
lookup_field_type: tableFieldTypeNameSchema.optional().describe(
|
|
71374
|
-
"The type of the target lookup field (e.g. 'text', 'number', 'date'). Resolved from the linked table's field definition at read time."
|
|
71375
|
-
),
|
|
71376
|
-
lookup_field_format: zod_default.string().optional().describe(
|
|
71377
|
-
"The format of the target lookup field (e.g. 'currency', 'percentage', 'datetime'). Resolved from the linked table's field definition at read time."
|
|
71378
|
-
),
|
|
71379
|
-
lookup_field_currency: zod_default.string().optional().describe(
|
|
71380
|
-
"The currency code of the target lookup field (e.g. 'USD', 'VND'). Resolved from the linked table's field definition at read time."
|
|
71381
|
-
),
|
|
71382
|
-
lookup_field_options: zod_default.array(zod_default.object({ key: zod_default.string(), name: zod_default.string(), color: zod_default.string().optional() })).optional().describe(
|
|
71383
|
-
"Options for select-type lookup fields. Synced from the source select field's options."
|
|
71384
|
-
),
|
|
71385
|
-
order_by: lookupOrderBySchema.optional().describe(
|
|
71386
|
-
"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."
|
|
71387
|
-
)
|
|
71388
|
-
});
|
|
71389
|
-
var tableFilesFieldSchema = tableFieldBaseSchema.extend({
|
|
71390
|
-
type: zod_default.literal("files").describe("Field type for file attachments (images, PDFs, documents)")
|
|
71391
|
-
});
|
|
71392
|
-
var formulaInputSchema = zod_default.object({
|
|
71393
|
-
expression: zod_default.string().describe(
|
|
71394
|
-
"JavaScript expression. Uses {Field Name} for field references."
|
|
71395
|
-
),
|
|
71396
|
-
format: zod_default.enum(["number", "currency", "percentage", "link"]).optional().describe(
|
|
71397
|
-
"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."
|
|
71398
|
-
),
|
|
71399
|
-
currency: zod_default.string().optional().describe("ISO 4217 currency code, e.g. USD, VND, EUR")
|
|
71400
|
-
});
|
|
71401
|
-
var formulaSchema = formulaInputSchema.extend({
|
|
71402
|
-
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)."),
|
|
71403
|
-
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.")
|
|
71404
|
-
});
|
|
71405
|
-
var tableFormulaFieldSchema = tableFieldBaseSchema.extend({
|
|
71406
|
-
type: zod_default.literal("formula").describe("Field type for calculated values based on expressions"),
|
|
71407
|
-
formula: formulaSchema.describe("Formula configuration and expression")
|
|
71408
|
-
});
|
|
71409
|
-
var workflowMetadataSchema = zod_default.object({
|
|
71410
|
-
table_ids: zod_default.array(zod_default.string()).describe("IDs of the tables this workflow affects"),
|
|
71411
|
-
staged_for_app_id: zod_default.string().optional().describe(
|
|
71412
|
-
"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."
|
|
71413
|
-
)
|
|
71414
|
-
});
|
|
71415
|
-
var workflowSchema = zod_default.object({
|
|
71416
|
-
id: zod_default.string().describe("Unique identifier for the workflow"),
|
|
71417
|
-
name: zod_default.string().describe("Display name of the workflow"),
|
|
71418
|
-
description: zod_default.string().describe("Human-readable description of what this workflow does"),
|
|
71419
|
-
steps: zod_default.unknown().describe(
|
|
71420
|
-
"AST-valued step tree (tool calls, conditionals, loops)."
|
|
71421
|
-
),
|
|
71422
|
-
metadata: workflowMetadataSchema.nullable().optional().describe("Metadata for the workflow"),
|
|
71423
|
-
current_version: zod_default.number().int().describe("Current version number"),
|
|
71424
|
-
enabled: zod_default.boolean().describe("Whether this workflow is active"),
|
|
71425
|
-
workspace_id: zod_default.string().describe("ID of the workspace this workflow belongs to"),
|
|
71426
|
-
created_at: zod_default.string().describe("Timestamp when workflow was created"),
|
|
71427
|
-
updated_at: zod_default.string().describe("Timestamp of last update")
|
|
71428
|
-
});
|
|
71429
|
-
var tableButtonFieldSchema = tableFieldBaseSchema.extend({
|
|
71430
|
-
type: zod_default.literal("button").describe("Field type for action buttons"),
|
|
71431
|
-
text: zod_default.string().describe("Button label text displayed to users"),
|
|
71432
|
-
workflow_id: zod_default.string().nullable().optional().describe(
|
|
71433
|
-
"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."
|
|
71434
|
-
)
|
|
71435
|
-
});
|
|
71436
|
-
var tableAutonumberFieldSchema = tableFieldBaseSchema.extend({
|
|
71437
|
-
type: zod_default.literal("autonumber"),
|
|
71438
|
-
prefix: zod_default.string().optional().describe(
|
|
71439
|
-
"Literal prefix prepended to every display value (e.g. 'KH-' \u2192 'KH-001'). Ignored when `template` is set."
|
|
71440
|
-
),
|
|
71441
|
-
padding: zod_default.number().int().min(1).max(20).optional().describe(
|
|
71442
|
-
"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."
|
|
71443
|
-
),
|
|
71444
|
-
template: zod_default.string().optional().describe(
|
|
71445
|
-
"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)."
|
|
71446
|
-
)
|
|
71447
|
-
});
|
|
71448
|
-
var tableFieldSchema = zod_default.discriminatedUnion("type", [
|
|
71449
|
-
tableNumberFieldSchema,
|
|
71450
|
-
tableTextFieldSchema,
|
|
71451
|
-
tableDateFieldSchema,
|
|
71452
|
-
tableBooleanFieldSchema,
|
|
71453
|
-
tableSelectFieldSchema,
|
|
71454
|
-
tableSelectMemberFieldSchema,
|
|
71455
|
-
tableSelectRecordLinkFieldSchema,
|
|
71456
|
-
tableRollupFieldSchema,
|
|
71457
|
-
tableLookupFieldSchema,
|
|
71458
|
-
tableFilesFieldSchema,
|
|
71459
|
-
tableFormulaFieldSchema,
|
|
71460
|
-
tableButtonFieldSchema,
|
|
71461
|
-
tableAutonumberFieldSchema
|
|
71462
|
-
]);
|
|
71463
|
-
var tableFieldInputSchema = zod_default.discriminatedUnion("type", [
|
|
71464
|
-
tableNumberFieldSchema,
|
|
71465
|
-
tableTextFieldSchema,
|
|
71466
|
-
tableDateFieldSchema,
|
|
71467
|
-
tableBooleanFieldSchema,
|
|
71468
|
-
tableSelectFieldSchema,
|
|
71469
|
-
tableSelectMemberFieldSchema,
|
|
71470
|
-
tableSelectRecordLinkFieldInputSchema,
|
|
71471
|
-
tableRollupFieldSchema,
|
|
71472
|
-
tableLookupFieldSchema,
|
|
71473
|
-
tableFilesFieldSchema,
|
|
71474
|
-
tableFormulaFieldSchema,
|
|
71475
|
-
tableButtonFieldSchema,
|
|
71476
|
-
tableAutonumberFieldSchema
|
|
71477
|
-
]);
|
|
71478
|
-
var tableFieldsSchema = zod_default.array(tableFieldSchema);
|
|
71479
|
-
var tableFieldCreateBaseSchema = zod_default.object({
|
|
71480
|
-
name: zod_default.string().describe("Display name"),
|
|
71481
|
-
description: zod_default.string().describe("Field description"),
|
|
71482
|
-
confirm_before_update: zod_default.boolean().optional().describe("Show confirmation before AI updates")
|
|
71483
|
-
});
|
|
71484
|
-
var tableSelectFieldOptionCreateSchema = zod_default.object({
|
|
71485
|
-
name: zod_default.string(),
|
|
71486
|
-
color: optionColorSchema
|
|
71487
|
-
});
|
|
71488
|
-
var tableFieldTypeConfigSchema = zod_default.discriminatedUnion("type", [
|
|
71489
|
-
zod_default.object({
|
|
71490
|
-
type: zod_default.literal("number"),
|
|
71491
|
-
format: numberFormatSchema.default("number"),
|
|
71492
|
-
currency: zod_default.string().optional().describe("ISO 4217 code"),
|
|
71493
|
-
default_value: numberDefaultValueSchema
|
|
71494
|
-
}),
|
|
71495
|
-
zod_default.object({
|
|
71496
|
-
type: zod_default.literal("text"),
|
|
71497
|
-
unique: zod_default.boolean().optional().describe("Unique values required"),
|
|
71498
|
-
format: textFormatSchema.default("text"),
|
|
71499
|
-
default_value: textDefaultValueSchema
|
|
71500
|
-
}),
|
|
71501
|
-
zod_default.object({
|
|
71502
|
-
type: zod_default.literal("date"),
|
|
71503
|
-
format: dateFormatSchema.optional(),
|
|
71504
|
-
timezone: zod_default.string().optional().describe("IANA timezone"),
|
|
71505
|
-
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."),
|
|
71506
|
-
default_value: dateDefaultValueSchema
|
|
71507
|
-
}),
|
|
71508
|
-
zod_default.object({
|
|
71509
|
-
type: zod_default.literal("boolean"),
|
|
71510
|
-
default_value: booleanDefaultValueSchema
|
|
71511
|
-
}),
|
|
71512
|
-
zod_default.object({
|
|
71513
|
-
type: zod_default.literal("select"),
|
|
71514
|
-
options: zod_default.array(tableSelectFieldOptionCreateSchema),
|
|
71515
|
-
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
71516
|
-
default_value: selectDefaultValueSchema
|
|
71517
|
-
}),
|
|
71518
|
-
zod_default.object({
|
|
71519
|
-
type: zod_default.literal("select_member"),
|
|
71520
|
-
multi: zod_default.boolean().optional().describe("Allow multiple selections"),
|
|
71521
|
-
default_value: memberDefaultValueSchema
|
|
71522
|
-
}),
|
|
71523
|
-
zod_default.object({
|
|
71524
|
-
type: zod_default.literal("select_record_link"),
|
|
71525
|
-
table_id: zod_default.string().describe("Linked table ID"),
|
|
71526
|
-
display_field_keys: zod_default.array(zod_default.string()).optional().describe(
|
|
71527
|
-
"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."
|
|
71528
|
-
),
|
|
71529
|
-
display_field_widths: zod_default.record(zod_default.string(), zod_default.number().int().positive()).optional().describe(
|
|
71530
|
-
"Per-column widths in pixels for the record picker, keyed by linked-table field key. Missing keys fall back to the default column width."
|
|
71531
|
-
),
|
|
71532
|
-
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."),
|
|
71533
|
-
paired_field_display_field_keys: zod_default.array(zod_default.string()).optional().describe("Paired field display"),
|
|
71534
|
-
paired_field_name: zod_default.string().optional().describe(
|
|
71535
|
-
"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."
|
|
71536
|
-
),
|
|
71537
|
-
cardinality: zod_default.enum(["one", "many"]).optional().describe(
|
|
71538
|
-
"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'."
|
|
71539
|
-
)
|
|
71540
|
-
}),
|
|
71541
|
-
zod_default.object({
|
|
71542
|
-
type: zod_default.literal("rollup"),
|
|
71543
|
-
source_field_key: zod_default.string().describe("Source link field key"),
|
|
71544
|
-
aggregate_option: aggregateOptionSchema,
|
|
71545
|
-
filter: tableRecordFiltersGroupNodeSchema.optional().describe("Filter linked records")
|
|
71546
|
-
}),
|
|
71547
|
-
zod_default.object({
|
|
71548
|
-
type: zod_default.literal("lookup"),
|
|
71549
|
-
source_field_key: zod_default.string().describe("Source link field key"),
|
|
71550
|
-
lookup_field_key: zod_default.string().describe("Field to display"),
|
|
71551
|
-
order_by: lookupOrderBySchema.optional().describe("Ordered lookup: pick only the extreme linked record's field (desc=latest, asc=earliest)")
|
|
71552
|
-
}),
|
|
71553
|
-
zod_default.object({
|
|
71554
|
-
type: zod_default.literal("files")
|
|
71555
|
-
}),
|
|
71556
|
-
zod_default.object({
|
|
71557
|
-
type: zod_default.literal("formula"),
|
|
71558
|
-
formula: formulaInputSchema
|
|
71559
|
-
}),
|
|
71560
|
-
// `button` is deliberately absent: button fields are legacy — this union
|
|
71561
|
-
// shapes CREATE input only, and new buttons can no longer be created
|
|
71562
|
-
// (see LEGACY_FIELD_TYPES). Stored button fields still parse via the
|
|
71563
|
-
// stored-field union above, and update paths keep accepting text edits.
|
|
71564
|
-
zod_default.object({
|
|
71565
|
-
type: zod_default.literal("autonumber"),
|
|
71566
|
-
prefix: zod_default.string().optional().describe("Literal prefix prepended to display (ignored when template is set)"),
|
|
71567
|
-
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)"),
|
|
71568
|
-
template: zod_default.string().optional().describe(
|
|
71569
|
-
"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'."
|
|
71570
|
-
)
|
|
71571
|
-
})
|
|
71572
|
-
]);
|
|
71573
|
-
var tableFieldCreateInputSchema = zod_default.intersection(
|
|
71574
|
-
tableFieldCreateBaseSchema,
|
|
71575
|
-
tableFieldTypeConfigSchema
|
|
71576
|
-
);
|
|
71577
|
-
var fieldVisibilitySchema = zod_default.enum(["visible", "hidden"]).describe(
|
|
71578
|
-
"Field visibility state: 'visible' = shown to everyone, 'hidden' = not shown by default but members can toggle"
|
|
71579
|
-
);
|
|
71580
|
-
|
|
71581
|
-
// ../shared/src/schemas/field_config.ts
|
|
71582
|
-
var fieldConfigEntrySchema = zod_default.object({
|
|
71583
|
-
key: zod_default.string().min(1).describe("Field key"),
|
|
71584
|
-
visibility: fieldVisibilitySchema,
|
|
71585
|
-
width: zod_default.number().optional()
|
|
71586
|
-
});
|
|
71587
|
-
|
|
71588
|
-
// ../shared/src/schemas/iam.ts
|
|
71589
|
-
var jsonSchemaSchema = zod_default.string();
|
|
71590
|
-
var organizationSchema = zod_default.object({
|
|
71591
|
-
id: zod_default.string().describe("Unique identifier for the organization"),
|
|
71592
|
-
name: zod_default.string().describe("Display name of the organization"),
|
|
71593
|
-
slug: zod_default.string().nullable().describe("Slug for the organization")
|
|
71594
|
-
});
|
|
71595
|
-
var memberSchema = zod_default.object({
|
|
71596
|
-
member_id: zod_default.string().describe("Unique identifier for the member"),
|
|
71597
|
-
organization_id: zod_default.string().describe("Organization ID the member belongs to"),
|
|
71598
|
-
name: zod_default.string().describe("Display name of the member"),
|
|
71599
|
-
email_address: zod_default.string().describe(
|
|
71600
|
-
"What the member types to sign in: an email address for a self-managed member, an administrator-issued name (e.g. giamdoc.sunrise) for an admin-managed one. The latter is NOT an address and cannot receive mail \u2014 the field name predates the split."
|
|
71601
|
-
),
|
|
71602
|
-
role: zod_default.enum(["owner", "admin", "member"]).describe("Organization role"),
|
|
71603
|
-
image: zod_default.string().nullable().optional().describe("URL to the member's profile picture"),
|
|
71604
|
-
account_type: zod_default.enum(["self_managed", "admin_managed"]).describe(
|
|
71605
|
-
"How the account is credentialed. admin_managed means an admin chose the sign-in name and set the password; the account has NO email address at all, so nothing can be mailed to it until the member claims one they control."
|
|
71606
|
-
),
|
|
71607
|
-
archived: zod_default.boolean().optional().describe(
|
|
71608
|
-
"True when this person has been removed from the organization. The membership survives removal so records naming them keep resolving; it grants nothing. Optional because an older server omits it \u2014 absent means active."
|
|
71609
|
-
),
|
|
71610
|
-
joined_at: zod_default.string().optional().describe(
|
|
71611
|
-
"ISO timestamp of when this membership began. Optional because an older server omits it \u2014 absent means not told, never 'joined at the epoch'."
|
|
71612
|
-
)
|
|
71613
|
-
});
|
|
71614
|
-
var pendingInvitationSchema = zod_default.object({
|
|
71615
|
-
invitation_id: zod_default.string().describe("Unique identifier for the pending invitation"),
|
|
71616
|
-
organization_id: zod_default.string().describe("Organization the invitee will join on accept"),
|
|
71617
|
-
email: zod_default.string().describe("Email the invitation was sent to"),
|
|
71618
|
-
name: zod_default.string().nullable().describe("Admin-supplied display name (carried onto member.name on accept; invitee can override at accept time)"),
|
|
71619
|
-
role: zod_default.enum(["owner", "admin", "member"]).describe("Role the invitee will receive on accept"),
|
|
71620
|
-
expires_at: zod_default.string().describe("ISO timestamp when the invitation expires")
|
|
71621
|
-
});
|
|
71622
|
-
var workspaceSchema = zod_default.object({
|
|
71623
|
-
id: zod_default.string().describe("Unique identifier for the workspace"),
|
|
71624
|
-
name: zod_default.string().describe("Display name of the workspace"),
|
|
71625
|
-
default_currency: zod_default.string().describe("Default currency code for the workspace"),
|
|
71626
|
-
timezone: zod_default.string().describe("IANA timezone name (e.g., 'America/New_York', 'Asia/Tokyo')"),
|
|
71627
|
-
organization_id: zod_default.string().describe("Organization ID this workspace belongs to"),
|
|
71628
|
-
created_at: zod_default.string().describe("Timestamp when workspace was created")
|
|
71629
|
-
});
|
|
71630
|
-
var memberGroupSchema = zod_default.object({
|
|
71631
|
-
id: zod_default.string().describe("Unique identifier for the member group"),
|
|
71632
|
-
name: zod_default.string().describe("Display name of the group"),
|
|
71633
|
-
description: zod_default.string().optional().describe("Optional description of the group's purpose"),
|
|
71634
|
-
member_ids: zod_default.array(zod_default.string()).describe("Array of member IDs in this group"),
|
|
71635
|
-
invitation_ids: zod_default.array(zod_default.string()).describe("Array of pending invitation IDs pre-granted membership; migrated to member_ids on accept"),
|
|
71636
|
-
organization_id: zod_default.string().describe("ID of the organization this group belongs to"),
|
|
71637
|
-
created_at: zod_default.string().describe("Timestamp when group was created"),
|
|
71638
|
-
created_by: zod_default.string().describe("Member ID of the user who created this group")
|
|
71639
|
-
});
|
|
71640
|
-
var principalGroupSchema = zod_default.object({
|
|
71641
|
-
id: zod_default.string().describe("Unique identifier for the member group"),
|
|
71642
|
-
name: zod_default.string().describe("Display name of the group"),
|
|
71643
|
-
description: zod_default.string().optional().describe("Optional description of the group's purpose"),
|
|
71644
|
-
member_count: zod_default.number().int().describe("Number of accepted members in the group"),
|
|
71645
|
-
invitation_count: zod_default.number().int().describe("Number of pending invitations pre-granted membership")
|
|
71646
|
-
});
|
|
71647
|
-
var PUBLIC_PRINCIPAL_ID = "public";
|
|
71648
|
-
var principalSchema = zod_default.discriminatedUnion("type", [
|
|
71649
|
-
zod_default.object({
|
|
71650
|
-
type: zod_default.literal("member").describe("Principal type: individual member"),
|
|
71651
|
-
id: zod_default.string().describe("Member ID")
|
|
71652
|
-
}),
|
|
71653
|
-
zod_default.object({
|
|
71654
|
-
type: zod_default.literal("member_group").describe("Principal type: group of members"),
|
|
71655
|
-
id: zod_default.string().describe("Member group ID")
|
|
71656
|
-
}),
|
|
71657
|
-
zod_default.object({
|
|
71658
|
-
type: zod_default.literal("organization").describe("Principal type: all members in organization"),
|
|
71659
|
-
id: zod_default.string().describe("Organization ID")
|
|
71660
|
-
}),
|
|
71661
|
-
zod_default.object({
|
|
71662
|
-
type: zod_default.literal("public").describe("Principal type: anyone, including unauthenticated visitors"),
|
|
71663
|
-
id: zod_default.literal(PUBLIC_PRINCIPAL_ID).describe("Always the `public` sentinel \u2014 no entity")
|
|
71664
|
-
}),
|
|
71665
|
-
// Pending invitation as principal: lets admins pre-grant group membership and
|
|
71666
|
-
// resource access before the invitee accepts. Never resolved as a Subject —
|
|
71667
|
-
// a pending invitee cannot authenticate, so these bindings stay dormant until
|
|
71668
|
-
// accept-time migration rewrites them to type:"member".
|
|
71669
|
-
zod_default.object({
|
|
71670
|
-
type: zod_default.literal("invitation").describe("Principal type: pending invitation (not yet accepted)"),
|
|
71671
|
-
id: zod_default.string().describe("Invitation ID")
|
|
71672
|
-
})
|
|
71673
|
-
]);
|
|
71674
|
-
var subjectSchema = zod_default.discriminatedUnion("type", [
|
|
71675
|
-
zod_default.object({
|
|
71676
|
-
type: zod_default.literal("member").describe("Subject type: authenticated member"),
|
|
71677
|
-
id: zod_default.string().describe("Member ID")
|
|
71678
|
-
}),
|
|
71679
|
-
zod_default.object({
|
|
71680
|
-
type: zod_default.literal("public").describe("Subject type: unauthenticated visitor")
|
|
71681
|
-
})
|
|
71682
|
-
]);
|
|
71683
|
-
var resourceTypeSchema = zod_default.enum(["table", "table_view", "app", "automation", "skill", "document_template", "instruction", "knowledge_doc"]);
|
|
71684
|
-
var accessPrincipalSchema = zod_default.discriminatedUnion("type", [
|
|
71685
|
-
zod_default.object({
|
|
71686
|
-
type: zod_default.literal("member").describe("Principal type: an individual member"),
|
|
71687
|
-
id: zod_default.string().describe("Member ID")
|
|
71688
|
-
}),
|
|
71689
|
-
zod_default.object({
|
|
71690
|
-
type: zod_default.literal("member_group").describe("Principal type: a member group"),
|
|
71691
|
-
id: zod_default.string().describe("Group ID")
|
|
71692
|
-
}),
|
|
71693
|
-
zod_default.object({
|
|
71694
|
-
type: zod_default.literal("organization").describe("Principal type: everyone in the organization"),
|
|
71695
|
-
id: zod_default.string().describe("Organization ID")
|
|
71696
|
-
})
|
|
71697
|
-
]);
|
|
71698
|
-
var resourceAccessSchema = zod_default.object({
|
|
71699
|
-
resource_id: zod_default.string().describe("ID of the resource these principals can reach"),
|
|
71700
|
-
principals: zod_default.array(accessPrincipalSchema).describe("Members, groups and the organization that have been granted access")
|
|
71701
|
-
});
|
|
71702
|
-
var resourceRoleBindingSchema = zod_default.object({
|
|
71703
|
-
id: zod_default.string().describe("Unique identifier for the role binding"),
|
|
71704
|
-
principal: principalSchema.describe(
|
|
71705
|
-
"Who this role binding applies to (member, group, or organization)"
|
|
71706
|
-
),
|
|
71707
|
-
resource_type: resourceTypeSchema.describe("Type of resource being accessed"),
|
|
71708
|
-
resource_id: zod_default.string().describe("ID of the specific resource"),
|
|
71709
|
-
role: zod_default.string().describe("Role name (e.g., 'viewer', 'editor', 'manager', 'user')")
|
|
71710
|
-
});
|
|
71711
|
-
|
|
71712
|
-
// ../shared/src/schemas/table_records.ts
|
|
71713
|
-
var tableWorkflowEventSchema = zod_default.enum([
|
|
71714
|
-
"before_create",
|
|
71715
|
-
"after_create",
|
|
71716
|
-
"before_update",
|
|
71717
|
-
"after_update",
|
|
71718
|
-
"before_delete",
|
|
71719
|
-
"after_delete"
|
|
71720
|
-
]);
|
|
71721
|
-
var tableWorkflowSchema = zod_default.object({
|
|
71722
|
-
id: zod_default.string().describe("Unique table-workflow binding ID (tbw_ prefix)"),
|
|
71723
|
-
name: zod_default.string().describe("Human-readable name"),
|
|
71724
|
-
description: zod_default.string().describe("Description of what this workflow does"),
|
|
71725
|
-
enabled: zod_default.boolean().describe("Whether this workflow is active"),
|
|
71726
|
-
event: tableWorkflowEventSchema.describe(
|
|
71727
|
-
"Lifecycle event that fires this workflow. before_* runs synchronously and may reject the mutation; after_* runs after commit and does not block."
|
|
71728
|
-
),
|
|
71729
|
-
workflow_id: zod_default.string().describe(
|
|
71730
|
-
"ID of the workflow row that owns this binding's steps. The workflow's steps_v2 is the source of truth for the AST."
|
|
71731
|
-
),
|
|
71732
|
-
// Recursive v2 expression AST. Lazy schema would crash the OpenAPI walker;
|
|
71733
|
-
// runtime is `unknown` and the casted Zod type preserves the compile-time
|
|
71734
|
-
// signature for callers. Write paths re-parse with the strict schema before
|
|
71735
|
-
// storage.
|
|
71736
|
-
if: zod_default.unknown().nullable().optional().describe(
|
|
71737
|
-
"Optional pre-execution gate. Evaluated against the trigger context (record / prev_record / changes / runtime); the workflow fires only when truthy. Skip gating means the workflow always fires."
|
|
71738
|
-
),
|
|
71739
|
-
created_at: zod_default.string().describe("When the binding was created"),
|
|
71740
|
-
updated_at: zod_default.string().describe("When the binding was last modified"),
|
|
71741
|
-
archived_at: zod_default.string().nullable().optional().describe(
|
|
71742
|
-
"Set when the binding was removed (soft-delete). An archived binding never fires and is hidden from active listings, but is restorable; null/absent = active."
|
|
71743
|
-
)
|
|
71744
|
-
});
|
|
71745
|
-
var tableWorkflowMessageSchema = zod_default.object({
|
|
71746
|
-
table_workflow_id: zod_default.string().describe("tbw_* binding that emitted the message."),
|
|
71747
|
-
workflow_name: zod_default.string().describe("Human name of the workflow at execution time."),
|
|
71748
|
-
event: tableWorkflowEventSchema.describe(
|
|
71749
|
-
"Lifecycle event that produced the message. Only before_* events can surface here."
|
|
71750
|
-
),
|
|
71751
|
-
record_id: zod_default.string().describe(
|
|
71752
|
-
"Record that triggered the workflow. Lets the UI scope the message to a specific row in bulk responses."
|
|
71753
|
-
),
|
|
71754
|
-
message: zod_default.string().describe("Author-provided text from the workflow's return.message.")
|
|
71755
|
-
});
|
|
71756
|
-
var tableSchema = zod_default.object({
|
|
71757
|
-
id: zod_default.string().describe("Unique identifier for the table"),
|
|
71758
|
-
workspace_id: zod_default.string().describe("ID of the workspace this table belongs to"),
|
|
71759
|
-
name: zod_default.string().describe("Display name of the table"),
|
|
71760
|
-
description: zod_default.string().describe("Description of the table's purpose"),
|
|
71761
|
-
position: zod_default.number().int().optional().nullable().describe("Display ordering index for the table. Lower numbers are shown first. "),
|
|
71762
|
-
fields: tableFieldsSchema.describe("Array of field definitions for this table"),
|
|
71763
|
-
workflows: zod_default.array(tableWorkflowSchema).optional().describe(
|
|
71764
|
-
"Workflows attached to this table that fire around record mutations. before_* run synchronously and may reject; after_* run after commit and do not block."
|
|
71765
|
-
),
|
|
71766
|
-
private_filters: tableRecordFiltersGroupNodeSchema.nullable().optional().describe("Row-level private filters AND'd to every query as a security boundary (admin bypass)"),
|
|
71767
|
-
colors: tableRecordColorsSchema.nullable().optional().describe("Color rules for styling records based on filter conditions"),
|
|
71768
|
-
approvers: zod_default.array(principalSchema).nullable().optional().describe(
|
|
71769
|
-
"Principals (members, groups, or the organization) who review locked-record change requests on this table. Null/empty = organization admins review. The requester never reviews their own request."
|
|
71770
|
-
),
|
|
71771
|
-
created_at: zod_default.string().describe("Timestamp when table was created")
|
|
71772
|
-
});
|
|
71773
|
-
var recordDataTemplateSchema = zod_default.object({
|
|
71774
|
-
id: zod_default.string().describe("Unique identifier for the record data template"),
|
|
71775
|
-
name: zod_default.string().describe("Display name of the record data template"),
|
|
71776
|
-
description: zod_default.string().describe("Description of the record data template"),
|
|
71777
|
-
table_id: zod_default.string().describe("ID of the table this record template belongs to"),
|
|
71778
|
-
data: zod_default.record(zod_default.string(), zod_default.unknown()).describe("The data of the record template. The key is the Field key.")
|
|
71779
|
-
});
|
|
71780
|
-
var tableRecordSchema = zod_default.object({
|
|
71781
|
-
id: zod_default.string().describe("Unique identifier for the record"),
|
|
71782
|
-
table_id: zod_default.string().describe("ID of the table this record belongs to"),
|
|
71783
|
-
workspace_id: zod_default.string().describe("ID of the workspace this record belongs to"),
|
|
71784
|
-
data: zod_default.record(zod_default.string(), zod_default.unknown()).describe("The data of the record. The key is the Field key."),
|
|
71785
|
-
locked: zod_default.boolean().optional().describe("Whether the entire record is locked from editing"),
|
|
71786
|
-
draft: zod_default.boolean().optional().describe("Whether the record is an unsubmitted draft \u2014 UI-only in-progress state, not yet a real row. Row-visibility scoping is enforced at submit, not while a draft is being filled in."),
|
|
71787
|
-
updated_at: zod_default.string().describe("Timestamp of last update"),
|
|
71788
|
-
created_at: zod_default.string().describe("Timestamp when record was created")
|
|
71789
|
-
});
|
|
71790
|
-
var viewSummaryEntrySchema = zod_default.object({
|
|
71791
|
-
operation: zod_default.string().describe("Operation to perform on the field"),
|
|
71792
|
-
field_key: zod_default.string().describe("Field key to display in the summary row")
|
|
71793
|
-
});
|
|
71794
|
-
var viewSummarySchema = zod_default.record(zod_default.string(), viewSummaryEntrySchema.nullable().optional()).nullable().optional().describe("Map of field keys to summary operations.");
|
|
71795
|
-
var visibleToEntrySchema = zod_default.object({
|
|
71796
|
-
type: zod_default.enum(["member", "group"]).describe("Principal kind that may see the view: an individual member or a member group"),
|
|
71797
|
-
id: zod_default.string().describe("Member ID (type=member) or member-group ID (type=group)")
|
|
71798
|
-
});
|
|
71799
|
-
var visibleToSchema = zod_default.array(visibleToEntrySchema).nullable();
|
|
71800
|
-
var tableViewSchema = zod_default.object({
|
|
71801
|
-
id: zod_default.string().describe("Unique identifier for the view"),
|
|
71802
|
-
table_id: zod_default.string().describe("ID of the table this view displays"),
|
|
71803
|
-
workspace_id: zod_default.string().describe("ID of the workspace this view belongs to"),
|
|
71804
|
-
name: zod_default.string().describe("Display name of the view"),
|
|
71805
|
-
description: zod_default.string().describe("Description of the view's purpose"),
|
|
71806
|
-
visible_to: visibleToSchema.optional().describe(
|
|
71807
|
-
"Sidebar declutter list (NOT access control). null/absent = every member with access to the parent table sees this view; a non-empty list of members/groups restricts who sees it in the explorer. [] is normalized to null on write."
|
|
71808
|
-
),
|
|
71809
|
-
position: zod_default.number().int().nullable().describe(
|
|
71810
|
-
"Display ordering index for the view. Lower numbers are shown first. Use incremental values with gaps (100, 200, 300) instead of consecutive numbers (1, 2, 3) to enable efficient reordering without updating multiple records. Example: To insert between 100 and 200, use 150."
|
|
71811
|
-
),
|
|
71812
|
-
frozen_columns: zod_default.number().int().nullable().optional().describe("Number of columns to freeze. Frozen columns are not scrollable."),
|
|
71813
|
-
summary: viewSummarySchema,
|
|
71814
|
-
default_record_data_template_id: zod_default.string().nullable().optional().describe("ID of the record template to use as the default record initial data"),
|
|
71815
|
-
field_config: zod_default.array(fieldConfigEntrySchema).describe(
|
|
71816
|
-
"Ordered array of field config entries. Order = display order, visibility = per-entry. Fields not listed are hidden."
|
|
71817
|
-
),
|
|
71818
|
-
sort: tableRecordSortSchema.nullable().describe("Sorting configuration for records in this view"),
|
|
71819
|
-
filters: tableRecordFiltersGroupNodeSchema.nullable().describe("Filter conditions applied to records in this view"),
|
|
71820
|
-
created_at: zod_default.string().describe("Timestamp when view was created")
|
|
71821
|
-
});
|
|
71822
|
-
var tableWithViewsSchema = tableSchema.extend({
|
|
71823
|
-
views: zod_default.array(tableViewSchema).describe("Array of views for this table")
|
|
71824
|
-
});
|
|
71825
|
-
var explorerViewSchema = zod_default.object({
|
|
71826
|
-
id: zod_default.string(),
|
|
71827
|
-
name: zod_default.string(),
|
|
71828
|
-
owner_member_id: zod_default.string(),
|
|
71829
|
-
// Per-view sidebar declutter list (NOT access control). null = every member
|
|
71830
|
-
// with table access sees this view; a non-empty member/group list restricts
|
|
71831
|
-
// it. Surfaced here so the table share dialog can render and edit each view's
|
|
71832
|
-
// audience without a second round-trip.
|
|
71833
|
-
visible_to: visibleToSchema.optional(),
|
|
71834
|
-
// Per-requesting-member sidebar preference: true if this member has hidden
|
|
71835
|
-
// the view. Hiding is UX-only — it never affects access or other members.
|
|
71836
|
-
hidden: zod_default.boolean()
|
|
71837
|
-
});
|
|
71838
|
-
var explorerTableSchema = zod_default.object({
|
|
71839
|
-
id: zod_default.string(),
|
|
71840
|
-
name: zod_default.string(),
|
|
71841
|
-
position: zod_default.number().int().nullable().optional(),
|
|
71842
|
-
views: zod_default.array(explorerViewSchema),
|
|
71843
|
-
owner_member_id: zod_default.string(),
|
|
71844
|
-
// Active package installations whose binding includes this table — the
|
|
71845
|
-
// sidebar marks these so members see the structure is app-managed before
|
|
71846
|
-
// they try to change it. Absent for unbound tables.
|
|
71847
|
-
package_apps: zod_default.array(zod_default.object({ id: zod_default.string(), name: zod_default.string() })).optional()
|
|
71848
|
-
});
|
|
71849
|
-
var documentTemplateTypeSchema = zod_default.enum(["html", "pdf-form", "excel", "word", "email"]).describe("Template type: 'html' for HTML templates, 'pdf-form' for fillable PDF forms, 'excel' for Excel templates, 'word' for Word templates, 'email' for email HTML templates");
|
|
71850
|
-
var documentTemplateSchema = zod_default.object({
|
|
71851
|
-
id: zod_default.string().describe("Unique identifier for the document template"),
|
|
71852
|
-
workspace_id: zod_default.string().describe("ID of the workspace this template belongs to"),
|
|
71853
|
-
name: zod_default.string().describe("Display name of the template"),
|
|
71854
|
-
description: zod_default.string().describe("What the template produces, shown under its name in the library"),
|
|
71855
|
-
type: documentTemplateTypeSchema,
|
|
71856
|
-
template: zod_default.string().describe("Template content with variable placeholders (e.g., {{customer_name}})"),
|
|
71857
|
-
format: zod_default.string().describe("Supported document formats.").optional(),
|
|
71858
|
-
orientation: zod_default.enum(["portrait", "landscape"]).describe("Page orientation for PDF generation").optional(),
|
|
71859
|
-
variables: zod_default.record(zod_default.string(), zod_default.unknown()).describe("Data to pass to the template."),
|
|
71860
|
-
current_version: zod_default.number().describe("Current version number of the template"),
|
|
71861
|
-
owner_member_id: zod_default.string().nullable().optional().describe("Member who created the template, from the IAM registry. Absent on write responses."),
|
|
71862
|
-
created_at: zod_default.string().describe("Timestamp when template was created"),
|
|
71863
|
-
template_url: zod_default.string().nullable().describe("Signed URL to download the template file (pdf-form/excel only)")
|
|
71864
|
-
});
|
|
71865
|
-
|
|
71866
|
-
// ../shared/src/schemas/packages.ts
|
|
71867
|
-
var contractAliasSchema = zod_default.string().regex(
|
|
71868
|
-
/^[a-z][a-z0-9_]*$/,
|
|
71869
|
-
"alias must be a lowercase slug: start with a letter, then letters/digits/underscores"
|
|
71870
|
-
);
|
|
71871
|
-
var runtimeAliasSchema = zod_default.string().min(1).max(200);
|
|
71872
|
-
var contractFieldBaseSchema = zod_default.object({
|
|
71873
|
-
alias: contractAliasSchema.describe("Stable local alias, unique within the entity"),
|
|
71874
|
-
// No braces: scaffold translates formula expressions from `{alias}` to the
|
|
71875
|
-
// platform's `{Field Label}` reference form, so a brace inside a label would
|
|
71876
|
-
// corrupt every formula that references the field.
|
|
71877
|
-
label: zod_default.string().min(1).regex(/^[^{}]*$/, "field labels cannot contain { or }").describe("Display label used as the field name at scaffold time"),
|
|
71878
|
-
description: zod_default.string().optional(),
|
|
71879
|
-
required: zod_default.boolean().optional().describe(
|
|
71880
|
-
"Advisory only: marks the field required for app-form/workflow UX. The table data model has no required constraint, so scaffold does NOT enforce it at the schema level \u2014 validation lives in the app/workflow layer."
|
|
71881
|
-
)
|
|
71882
|
-
});
|
|
71883
|
-
var contractSelectOptionSchema = zod_default.object({
|
|
71884
|
-
alias: contractAliasSchema.describe("Stable local alias, unique within the field"),
|
|
71885
|
-
label: zod_default.string().min(1).describe("Display label for the option"),
|
|
71886
|
-
color: optionColorSchema
|
|
71887
|
-
});
|
|
71888
|
-
var contractAutonumberConfigSchema = tableAutonumberFieldSchema.pick({
|
|
71889
|
-
prefix: true,
|
|
71890
|
-
padding: true,
|
|
71891
|
-
template: true
|
|
71892
|
-
});
|
|
71893
|
-
var contractTextFieldSchema = contractFieldBaseSchema.extend({
|
|
71894
|
-
type: zod_default.literal("text"),
|
|
71895
|
-
unique: zod_default.boolean().optional().describe("Unique values required"),
|
|
71896
|
-
format: textFormatSchema.optional()
|
|
71897
|
-
});
|
|
71898
|
-
var contractNumberFieldSchema = contractFieldBaseSchema.extend({
|
|
71899
|
-
type: zod_default.literal("number"),
|
|
71900
|
-
format: numberFormatSchema.optional(),
|
|
71901
|
-
currency: zod_default.string().optional().describe("ISO 4217 code")
|
|
71902
|
-
});
|
|
71903
|
-
var contractDateFieldSchema = contractFieldBaseSchema.extend({
|
|
71904
|
-
type: zod_default.literal("date"),
|
|
71905
|
-
format: dateFormatSchema.optional(),
|
|
71906
|
-
timezone: zod_default.string().optional().describe("IANA timezone"),
|
|
71907
|
-
derive_from: zod_default.enum(["created_at", "updated_at"]).optional().describe("Auto-populate from the row's system timestamp; the field becomes read-only.")
|
|
71908
|
-
});
|
|
71909
|
-
var contractBooleanFieldSchema = contractFieldBaseSchema.extend({
|
|
71910
|
-
type: zod_default.literal("boolean")
|
|
71911
|
-
});
|
|
71912
|
-
var contractSelectFieldSchema = contractFieldBaseSchema.extend({
|
|
71913
|
-
type: zod_default.literal("select"),
|
|
71914
|
-
options: zod_default.array(contractSelectOptionSchema).min(1),
|
|
71915
|
-
multi: zod_default.boolean().optional().describe("Allow multiple selections")
|
|
71916
|
-
});
|
|
71917
|
-
var contractSelectMemberFieldSchema = contractFieldBaseSchema.extend({
|
|
71918
|
-
type: zod_default.literal("select_member"),
|
|
71919
|
-
multi: zod_default.boolean().optional().describe("Allow multiple selections")
|
|
71920
|
-
});
|
|
71921
|
-
var contractSelectRecordLinkFieldSchema = contractFieldBaseSchema.extend({
|
|
71922
|
-
type: zod_default.literal("select_record_link"),
|
|
71923
|
-
target_entity: contractAliasSchema.describe("Alias of the entity this field links to"),
|
|
71924
|
-
sync_both_ways: zod_default.boolean().optional().describe("Create a paired link field on the target entity for bidirectional sync"),
|
|
71925
|
-
paired_field_alias: contractAliasSchema.optional().describe(
|
|
71926
|
-
"The pair edge of a bidirectional link: the field alias ON THE TARGET ENTITY that is this link's sync partner. Both sides of a pair carry it, each naming the other. Scaffold creates whichever side it reaches first WITH the pairing (the platform auto-creates the partner) and binds the partner alias to the auto-created field \u2014 without this edge the two contract fields would be created independently and collide with the auto-created partner."
|
|
71927
|
-
),
|
|
71928
|
-
cardinality: zod_default.enum(["one", "many"]).optional().describe("How many linked records this field holds. Default 'many'."),
|
|
71929
|
-
display_field_aliases: zod_default.array(contractAliasSchema).optional().describe("Field aliases on the target entity shown as the link's display text / picker columns")
|
|
71930
|
-
});
|
|
71931
|
-
var contractFilesFieldSchema = contractFieldBaseSchema.extend({
|
|
71932
|
-
type: zod_default.literal("files")
|
|
71933
|
-
});
|
|
71934
|
-
var contractFormulaFieldSchema = contractFieldBaseSchema.extend({
|
|
71935
|
-
type: zod_default.literal("formula"),
|
|
71936
|
-
formula: formulaInputSchema.describe(
|
|
71937
|
-
"Formula config. The expression references other fields on the SAME entity by alias in braces, e.g. `{quantity} * {unit_price}`."
|
|
71938
|
-
)
|
|
71939
|
-
});
|
|
71940
|
-
var contractRollupFieldSchema = contractFieldBaseSchema.extend({
|
|
71941
|
-
type: zod_default.literal("rollup"),
|
|
71942
|
-
source_field_alias: contractAliasSchema.describe(
|
|
71943
|
-
"Alias of a select_record_link field on this entity to roll up from"
|
|
71944
|
-
),
|
|
71945
|
-
aggregate_option: aggregateOptionSchema.describe(
|
|
71946
|
-
"Aggregation operation. Its `field_key` names a field alias on the linked entity."
|
|
71947
|
-
)
|
|
71948
|
-
});
|
|
71949
|
-
var contractLookupFieldSchema = contractFieldBaseSchema.extend({
|
|
71950
|
-
type: zod_default.literal("lookup"),
|
|
71951
|
-
source_field_alias: contractAliasSchema.describe(
|
|
71952
|
-
"Alias of a select_record_link field on this entity to look up through"
|
|
71953
|
-
),
|
|
71954
|
-
lookup_field_alias: contractAliasSchema.describe(
|
|
71955
|
-
"Alias of the field on the linked entity to display"
|
|
71956
|
-
),
|
|
71957
|
-
order_by: lookupOrderBySchema.optional().describe("Ordered lookup. Its `field_key` names a field alias on the linked entity.")
|
|
71958
|
-
});
|
|
71959
|
-
var contractAutonumberFieldSchema = contractFieldBaseSchema.extend({
|
|
71960
|
-
type: zod_default.literal("autonumber"),
|
|
71961
|
-
...contractAutonumberConfigSchema.shape
|
|
71962
|
-
});
|
|
71963
|
-
var contractFieldSchema = zod_default.discriminatedUnion("type", [
|
|
71964
|
-
contractTextFieldSchema,
|
|
71965
|
-
contractNumberFieldSchema,
|
|
71966
|
-
contractDateFieldSchema,
|
|
71967
|
-
contractBooleanFieldSchema,
|
|
71968
|
-
contractSelectFieldSchema,
|
|
71969
|
-
contractSelectMemberFieldSchema,
|
|
71970
|
-
contractSelectRecordLinkFieldSchema,
|
|
71971
|
-
contractFilesFieldSchema,
|
|
71972
|
-
contractFormulaFieldSchema,
|
|
71973
|
-
contractRollupFieldSchema,
|
|
71974
|
-
contractLookupFieldSchema,
|
|
71975
|
-
contractAutonumberFieldSchema
|
|
71976
|
-
]);
|
|
71977
|
-
var contractEntitySchema = zod_default.object({
|
|
71978
|
-
alias: contractAliasSchema.describe("Stable entity alias, unique within the contract"),
|
|
71979
|
-
label: zod_default.string().min(1).describe("Display label used as the table name at scaffold time"),
|
|
71980
|
-
description: zod_default.string().optional(),
|
|
71981
|
-
fields: zod_default.array(contractFieldSchema).min(1)
|
|
71982
|
-
});
|
|
71983
|
-
var contractRoleSchema = zod_default.object({
|
|
71984
|
-
alias: contractAliasSchema.describe("Stable role alias, bound to a workspace group at install"),
|
|
71985
|
-
label: zod_default.string().min(1)
|
|
71986
|
-
});
|
|
71987
|
-
var contractTemplateBaseSchema = zod_default.object({
|
|
71988
|
-
alias: contractAliasSchema.describe("Stable template alias, unique within the contract"),
|
|
71989
|
-
label: zod_default.string().min(1),
|
|
71990
|
-
content_sha256: zod_default.string().optional().describe(
|
|
71991
|
-
"sha256 (64-char lowercase hex) of the template content \u2014 inline: the utf-8 content string; file-backed: the bytes_ref bytes. The modified-detection reference. Optional in the schema so contracts published before template sha still parse; REQUIRED at publish (validatePackageContract)."
|
|
71992
|
-
)
|
|
71993
|
-
});
|
|
71994
|
-
var contractInlineTemplateSchema = (templateType) => contractTemplateBaseSchema.extend({
|
|
71995
|
-
type: zod_default.literal(templateType),
|
|
71996
|
-
content: zod_default.string().min(1).describe("Inline template content; placeholders reference field aliases")
|
|
71997
|
-
});
|
|
71998
|
-
var contractFileTemplateSchema = (templateType) => contractTemplateBaseSchema.extend({
|
|
71999
|
-
type: zod_default.literal(templateType),
|
|
72000
|
-
bytes_ref: zod_default.string().min(1).describe("Path of the backing file within the package bundle; markers reference field aliases")
|
|
72001
|
-
});
|
|
72002
|
-
var contractTemplateSchema = zod_default.discriminatedUnion("type", [
|
|
72003
|
-
contractInlineTemplateSchema("html"),
|
|
72004
|
-
contractInlineTemplateSchema("email"),
|
|
72005
|
-
contractFileTemplateSchema("excel"),
|
|
72006
|
-
contractFileTemplateSchema("word"),
|
|
72007
|
-
contractFileTemplateSchema("pdf-form")
|
|
72008
|
-
]);
|
|
72009
|
-
var contractFromTableNodeSchema = zod_default.object({
|
|
72010
|
-
kind: zod_default.literal("from_table"),
|
|
72011
|
-
from_entity: contractAliasSchema.describe("Entity alias this query reads from"),
|
|
72012
|
-
filter: tableRecordFiltersSchema.optional(),
|
|
72013
|
-
search: zod_default.string().optional(),
|
|
72014
|
-
sort: tableRecordSortSchema.optional(),
|
|
72015
|
-
limit: zod_default.number().optional()
|
|
72016
|
-
});
|
|
72017
|
-
var contractProjectNodeSchema = zod_default.object({
|
|
72018
|
-
kind: zod_default.literal("project"),
|
|
72019
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72020
|
-
columns: zod_default.array(queryProjectionColumnSchema).min(1)
|
|
72021
|
-
});
|
|
72022
|
-
var contractFilterNodeSchema = zod_default.object({
|
|
72023
|
-
kind: zod_default.literal("filter"),
|
|
72024
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72025
|
-
predicate: tableRecordFiltersSchema
|
|
72026
|
-
});
|
|
72027
|
-
var contractJoinNodeSchema = zod_default.object({
|
|
72028
|
-
kind: zod_default.literal("join"),
|
|
72029
|
-
left: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72030
|
-
right: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72031
|
-
on: queryJoinPredicateSchema,
|
|
72032
|
-
type: zod_default.enum(["inner", "left"])
|
|
72033
|
-
});
|
|
72034
|
-
var contractUnionNodeSchema = zod_default.object({
|
|
72035
|
-
kind: zod_default.literal("union"),
|
|
72036
|
-
sources: zod_default.array(zod_default.lazy(() => contractQueryNodeSchema)).min(2)
|
|
72037
|
-
});
|
|
72038
|
-
var contractGroupNodeSchema = zod_default.object({
|
|
72039
|
-
kind: zod_default.literal("group"),
|
|
72040
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72041
|
-
by: zod_default.array(zod_default.string()),
|
|
72042
|
-
aggregates: zod_default.array(queryAggregateColumnSchema).min(1)
|
|
72043
|
-
});
|
|
72044
|
-
var contractWindowNodeSchema = zod_default.object({
|
|
72045
|
-
kind: zod_default.literal("window"),
|
|
72046
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72047
|
-
partition_by: zod_default.array(zod_default.string()),
|
|
72048
|
-
order_by: tableRecordSortSchema,
|
|
72049
|
-
frame: queryWindowFrameSchema.optional(),
|
|
72050
|
-
aggregates: zod_default.array(queryAggregateColumnSchema).optional(),
|
|
72051
|
-
functions: zod_default.array(queryWindowFunctionColumnSchema).optional()
|
|
72052
|
-
});
|
|
72053
|
-
var contractSortNodeSchema = zod_default.object({
|
|
72054
|
-
kind: zod_default.literal("sort"),
|
|
72055
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72056
|
-
by: tableRecordSortSchema
|
|
72057
|
-
});
|
|
72058
|
-
var contractLimitNodeSchema = zod_default.object({
|
|
72059
|
-
kind: zod_default.literal("limit"),
|
|
72060
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72061
|
-
n: zod_default.number().int().positive(),
|
|
72062
|
-
offset: zod_default.number().int().nonnegative().optional()
|
|
72063
|
-
});
|
|
72064
|
-
var contractUnpivotNodeSchema = zod_default.object({
|
|
72065
|
-
kind: zod_default.literal("unpivot"),
|
|
72066
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72067
|
-
passthrough: zod_default.array(queryUnpivotPassthroughColumnSchema),
|
|
72068
|
-
row_columns: zod_default.array(queryUnpivotRowColumnSchema).min(1),
|
|
72069
|
-
rows: zod_default.array(zod_default.record(zod_default.string(), querySourceSchema)).min(1)
|
|
72070
|
-
});
|
|
72071
|
-
var contractUnnestNodeSchema = zod_default.object({
|
|
72072
|
-
kind: zod_default.literal("unnest"),
|
|
72073
|
-
from: zod_default.lazy(() => contractQueryNodeSchema),
|
|
72074
|
-
source: zod_default.string(),
|
|
72075
|
-
output: zod_default.string(),
|
|
72076
|
-
display_output: zod_default.string().optional(),
|
|
72077
|
-
keep_empty: zod_default.boolean().optional()
|
|
72078
|
-
});
|
|
72079
|
-
var contractQueryNodeSchema = zod_default.lazy(
|
|
72080
|
-
() => zod_default.discriminatedUnion("kind", [
|
|
72081
|
-
contractFromTableNodeSchema,
|
|
72082
|
-
contractProjectNodeSchema,
|
|
72083
|
-
contractFilterNodeSchema,
|
|
72084
|
-
contractJoinNodeSchema,
|
|
72085
|
-
contractUnionNodeSchema,
|
|
72086
|
-
contractGroupNodeSchema,
|
|
72087
|
-
contractWindowNodeSchema,
|
|
72088
|
-
contractSortNodeSchema,
|
|
72089
|
-
contractLimitNodeSchema,
|
|
72090
|
-
contractUnpivotNodeSchema,
|
|
72091
|
-
contractUnnestNodeSchema
|
|
72092
|
-
])
|
|
72093
|
-
);
|
|
72094
|
-
var contractQuerySchema = zod_default.object({
|
|
72095
|
-
alias: runtimeAliasSchema.describe(
|
|
72096
|
-
"Stable query alias, unique within the contract \u2014 carried verbatim from the app (source invokes it at runtime)"
|
|
72097
|
-
),
|
|
72098
|
-
params: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe("Typed param schema. Keys are param names referenced as {{params.<name>}} in the ast."),
|
|
72099
|
-
ast: contractQueryNodeSchema
|
|
72100
|
-
});
|
|
72101
|
-
var contractLifecycleEventSchema = tableWorkflowEventSchema;
|
|
72102
|
-
var contractWorkflowTriggerSchema = zod_default.discriminatedUnion("type", [
|
|
72103
|
-
zod_default.object({ type: zod_default.literal("app") }),
|
|
72104
|
-
zod_default.object({
|
|
72105
|
-
type: zod_default.literal("entity_lifecycle"),
|
|
72106
|
-
entity: contractAliasSchema.describe("Alias of the entity whose lifecycle fires this workflow"),
|
|
72107
|
-
event: contractLifecycleEventSchema
|
|
72108
|
-
})
|
|
72109
|
-
]);
|
|
72110
|
-
var contractWorkflowSchema = zod_default.object({
|
|
72111
|
-
alias: runtimeAliasSchema.describe(
|
|
72112
|
-
"Stable workflow alias, unique within the contract \u2014 app-trigger aliases are carried verbatim from the app (source invokes them at runtime)"
|
|
72113
|
-
),
|
|
72114
|
-
trigger: contractWorkflowTriggerSchema,
|
|
72115
|
-
inputs: zod_default.record(zod_default.string(), appWorkflowInputSchema).optional().describe("Typed inputs. record_link `table_id` names an entity alias; member `group` a role alias."),
|
|
72116
|
-
outputs: zod_default.record(zod_default.string(), appWorkflowOutputSchema).optional().describe("Typed outputs. record_link `table_id` names an entity alias."),
|
|
72117
|
-
body: zod_default.string().min(1).describe("Alias-form JS-subset workflow source. Identifiers are resolved against the binding at materialize time.")
|
|
72118
|
-
});
|
|
72119
|
-
var contractAgentSchema = appAgentDeclarationSchema.extend({
|
|
72120
|
-
alias: runtimeAliasSchema.describe(
|
|
72121
|
-
"Stable agent alias, unique within the contract \u2014 carried verbatim from the app (source invokes it at runtime)"
|
|
72122
|
-
),
|
|
72123
|
-
knowledge_expects: zod_default.array(zod_default.string().min(1)).optional().describe(
|
|
72124
|
-
"Doc NAMES this agent must read that the package does NOT own \u2014 the installer's own docs. Resolved by name against the installing workspace: exactly one non-archived match binds, zero or several bind nothing and surface as an install warning, because doc names are not unique and picking one would be a guess. The agent installs either way."
|
|
72125
|
-
),
|
|
72126
|
-
knowledge_aliases: zod_default.array(contractAliasSchema).optional().describe(
|
|
72127
|
-
"Package knowledge docs this agent may read, by contract alias. Materialize resolves each against `binding.knowledge` to the installing workspace's own doc id and writes the agent's `knowledge_doc_ids`. Omit for an agent that reads no package knowledge \u2014 an agent whose declared set does not travel can read NOTHING, since a declared set bounds every read."
|
|
72128
|
-
)
|
|
72129
|
-
});
|
|
72130
|
-
var contractConfigBaseSchema = zod_default.object({
|
|
72131
|
-
alias: contractAliasSchema.describe("Stable config alias, unique within the contract"),
|
|
72132
|
-
label: zod_default.string().min(1),
|
|
72133
|
-
description: zod_default.string().optional()
|
|
72134
|
-
});
|
|
72135
|
-
var contractTextConfigSchema = contractConfigBaseSchema.extend({
|
|
72136
|
-
type: zod_default.literal("text"),
|
|
72137
|
-
default: zod_default.string()
|
|
72138
|
-
});
|
|
72139
|
-
var contractBooleanConfigSchema = contractConfigBaseSchema.extend({
|
|
72140
|
-
type: zod_default.literal("boolean"),
|
|
72141
|
-
default: zod_default.boolean()
|
|
72142
|
-
});
|
|
72143
|
-
var contractColorConfigSchema = contractConfigBaseSchema.extend({
|
|
72144
|
-
type: zod_default.literal("color"),
|
|
72145
|
-
default: optionColorSchema
|
|
72146
|
-
});
|
|
72147
|
-
var contractNumberConfigSchema = contractConfigBaseSchema.extend({
|
|
72148
|
-
type: zod_default.literal("number"),
|
|
72149
|
-
default: zod_default.number()
|
|
72150
|
-
});
|
|
72151
|
-
var contractSelectConfigSchema = contractConfigBaseSchema.extend({
|
|
72152
|
-
type: zod_default.literal("select"),
|
|
72153
|
-
options: zod_default.array(zod_default.object({ value: zod_default.string(), label: zod_default.string().min(1) })).min(1),
|
|
72154
|
-
default: zod_default.string()
|
|
72155
|
-
});
|
|
72156
|
-
var contractConfigEntrySchema = zod_default.discriminatedUnion("type", [
|
|
72157
|
-
contractTextConfigSchema,
|
|
72158
|
-
contractBooleanConfigSchema,
|
|
72159
|
-
contractColorConfigSchema,
|
|
72160
|
-
contractNumberConfigSchema,
|
|
72161
|
-
contractSelectConfigSchema
|
|
72162
|
-
]);
|
|
72163
|
-
var packageKindSchema = zod_default.enum(["app", "content"]);
|
|
72164
|
-
var contractKnowledgeEntrySchema = zod_default.object({
|
|
72165
|
-
name: zod_default.string().min(1).describe(
|
|
72166
|
-
"Display name \u2014 the runtime routing key an agent resolves the doc by; unique across the contract's knowledge"
|
|
72167
|
-
),
|
|
72168
|
-
description: zod_default.string().describe("Doc description (may be empty)"),
|
|
72169
|
-
// Optional so contracts published before tagging still parse; absent means
|
|
72170
|
-
// untagged. A curated corpus is exactly the case where classification is
|
|
72171
|
-
// authored deliberately, so install and upgrade have to carry it — otherwise
|
|
72172
|
-
// every installed corpus lands unlabelled and the customer re-tags it by hand.
|
|
72173
|
-
//
|
|
72174
|
-
// ABSENT IS NOT EMPTY, and that distinction is load-bearing on the wire: a
|
|
72175
|
-
// contract that says nothing about tags must leave the customer's own labels
|
|
72176
|
-
// alone, or a routine content upgrade silently strips classification the
|
|
72177
|
-
// workspace added. Every reader below branches on `undefined`, never on length.
|
|
72178
|
-
tags: zod_default.array(zod_default.string()).optional().describe("Labels for the doc; omitted leaves existing labels alone"),
|
|
72179
|
-
/**
|
|
72180
|
-
* LEGACY, read-only, removed in a later release.
|
|
72181
|
-
*
|
|
72182
|
-
* Content packages published while knowledge docs had folders carry a `path`,
|
|
72183
|
-
* and those contracts are stored verbatim in the workspaces that installed
|
|
72184
|
-
* them. Dropping the field would make an installed contract fail to parse and
|
|
72185
|
-
* would discard what the publisher declared, so it is still accepted and
|
|
72186
|
-
* mapped to `tags` on install/upgrade (a path's segments were always labels;
|
|
72187
|
-
* the hierarchy merely insisted on an order for them). Nothing EMITS it any
|
|
72188
|
-
* more — `content_bundle` writes `tags` — so it disappears from a package the
|
|
72189
|
-
* first time it is re-published.
|
|
72190
|
-
*/
|
|
72191
|
-
path: zod_default.string().optional().describe("Deprecated: pre-tagging folder. Mapped to tags on install."),
|
|
72192
|
-
content_ref: zod_default.string().min(1).describe("Path of the content file within the bundle \u2014 must be `knowledge/<alias>.md`"),
|
|
72193
|
-
content_sha256: zod_default.string().describe("sha256 (64-char lowercase hex) of the content bytes \u2014 the modified-detection reference")
|
|
72194
|
-
});
|
|
72195
|
-
var contractKnowledgeSchema = zod_default.record(contractAliasSchema, contractKnowledgeEntrySchema);
|
|
72196
|
-
var packageContractSchema = zod_default.object({
|
|
72197
|
-
entities: zod_default.array(contractEntitySchema).default([]),
|
|
72198
|
-
roles: zod_default.array(contractRoleSchema).default([]),
|
|
72199
|
-
templates: zod_default.array(contractTemplateSchema).default([]),
|
|
72200
|
-
queries: zod_default.array(contractQuerySchema).default([]),
|
|
72201
|
-
workflows: zod_default.array(contractWorkflowSchema).default([]),
|
|
72202
|
-
agents: zod_default.array(contractAgentSchema).default([]),
|
|
72203
|
-
config: zod_default.array(contractConfigEntrySchema).default([]),
|
|
72204
|
-
// Package-managed knowledge docs (alias → metadata + content sha). Defaults to
|
|
72205
|
-
// {} so contracts published before knowledge packaging still parse.
|
|
72206
|
-
knowledge: contractKnowledgeSchema.default({}),
|
|
72207
|
-
// Doc NAMES the package's agents route to but the package does not own —
|
|
72208
|
-
// install/health WARN (advisory) when a name has no doc in the workspace.
|
|
72209
|
-
// The first instance of the general cross-package "expects" contract.
|
|
72210
|
-
knowledge_expects: zod_default.array(zod_default.string()).default([])
|
|
72211
|
-
});
|
|
72212
|
-
var bindingMapSchema = zod_default.record(zod_default.string().min(1), zod_default.string().min(1));
|
|
72213
|
-
var bindingSchema = zod_default.object({
|
|
72214
|
-
entities: bindingMapSchema.default({}),
|
|
72215
|
-
fields: bindingMapSchema.default({}),
|
|
72216
|
-
options: bindingMapSchema.default({}),
|
|
72217
|
-
templates: bindingMapSchema.default({}),
|
|
72218
|
-
roles: bindingMapSchema.default({}),
|
|
72219
|
-
// Artifact registry, not a schema binding: the package-owned table-workflow
|
|
72220
|
-
// ROW id per entity_lifecycle workflow alias. Materialize matches/updates by
|
|
72221
|
-
// this id (a display name is forgeable and renameable), upgrade prunes by
|
|
72222
|
-
// it, and hashes look rows up through it. Excluded from BINDING_NAMESPACES:
|
|
72223
|
-
// a deleted row is a modified-core finding (fingerprints), never binding
|
|
72224
|
-
// drift, so validateBinding/applyDriftResolutions ignore it.
|
|
72225
|
-
workflows: bindingMapSchema.default({}),
|
|
72226
|
-
// The app's BUNDLED knowledge corpus: contract knowledge alias → the
|
|
72227
|
-
// workspace's concrete `kdc_` id. One row, one pin — the app installation IS
|
|
72228
|
-
// the anchor for its bundled docs (`package_content_installations` rows are
|
|
72229
|
-
// standalone content packages only). Excluded from BINDING_NAMESPACES: a
|
|
72230
|
-
// gone/edited doc is detected by the knowledge upgrade preview (live doc +
|
|
72231
|
-
// content-sha reads), never by validateBinding's live-id sweep.
|
|
72232
|
-
knowledge: bindingMapSchema.default({})
|
|
72233
|
-
});
|
|
72234
|
-
var BINDING_NAMESPACES = ["entities", "fields", "options", "templates", "roles"];
|
|
72235
|
-
var contentBindingMapSchema = zod_default.record(zod_default.string().min(1), zod_default.string().min(1));
|
|
72236
|
-
var packageContentBindingSchema = zod_default.object({
|
|
72237
|
-
knowledge: contentBindingMapSchema.default({}),
|
|
72238
|
-
templates: contentBindingMapSchema.default({})
|
|
72239
|
-
});
|
|
72240
|
-
var bindingDriftSchema = zod_default.object({
|
|
72241
|
-
namespace: zod_default.enum(BINDING_NAMESPACES),
|
|
72242
|
-
alias: zod_default.string(),
|
|
72243
|
-
id: zod_default.string().describe("The stale concrete id the alias was bound to")
|
|
72244
|
-
});
|
|
72245
|
-
var driftResolutionSchema = zod_default.union([
|
|
72246
|
-
zod_default.literal("recreate"),
|
|
72247
|
-
zod_default.object({ bind_to: zod_default.string().min(1) })
|
|
72248
|
-
]);
|
|
72249
|
-
var MODIFIED_ARTIFACT_KINDS = ["queries", "workflows", "agents", "template"];
|
|
72250
|
-
var modifiedArtifactSchema = zod_default.object({
|
|
72251
|
-
kind: zod_default.enum(MODIFIED_ARTIFACT_KINDS),
|
|
72252
|
-
alias: zod_default.string(),
|
|
72253
|
-
// Templates only: the OLD pinned contract carried no content_sha256, so the
|
|
72254
|
-
// preview cannot attribute the divergence from the target to a local edit vs.
|
|
72255
|
-
// the older upstream content — a one-time consent, converging once a
|
|
72256
|
-
// sha-carrying version is pinned. Surfaces can say "can't verify local edits
|
|
72257
|
-
// (older package version)".
|
|
72258
|
-
baseline_unknown: zod_default.boolean().optional()
|
|
72259
|
-
});
|
|
72260
|
-
var packageArtifactHashesSchema = zod_default.object({
|
|
72261
|
-
queries: zod_default.record(zod_default.string(), zod_default.string()),
|
|
72262
|
-
workflows: zod_default.record(zod_default.string(), zod_default.string()),
|
|
72263
|
-
agents: zod_default.record(zod_default.string(), zod_default.string())
|
|
72264
|
-
});
|
|
72265
|
-
var modificationResolutionSchema = zod_default.union([zod_default.literal("revert"), zod_default.literal("keep")]);
|
|
72266
|
-
var KNOWLEDGE_UPGRADE_CHANGES = ["added", "changed", "removed", "drifted"];
|
|
72267
|
-
var knowledgeUpgradeEntrySchema = zod_default.object({
|
|
72268
|
-
alias: zod_default.string(),
|
|
72269
|
-
name: zod_default.string().describe("The doc's display name \u2014 the target contract's name, or the live name for a drifted doc"),
|
|
72270
|
-
change: zod_default.enum(KNOWLEDGE_UPGRADE_CHANGES),
|
|
72271
|
-
/** `changed`/`removed` only: the live doc's content diverged from the OLD pinned sha. */
|
|
72272
|
-
modified: zod_default.boolean(),
|
|
72273
|
-
/** The bound live doc id; null for `added`, or for a `drifted` doc that is gone. */
|
|
72274
|
-
doc_id: zod_default.string().nullable()
|
|
72275
|
-
});
|
|
72276
|
-
function knowledgeEntryNeedsConsent(entry) {
|
|
72277
|
-
if (entry.change === "drifted") return true;
|
|
72278
|
-
if (entry.change === "changed" || entry.change === "removed") return entry.modified;
|
|
72279
|
-
return false;
|
|
72280
|
-
}
|
|
72281
|
-
var knowledgeResolutionSchema = zod_default.enum(["apply", "keep", "archive", "recreate", "unbind"]);
|
|
72282
|
-
var upgradeResolutionsSchema = zod_default.record(
|
|
72283
|
-
zod_default.string(),
|
|
72284
|
-
zod_default.union([driftResolutionSchema, modificationResolutionSchema, knowledgeResolutionSchema])
|
|
72285
|
-
);
|
|
72286
|
-
var knowledgeBindConsentSchema = zod_default.record(zod_default.string(), zod_default.string());
|
|
72287
|
-
var knowledgeUpgradeResolutionsSchema = zod_default.object({
|
|
72288
|
-
resolutions: zod_default.record(zod_default.string(), knowledgeResolutionSchema).default({}),
|
|
72289
|
-
bind_to: knowledgeBindConsentSchema.default({})
|
|
72290
|
-
});
|
|
72291
|
-
var knowledgeBoundRefSchema = zod_default.object({
|
|
72292
|
-
alias: zod_default.string(),
|
|
72293
|
-
name: zod_default.string(),
|
|
72294
|
-
/** The bound doc id; null when the bound doc is gone/archived (drift). */
|
|
72295
|
-
doc_id: zod_default.string().nullable()
|
|
72296
|
-
});
|
|
72297
|
-
var appInstallationConfigValueSchema = zod_default.union([zod_default.string(), zod_default.number(), zod_default.boolean()]);
|
|
72298
|
-
var appInstallationConfigSchema = zod_default.record(
|
|
72299
|
-
contractAliasSchema,
|
|
72300
|
-
appInstallationConfigValueSchema
|
|
72301
|
-
);
|
|
72302
|
-
var appInstallationProvenanceSchema = zod_default.enum(["install", "adopt"]);
|
|
72303
|
-
|
|
72304
71093
|
// ../shared/src/agent_instructions.ts
|
|
72305
71094
|
function agentFilePath(alias) {
|
|
72306
71095
|
return `src/agents/${alias}.md`;
|
|
@@ -72317,7 +71106,10 @@ ${args.instructions.replace(/\s+$/, "")}
|
|
|
72317
71106
|
`;
|
|
72318
71107
|
}
|
|
72319
71108
|
function stripAgentHeader(text) {
|
|
72320
|
-
return text.replace(/<!--\s*lotics:[\s\S]*?-->\n?/g, "")
|
|
71109
|
+
return normalizeAgentInstructions(text.replace(/<!--\s*lotics:[\s\S]*?-->\n?/g, ""));
|
|
71110
|
+
}
|
|
71111
|
+
function normalizeAgentInstructions(text) {
|
|
71112
|
+
return text.replace(/\n{3,}/g, "\n\n").trim();
|
|
72321
71113
|
}
|
|
72322
71114
|
|
|
72323
71115
|
// src/npm_registry.ts
|
|
@@ -72436,6 +71228,49 @@ function writeSynced(projectDir, kind, alias, entry) {
|
|
|
72436
71228
|
pkg2.lotics.synced[kind] = { ...pkg2.lotics.synced[kind], [alias]: entry };
|
|
72437
71229
|
fs8.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
|
|
72438
71230
|
}
|
|
71231
|
+
function readManifestEntry(projectDir, kind, alias) {
|
|
71232
|
+
const pkg2 = readManifest(projectDir);
|
|
71233
|
+
if (!pkg2.lotics) return { found: false };
|
|
71234
|
+
const entry = { found: true };
|
|
71235
|
+
let found = false;
|
|
71236
|
+
const declarations = pkg2.lotics[kind];
|
|
71237
|
+
if (declarations && typeof declarations === "object" && !Array.isArray(declarations)) {
|
|
71238
|
+
const map3 = declarations;
|
|
71239
|
+
if (alias in map3) {
|
|
71240
|
+
entry.declaration = map3[alias];
|
|
71241
|
+
found = true;
|
|
71242
|
+
}
|
|
71243
|
+
}
|
|
71244
|
+
const baselines = pkg2.lotics.synced?.[kind];
|
|
71245
|
+
if (baselines && alias in baselines) {
|
|
71246
|
+
entry.synced = baselines[alias];
|
|
71247
|
+
found = true;
|
|
71248
|
+
}
|
|
71249
|
+
return found ? entry : { found: false };
|
|
71250
|
+
}
|
|
71251
|
+
function readManifest(projectDir) {
|
|
71252
|
+
const pkgPath2 = path10.join(projectDir, "package.json");
|
|
71253
|
+
return JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
|
|
71254
|
+
}
|
|
71255
|
+
function removeFromManifest(projectDir, kind, alias) {
|
|
71256
|
+
const pkgPath2 = path10.join(projectDir, "package.json");
|
|
71257
|
+
const pkg2 = readManifest(projectDir);
|
|
71258
|
+
if (!pkg2.lotics) return;
|
|
71259
|
+
const declarations = pkg2.lotics[kind];
|
|
71260
|
+
if (declarations && typeof declarations === "object" && !Array.isArray(declarations)) {
|
|
71261
|
+
delete declarations[alias];
|
|
71262
|
+
}
|
|
71263
|
+
const baselines = pkg2.lotics.synced?.[kind];
|
|
71264
|
+
if (baselines) delete baselines[alias];
|
|
71265
|
+
fs8.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
|
|
71266
|
+
}
|
|
71267
|
+
function parkPrunedDeclaration(projectDir, kind, alias, removed) {
|
|
71268
|
+
const dir = path10.join(projectDir, ".lotics", "pruned", kind);
|
|
71269
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
71270
|
+
const file2 = path10.join(dir, `${alias}.json`);
|
|
71271
|
+
fs8.writeFileSync(file2, JSON.stringify(removed, null, 2) + "\n");
|
|
71272
|
+
return path10.relative(projectDir, file2);
|
|
71273
|
+
}
|
|
72439
71274
|
var WORKFLOWS_DIR = path10.join("src", "workflows");
|
|
72440
71275
|
var WORKFLOW_GLOBALS_DIR = path10.join(".lotics", "workflows");
|
|
72441
71276
|
var AGENTS_DIR = path10.join("src", "agents");
|
|
@@ -72585,13 +71420,52 @@ function writeAgentFiles(projectDir, agents, opts) {
|
|
|
72585
71420
|
}
|
|
72586
71421
|
return written;
|
|
72587
71422
|
}
|
|
71423
|
+
function parkLiveAgentProse(projectDir, alias, instructions) {
|
|
71424
|
+
const dir = path10.join(projectDir, ".lotics", "agents");
|
|
71425
|
+
const file2 = path10.join(dir, `${alias}.live.md`);
|
|
71426
|
+
try {
|
|
71427
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
71428
|
+
fs8.writeFileSync(file2, normalizeAgentInstructions(instructions) + "\n");
|
|
71429
|
+
return path10.relative(projectDir, file2);
|
|
71430
|
+
} catch (err2) {
|
|
71431
|
+
console.error(
|
|
71432
|
+
`\u26A0 Could not write the live prose for ${alias} to ${path10.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
71433
|
+
);
|
|
71434
|
+
return null;
|
|
71435
|
+
}
|
|
71436
|
+
}
|
|
71437
|
+
function reportUnseenLive(kind, unseen, appId) {
|
|
71438
|
+
if (unseen.length === 0) return;
|
|
71439
|
+
const plural = unseen.length === 1;
|
|
71440
|
+
console.error(
|
|
71441
|
+
`
|
|
71442
|
+
\u26A0 Kept your ${plural ? kind : `${kind}s`} for ` + unseen.map((u) => u.parked ? `${u.alias} (live copy written to ${u.parked})` : u.alias).join(", ") + ` \u2014 and the live ${kind} has CHANGED since this checkout last saw it, so somebody else edited ${plural ? "it" : "them"}.
|
|
71443
|
+
Your next deploy will be REFUSED for ${plural ? "this alias" : "these aliases"}, which is the point: pushing would overwrite their edit.
|
|
71444
|
+
Merge what you want from the live copy into your file and deploy, or run 'lotics app pull ${appId} --force' to take the live version and discard yours.`
|
|
71445
|
+
);
|
|
71446
|
+
}
|
|
71447
|
+
function parkLiveWorkflowBody(projectDir, alias, source) {
|
|
71448
|
+
const dir = path10.join(projectDir, WORKFLOW_GLOBALS_DIR);
|
|
71449
|
+
const file2 = path10.join(dir, `${alias}.live.ts`);
|
|
71450
|
+
try {
|
|
71451
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
71452
|
+
fs8.writeFileSync(file2, normalizeWorkflowBody(source) + "\n");
|
|
71453
|
+
return path10.relative(projectDir, file2);
|
|
71454
|
+
} catch (err2) {
|
|
71455
|
+
console.error(
|
|
71456
|
+
`\u26A0 Could not write the live body for ${alias} to ${path10.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
71457
|
+
);
|
|
71458
|
+
return null;
|
|
71459
|
+
}
|
|
71460
|
+
}
|
|
72588
71461
|
function localPromptUnpushed(projectDir, alias, live) {
|
|
72589
71462
|
const file2 = agentFilePath2(projectDir, alias);
|
|
72590
71463
|
if (!fs8.existsSync(file2)) return false;
|
|
72591
|
-
const onDisk = fs8.readFileSync(file2, "utf-8");
|
|
71464
|
+
const onDisk = stripAgentHeader(fs8.readFileSync(file2, "utf-8"));
|
|
71465
|
+
if (onDisk === normalizeAgentInstructions(live)) return false;
|
|
72592
71466
|
const baseline = readSynced(projectDir).agents[alias]?.content;
|
|
72593
|
-
if (baseline === void 0) return
|
|
72594
|
-
return contentSha(
|
|
71467
|
+
if (baseline === void 0) return true;
|
|
71468
|
+
return contentSha(onDisk) !== baseline;
|
|
72595
71469
|
}
|
|
72596
71470
|
function generatedWorkflowDescription(appName, alias) {
|
|
72597
71471
|
return `Workflow invoked by app "${appName}" via useWorkflow("${alias}").`;
|
|
@@ -72600,14 +71474,15 @@ function localBodyUnpushed(projectDir, alias, live) {
|
|
|
72600
71474
|
const file2 = workflowFilePath(projectDir, alias);
|
|
72601
71475
|
if (!fs8.existsSync(file2)) return false;
|
|
72602
71476
|
const onDisk = fs8.readFileSync(file2, "utf-8");
|
|
71477
|
+
if (stripWorkflowHeader(onDisk).trim() === normalizeWorkflowBody(live).trim()) return false;
|
|
72603
71478
|
const baseline = readSynced(projectDir).workflows[alias]?.content;
|
|
72604
|
-
if (baseline === void 0)
|
|
72605
|
-
return stripWorkflowHeader(onDisk).trim() !== normalizeWorkflowBody(live).trim();
|
|
72606
|
-
}
|
|
71479
|
+
if (baseline === void 0) return true;
|
|
72607
71480
|
return contentSha(stripWorkflowHeader(onDisk)) !== baseline;
|
|
72608
71481
|
}
|
|
72609
71482
|
async function writeWorkflowFiles(client, projectDir, app_id, appName, workflows, opts) {
|
|
72610
71483
|
const written = [];
|
|
71484
|
+
const kept = [];
|
|
71485
|
+
const unseenLive = [];
|
|
72611
71486
|
for (const [alias, declaration] of Object.entries(workflows)) {
|
|
72612
71487
|
const res = await client.getAppWorkflow(app_id, alias);
|
|
72613
71488
|
if (res.error && !isMissingWorkflowBodyError(res.error)) {
|
|
@@ -72632,7 +71507,16 @@ async function writeWorkflowFiles(client, projectDir, app_id, appName, workflows
|
|
|
72632
71507
|
toWorkflowDtsDeclaration(declaration)
|
|
72633
71508
|
);
|
|
72634
71509
|
if (!opts.overwrite && localBodyUnpushed(projectDir, alias, source)) {
|
|
72635
|
-
|
|
71510
|
+
kept.push(`src/workflows/${alias}.ts`);
|
|
71511
|
+
const previous = readSynced(projectDir).workflows[alias];
|
|
71512
|
+
if (body_sha && (previous?.live === void 0 || previous.live === body_sha)) {
|
|
71513
|
+
writeSynced(projectDir, "workflows", alias, { ...previous, live: body_sha });
|
|
71514
|
+
} else if (body_sha) {
|
|
71515
|
+
unseenLive.push({
|
|
71516
|
+
alias,
|
|
71517
|
+
parked: parkLiveWorkflowBody(projectDir, alias, source)
|
|
71518
|
+
});
|
|
71519
|
+
}
|
|
72636
71520
|
continue;
|
|
72637
71521
|
}
|
|
72638
71522
|
writeWorkflowFile(projectDir, alias, source, envelope2);
|
|
@@ -72656,7 +71540,7 @@ async function writeWorkflowFiles(client, projectDir, app_id, appName, workflows
|
|
|
72656
71540
|
}
|
|
72657
71541
|
written.push(alias);
|
|
72658
71542
|
}
|
|
72659
|
-
return written;
|
|
71543
|
+
return { written, kept, unseenLive };
|
|
72660
71544
|
}
|
|
72661
71545
|
function writeWorkflowDescription(projectDir, alias, description) {
|
|
72662
71546
|
const pkgPath2 = path10.join(projectDir, "package.json");
|
|
@@ -72712,6 +71596,16 @@ function runNpm(args, cwd) {
|
|
|
72712
71596
|
});
|
|
72713
71597
|
});
|
|
72714
71598
|
}
|
|
71599
|
+
function npmInstallArgs(hasLockfile) {
|
|
71600
|
+
return [hasLockfile ? "ci" : "install", "--ignore-scripts"];
|
|
71601
|
+
}
|
|
71602
|
+
function runNpmInstall(cwd) {
|
|
71603
|
+
const hasLockfile = fs8.existsSync(path10.join(cwd, "package-lock.json"));
|
|
71604
|
+
console.error(
|
|
71605
|
+
hasLockfile ? "Installing npm dependencies (npm ci \u2014 the lockfile's exact tree, no install scripts)..." : "Installing npm dependencies (no lockfile yet \u2014 resolving ranges, no install scripts)..."
|
|
71606
|
+
);
|
|
71607
|
+
return runNpm(npmInstallArgs(hasLockfile), cwd);
|
|
71608
|
+
}
|
|
72715
71609
|
function readAppWorkspaceId(projectDir) {
|
|
72716
71610
|
try {
|
|
72717
71611
|
const pkgPath2 = path10.join(projectDir, "package.json");
|
|
@@ -72924,13 +71818,6 @@ function writeAppFields(projectDir, tables) {
|
|
|
72924
71818
|
fs8.writeFileSync(file2, generateAppFields(tables));
|
|
72925
71819
|
return file2;
|
|
72926
71820
|
}
|
|
72927
|
-
function writeBindingAppFields(projectDir, binding) {
|
|
72928
|
-
const dotLotics = path10.join(projectDir, ".lotics");
|
|
72929
|
-
fs8.mkdirSync(dotLotics, { recursive: true });
|
|
72930
|
-
const file2 = path10.join(dotLotics, "app_fields.ts");
|
|
72931
|
-
fs8.writeFileSync(file2, generatePackageAppFields(binding));
|
|
72932
|
-
return file2;
|
|
72933
|
-
}
|
|
72934
71821
|
async function writeGeneratedAppFields(client, projectDir, app, queries) {
|
|
72935
71822
|
if (client.viewAsMemberId) {
|
|
72936
71823
|
console.error(
|
|
@@ -72939,14 +71826,7 @@ async function writeGeneratedAppFields(client, projectDir, app, queries) {
|
|
|
72939
71826
|
return;
|
|
72940
71827
|
}
|
|
72941
71828
|
try {
|
|
72942
|
-
|
|
72943
|
-
const binding = await client.appBinding(app.app_id);
|
|
72944
|
-
const fieldsPath = writeBindingAppFields(projectDir, binding);
|
|
72945
|
-
const count = Object.keys(binding.fields).length;
|
|
72946
|
-
console.error(
|
|
72947
|
-
`Wrote ${fieldsPath} (binding form \u2014 linked to package ${app.package_id}; ${count} field alias${count === 1 ? "" : "es"} resolved per-install)`
|
|
72948
|
-
);
|
|
72949
|
-
} else {
|
|
71829
|
+
{
|
|
72950
71830
|
const tableIds = resolveCodegenTableIds(projectDir, queries);
|
|
72951
71831
|
const tables = await client.getWorkspaceSchema(tableIds);
|
|
72952
71832
|
const missing = tableIds.filter((id) => !tables.some((t) => t.id === id));
|
|
@@ -73068,19 +71948,14 @@ function ensureAppVitestSetup(projectDir) {
|
|
|
73068
71948
|
const setupPath = path10.join(projectDir, VITEST_SETUP_FILENAME);
|
|
73069
71949
|
if (!fs8.existsSync(setupPath)) {
|
|
73070
71950
|
fs8.writeFileSync(setupPath, VITEST_SETUP_CONTENT);
|
|
73071
|
-
console.error(`Wrote ${VITEST_SETUP_FILENAME} (
|
|
73072
|
-
} else if (!fs8.readFileSync(setupPath, "utf-8").includes("getAppBinding")) {
|
|
73073
|
-
console.error(
|
|
73074
|
-
`\u26A0 ${VITEST_SETUP_FILENAME} exists but does not stub getAppBinding \u2014 \`npm test\` will fail to collect any test that imports the app graph (the binding-form .lotics/app_fields.ts awaits a network call). Add the stub to it:
|
|
73075
|
-
${VITEST_SETUP_CONTENT}`
|
|
73076
|
-
);
|
|
71951
|
+
console.error(`Wrote ${VITEST_SETUP_FILENAME} (wired by vite.config.ts; empty until you fill it).`);
|
|
73077
71952
|
}
|
|
73078
71953
|
const viteConfigPath = path10.join(projectDir, "vite.config.ts");
|
|
73079
71954
|
if (!fs8.existsSync(viteConfigPath)) return;
|
|
73080
71955
|
const viteConfig = fs8.readFileSync(viteConfigPath, "utf-8");
|
|
73081
71956
|
if (/setupFiles\s*:/.test(viteConfig) && viteConfig.includes(VITEST_SETUP_FILENAME)) return;
|
|
73082
71957
|
console.error(
|
|
73083
|
-
`\u26A0 vite.config.ts does not wire ${VITEST_SETUP_FILENAME}
|
|
71958
|
+
`\u26A0 vite.config.ts does not wire ${VITEST_SETUP_FILENAME}. Nothing is broken by that \u2014 it is the slot for global test setup (matchers, stubs, timezone pinning). Add it to the \`test\` block when you need one:
|
|
73084
71959
|
setupFiles: ["./${VITEST_SETUP_FILENAME}"],`
|
|
73085
71960
|
);
|
|
73086
71961
|
}
|
|
@@ -73114,7 +71989,7 @@ async function appCodegen(args) {
|
|
|
73114
71989
|
await writeGeneratedAppFields(
|
|
73115
71990
|
args.client,
|
|
73116
71991
|
projectDir,
|
|
73117
|
-
{ app_id: meta3.app_id
|
|
71992
|
+
{ app_id: meta3.app_id },
|
|
73118
71993
|
meta3.queries ?? {}
|
|
73119
71994
|
);
|
|
73120
71995
|
} catch (err2) {
|
|
@@ -73233,8 +72108,7 @@ async function materializeScaffold(targetPath, files) {
|
|
|
73233
72108
|
}
|
|
73234
72109
|
console.error(`Scaffolded ${files.length} files into ${targetPath}`);
|
|
73235
72110
|
writeAppDts(targetPath, {});
|
|
73236
|
-
|
|
73237
|
-
await runNpm(["install"], targetPath);
|
|
72111
|
+
await runNpmInstall(targetPath);
|
|
73238
72112
|
writeAppDtsKitLinks(targetPath);
|
|
73239
72113
|
}
|
|
73240
72114
|
async function appCreate(client, args) {
|
|
@@ -73340,43 +72214,7 @@ function defaultPullTarget(appId, appName) {
|
|
|
73340
72214
|
}
|
|
73341
72215
|
return appDirName(appName);
|
|
73342
72216
|
}
|
|
73343
|
-
async function
|
|
73344
|
-
const app = await client.getApp(args.app_id);
|
|
73345
|
-
if (!app.current_version_id && args.version === void 0) {
|
|
73346
|
-
throw new Error(
|
|
73347
|
-
`App ${app.id} has no published version yet. Deploy from another machine first, or use 'lotics app create' to scaffold a new app.`
|
|
73348
|
-
);
|
|
73349
|
-
}
|
|
73350
|
-
const versionId = args.version ?? app.current_version_id;
|
|
73351
|
-
if (!versionId) throw new Error(`App ${app.id} has no version to pull.`);
|
|
73352
|
-
const version2 = await client.getAppVersion(app.id, versionId);
|
|
73353
|
-
const sourceUrl = await client.getAppVersionSourceUrl(app.id, version2.id);
|
|
73354
|
-
const targetPath = path10.resolve(args.targetPath ?? defaultPullTarget(app.id, app.name));
|
|
73355
|
-
fs8.mkdirSync(targetPath, { recursive: true });
|
|
73356
|
-
const prior = readPriorStamp(targetPath);
|
|
73357
|
-
const tmpFile = path10.join(tmpdir(), `lotics-app-${app.id}-${Date.now()}.tar.gz`);
|
|
73358
|
-
console.error(`Downloading source archive...`);
|
|
73359
|
-
await downloadToFile(sourceUrl, tmpFile);
|
|
73360
|
-
const keptLocal = [];
|
|
73361
|
-
const stagingDir = fs8.mkdtempSync(path10.join(tmpdir(), `lotics-pull-${app.id}-`));
|
|
73362
|
-
try {
|
|
73363
|
-
await runTar(["-xzf", tmpFile, "-C", stagingDir], stagingDir);
|
|
73364
|
-
console.error(`Extracting to ${targetPath}...`);
|
|
73365
|
-
keptLocal.push(
|
|
73366
|
-
...copyTree(stagingDir, targetPath, {
|
|
73367
|
-
overwrite: args.force === true,
|
|
73368
|
-
skip: [WORKFLOWS_DIR, AGENTS_DIR].map((d) => d.split(path10.sep).join("/"))
|
|
73369
|
-
})
|
|
73370
|
-
);
|
|
73371
|
-
} finally {
|
|
73372
|
-
if (fs8.existsSync(tmpFile)) fs8.unlinkSync(tmpFile);
|
|
73373
|
-
fs8.rmSync(stagingDir, { recursive: true, force: true });
|
|
73374
|
-
}
|
|
73375
|
-
const stamp = stampAfterPull({
|
|
73376
|
-
prior,
|
|
73377
|
-
pulled: { id: versionId, number: version2.version },
|
|
73378
|
-
keptCount: keptLocal.length
|
|
73379
|
-
});
|
|
72217
|
+
async function hydrateAppProject(client, targetPath, app, opts) {
|
|
73380
72218
|
stampPulledManifest(targetPath, {
|
|
73381
72219
|
app_id: app.id,
|
|
73382
72220
|
workspace_id: app.workspace_id,
|
|
@@ -73384,8 +72222,8 @@ async function appPull(client, args) {
|
|
|
73384
72222
|
// after pulling an OLD one would let the next deploy ship that old source as
|
|
73385
72223
|
// if it were built on the newest — the version guard exists to refuse
|
|
73386
72224
|
// exactly that, and it can only do so if this tells the truth.
|
|
73387
|
-
current_version_id: stamp.id,
|
|
73388
|
-
version_number: stamp.number,
|
|
72225
|
+
current_version_id: opts.stamp.id,
|
|
72226
|
+
version_number: opts.stamp.number,
|
|
73389
72227
|
workflows: app.workflows ?? {},
|
|
73390
72228
|
queries: app.queries ?? {},
|
|
73391
72229
|
agents: app.agents ?? {}
|
|
@@ -73397,42 +72235,106 @@ async function appPull(client, args) {
|
|
|
73397
72235
|
await writeGeneratedAppFields(
|
|
73398
72236
|
client,
|
|
73399
72237
|
targetPath,
|
|
73400
|
-
{ app_id: app.id
|
|
72238
|
+
{ app_id: app.id },
|
|
73401
72239
|
app.queries ?? {}
|
|
73402
72240
|
);
|
|
73403
72241
|
const workflows = app.workflows ?? {};
|
|
73404
72242
|
if (Object.keys(workflows).length > 0) {
|
|
73405
|
-
const written = await writeWorkflowFiles(
|
|
73406
|
-
|
|
73407
|
-
|
|
73408
|
-
|
|
72243
|
+
const { written, kept, unseenLive } = await writeWorkflowFiles(
|
|
72244
|
+
client,
|
|
72245
|
+
targetPath,
|
|
72246
|
+
app.id,
|
|
72247
|
+
app.name,
|
|
72248
|
+
workflows,
|
|
72249
|
+
{ overwrite: opts.force === true }
|
|
72250
|
+
);
|
|
72251
|
+
opts.kept.push(...kept);
|
|
73409
72252
|
if (written.length > 0) {
|
|
73410
72253
|
console.error(
|
|
73411
72254
|
`Wrote ${written.length} workflow ${written.length === 1 ? "body" : "bodies"} to ${WORKFLOWS_DIR}/ (${written.join(", ")})`
|
|
73412
72255
|
);
|
|
73413
72256
|
}
|
|
72257
|
+
reportUnseenLive("workflow body", unseenLive, app.id);
|
|
73414
72258
|
}
|
|
73415
72259
|
const agents = app.agents ?? {};
|
|
73416
72260
|
if (Object.keys(agents).length > 0) {
|
|
73417
72261
|
const written = writeAgentFiles(targetPath, agents, {
|
|
73418
|
-
overwrite:
|
|
73419
|
-
kept:
|
|
72262
|
+
overwrite: opts.force === true,
|
|
72263
|
+
kept: opts.kept
|
|
73420
72264
|
});
|
|
73421
|
-
|
|
73422
|
-
|
|
73423
|
-
|
|
73424
|
-
|
|
73425
|
-
|
|
72265
|
+
const unseenLiveProse = [];
|
|
72266
|
+
for (const [alias, declaration] of Object.entries(agents)) {
|
|
72267
|
+
const instructions = declaration?.instructions;
|
|
72268
|
+
if (typeof instructions !== "string") continue;
|
|
72269
|
+
const live = contentSha(instructions);
|
|
72270
|
+
if (written.includes(alias)) {
|
|
72271
|
+
writeSynced(targetPath, "agents", alias, {
|
|
72272
|
+
content: contentSha(normalizeAgentInstructions(instructions)),
|
|
72273
|
+
live
|
|
72274
|
+
});
|
|
72275
|
+
continue;
|
|
72276
|
+
}
|
|
72277
|
+
const previous = readSynced(targetPath).agents[alias];
|
|
72278
|
+
if (previous?.live === void 0 || previous.live === live) {
|
|
72279
|
+
writeSynced(targetPath, "agents", alias, { ...previous, live });
|
|
72280
|
+
continue;
|
|
72281
|
+
}
|
|
72282
|
+
unseenLiveProse.push({ alias, parked: parkLiveAgentProse(targetPath, alias, instructions) });
|
|
73426
72283
|
}
|
|
73427
72284
|
if (written.length > 0) {
|
|
73428
72285
|
console.error(
|
|
73429
72286
|
`Wrote ${written.length} agent instruction ${written.length === 1 ? "file" : "files"} to ${AGENTS_DIR}/ (${written.join(", ")})`
|
|
73430
72287
|
);
|
|
73431
72288
|
}
|
|
72289
|
+
reportUnseenLive("prompt", unseenLiveProse, app.id);
|
|
73432
72290
|
}
|
|
73433
|
-
|
|
73434
|
-
await runNpm(["install"], targetPath);
|
|
72291
|
+
await runNpmInstall(targetPath);
|
|
73435
72292
|
writeAppDtsKitLinks(targetPath);
|
|
72293
|
+
}
|
|
72294
|
+
async function appPull(client, args) {
|
|
72295
|
+
const app = await client.getApp(args.app_id);
|
|
72296
|
+
if (!app.current_version_id && args.version === void 0) {
|
|
72297
|
+
throw new Error(
|
|
72298
|
+
`App ${app.id} has no published version yet. Deploy from another machine first, or use 'lotics app create' to scaffold a new app.`
|
|
72299
|
+
);
|
|
72300
|
+
}
|
|
72301
|
+
const versionId = args.version ?? app.current_version_id;
|
|
72302
|
+
if (!versionId) throw new Error(`App ${app.id} has no version to pull.`);
|
|
72303
|
+
const version2 = await client.getAppVersion(app.id, versionId);
|
|
72304
|
+
const sourceUrl = await client.getAppVersionSourceUrl(app.id, version2.id);
|
|
72305
|
+
const targetPath = path10.resolve(args.targetPath ?? defaultPullTarget(app.id, app.name));
|
|
72306
|
+
fs8.mkdirSync(targetPath, { recursive: true });
|
|
72307
|
+
const prior = readPriorStamp(targetPath);
|
|
72308
|
+
const tmpFile = path10.join(tmpdir(), `lotics-app-${app.id}-${Date.now()}.tar.gz`);
|
|
72309
|
+
console.error(`Downloading source archive...`);
|
|
72310
|
+
await downloadToFile(sourceUrl, tmpFile);
|
|
72311
|
+
const keptLocal = [];
|
|
72312
|
+
const restoredFromArchive = [];
|
|
72313
|
+
const stagingDir = fs8.mkdtempSync(path10.join(tmpdir(), `lotics-pull-${app.id}-`));
|
|
72314
|
+
try {
|
|
72315
|
+
await runTar(["-xzf", tmpFile, "-C", stagingDir], stagingDir);
|
|
72316
|
+
console.error(`Extracting to ${targetPath}...`);
|
|
72317
|
+
const copied = copyTree(stagingDir, targetPath, {
|
|
72318
|
+
overwrite: args.force === true,
|
|
72319
|
+
skip: [WORKFLOWS_DIR, AGENTS_DIR].map((d) => d.split(path10.sep).join("/"))
|
|
72320
|
+
});
|
|
72321
|
+
keptLocal.push(...copied.kept);
|
|
72322
|
+
restoredFromArchive.push(...copied.created);
|
|
72323
|
+
} finally {
|
|
72324
|
+
if (fs8.existsSync(tmpFile)) fs8.unlinkSync(tmpFile);
|
|
72325
|
+
fs8.rmSync(stagingDir, { recursive: true, force: true });
|
|
72326
|
+
}
|
|
72327
|
+
const stamp = stampAfterPull({
|
|
72328
|
+
prior,
|
|
72329
|
+
pulled: { id: versionId, number: version2.version },
|
|
72330
|
+
keptCount: keptLocal.length
|
|
72331
|
+
});
|
|
72332
|
+
await hydrateAppProject(client, targetPath, app, {
|
|
72333
|
+
stamp: { id: stamp.id, number: stamp.number },
|
|
72334
|
+
...args.force !== void 0 ? { force: args.force } : {},
|
|
72335
|
+
kept: keptLocal
|
|
72336
|
+
});
|
|
72337
|
+
reportRestoredFiles(restoredFromArchive, prior !== null);
|
|
73436
72338
|
reportKeptLocalFiles(keptLocal, app.id, {
|
|
73437
72339
|
// `prior` is non-null whenever the stamp was held — `stampAfterPull` cannot
|
|
73438
72340
|
// hold against nothing — so the fallback only covers the un-held branch,
|
|
@@ -73490,7 +72392,7 @@ async function appDeploy(client, args) {
|
|
|
73490
72392
|
await writeGeneratedAppFields(
|
|
73491
72393
|
client,
|
|
73492
72394
|
projectDir,
|
|
73493
|
-
{ app_id: meta3.app_id
|
|
72395
|
+
{ app_id: meta3.app_id },
|
|
73494
72396
|
meta3.queries ?? {}
|
|
73495
72397
|
);
|
|
73496
72398
|
} catch (err2) {
|
|
@@ -73594,7 +72496,8 @@ async function appDeploy(client, args) {
|
|
|
73594
72496
|
if (args.prune) {
|
|
73595
72497
|
await pruneOrphanedBindings(
|
|
73596
72498
|
client,
|
|
73597
|
-
|
|
72499
|
+
projectDir,
|
|
72500
|
+
{ app_id: meta3.app_id },
|
|
73598
72501
|
orphanedBindings(called, liveAfter),
|
|
73599
72502
|
called.dynamic
|
|
73600
72503
|
);
|
|
@@ -73650,80 +72553,6 @@ async function readLiveQueries(client, appId) {
|
|
|
73650
72553
|
process.exit(1);
|
|
73651
72554
|
}
|
|
73652
72555
|
}
|
|
73653
|
-
async function installCommand(client, args) {
|
|
73654
|
-
const res = await client.installPackage(args.packageId, {});
|
|
73655
|
-
if (res.kind === "app") {
|
|
73656
|
-
const { app } = res;
|
|
73657
|
-
console.error(
|
|
73658
|
-
`Installed "${app.name}" (${app.id})` + (app.package_version !== null ? ` at v${app.package_version}` : "") + `.
|
|
73659
|
-
Open it from the workspace's app launcher.
|
|
73660
|
-
To work on it locally: lotics app pull ${app.id}
|
|
73661
|
-
To give it an address: lotics app subdomain <slug> (from inside that project)`
|
|
73662
|
-
);
|
|
73663
|
-
reportKnowledgeWarnings(res.knowledge_warnings);
|
|
73664
|
-
return;
|
|
73665
|
-
}
|
|
73666
|
-
console.error(
|
|
73667
|
-
`Installed content package (${res.installation.id}).
|
|
73668
|
-
Its documents and templates are now in this workspace.`
|
|
73669
|
-
);
|
|
73670
|
-
reportKnowledgeWarnings(res.warnings);
|
|
73671
|
-
}
|
|
73672
|
-
function reportKnowledgeWarnings(warnings) {
|
|
73673
|
-
const missing = warnings.missing_expected_docs;
|
|
73674
|
-
if (missing.length === 0) return;
|
|
73675
|
-
console.error(
|
|
73676
|
-
`
|
|
73677
|
-
\u26A0 ${missing.length} expected knowledge doc(s) are missing from this workspace:
|
|
73678
|
-
` + missing.map((name2) => ` \u2022 ${name2}`).join("\n") + `
|
|
73679
|
-
An agent declaring one of these reads nothing from it \u2014 the run still completes,
|
|
73680
|
-
answering from nowhere. Create them, then re-run the install.`
|
|
73681
|
-
);
|
|
73682
|
-
}
|
|
73683
|
-
async function upgradeCommand(client, args) {
|
|
73684
|
-
const projectDir = path10.resolve(args.projectDir ?? process.cwd());
|
|
73685
|
-
const meta3 = readAppMeta(projectDir);
|
|
73686
|
-
const plan = await client.previewPackageUpgrade(meta3.app_id, {});
|
|
73687
|
-
if (plan.from_version === plan.to_version) {
|
|
73688
|
-
console.error(`Already on v${plan.from_version} \u2014 nothing to take.`);
|
|
73689
|
-
return;
|
|
73690
|
-
}
|
|
73691
|
-
const blockers = [
|
|
73692
|
-
...plan.diff.breaking.map(
|
|
73693
|
-
(b) => ` \u2022 breaking: ${b.entity}.${b.alias} ${b.kind} ${b.from} \u2192 ${b.to}`
|
|
73694
|
-
),
|
|
73695
|
-
...plan.modified.map(
|
|
73696
|
-
(m) => ` \u2022 locally modified: ${m.kind} "${m.alias}"` + (m.baseline_unknown === true ? " (no baseline recorded \u2014 cannot tell what changed)" : "")
|
|
73697
|
-
),
|
|
73698
|
-
...plan.drift.map((d) => ` \u2022 drifted: ${d.namespace} "${d.alias}"`),
|
|
73699
|
-
// The FOURTH refusal source, and the one this originally missed. The server
|
|
73700
|
-
// throws a BadRequestError for every entry `knowledgeEntryNeedsConsent`
|
|
73701
|
-
// accepts, so leaving it out did not make those upgrades work — it swapped
|
|
73702
|
-
// the carefully-framed refusal for a raw wire 400. Read the canonical
|
|
73703
|
-
// predicate rather than re-deriving the rule: a hand-listed subset of a
|
|
73704
|
-
// server-side decision is how three of four got covered in the first place.
|
|
73705
|
-
...plan.knowledge.filter(knowledgeEntryNeedsConsent).map(
|
|
73706
|
-
(k) => ` \u2022 knowledge: "${k.alias}" (${k.change}${k.modified ? ", locally edited" : ""})`
|
|
73707
|
-
)
|
|
73708
|
-
];
|
|
73709
|
-
if (blockers.length > 0) {
|
|
73710
|
-
console.error(
|
|
73711
|
-
`v${plan.from_version} \u2192 v${plan.to_version} needs decisions this command will not make for you:
|
|
73712
|
-
` + blockers.join("\n") + `
|
|
73713
|
-
|
|
73714
|
-
Each one resolves by choosing what to KEEP, and guessing would discard
|
|
73715
|
-
work nobody asked to lose. Resolve them, or ask an operator to run the
|
|
73716
|
-
upgrade with explicit resolutions.`
|
|
73717
|
-
);
|
|
73718
|
-
process.exit(1);
|
|
73719
|
-
}
|
|
73720
|
-
const applied = await client.upgradePackage(meta3.app_id, { version: plan.to_version });
|
|
73721
|
-
console.error(
|
|
73722
|
-
`Upgraded to v${applied.package_version ?? plan.to_version}.` + (plan.changelog ? `
|
|
73723
|
-
${plan.changelog}` : "") + `
|
|
73724
|
-
Run \`lotics app pull\` to bring this checkout in step.`
|
|
73725
|
-
);
|
|
73726
|
-
}
|
|
73727
72556
|
async function appCheck(client, args = {}) {
|
|
73728
72557
|
const projectDir = path10.resolve(args.projectDir ?? process.cwd());
|
|
73729
72558
|
const meta3 = readAppMeta(projectDir);
|
|
@@ -73836,7 +72665,7 @@ function driftedAgentAliases(projectDir, liveAgents) {
|
|
|
73836
72665
|
const file2 = agentFilePath2(projectDir, alias);
|
|
73837
72666
|
if (!fs8.existsSync(file2)) continue;
|
|
73838
72667
|
const local = stripAgentHeader(fs8.readFileSync(file2, "utf-8"));
|
|
73839
|
-
if (local === "" || local === (live.instructions ?? "")) continue;
|
|
72668
|
+
if (local === "" || local === normalizeAgentInstructions(live.instructions ?? "")) continue;
|
|
73840
72669
|
drifted.push(alias);
|
|
73841
72670
|
}
|
|
73842
72671
|
return drifted.sort();
|
|
@@ -73898,28 +72727,31 @@ function warnAboutOrphanedBindings(called, live) {
|
|
|
73898
72727
|
);
|
|
73899
72728
|
return lines.length;
|
|
73900
72729
|
}
|
|
73901
|
-
async function pruneOrphanedBindings(client,
|
|
72730
|
+
async function pruneOrphanedBindings(client, projectDir, app, orphans, dynamic) {
|
|
73902
72731
|
const targets = [
|
|
73903
72732
|
...orphans.queries.map((alias) => ({
|
|
73904
72733
|
tool: "remove_app_query",
|
|
72734
|
+
kind: "queries",
|
|
73905
72735
|
alias,
|
|
73906
72736
|
label: `query ${alias}`,
|
|
73907
|
-
|
|
72737
|
+
setCommand: `lotics app query set ${alias}`
|
|
73908
72738
|
})),
|
|
73909
72739
|
...orphans.workflows.map((alias) => ({
|
|
73910
72740
|
tool: "remove_app_workflow",
|
|
72741
|
+
kind: "workflows",
|
|
73911
72742
|
alias,
|
|
73912
72743
|
label: `workflow ${alias}`,
|
|
73913
|
-
|
|
72744
|
+
setCommand: `lotics app workflow set ${alias}`
|
|
73914
72745
|
})),
|
|
73915
72746
|
...orphans.agents.map((alias) => ({
|
|
73916
72747
|
tool: "remove_app_agent",
|
|
72748
|
+
kind: "agents",
|
|
73917
72749
|
alias,
|
|
73918
72750
|
label: `agent ${alias}`,
|
|
73919
|
-
|
|
72751
|
+
setCommand: `lotics app agent set ${alias}`
|
|
73920
72752
|
}))
|
|
73921
72753
|
];
|
|
73922
|
-
if (targets.length === 0) return
|
|
72754
|
+
if (targets.length === 0) return;
|
|
73923
72755
|
if (dynamic.length > 0) {
|
|
73924
72756
|
console.error(
|
|
73925
72757
|
`
|
|
@@ -73927,19 +72759,63 @@ async function pruneOrphanedBindings(client, appId, orphans, dynamic) {
|
|
|
73927
72759
|
` + targets.map((t) => ` \u2022 ${t.label}`).join("\n") + `
|
|
73928
72760
|
Make those call sites literal and the next deploy will clean them up, or remove the ones you know are dead by hand.`
|
|
73929
72761
|
);
|
|
73930
|
-
return
|
|
72762
|
+
return;
|
|
73931
72763
|
}
|
|
73932
|
-
|
|
72764
|
+
const tablesBefore = new Set(resolveCodegenTableIds(projectDir, readAppMeta(projectDir).queries ?? {}));
|
|
72765
|
+
let removedLocally = false;
|
|
73933
72766
|
for (const target of targets) {
|
|
73934
|
-
const res = await client.execute(target.tool, { app_id:
|
|
72767
|
+
const res = await client.execute(target.tool, { app_id: app.app_id, alias: target.alias });
|
|
73935
72768
|
if (res.error) {
|
|
73936
|
-
failed += 1;
|
|
73937
72769
|
console.error(` \u2717 could not unbind ${target.label} \u2014 ${res.error}`);
|
|
73938
72770
|
continue;
|
|
73939
72771
|
}
|
|
73940
|
-
|
|
72772
|
+
let line;
|
|
72773
|
+
try {
|
|
72774
|
+
const entry = readManifestEntry(projectDir, target.kind, target.alias);
|
|
72775
|
+
if (entry.found) {
|
|
72776
|
+
const parked = parkPrunedDeclaration(projectDir, target.kind, target.alias, {
|
|
72777
|
+
declaration: entry.declaration,
|
|
72778
|
+
synced: entry.synced
|
|
72779
|
+
});
|
|
72780
|
+
removeFromManifest(projectDir, target.kind, target.alias);
|
|
72781
|
+
removedLocally = true;
|
|
72782
|
+
line = ` \u2713 unbound ${target.label} + removed package.json#lotics.${target.kind}.${target.alias} \u2014 restore: put ${parked} back under lotics.${target.kind}.${target.alias}, then ${target.setCommand}`;
|
|
72783
|
+
} else {
|
|
72784
|
+
line = ` \u2713 unbound ${target.label} \u2014 nothing was declared for it in package.json, so there is nothing to restore from this project (recover it with lotics app pull --from-version <apv_\u2026>)`;
|
|
72785
|
+
}
|
|
72786
|
+
} catch (err2) {
|
|
72787
|
+
console.error(
|
|
72788
|
+
` \u2713 unbound ${target.label} server-side, but could not update the local project \u2014 ${err2 instanceof Error ? err2.message : String(err2)}. lotics.${target.kind}.${target.alias} is still declared: remove it by hand, or the next deploy re-creates the binding.`
|
|
72789
|
+
);
|
|
72790
|
+
continue;
|
|
72791
|
+
}
|
|
72792
|
+
console.error(line);
|
|
72793
|
+
}
|
|
72794
|
+
if (removedLocally) {
|
|
72795
|
+
try {
|
|
72796
|
+
const meta3 = readAppMeta(projectDir);
|
|
72797
|
+
writeAppDts(projectDir, {
|
|
72798
|
+
workflows: meta3.workflows,
|
|
72799
|
+
queries: meta3.queries,
|
|
72800
|
+
agents: meta3.agents
|
|
72801
|
+
});
|
|
72802
|
+
if (orphans.queries.length > 0) {
|
|
72803
|
+
const dropped = [...tablesBefore].filter(
|
|
72804
|
+
(id) => !resolveCodegenTableIds(projectDir, meta3.queries ?? {}).includes(id)
|
|
72805
|
+
);
|
|
72806
|
+
if (dropped.length > 0) {
|
|
72807
|
+
console.error(
|
|
72808
|
+
` \u26A0 .lotics/app_fields.ts no longer covers ${dropped.join(", ")} \u2014 ${dropped.length === 1 ? "that table was" : "those tables were"} named only by the pruned quer${orphans.queries.length === 1 ? "y" : "ies"}. If your source still uses F/OPT for ${dropped.length === 1 ? "it" : "them"}, add ${dropped.map((id) => `"${id}"`).join(", ")} to package.json#lotics.codegen.tables and re-run lotics app codegen.`
|
|
72809
|
+
);
|
|
72810
|
+
}
|
|
72811
|
+
await writeGeneratedAppFields(client, projectDir, app, meta3.queries ?? {});
|
|
72812
|
+
}
|
|
72813
|
+
} catch (err2) {
|
|
72814
|
+
console.error(
|
|
72815
|
+
` \u2717 could not refresh the generated companions after pruning \u2014 ${err2 instanceof Error ? err2.message : String(err2)}. Run lotics app codegen.`
|
|
72816
|
+
);
|
|
72817
|
+
}
|
|
73941
72818
|
}
|
|
73942
|
-
return failed;
|
|
73943
72819
|
}
|
|
73944
72820
|
function derivedDeployMessage(pending) {
|
|
73945
72821
|
const parts = [
|
|
@@ -73951,6 +72827,7 @@ function derivedDeployMessage(pending) {
|
|
|
73951
72827
|
}
|
|
73952
72828
|
function copyTree(from, to, opts, relative = "") {
|
|
73953
72829
|
const kept = [];
|
|
72830
|
+
const created = [];
|
|
73954
72831
|
for (const entry of fs8.readdirSync(from, { withFileTypes: true })) {
|
|
73955
72832
|
const src = path10.join(from, entry.name);
|
|
73956
72833
|
const dest = path10.join(to, entry.name);
|
|
@@ -73958,17 +72835,32 @@ function copyTree(from, to, opts, relative = "") {
|
|
|
73958
72835
|
if (opts.skip?.includes(rel.split(path10.sep).join("/"))) continue;
|
|
73959
72836
|
if (entry.isDirectory()) {
|
|
73960
72837
|
fs8.mkdirSync(dest, { recursive: true });
|
|
73961
|
-
|
|
72838
|
+
const child = copyTree(src, dest, opts, rel);
|
|
72839
|
+
kept.push(...child.kept);
|
|
72840
|
+
created.push(...child.created);
|
|
73962
72841
|
continue;
|
|
73963
72842
|
}
|
|
73964
|
-
|
|
72843
|
+
const existed = fs8.existsSync(dest);
|
|
72844
|
+
if (!opts.overwrite && existed) {
|
|
73965
72845
|
if (fs8.readFileSync(src).equals(fs8.readFileSync(dest))) continue;
|
|
73966
72846
|
kept.push(rel);
|
|
73967
72847
|
continue;
|
|
73968
72848
|
}
|
|
73969
72849
|
fs8.copyFileSync(src, dest);
|
|
72850
|
+
if (!existed) created.push(rel);
|
|
73970
72851
|
}
|
|
73971
|
-
return kept;
|
|
72852
|
+
return { kept, created };
|
|
72853
|
+
}
|
|
72854
|
+
function reportRestoredFiles(restored, isRefresh) {
|
|
72855
|
+
if (!isRefresh || restored.length === 0) return;
|
|
72856
|
+
const shown = restored.slice(0, 10);
|
|
72857
|
+
console.error(
|
|
72858
|
+
`
|
|
72859
|
+
Restored ${restored.length} file${restored.length === 1 ? "" : "s"} the app's last deployed source carries and your tree did not:
|
|
72860
|
+
` + shown.map((f) => ` \u2022 ${f}`).join("\n") + (restored.length > shown.length ? `
|
|
72861
|
+
\u2022 \u2026and ${restored.length - shown.length} more` : "") + `
|
|
72862
|
+
A pull mirrors the last DEPLOYED source, so a file you deleted here comes back until the deletion ships. Delete it again and run 'lotics app deploy' to make it stick.`
|
|
72863
|
+
);
|
|
73972
72864
|
}
|
|
73973
72865
|
function reportKeptLocalFiles(kept, appId, motion) {
|
|
73974
72866
|
if (kept.length === 0) return;
|
|
@@ -74528,15 +73420,19 @@ async function appWorkflowPull(client, args = {}) {
|
|
|
74528
73420
|
console.error(`App ${meta3.app_id} has no bound workflows.`);
|
|
74529
73421
|
return;
|
|
74530
73422
|
}
|
|
74531
|
-
const kept =
|
|
74532
|
-
|
|
74533
|
-
|
|
74534
|
-
|
|
74535
|
-
|
|
73423
|
+
const { written, kept, unseenLive } = await writeWorkflowFiles(
|
|
73424
|
+
client,
|
|
73425
|
+
projectDir,
|
|
73426
|
+
meta3.app_id,
|
|
73427
|
+
app.name,
|
|
73428
|
+
workflows,
|
|
73429
|
+
{ overwrite: args.force === true }
|
|
73430
|
+
);
|
|
74536
73431
|
console.error(
|
|
74537
73432
|
`Wrote ${written.length} workflow ${written.length === 1 ? "body" : "bodies"} to ${WORKFLOWS_DIR}/` + (written.length > 0 ? ` (${written.join(", ")})` : "")
|
|
74538
73433
|
);
|
|
74539
73434
|
reportKeptLocalFiles(kept, meta3.app_id, null);
|
|
73435
|
+
reportUnseenLive("workflow body", unseenLive, meta3.app_id);
|
|
74540
73436
|
ensureAppTsconfig(projectDir);
|
|
74541
73437
|
}
|
|
74542
73438
|
async function appWorkflowCheck(args) {
|
|
@@ -74669,6 +73565,10 @@ function parseArgs(argv) {
|
|
|
74669
73565
|
printCreated: false,
|
|
74670
73566
|
cleanup: false,
|
|
74671
73567
|
prune: false,
|
|
73568
|
+
noSampleData: false,
|
|
73569
|
+
adopt: false,
|
|
73570
|
+
entity: [],
|
|
73571
|
+
limit: void 0,
|
|
74672
73572
|
version: false,
|
|
74673
73573
|
help: false
|
|
74674
73574
|
};
|
|
@@ -74680,6 +73580,23 @@ function parseArgs(argv) {
|
|
|
74680
73580
|
let i2 = 0;
|
|
74681
73581
|
while (i2 < argv.length) {
|
|
74682
73582
|
const arg = argv[i2];
|
|
73583
|
+
if (subcommand !== void 0 && commandOwnsTail(command) && arg !== "--help" && arg !== "-h") {
|
|
73584
|
+
const local = subcommandArgs(command, subcommand);
|
|
73585
|
+
const looksLikeFlag = arg.length > 1 && arg.startsWith("-");
|
|
73586
|
+
const declared = looksLikeFlag && local !== void 0 && matchesKnownFlag([...local.valueFlags ?? [], ...local.flags ?? []], arg);
|
|
73587
|
+
if (declared) {
|
|
73588
|
+
restArgs.push(arg);
|
|
73589
|
+
if ((local?.valueFlags ?? []).includes(arg) && i2 + 1 < argv.length) restArgs.push(argv[++i2]);
|
|
73590
|
+
} else if (looksLikeFlag && local?.content !== true) {
|
|
73591
|
+
unknownFlag = arg;
|
|
73592
|
+
} else if (!toolArgs) {
|
|
73593
|
+
toolArgs = arg;
|
|
73594
|
+
} else {
|
|
73595
|
+
restArgs.push(arg);
|
|
73596
|
+
}
|
|
73597
|
+
i2++;
|
|
73598
|
+
continue;
|
|
73599
|
+
}
|
|
74683
73600
|
switch (arg) {
|
|
74684
73601
|
case "--json":
|
|
74685
73602
|
flags.json = true;
|
|
@@ -74773,6 +73690,20 @@ function parseArgs(argv) {
|
|
|
74773
73690
|
case "--cleanup":
|
|
74774
73691
|
flags.cleanup = true;
|
|
74775
73692
|
break;
|
|
73693
|
+
case "--no-sample-data":
|
|
73694
|
+
flags.noSampleData = true;
|
|
73695
|
+
break;
|
|
73696
|
+
case "--adopt":
|
|
73697
|
+
flags.adopt = true;
|
|
73698
|
+
break;
|
|
73699
|
+
// Comma-separated AND repeatable, like `--tags` above: an agent scripting
|
|
73700
|
+
// this reaches for whichever form it knows, and both accumulate.
|
|
73701
|
+
case "--entity":
|
|
73702
|
+
flags.entity = [...flags.entity, ...splitList(argv[++i2])];
|
|
73703
|
+
break;
|
|
73704
|
+
case "--limit":
|
|
73705
|
+
flags.limit = argv[++i2];
|
|
73706
|
+
break;
|
|
74776
73707
|
case "--prune":
|
|
74777
73708
|
flags.prune = true;
|
|
74778
73709
|
break;
|
|
@@ -74816,6 +73747,207 @@ function parseArgs(argv) {
|
|
|
74816
73747
|
return { command, subcommand, toolArgs, restArgs, flags, unknownFlag };
|
|
74817
73748
|
}
|
|
74818
73749
|
|
|
73750
|
+
// src/starter_commands.ts
|
|
73751
|
+
import fs9 from "node:fs";
|
|
73752
|
+
import path11 from "node:path";
|
|
73753
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
73754
|
+
async function starterList(client) {
|
|
73755
|
+
const starters = await client.listStarters();
|
|
73756
|
+
if (starters.length === 0) {
|
|
73757
|
+
console.error(
|
|
73758
|
+
"No starters available to this organization.\n A starter is copyable when Lotics has reviewed it, or when your own organization published it."
|
|
73759
|
+
);
|
|
73760
|
+
return;
|
|
73761
|
+
}
|
|
73762
|
+
const width = Math.max(...starters.map((s) => s.id.length));
|
|
73763
|
+
console.error(`${starters.length} starter${starters.length === 1 ? "" : "s"}:
|
|
73764
|
+
`);
|
|
73765
|
+
for (const s of starters) {
|
|
73766
|
+
const tags = [
|
|
73767
|
+
s.is_official ? "official" : null,
|
|
73768
|
+
s.owned_by_caller === true ? "yours" : null
|
|
73769
|
+
].filter((t) => t !== null);
|
|
73770
|
+
console.log(
|
|
73771
|
+
` ${s.id.padEnd(width)} ${s.name}${tags.length > 0 ? ` [${tags.join(", ")}]` : ""}`
|
|
73772
|
+
);
|
|
73773
|
+
if (s.description) console.log(` ${" ".repeat(width)} ${s.description}`);
|
|
73774
|
+
}
|
|
73775
|
+
console.error(`
|
|
73776
|
+
lotics starter init <starter_id> Copy one into this workspace`);
|
|
73777
|
+
}
|
|
73778
|
+
async function starterShow(client, starter_id) {
|
|
73779
|
+
const starter = await client.getPackage(starter_id);
|
|
73780
|
+
console.log(`${starter.name} (${starter.id})`);
|
|
73781
|
+
if (starter.description) console.log(starter.description);
|
|
73782
|
+
console.log(
|
|
73783
|
+
`
|
|
73784
|
+
version ${starter.latest_version}
|
|
73785
|
+
trust ${starter.is_official ? "official \u2014 reviewed by Lotics" : starter.owned_by_caller === true ? "your organization's own" : "not copyable from this organization"}`
|
|
73786
|
+
);
|
|
73787
|
+
if (starter.retired_at !== null) {
|
|
73788
|
+
console.log(`retired ${starter.retired_at} \u2014 can no longer be copied`);
|
|
73789
|
+
}
|
|
73790
|
+
}
|
|
73791
|
+
function reportKnowledgeWarnings(warnings) {
|
|
73792
|
+
const missing = warnings.missing_expected_docs;
|
|
73793
|
+
if (missing.length === 0) return;
|
|
73794
|
+
console.error(
|
|
73795
|
+
`
|
|
73796
|
+
\u26A0 ${missing.length} knowledge doc(s) this starter's agents expect are missing here:
|
|
73797
|
+
` + missing.map((name2) => ` \u2022 ${name2}`).join("\n") + `
|
|
73798
|
+
An agent declaring one of these reads nothing from it \u2014 the run still completes,
|
|
73799
|
+
answering from nowhere. Create them with those names, or edit the agent.`
|
|
73800
|
+
);
|
|
73801
|
+
}
|
|
73802
|
+
async function starterInit(client, args) {
|
|
73803
|
+
const starter = await client.getPackage(args.starter_id);
|
|
73804
|
+
console.error(
|
|
73805
|
+
`Copying ${starter.name}${starter.is_official ? " (official)" : ""} into this workspace\u2026`
|
|
73806
|
+
);
|
|
73807
|
+
const result = await client.instantiateStarter(args.starter_id, {
|
|
73808
|
+
...args.noSampleData === true ? { no_sample_data: true } : {},
|
|
73809
|
+
...args.adopt === true ? { adopt: true } : {}
|
|
73810
|
+
});
|
|
73811
|
+
const entities = Object.keys(result.binding.entities ?? {}).length;
|
|
73812
|
+
const docs = Object.keys(result.binding.knowledge ?? {}).length;
|
|
73813
|
+
const templates = Object.keys(result.binding.templates ?? {}).length;
|
|
73814
|
+
const records = Object.values(result.sample_record_ids).reduce((n, ids) => n + ids.length, 0);
|
|
73815
|
+
console.error(
|
|
73816
|
+
` Created ${entities} table${entities === 1 ? "" : "s"}, ${templates} template${templates === 1 ? "" : "s"}, ${docs} knowledge doc${docs === 1 ? "" : "s"}, ${records} sample record${records === 1 ? "" : "s"}.`
|
|
73817
|
+
);
|
|
73818
|
+
reportKnowledgeWarnings(result.knowledge_warnings);
|
|
73819
|
+
if (result.app_id === null || result.bundle_url === null) {
|
|
73820
|
+
console.error(`
|
|
73821
|
+
Done. The documents and knowledge are yours to edit \u2014 nothing links back.`);
|
|
73822
|
+
return;
|
|
73823
|
+
}
|
|
73824
|
+
const targetPath = path11.resolve(args.targetPath ?? appDirName(starter.name));
|
|
73825
|
+
if (fs9.existsSync(targetPath) && fs9.readdirSync(targetPath).length > 0) {
|
|
73826
|
+
throw new Error(
|
|
73827
|
+
`Target directory ${targetPath} is not empty. The app (${result.app_id}) was created \u2014 pass an empty path and re-run, or finish it with "lotics app pull ${result.app_id}".`
|
|
73828
|
+
);
|
|
73829
|
+
}
|
|
73830
|
+
fs9.mkdirSync(targetPath, { recursive: true });
|
|
73831
|
+
console.error(`Downloading source\u2026`);
|
|
73832
|
+
const bundleFile = path11.join(tmpdir2(), `lotics-starter-${args.starter_id}-${process.pid}.tar.gz`);
|
|
73833
|
+
const wrapperDir = fs9.mkdtempSync(path11.join(tmpdir2(), `lotics-starter-`));
|
|
73834
|
+
try {
|
|
73835
|
+
await downloadToFile(result.bundle_url, bundleFile);
|
|
73836
|
+
await runTar(["-xzf", bundleFile, "-C", wrapperDir], wrapperDir);
|
|
73837
|
+
const sourceArchive = path11.join(wrapperDir, "source.tar.gz");
|
|
73838
|
+
if (!fs9.existsSync(sourceArchive)) {
|
|
73839
|
+
throw new Error(
|
|
73840
|
+
`Starter bundle carried no source.tar.gz \u2014 the app (${result.app_id}) exists but has no code. Report this to the starter's publisher.`
|
|
73841
|
+
);
|
|
73842
|
+
}
|
|
73843
|
+
await runTar(["-xzf", sourceArchive, "-C", targetPath], targetPath);
|
|
73844
|
+
} finally {
|
|
73845
|
+
if (fs9.existsSync(bundleFile)) fs9.unlinkSync(bundleFile);
|
|
73846
|
+
fs9.rmSync(wrapperDir, { recursive: true, force: true });
|
|
73847
|
+
}
|
|
73848
|
+
for (const dir of ["knowledge", "fixtures"]) {
|
|
73849
|
+
fs9.rmSync(path11.join(targetPath, dir), { recursive: true, force: true });
|
|
73850
|
+
}
|
|
73851
|
+
const app = await client.getApp(result.app_id);
|
|
73852
|
+
const kept = [];
|
|
73853
|
+
await hydrateAppProject(client, targetPath, app, {
|
|
73854
|
+
// Nothing is deployed yet; the build below is what mints v1.
|
|
73855
|
+
stamp: { id: null, number: null },
|
|
73856
|
+
kept
|
|
73857
|
+
});
|
|
73858
|
+
if (starter.owned_by_caller !== true) {
|
|
73859
|
+
console.error(
|
|
73860
|
+
`
|
|
73861
|
+
Building ${starter.name} \u2014 this runs its build on your machine (its package scripts
|
|
73862
|
+
and vite config are the publisher's code, executed as you).${starter.is_official ? " Lotics reviewed this starter." : ""}`
|
|
73863
|
+
);
|
|
73864
|
+
} else {
|
|
73865
|
+
console.error(`Building and deploying\u2026`);
|
|
73866
|
+
}
|
|
73867
|
+
await runNpm(["run", "build"], targetPath);
|
|
73868
|
+
await appDeploy(client, {
|
|
73869
|
+
projectDir: targetPath,
|
|
73870
|
+
message: `Copied from starter ${starter.name}`
|
|
73871
|
+
});
|
|
73872
|
+
let signInUrl = null;
|
|
73873
|
+
try {
|
|
73874
|
+
const link = await client.login({
|
|
73875
|
+
return_link: true,
|
|
73876
|
+
redirect_path: `/apps/${result.app_id}`
|
|
73877
|
+
});
|
|
73878
|
+
signInUrl = link.url ?? null;
|
|
73879
|
+
} catch (error52) {
|
|
73880
|
+
console.error(
|
|
73881
|
+
`
|
|
73882
|
+
(no sign-in link: ${error52 instanceof Error ? error52.message : String(error52)})
|
|
73883
|
+
The copy is complete either way \u2014 open it with "lotics auth web".`
|
|
73884
|
+
);
|
|
73885
|
+
signInUrl = null;
|
|
73886
|
+
}
|
|
73887
|
+
console.error(
|
|
73888
|
+
`
|
|
73889
|
+
Done \u2014 ${starter.name} is live and yours.
|
|
73890
|
+
App: ${result.app_id}
|
|
73891
|
+
Project: ${targetPath}
|
|
73892
|
+
|
|
73893
|
+
Edit anything: the tables, the app source, the templates, the docs. There is no
|
|
73894
|
+
link back to the starter and nothing to upgrade \u2014 this is your app now.
|
|
73895
|
+
Ship a change: cd ${path11.relative(process.cwd(), targetPath) || "."} && lotics app deploy -m "<what changed>"`
|
|
73896
|
+
);
|
|
73897
|
+
if (records > 0) {
|
|
73898
|
+
console.error(
|
|
73899
|
+
`
|
|
73900
|
+
${records} sample record${records === 1 ? "" : "s"} came with it. They are ordinary records \u2014
|
|
73901
|
+
delete them whenever you like, or re-run with --no-sample-data next time.`
|
|
73902
|
+
);
|
|
73903
|
+
}
|
|
73904
|
+
if (signInUrl !== null) {
|
|
73905
|
+
console.error(
|
|
73906
|
+
`
|
|
73907
|
+
Open it \u2014 one-time sign-in link, expires in 15 minutes:
|
|
73908
|
+
${signInUrl}`
|
|
73909
|
+
);
|
|
73910
|
+
}
|
|
73911
|
+
}
|
|
73912
|
+
async function starterFixturesCapture(client, args) {
|
|
73913
|
+
const projectDir = path11.resolve(args.projectDir ?? process.cwd());
|
|
73914
|
+
const meta3 = readAppMeta(projectDir);
|
|
73915
|
+
const result = await client.captureStarterFixtures(meta3.app_id, {
|
|
73916
|
+
entities: args.entities,
|
|
73917
|
+
...args.limit !== void 0 ? { limit: args.limit } : {}
|
|
73918
|
+
});
|
|
73919
|
+
const fixturesDir = path11.join(projectDir, "fixtures");
|
|
73920
|
+
fs9.mkdirSync(fixturesDir, { recursive: true });
|
|
73921
|
+
let totalRows = 0;
|
|
73922
|
+
for (const entry of result.captured) {
|
|
73923
|
+
const file2 = path11.join(projectDir, entry.content_ref);
|
|
73924
|
+
fs9.writeFileSync(file2, `${JSON.stringify(entry.file, null, 2)}
|
|
73925
|
+
`, "utf-8");
|
|
73926
|
+
totalRows += entry.file.rows.length;
|
|
73927
|
+
console.error(
|
|
73928
|
+
` ${entry.content_ref} \u2014 ${entry.file.rows.length} row${entry.file.rows.length === 1 ? "" : "s"}`
|
|
73929
|
+
);
|
|
73930
|
+
for (const note of entry.notes) console.error(` \u26A0 ${note}`);
|
|
73931
|
+
}
|
|
73932
|
+
if (result.captured.length === 0) {
|
|
73933
|
+
console.error(
|
|
73934
|
+
`This app declares no tables, so there is nothing to capture.
|
|
73935
|
+
Entities available: ${result.available_entity_aliases.join(", ") || "(none)"}`
|
|
73936
|
+
);
|
|
73937
|
+
return;
|
|
73938
|
+
}
|
|
73939
|
+
console.error(
|
|
73940
|
+
`
|
|
73941
|
+
Captured ${totalRows} row${totalRows === 1 ? "" : "s"} across ${result.captured.length} entit${result.captured.length === 1 ? "y" : "ies"}.
|
|
73942
|
+
|
|
73943
|
+
READ WHAT IT WROTE before committing. These rows ship inside the starter and are
|
|
73944
|
+
created in every workspace that copies it \u2014 a real customer name, a real price or a
|
|
73945
|
+
real address captured here is published.
|
|
73946
|
+
|
|
73947
|
+
Entities available: ${result.available_entity_aliases.join(", ")}`
|
|
73948
|
+
);
|
|
73949
|
+
}
|
|
73950
|
+
|
|
74819
73951
|
// src/inputs.ts
|
|
74820
73952
|
async function ingestJsonArgs(opts) {
|
|
74821
73953
|
let raw = opts.rawArg;
|
|
@@ -74875,11 +74007,11 @@ async function validateOrgWorkspacePin(client, orgId, profile) {
|
|
|
74875
74007
|
}
|
|
74876
74008
|
|
|
74877
74009
|
// src/xlsx.ts
|
|
74878
|
-
import
|
|
74010
|
+
import fs11 from "node:fs";
|
|
74879
74011
|
|
|
74880
74012
|
// src/file_command_io.ts
|
|
74881
|
-
import
|
|
74882
|
-
import
|
|
74013
|
+
import fs10 from "node:fs";
|
|
74014
|
+
import path12 from "node:path";
|
|
74883
74015
|
var CliError = class extends Error {
|
|
74884
74016
|
constructor(message2) {
|
|
74885
74017
|
super(message2);
|
|
@@ -74889,25 +74021,27 @@ var CliError = class extends Error {
|
|
|
74889
74021
|
function fail2(message2) {
|
|
74890
74022
|
throw new CliError(message2);
|
|
74891
74023
|
}
|
|
74892
|
-
function rejectUnknownFlags(rest2,
|
|
74893
|
-
const
|
|
74894
|
-
const unknown2 = rest2.filter((a) => a.startsWith("--") && !
|
|
74024
|
+
function rejectUnknownFlags(rest2, command, subcommand) {
|
|
74025
|
+
const known = knownSubcommandFlags(command, subcommand);
|
|
74026
|
+
const unknown2 = rest2.filter((a) => a.startsWith("--") && !matchesKnownFlag(known, a));
|
|
74895
74027
|
if (unknown2.length === 0) return;
|
|
74896
|
-
fail2(
|
|
74028
|
+
fail2(
|
|
74029
|
+
`Unknown ${unknown2.length > 1 ? "flags" : "flag"} for ${command} ${subcommand}: ${unknown2.join(", ")}. Supported: ${known.join(", ")}.`
|
|
74030
|
+
);
|
|
74897
74031
|
}
|
|
74898
74032
|
function rejectExtraArgs(rest2, arity, usage) {
|
|
74899
74033
|
if (rest2.length <= arity) return;
|
|
74900
74034
|
fail2(`${usage} takes ${arity} argument${arity === 1 ? "" : "s"} after <file>, got ${rest2.length}. Unused: ${rest2.slice(arity).join(" ")}`);
|
|
74901
74035
|
}
|
|
74902
74036
|
function writeFileAtomic(filePath, bytes) {
|
|
74903
|
-
const dir =
|
|
74904
|
-
const tmp =
|
|
74905
|
-
|
|
74037
|
+
const dir = path12.dirname(path12.resolve(filePath));
|
|
74038
|
+
const tmp = path12.join(dir, `.${path12.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
|
|
74039
|
+
fs10.writeFileSync(tmp, bytes);
|
|
74906
74040
|
try {
|
|
74907
|
-
|
|
74041
|
+
fs10.renameSync(tmp, filePath);
|
|
74908
74042
|
} catch (error52) {
|
|
74909
74043
|
try {
|
|
74910
|
-
|
|
74044
|
+
fs10.unlinkSync(tmp);
|
|
74911
74045
|
} catch {
|
|
74912
74046
|
}
|
|
74913
74047
|
throw error52;
|
|
@@ -77704,16 +76838,16 @@ var MatcherView = class {
|
|
|
77704
76838
|
* @returns {string|undefined}
|
|
77705
76839
|
*/
|
|
77706
76840
|
getCurrentTag() {
|
|
77707
|
-
const
|
|
77708
|
-
return
|
|
76841
|
+
const path14 = this._matcher.path;
|
|
76842
|
+
return path14.length > 0 ? path14[path14.length - 1].tag : void 0;
|
|
77709
76843
|
}
|
|
77710
76844
|
/**
|
|
77711
76845
|
* Get current namespace.
|
|
77712
76846
|
* @returns {string|undefined}
|
|
77713
76847
|
*/
|
|
77714
76848
|
getCurrentNamespace() {
|
|
77715
|
-
const
|
|
77716
|
-
return
|
|
76849
|
+
const path14 = this._matcher.path;
|
|
76850
|
+
return path14.length > 0 ? path14[path14.length - 1].namespace : void 0;
|
|
77717
76851
|
}
|
|
77718
76852
|
/**
|
|
77719
76853
|
* Get current node's attribute value.
|
|
@@ -77721,9 +76855,9 @@ var MatcherView = class {
|
|
|
77721
76855
|
* @returns {*}
|
|
77722
76856
|
*/
|
|
77723
76857
|
getAttrValue(attrName) {
|
|
77724
|
-
const
|
|
77725
|
-
if (
|
|
77726
|
-
return
|
|
76858
|
+
const path14 = this._matcher.path;
|
|
76859
|
+
if (path14.length === 0) return void 0;
|
|
76860
|
+
return path14[path14.length - 1].values?.[attrName];
|
|
77727
76861
|
}
|
|
77728
76862
|
/**
|
|
77729
76863
|
* Check if current node has an attribute.
|
|
@@ -77731,9 +76865,9 @@ var MatcherView = class {
|
|
|
77731
76865
|
* @returns {boolean}
|
|
77732
76866
|
*/
|
|
77733
76867
|
hasAttr(attrName) {
|
|
77734
|
-
const
|
|
77735
|
-
if (
|
|
77736
|
-
const current =
|
|
76868
|
+
const path14 = this._matcher.path;
|
|
76869
|
+
if (path14.length === 0) return false;
|
|
76870
|
+
const current = path14[path14.length - 1];
|
|
77737
76871
|
return current.values !== void 0 && attrName in current.values;
|
|
77738
76872
|
}
|
|
77739
76873
|
/**
|
|
@@ -77759,18 +76893,18 @@ var MatcherView = class {
|
|
|
77759
76893
|
* @returns {number}
|
|
77760
76894
|
*/
|
|
77761
76895
|
getPosition() {
|
|
77762
|
-
const
|
|
77763
|
-
if (
|
|
77764
|
-
return
|
|
76896
|
+
const path14 = this._matcher.path;
|
|
76897
|
+
if (path14.length === 0) return -1;
|
|
76898
|
+
return path14[path14.length - 1].position ?? 0;
|
|
77765
76899
|
}
|
|
77766
76900
|
/**
|
|
77767
76901
|
* Get current node's repeat counter (occurrence count of this tag name).
|
|
77768
76902
|
* @returns {number}
|
|
77769
76903
|
*/
|
|
77770
76904
|
getCounter() {
|
|
77771
|
-
const
|
|
77772
|
-
if (
|
|
77773
|
-
return
|
|
76905
|
+
const path14 = this._matcher.path;
|
|
76906
|
+
if (path14.length === 0) return -1;
|
|
76907
|
+
return path14[path14.length - 1].counter ?? 0;
|
|
77774
76908
|
}
|
|
77775
76909
|
/**
|
|
77776
76910
|
* Get current node's sibling index (alias for getPosition).
|
|
@@ -80651,14 +79785,14 @@ function isOle2(bytes) {
|
|
|
80651
79785
|
}
|
|
80652
79786
|
function readCfbStreams(bytes) {
|
|
80653
79787
|
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
80654
|
-
const
|
|
80655
|
-
const
|
|
80656
|
-
const sectorSize = 1 <<
|
|
80657
|
-
const miniSectorSize = 1 <<
|
|
80658
|
-
const firstDirSector =
|
|
80659
|
-
const miniCutoff =
|
|
80660
|
-
const firstMiniFatSector =
|
|
80661
|
-
const firstDifatSector =
|
|
79788
|
+
const u163 = (o) => dv.getUint16(o, true);
|
|
79789
|
+
const u322 = (o) => dv.getUint32(o, true);
|
|
79790
|
+
const sectorSize = 1 << u163(30);
|
|
79791
|
+
const miniSectorSize = 1 << u163(32);
|
|
79792
|
+
const firstDirSector = u322(48);
|
|
79793
|
+
const miniCutoff = u322(56);
|
|
79794
|
+
const firstMiniFatSector = u322(60);
|
|
79795
|
+
const firstDifatSector = u322(68);
|
|
80662
79796
|
if (sectorSize < 512 || sectorSize > 1 << 20) {
|
|
80663
79797
|
throw new Error("Unsupported OLE2 file: invalid sector size");
|
|
80664
79798
|
}
|
|
@@ -80666,7 +79800,7 @@ function readCfbStreams(bytes) {
|
|
|
80666
79800
|
const maxSectors = Math.ceil(bytes.length / sectorSize) + 1;
|
|
80667
79801
|
const difat = [];
|
|
80668
79802
|
for (let i2 = 0; i2 < 109; i2++) {
|
|
80669
|
-
const v =
|
|
79803
|
+
const v = u322(76 + i2 * 4);
|
|
80670
79804
|
if (v !== FREESECT) difat.push(v);
|
|
80671
79805
|
}
|
|
80672
79806
|
let ds = firstDifatSector;
|
|
@@ -80676,10 +79810,10 @@ function readCfbStreams(bytes) {
|
|
|
80676
79810
|
seenDifat.add(ds);
|
|
80677
79811
|
const base = sectorOffset(ds);
|
|
80678
79812
|
for (let i2 = 0; i2 < entriesPerSector - 1; i2++) {
|
|
80679
|
-
const v =
|
|
79813
|
+
const v = u322(base + i2 * 4);
|
|
80680
79814
|
if (v !== FREESECT) difat.push(v);
|
|
80681
79815
|
}
|
|
80682
|
-
ds =
|
|
79816
|
+
ds = u322(base + (entriesPerSector - 1) * 4);
|
|
80683
79817
|
}
|
|
80684
79818
|
const fat = [];
|
|
80685
79819
|
for (const fatSector of difat) {
|
|
@@ -80687,7 +79821,7 @@ function readCfbStreams(bytes) {
|
|
|
80687
79821
|
if (fatSector >= maxSectors) continue;
|
|
80688
79822
|
const base = sectorOffset(fatSector);
|
|
80689
79823
|
for (let i2 = 0; i2 < entriesPerSector && fat.length < maxSectors; i2++) {
|
|
80690
|
-
fat.push(
|
|
79824
|
+
fat.push(u322(base + i2 * 4));
|
|
80691
79825
|
}
|
|
80692
79826
|
}
|
|
80693
79827
|
const readChain = (src, start, size2, ss, offOf, chain2) => {
|
|
@@ -83428,10 +82562,10 @@ function resolveRelativePath(basePath, relativePath) {
|
|
|
83428
82562
|
}
|
|
83429
82563
|
return resolved.join("/");
|
|
83430
82564
|
}
|
|
83431
|
-
function findZipEntry(zipEntries,
|
|
83432
|
-
if (zipEntries[
|
|
83433
|
-
if (zipEntries[`xl/${
|
|
83434
|
-
const noSlash =
|
|
82565
|
+
function findZipEntry(zipEntries, path14) {
|
|
82566
|
+
if (zipEntries[path14]) return zipEntries[path14];
|
|
82567
|
+
if (zipEntries[`xl/${path14}`]) return zipEntries[`xl/${path14}`];
|
|
82568
|
+
const noSlash = path14.replace(/^\//, "");
|
|
83435
82569
|
if (zipEntries[noSlash]) return zipEntries[noSlash];
|
|
83436
82570
|
return void 0;
|
|
83437
82571
|
}
|
|
@@ -84547,6 +83681,221 @@ function ensureVmlArray(val) {
|
|
|
84547
83681
|
return Array.isArray(val) ? val : [val];
|
|
84548
83682
|
}
|
|
84549
83683
|
|
|
83684
|
+
// ../xlsx/src/biff8_styles.ts
|
|
83685
|
+
var DEFAULT_PALETTE = [
|
|
83686
|
+
"#000000",
|
|
83687
|
+
"#FFFFFF",
|
|
83688
|
+
"#FF0000",
|
|
83689
|
+
"#00FF00",
|
|
83690
|
+
"#0000FF",
|
|
83691
|
+
"#FFFF00",
|
|
83692
|
+
"#FF00FF",
|
|
83693
|
+
"#00FFFF",
|
|
83694
|
+
"#000000",
|
|
83695
|
+
"#FFFFFF",
|
|
83696
|
+
"#FF0000",
|
|
83697
|
+
"#00FF00",
|
|
83698
|
+
"#0000FF",
|
|
83699
|
+
"#FFFF00",
|
|
83700
|
+
"#FF00FF",
|
|
83701
|
+
"#00FFFF",
|
|
83702
|
+
"#800000",
|
|
83703
|
+
"#008000",
|
|
83704
|
+
"#000080",
|
|
83705
|
+
"#808000",
|
|
83706
|
+
"#800080",
|
|
83707
|
+
"#008080",
|
|
83708
|
+
"#C0C0C0",
|
|
83709
|
+
"#808080",
|
|
83710
|
+
"#9999FF",
|
|
83711
|
+
"#993366",
|
|
83712
|
+
"#FFFFCC",
|
|
83713
|
+
"#CCFFFF",
|
|
83714
|
+
"#660066",
|
|
83715
|
+
"#FF8080",
|
|
83716
|
+
"#0066CC",
|
|
83717
|
+
"#CCCCFF",
|
|
83718
|
+
"#000080",
|
|
83719
|
+
"#FF00FF",
|
|
83720
|
+
"#FFFF00",
|
|
83721
|
+
"#00FFFF",
|
|
83722
|
+
"#800080",
|
|
83723
|
+
"#800000",
|
|
83724
|
+
"#008080",
|
|
83725
|
+
"#0000FF",
|
|
83726
|
+
"#00CCFF",
|
|
83727
|
+
"#CCFFFF",
|
|
83728
|
+
"#CCFFCC",
|
|
83729
|
+
"#FFFF99",
|
|
83730
|
+
"#99CCFF",
|
|
83731
|
+
"#FF99CC",
|
|
83732
|
+
"#CC99FF",
|
|
83733
|
+
"#FFCC99",
|
|
83734
|
+
"#3366FF",
|
|
83735
|
+
"#33CCCC",
|
|
83736
|
+
"#99CC00",
|
|
83737
|
+
"#FFCC00",
|
|
83738
|
+
"#FF9900",
|
|
83739
|
+
"#FF6600",
|
|
83740
|
+
"#666699",
|
|
83741
|
+
"#969696",
|
|
83742
|
+
"#003366",
|
|
83743
|
+
"#339966",
|
|
83744
|
+
"#003300",
|
|
83745
|
+
"#333300",
|
|
83746
|
+
"#993300",
|
|
83747
|
+
"#993366",
|
|
83748
|
+
"#333399",
|
|
83749
|
+
"#333333"
|
|
83750
|
+
];
|
|
83751
|
+
var AUTOMATIC = /* @__PURE__ */ new Set([64, 65, 32767]);
|
|
83752
|
+
var u162 = (b, o) => b[o] | b[o + 1] << 8;
|
|
83753
|
+
var u32 = (b, o) => (u162(b, o) | u162(b, o + 2) << 16) >>> 0;
|
|
83754
|
+
function parsePalette(body) {
|
|
83755
|
+
const palette = [...DEFAULT_PALETTE];
|
|
83756
|
+
const count = u162(body, 0);
|
|
83757
|
+
for (let i2 = 0; i2 < count && 2 + i2 * 4 + 3 < body.length; i2++) {
|
|
83758
|
+
const o = 2 + i2 * 4;
|
|
83759
|
+
const hex3 = (n) => n.toString(16).padStart(2, "0").toUpperCase();
|
|
83760
|
+
palette[8 + i2] = `#${hex3(body[o])}${hex3(body[o + 1])}${hex3(body[o + 2])}`;
|
|
83761
|
+
}
|
|
83762
|
+
return palette;
|
|
83763
|
+
}
|
|
83764
|
+
function defaultPalette() {
|
|
83765
|
+
return [...DEFAULT_PALETTE];
|
|
83766
|
+
}
|
|
83767
|
+
function parseFont2(body) {
|
|
83768
|
+
const grbit = u162(body, 2);
|
|
83769
|
+
const uls = body[10];
|
|
83770
|
+
const sss = u162(body, 8);
|
|
83771
|
+
let name2 = "";
|
|
83772
|
+
if (body.length > 15) {
|
|
83773
|
+
const cch = body[14];
|
|
83774
|
+
const high = (body[15] & 1) !== 0;
|
|
83775
|
+
for (let i2 = 0; i2 < cch; i2++) {
|
|
83776
|
+
const o = 16 + (high ? i2 * 2 : i2);
|
|
83777
|
+
if (o >= body.length) break;
|
|
83778
|
+
name2 += String.fromCharCode(high ? body[o] | body[o + 1] << 8 : body[o]);
|
|
83779
|
+
}
|
|
83780
|
+
}
|
|
83781
|
+
return {
|
|
83782
|
+
size: u162(body, 0) / 20,
|
|
83783
|
+
bold: u162(body, 6) >= 600,
|
|
83784
|
+
italic: (grbit & 2) !== 0,
|
|
83785
|
+
strike: (grbit & 8) !== 0,
|
|
83786
|
+
underline: uls === 1 || uls === 33 ? "single" : uls === 2 || uls === 34 ? "double" : void 0,
|
|
83787
|
+
vertAlign: sss === 1 ? "superscript" : sss === 2 ? "subscript" : void 0,
|
|
83788
|
+
colorIndex: u162(body, 4),
|
|
83789
|
+
name: name2
|
|
83790
|
+
};
|
|
83791
|
+
}
|
|
83792
|
+
function parseXf2(body) {
|
|
83793
|
+
const alignByte = body[6] ?? 0;
|
|
83794
|
+
const indentByte = body[8] ?? 0;
|
|
83795
|
+
const b1 = u32(body, 10);
|
|
83796
|
+
const b22 = u32(body, 14);
|
|
83797
|
+
const fill = u162(body, 18);
|
|
83798
|
+
const HORIZ = [
|
|
83799
|
+
void 0,
|
|
83800
|
+
"left",
|
|
83801
|
+
"center",
|
|
83802
|
+
"right",
|
|
83803
|
+
void 0,
|
|
83804
|
+
void 0,
|
|
83805
|
+
"center"
|
|
83806
|
+
];
|
|
83807
|
+
const VERT = ["top", "middle", "bottom", "middle", "middle"];
|
|
83808
|
+
const rot = body[7] ?? 0;
|
|
83809
|
+
return {
|
|
83810
|
+
fontIndex: u162(body, 0),
|
|
83811
|
+
horizontal: HORIZ[alignByte & 7],
|
|
83812
|
+
vertical: VERT[alignByte >> 4 & 7],
|
|
83813
|
+
wrap: (alignByte & 8) !== 0,
|
|
83814
|
+
shrink: (indentByte & 16) !== 0,
|
|
83815
|
+
indent: indentByte & 15,
|
|
83816
|
+
// 0–90 means degrees; 91–180 means −1…−90; 255 is stacked/vertical text.
|
|
83817
|
+
rotation: rot === 255 ? 255 : rot <= 90 ? rot : -(rot - 90),
|
|
83818
|
+
borders: {
|
|
83819
|
+
left: b1 & 15,
|
|
83820
|
+
right: b1 >> 4 & 15,
|
|
83821
|
+
top: b1 >> 8 & 15,
|
|
83822
|
+
bottom: b1 >> 12 & 15,
|
|
83823
|
+
leftColor: b1 >> 16 & 127,
|
|
83824
|
+
rightColor: b1 >> 23 & 127,
|
|
83825
|
+
topColor: b22 & 127,
|
|
83826
|
+
bottomColor: b22 >> 7 & 127
|
|
83827
|
+
},
|
|
83828
|
+
fillPattern: b22 >>> 26 & 63,
|
|
83829
|
+
fillFore: fill & 127,
|
|
83830
|
+
fillBack: fill >> 7 & 127
|
|
83831
|
+
};
|
|
83832
|
+
}
|
|
83833
|
+
var BORDER_STYLES = [
|
|
83834
|
+
"none",
|
|
83835
|
+
"thin",
|
|
83836
|
+
"medium",
|
|
83837
|
+
"dashed",
|
|
83838
|
+
"dotted",
|
|
83839
|
+
"thick",
|
|
83840
|
+
"double",
|
|
83841
|
+
"hair",
|
|
83842
|
+
"mediumDashed",
|
|
83843
|
+
"dashDot",
|
|
83844
|
+
"mediumDashDot",
|
|
83845
|
+
"dashDotDot",
|
|
83846
|
+
"mediumDashDotDot",
|
|
83847
|
+
"slantDashDot"
|
|
83848
|
+
];
|
|
83849
|
+
var BORDER_WIDTH = { thick: 3, medium: 2, mediumDashed: 2, mediumDashDot: 2, mediumDashDotDot: 2, double: 3, hair: 1 };
|
|
83850
|
+
function colorOf(index, palette) {
|
|
83851
|
+
if (AUTOMATIC.has(index)) return void 0;
|
|
83852
|
+
return palette[index];
|
|
83853
|
+
}
|
|
83854
|
+
function borderOf(style, colorIndex, palette) {
|
|
83855
|
+
if (style === 0) return void 0;
|
|
83856
|
+
const name2 = BORDER_STYLES[style] ?? "thin";
|
|
83857
|
+
return { width: BORDER_WIDTH[name2] ?? 1, style: name2, color: colorOf(colorIndex, palette) ?? "#000000" };
|
|
83858
|
+
}
|
|
83859
|
+
function toCellStyle(xf, fonts, palette) {
|
|
83860
|
+
const style = {};
|
|
83861
|
+
const font = fonts[xf.fontIndex];
|
|
83862
|
+
if (font) {
|
|
83863
|
+
if (font.bold) style.fontBold = true;
|
|
83864
|
+
if (font.italic) style.fontItalic = true;
|
|
83865
|
+
if (font.strike) style.fontStrike = true;
|
|
83866
|
+
if (font.underline) style.fontUnderline = font.underline;
|
|
83867
|
+
if (font.vertAlign) style.fontVertAlign = font.vertAlign;
|
|
83868
|
+
if (font.size > 0) style.fontSize = font.size;
|
|
83869
|
+
if (font.name) style.fontName = font.name;
|
|
83870
|
+
const color = colorOf(font.colorIndex, palette);
|
|
83871
|
+
if (color) style.fontColor = color;
|
|
83872
|
+
}
|
|
83873
|
+
if (xf.horizontal) style.horizontalAlign = xf.horizontal;
|
|
83874
|
+
if (xf.vertical) style.verticalAlign = xf.vertical;
|
|
83875
|
+
if (xf.wrap) style.wrapText = true;
|
|
83876
|
+
if (xf.shrink) style.shrinkToFit = true;
|
|
83877
|
+
if (xf.indent > 0) style.indent = xf.indent;
|
|
83878
|
+
if (xf.rotation === 255) style.textRotation = "vertical";
|
|
83879
|
+
else if (xf.rotation !== 0) style.textRotation = xf.rotation;
|
|
83880
|
+
const left = borderOf(xf.borders.left, xf.borders.leftColor, palette);
|
|
83881
|
+
const right = borderOf(xf.borders.right, xf.borders.rightColor, palette);
|
|
83882
|
+
const top = borderOf(xf.borders.top, xf.borders.topColor, palette);
|
|
83883
|
+
const bottom = borderOf(xf.borders.bottom, xf.borders.bottomColor, palette);
|
|
83884
|
+
if (left) style.borderLeft = left;
|
|
83885
|
+
if (right) style.borderRight = right;
|
|
83886
|
+
if (top) style.borderTop = top;
|
|
83887
|
+
if (bottom) style.borderBottom = bottom;
|
|
83888
|
+
if (xf.fillPattern === 1) {
|
|
83889
|
+
const bg = colorOf(xf.fillFore, palette);
|
|
83890
|
+
if (bg) style.backgroundColor = bg;
|
|
83891
|
+
} else if (xf.fillPattern > 1) {
|
|
83892
|
+
const bg = colorOf(xf.fillBack, palette);
|
|
83893
|
+
if (bg) style.backgroundColor = bg;
|
|
83894
|
+
style.patternType = "gray125";
|
|
83895
|
+
}
|
|
83896
|
+
return style;
|
|
83897
|
+
}
|
|
83898
|
+
|
|
84550
83899
|
// ../xlsx/src/biff8_reader.ts
|
|
84551
83900
|
var DEFAULT_MAX_ROWS = 1e4;
|
|
84552
83901
|
var REC = {
|
|
@@ -84568,7 +83917,12 @@ var REC = {
|
|
|
84568
83917
|
MULBLANK: 190,
|
|
84569
83918
|
LABELSST: 253,
|
|
84570
83919
|
SST: 252,
|
|
84571
|
-
BOF: 2057
|
|
83920
|
+
BOF: 2057,
|
|
83921
|
+
DEFCOLWIDTH: 85,
|
|
83922
|
+
COLINFO: 125,
|
|
83923
|
+
FONT: 49,
|
|
83924
|
+
PALETTE: 146,
|
|
83925
|
+
ROW: 520
|
|
84572
83926
|
};
|
|
84573
83927
|
function* iterRecords(stream, from, to) {
|
|
84574
83928
|
const dv = new DataView(stream.buffer, stream.byteOffset, stream.byteLength);
|
|
@@ -84586,6 +83940,9 @@ function parseGlobals(stream) {
|
|
|
84586
83940
|
const sstChunks = [];
|
|
84587
83941
|
const formats = /* @__PURE__ */ new Map();
|
|
84588
83942
|
const xfFormatIds = [];
|
|
83943
|
+
const xfRecords = [];
|
|
83944
|
+
const fonts = [];
|
|
83945
|
+
let palette = null;
|
|
84589
83946
|
const boundsheets = [];
|
|
84590
83947
|
let date1904 = false;
|
|
84591
83948
|
let sawSst = false;
|
|
@@ -84629,8 +83986,17 @@ function parseGlobals(stream) {
|
|
|
84629
83986
|
}
|
|
84630
83987
|
case REC.XF: {
|
|
84631
83988
|
xfFormatIds.push(readU16(r.body, 2));
|
|
83989
|
+
xfRecords.push(r.body.slice());
|
|
83990
|
+
break;
|
|
83991
|
+
}
|
|
83992
|
+
case REC.FONT: {
|
|
83993
|
+
fonts.push(parseFont2(r.body));
|
|
83994
|
+
if (fonts.length === 4) fonts.push(fonts[3]);
|
|
84632
83995
|
break;
|
|
84633
83996
|
}
|
|
83997
|
+
case REC.PALETTE:
|
|
83998
|
+
palette = parsePalette(r.body);
|
|
83999
|
+
break;
|
|
84634
84000
|
case REC.BOUNDSHEET: {
|
|
84635
84001
|
const pos = dv.getUint32(r.offset + 4, true);
|
|
84636
84002
|
boundsheets.push({ name: readUnicodeShort(r.body, 6, 1), pos });
|
|
@@ -84642,7 +84008,9 @@ function parseGlobals(stream) {
|
|
|
84642
84008
|
}
|
|
84643
84009
|
const sst = parseSst(sstChunks, sstUnique);
|
|
84644
84010
|
const xfFormats = xfFormatIds.map((id) => formats.get(id) ?? builtinFormat(id));
|
|
84645
|
-
|
|
84011
|
+
const pal = palette ?? defaultPalette();
|
|
84012
|
+
const xfStyles = xfRecords.map((body) => toCellStyle(parseXf2(body), fonts, pal));
|
|
84013
|
+
return { sst, date1904, xfFormats, xfStyles, boundsheets };
|
|
84646
84014
|
}
|
|
84647
84015
|
function parseSst(chunks, count) {
|
|
84648
84016
|
const out = [];
|
|
@@ -84727,26 +84095,55 @@ function parseSheet2(stream, start, name2, g, maxRows) {
|
|
|
84727
84095
|
break;
|
|
84728
84096
|
}
|
|
84729
84097
|
}
|
|
84098
|
+
const colDefs = /* @__PURE__ */ new Map();
|
|
84099
|
+
const rowHeights = /* @__PURE__ */ new Map();
|
|
84100
|
+
const hiddenRows = /* @__PURE__ */ new Set();
|
|
84730
84101
|
for (const r of iterRecords(stream, start, end)) {
|
|
84731
84102
|
switch (r.type) {
|
|
84103
|
+
case REC.DEFCOLWIDTH: {
|
|
84104
|
+
sheet.defaultColWidth = readU16(r.body, 0);
|
|
84105
|
+
break;
|
|
84106
|
+
}
|
|
84107
|
+
case REC.COLINFO: {
|
|
84108
|
+
const first3 = readU16(r.body, 0), last3 = readU16(r.body, 2);
|
|
84109
|
+
const width = readU16(r.body, 4) / 256;
|
|
84110
|
+
const grbit = readU16(r.body, 8);
|
|
84111
|
+
const hidden = (grbit & 1) !== 0;
|
|
84112
|
+
const outline = grbit >> 8 & 7;
|
|
84113
|
+
for (let c = first3; c <= last3 && c <= 255; c++) {
|
|
84114
|
+
colDefs.set(c, { index: c + 1, width, hidden, customWidth: true });
|
|
84115
|
+
if (outline > 0) sheet.colOutlineLevels.set(c + 1, outline);
|
|
84116
|
+
}
|
|
84117
|
+
break;
|
|
84118
|
+
}
|
|
84119
|
+
case REC.ROW: {
|
|
84120
|
+
const row = readU16(r.body, 0);
|
|
84121
|
+
const grbit = readU16(r.body, 12);
|
|
84122
|
+
const height = (readU16(r.body, 6) & 32767) / 20;
|
|
84123
|
+
if (height > 0) rowHeights.set(row, height);
|
|
84124
|
+
if ((grbit & 32) !== 0) hiddenRows.add(row);
|
|
84125
|
+
const outline = grbit & 7;
|
|
84126
|
+
if (outline > 0) sheet.rowOutlineLevels.set(row + 1, outline);
|
|
84127
|
+
break;
|
|
84128
|
+
}
|
|
84732
84129
|
case REC.LABELSST: {
|
|
84733
|
-
const row = readU16(r.body, 0), col = readU16(r.body, 2), isst = readU32(r.body, 6);
|
|
84734
|
-
put(row, col, textCell(col, g.sst[isst] ?? ""));
|
|
84130
|
+
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4), isst = readU32(r.body, 6);
|
|
84131
|
+
put(row, col, textCell(col, g.sst[isst] ?? "", g.xfStyles[xf]));
|
|
84735
84132
|
break;
|
|
84736
84133
|
}
|
|
84737
84134
|
case REC.LABEL: {
|
|
84738
|
-
const row = readU16(r.body, 0), col = readU16(r.body, 2);
|
|
84739
|
-
put(row, col, textCell(col, readUnicodeShort(r.body, 6, 2)));
|
|
84135
|
+
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4);
|
|
84136
|
+
put(row, col, textCell(col, readUnicodeShort(r.body, 6, 2), g.xfStyles[xf]));
|
|
84740
84137
|
break;
|
|
84741
84138
|
}
|
|
84742
84139
|
case REC.NUMBER: {
|
|
84743
84140
|
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4);
|
|
84744
|
-
put(row, col, numberCell(col, readF64(r.body, 6), g.xfFormats[xf]));
|
|
84141
|
+
put(row, col, numberCell(col, readF64(r.body, 6), g.xfFormats[xf], g.xfStyles[xf]));
|
|
84745
84142
|
break;
|
|
84746
84143
|
}
|
|
84747
84144
|
case REC.RK: {
|
|
84748
84145
|
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4);
|
|
84749
|
-
put(row, col, numberCell(col, decodeRk(readU32(r.body, 6)), g.xfFormats[xf]));
|
|
84146
|
+
put(row, col, numberCell(col, decodeRk(readU32(r.body, 6)), g.xfFormats[xf], g.xfStyles[xf]));
|
|
84750
84147
|
break;
|
|
84751
84148
|
}
|
|
84752
84149
|
case REC.MULRK: {
|
|
@@ -84755,13 +84152,13 @@ function parseSheet2(stream, start, name2, g, maxRows) {
|
|
|
84755
84152
|
for (let i2 = 0; i2 < n; i2++) {
|
|
84756
84153
|
const xf = readU16(r.body, 4 + i2 * 6);
|
|
84757
84154
|
const rk = readU32(r.body, 6 + i2 * 6);
|
|
84758
|
-
put(row, first3 + i2, numberCell(first3 + i2, decodeRk(rk), g.xfFormats[xf]));
|
|
84155
|
+
put(row, first3 + i2, numberCell(first3 + i2, decodeRk(rk), g.xfFormats[xf], g.xfStyles[xf]));
|
|
84759
84156
|
}
|
|
84760
84157
|
break;
|
|
84761
84158
|
}
|
|
84762
84159
|
case REC.FORMULA: {
|
|
84763
84160
|
const row = readU16(r.body, 0), col = readU16(r.body, 2), xf = readU16(r.body, 4);
|
|
84764
|
-
const cell = formulaCell(col, r.body, g.xfFormats[xf]);
|
|
84161
|
+
const cell = formulaCell(col, r.body, g.xfFormats[xf], g.xfStyles[xf]);
|
|
84765
84162
|
if (cell) put(row, col, cell);
|
|
84766
84163
|
break;
|
|
84767
84164
|
}
|
|
@@ -84775,17 +84172,23 @@ function parseSheet2(stream, start, name2, g, maxRows) {
|
|
|
84775
84172
|
const r = grid.get(ri);
|
|
84776
84173
|
if (!r) continue;
|
|
84777
84174
|
const cells = [...r.values()].sort((a, b) => a.column - b.column);
|
|
84778
|
-
rows.push({
|
|
84175
|
+
rows.push({
|
|
84176
|
+
index: ri + 1,
|
|
84177
|
+
height: rowHeights.get(ri) ?? sheet.defaultRowHeight,
|
|
84178
|
+
cells,
|
|
84179
|
+
hidden: hiddenRows.has(ri)
|
|
84180
|
+
});
|
|
84779
84181
|
}
|
|
84780
84182
|
sheet.rows = rows;
|
|
84183
|
+
sheet.columns = [...colDefs.values()].sort((a, b) => a.index - b.index);
|
|
84781
84184
|
sheet.totalRowCount = maxRow + 1;
|
|
84782
84185
|
sheet.truncated = truncated;
|
|
84783
84186
|
return sheet;
|
|
84784
84187
|
}
|
|
84785
|
-
function textCell(column, text) {
|
|
84786
|
-
return { column: column + 1, value: text, typedValue: text, content: { type: "plain", text }, style
|
|
84188
|
+
function textCell(column, text, style = {}) {
|
|
84189
|
+
return { column: column + 1, value: text, typedValue: text, content: { type: "plain", text }, style };
|
|
84787
84190
|
}
|
|
84788
|
-
function numberCell(column, num3, numFmt) {
|
|
84191
|
+
function numberCell(column, num3, numFmt, style = {}) {
|
|
84789
84192
|
const value2 = Number.isFinite(num3) ? String(num3) : "";
|
|
84790
84193
|
return {
|
|
84791
84194
|
column: column + 1,
|
|
@@ -84794,19 +84197,19 @@ function numberCell(column, num3, numFmt) {
|
|
|
84794
84197
|
typedValue: num3,
|
|
84795
84198
|
numFmtCode: numFmt && numFmt !== "General" ? numFmt : void 0,
|
|
84796
84199
|
content: { type: "plain", text: value2 },
|
|
84797
|
-
style
|
|
84200
|
+
style
|
|
84798
84201
|
};
|
|
84799
84202
|
}
|
|
84800
|
-
function formulaCell(column, body, numFmt) {
|
|
84203
|
+
function formulaCell(column, body, numFmt, style = {}) {
|
|
84801
84204
|
if (readU16(body, 12) === 65535) {
|
|
84802
84205
|
const kind = body[6];
|
|
84803
84206
|
if (kind === 1) {
|
|
84804
84207
|
const b = body[8] !== 0;
|
|
84805
|
-
return { column: column + 1, value: b ? "TRUE" : "FALSE", typedValue: b, content: { type: "plain", text: b ? "TRUE" : "FALSE" }, style
|
|
84208
|
+
return { column: column + 1, value: b ? "TRUE" : "FALSE", typedValue: b, content: { type: "plain", text: b ? "TRUE" : "FALSE" }, style };
|
|
84806
84209
|
}
|
|
84807
84210
|
return null;
|
|
84808
84211
|
}
|
|
84809
|
-
return numberCell(column, readF64(body, 6), numFmt);
|
|
84212
|
+
return numberCell(column, readF64(body, 6), numFmt, style);
|
|
84810
84213
|
}
|
|
84811
84214
|
function decodeRk(rk) {
|
|
84812
84215
|
const div100 = (rk & 1) !== 0;
|
|
@@ -85063,9 +84466,9 @@ function parseExcelFromZip(zip, options) {
|
|
|
85063
84466
|
}
|
|
85064
84467
|
return result;
|
|
85065
84468
|
}
|
|
85066
|
-
function findEntry(zip,
|
|
85067
|
-
if (zip[
|
|
85068
|
-
const lower2 =
|
|
84469
|
+
function findEntry(zip, path14) {
|
|
84470
|
+
if (zip[path14]) return zip[path14];
|
|
84471
|
+
const lower2 = path14.toLowerCase();
|
|
85069
84472
|
for (const key of Object.keys(zip)) {
|
|
85070
84473
|
if (key.toLowerCase() === lower2) return zip[key];
|
|
85071
84474
|
}
|
|
@@ -85702,12 +85105,12 @@ function extractPivotRoundTripInfo(originalZip) {
|
|
|
85702
85105
|
if (paths.length > 0) pivotTablesBySheetIndex.set(i2, paths);
|
|
85703
85106
|
}
|
|
85704
85107
|
const pivotXmlPaths = [];
|
|
85705
|
-
for (const
|
|
85706
|
-
if (
|
|
85707
|
-
pivotXmlPaths.push(
|
|
85108
|
+
for (const path14 of Object.keys(originalZip)) {
|
|
85109
|
+
if (path14.startsWith("xl/pivotTables/") && path14.endsWith(".xml")) {
|
|
85110
|
+
pivotXmlPaths.push(path14);
|
|
85708
85111
|
}
|
|
85709
|
-
if (
|
|
85710
|
-
pivotXmlPaths.push(
|
|
85112
|
+
if (path14.startsWith("xl/pivotCache/") && path14.endsWith(".xml")) {
|
|
85113
|
+
pivotXmlPaths.push(path14);
|
|
85711
85114
|
}
|
|
85712
85115
|
}
|
|
85713
85116
|
return { cachesByWorkbook, pivotTablesBySheetIndex, pivotXmlPaths };
|
|
@@ -85715,15 +85118,15 @@ function extractPivotRoundTripInfo(originalZip) {
|
|
|
85715
85118
|
function decode3(bytes) {
|
|
85716
85119
|
return new TextDecoder().decode(bytes);
|
|
85717
85120
|
}
|
|
85718
|
-
function pivotContentTypeFor(
|
|
85719
|
-
if (
|
|
85720
|
-
return `<Override PartName="/${
|
|
85121
|
+
function pivotContentTypeFor(path14) {
|
|
85122
|
+
if (path14.startsWith("xl/pivotTables/") && path14.endsWith(".xml")) {
|
|
85123
|
+
return `<Override PartName="/${path14}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>`;
|
|
85721
85124
|
}
|
|
85722
|
-
if (
|
|
85723
|
-
return `<Override PartName="/${
|
|
85125
|
+
if (path14.includes("/pivotCacheDefinition") && path14.endsWith(".xml")) {
|
|
85126
|
+
return `<Override PartName="/${path14}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>`;
|
|
85724
85127
|
}
|
|
85725
|
-
if (
|
|
85726
|
-
return `<Override PartName="/${
|
|
85128
|
+
if (path14.includes("/pivotCacheRecords") && path14.endsWith(".xml")) {
|
|
85129
|
+
return `<Override PartName="/${path14}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>`;
|
|
85727
85130
|
}
|
|
85728
85131
|
return void 0;
|
|
85729
85132
|
}
|
|
@@ -85796,16 +85199,16 @@ function exportWorkbook(workbook, originalZip) {
|
|
|
85796
85199
|
regeneratedPaths.add(`xl/worksheets/sheet${i2 + 1}.xml`);
|
|
85797
85200
|
regeneratedPaths.add(`xl/worksheets/_rels/sheet${i2 + 1}.xml.rels`);
|
|
85798
85201
|
}
|
|
85799
|
-
for (const
|
|
85800
|
-
if (
|
|
85801
|
-
regeneratedPaths.add(
|
|
85202
|
+
for (const path14 of Object.keys(originalZip)) {
|
|
85203
|
+
if (path14.startsWith("xl/drawings/") || path14.startsWith("xl/charts/") || path14.startsWith("xl/tables/") || path14.startsWith("xl/media/")) {
|
|
85204
|
+
regeneratedPaths.add(path14);
|
|
85802
85205
|
}
|
|
85803
85206
|
}
|
|
85804
|
-
for (const [
|
|
85805
|
-
if (regeneratedPaths.has(
|
|
85806
|
-
const ext =
|
|
85207
|
+
for (const [path14, data2] of Object.entries(originalZip)) {
|
|
85208
|
+
if (regeneratedPaths.has(path14)) continue;
|
|
85209
|
+
const ext = path14.slice(path14.lastIndexOf(".") + 1).toLowerCase();
|
|
85807
85210
|
if (!DECLARED_EXTENSIONS.includes(ext)) continue;
|
|
85808
|
-
entries2[
|
|
85211
|
+
entries2[path14] = data2;
|
|
85809
85212
|
}
|
|
85810
85213
|
}
|
|
85811
85214
|
const sharedStrings = buildSharedStrings(workbook);
|
|
@@ -85821,8 +85224,8 @@ function exportWorkbook(workbook, originalZip) {
|
|
|
85821
85224
|
buildWorkbookRels(workbook, pivotInfo)
|
|
85822
85225
|
);
|
|
85823
85226
|
const extraContentTypes = [];
|
|
85824
|
-
for (const
|
|
85825
|
-
const ct = pivotContentTypeFor(
|
|
85227
|
+
for (const path14 of pivotInfo.pivotXmlPaths) {
|
|
85228
|
+
const ct = pivotContentTypeFor(path14);
|
|
85826
85229
|
if (ct) extraContentTypes.push(ct);
|
|
85827
85230
|
}
|
|
85828
85231
|
let globalChartIndex = 1;
|
|
@@ -95008,14 +94411,14 @@ var DependencyGraph = class {
|
|
|
95008
94411
|
stack.push({ cell: p, path: [cell, p] });
|
|
95009
94412
|
}
|
|
95010
94413
|
while (stack.length > 0) {
|
|
95011
|
-
const { cell: current, path:
|
|
95012
|
-
if (current === cell || originCoarse.has(current)) return
|
|
94414
|
+
const { cell: current, path: path14 } = stack.pop();
|
|
94415
|
+
if (current === cell || originCoarse.has(current)) return path14;
|
|
95013
94416
|
if (visited.has(current)) continue;
|
|
95014
94417
|
visited.add(current);
|
|
95015
94418
|
const nextPrec = this.precedents.get(current);
|
|
95016
94419
|
if (!nextPrec) continue;
|
|
95017
94420
|
for (const p of nextPrec) {
|
|
95018
|
-
stack.push({ cell: p, path: [...
|
|
94421
|
+
stack.push({ cell: p, path: [...path14, p] });
|
|
95019
94422
|
}
|
|
95020
94423
|
}
|
|
95021
94424
|
return null;
|
|
@@ -95713,6 +95116,37 @@ function collectRecomputeReport(workbook, unreadable) {
|
|
|
95713
95116
|
return { total, unevaluated };
|
|
95714
95117
|
}
|
|
95715
95118
|
|
|
95119
|
+
// ../xlsx/src/numfmt_type.ts
|
|
95120
|
+
function classifyNumFmt(code) {
|
|
95121
|
+
if (!code || code === "General") return "general";
|
|
95122
|
+
const first3 = code.split(";")[0] ?? code;
|
|
95123
|
+
const currency = hasCurrencyTokens(first3);
|
|
95124
|
+
const stripped = stripQuotedLiterals(first3);
|
|
95125
|
+
if (stripped.trim() === "@") return "text";
|
|
95126
|
+
if (hasDateTokens(stripped)) return "date";
|
|
95127
|
+
if (stripped.includes("%")) return "percent";
|
|
95128
|
+
if (currency) return "currency";
|
|
95129
|
+
if (/[#0?]/.test(stripped)) return "numeric";
|
|
95130
|
+
return "general";
|
|
95131
|
+
}
|
|
95132
|
+
function stripQuotedLiterals(code) {
|
|
95133
|
+
return code.replace(/"[^"]*"/g, "").replace(/\\./g, " ");
|
|
95134
|
+
}
|
|
95135
|
+
function hasDateTokens(code) {
|
|
95136
|
+
if (/\b(y{1,4}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/p)\b/i.test(code)) return true;
|
|
95137
|
+
if (/[ymdhs]\s*[-\/.:\s]\s*m/i.test(code)) return true;
|
|
95138
|
+
if (/m\s*[-\/.:\s]\s*[ymdhs]/i.test(code)) return true;
|
|
95139
|
+
return false;
|
|
95140
|
+
}
|
|
95141
|
+
function hasCurrencyTokens(code) {
|
|
95142
|
+
if (/[$¥€£₫¢]/.test(code)) return true;
|
|
95143
|
+
if (/\[\$/.test(code)) return true;
|
|
95144
|
+
return false;
|
|
95145
|
+
}
|
|
95146
|
+
function isPaddedIdentifier(input) {
|
|
95147
|
+
return /^[+-]?0\d/.test(input);
|
|
95148
|
+
}
|
|
95149
|
+
|
|
95716
95150
|
// ../xlsx/src/clipboard.ts
|
|
95717
95151
|
function adjustFormulaRefsForRowShift(formula, atRow, delta) {
|
|
95718
95152
|
return formula.replace(
|
|
@@ -95740,17 +95174,18 @@ function adjustFormulaRefsForColShift(formula, atCol, delta) {
|
|
|
95740
95174
|
}
|
|
95741
95175
|
|
|
95742
95176
|
// ../xlsx/src/spreadsheet_commands.ts
|
|
95743
|
-
function setCellValueCommand(workbook, engine, sheetIndex, row, col, newValue) {
|
|
95177
|
+
function setCellValueCommand(workbook, engine, sheetIndex, row, col, newValue, options) {
|
|
95744
95178
|
const sheet = workbook.sheets[sheetIndex];
|
|
95745
95179
|
const ref2 = rowColToRef(row, col);
|
|
95746
95180
|
const oldCell = sheet.getCell(ref2);
|
|
95747
95181
|
const oldValue = oldCell?.value ?? null;
|
|
95748
95182
|
const oldFormula = oldCell?.formula;
|
|
95749
|
-
const isFormula = newValue.startsWith("=");
|
|
95750
|
-
const formula = isFormula ? newValue.slice(1) : void 0;
|
|
95751
|
-
const value2 = isFormula ? null : parseInputValue(newValue);
|
|
95752
95183
|
const styleIndex = oldCell?.styleIndex ?? 0;
|
|
95753
95184
|
const numFmtCode = oldCell?.numFmtCode ?? "General";
|
|
95185
|
+
const isText = typeof newValue === "string" && options?.typed !== true;
|
|
95186
|
+
const isFormula = isText && newValue.startsWith("=");
|
|
95187
|
+
const formula = isFormula ? newValue.slice(1) : void 0;
|
|
95188
|
+
const value2 = isFormula ? null : isText ? parseInputValue(newValue, numFmtCode) : newValue;
|
|
95754
95189
|
return {
|
|
95755
95190
|
description: `Set ${ref2} = ${newValue}`,
|
|
95756
95191
|
execute() {
|
|
@@ -96289,6 +95724,43 @@ function deleteColsCommand(workbook, sheetIndex, at2, count) {
|
|
|
96289
95724
|
}
|
|
96290
95725
|
};
|
|
96291
95726
|
}
|
|
95727
|
+
function setRangeNumFmtCommand(workbook, sheetIndex, startRow, startCol, endRow, endCol, numFmtCode) {
|
|
95728
|
+
const sheet = workbook.sheets[sheetIndex];
|
|
95729
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
95730
|
+
for (let r = startRow; r <= endRow; r++) {
|
|
95731
|
+
for (let c = startCol; c <= endCol; c++) {
|
|
95732
|
+
const ref2 = rowColToRef(r, c);
|
|
95733
|
+
const cell = sheet.getCell(ref2);
|
|
95734
|
+
snapshot.set(ref2, cell ? { value: cell.value, styleIndex: cell.styleIndex, numFmtCode: cell.numFmtCode, formula: cell.formula } : null);
|
|
95735
|
+
}
|
|
95736
|
+
}
|
|
95737
|
+
const rangeRef = `${rowColToRef(startRow, startCol)}:${rowColToRef(endRow, endCol)}`;
|
|
95738
|
+
return {
|
|
95739
|
+
description: `Format ${rangeRef} as ${numFmtCode}`,
|
|
95740
|
+
execute() {
|
|
95741
|
+
for (let r = startRow; r <= endRow; r++) {
|
|
95742
|
+
for (let c = startCol; c <= endCol; c++) {
|
|
95743
|
+
const ref2 = rowColToRef(r, c);
|
|
95744
|
+
const cell = sheet.getCell(ref2);
|
|
95745
|
+
if (cell) {
|
|
95746
|
+
sheet.set(ref2, cell.value, sheet.styles?.get(cell.styleIndex), numFmtCode, cell.formula);
|
|
95747
|
+
} else {
|
|
95748
|
+
sheet.set(ref2, null, void 0, numFmtCode);
|
|
95749
|
+
}
|
|
95750
|
+
}
|
|
95751
|
+
}
|
|
95752
|
+
},
|
|
95753
|
+
undo() {
|
|
95754
|
+
for (const [ref2, snap] of snapshot) {
|
|
95755
|
+
if (snap) {
|
|
95756
|
+
sheet.set(ref2, snap.value, sheet.styles?.get(snap.styleIndex), snap.numFmtCode, snap.formula);
|
|
95757
|
+
} else {
|
|
95758
|
+
sheet.deleteCell(ref2);
|
|
95759
|
+
}
|
|
95760
|
+
}
|
|
95761
|
+
}
|
|
95762
|
+
};
|
|
95763
|
+
}
|
|
96292
95764
|
function addSheetCommand(workbook, name2) {
|
|
96293
95765
|
return {
|
|
96294
95766
|
description: `Add sheet ${name2}`,
|
|
@@ -96331,10 +95803,23 @@ function renameSheetCommand(workbook, index, newName) {
|
|
|
96331
95803
|
}
|
|
96332
95804
|
};
|
|
96333
95805
|
}
|
|
96334
|
-
function
|
|
95806
|
+
function batchCommand(description, commands) {
|
|
95807
|
+
return {
|
|
95808
|
+
description,
|
|
95809
|
+
execute() {
|
|
95810
|
+
for (const cmd of commands) cmd.execute();
|
|
95811
|
+
},
|
|
95812
|
+
undo() {
|
|
95813
|
+
for (let i2 = commands.length - 1; i2 >= 0; i2--) commands[i2].undo();
|
|
95814
|
+
}
|
|
95815
|
+
};
|
|
95816
|
+
}
|
|
95817
|
+
function parseInputValue(input, numFmtCode) {
|
|
96335
95818
|
if (input === "") return null;
|
|
95819
|
+
if (classifyNumFmt(numFmtCode) === "text") return input;
|
|
96336
95820
|
if (input.toUpperCase() === "TRUE") return true;
|
|
96337
95821
|
if (input.toUpperCase() === "FALSE") return false;
|
|
95822
|
+
if (isPaddedIdentifier(input.trim())) return input;
|
|
96338
95823
|
const num3 = Number(input);
|
|
96339
95824
|
if (!isNaN(num3) && input.trim() !== "") return num3;
|
|
96340
95825
|
return input;
|
|
@@ -96461,8 +95946,8 @@ var SIMPLE_SHEET_KEYS = /* @__PURE__ */ new Set(["name", "cells", "merges", "fre
|
|
|
96461
95946
|
var MAX_COLUMN = 16384;
|
|
96462
95947
|
var MAX_ROW = 1048576;
|
|
96463
95948
|
function loadFile(filePath) {
|
|
96464
|
-
if (!
|
|
96465
|
-
const buffer =
|
|
95949
|
+
if (!fs11.existsSync(filePath)) fail2(`File not found: ${filePath}`);
|
|
95950
|
+
const buffer = fs11.readFileSync(filePath);
|
|
96466
95951
|
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
96467
95952
|
const originalZip = unzipXlsx(arrayBuffer);
|
|
96468
95953
|
const parsed = parseExcelBuffer(arrayBuffer);
|
|
@@ -96512,7 +95997,7 @@ function lazyEngine(workbook) {
|
|
|
96512
95997
|
};
|
|
96513
95998
|
}
|
|
96514
95999
|
function readToJson(filePath, filter3, opts) {
|
|
96515
|
-
const buffer =
|
|
96000
|
+
const buffer = fs11.readFileSync(filePath);
|
|
96516
96001
|
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
96517
96002
|
const parsed = parseExcelBuffer(arrayBuffer);
|
|
96518
96003
|
let sheets = parsed.sheets;
|
|
@@ -96607,21 +96092,20 @@ function applySheetCells(workbook, sheetIndex, def) {
|
|
|
96607
96092
|
const sheet = workbook.sheets[sheetIndex];
|
|
96608
96093
|
if (def.cells) {
|
|
96609
96094
|
for (const [ref2, raw] of Object.entries(def.cells)) {
|
|
96610
|
-
const cell = normalizeSimpleCell(raw, def.name
|
|
96611
|
-
const
|
|
96095
|
+
const cell = normalizeSimpleCell(raw, `sheet "${def.name}" cell ${ref2}`);
|
|
96096
|
+
const upper2 = ref2.toUpperCase();
|
|
96097
|
+
const coord = refToRowCol(upper2);
|
|
96612
96098
|
if (!coord) fail2(`Invalid cell ref in sheet "${def.name}": ${ref2}`);
|
|
96613
|
-
|
|
96614
|
-
|
|
96615
|
-
|
|
96099
|
+
sheet.set(
|
|
96100
|
+
upper2,
|
|
96101
|
+
cell.formula ? null : cell.value ?? null,
|
|
96102
|
+
void 0,
|
|
96103
|
+
cell.numFmt,
|
|
96104
|
+
cell.formula ?? void 0
|
|
96105
|
+
);
|
|
96616
96106
|
if (cell.style) {
|
|
96617
96107
|
setRangeStyleCommand(workbook, sheetIndex, coord.row, coord.col, coord.row, coord.col, cell.style).execute();
|
|
96618
96108
|
}
|
|
96619
|
-
if (cell.numFmt !== void 0) {
|
|
96620
|
-
const upper2 = ref2.toUpperCase();
|
|
96621
|
-
const target = sheet.getCell(upper2);
|
|
96622
|
-
if (target) target.numFmtCode = cell.numFmt;
|
|
96623
|
-
else sheet.set(upper2, null, cell.style, cell.numFmt);
|
|
96624
|
-
}
|
|
96625
96109
|
}
|
|
96626
96110
|
}
|
|
96627
96111
|
if (def.merges) {
|
|
@@ -96649,22 +96133,33 @@ function applySheetCells(workbook, sheetIndex, def) {
|
|
|
96649
96133
|
}
|
|
96650
96134
|
}
|
|
96651
96135
|
}
|
|
96652
|
-
function normalizeSimpleCell(raw,
|
|
96136
|
+
function normalizeSimpleCell(raw, label) {
|
|
96653
96137
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
96654
96138
|
const unknown2 = Object.keys(raw).filter((k) => !SIMPLE_CELL_KEYS.has(k));
|
|
96655
96139
|
if (unknown2.length > 0) {
|
|
96656
96140
|
fail2(
|
|
96657
|
-
`Unknown propert${unknown2.length > 1 ? "ies" : "y"} on
|
|
96141
|
+
`Unknown propert${unknown2.length > 1 ? "ies" : "y"} on ${label}: ${unknown2.join(", ")}. Supported: ${[...SIMPLE_CELL_KEYS].join(", ")}.`
|
|
96658
96142
|
);
|
|
96659
96143
|
}
|
|
96144
|
+
if (raw.formula === void 0 || raw.formula === null) {
|
|
96145
|
+
if (typeof raw.value === "string" && raw.value.startsWith("=")) {
|
|
96146
|
+
console.error(
|
|
96147
|
+
`Warning: ${label} was written as the text ${JSON.stringify(raw.value)}. An object cell's "value" is a literal; write {"formula": ${JSON.stringify(raw.value.slice(1))}} or the bare string ${JSON.stringify(raw.value)} for a formula.`
|
|
96148
|
+
);
|
|
96149
|
+
}
|
|
96150
|
+
}
|
|
96660
96151
|
return raw;
|
|
96661
96152
|
}
|
|
96153
|
+
if (raw !== null && !["string", "number", "boolean"].includes(typeof raw)) {
|
|
96154
|
+
fail2(
|
|
96155
|
+
`Value of ${label} must be a string, number, boolean, null, or a { ${[...SIMPLE_CELL_KEYS].join(", ")} } object, got ${JSON.stringify(raw) ?? typeof raw}.`
|
|
96156
|
+
);
|
|
96157
|
+
}
|
|
96158
|
+
if (typeof raw === "string" && raw.startsWith("=")) {
|
|
96159
|
+
return { formula: raw.slice(1) };
|
|
96160
|
+
}
|
|
96662
96161
|
return { value: raw };
|
|
96663
96162
|
}
|
|
96664
|
-
function valueToInput(value2) {
|
|
96665
|
-
if (value2 === null || value2 === void 0) return "";
|
|
96666
|
-
return String(value2);
|
|
96667
|
-
}
|
|
96668
96163
|
function readOptionFlag(rest2, name2) {
|
|
96669
96164
|
const i2 = rest2.indexOf(name2);
|
|
96670
96165
|
if (i2 < 0) return void 0;
|
|
@@ -96679,7 +96174,6 @@ function splitOptionalSheetRef(spec) {
|
|
|
96679
96174
|
}
|
|
96680
96175
|
function xlsxRead(filePath, rest2) {
|
|
96681
96176
|
if (!filePath) fail2("Usage: lotics xlsx read <file> [--sheet <name>] [--range <sheet>!<A1:G60>] [--with-format]");
|
|
96682
|
-
rejectUnknownFlags(rest2, ["--sheet", "--range", "--with-format"], "xlsx read");
|
|
96683
96177
|
const rangeArg = readOptionFlag(rest2, "--range");
|
|
96684
96178
|
const sheetArg = readOptionFlag(rest2, "--sheet");
|
|
96685
96179
|
const withFormat = rest2.includes("--with-format");
|
|
@@ -96889,7 +96383,29 @@ function buildBatchCommand(workbook, engine, op, index) {
|
|
|
96889
96383
|
const sheetIndex = resolveSheetIndex(workbook, op.sheet);
|
|
96890
96384
|
const coord = refToRowCol(op.ref.toUpperCase());
|
|
96891
96385
|
if (!coord) fail2(`[op ${index}] Invalid cell ref: ${op.ref}`);
|
|
96892
|
-
|
|
96386
|
+
const cell = normalizeSimpleCell(op.value, `[op ${index}] set-cell ${op.sheet}!${op.ref}`);
|
|
96387
|
+
const commands = [
|
|
96388
|
+
cell.formula ? (
|
|
96389
|
+
// The entry path is the only one that writes a formula, and it takes
|
|
96390
|
+
// it spelled the way a person types it. Re-adding the `=` this
|
|
96391
|
+
// surface's reader just stripped is lossless and keeps the formula
|
|
96392
|
+
// write in one place.
|
|
96393
|
+
setCellValueCommand(workbook, engine.get(), sheetIndex, coord.row, coord.col, `=${cell.formula}`)
|
|
96394
|
+
) : setCellValueCommand(workbook, engine.get(), sheetIndex, coord.row, coord.col, cell.value ?? null, {
|
|
96395
|
+
typed: true
|
|
96396
|
+
})
|
|
96397
|
+
];
|
|
96398
|
+
if (cell.numFmt !== void 0) {
|
|
96399
|
+
commands.push(
|
|
96400
|
+
setRangeNumFmtCommand(workbook, sheetIndex, coord.row, coord.col, coord.row, coord.col, cell.numFmt)
|
|
96401
|
+
);
|
|
96402
|
+
}
|
|
96403
|
+
if (cell.style) {
|
|
96404
|
+
commands.push(
|
|
96405
|
+
setRangeStyleCommand(workbook, sheetIndex, coord.row, coord.col, coord.row, coord.col, cell.style)
|
|
96406
|
+
);
|
|
96407
|
+
}
|
|
96408
|
+
return commands.length === 1 ? commands[0] : batchCommand(`Set ${op.sheet}!${op.ref}`, commands);
|
|
96893
96409
|
}
|
|
96894
96410
|
case "clear-range": {
|
|
96895
96411
|
const sheetIndex = resolveSheetIndex(workbook, op.sheet);
|
|
@@ -96946,6 +96462,8 @@ Uses Lotics' own xlsx engine; round-trips faithfully with the Lotics editor and
|
|
|
96946
96462
|
lotics xlsx write <file> '<json>' Create .xlsx from {"sheets":[{"name","cells":{"A1":...}}]}
|
|
96947
96463
|
A cell is a bare value, or {value|formula, numFmt, style}:
|
|
96948
96464
|
{"A1":{"value":1234,"numFmt":"#,##0 \\"\u20AB\\"","style":{"fontBold":true}}}
|
|
96465
|
+
A bare "=A1+B1" is a formula; an object's "value" is
|
|
96466
|
+
always a literal, so use {"formula":"A1+B1"} there.
|
|
96949
96467
|
A sheet also takes merges, freeze, colWidths ({"A":34}),
|
|
96950
96468
|
rowHeights ({"1":44}). Unknown properties are rejected.
|
|
96951
96469
|
lotics xlsx set-cell <file> <sheet>!<ref> '<v>' Set cell value (prefix '=' for formula)
|
|
@@ -97025,7 +96543,7 @@ async function runXlsxCommand(subcommand, toolArgs, restArgs) {
|
|
|
97025
96543
|
}
|
|
97026
96544
|
|
|
97027
96545
|
// src/docx.ts
|
|
97028
|
-
import
|
|
96546
|
+
import fs12 from "node:fs";
|
|
97029
96547
|
|
|
97030
96548
|
// ../ooxml/src/doc/errors.ts
|
|
97031
96549
|
var DocParseError = class extends Error {
|
|
@@ -101854,8 +101372,8 @@ async function docModelToDocx(model) {
|
|
|
101854
101372
|
// ../ooxml/src/opc.ts
|
|
101855
101373
|
var import_jszip = __toESM(require_lib4(), 1);
|
|
101856
101374
|
function dropFolderEntries(zip) {
|
|
101857
|
-
for (const [
|
|
101858
|
-
if (entry.dir) delete zip.files[
|
|
101375
|
+
for (const [path14, entry] of Object.entries(zip.files)) {
|
|
101376
|
+
if (entry.dir) delete zip.files[path14];
|
|
101859
101377
|
}
|
|
101860
101378
|
}
|
|
101861
101379
|
|
|
@@ -102110,11 +101628,11 @@ async function parseDocx(buffer) {
|
|
|
102110
101628
|
const zip = await import_jszip3.default.loadAsync(buffer);
|
|
102111
101629
|
const parts = /* @__PURE__ */ new Map();
|
|
102112
101630
|
const filePromises = [];
|
|
102113
|
-
zip.forEach((
|
|
101631
|
+
zip.forEach((path14, file2) => {
|
|
102114
101632
|
if (file2.dir) return;
|
|
102115
101633
|
filePromises.push(
|
|
102116
101634
|
file2.async("uint8array").then((bytes) => {
|
|
102117
|
-
parts.set(
|
|
101635
|
+
parts.set(path14, bytes);
|
|
102118
101636
|
})
|
|
102119
101637
|
);
|
|
102120
101638
|
});
|
|
@@ -102346,9 +101864,9 @@ var DEFAULT_PARTS = [
|
|
|
102346
101864
|
["word/theme/theme1.xml", () => encoder.encode(THEME_XML)]
|
|
102347
101865
|
];
|
|
102348
101866
|
function fillDefaultParts(parts) {
|
|
102349
|
-
for (const [
|
|
102350
|
-
if (!parts.has(
|
|
102351
|
-
parts.set(
|
|
101867
|
+
for (const [path14, makeBytes] of DEFAULT_PARTS) {
|
|
101868
|
+
if (!parts.has(path14)) {
|
|
101869
|
+
parts.set(path14, makeBytes());
|
|
102352
101870
|
}
|
|
102353
101871
|
}
|
|
102354
101872
|
return parts;
|
|
@@ -102358,9 +101876,9 @@ function fillDefaultParts(parts) {
|
|
|
102358
101876
|
async function serializeDocx(doc) {
|
|
102359
101877
|
const zip = new import_jszip4.default();
|
|
102360
101878
|
const parts = fillDefaultParts(new Map(doc.parts));
|
|
102361
|
-
for (const [
|
|
102362
|
-
if (
|
|
102363
|
-
zip.file(
|
|
101879
|
+
for (const [path14, bytes] of parts) {
|
|
101880
|
+
if (path14 === "word/document.xml") continue;
|
|
101881
|
+
zip.file(path14, bytes);
|
|
102364
101882
|
}
|
|
102365
101883
|
const documentXml = serializeDocumentXml(doc);
|
|
102366
101884
|
zip.file("word/document.xml", documentXml);
|
|
@@ -102447,8 +101965,8 @@ var DEFAULT_DOC_ATTRS = {
|
|
|
102447
101965
|
"@_xmlns:w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
102448
101966
|
};
|
|
102449
101967
|
async function loadFile2(filePath) {
|
|
102450
|
-
if (!
|
|
102451
|
-
const bytes =
|
|
101968
|
+
if (!fs12.existsSync(filePath)) fail2(`File not found: ${filePath}`);
|
|
101969
|
+
const bytes = fs12.readFileSync(filePath);
|
|
102452
101970
|
if (isLegacyDoc(bytes)) {
|
|
102453
101971
|
const upgraded = await saveDocxToBuffer(await loadDocxFromBuffer(bytes));
|
|
102454
101972
|
return parseDocx(new Uint8Array(upgraded));
|
|
@@ -102560,7 +102078,6 @@ function buildDoc(input) {
|
|
|
102560
102078
|
}
|
|
102561
102079
|
async function docxRead(filePath, rest2) {
|
|
102562
102080
|
if (!filePath) fail2("Usage: lotics docx read <file> [--include-opaque]");
|
|
102563
|
-
rejectUnknownFlags(rest2, ["--include-opaque"], "docx read");
|
|
102564
102081
|
const includeOpaque = rest2.includes("--include-opaque");
|
|
102565
102082
|
const doc = await loadFile2(filePath);
|
|
102566
102083
|
console.log(JSON.stringify(readToJson2(doc, includeOpaque), null, 2));
|
|
@@ -102595,7 +102112,7 @@ function firstPositional(rest2) {
|
|
|
102595
102112
|
return rest2.find((a) => !a.startsWith("--"));
|
|
102596
102113
|
}
|
|
102597
102114
|
async function docxAppendParagraph(filePath, rest2) {
|
|
102598
|
-
rejectUnknownFlags(rest2,
|
|
102115
|
+
rejectUnknownFlags(rest2, "docx", "append-paragraph");
|
|
102599
102116
|
const text = firstPositional(rest2);
|
|
102600
102117
|
if (!filePath || text === void 0) fail2("Usage: lotics docx append-paragraph <file> '<text>' [--style=NAME]");
|
|
102601
102118
|
const style = getStyleFlag(rest2);
|
|
@@ -102605,7 +102122,7 @@ async function docxAppendParagraph(filePath, rest2) {
|
|
|
102605
102122
|
await writeDoc(filePath, replaceChildren(doc, newChildren));
|
|
102606
102123
|
}
|
|
102607
102124
|
async function docxInsertParagraph(filePath, rest2) {
|
|
102608
|
-
rejectUnknownFlags(rest2,
|
|
102125
|
+
rejectUnknownFlags(rest2, "docx", "insert-paragraph");
|
|
102609
102126
|
const text = firstPositional(rest2);
|
|
102610
102127
|
const at2 = getAtFlag(rest2);
|
|
102611
102128
|
if (!filePath || text === void 0 || at2 === void 0) {
|
|
@@ -102622,7 +102139,6 @@ async function docxInsertParagraph(filePath, rest2) {
|
|
|
102622
102139
|
await writeDoc(filePath, replaceChildren(doc, newChildren));
|
|
102623
102140
|
}
|
|
102624
102141
|
async function docxDeleteBlock(filePath, rest2) {
|
|
102625
|
-
rejectUnknownFlags(rest2, ["--at="], "docx delete-block");
|
|
102626
102142
|
const at2 = getAtFlag(rest2);
|
|
102627
102143
|
if (!filePath || at2 === void 0) fail2("Usage: lotics docx delete-block <file> --at=<index>");
|
|
102628
102144
|
const doc = await loadFile2(filePath);
|
|
@@ -102933,7 +102449,7 @@ async function runDocxCommand(subcommand, toolArgs, restArgs) {
|
|
|
102933
102449
|
}
|
|
102934
102450
|
|
|
102935
102451
|
// src/knowledge.ts
|
|
102936
|
-
import
|
|
102452
|
+
import fs13 from "node:fs";
|
|
102937
102453
|
|
|
102938
102454
|
// ../shared/src/knowledge_tags.ts
|
|
102939
102455
|
function isHiddenDoc(doc) {
|
|
@@ -102942,8 +102458,8 @@ function isHiddenDoc(doc) {
|
|
|
102942
102458
|
|
|
102943
102459
|
// src/knowledge.ts
|
|
102944
102460
|
function readBodyFile(filePath) {
|
|
102945
|
-
if (!
|
|
102946
|
-
return
|
|
102461
|
+
if (!fs13.existsSync(filePath)) fail2(`File not found: ${filePath}`);
|
|
102462
|
+
return fs13.readFileSync(filePath, "utf-8");
|
|
102947
102463
|
}
|
|
102948
102464
|
function resolveBody(flags, required2) {
|
|
102949
102465
|
if (flags.from !== void 0 && flags.content !== void 0) {
|
|
@@ -103152,7 +102668,7 @@ async function runKnowledgeCommand(client, subcommand, toolArgs, flags, restArgs
|
|
|
103152
102668
|
import { spawn as spawn3 } from "node:child_process";
|
|
103153
102669
|
import { createServer } from "node:http";
|
|
103154
102670
|
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdtempSync, rmSync, readdirSync } from "node:fs";
|
|
103155
|
-
import { tmpdir as
|
|
102671
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
103156
102672
|
import { join as join2, dirname, resolve, extname, basename } from "node:path";
|
|
103157
102673
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
103158
102674
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
@@ -103251,7 +102767,7 @@ async function runPreviewCommand(filePath, flags) {
|
|
|
103251
102767
|
});
|
|
103252
102768
|
await new Promise((r) => server.listen(0, "127.0.0.1", () => r()));
|
|
103253
102769
|
const httpPort = server.address().port;
|
|
103254
|
-
const udd = mkdtempSync(join2(
|
|
102770
|
+
const udd = mkdtempSync(join2(tmpdir3(), "lotics-render-"));
|
|
103255
102771
|
const child = spawn3(chrome, [
|
|
103256
102772
|
"--headless=new",
|
|
103257
102773
|
"--disable-gpu",
|
|
@@ -103491,8 +103007,8 @@ function prompt(question) {
|
|
|
103491
103007
|
});
|
|
103492
103008
|
});
|
|
103493
103009
|
}
|
|
103494
|
-
async function publicPost(
|
|
103495
|
-
const response = await fetch(`${API_BASE_URL}${
|
|
103010
|
+
async function publicPost(path14, body) {
|
|
103011
|
+
const response = await fetch(`${API_BASE_URL}${path14}`, {
|
|
103496
103012
|
method: "POST",
|
|
103497
103013
|
headers: { "Content-Type": "application/json" },
|
|
103498
103014
|
body: JSON.stringify(body)
|
|
@@ -103660,13 +103176,13 @@ async function resolveWorkspace(client, ctx) {
|
|
|
103660
103176
|
function resolveUploadPaths(rawPaths) {
|
|
103661
103177
|
const result = [];
|
|
103662
103178
|
for (const p of rawPaths) {
|
|
103663
|
-
const resolved =
|
|
103664
|
-
const stat =
|
|
103179
|
+
const resolved = path13.resolve(p);
|
|
103180
|
+
const stat = fs14.statSync(resolved);
|
|
103665
103181
|
if (stat.isDirectory()) {
|
|
103666
|
-
const entries2 =
|
|
103182
|
+
const entries2 = fs14.readdirSync(resolved, { withFileTypes: true });
|
|
103667
103183
|
for (const entry of entries2) {
|
|
103668
103184
|
if (entry.isFile()) {
|
|
103669
|
-
result.push(
|
|
103185
|
+
result.push(path13.join(resolved, entry.name));
|
|
103670
103186
|
}
|
|
103671
103187
|
}
|
|
103672
103188
|
} else {
|
|
@@ -103715,23 +103231,69 @@ async function main() {
|
|
|
103715
103231
|
console.log(VERSION);
|
|
103716
103232
|
return;
|
|
103717
103233
|
}
|
|
103718
|
-
if (command === "
|
|
103719
|
-
if (
|
|
103720
|
-
|
|
103721
|
-
|
|
103722
|
-
|
|
103234
|
+
if (command === "starter") {
|
|
103235
|
+
if (subcommand === "list") {
|
|
103236
|
+
const { client: client2, ctx: ctx2 } = requireClient(flags);
|
|
103237
|
+
await resolveWorkspace(client2, ctx2);
|
|
103238
|
+
await starterList(client2);
|
|
103239
|
+
return;
|
|
103723
103240
|
}
|
|
103724
|
-
|
|
103725
|
-
|
|
103726
|
-
|
|
103727
|
-
|
|
103728
|
-
|
|
103729
|
-
|
|
103730
|
-
|
|
103731
|
-
|
|
103732
|
-
|
|
103733
|
-
|
|
103734
|
-
|
|
103241
|
+
if (subcommand === "show") {
|
|
103242
|
+
if (!toolArgs) {
|
|
103243
|
+
console.error("Usage: lotics starter show <starter_id>");
|
|
103244
|
+
process.exit(1);
|
|
103245
|
+
}
|
|
103246
|
+
const { client: client2, ctx: ctx2 } = requireClient(flags);
|
|
103247
|
+
await resolveWorkspace(client2, ctx2);
|
|
103248
|
+
await starterShow(client2, toolArgs);
|
|
103249
|
+
return;
|
|
103250
|
+
}
|
|
103251
|
+
if (subcommand === "init") {
|
|
103252
|
+
if (!toolArgs) {
|
|
103253
|
+
console.error("Usage: lotics starter init <starter_id> [path] [--no-sample-data] [--adopt]");
|
|
103254
|
+
console.error(" Copies a starter into this workspace: schema, templates, knowledge");
|
|
103255
|
+
console.error(" docs, sample records and an editable app project. Builds and deploys");
|
|
103256
|
+
console.error(" locally, so it needs node and a few minutes.");
|
|
103257
|
+
process.exit(1);
|
|
103258
|
+
}
|
|
103259
|
+
const { client: client2, ctx: ctx2 } = requireClient(flags);
|
|
103260
|
+
await resolveWorkspace(client2, ctx2);
|
|
103261
|
+
await starterInit(client2, {
|
|
103262
|
+
starter_id: toolArgs,
|
|
103263
|
+
...restArgs[0] !== void 0 ? { targetPath: restArgs[0] } : {},
|
|
103264
|
+
...flags.noSampleData === true ? { noSampleData: true } : {},
|
|
103265
|
+
...flags.adopt === true ? { adopt: true } : {}
|
|
103266
|
+
});
|
|
103267
|
+
return;
|
|
103268
|
+
}
|
|
103269
|
+
if (subcommand === "fixtures") {
|
|
103270
|
+
if (toolArgs !== "capture") {
|
|
103271
|
+
console.error("Usage: lotics starter fixtures capture [--entity <alias> ...] [--limit <n>]");
|
|
103272
|
+
console.error(" Writes fixtures/<entity>.json into this app project from live records.");
|
|
103273
|
+
console.error(" Repeat --entity to capture a linked set in one call: a link only");
|
|
103274
|
+
console.error(" resolves within ONE capture, so separate calls lose the edge.");
|
|
103275
|
+
process.exit(1);
|
|
103276
|
+
}
|
|
103277
|
+
let limit;
|
|
103278
|
+
if (flags.limit !== void 0) {
|
|
103279
|
+
limit = Number(flags.limit);
|
|
103280
|
+
if (!Number.isInteger(limit) || limit < 1) {
|
|
103281
|
+
console.error(`Invalid --limit "${flags.limit}" \u2014 expected a positive integer.`);
|
|
103282
|
+
process.exit(1);
|
|
103283
|
+
}
|
|
103284
|
+
}
|
|
103285
|
+
const { client: client2, ctx: ctx2 } = requireClient(flags);
|
|
103286
|
+
await resolveWorkspace(client2, ctx2);
|
|
103287
|
+
await starterFixturesCapture(client2, {
|
|
103288
|
+
entities: flags.entity,
|
|
103289
|
+
...limit !== void 0 ? { limit } : {}
|
|
103290
|
+
});
|
|
103291
|
+
return;
|
|
103292
|
+
}
|
|
103293
|
+
console.error(
|
|
103294
|
+
"Usage: lotics starter list | show <starter_id> | init <starter_id> [path] | fixtures capture"
|
|
103295
|
+
);
|
|
103296
|
+
process.exit(1);
|
|
103735
103297
|
}
|
|
103736
103298
|
if (command === "docs") {
|
|
103737
103299
|
docsCommand({ area: subcommand });
|
|
@@ -103741,11 +103303,11 @@ async function main() {
|
|
|
103741
103303
|
let input = subcommand ?? "";
|
|
103742
103304
|
if (input.startsWith("@")) {
|
|
103743
103305
|
const file2 = input.slice(1);
|
|
103744
|
-
if (!
|
|
103306
|
+
if (!fs14.existsSync(file2)) {
|
|
103745
103307
|
console.error(`No such file: ${file2}`);
|
|
103746
103308
|
process.exit(1);
|
|
103747
103309
|
}
|
|
103748
|
-
input =
|
|
103310
|
+
input = fs14.readFileSync(file2, "utf-8");
|
|
103749
103311
|
} else if (input === "-") {
|
|
103750
103312
|
input = await readStdin();
|
|
103751
103313
|
}
|
|
@@ -103872,13 +103434,13 @@ async function main() {
|
|
|
103872
103434
|
if (command === "preview") {
|
|
103873
103435
|
if (subcommand && isStoredFileId(subcommand)) {
|
|
103874
103436
|
const { client: client2 } = requireClient(flags);
|
|
103875
|
-
const tmpDir =
|
|
103437
|
+
const tmpDir = fs14.mkdtempSync(path13.join(os4.tmpdir(), "lotics-preview-"));
|
|
103876
103438
|
try {
|
|
103877
103439
|
const { path: localPath, filename } = await client2.downloadFileById(subcommand, tmpDir);
|
|
103878
103440
|
const output = flags.output ?? defaultPreviewOutputPath(filename, process.cwd());
|
|
103879
103441
|
await runPreviewCommand(localPath, { output });
|
|
103880
103442
|
} finally {
|
|
103881
|
-
|
|
103443
|
+
fs14.rmSync(tmpDir, { recursive: true, force: true });
|
|
103882
103444
|
}
|
|
103883
103445
|
return;
|
|
103884
103446
|
}
|
|
@@ -104426,7 +103988,7 @@ ${JSON.stringify(info.input_schema, null, 2)}`);
|
|
|
104426
103988
|
const ingested = await ingestJsonArgs({
|
|
104427
103989
|
rawArg: toolArgs,
|
|
104428
103990
|
stdinIsTTY: process.stdin.isTTY ?? false,
|
|
104429
|
-
readFile: (p) =>
|
|
103991
|
+
readFile: (p) => fs14.readFileSync(p, "utf-8"),
|
|
104430
103992
|
readStdin
|
|
104431
103993
|
});
|
|
104432
103994
|
if (ingested.kind === "error") {
|