@datarails-ai/dr-appspace-cli 0.10.15 → 0.10.17
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/dist/cli.js +93 -12
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import { fileURLToPath as fileURLToPath6 } from "url";
|
|
|
13
13
|
// package.json
|
|
14
14
|
var package_default = {
|
|
15
15
|
name: "@datarails-ai/dr-appspace-cli",
|
|
16
|
-
version: "0.10.
|
|
16
|
+
version: "0.10.17",
|
|
17
17
|
description: "Datarails App Space CLI \u2014 build, try, push and publish App Space apps",
|
|
18
18
|
type: "module",
|
|
19
19
|
engines: {
|
|
@@ -57,7 +57,7 @@ var package_default = {
|
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
// src/buildInfo.ts
|
|
60
|
-
var BUILD_TIME = "2026-10-
|
|
60
|
+
var BUILD_TIME = "2026-10-01T11:50:28.550Z";
|
|
61
61
|
function formatBuildTime(iso) {
|
|
62
62
|
if (iso === "") return "";
|
|
63
63
|
const d = new Date(iso);
|
|
@@ -7774,10 +7774,11 @@ async function runLiveness(dir, appId, whole, client, only) {
|
|
|
7774
7774
|
`${handler.file} is not in this folder, so no handler was run`
|
|
7775
7775
|
);
|
|
7776
7776
|
}
|
|
7777
|
-
const groups =
|
|
7777
|
+
const groups = pagesToLoad(whole, only);
|
|
7778
7778
|
const merged = {};
|
|
7779
7779
|
const violations = /* @__PURE__ */ new Map();
|
|
7780
7780
|
const skipped = /* @__PURE__ */ new Map();
|
|
7781
|
+
const others = [];
|
|
7781
7782
|
const where2 = handler.file;
|
|
7782
7783
|
let loaded = false;
|
|
7783
7784
|
const keep = (verdict) => {
|
|
@@ -7795,7 +7796,8 @@ async function runLiveness(dir, appId, whole, client, only) {
|
|
|
7795
7796
|
{ violations: [...violations.values()], skipped: [...skipped.values()] },
|
|
7796
7797
|
declaredWidgets(contract)
|
|
7797
7798
|
),
|
|
7798
|
-
...loaded ? { payloads: merged } : {}
|
|
7799
|
+
...loaded ? { payloads: merged } : {},
|
|
7800
|
+
...others.length > 0 ? { others } : {}
|
|
7799
7801
|
});
|
|
7800
7802
|
const sole = groups.length === 1 ? groups[0] : null;
|
|
7801
7803
|
for (const group of groups.length > 1 || only !== void 0 ? groups : [null]) {
|
|
@@ -7837,13 +7839,19 @@ async function runLiveness(dir, appId, whole, client, only) {
|
|
|
7837
7839
|
const result = isRecord(answer.result) ? answer.result : {};
|
|
7838
7840
|
const answered = isRecord(result["widgets"]) ? result["widgets"] : {};
|
|
7839
7841
|
loaded = true;
|
|
7842
|
+
const load = { ok: true, envelope: { ...result, widgets: answered } };
|
|
7840
7843
|
keep(
|
|
7841
|
-
checkLiveness(
|
|
7842
|
-
view,
|
|
7843
|
-
{ ok: true, envelope: { ...result, widgets: answered } },
|
|
7844
|
-
{ handlerWhere: where2 }
|
|
7845
|
-
)
|
|
7844
|
+
checkLiveness(view, load, { handlerWhere: where2 })
|
|
7846
7845
|
);
|
|
7846
|
+
if (only !== void 0 && group !== null) {
|
|
7847
|
+
const rest = narrowTo(whole, group.ids.filter((id) => !only.has(id)));
|
|
7848
|
+
const verdict = checkLiveness(rest, load, { handlerWhere: where2 });
|
|
7849
|
+
for (const one of verdict.violations) {
|
|
7850
|
+
if (one.rule === "R5.1" && one.message !== void 0 && !others.includes(one.message)) {
|
|
7851
|
+
others.push(one.message);
|
|
7852
|
+
}
|
|
7853
|
+
}
|
|
7854
|
+
}
|
|
7847
7855
|
for (const [id, payload2] of Object.entries(answered)) {
|
|
7848
7856
|
if (!(id in merged)) merged[id] = payload2;
|
|
7849
7857
|
}
|
|
@@ -7889,6 +7897,11 @@ function pageGroups(contract) {
|
|
|
7889
7897
|
if (orphans.length > 0) groups.push({ path: null, ids: orphans });
|
|
7890
7898
|
return groups;
|
|
7891
7899
|
}
|
|
7900
|
+
function pagesToLoad(whole, only) {
|
|
7901
|
+
const groups = pageGroups(whole);
|
|
7902
|
+
if (only === void 0) return groups;
|
|
7903
|
+
return groups.map((group) => group.path === null ? { ...group, ids: group.ids.filter((id) => only.has(id)) } : group).filter((group) => group.ids.some((id) => only.has(id)));
|
|
7904
|
+
}
|
|
7892
7905
|
function pageFilters(contract, path3) {
|
|
7893
7906
|
const pages = contract.pages;
|
|
7894
7907
|
if (!Array.isArray(pages)) return null;
|
|
@@ -10131,6 +10144,9 @@ var contract_schema_default = {
|
|
|
10131
10144
|
where: { type: "object" },
|
|
10132
10145
|
order_by: { type: "string" },
|
|
10133
10146
|
limit: { type: "integer" },
|
|
10147
|
+
order: { enum: ["source", "declared"], description: "OPTIONAL, shape breakdown only (this schema has no conditional keyword, so the shape rule is the compiler's: source_shape refuses order on a breakdown source outside this enum). The order the items are answered in: declared is the labels listed in items, over any read; source keeps the rows' own order, which holds only where something promises one: a transform, or an app-table read that states order_by. Absent, the items are sorted by size. A waterfall card over a breakdown source needs one, with top: null." },
|
|
10148
|
+
items: { type: "array", items: { type: "string", minLength: 1 }, minItems: 1, description: `OPTIONAL, shape breakdown with order: declared only; on any other shape the compiler refuses it (source_shape). The breakdown's labels, each once, in the order they are drawn (a bridge's steps: ["Opening ARR", "New", ...]). A label the rows do not carry is left out; one they carry and the list does not name follows, in row order.` },
|
|
10149
|
+
top: { type: ["integer", "null"], minimum: 1, description: "OPTIONAL. On a breakdown source (the only shape whose top the compiler holds), how many items are drawn (default 5; the rest is one Other figure, other_value), or null to draw every one; a waterfall card over a breakdown source needs null. An app-table read is also capped by limit (default 200 rows), so a total over a bigger table needs limit set above its row count." },
|
|
10134
10150
|
requiresRole: { type: "array", items: { type: "string" }, description: "OPTIONAL. The app roles that may read this source, any of them: written as its handler's requiresRole, so the server refuses anyone else with 403. Absent means the roles of the pages whose components read it (pages[].roles), and every role as soon as one of those pages is open to every role." }
|
|
10135
10151
|
}
|
|
10136
10152
|
}
|
|
@@ -12493,6 +12509,7 @@ function sourceProblems(sources, app, handlers, extra) {
|
|
|
12493
12509
|
message: `source "${name}" states shape ${JSON.stringify(row.shape)}; a source answers ${either3(SOURCE_SHAPES2)}`
|
|
12494
12510
|
});
|
|
12495
12511
|
}
|
|
12512
|
+
problems.push(...orderProblems(name, row, at));
|
|
12496
12513
|
if (row.transform !== void 0 && row.transform !== null) {
|
|
12497
12514
|
const path3 = String(row.transform);
|
|
12498
12515
|
if (!TRANSFORM_RE.test(path3)) {
|
|
@@ -12512,6 +12529,62 @@ function sourceProblems(sources, app, handlers, extra) {
|
|
|
12512
12529
|
}
|
|
12513
12530
|
return problems;
|
|
12514
12531
|
}
|
|
12532
|
+
var SOURCE_ORDERS = ["source", "declared"];
|
|
12533
|
+
function orderProblems(name, row, at) {
|
|
12534
|
+
const problems = [];
|
|
12535
|
+
const say = (key, message) => problems.push({ code: "source_shape", pointer: at(name, key), message: `source "${name}" ${message}` });
|
|
12536
|
+
const has = (key) => Object.prototype.hasOwnProperty.call(row, key);
|
|
12537
|
+
if (row.shape !== "breakdown") {
|
|
12538
|
+
if (has("items")) say("items", 'states items, which only a source shaped breakdown reads (with order "declared"); give it shape breakdown, or drop items');
|
|
12539
|
+
return problems;
|
|
12540
|
+
}
|
|
12541
|
+
if (has("order") && !SOURCE_ORDERS.includes(row.order)) {
|
|
12542
|
+
say("order", `states order ${JSON.stringify(row.order)}; a breakdown source keeps ${either3(SOURCE_ORDERS.map((one) => JSON.stringify(one)))} order (the rows' own, or the labels listed in items), and is otherwise sorted by size`);
|
|
12543
|
+
}
|
|
12544
|
+
if (has("items")) {
|
|
12545
|
+
const labels = Array.isArray(row.items) ? row.items : null;
|
|
12546
|
+
if (labels === null || labels.length === 0 || !labels.every(named4) || new Set(labels).size !== labels.length) {
|
|
12547
|
+
say("items", `states items as ${JSON.stringify(row.items)}; items is the breakdown's labels, each once, in the order they are drawn (["Opening ARR", "New", "Churn"])`);
|
|
12548
|
+
} else if (row.order !== "declared") {
|
|
12549
|
+
say("items", 'lists items, which are read only with order "declared"; add "order": "declared", or drop items');
|
|
12550
|
+
}
|
|
12551
|
+
} else if (row.order === "declared") {
|
|
12552
|
+
say("order", `states order "declared" and lists no items; add "items": [the labels, in the order they are drawn], or use "order": "source" to keep the rows' own order`);
|
|
12553
|
+
}
|
|
12554
|
+
if (has("top") && row.top !== null && !(Number.isInteger(row.top) && row.top > 0)) {
|
|
12555
|
+
say("top", `states top ${JSON.stringify(row.top)}; top is how many of the breakdown's items are drawn (a whole number, default 5; the rest is one "Other" figure), or null to draw every one`);
|
|
12556
|
+
}
|
|
12557
|
+
return problems;
|
|
12558
|
+
}
|
|
12559
|
+
function bridgeFixes(row) {
|
|
12560
|
+
const declare = '"order": "declared" with "items": [the step labels, in order]';
|
|
12561
|
+
const transformed = row.transform !== void 0 && row.transform !== null;
|
|
12562
|
+
const origin = originOf(row);
|
|
12563
|
+
const unordered = origin === "financeos" ? "a FinanceOS aggregate" : origin === "call" ? "a call" : "an app-table read with no order_by";
|
|
12564
|
+
const fixes = [];
|
|
12565
|
+
let order2 = null;
|
|
12566
|
+
if (row.order === "declared") {
|
|
12567
|
+
if (!(Array.isArray(row.items) && row.items.length > 0)) {
|
|
12568
|
+
order2 = "unstated";
|
|
12569
|
+
fixes.push('add "items": [the step labels, in order] beside "order": "declared"');
|
|
12570
|
+
}
|
|
12571
|
+
} else if (row.order === "source") {
|
|
12572
|
+
if (!transformed && !(origin === "table" && named4(row.order_by))) {
|
|
12573
|
+
order2 = "unpromised";
|
|
12574
|
+
fixes.push(
|
|
12575
|
+
origin === "table" ? `add "order_by" naming the column the steps sort by (${unordered} comes back in no promised order), or replace "order": "source" with ${declare}` : `replace "order": "source" with ${declare} \u2014 ${unordered} comes back in no promised order, so its steps could be drawn shuffled`
|
|
12576
|
+
);
|
|
12577
|
+
}
|
|
12578
|
+
} else {
|
|
12579
|
+
order2 = "unstated";
|
|
12580
|
+
fixes.push(
|
|
12581
|
+
transformed ? `add ${declare}, or "order": "source" to keep the order your transform returns` : origin === "table" ? `add ${declare}, or "order": "source" with an "order_by" naming the column the steps sort by` : `add ${declare} (${unordered} comes back in no promised order, so "order": "source" would not hold)`
|
|
12582
|
+
);
|
|
12583
|
+
}
|
|
12584
|
+
const cut3 = !(Object.prototype.hasOwnProperty.call(row, "top") && row.top === null);
|
|
12585
|
+
if (cut3) fixes.push('add "top": null (nothing cut, no "Other")');
|
|
12586
|
+
return { fixes, order: order2, cut: cut3 };
|
|
12587
|
+
}
|
|
12515
12588
|
function carriedFields(row, model) {
|
|
12516
12589
|
if (row.transform !== void 0 && row.transform !== null) return null;
|
|
12517
12590
|
const origin = originOf(row);
|
|
@@ -14091,9 +14164,12 @@ function widgetProblems(elements, tree, handlers, sources, widgetsPin = WIDGETS)
|
|
|
14091
14164
|
shaped(`draws ${props.kind}, and source "${props.source}" answers ${shape} (its shape); give the source the shape ${reads.join(" or ")}`);
|
|
14092
14165
|
continue;
|
|
14093
14166
|
}
|
|
14094
|
-
|
|
14167
|
+
const bridge = ORDERED_KINDS.includes(props.kind) && shape === "breakdown" ? bridgeFixes(source) : null;
|
|
14168
|
+
if (bridge !== null && bridge.fixes.length > 0) {
|
|
14169
|
+
const otherFigure = 'cuts to its top 5 (the rest is one "Other" figure a waterfall does not draw)';
|
|
14170
|
+
const why = bridge.order === "unpromised" ? `that keeps the order its rows arrive in, which nothing promises${bridge.cut ? `, and the platform ${otherFigure}` : ""}` : bridge.order === "unstated" ? `which the platform sorts by size${bridge.cut ? ` and ${otherFigure}` : ""}` : `which the platform ${otherFigure}`;
|
|
14095
14171
|
shaped(
|
|
14096
|
-
`draws ${props.kind}, and source "${props.source}" is a breakdown
|
|
14172
|
+
`draws ${props.kind}, and source "${props.source}" is a breakdown ${why} \u2014 so the bridge would draw the wrong steps${bridge.cut ? " and the wrong total" : ""}. In data.sources.${props.source}: ${bridge.fixes.join("; and ")}; or give the source the shape series (the periods are the steps, in order)`
|
|
14097
14173
|
);
|
|
14098
14174
|
}
|
|
14099
14175
|
}
|
|
@@ -25974,9 +26050,14 @@ function livenessLine(report) {
|
|
|
25974
26050
|
`;
|
|
25975
26051
|
}
|
|
25976
26052
|
const blank4 = live.problems.length;
|
|
25977
|
-
|
|
26053
|
+
const line2 = blank4 === 0 ? `liveness: ${String(live.widgets)} of ${String(live.widgets)} widget(s) came back with a figure.
|
|
25978
26054
|
` : `liveness: ${String(blank4)} of ${String(live.widgets)} widget(s) came back with NO figure.
|
|
25979
26055
|
`;
|
|
26056
|
+
const others = live.others ?? [];
|
|
26057
|
+
if (others.length === 0) return line2;
|
|
26058
|
+
return line2 + `liveness: noted \u2014 ${String(others.length)} card(s) other landings put on these pages came back with NO figure (not this landing's to fix):
|
|
26059
|
+
` + others.map((one) => ` ${one}
|
|
26060
|
+
`).join("");
|
|
25980
26061
|
}
|
|
25981
26062
|
function describe5(report, skipped) {
|
|
25982
26063
|
let out = `${report.kit}: ${String(report.files.length)} files, round trip equal
|