@smart-data-engines/sde 0.1.0-dev.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.
- package/LICENSE +201 -0
- package/NOTICE +13 -0
- package/README.md +153 -0
- package/bin/weather.mjs +32 -0
- package/dist/_usage.d.ts +30 -0
- package/dist/_usage.js +194 -0
- package/dist/_usage.js.map +1 -0
- package/dist/bulk.d.ts +9 -0
- package/dist/bulk.js +83 -0
- package/dist/bulk.js.map +1 -0
- package/dist/canonical.d.ts +46 -0
- package/dist/canonical.js +150 -0
- package/dist/canonical.js.map +1 -0
- package/dist/capabilities.d.ts +48 -0
- package/dist/capabilities.js +62 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cutover.d.ts +36 -0
- package/dist/cutover.js +219 -0
- package/dist/cutover.js.map +1 -0
- package/dist/demo/model.d.ts +28 -0
- package/dist/demo/model.js +40 -0
- package/dist/demo/model.js.map +1 -0
- package/dist/demo/project.d.ts +19 -0
- package/dist/demo/project.js +128 -0
- package/dist/demo/project.js.map +1 -0
- package/dist/demo/weather.d.ts +73 -0
- package/dist/demo/weather.js +334 -0
- package/dist/demo/weather.js.map +1 -0
- package/dist/engines/_clickhouse-connection.d.ts +17 -0
- package/dist/engines/_clickhouse-connection.js +182 -0
- package/dist/engines/_clickhouse-connection.js.map +1 -0
- package/dist/engines/_tls-peer-identity.d.ts +2 -0
- package/dist/engines/_tls-peer-identity.js +23 -0
- package/dist/engines/_tls-peer-identity.js.map +1 -0
- package/dist/engines/_write-fences.d.ts +51 -0
- package/dist/engines/_write-fences.js +189 -0
- package/dist/engines/_write-fences.js.map +1 -0
- package/dist/engines/clickhouse.d.ts +193 -0
- package/dist/engines/clickhouse.js +899 -0
- package/dist/engines/clickhouse.js.map +1 -0
- package/dist/engines/postgres.d.ts +293 -0
- package/dist/engines/postgres.js +981 -0
- package/dist/engines/postgres.js.map +1 -0
- package/dist/errors.d.ts +89 -0
- package/dist/errors.js +90 -0
- package/dist/errors.js.map +1 -0
- package/dist/frozen-verification.d.ts +26 -0
- package/dist/frozen-verification.js +67 -0
- package/dist/frozen-verification.js.map +1 -0
- package/dist/generation.d.ts +34 -0
- package/dist/generation.js +81 -0
- package/dist/generation.js.map +1 -0
- package/dist/groups.d.ts +17 -0
- package/dist/groups.js +66 -0
- package/dist/groups.js.map +1 -0
- package/dist/hashing.d.ts +68 -0
- package/dist/hashing.js +146 -0
- package/dist/hashing.js.map +1 -0
- package/dist/in-place-index.d.ts +43 -0
- package/dist/in-place-index.js +272 -0
- package/dist/in-place-index.js.map +1 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/inspection.d.ts +19 -0
- package/dist/inspection.js +31 -0
- package/dist/inspection.js.map +1 -0
- package/dist/internal.d.ts +42 -0
- package/dist/internal.js +56 -0
- package/dist/internal.js.map +1 -0
- package/dist/layout.d.ts +36 -0
- package/dist/layout.js +62 -0
- package/dist/layout.js.map +1 -0
- package/dist/migration.d.ts +197 -0
- package/dist/migration.js +592 -0
- package/dist/migration.js.map +1 -0
- package/dist/model.d.ts +93 -0
- package/dist/model.js +313 -0
- package/dist/model.js.map +1 -0
- package/dist/physical.d.ts +128 -0
- package/dist/physical.js +421 -0
- package/dist/physical.js.map +1 -0
- package/dist/placement.d.ts +157 -0
- package/dist/placement.js +651 -0
- package/dist/placement.js.map +1 -0
- package/dist/provisioning.d.ts +6 -0
- package/dist/provisioning.js +45 -0
- package/dist/provisioning.js.map +1 -0
- package/dist/query.d.ts +68 -0
- package/dist/query.js +340 -0
- package/dist/query.js.map +1 -0
- package/dist/routing.d.ts +25 -0
- package/dist/routing.js +35 -0
- package/dist/routing.js.map +1 -0
- package/dist/schema.d.ts +110 -0
- package/dist/schema.js +337 -0
- package/dist/schema.js.map +1 -0
- package/dist/session.d.ts +195 -0
- package/dist/session.js +870 -0
- package/dist/session.js.map +1 -0
- package/dist/shapes.d.ts +30 -0
- package/dist/shapes.js +112 -0
- package/dist/shapes.js.map +1 -0
- package/dist/staging.d.ts +29 -0
- package/dist/staging.js +214 -0
- package/dist/staging.js.map +1 -0
- package/dist/telemetry.d.ts +468 -0
- package/dist/telemetry.js +872 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/testing/loader.d.ts +38 -0
- package/dist/testing/loader.js +86 -0
- package/dist/testing/loader.js.map +1 -0
- package/dist/testing/memory.d.ts +131 -0
- package/dist/testing/memory.js +311 -0
- package/dist/testing/memory.js.map +1 -0
- package/dist/timestamp.d.ts +20 -0
- package/dist/timestamp.js +89 -0
- package/dist/timestamp.js.map +1 -0
- package/dist/types.d.ts +79 -0
- package/dist/types.js +100 -0
- package/dist/types.js.map +1 -0
- package/dist/verification.d.ts +41 -0
- package/dist/verification.js +169 -0
- package/dist/verification.js.map +1 -0
- package/dist/watermark.d.ts +103 -0
- package/dist/watermark.js +170 -0
- package/dist/watermark.js.map +1 -0
- package/dist/write-fence.d.ts +58 -0
- package/dist/write-fence.js +225 -0
- package/dist/write-fence.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/** Bounded customer workload. Values and runtime credentials remain in this process. */
|
|
2
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { setTimeout as pause } from 'node:timers/promises';
|
|
7
|
+
import { EngineError, MapRolledBack, MigrationRefused } from '../errors.js';
|
|
8
|
+
import { PostgresEngine } from '../engines/postgres.js';
|
|
9
|
+
import { ClickHouseEngine } from '../engines/clickhouse.js';
|
|
10
|
+
import { Session } from '../session.js';
|
|
11
|
+
import { Recorder, windowRecord } from '../telemetry.js';
|
|
12
|
+
import { baseTime, celsiusBaseCents, celsiusModulus, generatorId, humidityBase, humidityModulus, reading } from './model.js';
|
|
13
|
+
import { DemoRefused, project, read, write } from './project.js';
|
|
14
|
+
/** What a run can drive. The CLI offers and the runtime accepts this one list. */
|
|
15
|
+
export const workloads = ['mixed', 'point', 'analytics', 'fleet', 'alerts'];
|
|
16
|
+
/** The fleet checks one cross-station page exactly; its count and sum cover the whole window. */
|
|
17
|
+
const fleetPage = 100;
|
|
18
|
+
const maxRunRows = 10000;
|
|
19
|
+
/**
|
|
20
|
+
* The alert threshold. Humidity is 30 + sequence % 70, so a reading alerts when sequence % 70 is 65
|
|
21
|
+
* or more - five readings in seventy, known exactly from the sequence number.
|
|
22
|
+
*/
|
|
23
|
+
export const alertHumidity = 95;
|
|
24
|
+
export const alertPage = 100;
|
|
25
|
+
function recoverable(error) {
|
|
26
|
+
return error instanceof EngineError || error instanceof MapRolledBack || error instanceof MigrationRefused;
|
|
27
|
+
}
|
|
28
|
+
function same(actual, expected) {
|
|
29
|
+
if (!isDeepStrictEqual(actual, expected))
|
|
30
|
+
throw new DemoRefused('A logical read did not match this run.');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A run that stopped, failed, before it recorded its first write: it wrote no row. A run records the
|
|
34
|
+
* batch it is about to write before writing it, so no pending batch and no acknowledged or verified
|
|
35
|
+
* row means nothing reached the engine. Without this, a first run that could not open its session -
|
|
36
|
+
* a missing driver - stopped every later fleet run in that directory.
|
|
37
|
+
*/
|
|
38
|
+
function failedBeforeWriting(report) {
|
|
39
|
+
return report.status === 'incomplete' && report.pending === null && report.generator_id === generatorId &&
|
|
40
|
+
['acknowledged_rows', 'verified_after_uncertain_rows', 'verified_rows']
|
|
41
|
+
.every(field => report[field] === 0);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Every earlier run of this project, by run ID, with the rows it verified.
|
|
45
|
+
*
|
|
46
|
+
* Fleet analytics reads every station's rows in one time window, and every run in a directory writes
|
|
47
|
+
* the same timeline, so the exact answer is a sum over the runs - known exactly, because generated
|
|
48
|
+
* values depend only on the sequence number and each run's local report says how many rows it
|
|
49
|
+
* verified. A run that did not complete makes that sum unknowable, so the workload refuses instead
|
|
50
|
+
* of comparing a read with a guess - except a run that failed before its first write, which wrote no
|
|
51
|
+
* row (failedBeforeWriting). The same rules as the Python starter's fleet_runs.
|
|
52
|
+
*/
|
|
53
|
+
export function fleetRuns(root, projectId) {
|
|
54
|
+
const runs = new Map();
|
|
55
|
+
const directory = join(root, 'runs');
|
|
56
|
+
if (!existsSync(directory))
|
|
57
|
+
return runs;
|
|
58
|
+
for (const name of readdirSync(directory).sort()) {
|
|
59
|
+
const path = join(directory, name, 'report.json');
|
|
60
|
+
if (!existsSync(path))
|
|
61
|
+
continue;
|
|
62
|
+
const report = read(path).value;
|
|
63
|
+
if (report.project_id !== projectId)
|
|
64
|
+
continue;
|
|
65
|
+
const identity = report.run_id, rows = report.verified_rows;
|
|
66
|
+
if (failedBeforeWriting(report) && identity === name)
|
|
67
|
+
continue;
|
|
68
|
+
if (typeof identity !== 'string' || !/^[0-9a-f]{32}$/.test(identity) || name !== identity ||
|
|
69
|
+
report.status !== 'complete' || report.pending !== null || report.generator_id !== generatorId ||
|
|
70
|
+
typeof rows !== 'number' || !Number.isSafeInteger(rows) || rows < 0 || rows > maxRunRows) {
|
|
71
|
+
throw new DemoRefused("Fleet analytics reads every run's rows, so every earlier run of this project must " +
|
|
72
|
+
'be complete; inspect the unfinished run first.');
|
|
73
|
+
}
|
|
74
|
+
runs.set(identity, rows);
|
|
75
|
+
}
|
|
76
|
+
return runs;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The first page, row count and celsius total of the window holding sequences 1..through. A page is
|
|
80
|
+
* in key order, station then time; a station is its run's namespace and is ASCII, so the default
|
|
81
|
+
* string order is the engines' byte order.
|
|
82
|
+
*/
|
|
83
|
+
export function fleetExpected(runs, through, limit) {
|
|
84
|
+
const page = [];
|
|
85
|
+
let total = 0, cents = 0n;
|
|
86
|
+
const ordered = [...runs.keys()].sort((left, right) => {
|
|
87
|
+
const a = reading(left, 0, 1).station, b = reading(right, 0, 1).station;
|
|
88
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
89
|
+
});
|
|
90
|
+
for (const identity of ordered) {
|
|
91
|
+
const rows = Math.min(through, runs.get(identity));
|
|
92
|
+
total += rows;
|
|
93
|
+
for (let sequence = 1; sequence <= rows; sequence++) {
|
|
94
|
+
cents += BigInt(celsiusBaseCents + sequence % celsiusModulus);
|
|
95
|
+
if (page.length < limit)
|
|
96
|
+
page.push(reading(identity, 0, sequence));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return [page, total, `${cents / 100n}.${String(cents % 100n).padStart(2, '0')}`];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The first page, count and celsius total of this run's alerts among sequences 1..through. One
|
|
103
|
+
* station, so key order - station, then time - is sequence order. With no alert yet the total is
|
|
104
|
+
* null, as the library reports a summary of no values on every engine. The same rules as the Python
|
|
105
|
+
* starter's alert_expected.
|
|
106
|
+
*/
|
|
107
|
+
export function alertExpected(runId, through, limit) {
|
|
108
|
+
const page = [];
|
|
109
|
+
let total = 0, cents = 0n;
|
|
110
|
+
for (let sequence = 1; sequence <= through; sequence++) {
|
|
111
|
+
if (humidityBase + sequence % humidityModulus < alertHumidity)
|
|
112
|
+
continue;
|
|
113
|
+
total++;
|
|
114
|
+
cents += BigInt(celsiusBaseCents + sequence % celsiusModulus);
|
|
115
|
+
if (page.length < limit)
|
|
116
|
+
page.push(reading(runId, 0, sequence));
|
|
117
|
+
}
|
|
118
|
+
return [page, total, total ? `${cents / 100n}.${String(cents % 100n).padStart(2, '0')}` : null];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Refuse before a run's report exists when a binding's driver cannot be imported. Without this the
|
|
122
|
+
* first session open failed inside the run's retry loop: ten seconds of retries, a message that could
|
|
123
|
+
* only say the operation did not complete, and a report left `incomplete`. ClickHouse is spoken over
|
|
124
|
+
* fetch and needs no package. The import is the adapter's own, resolved from this package.
|
|
125
|
+
*/
|
|
126
|
+
export async function requireDrivers(dialects, load = name => import(name)) {
|
|
127
|
+
if (![...dialects].includes('postgres'))
|
|
128
|
+
return;
|
|
129
|
+
try {
|
|
130
|
+
await load('pg');
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
throw new DemoRefused("The PostgreSQL binding needs the 'pg' package: npm install pg");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
export async function runWeather(root, options = {}) {
|
|
137
|
+
const { iterations = 10, batchSize = 10, intervalMs = 100, recoveryMs = 10000, workload = 'mixed' } = options;
|
|
138
|
+
if (![iterations, batchSize, intervalMs, recoveryMs].every(Number.isSafeInteger) ||
|
|
139
|
+
iterations < 1 || iterations > 1000 || batchSize < 1 || batchSize > 1000 || iterations * batchSize > maxRunRows ||
|
|
140
|
+
intervalMs < 0 || intervalMs > 1000 || recoveryMs < 0 || recoveryMs > 30000 ||
|
|
141
|
+
!workloads.includes(workload))
|
|
142
|
+
throw new DemoRefused('Invalid bounded workload options.');
|
|
143
|
+
const { model, bindings, projectId, activeMap } = project(root);
|
|
144
|
+
await requireDrivers(Object.values(bindings).map(binding => binding.dialect));
|
|
145
|
+
// Read before this run's own report exists; a run that starts later is not in the window.
|
|
146
|
+
const earlier = workload === 'fleet' ? fleetRuns(root, projectId) : new Map();
|
|
147
|
+
const factories = {};
|
|
148
|
+
for (const [name, binding] of Object.entries(bindings))
|
|
149
|
+
factories[name] = () => binding.dialect === 'postgres' ? new PostgresEngine(binding.dsn) : new ClickHouseEngine(binding.dsn);
|
|
150
|
+
const runId = randomUUID().replaceAll('-', ''), directory = join(root, 'runs', runId);
|
|
151
|
+
const recorder = new Recorder(model.version);
|
|
152
|
+
let session, fingerprint;
|
|
153
|
+
const report = { protocol: 2, generator_id: generatorId, run_id: runId, language: 'typescript', status: 'running', workload,
|
|
154
|
+
sdk_version: String(JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version),
|
|
155
|
+
sdk_module: new URL('../index.js', import.meta.url).href, project_id: projectId, model_version: model.version,
|
|
156
|
+
acknowledged_rows: 0, verified_after_uncertain_rows: 0, verified_rows: 0, pending: null,
|
|
157
|
+
map_versions: [], read_retries: 0 };
|
|
158
|
+
function checkpoint() { write(join(directory, 'report.json'), report); }
|
|
159
|
+
async function opened(fresh = false) {
|
|
160
|
+
const placement = activeMap();
|
|
161
|
+
if (fresh || session === undefined || placement.fingerprint !== fingerprint) {
|
|
162
|
+
if (session !== undefined) {
|
|
163
|
+
await session.close();
|
|
164
|
+
session = undefined;
|
|
165
|
+
}
|
|
166
|
+
const required = new Set(Object.values(placement.groups).flatMap(group => [group.source, ...group.derived].map(material => material.engine)));
|
|
167
|
+
const activeFactories = Object.fromEntries([...required].map(name => {
|
|
168
|
+
if (!factories[name])
|
|
169
|
+
throw new DemoRefused('An active materialization has no local binding.');
|
|
170
|
+
return [name, factories[name]];
|
|
171
|
+
}));
|
|
172
|
+
session = await Session.connect(model, placement, activeFactories, { recorder, projectId });
|
|
173
|
+
fingerprint = placement.fingerprint;
|
|
174
|
+
if (!report.map_versions.includes(placement.mapVersion))
|
|
175
|
+
report.map_versions.push(placement.mapVersion);
|
|
176
|
+
}
|
|
177
|
+
return session;
|
|
178
|
+
}
|
|
179
|
+
async function readRetry(action) {
|
|
180
|
+
const deadline = performance.now() + recoveryMs;
|
|
181
|
+
let fresh = false;
|
|
182
|
+
for (;;) {
|
|
183
|
+
try {
|
|
184
|
+
return await action(await opened(fresh));
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
if (!recoverable(error) || performance.now() >= deadline)
|
|
188
|
+
throw error;
|
|
189
|
+
report.read_retries++;
|
|
190
|
+
fresh = true;
|
|
191
|
+
await pause(50);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async function checkRows(client, rows) {
|
|
196
|
+
for (const row of rows) {
|
|
197
|
+
const actual = await client.get('WeatherReading', { station: row.station, at: row.at }, { fresh: true });
|
|
198
|
+
if (actual === null)
|
|
199
|
+
return false;
|
|
200
|
+
same(actual, row);
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
checkpoint();
|
|
205
|
+
const began = process.hrtime.bigint();
|
|
206
|
+
try {
|
|
207
|
+
// The group's size at the start of the run and again at its end, for the window: the engine's
|
|
208
|
+
// catalogue answers with numbers, and a refused read leaves the size unknown.
|
|
209
|
+
await readRetry(current => current.measureStorage());
|
|
210
|
+
for (let iteration = 0; iteration < iterations; iteration++) {
|
|
211
|
+
const first = iteration * batchSize + 1;
|
|
212
|
+
const rows = Array.from({ length: batchSize }, (_, index) => reading(runId, 0, first + index));
|
|
213
|
+
const client = await readRetry(async (current) => current);
|
|
214
|
+
report.pending = { first, count: batchSize };
|
|
215
|
+
checkpoint();
|
|
216
|
+
try {
|
|
217
|
+
await client.saveMany('WeatherReading', rows);
|
|
218
|
+
report.acknowledged_rows += batchSize;
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
if (!(error instanceof EngineError))
|
|
222
|
+
throw error;
|
|
223
|
+
const deadline = performance.now() + recoveryMs;
|
|
224
|
+
for (;;) {
|
|
225
|
+
try {
|
|
226
|
+
if (await checkRows(await opened(true), rows)) {
|
|
227
|
+
report.verified_after_uncertain_rows += batchSize;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch (readError) {
|
|
232
|
+
if (!recoverable(readError))
|
|
233
|
+
throw readError;
|
|
234
|
+
}
|
|
235
|
+
if (performance.now() >= deadline)
|
|
236
|
+
throw new DemoRefused('Write outcome is uncertain. Inspect the pending range locally; the starter did not replay it.');
|
|
237
|
+
await pause(50);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
report.pending = null;
|
|
241
|
+
checkpoint();
|
|
242
|
+
const last = rows.at(-1), count = first + batchSize - 1, where = { station: last.station };
|
|
243
|
+
for (let index = 0; index < (workload === 'point' ? 20 : 1); index++) {
|
|
244
|
+
same(await readRetry(current => current.get('WeatherReading', { station: last.station, at: last.at })), last);
|
|
245
|
+
}
|
|
246
|
+
if (workload === 'fleet') {
|
|
247
|
+
// Every station, one time window: the traffic a time-first layout is for. The expected
|
|
248
|
+
// answer is exact, from this directory's run reports (fleetRuns).
|
|
249
|
+
const window = new Map(earlier).set(runId, count);
|
|
250
|
+
const [expected, rows, celsius] = fleetExpected(window, count, fleetPage);
|
|
251
|
+
const bounds = { field: 'at', low: reading(runId, 0, 1).at, high: reading(runId, 0, count + 1).at };
|
|
252
|
+
const page = await readRetry(current => current.scan('WeatherReading', { bounds, limit: expected.length }));
|
|
253
|
+
if (page.rows.length !== expected.length)
|
|
254
|
+
throw new DemoRefused("The fleet page did not match this directory's runs.");
|
|
255
|
+
page.rows.forEach((row, index) => same(row, expected[index]));
|
|
256
|
+
if (await readRetry(current => current.count('WeatherReading', { bounds })) !== BigInt(rows)) {
|
|
257
|
+
throw new DemoRefused("The fleet count did not match this directory's runs.");
|
|
258
|
+
}
|
|
259
|
+
const summary = await readRetry(current => current.summarize('WeatherReading', 'celsius', { bounds }));
|
|
260
|
+
if (summary.count !== BigInt(rows) || summary.total !== celsius) {
|
|
261
|
+
throw new DemoRefused("The exact fleet summary did not match this directory's runs.");
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else if (workload === 'alerts') {
|
|
265
|
+
// One station's readings at or above the alert threshold: a range on humidity, a field
|
|
266
|
+
// outside the key, which the key cannot serve and an index can. Exact from the generator.
|
|
267
|
+
const [expected, alerts, celsius] = alertExpected(runId, count, alertPage);
|
|
268
|
+
const bounds = { field: 'humidity', low: BigInt(alertHumidity) };
|
|
269
|
+
const page = await readRetry(current => current.scan('WeatherReading', { where, bounds, limit: alertPage }));
|
|
270
|
+
if (page.rows.length !== expected.length)
|
|
271
|
+
throw new DemoRefused('The alert page did not match this run.');
|
|
272
|
+
page.rows.forEach((row, index) => same(row, expected[index]));
|
|
273
|
+
if (await readRetry(current => current.count('WeatherReading', { where, bounds })) !== BigInt(alerts)) {
|
|
274
|
+
throw new DemoRefused('The alert count did not match this run.');
|
|
275
|
+
}
|
|
276
|
+
const summary = await readRetry(current => current.summarize('WeatherReading', 'celsius', { where, bounds }));
|
|
277
|
+
if (summary.count !== BigInt(alerts) || summary.total !== celsius) {
|
|
278
|
+
throw new DemoRefused('The exact alert summary did not match this run.');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else if (workload !== 'point' || iteration === iterations - 1) {
|
|
282
|
+
const page = await readRetry(current => current.scan('WeatherReading', {
|
|
283
|
+
where, bounds: { field: 'at', low: baseTime }, limit: Math.min(count, 1000),
|
|
284
|
+
}));
|
|
285
|
+
if (page.rows.length !== Math.min(count, 1000))
|
|
286
|
+
throw new DemoRefused('The bounded page has a different length.');
|
|
287
|
+
page.rows.forEach((row, index) => same(row, reading(runId, 0, index + 1)));
|
|
288
|
+
if (await readRetry(current => current.count('WeatherReading', { where })) !== BigInt(count)) {
|
|
289
|
+
throw new DemoRefused('The logical count did not match this run.');
|
|
290
|
+
}
|
|
291
|
+
const summary = await readRetry(current => current.summarize('WeatherReading', 'celsius', { where }));
|
|
292
|
+
let cents = 0n;
|
|
293
|
+
for (let index = 1; index <= count; index++)
|
|
294
|
+
cents += BigInt(1525 + index % 1000);
|
|
295
|
+
const total = `${cents / 100n}.${String(cents % 100n).padStart(2, '0')}`;
|
|
296
|
+
if (summary.count !== BigInt(count) || summary.total !== total)
|
|
297
|
+
throw new DemoRefused('The exact summary did not match this run.');
|
|
298
|
+
}
|
|
299
|
+
report.verified_rows = count;
|
|
300
|
+
checkpoint();
|
|
301
|
+
if (intervalMs && iteration + 1 < iterations)
|
|
302
|
+
await pause(intervalMs);
|
|
303
|
+
}
|
|
304
|
+
await readRetry(current => current.measureStorage());
|
|
305
|
+
report.status = 'complete';
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
report.status = 'incomplete';
|
|
309
|
+
report.failure = error instanceof Error ? error.name : 'UnknownError';
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
finally {
|
|
313
|
+
report.elapsed_ns = String(process.hrtime.bigint() - began);
|
|
314
|
+
try {
|
|
315
|
+
if (session !== undefined)
|
|
316
|
+
await session.close();
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
report.status = 'incomplete';
|
|
320
|
+
report.cleanup_failed = true;
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
const window = recorder.roll();
|
|
325
|
+
if (window !== undefined) {
|
|
326
|
+
write(join(directory, 'window.json'), windowRecord(window, model));
|
|
327
|
+
recorder.acknowledge(1);
|
|
328
|
+
}
|
|
329
|
+
checkpoint();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return report;
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=weather.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weather.js","sourceRoot":"","sources":["../../src/demo/weather.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAC5H,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEhE,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAA;AAEpF,iGAAiG;AACjG,MAAM,SAAS,GAAG,GAAG,CAAA;AACrB,MAAM,UAAU,GAAG,KAAK,CAAA;AACxB;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAA;AAC/B,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAA;AAa5B,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,WAAW,IAAI,KAAK,YAAY,aAAa,IAAI,KAAK,YAAY,gBAAgB,CAAA;AAC5G,CAAC;AACD,SAAS,IAAI,CAAC,MAAkB,EAAE,QAAa;IAC7C,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC;QAAE,MAAM,IAAI,WAAW,CAAC,wCAAwC,CAAC,CAAA;AAC3G,CAAC;AACD;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,MAA+B;IAC1D,OAAO,MAAM,CAAC,MAAM,KAAK,YAAY,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,YAAY,KAAK,WAAW;QACpG,CAAC,mBAAmB,EAAE,+BAA+B,EAAE,eAAe,CAAW;aAC/E,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;AAC1C,CAAC;AACD;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,SAAiB;IACvD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAA;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACpC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAA;IACvC,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,aAAa,CAAC,CAAA;QACjD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAQ;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAA;QAC/B,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;YAAE,SAAQ;QAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,aAAa,CAAA;QAC3D,IAAI,mBAAmB,CAAC,MAAM,CAAC,IAAI,QAAQ,KAAK,IAAI;YAAE,SAAQ;QAC9D,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,QAAQ;YACrF,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,YAAY,KAAK,WAAW;YAC9F,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,UAAU,EAAE,CAAC;YAC7F,MAAM,IAAI,WAAW,CAAC,oFAAoF;gBACxG,gDAAgD,CAAC,CAAA;QACrD,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAC1B,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AACD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAyB,EAAE,OAAe,EAAE,KAAa;IACrF,MAAM,IAAI,GAAU,EAAE,CAAA;IACtB,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,CAAA;IACzB,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACpD,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;QACvE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IACF,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,CAAA;QACnD,KAAK,IAAI,IAAI,CAAA;QACb,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,IAAI,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;YACpD,KAAK,IAAI,MAAM,CAAC,gBAAgB,GAAG,QAAQ,GAAG,cAAc,CAAC,CAAA;YAC7D,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK;gBAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;QACpE,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;AAClF,CAAC;AACD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,OAAe,EAAE,KAAa;IACzE,MAAM,IAAI,GAAU,EAAE,CAAA;IACtB,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,CAAA;IACzB,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,IAAI,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC;QACvD,IAAI,YAAY,GAAG,QAAQ,GAAG,eAAe,GAAG,aAAa;YAAE,SAAQ;QACvE,KAAK,EAAE,CAAA;QACP,KAAK,IAAI,MAAM,CAAC,gBAAgB,GAAG,QAAQ,GAAG,cAAc,CAAC,CAAA;QAC7D,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AACjG,CAAC;AACD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAA0B,EAAE,OAA2C,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;IAE3F,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAM;IAC/C,IAAI,CAAC;QAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC;QAC9B,MAAM,IAAI,WAAW,CAAC,+DAA+D,CAAC,CAAA;IACxF,CAAC;AACH,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,UAAsB,EAAE;IACrE,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,EAAE,UAAU,GAAG,GAAG,EAAE,UAAU,GAAG,KAAK,EAAE,QAAQ,GAAG,OAAO,EAAE,GAAG,OAAO,CAAA;IAC7G,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QAC5E,UAAU,GAAG,CAAC,IAAI,UAAU,GAAG,IAAI,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,IAAI,IAAI,UAAU,GAAG,SAAS,GAAG,UAAU;QAC/G,UAAU,GAAG,CAAC,IAAI,UAAU,GAAG,IAAI,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,GAAG,KAAK;QAC3E,CAAE,SAA+B,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,WAAW,CAAC,mCAAmC,CAAC,CAAA;IACpH,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAC7E,0FAA0F;IAC1F,MAAM,OAAO,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAkB,CAAA;IAC7F,MAAM,SAAS,GAAwC,EAAE,CAAA;IACzD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,SAAS,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAC7E,OAAO,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACtG,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;IACrF,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,OAA4B,EAAE,WAA+B,CAAA;IACjE,MAAM,MAAM,GAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ;QACpI,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7G,UAAU,EAAE,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO;QAC7G,iBAAiB,EAAE,CAAC,EAAE,6BAA6B,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI;QACvF,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,CAAA;IACrC,SAAS,UAAU,KAAK,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAA,CAAC,CAAC;IACvE,KAAK,UAAU,MAAM,CAAC,KAAK,GAAG,KAAK;QACjC,MAAM,SAAS,GAAG,SAAS,EAAE,CAAA;QAC7B,IAAI,KAAK,IAAI,OAAO,KAAK,SAAS,IAAI,SAAS,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;YAC5E,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBAAC,OAAO,GAAG,SAAS,CAAA;YAAC,CAAC;YACzE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CACvE,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACrE,MAAM,eAAe,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBAClE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAAE,MAAM,IAAI,WAAW,CAAC,iDAAiD,CAAC,CAAA;gBAC9F,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAE,CAAC,CAAA;YACjC,CAAC,CAAC,CAAC,CAAA;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAA;YAC3F,WAAW,GAAG,SAAS,CAAC,WAAW,CAAA;YACnC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC;gBAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QACzG,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,KAAK,UAAU,SAAS,CAAI,MAAuC;QACjE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,UAAU,CAAA;QAC/C,IAAI,KAAK,GAAG,KAAK,CAAA;QACjB,SAAS,CAAC;YACR,IAAI,CAAC;gBAAC,OAAO,MAAM,MAAM,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YAAC,CAAC;YAChD,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,QAAQ;oBAAE,MAAM,KAAK,CAAA;gBACrE,MAAM,CAAC,YAAY,EAAE,CAAC;gBAAC,KAAK,GAAG,IAAI,CAAC;gBAAC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAA;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,UAAU,SAAS,CAAC,MAAe,EAAE,IAAW;QACnD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YACxG,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAA;YACjC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QACnB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,UAAU,EAAE,CAAA;IACZ,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;IACrC,IAAI,CAAC;QACH,8FAA8F;QAC9F,8EAA8E;QAC9E,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;QACpD,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,UAAU,EAAE,SAAS,EAAE,EAAE,CAAC;YAC5D,MAAM,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,CAAC,CAAA;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC,CAAA;YAC9F,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,EAAC,OAAO,EAAC,EAAE,CAAC,OAAO,CAAC,CAAA;YACxD,MAAM,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YAAC,UAAU,EAAE,CAAA;YAC1D,IAAI,CAAC;gBAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;gBAAC,MAAM,CAAC,iBAAiB,IAAI,SAAS,CAAA;YAAC,CAAC;YAC5F,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC;oBAAE,MAAM,KAAK,CAAA;gBAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,UAAU,CAAA;gBAC/C,SAAS,CAAC;oBACR,IAAI,CAAC;wBACH,IAAI,MAAM,SAAS,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;4BAAC,MAAM,CAAC,6BAA6B,IAAI,SAAS,CAAC;4BAAC,MAAK;wBAAC,CAAC;oBAC7G,CAAC;oBAAC,OAAO,SAAS,EAAE,CAAC;wBAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;4BAAE,MAAM,SAAS,CAAA;oBAAC,CAAC;oBACpE,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,QAAQ;wBAAE,MAAM,IAAI,WAAW,CACtD,+FAA+F,CAAC,CAAA;oBAClG,MAAM,KAAK,CAAC,EAAE,CAAC,CAAA;gBACjB,CAAC;YACH,CAAC;YACD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;YAAC,UAAU,EAAE,CAAA;YACnC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAA;YAC3F,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;gBACrE,IAAI,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;YAC/G,CAAC;YACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACzB,uFAAuF;gBACvF,kEAAkE;gBAClE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;gBACjD,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;gBACzE,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;gBACnG,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBAC3G,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;oBAAE,MAAM,IAAI,WAAW,CAAC,qDAAqD,CAAC,CAAA;gBACtH,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAE,CAAC,CAAC,CAAA;gBAC9D,IAAI,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7F,MAAM,IAAI,WAAW,CAAC,sDAAsD,CAAC,CAAA;gBAC/E,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;gBACtG,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;oBAChE,MAAM,IAAI,WAAW,CAAC,8DAA8D,CAAC,CAAA;gBACvF,CAAC;YACH,CAAC;iBAAM,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACjC,uFAAuF;gBACvF,0FAA0F;gBAC1F,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;gBAC1E,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAA;gBAChE,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;gBAC5G,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;oBAAE,MAAM,IAAI,WAAW,CAAC,wCAAwC,CAAC,CAAA;gBACzG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAE,CAAC,CAAC,CAAA;gBAC9D,IAAI,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBACtG,MAAM,IAAI,WAAW,CAAC,yCAAyC,CAAC,CAAA;gBAClE,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;gBAC7G,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;oBAClE,MAAM,IAAI,WAAW,CAAC,iDAAiD,CAAC,CAAA;gBAC1E,CAAC;YACH,CAAC;iBAAM,IAAI,QAAQ,KAAK,OAAO,IAAI,SAAS,KAAK,UAAU,GAAG,CAAC,EAAE,CAAC;gBAChE,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE;oBACrE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC;iBAC5E,CAAC,CAAC,CAAA;gBACH,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC;oBAAE,MAAM,IAAI,WAAW,CAAC,0CAA0C,CAAC,CAAA;gBACjH,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBAC1E,IAAI,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7F,MAAM,IAAI,WAAW,CAAC,2CAA2C,CAAC,CAAA;gBACpE,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;gBACrG,IAAI,KAAK,GAAG,EAAE,CAAA;gBACd,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,KAAK,EAAE,KAAK,EAAE;oBAAE,KAAK,IAAI,MAAM,CAAC,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,CAAA;gBACjF,MAAM,KAAK,GAAG,GAAG,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAA;gBACxE,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK;oBAAE,MAAM,IAAI,WAAW,CAAC,2CAA2C,CAAC,CAAA;YACpI,CAAC;YACD,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC;YAAC,UAAU,EAAE,CAAA;YAC1C,IAAI,UAAU,IAAI,SAAS,GAAG,CAAC,GAAG,UAAU;gBAAE,MAAM,KAAK,CAAC,UAAU,CAAC,CAAA;QACvE,CAAC;QACD,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;QACpD,MAAM,CAAC,MAAM,GAAG,UAAU,CAAA;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,MAAM,GAAG,YAAY,CAAC;QAAC,MAAM,CAAC,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC;QAAC,MAAM,KAAK,CAAA;IAClH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAA;QAC3D,IAAI,CAAC;YAAC,IAAI,OAAO,KAAK,SAAS;gBAAE,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;QAAC,CAAC;QACxD,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,MAAM,GAAG,YAAY,CAAC;YAAC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;YAAC,MAAM,KAAK,CAAA;QAAC,CAAC;gBACjF,CAAC;YACP,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;YAC9B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;gBAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;YAAC,CAAC;YACzH,UAAU,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ConnectionOptions } from 'node:tls';
|
|
2
|
+
export interface ConnectionParameters {
|
|
3
|
+
readonly host: string;
|
|
4
|
+
readonly port: number;
|
|
5
|
+
readonly username: string;
|
|
6
|
+
readonly password: string;
|
|
7
|
+
readonly database: string;
|
|
8
|
+
readonly secure: boolean;
|
|
9
|
+
readonly ca_cert: string | null;
|
|
10
|
+
readonly connect_timeout: number;
|
|
11
|
+
readonly send_receive_timeout: number;
|
|
12
|
+
readonly receive_timeout_supplied: boolean;
|
|
13
|
+
readonly protocol: 'http:' | 'https:';
|
|
14
|
+
}
|
|
15
|
+
export declare function parseDsn(dsn: string): ConnectionParameters;
|
|
16
|
+
/** Read the selected CA once for this connection; never change process-global trust. */
|
|
17
|
+
export declare function verifiedTls(target: ConnectionParameters): ConnectionOptions;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/** Strict, portable connection intent; no driver-specific DSN fallback. */
|
|
2
|
+
import { X509Certificate } from 'node:crypto';
|
|
3
|
+
import { closeSync, constants, fstatSync, openSync, readSync } from 'node:fs';
|
|
4
|
+
import { isIP } from 'node:net';
|
|
5
|
+
import { isAbsolute } from 'node:path';
|
|
6
|
+
import { createSecureContext } from 'node:tls';
|
|
7
|
+
import { EngineError } from '../errors.js';
|
|
8
|
+
import { verifyPeerIdentity } from './_tls-peer-identity.js';
|
|
9
|
+
const PARAMETERS = new Set(['secure', 'verify', 'ca_cert', 'connect_timeout', 'send_receive_timeout']);
|
|
10
|
+
function refuse(field) {
|
|
11
|
+
throw new EngineError(`Invalid ClickHouse connection ${field}; no connection was opened.`);
|
|
12
|
+
}
|
|
13
|
+
function decode(value, field, form = false) {
|
|
14
|
+
try {
|
|
15
|
+
const result = decodeURIComponent(form ? value.replace(/\+/g, ' ') : value);
|
|
16
|
+
if (/[\u0000-\u001f\u007f]/u.test(result))
|
|
17
|
+
return refuse(field);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return refuse(field);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function seconds(value, fallback) {
|
|
25
|
+
if (value === undefined)
|
|
26
|
+
return fallback;
|
|
27
|
+
if (!/^(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?$/.test(value))
|
|
28
|
+
return refuse('timeout');
|
|
29
|
+
const parsed = Number(value);
|
|
30
|
+
if (!Number.isFinite(parsed) || parsed < 0.001 || parsed > 2147483.647)
|
|
31
|
+
return refuse('timeout');
|
|
32
|
+
return parsed;
|
|
33
|
+
}
|
|
34
|
+
export function parseDsn(dsn) {
|
|
35
|
+
if (typeof dsn !== 'string' || /[\u0000-\u0020\u007f\\#\p{White_Space}]/u.test(dsn))
|
|
36
|
+
return refuse('URI');
|
|
37
|
+
try {
|
|
38
|
+
encodeURIComponent(dsn);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return refuse('URI');
|
|
42
|
+
}
|
|
43
|
+
const matched = /^([A-Za-z][A-Za-z0-9+.-]*):\/\/([^/?#]*)(\/[^?#]*)?(?:\?([^#]*))?$/.exec(dsn);
|
|
44
|
+
if (matched === null)
|
|
45
|
+
return refuse('URI');
|
|
46
|
+
const scheme = matched[1].toLowerCase();
|
|
47
|
+
if (!['http', 'https', 'clickhouse', 'clickhouses'].includes(scheme))
|
|
48
|
+
return refuse('scheme');
|
|
49
|
+
const authority = matched[2];
|
|
50
|
+
const pieces = authority.split('@');
|
|
51
|
+
if (pieces.length > 2)
|
|
52
|
+
return refuse('authority');
|
|
53
|
+
const hostPort = pieces[pieces.length - 1];
|
|
54
|
+
let username = 'default', password = '';
|
|
55
|
+
if (pieces.length === 2) {
|
|
56
|
+
const userinfo = pieces[0], separator = userinfo.indexOf(':');
|
|
57
|
+
username = decode(separator < 0 ? userinfo : userinfo.slice(0, separator), 'username');
|
|
58
|
+
password = separator < 0 ? '' : decode(userinfo.slice(separator + 1), 'password');
|
|
59
|
+
if (username === '' || username.includes(':'))
|
|
60
|
+
return refuse('username');
|
|
61
|
+
}
|
|
62
|
+
let host, rawPort;
|
|
63
|
+
if (hostPort.startsWith('[')) {
|
|
64
|
+
const close = hostPort.indexOf(']');
|
|
65
|
+
if (close < 0)
|
|
66
|
+
return refuse('host');
|
|
67
|
+
const rawHost = hostPort.slice(1, close), remainder = hostPort.slice(close + 1);
|
|
68
|
+
if (isIP(rawHost) !== 6 || (remainder !== '' && !remainder.startsWith(':')))
|
|
69
|
+
return refuse('host');
|
|
70
|
+
host = new URL(`http://[${rawHost}]/`).hostname.slice(1, -1).toLowerCase();
|
|
71
|
+
rawPort = remainder === '' ? undefined : remainder.slice(1);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const pair = hostPort.split(':');
|
|
75
|
+
if (pair.length > 2)
|
|
76
|
+
return refuse('host');
|
|
77
|
+
host = pair[0].toLowerCase();
|
|
78
|
+
rawPort = pair[1];
|
|
79
|
+
const labels = (host.endsWith('.') ? host.slice(0, -1) : host).split('.');
|
|
80
|
+
if (host.length > 253 || labels.some((label) => !/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label)))
|
|
81
|
+
return refuse('host');
|
|
82
|
+
if (isIP(host) !== 4 && /^(?:0x[0-9a-f]+|[0-9]+)(?:\.(?:0x[0-9a-f]+|[0-9]+))*\.?$/.test(host))
|
|
83
|
+
return refuse('host');
|
|
84
|
+
}
|
|
85
|
+
const path = matched[3];
|
|
86
|
+
if (path === undefined || !/^\/[^/]+$/.test(path))
|
|
87
|
+
return refuse('database');
|
|
88
|
+
const database = decode(path.slice(1), 'database');
|
|
89
|
+
if (database === '' || database.includes('/') || database === '.' || database === '..')
|
|
90
|
+
return refuse('database');
|
|
91
|
+
const options = new Map();
|
|
92
|
+
const query = matched[4];
|
|
93
|
+
if (query !== undefined && query !== '')
|
|
94
|
+
for (const entry of query.split('&')) {
|
|
95
|
+
const separator = entry.indexOf('=');
|
|
96
|
+
if (separator <= 0)
|
|
97
|
+
return refuse('query option');
|
|
98
|
+
const key = decode(entry.slice(0, separator), 'query option', true);
|
|
99
|
+
const value = decode(entry.slice(separator + 1), 'query option', true);
|
|
100
|
+
if (!PARAMETERS.has(key) || options.has(key))
|
|
101
|
+
return refuse('query option');
|
|
102
|
+
options.set(key, value);
|
|
103
|
+
}
|
|
104
|
+
let secure = scheme === 'https' || scheme === 'clickhouses';
|
|
105
|
+
const requested = options.get('secure');
|
|
106
|
+
if (requested !== undefined) {
|
|
107
|
+
if (requested !== 'true' && requested !== 'false')
|
|
108
|
+
return refuse('secure option');
|
|
109
|
+
const wanted = requested === 'true';
|
|
110
|
+
if ((scheme === 'http' && wanted) || (secure && !wanted))
|
|
111
|
+
return refuse('conflicting transport');
|
|
112
|
+
secure = wanted;
|
|
113
|
+
}
|
|
114
|
+
let port;
|
|
115
|
+
if (rawPort !== undefined) {
|
|
116
|
+
if (!/^[0-9]+$/.test(rawPort))
|
|
117
|
+
return refuse('port');
|
|
118
|
+
port = Number(rawPort);
|
|
119
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
120
|
+
return refuse('port');
|
|
121
|
+
}
|
|
122
|
+
else
|
|
123
|
+
port = scheme === 'http' ? 80 : scheme === 'https' ? 443 : secure ? 8443 : 8123;
|
|
124
|
+
if (scheme === 'clickhouse' && requested === undefined && (port === 443 || port === 8443))
|
|
125
|
+
return refuse('ambiguous TLS port; use an explicit secure scheme or option');
|
|
126
|
+
if (options.has('verify') && (options.get('verify') !== 'true' || !secure))
|
|
127
|
+
return refuse('verify option');
|
|
128
|
+
const ca = options.get('ca_cert') ?? null;
|
|
129
|
+
if (ca !== null && (!secure || !isAbsolute(ca)))
|
|
130
|
+
return refuse('CA option');
|
|
131
|
+
return Object.freeze({ host, port, username, password, database, secure, ca_cert: ca,
|
|
132
|
+
connect_timeout: seconds(options.get('connect_timeout'), 10),
|
|
133
|
+
send_receive_timeout: seconds(options.get('send_receive_timeout'), 15),
|
|
134
|
+
receive_timeout_supplied: options.has('send_receive_timeout'),
|
|
135
|
+
protocol: secure ? 'https:' : 'http:',
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/** Read the selected CA once for this connection; never change process-global trust. */
|
|
139
|
+
export function verifiedTls(target) {
|
|
140
|
+
let ca;
|
|
141
|
+
if (target.ca_cert !== null) {
|
|
142
|
+
try {
|
|
143
|
+
const limit = 1024 * 1024;
|
|
144
|
+
const fd = openSync(target.ca_cert, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
145
|
+
try {
|
|
146
|
+
const info = fstatSync(fd);
|
|
147
|
+
if (!info.isFile() || info.size === 0 || info.size > limit)
|
|
148
|
+
return refuse('CA file');
|
|
149
|
+
const buffer = Buffer.alloc(limit + 1);
|
|
150
|
+
let size = 0;
|
|
151
|
+
while (size < buffer.length) {
|
|
152
|
+
const received = readSync(fd, buffer, size, buffer.length - size, null);
|
|
153
|
+
if (received === 0)
|
|
154
|
+
break;
|
|
155
|
+
size += received;
|
|
156
|
+
}
|
|
157
|
+
if (size === 0 || size > limit)
|
|
158
|
+
return refuse('CA file');
|
|
159
|
+
ca = buffer.subarray(0, size);
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
closeSync(fd);
|
|
163
|
+
}
|
|
164
|
+
const text = ca.toString('utf8');
|
|
165
|
+
const blocks = text.match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g);
|
|
166
|
+
if (blocks === null || blocks.length === 0)
|
|
167
|
+
return refuse('CA file');
|
|
168
|
+
for (const block of blocks)
|
|
169
|
+
new X509Certificate(block);
|
|
170
|
+
createSecureContext({ ca });
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return refuse('CA file');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
...(ca === undefined ? {} : { ca }), rejectUnauthorized: true,
|
|
178
|
+
...(isIP(target.host) === 0 ? { servername: target.host } : {}),
|
|
179
|
+
checkServerIdentity: (_host, certificate) => verifyPeerIdentity(target.host, certificate),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=_clickhouse-connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_clickhouse-connection.js","sourceRoot":"","sources":["../../src/engines/_clickhouse-connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Native peer-name checks, separate from TLS's certificate-chain verification. */
|
|
2
|
+
import { X509Certificate } from 'node:crypto';
|
|
3
|
+
import { isIP } from 'node:net';
|
|
4
|
+
import { checkServerIdentity } from 'node:tls';
|
|
5
|
+
function mismatch() {
|
|
6
|
+
return Object.assign(new Error('TLS peer certificate does not match the configured host.'), { code: 'ERR_TLS_CERT_ALTNAME_INVALID' });
|
|
7
|
+
}
|
|
8
|
+
export function verifyPeerIdentity(host, certificate) {
|
|
9
|
+
try {
|
|
10
|
+
if (isIP(host) === 0)
|
|
11
|
+
return checkServerIdentity(host, certificate);
|
|
12
|
+
// Node 22.23.2 applies domainToASCII before recognizing an IP, losing bare IPv6 addresses.
|
|
13
|
+
// OpenSSL's X509 IP check uses the actual DER certificate without a textual SAN parser.
|
|
14
|
+
if (!Buffer.isBuffer(certificate.raw) || certificate.raw.length === 0)
|
|
15
|
+
return mismatch();
|
|
16
|
+
return new X509Certificate(certificate.raw).checkIP(host) === undefined ? mismatch() : undefined;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Missing/malformed peer material must never turn a verification error into acceptance.
|
|
20
|
+
return mismatch();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=_tls-peer-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_tls-peer-identity.js","sourceRoot":"","sources":["../../src/engines/_tls-peer-identity.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,mBAAmB,EAAwB,MAAM,UAAU,CAAA;AAEpE,SAAS,QAAQ;IACf,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0DAA0D,CAAC,EACxF,EAAE,IAAI,EAAE,8BAA8B,EAAE,CAAC,CAAA;AAC7C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,WAA4B;IAC3E,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,mBAAmB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACnE,2FAA2F;QAC3F,wFAAwF;QACxF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,EAAE,CAAA;QACxF,OAAO,IAAI,eAAe,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAClG,CAAC;IAAC,MAAM,CAAC;QACP,wFAAwF;QACxF,OAAO,QAAQ,EAAE,CAAA;IACnB,CAAC;AACH,CAAC"}
|