@toa.io/extensions.chronicles 1.0.0-alpha.332 → 1.0.0-alpha.333

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 (82) hide show
  1. package/LICENSE +22 -0
  2. package/components/chronicles.encounters/manifest.toa.yaml +108 -0
  3. package/components/{chronicles.ingestion → chronicles.encounters}/operations/anonymous.js +1 -1
  4. package/components/chronicles.encounters/operations/describe.js +4 -0
  5. package/components/{chronicles.ingestion → chronicles.encounters}/operations/identified.js +1 -1
  6. package/components/{chronicles.ingestion → chronicles.encounters}/types/toa.d.ts +13 -0
  7. package/components/chronicles.queries/manifest.toa.yaml +39 -15
  8. package/components/chronicles.queries/operations/define.js +1 -1
  9. package/components/chronicles.queries/types/toa.d.ts +8 -3
  10. package/components/{chronicles.facts → chronicles.relay}/manifest.toa.yaml +14 -3
  11. package/components/chronicles.relay/operations/encounter.js +4 -0
  12. package/components/{chronicles.facts → chronicles.relay}/operations/record.js +1 -1
  13. package/components/{chronicles.facts → chronicles.relay}/types/toa.d.ts +5 -0
  14. package/guides/clickhouse.md +19 -0
  15. package/guides/log.md +52 -0
  16. package/package.json +8 -4
  17. package/readme.md +459 -142
  18. package/store/clickhouse.scope.sql +29 -0
  19. package/store/clickhouse.sql +99 -0
  20. package/transpiled/Client.d.ts +19 -6
  21. package/transpiled/Client.js +89 -37
  22. package/transpiled/Client.js.map +1 -1
  23. package/transpiled/Factory.d.ts +13 -5
  24. package/transpiled/Factory.js +32 -23
  25. package/transpiled/Factory.js.map +1 -1
  26. package/transpiled/Provider.d.ts +76 -25
  27. package/transpiled/Provider.js.map +1 -1
  28. package/transpiled/Publisher.d.ts +50 -0
  29. package/transpiled/Publisher.js +169 -0
  30. package/transpiled/Publisher.js.map +1 -0
  31. package/transpiled/Reader.d.ts +15 -3
  32. package/transpiled/Reader.js +98 -14
  33. package/transpiled/Reader.js.map +1 -1
  34. package/transpiled/Recorder.d.ts +21 -11
  35. package/transpiled/Recorder.js +49 -24
  36. package/transpiled/Recorder.js.map +1 -1
  37. package/transpiled/Relay.d.ts +14 -0
  38. package/transpiled/Relay.js +27 -0
  39. package/transpiled/Relay.js.map +1 -0
  40. package/transpiled/Sender.d.ts +8 -4
  41. package/transpiled/Sender.js +27 -10
  42. package/transpiled/Sender.js.map +1 -1
  43. package/transpiled/Service.d.ts +26 -0
  44. package/transpiled/Service.js +70 -0
  45. package/transpiled/Service.js.map +1 -0
  46. package/transpiled/agent.d.ts +16 -0
  47. package/transpiled/agent.js +48 -0
  48. package/transpiled/agent.js.map +1 -0
  49. package/transpiled/clickhouse/Client.d.ts +5 -8
  50. package/transpiled/clickhouse/Client.js +12 -14
  51. package/transpiled/clickhouse/Client.js.map +1 -1
  52. package/transpiled/clickhouse/Provider.d.ts +20 -18
  53. package/transpiled/clickhouse/Provider.js +97 -72
  54. package/transpiled/clickhouse/Provider.js.map +1 -1
  55. package/transpiled/clickhouse/ddl.d.ts +3 -20
  56. package/transpiled/clickhouse/ddl.js +6 -79
  57. package/transpiled/clickhouse/ddl.js.map +1 -1
  58. package/transpiled/clickhouse/views.d.ts +11 -0
  59. package/transpiled/clickhouse/views.js +97 -0
  60. package/transpiled/clickhouse/views.js.map +1 -0
  61. package/transpiled/contract.d.ts +12 -0
  62. package/transpiled/contract.js +58 -0
  63. package/transpiled/contract.js.map +1 -0
  64. package/transpiled/index.d.ts +9 -3
  65. package/transpiled/settings.d.ts +6 -4
  66. package/transpiled/settings.js +27 -14
  67. package/transpiled/settings.js.map +1 -1
  68. package/transpiled/store.d.ts +3 -3
  69. package/transpiled/store.js +3 -3
  70. package/transpiled/store.js.map +1 -1
  71. package/components/chronicles.ingestion/manifest.toa.yaml +0 -60
  72. package/transpiled/Facts.d.ts +0 -9
  73. package/transpiled/Facts.js +0 -16
  74. package/transpiled/Facts.js.map +0 -1
  75. package/transpiled/Scribe.d.ts +0 -25
  76. package/transpiled/Scribe.js +0 -61
  77. package/transpiled/Scribe.js.map +0 -1
  78. package/transpiled/Writer.d.ts +0 -14
  79. package/transpiled/Writer.js +0 -50
  80. package/transpiled/Writer.js.map +0 -1
  81. /package/components/{chronicles.facts → chronicles.encounters}/types/index.d.ts +0 -0
  82. /package/components/{chronicles.ingestion → chronicles.relay}/types/index.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Client.js","sourceRoot":"","sources":["../../source/clickhouse/Client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Client.js","sourceRoot":"","sources":["../../source/clickhouse/Client.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,26 @@
