@hypequery/clickhouse 2.4.0 → 2.5.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.
@@ -0,0 +1,25 @@
1
+ import { type CompiledIdentifiers, type CompiledOperation, type CompiledParameterDeclaration, type CompiledParameterValue, type CompiledQueryV1, type CompiledSensitivity, type CompiledSettings } from './types.js';
2
+ export interface CompileQueryInput {
3
+ readonly operation: CompiledOperation;
4
+ /** Trusted build/server output. Callers never author this. */
5
+ readonly sql: string;
6
+ readonly parameters?: readonly CompiledParameterDeclaration[];
7
+ /** Values supplied for declared parameter names. */
8
+ readonly values?: Readonly<Record<string, CompiledParameterValue>>;
9
+ readonly settings?: CompiledSettings;
10
+ readonly sensitivity?: CompiledSensitivity;
11
+ /** Server-generated authoritative identifier; the caller may add a correlation id. */
12
+ readonly identifiers: CompiledIdentifiers;
13
+ readonly deadline?: {
14
+ readonly callerAtEpochMs?: number;
15
+ readonly policyMaxMs?: number;
16
+ readonly nowEpochMs: number;
17
+ };
18
+ }
19
+ /**
20
+ * Assemble and validate a `CompiledQueryV1` (RFC 0010). This constructs the execution
21
+ * request beside the legacy positional path; it performs every fail-closed check before an
22
+ * adapter is ever handed the query, but performs no I/O.
23
+ */
24
+ export declare function compileQueryV1(input: CompileQueryInput): CompiledQueryV1;
25
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/core/compiled/compile.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAmBpB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAC9D,oDAAoD;IACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAC3C,sFAAsF;IACtF,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAClB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,CAqCxE"}
@@ -0,0 +1,134 @@
1
+ import { buildDebugForm } from './debug.js';
2
+ import { CompiledQueryError } from './errors.js';
3
+ import { assertNoValuesInSql, buildParameterBindings, validateParameterReferences, } from './parameters.js';
4
+ import { resolveCompiledDeadline, resolveCompiledSettings } from './settings.js';
5
+ import { COMPILED_QUERY_VERSION, } from './types.js';
6
+ const MAX_CORRELATION_ID_BYTES = 1024;
7
+ const MAX_QUERY_ID_BYTES = 200;
8
+ const MAX_SQL_BYTES = 1_048_576;
9
+ const MAX_PARAMETERS = 256;
10
+ const MAX_CLICKHOUSE_TYPE_BYTES = 256;
11
+ const MAX_SENSITIVITY_LABELS = 32;
12
+ const MAX_SENSITIVITY_LABEL_BYTES = 64;
13
+ // eslint-disable-next-line no-control-regex -- control chars are exactly what we reject
14
+ const CONTROL_CHAR_PATTERN = /[\u0000-\u001F\u007F-\u009F]/;
15
+ const QUERY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/;
16
+ const SENSITIVITY_LABEL_PATTERN = /^[a-z][a-z0-9._-]*$/;
17
+ const LOGICAL_TYPES = new Set([
18
+ 'array', 'boolean', 'bytes', 'date', 'datetime', 'decimal', 'enum', 'float',
19
+ 'integer', 'map', 'null', 'string', 'tuple', 'uuid',
20
+ ]);
21
+ const utf8 = new TextEncoder();
22
+ /**
23
+ * Assemble and validate a `CompiledQueryV1` (RFC 0010). This constructs the execution
24
+ * request beside the legacy positional path; it performs every fail-closed check before an
25
+ * adapter is ever handed the query, but performs no I/O.
26
+ */
27
+ export function compileQueryV1(input) {
28
+ validateOperation(input.operation);
29
+ validateSql(input.sql);
30
+ const parameters = snapshotParameters(input.parameters ?? []);
31
+ const values = input.values ?? {};
32
+ validateParameterReferences(input.sql, parameters);
33
+ const bindings = buildParameterBindings(parameters, values);
34
+ assertNoValuesInSql(input.sql, bindings);
35
+ const settings = resolveCompiledSettings(input.settings ?? {});
36
+ const identifiers = validateIdentifiers(input.identifiers);
37
+ const deadlineInputs = input.deadline
38
+ ? {
39
+ ...input.deadline,
40
+ policyMaxMs: minimumDefined(input.deadline.policyMaxMs, settings.maxExecutionMs),
41
+ }
42
+ : undefined;
43
+ const deadline = deadlineInputs
44
+ ? resolveCompiledDeadline(deadlineInputs)
45
+ : undefined;
46
+ const sensitivity = snapshotSensitivity(input.sensitivity);
47
+ const debug = buildDebugForm(input.sql, parameters, settings);
48
+ return Object.freeze({
49
+ version: COMPILED_QUERY_VERSION,
50
+ operation: input.operation,
51
+ sql: input.sql,
52
+ parameters,
53
+ bindings,
54
+ settings,
55
+ identifiers,
56
+ deadline,
57
+ sensitivity,
58
+ debug,
59
+ });
60
+ }
61
+ function minimumDefined(left, right) {
62
+ if (left === undefined)
63
+ return right;
64
+ if (right === undefined)
65
+ return left;
66
+ return Math.min(left, right);
67
+ }
68
+ function validateOperation(operation) {
69
+ if (operation !== 'query' && operation !== 'command' && operation !== 'insert') {
70
+ throw new CompiledQueryError('input-invalid', 'The compiled operation is invalid.');
71
+ }
72
+ }
73
+ function validateSql(sql) {
74
+ if (typeof sql !== 'string' || sql.length === 0 || utf8.encode(sql).length > MAX_SQL_BYTES) {
75
+ throw new CompiledQueryError('input-invalid', 'The compiled SQL is empty or too large.');
76
+ }
77
+ }
78
+ function snapshotParameters(input) {
79
+ if (!Array.isArray(input) || input.length > MAX_PARAMETERS) {
80
+ throw new CompiledQueryError('too-large', 'The compiled query has too many parameters.');
81
+ }
82
+ return Object.freeze(input.map((declaration) => {
83
+ const logical = declaration?.type?.logical;
84
+ const clickHouseType = declaration?.type?.clickHouseType;
85
+ if (!LOGICAL_TYPES.has(logical)
86
+ || typeof clickHouseType !== 'string'
87
+ || clickHouseType.length === 0
88
+ || CONTROL_CHAR_PATTERN.test(clickHouseType)
89
+ || utf8.encode(clickHouseType).length > MAX_CLICKHOUSE_TYPE_BYTES
90
+ || typeof declaration.optional !== 'boolean') {
91
+ throw new CompiledQueryError('input-invalid', 'A parameter declaration is invalid.');
92
+ }
93
+ return Object.freeze({
94
+ name: declaration.name,
95
+ type: Object.freeze({ logical, clickHouseType }),
96
+ optional: declaration.optional,
97
+ });
98
+ }));
99
+ }
100
+ function snapshotSensitivity(input) {
101
+ const tenantScoped = input?.tenantScoped ?? false;
102
+ const labels = input?.labels ?? [];
103
+ if (typeof tenantScoped !== 'boolean' || !Array.isArray(labels) || labels.length > MAX_SENSITIVITY_LABELS) {
104
+ throw new CompiledQueryError('input-invalid', 'Sensitivity metadata is invalid.');
105
+ }
106
+ const snapshot = labels.map((label) => {
107
+ if (typeof label !== 'string'
108
+ || !SENSITIVITY_LABEL_PATTERN.test(label)
109
+ || utf8.encode(label).length > MAX_SENSITIVITY_LABEL_BYTES) {
110
+ throw new CompiledQueryError('input-invalid', 'A sensitivity label is invalid.');
111
+ }
112
+ return label;
113
+ });
114
+ return Object.freeze({ tenantScoped, labels: Object.freeze(snapshot) });
115
+ }
116
+ function validateIdentifiers(identifiers) {
117
+ if (typeof identifiers.queryId !== 'string'
118
+ || !QUERY_ID_PATTERN.test(identifiers.queryId)
119
+ || utf8.encode(identifiers.queryId).length > MAX_QUERY_ID_BYTES) {
120
+ throw new CompiledQueryError('internal', 'A server-generated query id is required.');
121
+ }
122
+ const { correlationId } = identifiers;
123
+ if (correlationId !== undefined) {
124
+ if (CONTROL_CHAR_PATTERN.test(correlationId)) {
125
+ throw new CompiledQueryError('input-invalid', 'The correlation id contains control characters.');
126
+ }
127
+ if (utf8.encode(correlationId).length > MAX_CORRELATION_ID_BYTES) {
128
+ throw new CompiledQueryError('too-large', 'The correlation id exceeds the allowed size.');
129
+ }
130
+ }
131
+ return Object.freeze(correlationId === undefined
132
+ ? { queryId: identifiers.queryId }
133
+ : { queryId: identifiers.queryId, correlationId });
134
+ }
@@ -0,0 +1,7 @@
1
+ import type { CompiledDebugForm, CompiledParameterDeclaration, CompiledSettings } from './types.js';
2
+ /**
3
+ * Build the redacted, non-executable debug form. It carries no parameter values, tenant
4
+ * values, credentials, or setting values — only names, declared types, and structure.
5
+ */
6
+ export declare function buildDebugForm(sql: string, parameters: readonly CompiledParameterDeclaration[], settings: CompiledSettings): CompiledDebugForm;
7
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/core/compiled/debug.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,4BAA4B,EAC5B,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAWpB;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,SAAS,4BAA4B,EAAE,EACnD,QAAQ,EAAE,gBAAgB,GACzB,iBAAiB,CAkBnB"}
@@ -0,0 +1,25 @@
1
+ import { replaceParameterPlaceholders } from './parameters.js';
2
+ /**
3
+ * Marker wrapping placeholders in the debug form. The guillemets make the rendered SQL
4
+ * deliberately invalid as database SQL — it cannot be pasted into a client and run — while
5
+ * still showing structure and declared types (RFC 0010 §Debug form).
6
+ */
7
+ const DEBUG_OPEN = '«param ';
8
+ const DEBUG_CLOSE = '»';
9
+ /**
10
+ * Build the redacted, non-executable debug form. It carries no parameter values, tenant
11
+ * values, credentials, or setting values — only names, declared types, and structure.
12
+ */
13
+ export function buildDebugForm(sql, parameters, settings) {
14
+ const redactedSql = replaceParameterPlaceholders(sql, (name, type) => `${DEBUG_OPEN}${name}: ${type}${DEBUG_CLOSE}`);
15
+ return Object.freeze({
16
+ sql: redactedSql,
17
+ parameters: Object.freeze(parameters.map((p) => Object.freeze({
18
+ name: p.name,
19
+ type: p.type.clickHouseType,
20
+ optional: p.optional,
21
+ }))),
22
+ // Setting names only; values are policy and never appear in diagnostics.
23
+ settings: Object.freeze(Object.keys(settings).filter((key) => settings[key] !== undefined)),
24
+ });
25
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Public execution-failure envelope from RFC 0010 §Error envelope.
3
+ *
4
+ * The category set is closed and stable within version 1. It matches the frozen set in
5
+ * `@hypequery/protocol` (`events` module) so runtime failures and emitted diagnostics
6
+ * speak the same vocabulary. New categories require a new contract version.
7
+ */
8
+ export declare const COMPILED_ERROR_CATEGORIES: readonly ["input-invalid", "unauthenticated", "forbidden", "tenant-required", "not-found", "too-large", "aborted", "deadline-exceeded", "unavailable", "internal"];
9
+ export type CompiledErrorCategory = (typeof COMPILED_ERROR_CATEGORIES)[number];
10
+ export declare function isCompiledErrorCategory(value: unknown): value is CompiledErrorCategory;
11
+ export declare function isClientFaultCategory(category: CompiledErrorCategory): boolean;
12
+ /** The stable, serializable error object surfaced to callers. */
13
+ export interface CompiledErrorEnvelope {
14
+ readonly category: CompiledErrorCategory;
15
+ readonly message: string;
16
+ /** Authoritative query identifier; safe for logs. Absent only before one is assigned. */
17
+ readonly queryId?: string;
18
+ }
19
+ export interface CompiledQueryErrorOptions {
20
+ readonly queryId?: string;
21
+ /** Non-public cause retained for local logging; never serialized into the envelope. */
22
+ readonly cause?: unknown;
23
+ }
24
+ /**
25
+ * The only execution-failure shape a runtime may surface for a compiled query. For
26
+ * server-fault categories the caller-facing message is fixed to a generic string so no
27
+ * adapter text, SQL, value, or tenant identifier can leak.
28
+ */
29
+ export declare class CompiledQueryError extends Error {
30
+ readonly category: CompiledErrorCategory;
31
+ readonly queryId?: string;
32
+ readonly cause?: unknown;
33
+ constructor(category: CompiledErrorCategory, message: string, options?: CompiledQueryErrorOptions);
34
+ private static resolveMessage;
35
+ /** The redacted, serializable envelope. Only closed fields; no `cause`, no stack. */
36
+ toEnvelope(): CompiledErrorEnvelope;
37
+ }
38
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/core/compiled/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,oKAW5B,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAoB/E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAKtF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAE9E;AAED,iEAAiE;AACjE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAGhC,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,yBAA8B;IAUzC,OAAO,CAAC,MAAM,CAAC,cAAc;IAY7B,qFAAqF;IACrF,UAAU,IAAI,qBAAqB;CAKpC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Public execution-failure envelope from RFC 0010 §Error envelope.
3
+ *
4
+ * The category set is closed and stable within version 1. It matches the frozen set in
5
+ * `@hypequery/protocol` (`events` module) so runtime failures and emitted diagnostics
6
+ * speak the same vocabulary. New categories require a new contract version.
7
+ */
8
+ export const COMPILED_ERROR_CATEGORIES = [
9
+ 'input-invalid',
10
+ 'unauthenticated',
11
+ 'forbidden',
12
+ 'tenant-required',
13
+ 'not-found',
14
+ 'too-large',
15
+ 'aborted',
16
+ 'deadline-exceeded',
17
+ 'unavailable',
18
+ 'internal',
19
+ ];
20
+ /**
21
+ * Categories that describe a client-supplied fault. Their messages MAY carry a safe,
22
+ * caller-facing explanation. Every other category is a server/dependency fault whose
23
+ * message MUST NOT expose adapter error text, SQL, values, or tenant identifiers.
24
+ */
25
+ const CLIENT_FAULT_CATEGORIES = new Set([
26
+ 'input-invalid',
27
+ 'unauthenticated',
28
+ 'forbidden',
29
+ 'tenant-required',
30
+ 'not-found',
31
+ 'too-large',
32
+ 'aborted',
33
+ 'deadline-exceeded',
34
+ ]);
35
+ const SAFE_MESSAGE_PATTERN = /[\r\n\t]/;
36
+ export function isCompiledErrorCategory(value) {
37
+ return (typeof value === 'string' &&
38
+ COMPILED_ERROR_CATEGORIES.includes(value));
39
+ }
40
+ export function isClientFaultCategory(category) {
41
+ return CLIENT_FAULT_CATEGORIES.has(category);
42
+ }
43
+ /**
44
+ * The only execution-failure shape a runtime may surface for a compiled query. For
45
+ * server-fault categories the caller-facing message is fixed to a generic string so no
46
+ * adapter text, SQL, value, or tenant identifier can leak.
47
+ */
48
+ export class CompiledQueryError extends Error {
49
+ category;
50
+ queryId;
51
+ cause;
52
+ constructor(category, message, options = {}) {
53
+ const safeMessage = CompiledQueryError.resolveMessage(category, message);
54
+ super(safeMessage);
55
+ this.name = 'CompiledQueryError';
56
+ this.category = category;
57
+ this.queryId = options.queryId;
58
+ this.cause = options.cause;
59
+ }
60
+ static resolveMessage(category, message) {
61
+ if (!isClientFaultCategory(category)) {
62
+ // Server-fault categories never carry a caller-authored message.
63
+ return DEFAULT_SERVER_FAULT_MESSAGE[category] ?? 'The request could not be completed.';
64
+ }
65
+ const trimmed = typeof message === 'string' ? message.trim() : '';
66
+ if (trimmed.length === 0 || SAFE_MESSAGE_PATTERN.test(trimmed)) {
67
+ return DEFAULT_CLIENT_FAULT_MESSAGE[category] ?? 'The request was rejected.';
68
+ }
69
+ return trimmed;
70
+ }
71
+ /** The redacted, serializable envelope. Only closed fields; no `cause`, no stack. */
72
+ toEnvelope() {
73
+ return this.queryId === undefined
74
+ ? { category: this.category, message: this.message }
75
+ : { category: this.category, message: this.message, queryId: this.queryId };
76
+ }
77
+ }
78
+ const DEFAULT_CLIENT_FAULT_MESSAGE = {
79
+ 'input-invalid': 'The request parameters were invalid.',
80
+ unauthenticated: 'Authentication is required.',
81
+ forbidden: 'Access is denied.',
82
+ 'tenant-required': 'A tenant context is required.',
83
+ 'not-found': 'The requested resource was not found.',
84
+ 'too-large': 'The request or result exceeded an allowed bound.',
85
+ aborted: 'The request was cancelled.',
86
+ 'deadline-exceeded': 'The request deadline was exceeded.',
87
+ };
88
+ const DEFAULT_SERVER_FAULT_MESSAGE = {
89
+ unavailable: 'The executor is temporarily unavailable.',
90
+ internal: 'The request could not be completed.',
91
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CompiledQuery v1 (RFC 0010) — the versioned execution-request contract for the
3
+ * ClickHouse runtime, introduced beside the legacy positional path. See `./types.ts`.
4
+ *
5
+ * CH-01 provides the shape, validation, and redacted debug/error surfaces. Wiring the real
6
+ * `@clickhouse/client` `{name:Type}` + `query_params` transport, capability negotiation,
7
+ * and end-to-end cancellation is CH-02+ and does not touch the legacy adapter signature.
8
+ */
9
+ export { COMPILED_QUERY_VERSION, type CompiledDeadline, type CompiledDebugForm, type CompiledIdentifiers, type CompiledOperation, type CompiledParameterBindings, type CompiledParameterDeclaration, type CompiledParameterType, type CompiledParameterValue, type CompiledQueryV1, type CompiledSensitivity, type CompiledSettings, } from './types.js';
10
+ export { compileQueryV1, type CompileQueryInput } from './compile.js';
11
+ export { assertNoValuesInSql, buildParameterBindings, extractReferencedParameters, validateParameterReferences, } from './parameters.js';
12
+ export { COMPILED_SETTING_BOUNDS, type CompiledSettingName, type DeadlineInputs, type SettingBound, resolveCompiledDeadline, resolveCompiledSettings, } from './settings.js';
13
+ export { COMPILED_ERROR_CATEGORIES, CompiledQueryError, type CompiledErrorCategory, type CompiledErrorEnvelope, type CompiledQueryErrorOptions, isClientFaultCategory, isCompiledErrorCategory, } from './errors.js';
14
+ export { buildDebugForm } from './debug.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/compiled/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,uBAAuB,EACvB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * CompiledQuery v1 (RFC 0010) — the versioned execution-request contract for the
3
+ * ClickHouse runtime, introduced beside the legacy positional path. See `./types.ts`.
4
+ *
5
+ * CH-01 provides the shape, validation, and redacted debug/error surfaces. Wiring the real
6
+ * `@clickhouse/client` `{name:Type}` + `query_params` transport, capability negotiation,
7
+ * and end-to-end cancellation is CH-02+ and does not touch the legacy adapter signature.
8
+ */
9
+ export { COMPILED_QUERY_VERSION, } from './types.js';
10
+ export { compileQueryV1 } from './compile.js';
11
+ export { assertNoValuesInSql, buildParameterBindings, extractReferencedParameters, validateParameterReferences, } from './parameters.js';
12
+ export { COMPILED_SETTING_BOUNDS, resolveCompiledDeadline, resolveCompiledSettings, } from './settings.js';
13
+ export { COMPILED_ERROR_CATEGORIES, CompiledQueryError, isClientFaultCategory, isCompiledErrorCategory, } from './errors.js';
14
+ export { buildDebugForm } from './debug.js';
@@ -0,0 +1,28 @@
1
+ import type { CompiledParameterBindings, CompiledParameterDeclaration, CompiledParameterValue } from './types.js';
2
+ /** Extract the set of parameter names a SQL text references via `{name:Type}`. */
3
+ export declare function extractReferencedParameters(sql: string): Set<string>;
4
+ export declare function replaceParameterPlaceholders(sql: string, replace: (name: string, type: string) => string): string;
5
+ /**
6
+ * Validate that the SQL only references declared parameters. Fails closed when a
7
+ * placeholder names an undeclared parameter (RFC 0010 §Parameters).
8
+ */
9
+ export declare function validateParameterReferences(sql: string, declarations: readonly CompiledParameterDeclaration[]): void;
10
+ /**
11
+ * Resolve supplied values against declarations into the native `{name: value}` bindings
12
+ * an adapter binds to server parameters. Fail-closed rules (RFC 0010 §Parameters):
13
+ * - a supplied name that is not declared is rejected;
14
+ * - a required declared name with no supplied value is rejected;
15
+ * - an optional declared name may be absent;
16
+ * - every supplied value is validated (RFC 0001 for tagged values).
17
+ *
18
+ * No value is ever concatenated into SQL text: values live only in the returned bindings.
19
+ */
20
+ export declare function buildParameterBindings(declarations: readonly CompiledParameterDeclaration[], values: Readonly<Record<string, CompiledParameterValue>>): CompiledParameterBindings;
21
+ /**
22
+ * Assert the invariant that no bound value has leaked into the SQL text. The compile path
23
+ * never substitutes values, so this is a defense-in-depth check: the SQL must reference
24
+ * every non-optional bound name through a placeholder and must not be the legacy
25
+ * positional form (`?`).
26
+ */
27
+ export declare function assertNoValuesInSql(sql: string, bindings: CompiledParameterBindings): void;
28
+ //# sourceMappingURL=parameters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../../src/core/compiled/parameters.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,yBAAyB,EACzB,4BAA4B,EAC5B,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAsIpB,kFAAkF;AAClF,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAEpE;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,GAC9C,MAAM,CAUR;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,SAAS,4BAA4B,EAAE,GACpD,IAAI,CAoBN;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,SAAS,4BAA4B,EAAE,EACrD,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,GACvD,yBAAyB,CAyC3B;AAmFD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,yBAAyB,GAClC,IAAI,CAyBN"}
@@ -0,0 +1,282 @@
1
+ import { ProtocolValueError, isProtocolIdentifier, validateCanonicalValue, } from '@hypequery/protocol';
2
+ import { CompiledQueryError } from './errors.js';
3
+ const LOGICAL_TYPES = new Set([
4
+ 'array', 'boolean', 'bytes', 'date', 'datetime', 'decimal', 'enum', 'float',
5
+ 'integer', 'map', 'null', 'string', 'tuple', 'uuid',
6
+ ]);
7
+ function skipQuoted(sql, start, quote) {
8
+ let index = start + 1;
9
+ while (index < sql.length) {
10
+ if (sql[index] === '\\') {
11
+ index += 2;
12
+ continue;
13
+ }
14
+ if (sql[index] === quote) {
15
+ if (sql[index + 1] === quote) {
16
+ index += 2;
17
+ continue;
18
+ }
19
+ return index + 1;
20
+ }
21
+ index += 1;
22
+ }
23
+ return sql.length;
24
+ }
25
+ function parsePlaceholder(sql, start) {
26
+ let index = start + 1;
27
+ while (/\s/.test(sql[index] ?? ''))
28
+ index += 1;
29
+ const nameStart = index;
30
+ if (!/[A-Za-z_]/.test(sql[index] ?? ''))
31
+ return undefined;
32
+ index += 1;
33
+ while (/[A-Za-z0-9_]/.test(sql[index] ?? ''))
34
+ index += 1;
35
+ const name = sql.slice(nameStart, index);
36
+ while (/\s/.test(sql[index] ?? ''))
37
+ index += 1;
38
+ if (sql[index] !== ':')
39
+ return undefined;
40
+ index += 1;
41
+ const typeStart = index;
42
+ let quote;
43
+ let parenthesisDepth = 0;
44
+ while (index < sql.length) {
45
+ const character = sql[index];
46
+ if (quote) {
47
+ if (character === '\\') {
48
+ index += 2;
49
+ continue;
50
+ }
51
+ if (character === quote) {
52
+ if (sql[index + 1] === quote) {
53
+ index += 2;
54
+ continue;
55
+ }
56
+ quote = undefined;
57
+ }
58
+ index += 1;
59
+ continue;
60
+ }
61
+ if (character === "'" || character === '"' || character === '`') {
62
+ quote = character;
63
+ index += 1;
64
+ continue;
65
+ }
66
+ if (character === '(')
67
+ parenthesisDepth += 1;
68
+ if (character === ')') {
69
+ parenthesisDepth -= 1;
70
+ if (parenthesisDepth < 0)
71
+ return undefined;
72
+ }
73
+ if (character === '{')
74
+ return undefined;
75
+ if (character === '}' && parenthesisDepth === 0) {
76
+ const type = sql.slice(typeStart, index).trim();
77
+ if (type.length === 0)
78
+ return undefined;
79
+ return { name, type, start, end: index + 1 };
80
+ }
81
+ index += 1;
82
+ }
83
+ return undefined;
84
+ }
85
+ function scanSqlParameters(sql) {
86
+ const references = [];
87
+ let hasPositionalPlaceholder = false;
88
+ let index = 0;
89
+ while (index < sql.length) {
90
+ const character = sql[index];
91
+ if (character === "'" || character === '"' || character === '`') {
92
+ index = skipQuoted(sql, index, character);
93
+ continue;
94
+ }
95
+ if (character === '-' && sql[index + 1] === '-') {
96
+ const newline = sql.indexOf('\n', index + 2);
97
+ index = newline === -1 ? sql.length : newline + 1;
98
+ continue;
99
+ }
100
+ if (character === '#') {
101
+ const newline = sql.indexOf('\n', index + 1);
102
+ index = newline === -1 ? sql.length : newline + 1;
103
+ continue;
104
+ }
105
+ if (character === '/' && sql[index + 1] === '*') {
106
+ const close = sql.indexOf('*/', index + 2);
107
+ index = close === -1 ? sql.length : close + 2;
108
+ continue;
109
+ }
110
+ if (character === '?')
111
+ hasPositionalPlaceholder = true;
112
+ if (character === '{') {
113
+ const reference = parsePlaceholder(sql, index);
114
+ if (reference) {
115
+ references.push(reference);
116
+ index = reference.end;
117
+ continue;
118
+ }
119
+ }
120
+ index += 1;
121
+ }
122
+ return { references, hasPositionalPlaceholder };
123
+ }
124
+ /** Extract the set of parameter names a SQL text references via `{name:Type}`. */
125
+ export function extractReferencedParameters(sql) {
126
+ return new Set(scanSqlParameters(sql).references.map(({ name }) => name));
127
+ }
128
+ export function replaceParameterPlaceholders(sql, replace) {
129
+ const references = scanSqlParameters(sql).references;
130
+ let result = '';
131
+ let offset = 0;
132
+ for (const reference of references) {
133
+ result += sql.slice(offset, reference.start);
134
+ result += replace(reference.name, reference.type);
135
+ offset = reference.end;
136
+ }
137
+ return result + sql.slice(offset);
138
+ }
139
+ /**
140
+ * Validate that the SQL only references declared parameters. Fails closed when a
141
+ * placeholder names an undeclared parameter (RFC 0010 §Parameters).
142
+ */
143
+ export function validateParameterReferences(sql, declarations) {
144
+ const declared = new Map(declarations.map((declaration) => [
145
+ declaration.name,
146
+ declaration,
147
+ ]));
148
+ for (const reference of scanSqlParameters(sql).references) {
149
+ const declaration = declared.get(reference.name);
150
+ if (!declaration) {
151
+ throw new CompiledQueryError('input-invalid', `SQL references undeclared parameter ${reference.name}.`);
152
+ }
153
+ if (reference.type !== declaration.type.clickHouseType) {
154
+ throw new CompiledQueryError('input-invalid', `SQL parameter ${reference.name} does not match its declared ClickHouse type.`);
155
+ }
156
+ }
157
+ }
158
+ /**
159
+ * Resolve supplied values against declarations into the native `{name: value}` bindings
160
+ * an adapter binds to server parameters. Fail-closed rules (RFC 0010 §Parameters):
161
+ * - a supplied name that is not declared is rejected;
162
+ * - a required declared name with no supplied value is rejected;
163
+ * - an optional declared name may be absent;
164
+ * - every supplied value is validated (RFC 0001 for tagged values).
165
+ *
166
+ * No value is ever concatenated into SQL text: values live only in the returned bindings.
167
+ */
168
+ export function buildParameterBindings(declarations, values) {
169
+ const declaredByName = new Map();
170
+ for (const declaration of declarations) {
171
+ if (!isProtocolIdentifier(declaration.name)) {
172
+ throw new CompiledQueryError('input-invalid', 'Parameter declaration has an invalid name.');
173
+ }
174
+ if (declaredByName.has(declaration.name)) {
175
+ throw new CompiledQueryError('input-invalid', `Duplicate parameter declaration ${declaration.name}.`);
176
+ }
177
+ declaredByName.set(declaration.name, declaration);
178
+ }
179
+ for (const suppliedName of Object.keys(values)) {
180
+ if (!declaredByName.has(suppliedName)) {
181
+ throw new CompiledQueryError('input-invalid', `Value supplied for undeclared parameter ${suppliedName}.`);
182
+ }
183
+ }
184
+ const bindings = {};
185
+ for (const [name, declaration] of declaredByName) {
186
+ const present = Object.prototype.hasOwnProperty.call(values, name);
187
+ if (!present) {
188
+ if (declaration.optional)
189
+ continue;
190
+ throw new CompiledQueryError('input-invalid', `Required parameter ${name} is missing.`);
191
+ }
192
+ bindings[name] = validateParameterValue(name, declaration, values[name]);
193
+ }
194
+ return Object.freeze(bindings);
195
+ }
196
+ function validateParameterValue(name, declaration, value) {
197
+ try {
198
+ const validated = validateCanonicalValue(value, {
199
+ declaredClickHouseType: declaration.type.clickHouseType,
200
+ });
201
+ validateLogicalType(name, declaration, validated);
202
+ return validated;
203
+ }
204
+ catch (error) {
205
+ if (error instanceof ProtocolValueError) {
206
+ throw new CompiledQueryError('input-invalid', `Parameter ${name} failed value validation (${error.code}).`, { cause: error });
207
+ }
208
+ throw error;
209
+ }
210
+ }
211
+ function logicalTypeOf(value) {
212
+ if (value === null)
213
+ return 'null';
214
+ if (typeof value === 'string')
215
+ return 'string';
216
+ if (typeof value === 'number')
217
+ return 'float';
218
+ if (typeof value === 'boolean')
219
+ return 'boolean';
220
+ return value.$hypequery.type;
221
+ }
222
+ function unwrapNullable(type) {
223
+ const trimmed = type.trim();
224
+ if (trimmed.startsWith('Nullable(') && trimmed.endsWith(')')) {
225
+ return { nullable: true, inner: trimmed.slice(9, -1).trim() };
226
+ }
227
+ return { nullable: false, inner: trimmed };
228
+ }
229
+ function clickHouseTypeSupportsLogical(type, logical) {
230
+ const { nullable, inner } = unwrapNullable(type);
231
+ if (logical === 'null')
232
+ return nullable;
233
+ switch (logical) {
234
+ case 'string': return /^(?:String|FixedString\(\d+\)|LowCardinality\(String\))$/.test(inner);
235
+ case 'float': return /^Float(?:32|64)$/.test(inner);
236
+ case 'boolean': return /^(?:Bool|Boolean)$/.test(inner);
237
+ case 'integer': return /^(?:U?Int)(?:8|16|32|64|128|256)$/.test(inner);
238
+ case 'decimal': return /^Decimal(?:(?:32|64|128|256)\(\d+\)|\(\d+\s*,\s*\d+\))$/.test(inner);
239
+ case 'date': return /^(?:Date|Date32)$/.test(inner);
240
+ case 'datetime': return /^DateTime(?:64)?(?:\(.*\))?$/.test(inner);
241
+ case 'uuid': return inner === 'UUID';
242
+ case 'bytes': return /^(?:String|FixedString\(\d+\))$/.test(inner);
243
+ case 'enum': return /^Enum(?:8|16)\(.*\)$/.test(inner);
244
+ case 'array': return /^Array\(.+\)$/.test(inner);
245
+ case 'tuple': return /^Tuple\(.+\)$/.test(inner);
246
+ case 'map': return /^Map\(.+\)$/.test(inner);
247
+ default: return false;
248
+ }
249
+ }
250
+ function validateLogicalType(name, declaration, value) {
251
+ const actual = logicalTypeOf(value);
252
+ const declared = declaration.type.logical;
253
+ if (!LOGICAL_TYPES.has(declared) || (actual !== declared && actual !== 'null')) {
254
+ throw new CompiledQueryError('input-invalid', `Parameter ${name} does not match its declared logical type.`);
255
+ }
256
+ if (!clickHouseTypeSupportsLogical(declaration.type.clickHouseType, actual)) {
257
+ throw new CompiledQueryError('input-invalid', `Parameter ${name} does not match its declared ClickHouse type.`);
258
+ }
259
+ }
260
+ /**
261
+ * Assert the invariant that no bound value has leaked into the SQL text. The compile path
262
+ * never substitutes values, so this is a defense-in-depth check: the SQL must reference
263
+ * every non-optional bound name through a placeholder and must not be the legacy
264
+ * positional form (`?`).
265
+ */
266
+ export function assertNoValuesInSql(sql, bindings) {
267
+ const scan = scanSqlParameters(sql);
268
+ if (scan.hasPositionalPlaceholder) {
269
+ throw new CompiledQueryError('input-invalid', 'Compiled SQL must not use positional placeholders.');
270
+ }
271
+ const referenced = new Set(scan.references.map(({ name }) => name));
272
+ for (const name of Object.keys(bindings)) {
273
+ if (!referenced.has(name)) {
274
+ throw new CompiledQueryError('input-invalid', `Bound parameter ${name} is not referenced by the SQL.`);
275
+ }
276
+ }
277
+ for (const name of referenced) {
278
+ if (!Object.prototype.hasOwnProperty.call(bindings, name)) {
279
+ throw new CompiledQueryError('input-invalid', `SQL parameter ${name} does not have a bound value.`);
280
+ }
281
+ }
282
+ }
@@ -0,0 +1,49 @@
1
+ import type { CompiledDeadline, CompiledSettings } from './types.js';
2
+ /**
3
+ * Closed, typed settings allow-list (RFC 0010 §Settings). Each entry defines an inclusive
4
+ * range; products may TIGHTEN a range but never loosen it. Settings originate only from
5
+ * trusted components — a request can never set, override, or relax them.
6
+ */
7
+ export interface SettingBound {
8
+ readonly min: number;
9
+ readonly max: number;
10
+ }
11
+ export declare const COMPILED_SETTING_BOUNDS: Readonly<{
12
+ readonly maxExecutionMs: {
13
+ readonly min: 1;
14
+ readonly max: 3600000;
15
+ };
16
+ readonly maxResultRows: {
17
+ readonly min: 0;
18
+ readonly max: 1000000000000;
19
+ };
20
+ readonly maxResultBytes: {
21
+ readonly min: 0;
22
+ readonly max: 1099511627776;
23
+ };
24
+ }>;
25
+ export type CompiledSettingName = keyof typeof COMPILED_SETTING_BOUNDS;
26
+ /**
27
+ * Clamp trusted settings into the allow-list. A value outside the closed range is
28
+ * rejected fail-closed rather than silently coerced, since settings are trusted input and
29
+ * an out-of-range value signals a policy bug, not caller data.
30
+ */
31
+ export declare function resolveCompiledSettings(input: CompiledSettings): CompiledSettings;
32
+ export interface DeadlineInputs {
33
+ /** Absolute caller-supplied deadline, epoch-millis. */
34
+ readonly callerAtEpochMs?: number;
35
+ /** Policy-derived maximum window from `now`, milliseconds. */
36
+ readonly policyMaxMs?: number;
37
+ /** Current time, epoch-millis. Injected so resolution stays deterministic/testable. */
38
+ readonly nowEpochMs: number;
39
+ }
40
+ /**
41
+ * Resolve the effective deadline (RFC 0010 §Deadline and cancellation precedence).
42
+ *
43
+ * The effective deadline is the EARLIER of the caller-supplied deadline and the
44
+ * policy-derived maximum — a caller can shorten but never extend the window. A supplied
45
+ * deadline at or before `now` fails immediately with `deadline-exceeded` rather than being
46
+ * extended or ignored.
47
+ */
48
+ export declare function resolveCompiledDeadline(inputs: DeadlineInputs): CompiledDeadline | undefined;
49
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/core/compiled/settings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;EAI8B,CAAC;AAEnE,MAAM,MAAM,mBAAmB,GAAG,MAAM,OAAO,uBAAuB,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,CAejF;AAED,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,uFAAuF;IACvF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,GAAG,gBAAgB,GAAG,SAAS,CAyC5F"}
@@ -0,0 +1,65 @@
1
+ import { CompiledQueryError } from './errors.js';
2
+ export const COMPILED_SETTING_BOUNDS = Object.freeze({
3
+ maxExecutionMs: { min: 1, max: 3_600_000 },
4
+ maxResultRows: { min: 0, max: 1_000_000_000_000 },
5
+ maxResultBytes: { min: 0, max: 1_099_511_627_776 },
6
+ });
7
+ /**
8
+ * Clamp trusted settings into the allow-list. A value outside the closed range is
9
+ * rejected fail-closed rather than silently coerced, since settings are trusted input and
10
+ * an out-of-range value signals a policy bug, not caller data.
11
+ */
12
+ export function resolveCompiledSettings(input) {
13
+ const resolved = {};
14
+ for (const key of Object.keys(COMPILED_SETTING_BOUNDS)) {
15
+ const value = input[key];
16
+ if (value === undefined)
17
+ continue;
18
+ const bound = COMPILED_SETTING_BOUNDS[key];
19
+ if (!Number.isInteger(value) || value < bound.min || value > bound.max) {
20
+ throw new CompiledQueryError('input-invalid', `Setting ${key} is outside its allowed range.`);
21
+ }
22
+ resolved[key] = value;
23
+ }
24
+ return Object.freeze(resolved);
25
+ }
26
+ /**
27
+ * Resolve the effective deadline (RFC 0010 §Deadline and cancellation precedence).
28
+ *
29
+ * The effective deadline is the EARLIER of the caller-supplied deadline and the
30
+ * policy-derived maximum — a caller can shorten but never extend the window. A supplied
31
+ * deadline at or before `now` fails immediately with `deadline-exceeded` rather than being
32
+ * extended or ignored.
33
+ */
34
+ export function resolveCompiledDeadline(inputs) {
35
+ const { callerAtEpochMs, policyMaxMs, nowEpochMs } = inputs;
36
+ if (!Number.isSafeInteger(nowEpochMs) || nowEpochMs < 0) {
37
+ throw new CompiledQueryError('input-invalid', 'The current time is invalid.');
38
+ }
39
+ if (callerAtEpochMs !== undefined
40
+ && (!Number.isSafeInteger(callerAtEpochMs) || callerAtEpochMs < 0)) {
41
+ throw new CompiledQueryError('input-invalid', 'The supplied deadline is invalid.');
42
+ }
43
+ if (policyMaxMs !== undefined && (!Number.isSafeInteger(policyMaxMs) || policyMaxMs <= 0)) {
44
+ throw new CompiledQueryError('input-invalid', 'The policy deadline window is invalid.');
45
+ }
46
+ const policyAt = policyMaxMs === undefined ? undefined : nowEpochMs + policyMaxMs;
47
+ if (policyAt !== undefined && !Number.isSafeInteger(policyAt)) {
48
+ throw new CompiledQueryError('input-invalid', 'The policy deadline is outside the safe range.');
49
+ }
50
+ if (callerAtEpochMs !== undefined && callerAtEpochMs <= nowEpochMs) {
51
+ throw new CompiledQueryError('deadline-exceeded', 'The supplied deadline is at or before the current time.');
52
+ }
53
+ if (callerAtEpochMs === undefined && policyAt === undefined) {
54
+ return undefined;
55
+ }
56
+ if (callerAtEpochMs === undefined) {
57
+ return Object.freeze({ atEpochMs: policyAt, source: 'policy' });
58
+ }
59
+ if (policyAt === undefined) {
60
+ return Object.freeze({ atEpochMs: callerAtEpochMs, source: 'caller' });
61
+ }
62
+ return Object.freeze(callerAtEpochMs <= policyAt
63
+ ? { atEpochMs: callerAtEpochMs, source: 'caller' }
64
+ : { atEpochMs: policyAt, source: 'policy' });
65
+ }
@@ -0,0 +1,115 @@
1
+ import type { ProtocolIdentifier, TaggedValue } from '@hypequery/protocol';
2
+ /**
3
+ * Execution-request contract from RFC 0010 (compiled query, error, cancellation),
4
+ * realized for the ClickHouse runtime.
5
+ *
6
+ * This is the versioned shape a runtime hands to an adapter. It sits *beside* the
7
+ * legacy positional path (`adapter.query(sql, params: unknown[])`, which renders
8
+ * values into SQL text via `substituteParameters`). Nothing here lets a request
9
+ * author SQL, tenant proof, or settings — those are trusted build/policy output.
10
+ *
11
+ * NOTE: distinct from the internal `CompiledQuery` in `../../types/base.ts`, which
12
+ * is the SQL-formatter fragment `{ query, parameters }`.
13
+ */
14
+ export declare const COMPILED_QUERY_VERSION: 1;
15
+ /** Closed operation set (RFC 0010 §Operations). The operation belongs to the compiled
16
+ * query, never to the request. */
17
+ export type CompiledOperation = 'query' | 'command' | 'insert';
18
+ /**
19
+ * A logical parameter type. The logical tag drives validation and the `{name:Type}`
20
+ * placeholder the adapter sends; `clickHouseType` is the concrete server type string
21
+ * (e.g. `UInt64`, `DateTime64(3, 'UTC')`, `Array(String)`).
22
+ */
23
+ export interface CompiledParameterType {
24
+ /** RFC 0001 logical tag, or a scalar shorthand for native JSON scalars. */
25
+ readonly logical: TaggedValue['$hypequery']['type'] | 'boolean' | 'string' | 'float' | 'null';
26
+ /** Concrete ClickHouse server type used to build the native placeholder. */
27
+ readonly clickHouseType: string;
28
+ }
29
+ /**
30
+ * A named, typed parameter declaration carried beside the SQL text. A request supplies
31
+ * only values for declared names; it can neither add names nor change types.
32
+ */
33
+ export interface CompiledParameterDeclaration {
34
+ readonly name: ProtocolIdentifier;
35
+ readonly type: CompiledParameterType;
36
+ /** Optional parameters may be absent from a request; required ones fail closed. */
37
+ readonly optional: boolean;
38
+ }
39
+ /** A supplied parameter value: an RFC 0001 tagged value or a native JSON scalar. */
40
+ export type CompiledParameterValue = TaggedValue | string | number | boolean | null;
41
+ /**
42
+ * The resolved `{name: value}` map the adapter binds to native server parameters.
43
+ * Every key is a declared parameter name; no value is ever rendered into SQL text.
44
+ */
45
+ export type CompiledParameterBindings = Readonly<Record<string, CompiledParameterValue>>;
46
+ /**
47
+ * Data sensitivity metadata. Marks whether the query touches tenant-scoped or otherwise
48
+ * sensitive data so diagnostics/redaction downstream can act without inspecting values.
49
+ */
50
+ export interface CompiledSensitivity {
51
+ /** The compiled SQL already contains trusted tenant predicates (RFC 0010 §Operations). */
52
+ readonly tenantScoped: boolean;
53
+ /** Free-form trusted classification labels (e.g. 'pii'); never request-supplied. */
54
+ readonly labels: readonly string[];
55
+ }
56
+ /**
57
+ * Bounded settings the runtime applies per execution. These originate only from trusted
58
+ * components; a request can never set, override, or relax them. See `settings.ts` for the
59
+ * closed allow-list and ranges.
60
+ */
61
+ export interface CompiledSettings {
62
+ /** Wall-clock ceiling for server-side execution, milliseconds. Always enforced. */
63
+ readonly maxExecutionMs?: number;
64
+ /** Maximum rows the result may contain. */
65
+ readonly maxResultRows?: number;
66
+ /** Maximum bytes the result may contain. */
67
+ readonly maxResultBytes?: number;
68
+ }
69
+ /** Effective deadline + cancellation inputs (RFC 0010 §Deadline and cancellation). */
70
+ export interface CompiledDeadline {
71
+ /** Epoch-millis absolute deadline. Earlier of caller-supplied and policy-derived. */
72
+ readonly atEpochMs: number;
73
+ /** Which side set the effective deadline, for honest diagnostics. */
74
+ readonly source: 'caller' | 'policy';
75
+ }
76
+ /** Authoritative + optional correlation identifiers (RFC 0010 §Query identifier). */
77
+ export interface CompiledIdentifiers {
78
+ /** Server-generated, unique per execution, unguessable, safe for logs/cache metadata. */
79
+ readonly queryId: string;
80
+ /** Caller-supplied, non-authoritative, ≤1024 UTF-8 bytes, no control chars; never
81
+ * influences routing, cache keys, or authorization. */
82
+ readonly correlationId?: string;
83
+ }
84
+ /**
85
+ * Redacted, non-executable debug form (RFC 0010 §Debug form). Shows SQL structure with
86
+ * placeholders and declared types; carries no values, tenant values, credentials, or
87
+ * settings beyond their names. `sql` here is deliberately not valid database SQL.
88
+ */
89
+ export interface CompiledDebugForm {
90
+ readonly sql: string;
91
+ readonly parameters: readonly {
92
+ readonly name: string;
93
+ readonly type: string;
94
+ readonly optional: boolean;
95
+ }[];
96
+ readonly settings: readonly string[];
97
+ }
98
+ /**
99
+ * The compiled query: the only way a runtime asks a ClickHouse adapter to execute.
100
+ */
101
+ export interface CompiledQueryV1 {
102
+ readonly version: typeof COMPILED_QUERY_VERSION;
103
+ readonly operation: CompiledOperation;
104
+ /** Trusted build/server output. Callers influence execution only via `bindings`. */
105
+ readonly sql: string;
106
+ readonly parameters: readonly CompiledParameterDeclaration[];
107
+ /** Resolved values for declared names, bound to native server parameters. */
108
+ readonly bindings: CompiledParameterBindings;
109
+ readonly settings: CompiledSettings;
110
+ readonly identifiers: CompiledIdentifiers;
111
+ readonly deadline?: CompiledDeadline;
112
+ readonly sensitivity: CompiledSensitivity;
113
+ readonly debug: CompiledDebugForm;
114
+ }
115
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/compiled/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Execution-request contract from RFC 0010 (compiled query, error, cancellation),
3
+ * realized for the ClickHouse runtime.
4
+ *
5
+ * This is the versioned shape a runtime hands to an adapter. It sits *beside* the
6
+ * legacy positional path (`adapter.query(sql, params: unknown[])`, which renders
7
+ * values into SQL text via `substituteParameters`). Nothing here lets a request
8
+ * author SQL, tenant proof, or settings — those are trusted build/policy output.
9
+ *
10
+ * NOTE: distinct from the internal `CompiledQuery` in `../../types/base.ts`, which
11
+ * is the SQL-formatter fragment `{ query, parameters }`.
12
+ */
13
+ export const COMPILED_QUERY_VERSION = 1;
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export type { SqlDialect } from './core/dialects/sql-dialect.js';
12
12
  export type { ClickHouseConfig, ClickHouseClientConfig, CreateQueryBuilderConfig, ExecuteOptions } from './core/query-builder.js';
13
13
  export { isClientConfig } from './core/query-builder.js';
14
14
  export { substituteParameters, escapeValue } from './core/utils.js';
15
+ export * from './core/compiled/index.js';
15
16
  export type { CacheOptions, CacheConfig, CacheProvider, CacheEntry, CacheStatus } from './core/cache/types.js';
16
17
  export { CacheController } from './core/cache/controller.js';
17
18
  export { MemoryCacheProvider } from './core/cache/providers/memory-lru.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -9,6 +9,11 @@ export { isClientConfig } from './core/query-builder.js';
9
9
  // SQL rendering used by the built-in adapter; exported so third-party DatabaseAdapter
10
10
  // implementations (e.g. embedded engines) reproduce identical ?-param rendering.
11
11
  export { substituteParameters, escapeValue } from './core/utils.js';
12
+ // CompiledQuery v1 (RFC 0010) — versioned execution-request contract with named typed
13
+ // parameters, closed operations/settings, authoritative ids, deadlines, a redacted debug
14
+ // form, and the public error envelope. Introduced beside the legacy ?-param path (CH-01);
15
+ // the built-in adapter transport is wired in a later change.
16
+ export * from './core/compiled/index.js';
12
17
  export { CacheController } from './core/cache/controller.js';
13
18
  export { MemoryCacheProvider } from './core/cache/providers/memory-lru.js';
14
19
  export { MemoryCacheProvider as MemoryLRUCacheProvider } from './core/cache/providers/memory-lru.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/clickhouse",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "ClickHouse typescript query builder",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -35,7 +35,8 @@
35
35
  ],
36
36
  "dependencies": {
37
37
  "@clickhouse/client": "^1.18.3",
38
- "dotenv": "^16.0.0"
38
+ "dotenv": "^16.0.0",
39
+ "@hypequery/protocol": "0.9.0"
39
40
  },
40
41
  "peerDependencies": {
41
42
  "@clickhouse/client-web": "^0.2.0 || ^1.0.0",
@@ -61,7 +62,7 @@
61
62
  "typescript": "^5.7.3",
62
63
  "@vitest/coverage-v8": "^3.2.6",
63
64
  "vitest": "^3.2.6",
64
- "@hypequery/datasets": "0.10.0"
65
+ "@hypequery/datasets": "0.13.0"
65
66
  },
66
67
  "ts-node": {
67
68
  "esm": true,