flipstream 0.6.1 → 0.7.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.
@@ -71,7 +71,11 @@ export default class Catalog extends BaseCommand {
71
71
  ], 'No sources.');
72
72
  // Footer to STDERR: it is guidance, not data, and stdout must stay clean.
73
73
  const hint = index.defaultSource === undefined ? '' : `, default ${index.defaultSource}`;
74
- this.footer(`\n${index.sources.length} source(s)${hint}; \`${this.config.bin} catalog ${index.defaultSource ?? '<source>'}\` for its names`);
74
+ // WHICH MODEL produced this (#125). Without it, a current catalog and a
75
+ // planner running a stale image read identically, and the only way to
76
+ // tell them apart is cloning two repos to compare pins.
77
+ const served = index.catalogVersion === undefined ? '' : `\ndata-model ${index.catalogVersion}`;
78
+ this.footer(`\n${index.sources.length} source(s)${hint}; \`${this.config.bin} catalog ${index.defaultSource ?? '<source>'}\` for its names${served}`);
75
79
  });
76
80
  }
77
81
  const entry = parseCatalogSource(payload);
@@ -96,6 +100,13 @@ export default class Catalog extends BaseCommand {
96
100
  if (entry.customDimensionsMax !== undefined) {
97
101
  this.log(`\nCUSTOM DIMENSIONS up to ${entry.customDimensionsMax} per connection`);
98
102
  }
103
+ // The same version line the index carries (#125), and UNCONDITIONAL — unlike
104
+ // the Try block below, which only appears when this source has both a
105
+ // dimension and a metric. This is the view people read while checking whether
106
+ // a name exists, which is exactly when "is this the model I think it is?"
107
+ // is the question.
108
+ if (entry.catalogVersion !== undefined)
109
+ this.footer(`\ndata-model ${entry.catalogVersion}`);
99
110
  // A runnable next command built from THIS source's real names (E11-3, #102):
100
111
  // the reader of a catalog is one edit away from a working query, so hand
101
112
  // them that edit. stderr — guidance, not data.
@@ -5,6 +5,7 @@ export interface CatalogItem {
5
5
  type: string;
6
6
  }
7
7
  export interface CatalogSource {
8
+ catalogVersion?: string;
8
9
  customDimensionsMax?: number;
9
10
  description: string;
10
11
  dimensions: CatalogItem[];
@@ -19,6 +20,7 @@ export interface CatalogSourceSummary {
19
20
  name: string;
20
21
  }
21
22
  export interface CatalogIndex {
23
+ catalogVersion?: string;
22
24
  defaultSource?: string;
23
25
  sources: CatalogSourceSummary[];
24
26
  }
@@ -18,6 +18,15 @@ function str(value, fallback = '') {
18
18
  function arr(value) {
19
19
  return Array.isArray(value) ? value : [];
20
20
  }
21
+ // The data-model release that produced this document (#125). data-model stamps
22
+ // it on every catalog — `catalogVersion` is required by its own schema and reads
23
+ // the package version through importlib.metadata, so it cannot drift from the
24
+ // tag query-planner pins. OPTIONAL here regardless: a planner older than the
25
+ // field simply omits it, and a missing version must print nothing rather than
26
+ // the word "undefined".
27
+ function version(record) {
28
+ return typeof record.catalogVersion === 'string' ? record.catalogVersion : undefined;
29
+ }
21
30
  function parseItem(value) {
22
31
  const record = asRecord(value) ?? {};
23
32
  // `format` may be absent or null; its `type` is what the human table shows.
@@ -42,7 +51,7 @@ export function parseCatalogIndex(payload) {
42
51
  };
43
52
  });
44
53
  const defaultSource = typeof record.defaultSource === 'string' ? record.defaultSource : undefined;
45
- return { defaultSource, sources };
54
+ return { catalogVersion: version(record), defaultSource, sources };
46
55
  }
47
56
  // GET /catalog/<source> — one source's full vocabulary.
48
57
  export function parseCatalogSource(payload) {
@@ -50,6 +59,7 @@ export function parseCatalogSource(payload) {
50
59
  const custom = asRecord(record.customDimensions);
51
60
  const max = custom !== undefined && typeof custom.max === 'number' ? custom.max : undefined;
52
61
  return {
62
+ catalogVersion: version(record),
53
63
  customDimensionsMax: max,
54
64
  description: str(record.description),
55
65
  dimensions: arr(record.dimensions).map((item) => parseItem(item)),
@@ -1445,5 +1445,5 @@
1445
1445
  ]
1446
1446
  }
1447
1447
  },
1448
- "version": "0.6.1"
1448
+ "version": "0.7.0"
1449
1449
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flipstream",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Flipstream CLI — query your Flipstream data from the terminal.",
5
5
  "keywords": [
6
6
  "flipstream",