1
- import type { Label, Provider, Result, Row, State, Summary, View } from '../Provider.ts';
2
- import type { Credentials } from '../settings.ts';
1
+ import type { Definition, Encountered, Field, Label, Provider, Result, Summary, View } from '../Provider.ts';
2
+ import type { User } from '../settings.ts';
3
+ import type { Property } from '@toa.io/definitions/extensions.chronicles';
3
4
  /**
4
- * The log in ClickHouse: `events`, replaced by `id`, and `states`, by the `version` of an entity, both
5
- * read with `FINAL`. Queries run as `<database>_reader`, which provisioning creates with limits it
6
- * cannot lift; views are made by the writer from what the reader was let plan.
5
+ * The log in ClickHouse, read as the context's user of it: `events`, `states` and `encounters` in
6
+ * the user's default database, which the store lets it read the rows of its scope of, under limits
7
+ * of its own. A query is asked to be read-only besides; only a view is created, in the database
8
+ * named after the scope, where the store lets the user create one.
9
+ *
10
+ * A view says what it is in its comment, as JSON: the `title` and the `description` it was defined
11
+ * with.
7
12
  */
8
13
  export declare class ClickHouseProvider implements Provider {
9
- readonly dialect = "ClickHouse SQL; read `events` and `states` with FINAL";
14
+ readonly guide: string;
10
15
  readonly tables: string[];
11
- private readonly writer;
12
- private readonly reader;
13
- private readonly password;
14
- private readonly retention;
15
- constructor(url: string, credentials: Credentials, retention?: number);
16
- provision(): Promise<void>;
17
- write(rows: Row[], states: State[]): Promise<void>;
16
+ private readonly user;
17
+ private readonly scope;
18
+ /** `scope` is the context's, which its views are kept under */
19
+ constructor(url: string, user: User, scope: string);
20
+ fields(properties: Record<string, Property>): Field[];
18
21
  states(): Promise<Summary[]>;
19
22
  labels(): Promise<Label[]>;
23
+ encounters(): Promise<Encountered[]>;
20
24
  /**
21
25
  * One row more than is answered, cut by the `limit` setting — the result's own, outside whatever
22
26
  * the statement says — so a result of the limit exactly reads as whole, and one past it as cut.
@@ -24,10 +28,8 @@ export declare class ClickHouseProvider implements Provider {
24
28
  query(sql: string): Promise<Result>;
25
29
  validate(sql: string): Promise<void>;
26
30
  views(): Promise<View[]>;
27
- define(name: string, sql: string, refresh?: number): Promise<void>;
31
+ define(definition: Definition): Promise<void>;
28
32
  drop(name: string): Promise<void>;
29
- private insert;
30
- /** In order, each awaited: a view is made after the table it reads. */
31
- private run;
32
- private engine;
33
+ private view;
34
+ private read;
33
35
  }
@@ -1,118 +1,136 @@
1
- import { console } from 'openspan';
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
2
3
  import { ClickHouse, ClickHouseError } from './Client.js';
3
4
  import * as ddl from './ddl.js';
5
+ import * as views from './views.js';
4
6
  import { Refusal } from '../Provider.js';
5
7
  /**
6
- * The log in ClickHouse: `events`, replaced by `id`, and `states`, by the `version` of an entity, both
7
- * read with `FINAL`. Queries run as `<database>_reader`, which provisioning creates with limits it
8
- * cannot lift; views are made by the writer from what the reader was let plan.
8
+ * The log in ClickHouse, read as the context's user of it: `events`, `states` and `encounters` in
9
+ * the user's default database, which the store lets it read the rows of its scope of, under limits
10
+ * of its own. A query is asked to be read-only besides; only a view is created, in the database
11
+ * named after the scope, where the store lets the user create one.
12
+ *
13
+ * A view says what it is in its comment, as JSON: the `title` and the `description` it was defined
14
+ * with.
9
15
  */
