camusdb 0.1.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 +21 -0
- package/README.md +950 -0
- package/dist/auth/credentials.d.ts +30 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +23 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/login-client.d.ts +37 -0
- package/dist/auth/login-client.d.ts.map +1 -0
- package/dist/auth/login-client.js +8 -0
- package/dist/auth/login-client.js.map +1 -0
- package/dist/auth/rest-login-client.d.ts +17 -0
- package/dist/auth/rest-login-client.d.ts.map +1 -0
- package/dist/auth/rest-login-client.js +71 -0
- package/dist/auth/rest-login-client.js.map +1 -0
- package/dist/auth/token-provider.d.ts +123 -0
- package/dist/auth/token-provider.d.ts.map +1 -0
- package/dist/auth/token-provider.js +209 -0
- package/dist/auth/token-provider.js.map +1 -0
- package/dist/backup.d.ts +98 -0
- package/dist/backup.d.ts.map +1 -0
- package/dist/backup.js +153 -0
- package/dist/backup.js.map +1 -0
- package/dist/cache.d.ts +90 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +121 -0
- package/dist/cache.js.map +1 -0
- package/dist/client.d.ts +406 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +724 -0
- package/dist/client.js.map +1 -0
- package/dist/column-type.d.ts +33 -0
- package/dist/column-type.d.ts.map +1 -0
- package/dist/column-type.js +50 -0
- package/dist/column-type.js.map +1 -0
- package/dist/column-value.d.ts +77 -0
- package/dist/column-value.d.ts.map +1 -0
- package/dist/column-value.js +60 -0
- package/dist/column-value.js.map +1 -0
- package/dist/config.d.ts +181 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +315 -0
- package/dist/config.js.map +1 -0
- package/dist/connection-string.d.ts +45 -0
- package/dist/connection-string.d.ts.map +1 -0
- package/dist/connection-string.js +170 -0
- package/dist/connection-string.js.map +1 -0
- package/dist/endpoint-pool.d.ts +70 -0
- package/dist/endpoint-pool.d.ts.map +1 -0
- package/dist/endpoint-pool.js +120 -0
- package/dist/endpoint-pool.js.map +1 -0
- package/dist/error-codes.d.ts +44 -0
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/error-codes.js +43 -0
- package/dist/error-codes.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +33 -0
- package/dist/errors.js.map +1 -0
- package/dist/hlc.d.ts +19 -0
- package/dist/hlc.d.ts.map +1 -0
- package/dist/hlc.js +11 -0
- package/dist/hlc.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +41 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +345 -0
- package/dist/json.js.map +1 -0
- package/dist/object-id.d.ts +39 -0
- package/dist/object-id.d.ts.map +1 -0
- package/dist/object-id.js +99 -0
- package/dist/object-id.js.map +1 -0
- package/dist/options.d.ts +77 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +68 -0
- package/dist/options.js.map +1 -0
- package/dist/prepared/binder.d.ts +20 -0
- package/dist/prepared/binder.d.ts.map +1 -0
- package/dist/prepared/binder.js +32 -0
- package/dist/prepared/binder.js.map +1 -0
- package/dist/prepared/policy.d.ts +81 -0
- package/dist/prepared/policy.d.ts.map +1 -0
- package/dist/prepared/policy.js +164 -0
- package/dist/prepared/policy.js.map +1 -0
- package/dist/query-stream.d.ts +55 -0
- package/dist/query-stream.d.ts.map +1 -0
- package/dist/query-stream.js +94 -0
- package/dist/query-stream.js.map +1 -0
- package/dist/result-set.d.ts +62 -0
- package/dist/result-set.d.ts.map +1 -0
- package/dist/result-set.js +100 -0
- package/dist/result-set.js.map +1 -0
- package/dist/retry.d.ts +38 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +93 -0
- package/dist/retry.js.map +1 -0
- package/dist/routing/advice.d.ts +63 -0
- package/dist/routing/advice.d.ts.map +1 -0
- package/dist/routing/advice.js +61 -0
- package/dist/routing/advice.js.map +1 -0
- package/dist/routing/route-cache.d.ts +53 -0
- package/dist/routing/route-cache.d.ts.map +1 -0
- package/dist/routing/route-cache.js +123 -0
- package/dist/routing/route-cache.js.map +1 -0
- package/dist/routing/router.d.ts +53 -0
- package/dist/routing/router.d.ts.map +1 -0
- package/dist/routing/router.js +89 -0
- package/dist/routing/router.js.map +1 -0
- package/dist/row-source.d.ts +48 -0
- package/dist/row-source.d.ts.map +1 -0
- package/dist/row-source.js +35 -0
- package/dist/row-source.js.map +1 -0
- package/dist/runtime.d.ts +58 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +137 -0
- package/dist/runtime.js.map +1 -0
- package/dist/shared-registry.d.ts +32 -0
- package/dist/shared-registry.d.ts.map +1 -0
- package/dist/shared-registry.js +48 -0
- package/dist/shared-registry.js.map +1 -0
- package/dist/sql-syntax.d.ts +44 -0
- package/dist/sql-syntax.d.ts.map +1 -0
- package/dist/sql-syntax.js +83 -0
- package/dist/sql-syntax.js.map +1 -0
- package/dist/statements.d.ts +15 -0
- package/dist/statements.d.ts.map +1 -0
- package/dist/statements.js +90 -0
- package/dist/statements.js.map +1 -0
- package/dist/transaction.d.ts +117 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +204 -0
- package/dist/transaction.js.map +1 -0
- package/dist/transport/authenticating-transport.d.ts +63 -0
- package/dist/transport/authenticating-transport.d.ts.map +1 -0
- package/dist/transport/authenticating-transport.js +119 -0
- package/dist/transport/authenticating-transport.js.map +1 -0
- package/dist/transport/branch-statements.d.ts +39 -0
- package/dist/transport/branch-statements.d.ts.map +1 -0
- package/dist/transport/branch-statements.js +74 -0
- package/dist/transport/branch-statements.js.map +1 -0
- package/dist/transport/error-text.d.ts +26 -0
- package/dist/transport/error-text.d.ts.map +1 -0
- package/dist/transport/error-text.js +75 -0
- package/dist/transport/error-text.js.map +1 -0
- package/dist/transport/grpc/batcher.d.ts +127 -0
- package/dist/transport/grpc/batcher.d.ts.map +1 -0
- package/dist/transport/grpc/batcher.js +399 -0
- package/dist/transport/grpc/batcher.js.map +1 -0
- package/dist/transport/grpc/codec.d.ts +40 -0
- package/dist/transport/grpc/codec.d.ts.map +1 -0
- package/dist/transport/grpc/codec.js +231 -0
- package/dist/transport/grpc/codec.js.map +1 -0
- package/dist/transport/grpc/grpc-transport.d.ts +115 -0
- package/dist/transport/grpc/grpc-transport.d.ts.map +1 -0
- package/dist/transport/grpc/grpc-transport.js +577 -0
- package/dist/transport/grpc/grpc-transport.js.map +1 -0
- package/dist/transport/grpc/messages.d.ts +221 -0
- package/dist/transport/grpc/messages.d.ts.map +1 -0
- package/dist/transport/grpc/messages.js +56 -0
- package/dist/transport/grpc/messages.js.map +1 -0
- package/dist/transport/grpc/proto.d.ts +71 -0
- package/dist/transport/grpc/proto.d.ts.map +1 -0
- package/dist/transport/grpc/proto.js +67 -0
- package/dist/transport/grpc/proto.js.map +1 -0
- package/dist/transport/http.d.ts +62 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +169 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/transport/ndjson-row-source.d.ts +38 -0
- package/dist/transport/ndjson-row-source.d.ts.map +1 -0
- package/dist/transport/ndjson-row-source.js +197 -0
- package/dist/transport/ndjson-row-source.js.map +1 -0
- package/dist/transport/rest-decode.d.ts +33 -0
- package/dist/transport/rest-decode.d.ts.map +1 -0
- package/dist/transport/rest-decode.js +162 -0
- package/dist/transport/rest-decode.js.map +1 -0
- package/dist/transport/rest-prepared-cache.d.ts +50 -0
- package/dist/transport/rest-prepared-cache.d.ts.map +1 -0
- package/dist/transport/rest-prepared-cache.js +101 -0
- package/dist/transport/rest-prepared-cache.js.map +1 -0
- package/dist/transport/rest-transport.d.ts +88 -0
- package/dist/transport/rest-transport.d.ts.map +1 -0
- package/dist/transport/rest-transport.js +388 -0
- package/dist/transport/rest-transport.js.map +1 -0
- package/dist/transport/transport-pool.d.ts +40 -0
- package/dist/transport/transport-pool.d.ts.map +1 -0
- package/dist/transport/transport-pool.js +48 -0
- package/dist/transport/transport-pool.js.map +1 -0
- package/dist/transport/transport.d.ts +199 -0
- package/dist/transport/transport.d.ts.map +1 -0
- package/dist/transport/transport.js +11 -0
- package/dist/transport/transport.js.map +1 -0
- package/dist/values/decode.d.ts +39 -0
- package/dist/values/decode.d.ts.map +1 -0
- package/dist/values/decode.js +75 -0
- package/dist/values/decode.js.map +1 -0
- package/dist/values/encode.d.ts +45 -0
- package/dist/values/encode.d.ts.map +1 -0
- package/dist/values/encode.js +271 -0
- package/dist/values/encode.js.map +1 -0
- package/dist/values/ticks.d.ts +31 -0
- package/dist/values/ticks.d.ts.map +1 -0
- package/dist/values/ticks.js +52 -0
- package/dist/values/ticks.js.map +1 -0
- package/dist/values/typed.d.ts +67 -0
- package/dist/values/typed.d.ts.map +1 -0
- package/dist/values/typed.js +134 -0
- package/dist/values/typed.js.map +1 -0
- package/dist/values/uuid.d.ts +27 -0
- package/dist/values/uuid.d.ts.map +1 -0
- package/dist/values/uuid.js +76 -0
- package/dist/values/uuid.js.map +1 -0
- package/dist/vector.d.ts +26 -0
- package/dist/vector.d.ts.map +1 -0
- package/dist/vector.js +48 -0
- package/dist/vector.js.map +1 -0
- package/package.json +86 -0
- package/proto/camus_sql.proto +566 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
import type { ColumnType } from './column-type.js';
|
|
8
|
+
import type { ColumnValue } from './column-value.js';
|
|
9
|
+
import type { CamusResultSet } from './result-set.js';
|
|
10
|
+
/**
|
|
11
|
+
* Where a query's rows come from.
|
|
12
|
+
*
|
|
13
|
+
* It abstracts the delivery mode so the row mapper is written once and works for both:
|
|
14
|
+
*
|
|
15
|
+
* - A buffered source over a whole `CamusResultSet` — what the ordinary query endpoint returns,
|
|
16
|
+
* and what a write statement's affected-row count is wrapped in.
|
|
17
|
+
* - The streaming NDJSON source, which pulls rows off the network one line at a time as the caller
|
|
18
|
+
* advances, so a result of many thousands of rows never fully materializes on this side.
|
|
19
|
+
*
|
|
20
|
+
* The schema is always known up front. The streaming source reads the NDJSON header line before
|
|
21
|
+
* the caller sees a row, so column names and types are reportable before, and independently of,
|
|
22
|
+
* the first row.
|
|
23
|
+
*/
|
|
24
|
+
export interface CamusRowSource extends AsyncDisposable {
|
|
25
|
+
/** Output column names, aligned with `columnTypes`. */
|
|
26
|
+
readonly columnNames: readonly string[];
|
|
27
|
+
/** Declared column types, aligned with `columnNames`. */
|
|
28
|
+
readonly columnTypes: readonly ColumnType[];
|
|
29
|
+
/** The affected-row count for a write statement, or -1 for a query. */
|
|
30
|
+
readonly recordsAffected: number;
|
|
31
|
+
/** Advances to the next row and reports its cells, or `undefined` at the end of the result. */
|
|
32
|
+
next(): Promise<readonly ColumnValue[] | undefined>;
|
|
33
|
+
/** Releases the underlying response. Safe to call more than once. */
|
|
34
|
+
close(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
/** A source over a result set that is already in memory. */
|
|
37
|
+
export declare class BufferedRowSource implements CamusRowSource {
|
|
38
|
+
private readonly resultSet;
|
|
39
|
+
private position;
|
|
40
|
+
readonly recordsAffected: number;
|
|
41
|
+
constructor(resultSet: CamusResultSet, recordsAffected?: number);
|
|
42
|
+
get columnNames(): readonly string[];
|
|
43
|
+
get columnTypes(): readonly ColumnType[];
|
|
44
|
+
next(): Promise<readonly ColumnValue[] | undefined>;
|
|
45
|
+
close(): Promise<void>;
|
|
46
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=row-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-source.d.ts","sourceRoot":"","sources":["../src/row-source.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAExC,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;IAE5C,uEAAuE;IACvE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC,+FAA+F;IAC/F,IAAI,IAAI,OAAO,CAAC,SAAS,WAAW,EAAE,GAAG,SAAS,CAAC,CAAC;IAEpD,qEAAqE;IACrE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,4DAA4D;AAC5D,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAE3C,OAAO,CAAC,QAAQ,CAAM;IAEtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAErB,SAAS,EAAE,cAAc,EAAE,eAAe,SAAK;IAK3D,IAAI,WAAW,IAAI,SAAS,MAAM,EAAE,CAEnC;IAED,IAAI,WAAW,IAAI,SAAS,UAAU,EAAE,CAEvC;IAED,IAAI,IAAI,OAAO,CAAC,SAAS,WAAW,EAAE,GAAG,SAAS,CAAC;IAQnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhB,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7C"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/** A source over a result set that is already in memory. */
|
|
8
|
+
export class BufferedRowSource {
|
|
9
|
+
resultSet;
|
|
10
|
+
position = -1;
|
|
11
|
+
recordsAffected;
|
|
12
|
+
constructor(resultSet, recordsAffected = -1) {
|
|
13
|
+
this.resultSet = resultSet;
|
|
14
|
+
this.recordsAffected = recordsAffected;
|
|
15
|
+
}
|
|
16
|
+
get columnNames() {
|
|
17
|
+
return this.resultSet.columnNames;
|
|
18
|
+
}
|
|
19
|
+
get columnTypes() {
|
|
20
|
+
return this.resultSet.columnTypes;
|
|
21
|
+
}
|
|
22
|
+
next() {
|
|
23
|
+
this.position++;
|
|
24
|
+
if (this.position >= this.resultSet.rowCount)
|
|
25
|
+
return Promise.resolve(undefined);
|
|
26
|
+
return Promise.resolve(this.resultSet.rawRow(this.position));
|
|
27
|
+
}
|
|
28
|
+
close() {
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
async [Symbol.asyncDispose]() {
|
|
32
|
+
await this.close();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=row-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-source.js","sourceRoot":"","sources":["../src/row-source.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqCH,4DAA4D;AAC5D,MAAM,OAAO,iBAAiB;IACX,SAAS,CAAiB;IAEnC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAEb,eAAe,CAAS;IAEjC,YAAY,SAAyB,EAAE,eAAe,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IACzC,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;IACpC,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;IACpC,CAAC;IAED,IAAI;QACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEhB,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEhF,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK;QACH,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;QACzB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
import { CamusTokenProvider } from './auth/token-provider.js';
|
|
8
|
+
import type { ResolvedConfig } from './config.js';
|
|
9
|
+
import { CamusEndpointPool } from './endpoint-pool.js';
|
|
10
|
+
import { CamusPreparedStatementPolicy } from './prepared/policy.js';
|
|
11
|
+
import { CamusStatementRouter } from './routing/router.js';
|
|
12
|
+
import type { CamusTransport } from './transport/transport.js';
|
|
13
|
+
/**
|
|
14
|
+
* Everything a client runs on, assembled from its configuration.
|
|
15
|
+
*
|
|
16
|
+
* Four of these five objects are shared process-wide, keyed by what they actually depend on — see
|
|
17
|
+
* `SharedRegistry` for why. The runtime is the one place that resolves those keys, so a client
|
|
18
|
+
* never has to know which of its collaborators it owns and which it borrows.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ClientRuntime {
|
|
21
|
+
readonly config: ResolvedConfig;
|
|
22
|
+
/** The endpoint rotation, shared by every client with the same endpoint list. */
|
|
23
|
+
readonly pool: CamusEndpointPool;
|
|
24
|
+
/** The bearer token, shared by every client presenting the same identity to this deployment. */
|
|
25
|
+
readonly auth: CamusTokenProvider;
|
|
26
|
+
/** The wire transport, shared by deployment, identity, and stream tuning. */
|
|
27
|
+
readonly transport: CamusTransport;
|
|
28
|
+
/** Which statements to prepare, shared by deployment and prepare settings. */
|
|
29
|
+
readonly preparedStatements: CamusPreparedStatementPolicy;
|
|
30
|
+
/** Learned routing, or `undefined` when routing is off — which is the default. */
|
|
31
|
+
readonly router: CamusStatementRouter | undefined;
|
|
32
|
+
/** The database statements run against. `changeDatabase` moves it. */
|
|
33
|
+
database: string;
|
|
34
|
+
constructor(config: ResolvedConfig);
|
|
35
|
+
/** The request timeout in seconds. */
|
|
36
|
+
get timeoutSeconds(): number;
|
|
37
|
+
/** The next endpoint in the rotation. */
|
|
38
|
+
nextEndpoint(): string;
|
|
39
|
+
/** Where the backup admin API lives for this client. */
|
|
40
|
+
backupEndpoint(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Who performs the credential exchange.
|
|
43
|
+
*
|
|
44
|
+
* A gRPC client uses the `CamusAuth` service on the transport's own channel; a REST client posts
|
|
45
|
+
* to `/login`. Either way the token is obtained over the same protocol and endpoint that carries
|
|
46
|
+
* the statements: there is no second port to configure and no hop between protocols.
|
|
47
|
+
*/
|
|
48
|
+
private loginClient;
|
|
49
|
+
/**
|
|
50
|
+
* The router for this configuration, or `undefined` when routing is off.
|
|
51
|
+
*
|
|
52
|
+
* `learned` needs at least one mapped endpoint. `auto` — the default — needs at least two
|
|
53
|
+
* distinct ones, because one destination is not a routing decision. So a configuration with no
|
|
54
|
+
* trust map behaves exactly as `off`, and its requests are identical to a pre-routing driver's.
|
|
55
|
+
*/
|
|
56
|
+
private buildRouter;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAI3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAEhC,iFAAiF;IACjF,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAEjC,gGAAgG;IAChG,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAElC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IAEnC,8EAA8E;IAC9E,QAAQ,CAAC,kBAAkB,EAAE,4BAA4B,CAAC;IAE1D,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAElD,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;gBAEL,MAAM,EAAE,cAAc;IAuClC,sCAAsC;IACtC,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,yCAAyC;IACzC,YAAY,IAAI,MAAM;IAItB,wDAAwD;IACxD,cAAc,IAAI,MAAM;IAIxB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAOnB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;CA+BpB"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
import { RestLoginClient } from './auth/rest-login-client.js';
|
|
8
|
+
import { CamusTokenProvider } from './auth/token-provider.js';
|
|
9
|
+
import { CamusProtocol, CamusRoutingMode, deploymentKey, resolveBackupEndpoint } from './config.js';
|
|
10
|
+
import { CamusEndpointPool } from './endpoint-pool.js';
|
|
11
|
+
import { CamusPreparedStatementPolicy } from './prepared/policy.js';
|
|
12
|
+
import { CamusStatementRouter } from './routing/router.js';
|
|
13
|
+
import { AuthenticatingTransport } from './transport/authenticating-transport.js';
|
|
14
|
+
import { GrpcTransport } from './transport/grpc/grpc-transport.js';
|
|
15
|
+
import { RestTransport } from './transport/rest-transport.js';
|
|
16
|
+
import { CamusTransportPool } from './transport/transport-pool.js';
|
|
17
|
+
/**
|
|
18
|
+
* Everything a client runs on, assembled from its configuration.
|
|
19
|
+
*
|
|
20
|
+
* Four of these five objects are shared process-wide, keyed by what they actually depend on — see
|
|
21
|
+
* `SharedRegistry` for why. The runtime is the one place that resolves those keys, so a client
|
|
22
|
+
* never has to know which of its collaborators it owns and which it borrows.
|
|
23
|
+
*/
|
|
24
|
+
export class ClientRuntime {
|
|
25
|
+
config;
|
|
26
|
+
/** The endpoint rotation, shared by every client with the same endpoint list. */
|
|
27
|
+
pool;
|
|
28
|
+
/** The bearer token, shared by every client presenting the same identity to this deployment. */
|
|
29
|
+
auth;
|
|
30
|
+
/** The wire transport, shared by deployment, identity, and stream tuning. */
|
|
31
|
+
transport;
|
|
32
|
+
/** Which statements to prepare, shared by deployment and prepare settings. */
|
|
33
|
+
preparedStatements;
|
|
34
|
+
/** Learned routing, or `undefined` when routing is off — which is the default. */
|
|
35
|
+
router;
|
|
36
|
+
/** The database statements run against. `changeDatabase` moves it. */
|
|
37
|
+
database;
|
|
38
|
+
constructor(config) {
|
|
39
|
+
this.config = config;
|
|
40
|
+
this.database = config.database;
|
|
41
|
+
this.pool = CamusEndpointPool.forEndpoints(config.endpointList);
|
|
42
|
+
const deployment = deploymentKey(config);
|
|
43
|
+
this.auth = CamusTokenProvider.forKey(CamusTokenProvider.sharingKey(config.credentials, deployment), () => new CamusTokenProvider({
|
|
44
|
+
credentials: config.credentials,
|
|
45
|
+
resolveLoginClient: () => this.loginClient(),
|
|
46
|
+
resolveEndpoint: () => this.pool.next(),
|
|
47
|
+
resolveTimeoutSeconds: () => config.timeoutSeconds,
|
|
48
|
+
lifetimeMs: config.tokenLifetimeMs,
|
|
49
|
+
}));
|
|
50
|
+
this.transport = CamusTransportPool.forKey(transportKey(config, deployment), () => {
|
|
51
|
+
const inner = config.protocol === CamusProtocol.Grpc
|
|
52
|
+
? new GrpcTransport(this.auth, config.batch)
|
|
53
|
+
: new RestTransport(this.pool, this.auth);
|
|
54
|
+
// Wrapped unconditionally. With no credentials configured the wrapper is inert, and wrapping
|
|
55
|
+
// every transport means a client that authenticates later is covered too.
|
|
56
|
+
return new AuthenticatingTransport(inner, this.auth);
|
|
57
|
+
});
|
|
58
|
+
this.preparedStatements = CamusPreparedStatementPolicy.forKey(`${deployment}|${config.database}|${String(config.maxAutoPrepare)}|${String(config.autoPrepareMinUsages)}`, () => new CamusPreparedStatementPolicy(config.maxAutoPrepare, config.autoPrepareMinUsages));
|
|
59
|
+
this.router = this.buildRouter(deployment);
|
|
60
|
+
}
|
|
61
|
+
/** The request timeout in seconds. */
|
|
62
|
+
get timeoutSeconds() {
|
|
63
|
+
return this.config.timeoutSeconds;
|
|
64
|
+
}
|
|
65
|
+
/** The next endpoint in the rotation. */
|
|
66
|
+
nextEndpoint() {
|
|
67
|
+
return this.pool.next();
|
|
68
|
+
}
|
|
69
|
+
/** Where the backup admin API lives for this client. */
|
|
70
|
+
backupEndpoint() {
|
|
71
|
+
return resolveBackupEndpoint(this.config, this.pool);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Who performs the credential exchange.
|
|
75
|
+
*
|
|
76
|
+
* A gRPC client uses the `CamusAuth` service on the transport's own channel; a REST client posts
|
|
77
|
+
* to `/login`. Either way the token is obtained over the same protocol and endpoint that carries
|
|
78
|
+
* the statements: there is no second port to configure and no hop between protocols.
|
|
79
|
+
*/
|
|
80
|
+
loginClient() {
|
|
81
|
+
const transport = this.transport;
|
|
82
|
+
const inner = transport instanceof AuthenticatingTransport ? transport.inner : transport;
|
|
83
|
+
return isLoginClient(inner) ? inner : new RestLoginClient();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The router for this configuration, or `undefined` when routing is off.
|
|
87
|
+
*
|
|
88
|
+
* `learned` needs at least one mapped endpoint. `auto` — the default — needs at least two
|
|
89
|
+
* distinct ones, because one destination is not a routing decision. So a configuration with no
|
|
90
|
+
* trust map behaves exactly as `off`, and its requests are identical to a pre-routing driver's.
|
|
91
|
+
*/
|
|
92
|
+
buildRouter(deployment) {
|
|
93
|
+
const mode = this.config.routingMode;
|
|
94
|
+
if (mode === CamusRoutingMode.Off)
|
|
95
|
+
return undefined;
|
|
96
|
+
const nodes = this.config.routingNodes;
|
|
97
|
+
const enabled = mode === CamusRoutingMode.Learned
|
|
98
|
+
? nodes.size > 0
|
|
99
|
+
: new Set([...nodes.values()].map((address) => address.toLowerCase())).size >= 2;
|
|
100
|
+
if (!enabled)
|
|
101
|
+
return undefined;
|
|
102
|
+
const maxHintAge = this.config.routingMaxHintAgeMs;
|
|
103
|
+
const routerKey = [
|
|
104
|
+
deployment,
|
|
105
|
+
mode,
|
|
106
|
+
String(maxHintAge),
|
|
107
|
+
[...nodes]
|
|
108
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
109
|
+
.map(([nodeId, address]) => `${nodeId}=${address}`)
|
|
110
|
+
.join(','),
|
|
111
|
+
].join('|');
|
|
112
|
+
return CamusStatementRouter.forKey(routerKey, () => new CamusStatementRouter(nodes, this.pool, maxHintAge));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Which transport a configuration may share: the deployment and the identity presented to it, so a
|
|
117
|
+
* transport is never reused across servers, protocols, or users, plus the stream tuning, which
|
|
118
|
+
* sizes a gRPC transport's pool and so cannot be applied to one that already exists.
|
|
119
|
+
*
|
|
120
|
+
* The credentials are hashed by the token provider's own key function rather than held in a
|
|
121
|
+
* long-lived map key.
|
|
122
|
+
*/
|
|
123
|
+
function transportKey(config, deployment) {
|
|
124
|
+
return [
|
|
125
|
+
CamusTokenProvider.sharingKey(config.credentials, deployment),
|
|
126
|
+
String(config.batch.channelPoolSize),
|
|
127
|
+
String(config.batch.coalescingThreshold),
|
|
128
|
+
String(config.batch.coalescingDelayMs),
|
|
129
|
+
].join('|');
|
|
130
|
+
}
|
|
131
|
+
function isLoginClient(value) {
|
|
132
|
+
return (typeof value === 'object' &&
|
|
133
|
+
value !== null &&
|
|
134
|
+
typeof value.login === 'function' &&
|
|
135
|
+
typeof value.logout === 'function');
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A bounded, process-wide registry of objects that several clients share.
|
|
9
|
+
*
|
|
10
|
+
* Four kinds of driver state outlive the client that created it: the endpoint rotation and the
|
|
11
|
+
* health it depends on, the bearer token, the transport that holds prepared-statement
|
|
12
|
+
* registrations, and the learned-route cache. Each is a property of a deployment, not of one
|
|
13
|
+
* client object, and an application that builds a client per request would otherwise start every
|
|
14
|
+
* one of them cold — a multi-endpoint deployment would send all its traffic to one node, and every
|
|
15
|
+
* request would perform its own login against a per-account rate limit.
|
|
16
|
+
*
|
|
17
|
+
* Past `maxEntries` a caller gets an unshared object rather than growing a map nothing empties.
|
|
18
|
+
* Sharing is an optimization, so the cap trades that optimization for a bound on a process that
|
|
19
|
+
* talks to unboundedly many deployments or identities.
|
|
20
|
+
*/
|
|
21
|
+
export declare class SharedRegistry<T> {
|
|
22
|
+
private readonly entries;
|
|
23
|
+
private readonly maxEntries;
|
|
24
|
+
constructor(maxEntries?: number);
|
|
25
|
+
/** The shared object for `key`, built on first use. */
|
|
26
|
+
get(key: string, factory: () => T): T;
|
|
27
|
+
/** Every shared object. Used to shut a process down cleanly. */
|
|
28
|
+
values(): IterableIterator<T>;
|
|
29
|
+
/** Drops every entry. Tests use it to isolate one case from the next. */
|
|
30
|
+
clear(): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=shared-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-registry.d.ts","sourceRoot":"","sources":["../src/shared-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc,CAAC,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAEhD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,UAAU,SAAO;IAI7B,uDAAuD;IACvD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC;IAarC,gEAAgE;IAChE,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAI7B,yEAAyE;IACzE,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A bounded, process-wide registry of objects that several clients share.
|
|
9
|
+
*
|
|
10
|
+
* Four kinds of driver state outlive the client that created it: the endpoint rotation and the
|
|
11
|
+
* health it depends on, the bearer token, the transport that holds prepared-statement
|
|
12
|
+
* registrations, and the learned-route cache. Each is a property of a deployment, not of one
|
|
13
|
+
* client object, and an application that builds a client per request would otherwise start every
|
|
14
|
+
* one of them cold — a multi-endpoint deployment would send all its traffic to one node, and every
|
|
15
|
+
* request would perform its own login against a per-account rate limit.
|
|
16
|
+
*
|
|
17
|
+
* Past `maxEntries` a caller gets an unshared object rather than growing a map nothing empties.
|
|
18
|
+
* Sharing is an optimization, so the cap trades that optimization for a bound on a process that
|
|
19
|
+
* talks to unboundedly many deployments or identities.
|
|
20
|
+
*/
|
|
21
|
+
export class SharedRegistry {
|
|
22
|
+
entries = new Map();
|
|
23
|
+
maxEntries;
|
|
24
|
+
constructor(maxEntries = 1024) {
|
|
25
|
+
this.maxEntries = maxEntries;
|
|
26
|
+
}
|
|
27
|
+
/** The shared object for `key`, built on first use. */
|
|
28
|
+
get(key, factory) {
|
|
29
|
+
const existing = this.entries.get(key);
|
|
30
|
+
if (existing !== undefined)
|
|
31
|
+
return existing;
|
|
32
|
+
const created = factory();
|
|
33
|
+
if (this.entries.size >= this.maxEntries)
|
|
34
|
+
return created;
|
|
35
|
+
// A racing caller cannot exist: this runs on one thread and `factory` is synchronous.
|
|
36
|
+
this.entries.set(key, created);
|
|
37
|
+
return created;
|
|
38
|
+
}
|
|
39
|
+
/** Every shared object. Used to shut a process down cleanly. */
|
|
40
|
+
values() {
|
|
41
|
+
return this.entries.values();
|
|
42
|
+
}
|
|
43
|
+
/** Drops every entry. Tests use it to isolate one case from the next. */
|
|
44
|
+
clear() {
|
|
45
|
+
this.entries.clear();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=shared-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-registry.js","sourceRoot":"","sources":["../src/shared-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,cAAc;IACR,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;IAE/B,UAAU,CAAS;IAEpC,YAAY,UAAU,GAAG,IAAI;QAC3B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,uDAAuD;IACvD,GAAG,CAAC,GAAW,EAAE,OAAgB;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;QAE5C,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC;QAE1B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO,OAAO,CAAC;QAEzD,sFAAsF;QACtF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,gEAAgE;IAChE,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IAC/B,CAAC;IAED,yEAAyE;IACzE,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Quoting and validation for the few places this driver composes SQL text rather than binding a
|
|
9
|
+
* parameter: a database name in a `CREATE DATABASE`, and a cache family name in a hint.
|
|
10
|
+
*
|
|
11
|
+
* Everything else a caller runs goes to the server as written, with values bound separately.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A single-quoted SQL string literal.
|
|
15
|
+
*
|
|
16
|
+
* @throws {TypeError} when the value holds a backslash the lexer would read together with the
|
|
17
|
+
* closing quote.
|
|
18
|
+
*/
|
|
19
|
+
export declare function sqlLiteral(value: string, target: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Refuses a value that cannot be written as a literal.
|
|
22
|
+
*
|
|
23
|
+
* CamusDB's lexer reads a backslash and the character after it as one unit. A doubled quote
|
|
24
|
+
* therefore stops escaping the quote when a backslash precedes it, and a trailing backslash
|
|
25
|
+
* consumes the literal's closing quote. Neither case has a spelling, so both are refused here
|
|
26
|
+
* rather than sent as a statement that would parse as something else.
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateSqlLiteral(value: string, target: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* A backtick-delimited identifier.
|
|
31
|
+
*
|
|
32
|
+
* An identifier that holds a backtick is refused rather than doubled. CamusDB trims the delimiters
|
|
33
|
+
* instead of decoding a doubled backtick, so doubling neutralizes nothing and the name would break
|
|
34
|
+
* out of its quoting.
|
|
35
|
+
*/
|
|
36
|
+
export declare function delimitIdentifier(identifier: string, parameterName: string): string;
|
|
37
|
+
/** Refuses an identifier that cannot be delimited. */
|
|
38
|
+
export declare function validateIdentifier(identifier: string, parameterName: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Refuses a name that is emitted into SQL as bare text and therefore cannot be escaped at all.
|
|
41
|
+
* Letters, digits, and `_ - . :` are allowed.
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateBareName(name: string, maxLength: number, parameterName: string): void;
|
|
44
|
+
//# sourceMappingURL=sql-syntax.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-syntax.d.ts","sourceRoot":"","sources":["../src/sql-syntax.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAoBtE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAGnF;AAED,sDAAsD;AACtD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAUlF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAmB7F"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Quoting and validation for the few places this driver composes SQL text rather than binding a
|
|
9
|
+
* parameter: a database name in a `CREATE DATABASE`, and a cache family name in a hint.
|
|
10
|
+
*
|
|
11
|
+
* Everything else a caller runs goes to the server as written, with values bound separately.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A single-quoted SQL string literal.
|
|
15
|
+
*
|
|
16
|
+
* @throws {TypeError} when the value holds a backslash the lexer would read together with the
|
|
17
|
+
* closing quote.
|
|
18
|
+
*/
|
|
19
|
+
export function sqlLiteral(value, target) {
|
|
20
|
+
validateSqlLiteral(value, target);
|
|
21
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Refuses a value that cannot be written as a literal.
|
|
25
|
+
*
|
|
26
|
+
* CamusDB's lexer reads a backslash and the character after it as one unit. A doubled quote
|
|
27
|
+
* therefore stops escaping the quote when a backslash precedes it, and a trailing backslash
|
|
28
|
+
* consumes the literal's closing quote. Neither case has a spelling, so both are refused here
|
|
29
|
+
* rather than sent as a statement that would parse as something else.
|
|
30
|
+
*/
|
|
31
|
+
export function validateSqlLiteral(value, target) {
|
|
32
|
+
let index = value.indexOf('\\');
|
|
33
|
+
while (index >= 0) {
|
|
34
|
+
if (index === value.length - 1) {
|
|
35
|
+
throw new TypeError(`The value for ${target} ends with a backslash. CamusDB's lexer reads a backslash and the ` +
|
|
36
|
+
"character after it as one unit, so a trailing backslash would consume the literal's closing quote.");
|
|
37
|
+
}
|
|
38
|
+
if (value[index + 1] === "'") {
|
|
39
|
+
throw new TypeError(`The value for ${target} has a backslash immediately before a quote at position ${String(index)}. ` +
|
|
40
|
+
'CamusDB’s lexer reads that pair as one unit, so the quote cannot be escaped.');
|
|
41
|
+
}
|
|
42
|
+
index = value.indexOf('\\', index + 2);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A backtick-delimited identifier.
|
|
47
|
+
*
|
|
48
|
+
* An identifier that holds a backtick is refused rather than doubled. CamusDB trims the delimiters
|
|
49
|
+
* instead of decoding a doubled backtick, so doubling neutralizes nothing and the name would break
|
|
50
|
+
* out of its quoting.
|
|
51
|
+
*/
|
|
52
|
+
export function delimitIdentifier(identifier, parameterName) {
|
|
53
|
+
validateIdentifier(identifier, parameterName);
|
|
54
|
+
return `\`${identifier}\``;
|
|
55
|
+
}
|
|
56
|
+
/** Refuses an identifier that cannot be delimited. */
|
|
57
|
+
export function validateIdentifier(identifier, parameterName) {
|
|
58
|
+
if (identifier.trim().length === 0) {
|
|
59
|
+
throw new TypeError(`An identifier cannot be empty (${parameterName}).`);
|
|
60
|
+
}
|
|
61
|
+
if (identifier.includes('`')) {
|
|
62
|
+
throw new TypeError(`The identifier '${identifier}' holds a backtick, which CamusDB cannot quote (${parameterName}).`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Refuses a name that is emitted into SQL as bare text and therefore cannot be escaped at all.
|
|
67
|
+
* Letters, digits, and `_ - . :` are allowed.
|
|
68
|
+
*/
|
|
69
|
+
export function validateBareName(name, maxLength, parameterName) {
|
|
70
|
+
if (name.trim().length === 0) {
|
|
71
|
+
throw new TypeError(`'${parameterName}' cannot be empty.`);
|
|
72
|
+
}
|
|
73
|
+
if (name.length > maxLength) {
|
|
74
|
+
throw new TypeError(`'${parameterName}' is ${String(name.length)} characters; at most ${String(maxLength)} are allowed.`);
|
|
75
|
+
}
|
|
76
|
+
for (const character of name) {
|
|
77
|
+
if (/[\p{L}\p{Nd}_\-.:]/u.test(character))
|
|
78
|
+
continue;
|
|
79
|
+
throw new TypeError(`'${parameterName}' holds the character '${character}', which is not allowed. Use letters, digits, ` +
|
|
80
|
+
'or one of _ - . : — the name is emitted into SQL as text and cannot be escaped.');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=sql-syntax.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-syntax.js","sourceRoot":"","sources":["../src/sql-syntax.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAc;IACtD,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;AAC5C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,MAAc;IAC9D,IAAI,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC;QAClB,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,SAAS,CACjB,iBAAiB,MAAM,oEAAoE;gBACzF,oGAAoG,CACvG,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC7B,MAAM,IAAI,SAAS,CACjB,iBAAiB,MAAM,2DAA2D,MAAM,CAAC,KAAK,CAAC,IAAI;gBACjG,8EAA8E,CACjF,CAAC;QACJ,CAAC;QAED,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,aAAqB;IACzE,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAC9C,OAAO,KAAK,UAAU,IAAI,CAAC;AAC7B,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,kBAAkB,CAAC,UAAkB,EAAE,aAAqB;IAC1E,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CAAC,kCAAkC,aAAa,IAAI,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CACjB,mBAAmB,UAAU,mDAAmD,aAAa,IAAI,CAClG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,SAAiB,EAAE,aAAqB;IACrF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,IAAI,aAAa,oBAAoB,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,SAAS,CACjB,IAAI,aAAa,QAAQ,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,MAAM,CAAC,SAAS,CAAC,eAAe,CACrG,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;QAC7B,IAAI,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,SAAS;QAEpD,MAAM,IAAI,SAAS,CACjB,IAAI,aAAa,0BAA0B,SAAS,gDAAgD;YAClG,iFAAiF,CACpF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/** True when the statement goes to the DDL route. */
|
|
8
|
+
export declare function isDdlStatement(sql: string): boolean;
|
|
9
|
+
/** True when the statement writes rows and reports how many. */
|
|
10
|
+
export declare function isDmlStatement(sql: string): boolean;
|
|
11
|
+
/** True when the statement may be registered as a prepared statement. */
|
|
12
|
+
export declare function isPreparableStatement(sql: string): boolean;
|
|
13
|
+
/** True when the statement cannot run inside an explicit transaction. */
|
|
14
|
+
export declare function runsInOwnTransaction(sql: string): boolean;
|
|
15
|
+
//# sourceMappingURL=statements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statements.d.ts","sourceRoot":"","sources":["../src/statements.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgEH,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,gEAAgE;AAChE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,yEAAyE;AACzE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEzD"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of CamusDB
|
|
3
|
+
*
|
|
4
|
+
* For the full copyright and license information, please view the LICENSE.txt
|
|
5
|
+
* file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Classifies a statement by its leading keywords.
|
|
9
|
+
*
|
|
10
|
+
* The server decides what a statement means; these lists only decide which route the driver sends
|
|
11
|
+
* it to and whether it is worth preparing. A statement this module classifies wrongly still runs
|
|
12
|
+
* correctly, because the data route forwards a schema statement to the same implementation — it
|
|
13
|
+
* simply takes an extra parse and dispatch on the way.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The schema statements that go to the server's DDL route rather than its data route.
|
|
17
|
+
*
|
|
18
|
+
* An older server does not forward, and refuses such a statement on the data route as an unknown
|
|
19
|
+
* node, so this list is also what keeps the driver working against one.
|
|
20
|
+
*
|
|
21
|
+
* `REFRESH MATERIALIZED VIEW` is deliberately absent. It is a write, not schema: it replaces a
|
|
22
|
+
* relation's contents and reports how many rows it wrote, which the DDL route has no shape to
|
|
23
|
+
* return.
|
|
24
|
+
*/
|
|
25
|
+
const DDL_PREFIXES = [
|
|
26
|
+
'CREATE TABLE',
|
|
27
|
+
'DROP TABLE',
|
|
28
|
+
'ALTER TABLE',
|
|
29
|
+
// TRUNCATE is schema, not a write: the server retires the table's whole key space and commits a
|
|
30
|
+
// replicated schema entry instead of deleting rows. The TABLE keyword is optional, so the prefix
|
|
31
|
+
// stops at the verb and covers both spellings.
|
|
32
|
+
'TRUNCATE',
|
|
33
|
+
'CREATE UNIQUE INDEX',
|
|
34
|
+
'CREATE INDEX',
|
|
35
|
+
'DROP INDEX',
|
|
36
|
+
// Views. "CREATE VIEW" does not cover "CREATE OR REPLACE VIEW", because the test is a prefix
|
|
37
|
+
// test, so each spelling needs its own entry. The IF EXISTS and IF NOT EXISTS variants do fall
|
|
38
|
+
// under the base prefixes, because the condition follows the object keyword.
|
|
39
|
+
'CREATE VIEW',
|
|
40
|
+
'CREATE OR REPLACE VIEW',
|
|
41
|
+
'DROP VIEW',
|
|
42
|
+
'ALTER VIEW',
|
|
43
|
+
'CREATE MATERIALIZED VIEW',
|
|
44
|
+
'DROP MATERIALIZED VIEW',
|
|
45
|
+
'ALTER MATERIALIZED VIEW',
|
|
46
|
+
];
|
|
47
|
+
const DML_PREFIXES = ['INSERT', 'UPDATE', 'DELETE'];
|
|
48
|
+
/**
|
|
49
|
+
* The statements the server accepts a registration for: the repeatable data statements, whose
|
|
50
|
+
* whole point is running many times with different values. Schema and administration statements
|
|
51
|
+
* are one-shot and are excluded on the server too, so this list mirrors that rather than guessing.
|
|
52
|
+
*/
|
|
53
|
+
const PREPARABLE_PREFIXES = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'SHOW'];
|
|
54
|
+
/**
|
|
55
|
+
* The statements that own their internal transaction, which the server refuses inside an explicit
|
|
56
|
+
* one.
|
|
57
|
+
*
|
|
58
|
+
* `TRUNCATE` is the only member today. It commits a replicated schema entry, and a later rollback
|
|
59
|
+
* of the caller's transaction cannot undo that entry — so the server refuses the statement rather
|
|
60
|
+
* than promise a rollback it cannot deliver. The driver refuses it before the round trip, because
|
|
61
|
+
* the outcome is already known and a local message can name the fix.
|
|
62
|
+
*/
|
|
63
|
+
const OWN_TRANSACTION_PREFIXES = ['TRUNCATE'];
|
|
64
|
+
/** True when the statement goes to the DDL route. */
|
|
65
|
+
export function isDdlStatement(sql) {
|
|
66
|
+
return startsWithAny(sql, DDL_PREFIXES);
|
|
67
|
+
}
|
|
68
|
+
/** True when the statement writes rows and reports how many. */
|
|
69
|
+
export function isDmlStatement(sql) {
|
|
70
|
+
return startsWithAny(sql, DML_PREFIXES);
|
|
71
|
+
}
|
|
72
|
+
/** True when the statement may be registered as a prepared statement. */
|
|
73
|
+
export function isPreparableStatement(sql) {
|
|
74
|
+
return startsWithAny(sql, PREPARABLE_PREFIXES);
|
|
75
|
+
}
|
|
76
|
+
/** True when the statement cannot run inside an explicit transaction. */
|
|
77
|
+
export function runsInOwnTransaction(sql) {
|
|
78
|
+
return startsWithAny(sql, OWN_TRANSACTION_PREFIXES);
|
|
79
|
+
}
|
|
80
|
+
function startsWithAny(sql, prefixes) {
|
|
81
|
+
const trimmed = sql.trimStart();
|
|
82
|
+
for (const prefix of prefixes) {
|
|
83
|
+
if (trimmed.length < prefix.length)
|
|
84
|
+
continue;
|
|
85
|
+
if (trimmed.slice(0, prefix.length).toUpperCase() === prefix)
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=statements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statements.js","sourceRoot":"","sources":["../src/statements.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;GAOG;AAEH;;;;;;;;;GASG;AACH,MAAM,YAAY,GAAG;IACnB,cAAc;IACd,YAAY;IACZ,aAAa;IACb,gGAAgG;IAChG,iGAAiG;IACjG,+CAA+C;IAC/C,UAAU;IACV,qBAAqB;IACrB,cAAc;IACd,YAAY;IACZ,6FAA6F;IAC7F,+FAA+F;IAC/F,6EAA6E;IAC7E,aAAa;IACb,wBAAwB;IACxB,WAAW;IACX,YAAY;IACZ,0BAA0B;IAC1B,wBAAwB;IACxB,yBAAyB;CAC1B,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAEpD;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAE7E;;;;;;;;GAQG;AACH,MAAM,wBAAwB,GAAG,CAAC,UAAU,CAAC,CAAC;AAE9C,qDAAqD;AACrD,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,OAAO,aAAa,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,OAAO,aAAa,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,QAA2B;IAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAEhC,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM;YAAE,SAAS;QAE7C,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;IAC5E,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|