@graphit/cli 0.2.322 → 0.2.330
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/bin/graphit +1 -1
- package/bin/graphit.ps1 +1 -1
- package/dist/api/client.js +15 -0
- package/dist/api/client.js.map +1 -1
- package/dist/commands/ds-config.js +2 -2
- package/dist/commands/ds-config.js.map +1 -1
- package/dist/commands/ds.js +2 -2
- package/dist/commands/ds.js.map +1 -1
- package/dist/commands/kb.js +347 -15
- package/dist/commands/kb.js.map +1 -1
- package/dist/commands/query.js +7 -7
- package/dist/commands/query.js.map +1 -1
- package/dist/index.js +0 -8
- package/dist/index.js.map +1 -1
- package/dist/skill-guard.js +2 -1
- package/dist/skill-guard.js.map +1 -1
- package/package.json +1 -1
- package/scripts/verb-policy-source.json +31 -103
- package/skills/graphit/SKILL.md +32 -39
- package/skills/graphit/VERSION.json +1 -1
- package/skills/graphit/references/attached-docs.md +74 -0
- package/skills/graphit/references/data-source-refresh.md +38 -0
- package/skills/graphit/references/data-sources.md +39 -111
- package/skills/graphit/references/filters-advanced.md +2 -2
- package/skills/graphit/references/governance-explained.md +18 -29
- package/skills/graphit/references/governance.md +20 -83
- package/skills/graphit/references/kb-actions.md +28 -81
- package/skills/graphit/references/kb-discovery.md +35 -64
- package/skills/graphit/references/kb-scope.md +17 -15
- package/skills/graphit/references/kb-structure.md +28 -54
- package/skills/graphit/references/kb-traversal.md +24 -96
- package/skills/graphit/references/metric-families.md +19 -0
- package/skills/graphit/references/migration.md +2 -2
- package/skills/graphit/references/onboarding.md +5 -4
- package/skills/graphit/references/presentations.md +1 -1
- package/skills/graphit/references/runtime.md +6 -6
- package/skills/graphit/references/semantic-authoring.md +81 -0
- package/skills/graphit/references/sql-reference.md +19 -20
- package/dist/commands/kb-constraints.d.ts +0 -14
- package/dist/commands/kb-constraints.js +0 -53
- package/dist/commands/kb-constraints.js.map +0 -1
- package/dist/commands/kb-create.d.ts +0 -2
- package/dist/commands/kb-create.js +0 -296
- package/dist/commands/kb-create.js.map +0 -1
- package/dist/commands/kb-delete.d.ts +0 -2
- package/dist/commands/kb-delete.js +0 -37
- package/dist/commands/kb-delete.js.map +0 -1
- package/dist/commands/kb-read.d.ts +0 -2
- package/dist/commands/kb-read.js +0 -223
- package/dist/commands/kb-read.js.map +0 -1
- package/dist/commands/kb-shared.d.ts +0 -43
- package/dist/commands/kb-shared.js +0 -81
- package/dist/commands/kb-shared.js.map +0 -1
- package/dist/commands/kb-update.d.ts +0 -2
- package/dist/commands/kb-update.js +0 -240
- package/dist/commands/kb-update.js.map +0 -1
- package/dist/commands/sl/index.d.ts +0 -2
- package/dist/commands/sl/index.js +0 -263
- package/dist/commands/sl/index.js.map +0 -1
- package/skills/graphit/references/parameterized-metrics.md +0 -77
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { apiClient } from "../../api/client.js";
|
|
3
|
-
import { errorOutput } from "../../output/format.js";
|
|
4
|
-
import { writeStderr } from "../../stderr.js";
|
|
5
|
-
// The dbt-native semantic-layer command tree (dormant preview).
|
|
6
|
-
//
|
|
7
|
-
// GATED: registered only when GRAPHIT_SL=1 (see src/index.ts). This file lives
|
|
8
|
-
// in a SUBDIRECTORY of commands/ deliberately - the SKILL.md/tool-manifest
|
|
9
|
-
// generators walk only top-level dist/commands/*.js registrars, so nothing
|
|
10
|
-
// here can reach the published skill, the verb-policy manifest, or the in-app
|
|
11
|
-
// agent surface until the cutover promotes it. At cutover this tree replaces
|
|
12
|
-
// the legacy `kb` group (same verbs, `kb` group name), the gate drops, a
|
|
13
|
-
// top-level registrar makes the walk see it, verb-policy rows + skill
|
|
14
|
-
// references land, and gen:commands regenerates - the full CLI change
|
|
15
|
-
// checklist runs THEN, against commands users can actually run.
|
|
16
|
-
//
|
|
17
|
-
// The noun set mirrors the backend's typed descriptors: semantic-model,
|
|
18
|
-
// metric, group. Nested entities/dimensions/measures mutate through
|
|
19
|
-
// `update semantic-model` (a provided list replaces the stored list whole)
|
|
20
|
-
// and are independently readable (`sl entity`, `sl get semantic-model`).
|
|
21
|
-
const NOUNS = ["semantic-model", "metric", "group"];
|
|
22
|
-
const ARG_NOUN = "Semantic-layer noun - semantic-model, metric or group";
|
|
23
|
-
const ARG_NAME = "Asset name (lowercase snake_case), as returned by sl list or sl search";
|
|
24
|
-
function requireNoun(noun) {
|
|
25
|
-
if (!NOUNS.includes(noun)) {
|
|
26
|
-
writeStderr(JSON.stringify({
|
|
27
|
-
error: `Unknown noun '${noun}'. Valid: ${NOUNS.join(", ")}`,
|
|
28
|
-
}));
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
return noun;
|
|
32
|
-
}
|
|
33
|
-
function payloadFromOpts(opts) {
|
|
34
|
-
if (!opts.file && !opts.json) {
|
|
35
|
-
writeStderr(JSON.stringify({ error: "Provide the definition via --file <path> or --json <string>" }));
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
if (opts.file && opts.json) {
|
|
39
|
-
writeStderr(JSON.stringify({ error: "--file and --json are mutually exclusive" }));
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
const raw = opts.file ? readFileSync(opts.file, "utf-8") : opts.json;
|
|
43
|
-
try {
|
|
44
|
-
return JSON.parse(raw);
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
writeStderr(JSON.stringify({ error: "Definition is not valid JSON" }));
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function parseAxes(pairs) {
|
|
52
|
-
const axes = {};
|
|
53
|
-
for (const pair of pairs ?? []) {
|
|
54
|
-
const eq = pair.indexOf("=");
|
|
55
|
-
if (eq <= 0) {
|
|
56
|
-
writeStderr(JSON.stringify({ error: `--axis '${pair}' must be key=value` }));
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
axes[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
60
|
-
}
|
|
61
|
-
return axes;
|
|
62
|
-
}
|
|
63
|
-
export function registerSlCommands(program) {
|
|
64
|
-
const sl = program
|
|
65
|
-
.command("sl")
|
|
66
|
-
.description("Semantic layer (dbt-native Knowledge Base) - semantic models, metrics, groups");
|
|
67
|
-
// -- create ---------------------------------------------------------------
|
|
68
|
-
const create = sl.command("create").description("Create semantic-layer assets");
|
|
69
|
-
create
|
|
70
|
-
.command("semantic-model")
|
|
71
|
-
.description("Create a semantic model from a JSON definition (dbt shape: name, model, " +
|
|
72
|
-
"entities, dimensions, measures, defaults, group)")
|
|
73
|
-
.option("--file <path>", "Path to a JSON definition file")
|
|
74
|
-
.option("--json <string>", "Inline JSON definition")
|
|
75
|
-
.option("--unverified", "Create as draft instead of verified")
|
|
76
|
-
.action(async function () {
|
|
77
|
-
try {
|
|
78
|
-
const opts = this.opts();
|
|
79
|
-
const body = {
|
|
80
|
-
definition: payloadFromOpts(opts),
|
|
81
|
-
unverified: opts.unverified === true,
|
|
82
|
-
};
|
|
83
|
-
console.log(JSON.stringify(await apiClient.post("/api/v1/cli/sl/semantic-model", body)));
|
|
84
|
-
}
|
|
85
|
-
catch (err) {
|
|
86
|
-
errorOutput(err);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
create
|
|
90
|
-
.command("metric")
|
|
91
|
-
.description("Create a metric from a JSON definition (type: simple, ratio, derived, " +
|
|
92
|
-
"cumulative or conversion, with type_params). --family/--axis tag a " +
|
|
93
|
-
"concrete member of a metric family")
|
|
94
|
-
.option("--file <path>", "Path to a JSON definition file")
|
|
95
|
-
.option("--json <string>", "Inline JSON definition")
|
|
96
|
-
.option("--family <name>", "Metric family this variant belongs to")
|
|
97
|
-
.option("--axis <key=value...>", "Axis value that generated this variant (repeatable)")
|
|
98
|
-
.option("--unverified", "Create as draft instead of verified")
|
|
99
|
-
.action(async function () {
|
|
100
|
-
try {
|
|
101
|
-
const opts = this.opts();
|
|
102
|
-
const definition = payloadFromOpts(opts);
|
|
103
|
-
if (opts.family) {
|
|
104
|
-
const meta = (definition.meta ??= {});
|
|
105
|
-
const graphit = (meta.graphit ??=
|
|
106
|
-
{});
|
|
107
|
-
graphit.family ??= opts.family;
|
|
108
|
-
const axes = parseAxes(opts.axis);
|
|
109
|
-
if (Object.keys(axes).length > 0)
|
|
110
|
-
graphit.axes ??= axes;
|
|
111
|
-
}
|
|
112
|
-
const body = { definition, unverified: opts.unverified === true };
|
|
113
|
-
console.log(JSON.stringify(await apiClient.post("/api/v1/cli/sl/metric", body)));
|
|
114
|
-
}
|
|
115
|
-
catch (err) {
|
|
116
|
-
errorOutput(err);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
create
|
|
120
|
-
.command("group")
|
|
121
|
-
.description("Create a group (the domain analogue; admin only)")
|
|
122
|
-
.requiredOption("--name <name>", "Group name (lowercase snake_case)")
|
|
123
|
-
.option("--description <text>", "Group description")
|
|
124
|
-
.option("--owner-email <email>", "Owning analyst's email")
|
|
125
|
-
.option("--access <level>", "dbt group access level: private, protected or public")
|
|
126
|
-
.action(async function () {
|
|
127
|
-
try {
|
|
128
|
-
const opts = this.opts();
|
|
129
|
-
const definition = { name: opts.name };
|
|
130
|
-
if (opts.description)
|
|
131
|
-
definition.description = opts.description;
|
|
132
|
-
if (opts.ownerEmail)
|
|
133
|
-
definition.owner_email = opts.ownerEmail;
|
|
134
|
-
if (opts.access)
|
|
135
|
-
definition.access = opts.access;
|
|
136
|
-
console.log(JSON.stringify(await apiClient.post("/api/v1/cli/sl/group", { definition })));
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
errorOutput(err);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
// -- update ---------------------------------------------------------------
|
|
143
|
-
sl.command("update")
|
|
144
|
-
.argument("<noun>", ARG_NOUN)
|
|
145
|
-
.argument("<name>", ARG_NAME)
|
|
146
|
-
.description("Update an asset with a JSON patch. On semantic-model, a provided " +
|
|
147
|
-
"entities/dimensions/measures list replaces the stored list whole")
|
|
148
|
-
.option("--file <path>", "Path to a JSON patch file")
|
|
149
|
-
.option("--json <string>", "Inline JSON patch")
|
|
150
|
-
.action(async function (noun, name) {
|
|
151
|
-
try {
|
|
152
|
-
requireNoun(noun);
|
|
153
|
-
const body = { patch: payloadFromOpts(this.opts()) };
|
|
154
|
-
console.log(JSON.stringify(await apiClient.put(`/api/v1/cli/sl/${noun}/${encodeURIComponent(name)}`, body)));
|
|
155
|
-
}
|
|
156
|
-
catch (err) {
|
|
157
|
-
errorOutput(err);
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
// -- delete ---------------------------------------------------------------
|
|
161
|
-
sl.command("delete")
|
|
162
|
-
.argument("<noun>", ARG_NOUN)
|
|
163
|
-
.argument("<name>", ARG_NAME)
|
|
164
|
-
.description("Delete an asset (requires --yes). Refused while other definitions " +
|
|
165
|
-
"still reference it")
|
|
166
|
-
.requiredOption("--yes", "Confirm deletion")
|
|
167
|
-
.action(async function (noun, name) {
|
|
168
|
-
try {
|
|
169
|
-
requireNoun(noun);
|
|
170
|
-
await apiClient.delete(`/api/v1/cli/sl/${noun}/${encodeURIComponent(name)}`);
|
|
171
|
-
console.log(JSON.stringify({ status: "deleted", noun, name }));
|
|
172
|
-
}
|
|
173
|
-
catch (err) {
|
|
174
|
-
errorOutput(err);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
// -- reads ----------------------------------------------------------------
|
|
178
|
-
sl.command("get")
|
|
179
|
-
.argument("<noun>", ARG_NOUN)
|
|
180
|
-
.argument("<name>", ARG_NAME)
|
|
181
|
-
.description("Fetch one asset. Metrics include their family and sibling variants")
|
|
182
|
-
.action(async function (noun, name) {
|
|
183
|
-
try {
|
|
184
|
-
requireNoun(noun);
|
|
185
|
-
console.log(JSON.stringify(await apiClient.get(`/api/v1/cli/sl/${noun}/${encodeURIComponent(name)}`)));
|
|
186
|
-
}
|
|
187
|
-
catch (err) {
|
|
188
|
-
errorOutput(err);
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
sl.command("list")
|
|
192
|
-
.argument("<noun>", ARG_NOUN)
|
|
193
|
-
.description("List all visible assets of one noun")
|
|
194
|
-
.action(async function (noun) {
|
|
195
|
-
try {
|
|
196
|
-
requireNoun(noun);
|
|
197
|
-
console.log(JSON.stringify(await apiClient.get(`/api/v1/cli/sl/${noun}`)));
|
|
198
|
-
}
|
|
199
|
-
catch (err) {
|
|
200
|
-
errorOutput(err);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
sl.command("tree")
|
|
204
|
-
.description("The whole visible semantic layer: group -> semantic model -> assets, " +
|
|
205
|
-
"metric families collapsed to one card each")
|
|
206
|
-
.action(async function () {
|
|
207
|
-
try {
|
|
208
|
-
console.log(JSON.stringify(await apiClient.get("/api/v1/cli/sl/tree")));
|
|
209
|
-
}
|
|
210
|
-
catch (err) {
|
|
211
|
-
errorOutput(err);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
sl.command("search")
|
|
215
|
-
.argument("<query>", "Search text (name or description)")
|
|
216
|
-
.description("Search semantic models, metrics, groups and nested components")
|
|
217
|
-
.option("--limit <n>", "Maximum results (default 50)")
|
|
218
|
-
.action(async function (query) {
|
|
219
|
-
try {
|
|
220
|
-
const rawLimit = this.opts().limit;
|
|
221
|
-
if (rawLimit !== undefined && !/^[1-9]\d*$/.test(rawLimit)) {
|
|
222
|
-
writeStderr(JSON.stringify({ error: `--limit '${rawLimit}' must be a positive integer` }));
|
|
223
|
-
process.exit(1);
|
|
224
|
-
}
|
|
225
|
-
const limit = rawLimit ? `&limit=${rawLimit}` : "";
|
|
226
|
-
console.log(JSON.stringify(await apiClient.get(`/api/v1/cli/sl/search?q=${encodeURIComponent(query)}${limit}`)));
|
|
227
|
-
}
|
|
228
|
-
catch (err) {
|
|
229
|
-
errorOutput(err);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
sl.command("entity")
|
|
233
|
-
.argument("<name>", "Entity name (as declared inside semantic models)")
|
|
234
|
-
.description("One entity across every visible semantic model that declares it")
|
|
235
|
-
.action(async function (name) {
|
|
236
|
-
try {
|
|
237
|
-
console.log(JSON.stringify(await apiClient.get(`/api/v1/cli/sl/entity/${encodeURIComponent(name)}`)));
|
|
238
|
-
}
|
|
239
|
-
catch (err) {
|
|
240
|
-
errorOutput(err);
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
sl.command("family")
|
|
244
|
-
.argument("<family>", "Metric family name")
|
|
245
|
-
.description("Expand a metric family; with --axis constraints, resolve to the one " +
|
|
246
|
-
"concrete member (ambiguity answers with the still-open axes)")
|
|
247
|
-
.option("--axis <key=value...>", "Axis constraint to resolve against (repeatable)")
|
|
248
|
-
.action(async function (family) {
|
|
249
|
-
try {
|
|
250
|
-
const axes = parseAxes(this.opts().axis);
|
|
251
|
-
const entries = Object.entries(axes);
|
|
252
|
-
const encoded = encodeURIComponent(family);
|
|
253
|
-
const path = entries.length > 0
|
|
254
|
-
? `/api/v1/cli/sl/family/${encoded}/resolve?axes=${encodeURIComponent(entries.map(([k, v]) => `${k}=${v}`).join(","))}`
|
|
255
|
-
: `/api/v1/cli/sl/family/${encoded}`;
|
|
256
|
-
console.log(JSON.stringify(await apiClient.get(path)));
|
|
257
|
-
}
|
|
258
|
-
catch (err) {
|
|
259
|
-
errorOutput(err);
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/sl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,gEAAgE;AAChE,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,sEAAsE;AACtE,sEAAsE;AACtE,gEAAgE;AAChE,EAAE;AACF,wEAAwE;AACxE,oEAAoE;AACpE,2EAA2E;AAC3E,yEAAyE;AAEzE,MAAM,KAAK,GAAG,CAAC,gBAAgB,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAE7D,MAAM,QAAQ,GACZ,uDAAuD,CAAC;AAC1D,MAAM,QAAQ,GACZ,wEAAwE,CAAC;AAE3E,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAE,KAA2B,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,WAAW,CACT,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EAAE,iBAAiB,IAAI,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC5D,CAAC,CACH,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,IAGxB;IACC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7B,WAAW,CACT,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,6DAA6D,EAAE,CAAC,CACzF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,0CAA0C,EAAE,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,IAAe,CAAC;IACjF,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAA2B;IAC5C,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACZ,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,IAAI,qBAAqB,EAAE,CAAC,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,MAAM,EAAE,GAAG,OAAO;SACf,OAAO,CAAC,IAAI,CAAC;SACb,WAAW,CACV,+EAA+E,CAChF,CAAC;IAEJ,4EAA4E;IAE5E,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,8BAA8B,CAAC,CAAC;IAEhF,MAAM;SACH,OAAO,CAAC,gBAAgB,CAAC;SACzB,WAAW,CACV,0EAA0E;QACxE,kDAAkD,CACrD;SACA,MAAM,CAAC,eAAe,EAAE,gCAAgC,CAAC;SACzD,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;SACnD,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;SAC7D,MAAM,CAAC,KAAK;QACX,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG;gBACX,UAAU,EAAE,eAAe,CAAC,IAAI,CAAC;gBACjC,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,IAAI;aACrC,CAAC;YACF,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,+BAA+B,EAAE,IAAI,CAAC,CAAC,CAC5E,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CACV,wEAAwE;QACtE,qEAAqE;QACrE,oCAAoC,CACvC;SACA,MAAM,CAAC,eAAe,EAAE,gCAAgC,CAAC;SACzD,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;SACnD,MAAM,CAAC,iBAAiB,EAAE,uCAAuC,CAAC;SAClE,MAAM,CACL,uBAAuB,EACvB,qDAAqD,CACtD;SACA,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;SAC7D,MAAM,CAAC,KAAK;QACX,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,KAAK,EAAE,CAA4B,CAAC;gBACjE,MAAM,OAAO,GAAG,CAAE,IAA8C,CAAC,OAAO;oBACtE,EAAE,CAA4B,CAAC;gBACjC,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC;gBAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAA4B,CAAC,CAAC;gBAC1D,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC;YAC1D,CAAC;YACD,MAAM,IAAI,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,kDAAkD,CAAC;SAC/D,cAAc,CAAC,eAAe,EAAE,mCAAmC,CAAC;SACpE,MAAM,CAAC,sBAAsB,EAAE,mBAAmB,CAAC;SACnD,MAAM,CAAC,uBAAuB,EAAE,wBAAwB,CAAC;SACzD,MAAM,CACL,kBAAkB,EAClB,sDAAsD,CACvD;SACA,MAAM,CAAC,KAAK;QACX,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,UAAU,GAA4B,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;YAChE,IAAI,IAAI,CAAC,WAAW;gBAAE,UAAU,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;YAChE,IAAI,IAAI,CAAC,UAAU;gBAAE,UAAU,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;YAC9D,IAAI,IAAI,CAAC,MAAM;gBAAE,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YACjD,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ,MAAM,SAAS,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,UAAU,EAAE,CAAC,CAC7D,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,4EAA4E;IAE5E,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC5B,WAAW,CACV,mEAAmE;QACjE,kEAAkE,CACrE;SACA,MAAM,CAAC,eAAe,EAAE,2BAA2B,CAAC;SACpD,MAAM,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;SAC9C,MAAM,CAAC,KAAK,WAA0B,IAAY,EAAE,IAAY;QAC/D,IAAI,CAAC;YACH,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACrD,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ,MAAM,SAAS,CAAC,GAAG,CACjB,kBAAkB,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,EACpD,IAAI,CACL,CACF,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,4EAA4E;IAE5E,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC5B,WAAW,CACV,oEAAoE;QAClE,oBAAoB,CACvB;SACA,cAAc,CAAC,OAAO,EAAE,kBAAkB,CAAC;SAC3C,MAAM,CAAC,KAAK,WAA0B,IAAY,EAAE,IAAY;QAC/D,IAAI,CAAC;YACH,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,MAAM,SAAS,CAAC,MAAM,CACpB,kBAAkB,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CACrD,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,4EAA4E;IAE5E,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC5B,WAAW,CACV,oEAAoE,CACrE;SACA,MAAM,CAAC,KAAK,WAA0B,IAAY,EAAE,IAAY;QAC/D,IAAI,CAAC;YACH,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ,MAAM,SAAS,CAAC,GAAG,CACjB,kBAAkB,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CACrD,CACF,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC5B,WAAW,CAAC,qCAAqC,CAAC;SAClD,MAAM,CAAC,KAAK,WAA0B,IAAY;QACjD,IAAI,CAAC;YACH,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CACV,uEAAuE;QACrE,4CAA4C,CAC/C;SACA,MAAM,CAAC,KAAK;QACX,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,QAAQ,CAAC,SAAS,EAAE,mCAAmC,CAAC;SACxD,WAAW,CAAC,+DAA+D,CAAC;SAC5E,MAAM,CAAC,aAAa,EAAE,8BAA8B,CAAC;SACrD,MAAM,CAAC,KAAK,WAA0B,KAAa;QAClD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAA2B,CAAC;YACzD,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3D,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,YAAY,QAAQ,8BAA8B,EAAE,CAAC,CAAC,CAAC;gBAC3F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ,MAAM,SAAS,CAAC,GAAG,CACjB,2BAA2B,kBAAkB,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAC/D,CACF,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,QAAQ,CAAC,QAAQ,EAAE,kDAAkD,CAAC;SACtE,WAAW,CACV,iEAAiE,CAClE;SACA,MAAM,CAAC,KAAK,WAA0B,IAAY;QACjD,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ,MAAM,SAAS,CAAC,GAAG,CAAC,yBAAyB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CACzE,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;SAC1C,WAAW,CACV,sEAAsE;QACpE,8DAA8D,CACjE;SACA,MAAM,CACL,uBAAuB,EACvB,iDAAiD,CAClD;SACA,MAAM,CAAC,KAAK,WAA0B,MAAc;QACnD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAA4B,CAAC,CAAC;YACjE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,IAAI,GACR,OAAO,CAAC,MAAM,GAAG,CAAC;gBAChB,CAAC,CAAC,yBAAyB,OAAO,iBAAiB,kBAAkB,CACjE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAC/C,EAAE;gBACL,CAAC,CAAC,yBAAyB,OAAO,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Parameterized Metrics
|
|
2
|
-
|
|
3
|
-
A parameterized metric is a template whose calculation contains `${PARAM:NAME}` tokens (dollar sign and curly braces). Each token maps to a named parameter with a list of values (a value name paired with the SQL fragment it substitutes in). The system auto-generates one validated child variant per combination of values - a ROAS template with REVENUE (9 values) and DN (4 values) produces 36 children.
|
|
4
|
-
|
|
5
|
-
## When to Parameterize
|
|
6
|
-
|
|
7
|
-
Parameterize when columns or formulas follow a variant pattern: `total_iap` / `total_iap_new_users` / `estimated_gross_iap` map to one REVENUE parameter; metrics that differ only by a WHERE window (D7, D30, D90) map to one DN parameter. Stay standalone when the metric has no natural variants, has only one or two (template overhead is not worth it), or when variants use fundamentally different formulas.
|
|
8
|
-
|
|
9
|
-
## Authoring a Template
|
|
10
|
-
|
|
11
|
-
Put `${PARAM:NAME}` tokens in the calculation, then pass the value map with `--parameters` (inline JSON array) or `--parameters-file <path>` on `graphit kb create metric` / `graphit kb update metric`. Run `graphit kb create metric --help` for the exact flag spelling.
|
|
12
|
-
|
|
13
|
-
```json
|
|
14
|
-
[
|
|
15
|
-
{
|
|
16
|
-
"name": "REVENUE",
|
|
17
|
-
"values": {"ALL_BOOKINGS": "total_iap", "NEW_BOOKINGS": "total_iap_new_users"},
|
|
18
|
-
"default_value": "ALL_BOOKINGS"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"name": "DN",
|
|
22
|
-
"values": {"D0": "", "D7": "WHERE day <= 7"},
|
|
23
|
-
"default_value": "D0"
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Paired with a calculation such as `SUM(${PARAM:REVENUE}) / SUM(cost) * 100 ${PARAM:DN}`.
|
|
29
|
-
|
|
30
|
-
| Rule | Detail |
|
|
31
|
-
|------|--------|
|
|
32
|
-
| Token match | Every `${PARAM:NAME}` token in the calculation needs a matching parameter by name |
|
|
33
|
-
| Empty values | Valid as no-ops (e.g. D0 adds no filter) |
|
|
34
|
-
| Variant cap | Max 1000 (the Cartesian product of all parameter values) |
|
|
35
|
-
| Child naming | Auto-generated as `{PARENT}_{VALUE1}_{VALUE2}` (e.g. ROAS_ALL_BOOKINGS_D7) |
|
|
36
|
-
| Validation | Template create skips per-formula validation (children validate on generation) |
|
|
37
|
-
|
|
38
|
-
## Editing a Template
|
|
39
|
-
|
|
40
|
-
All edits go through the parent template; children are read-only. Run a fresh `--parameters` array to change the value sets.
|
|
41
|
-
|
|
42
|
-
| User intent | Edit action |
|
|
43
|
-
|-------------|-------------|
|
|
44
|
-
| Change formula | Update `--sql` on the template - children re-generate |
|
|
45
|
-
| Add a variant (e.g. D120) | Update `--parameters` with the new value added to the relevant parameter |
|
|
46
|
-
| Remove variants | Update `--parameters` with values removed from the relevant parameter |
|
|
47
|
-
| Change description or topics | Update those fields on the template - no child re-generation |
|
|
48
|
-
|
|
49
|
-
If the user targets a child for edit or delete, redirect to the parent: "ROAS_ALL_BOOKINGS_D7 is a variant of ROAS. Edit the parent template ROAS instead."
|
|
50
|
-
|
|
51
|
-
## Using a Variant in a Query
|
|
52
|
-
|
|
53
|
-
You never substitute tokens by hand. The server resolves a variant when you reference it with the parameter syntax in SQL.
|
|
54
|
-
|
|
55
|
-
1. Find the template. `graphit kb list metric` shows the collapsed inventory - templates and flat metrics only, never child variants - with a `params` column (the required parameter names, e.g. `REVENUE, DN`) and a `variant_count`; an empty `params` cell means the metric is flat. To enumerate a template's concrete variants, `graphit kb explore metric NAME`; reach for `graphit kb list metric --include-variants` only when you truly need every child row flat.
|
|
56
|
-
2. Map the user's words to parameter values: "D7 ROAS for new users" maps to `REVENUE=NEW_BOOKINGS` and `DN=D7`.
|
|
57
|
-
3. Reference it with `{{metric:NAME(K=V)}}` in the query SQL, e.g. `{{metric:ROAS(REVENUE=NEW_BOOKINGS, DN=D7)}}`. The server expands it to the pre-validated child calculation at query time.
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
graphit query "SELECT {{dim:INSTALL_MONTH}}, {{metric:ROAS(REVENUE=NEW_BOOKINGS, DN=D7)}} AS roas FROM MARKETING_UA_DS GROUP BY 1" --ds MARKETING_UA_DS --verbose
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Defaults and errors:
|
|
64
|
-
- Omitting a parameter on a required metric returns a clear error naming the parameter and the valid values. Retry with a value or ask the user which one they meant.
|
|
65
|
-
- A pre-baked variant (ROAS_D7, ARPU_D30) has its value hardcoded in the name, so reference it plainly as `{{metric:ROAS_D7}}` with no parameter clause. Find its exact name via `graphit kb explore metric ROAS` (lists the variants) or `graphit kb list metric --include-variants` - the collapsed `kb list` does not show child variant names.
|
|
66
|
-
|
|
67
|
-
## Contrast: Wrong vs Right
|
|
68
|
-
|
|
69
|
-
| Wrong | Right |
|
|
70
|
-
|-------|-------|
|
|
71
|
-
| Replace `${PARAM:REVENUE}` with `total_iap` by hand and put that in the query SQL | Reference `{{metric:ROAS(REVENUE=ALL_BOOKINGS, DN=D7)}}` and let the server expand the validated child |
|
|
72
|
-
| Create ROAS_ALL_BOOKINGS and ROAS_NEW_BOOKINGS as separate standalone metrics | Create one ROAS template with a REVENUE parameter |
|
|
73
|
-
| Edit ROAS_ALL_BOOKINGS_D7 directly | Edit the parent ROAS template instead |
|
|
74
|
-
|
|
75
|
-
## Delete and Verify
|
|
76
|
-
|
|
77
|
-
Deleting the parent cascade-deletes every child; the blast radius includes all children plus their downstream references (graphs, rules, synonyms), so confirm before deleting. Verifying the parent sets `verified=true` on the parent and every child at once.
|