10
16
  export class ClickHouseProvider {
11
- dialect = 'ClickHouse SQL; read `events` and `states` with FINAL';
17
+ guide = GUIDE;
12
18
  tables = ddl.TABLES;
13
- writer;
14
- reader;
15
- password;
16
- retention;
17
- constructor(url, credentials, retention) {
18
- this.writer = new ClickHouse(url, credentials.username, credentials.password);
19
- this.reader = new ClickHouse(url, `${this.writer.database}_reader`, credentials.reader);
20
- this.password = credentials.reader;
21
- this.retention = retention;
22
- }
23
- async provision() {
24
- const { database } = this.writer;
25
- for (const statement of ddl.database(database))
26
- await this.writer.run(statement, {}, '');
27
- await this.run(ddl.tables(this.retention));
28
- await this.run(ddl.retention(this.retention, await this.engine()));
29
- await this.run(ddl.reader(database, this.password));
30
- console.info('Chronicles provisioned', { database });
31
- }
32
- async write(rows, states) {
33
- if (rows.length > 0)
34
- await this.insert('events', EVENTS, rows);
35
- if (states.length > 0)
36
- await this.insert('states', STATES, states);
19
+ user;
20
+ scope;
21
+ /** `scope` is the context's, which its views are kept under */
22
+ constructor(url, user, scope) {
23
+ this.user = new ClickHouse(url, user.username, user.password);
24
+ this.scope = scope;
25
+ }
26
+ fields(properties) {
27
+ return views.fields(properties);
37
28
  }
38
29
  async states() {
39
- return await this.writer.rows(`SELECT component, uniqExact(entity) AS entities,
40
- arraySort(groupUniqArrayArray(JSONAllPaths(payload))) AS paths
30
+ return await this.read(`SELECT component, uniqExact(entity) AS entities, toString(max(time)) AS last
41
31
  FROM states GROUP BY component ORDER BY component`);
42
32
  }
43
33
  async labels() {
44
- const labels = await this.writer.rows(`SELECT label, count() AS rows, toString(min(time)) AS first, toString(max(time)) AS last
34
+ return await this.read(`SELECT label, count() AS rows, toString(min(time)) AS first, toString(max(time)) AS last
45
35
  FROM events GROUP BY label ORDER BY label`);
46
- // the fields of the latest payloads of each label, which is what a query is written against
47
- const paths = await this.writer.rows(`SELECT label, arraySort(groupUniqArrayArray(JSONAllPaths(payload))) AS paths
48
- FROM (SELECT label, payload FROM events ORDER BY time DESC LIMIT ${SAMPLE} BY label)
49
- GROUP BY label`);
50
- const byLabel = new Map(paths.map(({ label, paths }) => [label, paths]));
51
- return labels.map((label) => ({ ...label, paths: byLabel.get(label.label) ?? [] }));
36
+ }
37
+ async encounters() {
38
+ const names = await this.read(`SELECT name, count() AS rows, toString(min(time)) AS first, toString(max(time)) AS last,
39
+ toString(max(received)) AS received
40
+ FROM encounters GROUP BY name ORDER BY name`);
41
+ // the fields of the latest payloads of each name, as they were sent: two types of one path
42
+ // are two clients that disagree
43
+ const fields = await this.read(`SELECT name, path, arraySort(groupUniqArray(type)) AS types
44
+ FROM (
45
+ SELECT name, typed.1 AS path, typed.2 AS type
46
+ FROM (SELECT name, payload FROM encounters ORDER BY received DESC LIMIT ${SAMPLE} BY name)
47
+ ARRAY JOIN arrayZip(
48
+ mapKeys(JSONAllPathsWithTypes(payload)),
49
+ mapValues(JSONAllPathsWithTypes(payload))
50
+ ) AS typed
51
+ )
52
+ GROUP BY name, path ORDER BY name, path`);
53
+ return names.map((encountered) => ({
54
+ ...encountered,
55
+ fields: fields
56
+ .filter(({ name }) => name === encountered.name)
57
+ .map(({ path, types }) => ({ path, types }))
58
+ }));
52
59
  }
53
60
  /**
54
61
  * One row more than is answered, cut by the `limit` setting — the result's own, outside whatever
55
62
  * the statement says — so a result of the limit exactly reads as whole, and one past it as cut.
56
63
  */
57
64
  async query(sql) {
58
- const settings = { ...NUMBERS, limit: String(ddl.LIMITS.rows + 1) };
59
- const answer = await refusing(async () => await this.reader.select(sql, settings));
65
+ const settings = { ...READONLY, ...NUMBERS, limit: String(ddl.LIMITS.rows + 1) };
66
+ const answer = await refusing(async () => await this.user.select(sql, settings));
60
67
  return {
61
68
  columns: answer.meta,
62
69
  rows: answer.data.slice(0, ddl.LIMITS.rows),
63
70
  truncated: answer.data.length > ddl.LIMITS.rows
64
71
  };
65
72
  }
66
- // parsed and planned as the reader, which is what refuses a view that reads what a query
67
- // could not
73
+ // parsed and planned as the user, which is what refuses a view that reads what a query could not
68
74
  async validate(sql) {
69
75
  await refusing(async () => {
70
- const [ast] = await this.reader.rows(`EXPLAIN AST ${sql}`);
76
+ const [ast] = await this.read(`EXPLAIN AST ${sql}`);
71
77
  if (!ast.explain.startsWith('SelectWithUnionQuery'))
72
78
  throw new Refusal('A view is one SELECT');
73
- await this.reader.run(`EXPLAIN PLAN ${sql}`);
79
+ await this.user.run(`EXPLAIN PLAN ${sql}`, READONLY);
74
80
  });
75
81
  }
76
82
  async views() {
77
- const tables = await this.writer.rows(`SELECT name, as_select, create_table_query FROM system.tables
78
- WHERE database = currentDatabase()
79
- AND name NOT IN (${this.tables.map(ddl.literal).join(', ')})
80
- AND NOT startsWith(name, '.inner')
83
+ const tables = await this.read(`SELECT name, as_select, create_table_query, comment FROM system.tables
84
+ WHERE database = ${ddl.literal(this.scope)} AND NOT startsWith(name, '.inner')
81
85
  ORDER BY name`);
86
+ const refreshes = await this.read(`SELECT view, toString(last_success_time) AS refreshed FROM system.view_refreshes
87
+ WHERE database = ${ddl.literal(this.scope)} AND last_success_time IS NOT NULL`);
88
+ const refreshed = new Map(refreshes.map(({ view, refreshed }) => [view, refreshed]));
82
89
  return tables.map((table) => {
83
- const view = { name: table.name, sql: table.as_select };
90
+ const { title, description } = said(table.comment);
91
+ const view = {
92
+ name: table.name,
93
+ read: `${ddl.id(this.scope)}.${ddl.id(table.name)}`,
94
+ sql: table.as_select
95
+ };
96
+ if (title !== undefined)
97
+ view.title = title;
98
+ if (description !== undefined)
99
+ view.description = description;
84
100
  // stated in seconds, and kept in the largest unit that divides them
85
101
  const every = /REFRESH EVERY (\d+) (SECOND|MINUTE|HOUR|DAY|WEEK)/.exec(table.create_table_query);
86
- if (every !== null)
102
+ if (every !== null) {
87
103
  view.refresh = Number(every[1]) * UNITS[every[2]];
104
+ const at = refreshed.get(table.name);
105
+ if (at !== undefined)
106
+ view.refreshed = at;
107
+ }
88
108
  return view;
89
109
  });
90
110
  }
91
- async define(name, sql, refresh) {
92
- await this.writer.run(`DROP TABLE IF EXISTS ${ddl.id(name)} SYNC`);
111
+ // the comment is on a line of its own: a statement that ends in a comment of its own would
112
+ // take it in otherwise
113
+ async define(definition) {
114
+ const { name, sql, refresh, title, description } = definition;
115
+ const comment = ddl.literal(JSON.stringify({ title, description }));
116
+ const view = this.view(name);
93
117
  await refusing(async () => {
118
+ await this.user.run(`DROP TABLE IF EXISTS ${view} SYNC`);
94
119
  if (refresh === undefined)
95
- await this.writer.run(`CREATE VIEW ${ddl.id(name)} SQL SECURITY INVOKER AS ${sql}`);
120
+ await this.user.run(`CREATE VIEW ${view} SQL SECURITY INVOKER AS ${sql}\nCOMMENT ${comment}`);
96
121
  else
97
- await this.writer.run(`CREATE MATERIALIZED VIEW ${ddl.id(name)} REFRESH EVERY ${refresh} SECOND
98
- ENGINE = MergeTree ORDER BY tuple() AS ${sql}`);
122
+ await this.user.run(`CREATE MATERIALIZED VIEW ${view} REFRESH EVERY ${refresh} SECOND
123
+ ENGINE = MergeTree ORDER BY tuple() AS ${sql}\nCOMMENT ${comment}`);
99
124
  });
100
125
  }
101
126
  async drop(name) {
102
- await this.writer.run(`DROP TABLE IF EXISTS ${ddl.id(name)} SYNC`);
103
- }
104
- async insert(table, columns, rows) {
105
- const lines = rows.map((row) => JSON.stringify({ ...row, time: timestamp(row.time) }));
106
- await this.writer.run(`INSERT INTO ${table} (${columns}) FORMAT JSONEachRow\n${lines.join('\n')}`);
127
+ await refusing(async () => await this.user.run(`DROP TABLE IF EXISTS ${this.view(name)} SYNC`));
107
128
  }
108
- /** In order, each awaited: a view is made after the table it reads. */
109
- async run(statements) {
110
- for (const statement of statements)
111
- await this.writer.run(statement);
129
+ view(name) {
130
+ return `${ddl.id(this.scope)}.${ddl.id(name)}`;
112
131
  }
113
- async engine() {
114
- const [table] = await this.writer.rows("SELECT engine_full FROM system.tables WHERE database = currentDatabase() AND name = 'events'");
115
- return table?.engine_full ?? '';
132
+ async read(sql) {
133
+ return await this.user.rows(sql, READONLY);
116
134
  }
117
135
  }
118
136
  /** What ClickHouse refused is the provider's refusal, in ClickHouse's words. */
@@ -126,12 +144,16 @@ async function refusing(fn) {
126
144
  throw exception;
127
145
  }
128
146
  }
129
- /** A `DateTime64(3)` as ClickHouse reads one without guessing: UTC, to the millisecond. */
130
- function timestamp(ms) {
131
- return new Date(ms).toISOString().replace('T', ' ').replace('Z', '');
147
+ /** What a view's comment says of it; nothing, of one made otherwise. */
148
+ function said(comment) {
149
+ try {
150
+ const parsed = JSON.parse(comment);
151
+ return typeof parsed === 'object' && parsed !== null ? parsed : {};
152
+ }
153
+ catch {
154
+ return {};
155
+ }
132
156
  }
133
- const EVENTS = 'id, label, component, time, entity, version, identity, ip, country, trace, payload';
134
- const STATES = 'component, entity, version, identity, time, payload';
135
157
  const UNITS = {
136
158
  SECOND: 1,
137
159
  MINUTE: 60,
@@ -140,5 +162,8 @@ const UNITS = {
140
162
  WEEK: 604800
141
163
  };
142
164
  const SAMPLE = 1000;
165
+ const GUIDE = readFileSync(resolve(import.meta.dirname, '../../guides/clickhouse.md'), 'utf8');
143
166
  const NUMBERS = { output_format_json_quote_64bit_integers: '0' };
167
+ /** what a request asks besides its user's rights: to change nothing */
168
+ const READONLY = { readonly: '1' };
144
169
  //# sourceMappingURL=Provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../source/clickhouse/Provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../source/clickhouse/Provider.ts"],"names":[],"mappings":"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"}
@@ -1,26 +1,9 @@
1
- /**
2
- * The log in ClickHouse. Every statement is one a second start changes nothing with, so two
3
- * replicas starting together collide on nothing; the retention, which would change, is compared
4
- * with what is there and changed only where it differs.
5
- */
1
+ /** The log's tables, which a view is not named after. */
6
2
  export declare const TABLES: string[];
7
- export declare function database(name: string): string[];
8
- /** What is kept: a row for everything that happened, and each entity as it stands. */
9
- export declare function tables(retention: number | undefined): string[];
10
- /** `ALTER TABLE` for the retention declared, given what the table states now; none if it agrees. */
11
- export declare function retention(declared: number | undefined, engine: string): string[];
12
- /**
13
- * The user queries run as: it reads the database and nothing else, under limits a query cannot
14
- * lift, because they are constraints of its profile rather than settings a request passes. Past
15
- * the rows a query is refused, which is the overflow a client's query cache allows; a query of
16
- * the provider's own asks for one row more than it answers, to tell a full answer from a cut one.
17
- */
18
- export declare function reader(database: string, password: string): string[];
3
+ /** What a query answers at most, which the provider cuts a result at to tell it is cut. */
19
4
  export declare const LIMITS: {
20
- seconds: number;
21
5
  rows: number;
22
- memory: number;
23
6
  };
24
- /** An identifier, which the annotation and the schema have already held to this. */
7
+ /** An identifier, quoted: a scope, which may have hyphens, or a name held to letters and digits. */
25
8
  export declare function id(name: string): string;
26
9
  export declare function literal(value: string): string;
@@ -1,78 +1,8 @@
1
- /**
2
- * The log in ClickHouse. Every statement is one a second start changes nothing with, so two
3
- * replicas starting together collide on nothing; the retention, which would change, is compared
4
- * with what is there and changed only where it differs.
5
- */
6
- export const TABLES = ['events', 'states'];
7
- export function database(name) {
8
- return [`CREATE DATABASE IF NOT EXISTS ${id(name)}`];
9
- }
10
- /** What is kept: a row for everything that happened, and each entity as it stands. */
11
- export function tables(retention) {
12
- return [
13
- `CREATE TABLE IF NOT EXISTS events (
14
- id String,
15
- label LowCardinality(String),
16
- component LowCardinality(String),
17
- time DateTime64(3, 'UTC'),
18
- received DateTime64(3, 'UTC') DEFAULT now64(3),
19
- entity Nullable(String),
20
- version Nullable(UInt64),
21
- identity Nullable(String),
22
- ip Nullable(String),
23
- country LowCardinality(Nullable(String)),
24
- trace Nullable(String),
25
- payload JSON
26
- ) ENGINE = ReplacingMergeTree
27
- PARTITION BY toYYYYMM(time)
28
- ORDER BY (label, toDate(time), id)
29
- ${retention === undefined ? '' : ttl(retention)}`,
30
- `CREATE TABLE IF NOT EXISTS states (
31
- component LowCardinality(String),
32
- entity String,
33
- version UInt64,
34
- identity Nullable(String),
35
- time DateTime64(3, 'UTC'),
36
- received DateTime64(3, 'UTC') DEFAULT now64(3),
37
- payload JSON
38
- ) ENGINE = ReplacingMergeTree(version)
39
- ORDER BY (component, entity)`
40
- ];
41
- }
42
- /** `ALTER TABLE` for the retention declared, given what the table states now; none if it agrees. */
43
- export function retention(declared, engine) {
44
- const stated = /TTL toDateTime\(time\) \+ toIntervalDay\((\d+)\)/.exec(engine)?.[1];
45
- if (declared === undefined)
46
- return stated === undefined && !engine.includes(' TTL ')
47
- ? []
48
- : ['ALTER TABLE events REMOVE TTL'];
49
- if (stated === String(declared))
50
- return [];
51
- return [`ALTER TABLE events MODIFY ${ttl(declared)}`];
52
- }
53
- /**
54
- * The user queries run as: it reads the database and nothing else, under limits a query cannot
55
- * lift, because they are constraints of its profile rather than settings a request passes. Past
56
- * the rows a query is refused, which is the overflow a client's query cache allows; a query of
57
- * the provider's own asks for one row more than it answers, to tell a full answer from a cut one.
58
- */
59
- export function reader(database, password) {
60
- const name = id(`${database}_reader`);
61
- return [
62
- `CREATE SETTINGS PROFILE IF NOT EXISTS ${name}`,
63
- `ALTER SETTINGS PROFILE ${name} SETTINGS
64
- readonly = 2 CONST,
65
- max_execution_time = ${LIMITS.seconds} CONST,
66
- max_result_rows = ${LIMITS.rows + 1} CONST,
67
- max_memory_usage = ${LIMITS.memory} CONST`,
68
- `CREATE USER IF NOT EXISTS ${name} IDENTIFIED WITH sha256_password BY ${literal(password)}`,
69
- `ALTER USER ${name} IDENTIFIED WITH sha256_password BY ${literal(password)}
70
- SETTINGS PROFILE ${literal(`${database}_reader`)}`,
71
- `GRANT SELECT ON ${id(database)}.* TO ${name}`
72
- ];
73
- }
74
- export const LIMITS = { seconds: 30, rows: 10_000, memory: 4_000_000_000 };
75
- /** An identifier, which the annotation and the schema have already held to this. */
1
+ /** The log's tables, which a view is not named after. */
2
+ export const TABLES = ['events', 'states', 'encounters'];
3
+ /** What a query answers at most, which the provider cuts a result at to tell it is cut. */
4
+ export const LIMITS = { rows: 10_000 };
5
+ /** An identifier, quoted: a scope, which may have hyphens, or a name held to letters and digits. */
76
6
  export function id(name) {
77
7
  if (!IDENTIFIER.test(name))
78
8
  throw new Error(`'${name}' is not a ClickHouse identifier chronicles accept`);
@@ -81,8 +11,5 @@ export function id(name) {
81
11
  export function literal(value) {
82
12
  return "'" + value.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'";
83
13
  }
84
- function ttl(days) {
85
- return `TTL toDateTime(time) + INTERVAL ${days} DAY`;
86
- }
87
- const IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
14
+ const IDENTIFIER = /^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/;
88
15
  //# sourceMappingURL=ddl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ddl.js","sourceRoot":"","sources":["../../source/clickhouse/ddl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;AAE1C,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,CAAC,iCAAiC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACtD,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,MAAM,CAAC,SAA6B;IAClD,OAAO;QACL;;;;;;;;;;;;;;;;MAgBE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;QAEjD;;;;;;;;;iCAS6B;KAC9B,CAAA;AACH,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,SAAS,CAAC,QAA4B,EAAE,MAAc;IACpE,MAAM,MAAM,GAAG,kDAAkD,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAEnF,IAAI,QAAQ,KAAK,SAAS;QACxB,OAAO,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;YACtD,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAA;IAEvC,IAAI,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAA;IAE1C,OAAO,CAAC,6BAA6B,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,QAAgB,EAAE,QAAgB;IACvD,MAAM,IAAI,GAAG,EAAE,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAA;IAErC,OAAO;QACL,yCAAyC,IAAI,EAAE;QAC/C,0BAA0B,IAAI;;6BAEL,MAAM,CAAC,OAAO;0BACjB,MAAM,CAAC,IAAI,GAAG,CAAC;2BACd,MAAM,CAAC,MAAM,QAAQ;QAC5C,6BAA6B,IAAI,uCAAuC,OAAO,CAAC,QAAQ,CAAC,EAAE;QAC3F,cAAc,IAAI,uCAAuC,OAAO,CAAC,QAAQ,CAAC;yBACrD,OAAO,CAAC,GAAG,QAAQ,SAAS,CAAC,EAAE;QACpD,mBAAmB,EAAE,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE;KAC/C,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;AAE1E,oFAAoF;AACpF,MAAM,UAAU,EAAE,CAAC,IAAY;IAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,oDAAoD,CAAC,CAAA;IAE/E,OAAO,GAAG,GAAG,IAAI,GAAG,GAAG,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,GAAG,CAAA;AACtE,CAAC;AAED,SAAS,GAAG,CAAC,IAAY;IACvB,OAAO,mCAAmC,IAAI,MAAM,CAAA;AACtD,CAAC;AAED,MAAM,UAAU,GAAG,0BAA0B,CAAA"}
1
+ {"version":3,"file":"ddl.js","sourceRoot":"","sources":["../../source/clickhouse/ddl.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;AAExD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AAEtC,oGAAoG;AACpG,MAAM,UAAU,EAAE,CAAC,IAAY;IAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,oDAAoD,CAAC,CAAA;IAE/E,OAAO,GAAG,GAAG,IAAI,GAAG,GAAG,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,GAAG,CAAA;AACtE,CAAC;AAED,MAAM,UAAU,GAAG,8BAA8B,CAAA"}
@@ -0,0 +1,11 @@
1
+ import type { Property } from '@toa.io/definitions/extensions.chronicles';
2
+ import type { Field } from '../Provider.ts';
3
+ /**
4
+ * How a declared property is read from the payload in its type, by `JSONExtract`, which reads what
5
+ * is not of the type as `NULL` rather than failing the query — a row written under an earlier
6
+ * contract is read by the one there is now.
7
+ */
8
+ /** The fields of a contract, at every depth, each with the type its column reads it as. */
9
+ export declare function fields(properties: Record<string, Property>, prefix?: string): Field[];
10
+ /** What a property reads as, `NULL` aside. */
11
+ export declare function type(property: Property): string;
@@ -0,0 +1,97 @@
1
+ import { id, literal } from './ddl.js';
2
+ /**
3
+ * How a declared property is read from the payload in its type, by `JSONExtract`, which reads what
4
+ * is not of the type as `NULL` rather than failing the query — a row written under an earlier
5
+ * contract is read by the one there is now.
6
+ */
7
+ /** The fields of a contract, at every depth, each with the type its column reads it as. */
8
+ export function fields(properties, prefix = '') {
9
+ const found = [];
10
+ for (const [name, property] of Object.entries(properties)) {
11
+ if (empty(property))
12
+ continue;
13
+ const path = prefix === '' ? name : `${prefix}.${name}`;
14
+ const field = { path, type: type(property), description: property.description };
15
+ // a property of a property is read inside the one that holds it
16
+ if (prefix === '')
17
+ field.read = extract(name, property);
18
+ found.push(field);
19
+ const nested = property.type === 'array' ? property.items : property;
20
+ if (nested.type === 'object')
21
+ found.push(...fields(nested.properties, path));
22
+ }
23
+ return found;
24
+ }
25
+ /** What a property reads as, `NULL` aside. */
26
+ export function type(property) {
27
+ switch (property.type) {
28
+ case 'object':
29
+ return `Tuple(${members(property, type)})`;
30
+ case 'array':
31
+ return `Array(${type(property.items)})`;
32
+ default:
33
+ return scalar(property);
34
+ }
35
+ }
36
+ /** The column of a property: a value of the type, or `NULL` where it was not one. */
37
+ function column(property) {
38
+ switch (property.type) {
39
+ case 'object':
40
+ return `Tuple(${members(property, column)})`;
41
+ case 'array':
42
+ return `Array(${column(property.items)})`;
43
+ default:
44
+ return property.enum === undefined
45
+ ? `Nullable(${scalar(property)})`
46
+ : 'LowCardinality(Nullable(String))';
47
+ }
48
+ }
49
+ function scalar(property) {
50
+ if (property.enum !== undefined)
51
+ return 'LowCardinality(String)';
52
+ const formatted = property.format === undefined ? undefined : FORMATS[property.format];
53
+ return formatted?.type === property.type ? formatted.as : SCALARS[property.type];
54
+ }
55
+ function members(property, of) {
56
+ return Object.entries(property.properties)
57
+ .filter(([, nested]) => !empty(nested))
58
+ .map(([name, nested]) => `${name} ${of(nested)}`)
59
+ .join(', ');
60
+ }
61
+ /**
62
+ * An object is read from the JSON of its paths, which is an object however few of them a row has;
63
+ * anything else from the JSON of its value, which is `null` where a row has none.
64
+ */
65
+ function extract(name, property) {
66
+ const json = property.type === 'object'
67
+ ? `toJSONString(payload.^${id(name)})`
68
+ : `ifNull(toJSONString(payload.${id(name)}), 'null')`;
69
+ return `JSONExtract(${json}, ${literal(column(property))})`;
70
+ }
71
+ /** An object of no properties is no column: a tuple of nothing is no type. */
72
+ function empty(property) {
73
+ const nested = property.type === 'array' ? property.items : property;
74
+ return (nested.type === 'object' &&
75
+ Object.values(nested.properties ?? {}).every((member) => empty(member)));
76
+ }
77
+ const SCALARS = {
78
+ string: 'String',
79
+ integer: 'Int64',
80
+ number: 'Float64',
81
+ boolean: 'Bool'
82
+ };
83
+ const FORMATS = {
84
+ 'date-time': { type: 'string', as: "DateTime64(3, 'UTC')" },
85
+ 'iso-date-time': { type: 'string', as: "DateTime64(3, 'UTC')" },
86
+ date: { type: 'string', as: 'Date32' },
87
+ time: { type: 'string', as: 'Time64(3)' },
88
+ 'iso-time': { type: 'string', as: 'Time64(3)' },
89
+ uuid: { type: 'string', as: 'UUID' },
90
+ ipv4: { type: 'string', as: 'IPv4' },
91
+ ipv6: { type: 'string', as: 'IPv6' },
92
+ int32: { type: 'integer', as: 'Int32' },
93
+ int64: { type: 'integer', as: 'Int64' },
94
+ float: { type: 'number', as: 'Float32' },
95
+ double: { type: 'number', as: 'Float64' }
96
+ };
97
+ //# sourceMappingURL=views.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"views.js","sourceRoot":"","sources":["../../source/clickhouse/views.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Property } from '@toa.io/definitions/extensions.chronicles';
2
+ /**
3
+ * What of a payload is written: the declared properties, at every depth, and nothing else. A
4
+ * value that is not of its declared type is a payload the contract does not admit, which throws a
5
+ * `Mismatch` naming where; `null` is admitted for any property, and an absent one stays absent.
6
+ */
7
+ export declare function project(payload: object, properties: Record<string, Property>, path?: string): Record<string, unknown>;
8
+ /** A payload's value at `path` is not of the type its contract declares. */
9
+ export declare class Mismatch extends Error {
10
+ readonly path: string;
11
+ constructor(path: string, property: Property);
12
+ }