@graphit/cli 0.2.248 → 0.2.252

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.
Files changed (37) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/bin/graphit +1 -1
  5. package/bin/graphit.ps1 +1 -1
  6. package/dist/api/client.d.ts +18 -0
  7. package/dist/api/client.js +12 -0
  8. package/dist/api/client.js.map +1 -1
  9. package/dist/commands/dashboard.js +32 -11
  10. package/dist/commands/dashboard.js.map +1 -1
  11. package/dist/commands/ds.js +21 -9
  12. package/dist/commands/ds.js.map +1 -1
  13. package/dist/commands/kb-create.js +2 -1
  14. package/dist/commands/kb-create.js.map +1 -1
  15. package/dist/commands/kb-delete.js +2 -1
  16. package/dist/commands/kb-delete.js.map +1 -1
  17. package/dist/commands/kb-read.js +6 -0
  18. package/dist/commands/kb-read.js.map +1 -1
  19. package/dist/commands/query.js +55 -6
  20. package/dist/commands/query.js.map +1 -1
  21. package/dist/commands/setup.js +3 -2
  22. package/dist/commands/setup.js.map +1 -1
  23. package/dist/output/format.d.ts +4 -0
  24. package/dist/output/format.js +24 -2
  25. package/dist/output/format.js.map +1 -1
  26. package/dist/stderr.d.ts +0 -12
  27. package/dist/stderr.js +24 -5
  28. package/dist/stderr.js.map +1 -1
  29. package/package.json +1 -1
  30. package/skills/graphit/SKILL.md +13 -12
  31. package/skills/graphit/VERSION.json +1 -1
  32. package/skills/graphit/references/data-sources.md +3 -4
  33. package/skills/graphit/references/filters-advanced.md +2 -3
  34. package/skills/graphit/references/filters.md +7 -7
  35. package/skills/graphit/references/kpi.md +3 -4
  36. package/skills/graphit/references/presentations.md +3 -6
  37. package/skills/graphit/references/runtime.md +2 -2
@@ -116,18 +116,17 @@ Check `graphit status` for those domains before proposing a create or a config c
116
116
 
117
117
  ## Presenting data source results
118
118
 
119
- The user cannot see the raw CLI output - you are the rendering layer. After `graphit ds list`, present a markdown table and end with a recommendation of which source to use (or note that none covers the needed table):
119
+ The user cannot see raw CLI output - you are the rendering layer. After `graphit ds list`, present a markdown table and end with a recommendation of which source to use (or note none covers the needed table):
120
120
 
121
121
  ~~~
122
- **3 data sources:**
122
+ **2 data sources:**
123
123
 
124
124
  | Name | ID | Rows | Status | Governed |
125
125
  |---|---|---:|---|---|
126
126
  | **MARKETING_UA_DS** | ds_abc123 | 1,247,832 | active | yes |
127
- | **PLAYER_QUALITY** | ds_def456 | 892,104 | active | no |
128
127
  | **REVENUE_EVENTS** | ds_ghi789 | 3,412,006 | stale | yes |
129
128
 
130
129
  Using **MARKETING_UA_DS** (ds_abc123), which covers spend, installs, and ROAS columns.
131
130
  ~~~
132
131
 
133
- Bold every data source name. If a source is stale, say so and offer to refresh it before querying.
132
+ Bold every data source name. If a source is stale, say so and offer to refresh it before querying. If `truncated` is true, raise `--limit` before recommending.
@@ -46,12 +46,11 @@ A `dateRange` registration persists to saved views exactly like a `filter`/`para
46
46
 
47
47
  Relative presets auto-recompute on reload (a saved "last_7_days" always means the last 7 days from today). The 11 preset ids - also available via `graphit.datePresets` (`[{id,label}]`) and `graphit.datePreset(id)` (`{start,end}`): today, yesterday, last_7_days, last_30_days, this_month, last_month, this_quarter, last_quarter, ytd, last_90_days, last_12_months.
48
48
 
49
- Bind a chart to the range with two scalar params and a `BETWEEN`:
49
+ Bind a chart to the range with two scalar params and a `BETWEEN`. The entity owns the query - its `data-graphit-sql` holds the `BETWEEN :start_date AND :end_date` template and the call passes only the values:
50
50
 
51
51
  ```js
