@datarails-ai/dr-appspace-cli 0.10.12 → 0.10.14
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 +104 -6
- 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.14",
|
|
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-01T09:25:02.651Z";
|
|
61
61
|
function formatBuildTime(iso) {
|
|
62
62
|
if (iso === "") return "";
|
|
63
63
|
const d = new Date(iso);
|
|
@@ -13299,8 +13299,9 @@ function controlRow(elements) {
|
|
|
13299
13299
|
for (const control of controls) {
|
|
13300
13300
|
const props = isPlainObject5(control.props) ? control.props : {};
|
|
13301
13301
|
const id = control.id;
|
|
13302
|
+
out.push(' <span class="drw-field--inline">');
|
|
13302
13303
|
if (id && typeof props.label === "string") {
|
|
13303
|
-
out.push(`
|
|
13304
|
+
out.push(` <label for="${attr(id)}">${text(props.label)}</label>`);
|
|
13304
13305
|
}
|
|
13305
13306
|
const parts = [];
|
|
13306
13307
|
if (id) parts.push(`id="${attr(id)}"`);
|
|
@@ -13313,7 +13314,8 @@ function controlRow(elements) {
|
|
|
13313
13314
|
if (props.control_kind) parts.push(`data-dr-control-kind="${attr(props.control_kind)}"`);
|
|
13314
13315
|
const classes = (control.classes ?? []).join(" ");
|
|
13315
13316
|
const open2 = classes === "" ? "" : ` class="${attr(classes)}"`;
|
|
13316
|
-
out.push(`
|
|
13317
|
+
out.push(` <${control.tag ?? "input"}${open2} ${parts.join(" ")} />`);
|
|
13318
|
+
out.push(" </span>");
|
|
13317
13319
|
}
|
|
13318
13320
|
out.push("</div>");
|
|
13319
13321
|
return out;
|
|
@@ -14564,6 +14566,92 @@ function originOf(row) {
|
|
|
14564
14566
|
function sourcesOf(contract) {
|
|
14565
14567
|
return isPlainObject7(contract?.data?.sources) ? contract.data.sources : {};
|
|
14566
14568
|
}
|
|
14569
|
+
var FINANCEOS_SCOPES = {
|
|
14570
|
+
commands: {
|
|
14571
|
+
"status:read": ["status", "whoami"],
|
|
14572
|
+
"tables:read": ["list_tables", "get_table"],
|
|
14573
|
+
"semantic:read": ["list_semantic_tables", "get_semantic_table", "metric_series"],
|
|
14574
|
+
"metrics:read": ["list_metrics", "get_metric", "metric_series"],
|
|
14575
|
+
"filebox:read": ["list_filebox"],
|
|
14576
|
+
"users:read": ["list_users"],
|
|
14577
|
+
"pipeline:read": ["data_readiness"],
|
|
14578
|
+
"raw:read": ["get_raw_table", "get_raw_table_data", "get_aliased_table_data"]
|
|
14579
|
+
},
|
|
14580
|
+
namespaces: {
|
|
14581
|
+
"status:read": ["status"],
|
|
14582
|
+
"tables:read": ["tables"],
|
|
14583
|
+
"semantic:read": ["semantic_tables"],
|
|
14584
|
+
"metrics:read": ["metrics", "data_models"],
|
|
14585
|
+
"filebox:read": ["filebox"]
|
|
14586
|
+
},
|
|
14587
|
+
gated: {
|
|
14588
|
+
get_raw_table: "raw:read",
|
|
14589
|
+
get_raw_table_data: "raw:read",
|
|
14590
|
+
get_aliased_table_data: "raw:read"
|
|
14591
|
+
}
|
|
14592
|
+
};
|
|
14593
|
+
function scopesGranting(kind, name) {
|
|
14594
|
+
return Object.keys(FINANCEOS_SCOPES[kind]).filter((scope) => FINANCEOS_SCOPES[kind][scope].includes(name)).sort();
|
|
14595
|
+
}
|
|
14596
|
+
function financeosNeeds(row, origin) {
|
|
14597
|
+
const needs = [];
|
|
14598
|
+
const need = (reads, anyOf, catalog = false) => {
|
|
14599
|
+
if (anyOf.length > 0 && !needs.some((one) => one.reads === reads && one.catalog === catalog)) needs.push({ reads, anyOf, catalog });
|
|
14600
|
+
};
|
|
14601
|
+
if (origin === "call") {
|
|
14602
|
+
const parts = typeof row.from.call === "string" ? row.from.call.split(".") : [];
|
|
14603
|
+
if (parts.length === 1) need(parts[0], scopesGranting("commands", parts[0]));
|
|
14604
|
+
if (parts.length === 2) {
|
|
14605
|
+
need(parts[0], scopesGranting("namespaces", parts[0]));
|
|
14606
|
+
const gated = FINANCEOS_SCOPES.gated[parts[1]];
|
|
14607
|
+
if (gated) need(`${parts[0]}.${parts[1]}`, [gated]);
|
|
14608
|
+
}
|
|
14609
|
+
return needs;
|
|
14610
|
+
}
|
|
14611
|
+
const read = isPlainObject7(row.from.financeos) ? row.from.financeos : {};
|
|
14612
|
+
const filterable = Array.isArray(row.filterable) && row.filterable.length > 0;
|
|
14613
|
+
if (read.metric_id !== void 0 && read.metric_id !== null) {
|
|
14614
|
+
if (read.drill_rows) need("data_models", scopesGranting("namespaces", "data_models"));
|
|
14615
|
+
else need("metric_series", scopesGranting("commands", "metric_series"));
|
|
14616
|
+
if (filterable) need("data_models", scopesGranting("namespaces", "data_models"), true);
|
|
14617
|
+
return needs;
|
|
14618
|
+
}
|
|
14619
|
+
const address = read.address === "id" || read.address === "alias" ? read.address : read.table_alias ? "alias" : read.table_id !== void 0 && read.table_id !== null ? "id" : null;
|
|
14620
|
+
if (address === null) return needs;
|
|
14621
|
+
const raw = read.rows === "raw" || row.shape === "ohlc";
|
|
14622
|
+
if (address === "id") need("get_raw_table", scopesGranting("commands", "get_raw_table"));
|
|
14623
|
+
if (raw) {
|
|
14624
|
+
const page = address === "id" ? "get_raw_table_data" : "get_aliased_table_data";
|
|
14625
|
+
need(page, scopesGranting("commands", page));
|
|
14626
|
+
} else {
|
|
14627
|
+
need("data_models", scopesGranting("namespaces", "data_models"));
|
|
14628
|
+
}
|
|
14629
|
+
if (filterable) need("data_models", scopesGranting("namespaces", "data_models"), true);
|
|
14630
|
+
return needs;
|
|
14631
|
+
}
|
|
14632
|
+
function financeosScopeProblems(name, row, origin, declared) {
|
|
14633
|
+
const missing = /* @__PURE__ */ new Map();
|
|
14634
|
+
for (const { reads, anyOf, catalog } of financeosNeeds(row, origin)) {
|
|
14635
|
+
if (anyOf.some((scope2) => declared.includes(scope2))) continue;
|
|
14636
|
+
const scope = anyOf.includes("metrics:read") ? "metrics:read" : anyOf[0];
|
|
14637
|
+
const entry = missing.get(scope) ?? { scope, anyOf, reads: [], catalog: true };
|
|
14638
|
+
if (!entry.reads.includes(reads)) entry.reads.push(reads);
|
|
14639
|
+
entry.catalog = entry.catalog && catalog;
|
|
14640
|
+
missing.set(scope, entry);
|
|
14641
|
+
}
|
|
14642
|
+
return [...missing.values()].map(
|
|
14643
|
+
({ scope, anyOf, reads, catalog }) => catalog ? {
|
|
14644
|
+
code: "financeos_scope_catalog",
|
|
14645
|
+
pointer: `/data/sources/${escapePointer3(name)}/filterable`,
|
|
14646
|
+
message: `source "${name}" offers filterable values, which the filter bar reads from ${reads.join(" and ")} with financeos scope ${anyOf.join(" or ")}; the source loads without it, but its filter bar offers no values until you add ${JSON.stringify(scope)} to app.capabilities.financeos`,
|
|
14647
|
+
advisory: true
|
|
14648
|
+
} : {
|
|
14649
|
+
code: "financeos_scope",
|
|
14650
|
+
pointer: "/app/capabilities/financeos",
|
|
14651
|
+
message: `source "${name}" reads ${reads.join(" and ")}, which needs financeos scope ${anyOf.join(" or ")}; add ${JSON.stringify(scope)} to app.capabilities.financeos`
|
|
14652
|
+
}
|
|
14653
|
+
);
|
|
14654
|
+
}
|
|
14567
14655
|
function servedSources(elements, sources) {
|
|
14568
14656
|
const out = /* @__PURE__ */ new Set();
|
|
14569
14657
|
for (const element of Object.values(elements)) {
|
|
@@ -14604,6 +14692,8 @@ function sourceProblems(sources, app, handlers, extra) {
|
|
|
14604
14692
|
pointer: "/app/capabilities/financeos",
|
|
14605
14693
|
message: `source "${name}" reads FinanceOS, and this app grants no financeos capability; grant at least one read scope (e.g. metrics:read, plus raw:read to read a table by id)`
|
|
14606
14694
|
});
|
|
14695
|
+
} else if (origin === "financeos" || origin === "call") {
|
|
14696
|
+
problems.push(...financeosScopeProblems(name, row, origin, financeos));
|
|
14607
14697
|
}
|
|
14608
14698
|
if (origin === "depends") {
|
|
14609
14699
|
for (const [index, dep] of row.from.entries()) {
|
|
@@ -15122,7 +15212,8 @@ function compileApp(contract, { kit = null, runtime = RUNTIME, extra = {} } = {}
|
|
|
15122
15212
|
const handlers = isPlainObject7(contract.data?.app?.handlers) ? contract.data.app.handlers : {};
|
|
15123
15213
|
const names = Object.keys(handlers).sort(natural3);
|
|
15124
15214
|
const stated2 = sourcesOf(contract);
|
|
15125
|
-
|
|
15215
|
+
const sourceFindings = sourceProblems(stated2, app, handlers, extra);
|
|
15216
|
+
problems.push(...sourceFindings.filter((one) => !one.advisory));
|
|
15126
15217
|
problems.push(...compareProblems(stated2, model));
|
|
15127
15218
|
problems.push(...paramProblems(contract, stated2));
|
|
15128
15219
|
problems.push(...themeProblems(app));
|
|
@@ -15206,7 +15297,7 @@ function compileApp(contract, { kit = null, runtime = RUNTIME, extra = {} } = {}
|
|
|
15206
15297
|
problems.push(...numberPinProblems(declared, { "dr-app-runtime": runtime, "dr-app-widgets": appWidgets, "dr-components": appComponents, "dr-components-controls": appControls }));
|
|
15207
15298
|
problems.push(...whenPinProblems(declared, { "dr-components": appComponents }));
|
|
15208
15299
|
const widgetFindings = tree.problems.length === 0 ? widgetProblems(declared, tree, handlers, contract?.data?.sources, appWidgets) : [];
|
|
15209
|
-
const warnings = widgetFindings.filter((one) => one.advisory).map(({ advisory: _advisory, ...one }) => one);
|
|
15300
|
+
const warnings = [...sourceFindings, ...widgetFindings].filter((one) => one.advisory).map(({ advisory: _advisory, ...one }) => one);
|
|
15210
15301
|
problems.push(...widgetFindings.filter((one) => !one.advisory));
|
|
15211
15302
|
if (tree.problems.length === 0) problems.push(...partProblems(declared, tree, handlers, sources, contract?.pages, model));
|
|
15212
15303
|
if (problems.length > 0) return { files: {}, problems, contract, warnings };
|
|
@@ -24467,6 +24558,8 @@ var REFUSALS = /* @__PURE__ */ new Set([
|
|
|
24467
24558
|
"source_unknown",
|
|
24468
24559
|
"source_name_taken",
|
|
24469
24560
|
"source_needs_financeos",
|
|
24561
|
+
// a source the declared financeos scopes do not reach (conversation 34b3d658)
|
|
24562
|
+
"financeos_scope",
|
|
24470
24563
|
"transform_missing",
|
|
24471
24564
|
// a dashboard dataset row's own transform (transforms.mjs)
|
|
24472
24565
|
"transform_row",
|
|
@@ -24533,6 +24626,9 @@ var PARAM_REFUSALS = {
|
|
|
24533
24626
|
param_kind_value: "a param's default, min/max/step, values or max_selected is one its kind cannot hold",
|
|
24534
24627
|
param_conflict: "one param name declared twice with different rules (the server keeps the first)"
|
|
24535
24628
|
};
|
|
24629
|
+
var SOURCE_REFUSALS = {
|
|
24630
|
+
financeos_scope: "a FinanceOS source reads a surface app.capabilities.financeos does not grant (a table aggregate or a metric needs metrics:read; a by-id table or raw rows need raw:read; a call needs the scope its command is under) \u2014 add the scope the message names. `filterable` values without metrics:read are only a warning (financeos_scope_catalog): the source loads, its filter bar offers nothing"
|
|
24631
|
+
};
|
|
24536
24632
|
var KPI_REFUSALS = {
|
|
24537
24633
|
source_compare_field: "a source's compare names a field its rows do not carry (where that is knowable: a FinanceOS aggregate's dimensions, measures and period column; an app table's columns), or is set on a source not shaped kpi \u2014 declare the measure beside the figure, or name one it carries"
|
|
24538
24634
|
};
|
|
@@ -25586,6 +25682,8 @@ function registerCompileCommand(parent) {
|
|
|
25586
25682
|
"",
|
|
25587
25683
|
"An app's own header is refused with:",
|
|
25588
25684
|
...Object.entries(APP_REFUSALS).map(([code, what]) => ` ${code.padEnd(22)}${what}`),
|
|
25685
|
+
"A FinanceOS source the declared scopes do not reach is refused with:",
|
|
25686
|
+
...Object.entries(SOURCE_REFUSALS).map(([code, what]) => ` ${code.padEnd(22)}${what}`),
|
|
25589
25687
|
"A KPI source (shape kpi: its period comes from the rows; compare sets the figure against another measure of the same row) is refused with:",
|
|
25590
25688
|
...Object.entries(KPI_REFUSALS).map(([code, what]) => ` ${code.padEnd(22)}${what}`),
|
|
25591
25689
|
"",
|