52
+ // entity #rev: data-graphit-sql="SELECT day, SUM(rev) AS rev FROM orders WHERE day BETWEEN :start_date AND :end_date GROUP BY 1"
52
53
  graphit.bind('#rev', {
53
- sql: 'SELECT day, SUM(rev) AS rev FROM orders WHERE day BETWEEN :start_date AND :end_date GROUP BY 1',
54
- dataSourceId: 'ORDERS',
55
54
  params: () => ({ start_date: dr.start, end_date: dr.end }),
56
55
  deps: dr.deps,
57
56
  render: (r, el) => graphit.graph(el, { type: 'area', data: r.data, x: 'day', y: 'rev' }),
@@ -31,7 +31,7 @@ const country = graphit.filter('country', {
31
31
  Handle API:
32
32
  - `country.get()` - current value
33
33
  - `country.set(value)` - update value (triggers subscribers + bound re-resolves)
34
- - `country.subscribe(cb)` - called on change; returns unsubscribe fn
34
+ - `country.subscribe(cb)` - called immediately with the current value, then on every change; returns unsubscribe fn
35
35
 
36
36
  ## graphit.param(id, options)
37
37
 
@@ -45,14 +45,14 @@ const topN = graphit.param('top_n', { label: 'Top N', default: 10, options: [5,
45
45
 
46
46
  The registration renders nothing, so connect your own markup to the handle in three steps: set the element's initial value from `handle.get()`, call `handle.set(newValue)` in the change event, and pass `handle.subscribe(v => updateElement(v))` so the control restores its visual state on saved-view apply or page reload. The Complete Example below shows this end to end for a `<select>`.
47
47
 
48
+ `subscribe` fires the callback IMMEDIATELY at registration, then on every change, so init must be order-independent: a callback reaching a `const`/`let` declared further down throws at boot, and one uncaught throw kills the whole dashboard script - every chart spins forever with no error surfaced. Declare what the callback touches before you subscribe.
49
+
48
50
  ## graphit.bind(el, options) - Reactive Data Binding
49
51
 
50
- Connects a data entity to filter dependencies so it re-resolves automatically on change.
52
+ Connects a data entity to filter dependencies so it re-resolves automatically on change. The entity owns the query: `el` sits inside the `[data-graphit-id]` wrapper whose `data-graphit-sql` carries the `:name` placeholders, and the call supplies only the values (`runtime.md`).
51
53
 
52
54
  ```js
53
55
  graphit.bind(document.getElementById('revenue-chart'), {
54
- sql: 'SELECT date, SUM(revenue) AS revenue FROM orders WHERE country = :country GROUP BY 1',
55
- dataSourceId: 'ORDERS',
56
56
  params: () => ({ country: graphit.state.get('country') }),
57
57
  deps: ['country'], // state keys that trigger re-resolve (inferred from params if omitted)
58
58
  render: (result, el) => {
@@ -96,7 +96,9 @@ One control, wired to one reactive chart. The `<select>` is your own markup; `bi
96
96
  <option value="NA">North America</option>
97
97
  <option value="EU">Europe</option>
98
98
  </select>
99
- <div id="revenue-by-region"></div>
99
+ <div data-graphit-id="revenue-by-region" data-graphit-label="Revenue by Region"
100
+ data-graphit-sql="SELECT month, SUM(revenue) AS revenue FROM sales WHERE (:region = 'ALL' OR region = :region) GROUP BY 1 ORDER BY 1"
101
+ data-graphit-ds="SALES"></div>
100
102
 
101
103
  <script>
102
104
  const region = graphit.filter('region', { label: 'Region', field: 'REGION', default: 'ALL' });
@@ -107,8 +109,6 @@ One control, wired to one reactive chart. The `<select>` is your own markup; `bi
107
109
  region.subscribe(v => { sel.value = v; });
108
110
 
109
111
  graphit.bind(document.getElementById('revenue-by-region'), {
110
- sql: 'SELECT month, SUM(revenue) AS revenue FROM sales WHERE (:region = \'ALL\' OR region = :region) GROUP BY 1 ORDER BY 1',
111
- dataSourceId: 'SALES',
112
112
  params: () => ({ region: region.get() }),
113
113
  deps: ['region'],
114
114
  render: (result, el) => {
@@ -23,13 +23,14 @@ Fetch `compareValue` in the same resolve as the value (a prior-period column) or
23
23
 
24
24
  ## KPI Row: One Resolve, Several Cards
25
25
 
26
- The standard dashboard header - several KPI cards fed by ONE query (per the rate-limit budget in `runtime.md`). Put the loading overlay on the shared container and pass it as the single `target`; render each card with `graphit.kpi`; anchor provenance with `sourceEntityId` (first card) plus `targetEntityIds` (the rest) so every card's details panel shows the live query. Each card still carries its own complete, executable `data-graphit-sql`.
26
+ The standard dashboard header - several KPI cards fed by ONE query (per the rate-limit budget in `runtime.md`). One card OWNS the shared query: its `data-graphit-sql` is the combined statement the resolve runs, named by `sourceEntityId`. The other cards are `targetEntityIds` - each keeps its own complete, executable `data-graphit-sql` and gets the live query in its details panel. The resolve itself passes no `sql` and no `dataSourceId`; the entity contract in `runtime.md` holds here too, and passing both is the legacy shape that trips a `legacy_query_source` save warning (`migration.md`). Put the loading overlay on the shared container and pass it as the single `target` - with `sourceEntityId` set, `target` only carries the overlay, so it may wrap several entities.
27
27
 
28
28
  ```html
29
29
  <div id="kpi-row" class="gh-loading" style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px">
30
30
  <!-- gh-loading-overlay spinner from runtime.md First-paint section goes here -->
31
+ <!-- owner: its sql IS the shared query the resolve runs -->
31
32
  <div data-graphit-id="kpi-credits" data-graphit-label="Total Credits"
32
- data-graphit-sql="SELECT SUM(CREDIT_USED) AS v FROM CREDIT_USAGE_DS"
33
+ data-graphit-sql="SELECT SUM(CREDIT_USED) AS credits, COUNT(*) AS txns FROM CREDIT_USAGE_DS"
33
34
  data-graphit-ds="CREDIT_USAGE_DS">
34
35
  <div id="kpi-credits-card"></div>
35
36
  </div>
@@ -38,8 +39,6 @@ The standard dashboard header - several KPI cards fed by ONE query (per the rate
38
39
  <script>
39
40
  (async function () {
40
41
  var r = await graphit.resolve({
41
- sql: "SELECT SUM(CREDIT_USED) AS credits, COUNT(*) AS txns FROM CREDIT_USAGE_DS",
42
- dataSourceId: "CREDIT_USAGE_DS",
43
42
  target: "#kpi-row",
44
43
  sourceEntityId: "kpi-credits",
45
44
  targetEntityIds: ["kpi-txns", "kpi-success"]
@@ -89,12 +89,9 @@ deck.slide({
89
89
  // After deck.start(), fire resolve calls
90
90
  deck.start();
91
91
 
92
- graphit.resolve({
93
- sql: "SELECT MEDIA_SOURCE, SUM(APPSFLYER_COST) AS spend FROM MARKETING_UA_DS GROUP BY 1 ORDER BY spend DESC LIMIT 6",
94
- dataSourceId: "MARKETING_UA_DS",
95
- target: "#chart1"
96
- }).then(function(r) {
97
- graphit.graph("#chart1", { type: "bar", data: r.data, x: "MEDIA_SOURCE", y: "spend", valueFormat: "currency" });
92
+ // No sql/dataSourceId: target sits inside the entity, which owns the query
93
+ graphit.resolve({ target: "#chart1" }).then(function(r) {
94
+ graphit.graph("#chart1", { type: "bar", data: r.data, x: "source", y: "spend", valueFormat: "currency" });
98
95
  });
99
96
  ```
100
97
 
@@ -12,7 +12,7 @@ Consult when authoring dashboard HTML and wiring its data: fetching live data, m
12
12
 
13
13
  `graphit.resolve()` fetches live data from cached data sources on every page load. NEVER embed query results as static JS variables (`const data = [...]`) - that freezes a snapshot that never refreshes and breaks provenance.
14
14
 
15
- The entity owns the query. A resolve call passes no `sql` and no `dataSourceId`: both are read from the entity wrapper, authored once in the attributes and never repeated in the call.
15
+ The entity owns the query. A resolve call passes no `sql` and no `dataSourceId`: both are read from the entity - the wrapper around `target`, or the one named by `sourceEntityId` - authored once in the attributes and never repeated in the call.
16
16
 
17
17
  ```js
18
18
  const result = await graphit.resolve({
@@ -25,7 +25,7 @@ const result = await graphit.resolve({
25
25
  - `target` (CSS selector or element) does two jobs: locates the entity whose `data-graphit-sql` / `data-graphit-ds` this call runs, and shows a blur/spinner overlay while loading, removed on completion.
26
26
  - `params` (optional) supplies values for the `:name` placeholders in the entity's SQL.
27
27
  - `targetEntityIds` (optional, `string[]`) - `data-graphit-id`s of OTHER graphs this result also renders into, so each one's details panel reflects filters (not just `target`); entity ids, never CSS selectors.
28
- - `sourceEntityId` (optional) - the graph that owns a `target`-less resolve feeding several graphs (pair with `targetEntityIds`).
28
+ - `sourceEntityId` (optional) - the entity that owns the query when one result feeds several graphs; the SQL is read from IT, so `target` may be a plain container holding several entities and serves only the overlay (pair with `targetEntityIds`; canonical shape in `kpi.md`).
29
29
  - `maxRows` (optional) defaults to **10,000**, capped at **50,000**. Aggregate to a chartable grain well under the default; raise it only for a genuine row-level export, never above the cap.
30
30
  - `result.data` is an array of row objects you render however you want.
31
31