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.
Files changed (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +950 -0
  3. package/dist/auth/credentials.d.ts +30 -0
  4. package/dist/auth/credentials.d.ts.map +1 -0
  5. package/dist/auth/credentials.js +23 -0
  6. package/dist/auth/credentials.js.map +1 -0
  7. package/dist/auth/login-client.d.ts +37 -0
  8. package/dist/auth/login-client.d.ts.map +1 -0
  9. package/dist/auth/login-client.js +8 -0
  10. package/dist/auth/login-client.js.map +1 -0
  11. package/dist/auth/rest-login-client.d.ts +17 -0
  12. package/dist/auth/rest-login-client.d.ts.map +1 -0
  13. package/dist/auth/rest-login-client.js +71 -0
  14. package/dist/auth/rest-login-client.js.map +1 -0
  15. package/dist/auth/token-provider.d.ts +123 -0
  16. package/dist/auth/token-provider.d.ts.map +1 -0
  17. package/dist/auth/token-provider.js +209 -0
  18. package/dist/auth/token-provider.js.map +1 -0
  19. package/dist/backup.d.ts +98 -0
  20. package/dist/backup.d.ts.map +1 -0
  21. package/dist/backup.js +153 -0
  22. package/dist/backup.js.map +1 -0
  23. package/dist/cache.d.ts +90 -0
  24. package/dist/cache.d.ts.map +1 -0
  25. package/dist/cache.js +121 -0
  26. package/dist/cache.js.map +1 -0
  27. package/dist/client.d.ts +406 -0
  28. package/dist/client.d.ts.map +1 -0
  29. package/dist/client.js +724 -0
  30. package/dist/client.js.map +1 -0
  31. package/dist/column-type.d.ts +33 -0
  32. package/dist/column-type.d.ts.map +1 -0
  33. package/dist/column-type.js +50 -0
  34. package/dist/column-type.js.map +1 -0
  35. package/dist/column-value.d.ts +77 -0
  36. package/dist/column-value.d.ts.map +1 -0
  37. package/dist/column-value.js +60 -0
  38. package/dist/column-value.js.map +1 -0
  39. package/dist/config.d.ts +181 -0
  40. package/dist/config.d.ts.map +1 -0
  41. package/dist/config.js +315 -0
  42. package/dist/config.js.map +1 -0
  43. package/dist/connection-string.d.ts +45 -0
  44. package/dist/connection-string.d.ts.map +1 -0
  45. package/dist/connection-string.js +170 -0
  46. package/dist/connection-string.js.map +1 -0
  47. package/dist/endpoint-pool.d.ts +70 -0
  48. package/dist/endpoint-pool.d.ts.map +1 -0
  49. package/dist/endpoint-pool.js +120 -0
  50. package/dist/endpoint-pool.js.map +1 -0
  51. package/dist/error-codes.d.ts +44 -0
  52. package/dist/error-codes.d.ts.map +1 -0
  53. package/dist/error-codes.js +43 -0
  54. package/dist/error-codes.js.map +1 -0
  55. package/dist/errors.d.ts +24 -0
  56. package/dist/errors.d.ts.map +1 -0
  57. package/dist/errors.js +33 -0
  58. package/dist/errors.js.map +1 -0
  59. package/dist/hlc.d.ts +19 -0
  60. package/dist/hlc.d.ts.map +1 -0
  61. package/dist/hlc.js +11 -0
  62. package/dist/hlc.js.map +1 -0
  63. package/dist/index.d.ts +55 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +51 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/json.d.ts +41 -0
  68. package/dist/json.d.ts.map +1 -0
  69. package/dist/json.js +345 -0
  70. package/dist/json.js.map +1 -0
  71. package/dist/object-id.d.ts +39 -0
  72. package/dist/object-id.d.ts.map +1 -0
  73. package/dist/object-id.js +99 -0
  74. package/dist/object-id.js.map +1 -0
  75. package/dist/options.d.ts +77 -0
  76. package/dist/options.d.ts.map +1 -0
  77. package/dist/options.js +68 -0
  78. package/dist/options.js.map +1 -0
  79. package/dist/prepared/binder.d.ts +20 -0
  80. package/dist/prepared/binder.d.ts.map +1 -0
  81. package/dist/prepared/binder.js +32 -0
  82. package/dist/prepared/binder.js.map +1 -0
  83. package/dist/prepared/policy.d.ts +81 -0
  84. package/dist/prepared/policy.d.ts.map +1 -0
  85. package/dist/prepared/policy.js +164 -0
  86. package/dist/prepared/policy.js.map +1 -0
  87. package/dist/query-stream.d.ts +55 -0
  88. package/dist/query-stream.d.ts.map +1 -0
  89. package/dist/query-stream.js +94 -0
  90. package/dist/query-stream.js.map +1 -0
  91. package/dist/result-set.d.ts +62 -0
  92. package/dist/result-set.d.ts.map +1 -0
  93. package/dist/result-set.js +100 -0
  94. package/dist/result-set.js.map +1 -0
  95. package/dist/retry.d.ts +38 -0
  96. package/dist/retry.d.ts.map +1 -0
  97. package/dist/retry.js +93 -0
  98. package/dist/retry.js.map +1 -0
  99. package/dist/routing/advice.d.ts +63 -0
  100. package/dist/routing/advice.d.ts.map +1 -0
  101. package/dist/routing/advice.js +61 -0
  102. package/dist/routing/advice.js.map +1 -0
  103. package/dist/routing/route-cache.d.ts +53 -0
  104. package/dist/routing/route-cache.d.ts.map +1 -0
  105. package/dist/routing/route-cache.js +123 -0
  106. package/dist/routing/route-cache.js.map +1 -0
  107. package/dist/routing/router.d.ts +53 -0
  108. package/dist/routing/router.d.ts.map +1 -0
  109. package/dist/routing/router.js +89 -0
  110. package/dist/routing/router.js.map +1 -0
  111. package/dist/row-source.d.ts +48 -0
  112. package/dist/row-source.d.ts.map +1 -0
  113. package/dist/row-source.js +35 -0
  114. package/dist/row-source.js.map +1 -0
  115. package/dist/runtime.d.ts +58 -0
  116. package/dist/runtime.d.ts.map +1 -0
  117. package/dist/runtime.js +137 -0
  118. package/dist/runtime.js.map +1 -0
  119. package/dist/shared-registry.d.ts +32 -0
  120. package/dist/shared-registry.d.ts.map +1 -0
  121. package/dist/shared-registry.js +48 -0
  122. package/dist/shared-registry.js.map +1 -0
  123. package/dist/sql-syntax.d.ts +44 -0
  124. package/dist/sql-syntax.d.ts.map +1 -0
  125. package/dist/sql-syntax.js +83 -0
  126. package/dist/sql-syntax.js.map +1 -0
  127. package/dist/statements.d.ts +15 -0
  128. package/dist/statements.d.ts.map +1 -0
  129. package/dist/statements.js +90 -0
  130. package/dist/statements.js.map +1 -0
  131. package/dist/transaction.d.ts +117 -0
  132. package/dist/transaction.d.ts.map +1 -0
  133. package/dist/transaction.js +204 -0
  134. package/dist/transaction.js.map +1 -0
  135. package/dist/transport/authenticating-transport.d.ts +63 -0
  136. package/dist/transport/authenticating-transport.d.ts.map +1 -0
  137. package/dist/transport/authenticating-transport.js +119 -0
  138. package/dist/transport/authenticating-transport.js.map +1 -0
  139. package/dist/transport/branch-statements.d.ts +39 -0
  140. package/dist/transport/branch-statements.d.ts.map +1 -0
  141. package/dist/transport/branch-statements.js +74 -0
  142. package/dist/transport/branch-statements.js.map +1 -0
  143. package/dist/transport/error-text.d.ts +26 -0
  144. package/dist/transport/error-text.d.ts.map +1 -0
  145. package/dist/transport/error-text.js +75 -0
  146. package/dist/transport/error-text.js.map +1 -0
  147. package/dist/transport/grpc/batcher.d.ts +127 -0
  148. package/dist/transport/grpc/batcher.d.ts.map +1 -0
  149. package/dist/transport/grpc/batcher.js +399 -0
  150. package/dist/transport/grpc/batcher.js.map +1 -0
  151. package/dist/transport/grpc/codec.d.ts +40 -0
  152. package/dist/transport/grpc/codec.d.ts.map +1 -0
  153. package/dist/transport/grpc/codec.js +231 -0
  154. package/dist/transport/grpc/codec.js.map +1 -0
  155. package/dist/transport/grpc/grpc-transport.d.ts +115 -0
  156. package/dist/transport/grpc/grpc-transport.d.ts.map +1 -0
  157. package/dist/transport/grpc/grpc-transport.js +577 -0
  158. package/dist/transport/grpc/grpc-transport.js.map +1 -0
  159. package/dist/transport/grpc/messages.d.ts +221 -0
  160. package/dist/transport/grpc/messages.d.ts.map +1 -0
  161. package/dist/transport/grpc/messages.js +56 -0
  162. package/dist/transport/grpc/messages.js.map +1 -0
  163. package/dist/transport/grpc/proto.d.ts +71 -0
  164. package/dist/transport/grpc/proto.d.ts.map +1 -0
  165. package/dist/transport/grpc/proto.js +67 -0
  166. package/dist/transport/grpc/proto.js.map +1 -0
  167. package/dist/transport/http.d.ts +62 -0
  168. package/dist/transport/http.d.ts.map +1 -0
  169. package/dist/transport/http.js +169 -0
  170. package/dist/transport/http.js.map +1 -0
  171. package/dist/transport/ndjson-row-source.d.ts +38 -0
  172. package/dist/transport/ndjson-row-source.d.ts.map +1 -0
  173. package/dist/transport/ndjson-row-source.js +197 -0
  174. package/dist/transport/ndjson-row-source.js.map +1 -0
  175. package/dist/transport/rest-decode.d.ts +33 -0
  176. package/dist/transport/rest-decode.d.ts.map +1 -0
  177. package/dist/transport/rest-decode.js +162 -0
  178. package/dist/transport/rest-decode.js.map +1 -0
  179. package/dist/transport/rest-prepared-cache.d.ts +50 -0
  180. package/dist/transport/rest-prepared-cache.d.ts.map +1 -0
  181. package/dist/transport/rest-prepared-cache.js +101 -0
  182. package/dist/transport/rest-prepared-cache.js.map +1 -0
  183. package/dist/transport/rest-transport.d.ts +88 -0
  184. package/dist/transport/rest-transport.d.ts.map +1 -0
  185. package/dist/transport/rest-transport.js +388 -0
  186. package/dist/transport/rest-transport.js.map +1 -0
  187. package/dist/transport/transport-pool.d.ts +40 -0
  188. package/dist/transport/transport-pool.d.ts.map +1 -0
  189. package/dist/transport/transport-pool.js +48 -0
  190. package/dist/transport/transport-pool.js.map +1 -0
  191. package/dist/transport/transport.d.ts +199 -0
  192. package/dist/transport/transport.d.ts.map +1 -0
  193. package/dist/transport/transport.js +11 -0
  194. package/dist/transport/transport.js.map +1 -0
  195. package/dist/values/decode.d.ts +39 -0
  196. package/dist/values/decode.d.ts.map +1 -0
  197. package/dist/values/decode.js +75 -0
  198. package/dist/values/decode.js.map +1 -0
  199. package/dist/values/encode.d.ts +45 -0
  200. package/dist/values/encode.d.ts.map +1 -0
  201. package/dist/values/encode.js +271 -0
  202. package/dist/values/encode.js.map +1 -0
  203. package/dist/values/ticks.d.ts +31 -0
  204. package/dist/values/ticks.d.ts.map +1 -0
  205. package/dist/values/ticks.js +52 -0
  206. package/dist/values/ticks.js.map +1 -0
  207. package/dist/values/typed.d.ts +67 -0
  208. package/dist/values/typed.d.ts.map +1 -0
  209. package/dist/values/typed.js +134 -0
  210. package/dist/values/typed.js.map +1 -0
  211. package/dist/values/uuid.d.ts +27 -0
  212. package/dist/values/uuid.d.ts.map +1 -0
  213. package/dist/values/uuid.js +76 -0
  214. package/dist/values/uuid.js.map +1 -0
  215. package/dist/vector.d.ts +26 -0
  216. package/dist/vector.d.ts.map +1 -0
  217. package/dist/vector.js +48 -0
  218. package/dist/vector.js.map +1 -0
  219. package/package.json +86 -0
  220. package/proto/camus_sql.proto +566 -0
@@ -0,0 +1,98 @@
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 { ClientRuntime } from './runtime.js';
8
+ /** One backup in the node's catalog. */
9
+ export interface CamusBackupInfo {
10
+ readonly backupId: string;
11
+ readonly formatVersion: number;
12
+ /** `full`, `incremental`, or `coordinated`. */
13
+ readonly type: string;
14
+ readonly createdAtUtc?: string | undefined;
15
+ /** The backup this one builds on. Absent for a full backup. */
16
+ readonly parentBackupId?: string | undefined;
17
+ readonly partitionCount: number;
18
+ readonly clusterSnapshotNode?: number | undefined;
19
+ readonly clusterSnapshotPhysical?: number | undefined;
20
+ readonly clusterSnapshotCounter?: number | undefined;
21
+ /** What the caller asked for, and what the server actually took. */
22
+ readonly requestedKind?: string | undefined;
23
+ readonly actualKind?: string | undefined;
24
+ /** Why the server took a different kind than the one requested. */
25
+ readonly substitutionReason?: string | undefined;
26
+ /** True when the server marked this backup unusable for a restore. */
27
+ readonly isInvalid: boolean;
28
+ readonly invalidReason?: string | undefined;
29
+ /** The window this backup can restore to, in Unix milliseconds. */
30
+ readonly minRecoverablePhysicalMs?: number | undefined;
31
+ readonly maxRecoverablePhysicalMs?: number | undefined;
32
+ readonly clusterId?: string | undefined;
33
+ readonly coordinatorNode?: string | undefined;
34
+ /** True when the server took a different kind of backup than the one requested. */
35
+ readonly wasSubstituted: boolean;
36
+ }
37
+ /** One backup that retention deleted, or would delete. */
38
+ export interface CamusBackupGcDeletion {
39
+ readonly backupId: string;
40
+ readonly type: string;
41
+ readonly createdAtUtc?: string | undefined;
42
+ readonly bytes: number;
43
+ readonly reason: string;
44
+ }
45
+ /** One file or directory that belongs to no backup. */
46
+ export interface CamusBackupGcOrphan {
47
+ readonly name: string;
48
+ readonly isDirectory: boolean;
49
+ readonly reason: string;
50
+ }
51
+ /** What a retention run did, or would do. */
52
+ export interface CamusBackupGcResult {
53
+ /** False for a preview: nothing was deleted. */
54
+ readonly applied: boolean;
55
+ readonly bytesReclaimed: number;
56
+ readonly retentionDeletions: CamusBackupGcDeletion[];
57
+ readonly orphanReclamations: CamusBackupGcOrphan[];
58
+ }
59
+ /**
60
+ * The node's online backup administration API: take a full, incremental, or coordinated backup,
61
+ * list the catalog, resolve a restore chain, and run retention.
62
+ *
63
+ * It is server-level and node-wide, not scoped to the client's database. Every database on the
64
+ * server shares one storage node, so a backup captures all of them. It needs a superuser token
65
+ * when authentication is on.
66
+ *
67
+ * Restore is an offline operator procedure and is deliberately not reachable here.
68
+ *
69
+ * The routes are REST and JSON only. They have no SQL form and no gRPC service, so a gRPC client
70
+ * must configure `backupEndpoint` to say where the HTTP port is.
71
+ */
72
+ export declare class CamusBackupClient {
73
+ private readonly runtime;
74
+ /** @internal Reach it through `client.backups`. */
75
+ constructor(runtime: ClientRuntime);
76
+ /** Takes a full backup: a complete copy of the node's base image. */
77
+ takeFullBackup(signal?: AbortSignal): Promise<CamusBackupInfo>;
78
+ /** Takes an incremental backup, relative to `parentBackupId`. */
79
+ takeIncrementalBackup(parentBackupId: string, signal?: AbortSignal): Promise<CamusBackupInfo>;
80
+ /** Takes a cluster-coordinated backup. It must reach the coordinator node specifically. */
81
+ takeCoordinatedBackup(signal?: AbortSignal): Promise<CamusBackupInfo>;
82
+ /** Every backup in the node's catalog. */
83
+ listBackups(signal?: AbortSignal): Promise<CamusBackupInfo[]>;
84
+ /**
85
+ * The chain of backups a restore of `leafBackupId` needs, from its base full backup to the leaf.
86
+ * Use it to check that every link is present and valid before relying on the leaf.
87
+ */
88
+ getChain(leafBackupId: string, signal?: AbortSignal): Promise<CamusBackupInfo[]>;
89
+ /** Reports what retention would delete, without deleting anything. */
90
+ previewGarbageCollection(signal?: AbortSignal): Promise<CamusBackupGcResult>;
91
+ /** Runs retention: deletes the backups its policy has aged out, and reclaims orphaned files. */
92
+ collectGarbage(signal?: AbortSignal): Promise<CamusBackupGcResult>;
93
+ private takeBackup;
94
+ private list;
95
+ private collect;
96
+ private send;
97
+ }
98
+ //# sourceMappingURL=backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../src/backup.ts"],"names":[],"mappings":"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"}
package/dist/backup.js ADDED
@@ -0,0 +1,153 @@
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 { CamusError } from './errors.js';
8
+ import { CamusErrorCode } from './error-codes.js';
9
+ import { asNumber } from './json.js';
10
+ import { sendJson } from './transport/http.js';
11
+ /**
12
+ * The node's online backup administration API: take a full, incremental, or coordinated backup,
13
+ * list the catalog, resolve a restore chain, and run retention.
14
+ *
15
+ * It is server-level and node-wide, not scoped to the client's database. Every database on the
16
+ * server shares one storage node, so a backup captures all of them. It needs a superuser token
17
+ * when authentication is on.
18
+ *
19
+ * Restore is an offline operator procedure and is deliberately not reachable here.
20
+ *
21
+ * The routes are REST and JSON only. They have no SQL form and no gRPC service, so a gRPC client
22
+ * must configure `backupEndpoint` to say where the HTTP port is.
23
+ */
24
+ export class CamusBackupClient {
25
+ runtime;
26
+ /** @internal Reach it through `client.backups`. */
27
+ constructor(runtime) {
28
+ this.runtime = runtime;
29
+ }
30
+ /** Takes a full backup: a complete copy of the node's base image. */
31
+ takeFullBackup(signal) {
32
+ return this.takeBackup(['v1', 'backups', 'full'], undefined, 'Take full backup failed', signal);
33
+ }
34
+ /** Takes an incremental backup, relative to `parentBackupId`. */
35
+ takeIncrementalBackup(parentBackupId, signal) {
36
+ return this.takeBackup(['v1', 'backups', 'incremental'], { parentBackupId }, 'Take incremental backup failed', signal);
37
+ }
38
+ /** Takes a cluster-coordinated backup. It must reach the coordinator node specifically. */
39
+ takeCoordinatedBackup(signal) {
40
+ return this.takeBackup(['v1', 'backups', 'coordinated'], undefined, 'Take coordinated backup failed', signal);
41
+ }
42
+ /** Every backup in the node's catalog. */
43
+ listBackups(signal) {
44
+ return this.list(['v1', 'backups'], 'List backups failed', signal);
45
+ }
46
+ /**
47
+ * The chain of backups a restore of `leafBackupId` needs, from its base full backup to the leaf.
48
+ * Use it to check that every link is present and valid before relying on the leaf.
49
+ */
50
+ getChain(leafBackupId, signal) {
51
+ return this.list(['v1', 'backups', leafBackupId, 'chain'], 'Get backup chain failed', signal);
52
+ }
53
+ /** Reports what retention would delete, without deleting anything. */
54
+ previewGarbageCollection(signal) {
55
+ return this.collect(true, signal);
56
+ }
57
+ /** Runs retention: deletes the backups its policy has aged out, and reclaims orphaned files. */
58
+ collectGarbage(signal) {
59
+ return this.collect(false, signal);
60
+ }
61
+ async takeBackup(path, body, failureMessage, signal) {
62
+ const reply = await this.send(path, 'POST', body, undefined, signal);
63
+ if (reply.status !== 'ok' || reply.backup === undefined || reply.backup === null) {
64
+ throw new CamusError(reply.code ?? CamusErrorCode.Generic, reply.message ?? failureMessage);
65
+ }
66
+ return readBackupInfo(reply.backup);
67
+ }
68
+ async list(path, failureMessage, signal) {
69
+ const reply = await this.send(path, 'GET', undefined, undefined, signal);
70
+ if (reply.status !== 'ok') {
71
+ throw new CamusError(reply.code ?? CamusErrorCode.Generic, reply.message ?? failureMessage);
72
+ }
73
+ return (reply.backups ?? []).map(readBackupInfo);
74
+ }
75
+ async collect(dryRun, signal) {
76
+ const reply = await this.send(['v1', 'backups', 'gc'], 'POST', undefined, { dryRun: dryRun ? 'true' : 'false' }, signal);
77
+ if (reply.status !== 'ok') {
78
+ throw new CamusError(reply.code ?? CamusErrorCode.Generic, reply.message ?? 'Backup garbage collection failed');
79
+ }
80
+ return {
81
+ applied: reply.applied === true,
82
+ bytesReclaimed: asNumber(reply.bytesReclaimed),
83
+ retentionDeletions: (reply.retentionDeletions ?? []).map(readDeletion),
84
+ orphanReclamations: (reply.orphanReclamations ?? []).map(readOrphan),
85
+ };
86
+ }
87
+ async send(path, method, body, query, signal) {
88
+ const endpoint = this.runtime.backupEndpoint();
89
+ return sendJson(this.runtime.pool, {
90
+ endpoint,
91
+ path,
92
+ method,
93
+ body,
94
+ query,
95
+ token: await this.runtime.auth.getToken(signal),
96
+ timeoutSeconds: this.runtime.config.backupTimeoutSeconds,
97
+ signal,
98
+ });
99
+ }
100
+ }
101
+ function readBackupInfo(value) {
102
+ const record = (value ?? {});
103
+ const requestedKind = readString(record.requestedKind);
104
+ const actualKind = readString(record.actualKind);
105
+ return {
106
+ backupId: readString(record.backupId) ?? '',
107
+ formatVersion: asNumber(record.formatVersion),
108
+ type: readString(record.type) ?? '',
109
+ createdAtUtc: readString(record.createdAtUtc),
110
+ parentBackupId: readString(record.parentBackupId),
111
+ partitionCount: asNumber(record.partitionCount),
112
+ clusterSnapshotNode: readOptionalNumber(record.clusterSnapshotNode),
113
+ clusterSnapshotPhysical: readOptionalNumber(record.clusterSnapshotPhysical),
114
+ clusterSnapshotCounter: readOptionalNumber(record.clusterSnapshotCounter),
115
+ requestedKind,
116
+ actualKind,
117
+ substitutionReason: readString(record.substitutionReason),
118
+ isInvalid: record.isInvalid === true,
119
+ invalidReason: readString(record.invalidReason),
120
+ minRecoverablePhysicalMs: readOptionalNumber(record.minRecoverablePhysicalMs),
121
+ maxRecoverablePhysicalMs: readOptionalNumber(record.maxRecoverablePhysicalMs),
122
+ clusterId: readString(record.clusterId),
123
+ coordinatorNode: readString(record.coordinatorNode),
124
+ wasSubstituted: requestedKind !== undefined && actualKind !== undefined && requestedKind !== actualKind,
125
+ };
126
+ }
127
+ function readDeletion(value) {
128
+ const record = (value ?? {});
129
+ return {
130
+ backupId: readString(record.backupId) ?? '',
131
+ type: readString(record.type) ?? '',
132
+ createdAtUtc: readString(record.createdAtUtc),
133
+ bytes: asNumber(record.bytes),
134
+ reason: readString(record.reason) ?? '',
135
+ };
136
+ }
137
+ function readOrphan(value) {
138
+ const record = (value ?? {});
139
+ return {
140
+ name: readString(record.name) ?? '',
141
+ isDirectory: record.isDirectory === true,
142
+ reason: readString(record.reason) ?? '',
143
+ };
144
+ }
145
+ function readString(value) {
146
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
147
+ }
148
+ function readOptionalNumber(value) {
149
+ if (value === undefined || value === null)
150
+ return undefined;
151
+ return asNumber(value);
152
+ }
153
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../src/backup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAgF/C;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,iBAAiB;IACX,OAAO,CAAgB;IAExC,mDAAmD;IACnD,YAAY,OAAsB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,qEAAqE;IACrE,cAAc,CAAC,MAAoB;QACjC,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,yBAAyB,EAAE,MAAM,CAAC,CAAC;IAClG,CAAC;IAED,iEAAiE;IACjE,qBAAqB,CAAC,cAAsB,EAAE,MAAoB;QAChE,OAAO,IAAI,CAAC,UAAU,CACpB,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,EAChC,EAAE,cAAc,EAAE,EAClB,gCAAgC,EAChC,MAAM,CACP,CAAC;IACJ,CAAC;IAED,2FAA2F;IAC3F,qBAAqB,CAAC,MAAoB;QACxC,OAAO,IAAI,CAAC,UAAU,CACpB,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,EAChC,SAAS,EACT,gCAAgC,EAChC,MAAM,CACP,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,WAAW,CAAC,MAAoB;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,YAAoB,EAAE,MAAoB;QACjD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,yBAAyB,EAAE,MAAM,CAAC,CAAC;IAChG,CAAC;IAED,sEAAsE;IACtE,wBAAwB,CAAC,MAAoB;QAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,gGAAgG;IAChG,cAAc,CAAC,MAAoB;QACjC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAEO,KAAK,CAAC,UAAU,CACtB,IAAuB,EACvB,IAAa,EACb,cAAsB,EACtB,MAA+B;QAE/B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAErE,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACjF,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,cAAc,CAAC,CAAC;QAC9F,CAAC;QAED,OAAO,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,IAAI,CAChB,IAAuB,EACvB,cAAsB,EACtB,MAA+B;QAE/B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAEzE,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,cAAc,CAAC,CAAC;QAC9F,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,MAAe,EAAE,MAA+B;QACpE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAC3B,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,EACvB,MAAM,EACN,SAAS,EACT,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,EACrC,MAAM,CACP,CAAC;QAEF,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAClB,KAAK,CAAC,IAAI,IAAI,cAAc,CAAC,OAAO,EACpC,KAAK,CAAC,OAAO,IAAI,kCAAkC,CACpD,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK,CAAC,OAAO,KAAK,IAAI;YAC/B,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;YAC9C,kBAAkB,EAAE,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;YACtE,kBAAkB,EAAE,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC;SACrE,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,IAAI,CAChB,IAAuB,EACvB,MAAsB,EACtB,IAAa,EACb,KAAyC,EACzC,MAA+B;QAE/B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAE/C,OAAO,QAAQ,CAAiB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YACjD,QAAQ;YACR,IAAI;YACJ,MAAM;YACN,IAAI;YACJ,KAAK;YACL,KAAK,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC/C,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,oBAAoB;YACxD,MAAM;SACP,CAAC,CAAC;IACL,CAAC;CACF;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;IAExD,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAEjD,OAAO;QACL,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC3C,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC;QAC7C,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;QACnC,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC;QAC7C,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC;QACjD,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC;QAC/C,mBAAmB,EAAE,kBAAkB,CAAC,MAAM,CAAC,mBAAmB,CAAC;QACnE,uBAAuB,EAAE,kBAAkB,CAAC,MAAM,CAAC,uBAAuB,CAAC;QAC3E,sBAAsB,EAAE,kBAAkB,CAAC,MAAM,CAAC,sBAAsB,CAAC;QACzE,aAAa;QACb,UAAU;QACV,kBAAkB,EAAE,UAAU,CAAC,MAAM,CAAC,kBAAkB,CAAC;QACzD,SAAS,EAAE,MAAM,CAAC,SAAS,KAAK,IAAI;QACpC,aAAa,EAAE,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC;QAC/C,wBAAwB,EAAE,kBAAkB,CAAC,MAAM,CAAC,wBAAwB,CAAC;QAC7E,wBAAwB,EAAE,kBAAkB,CAAC,MAAM,CAAC,wBAAwB,CAAC;QAC7E,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC;QACvC,eAAe,EAAE,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC;QACnD,cAAc,EAAE,aAAa,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,IAAI,aAAa,KAAK,UAAU;KACxG,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;IAExD,OAAO;QACL,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC3C,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;QACnC,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC;QAC7C,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;QAC7B,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;KACxC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;IAExD,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW,KAAK,IAAI;QACxC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;KACxC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3E,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAE5D,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC"}
@@ -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
+ import type { CamusHlcTimestamp } from './hlc.js';
8
+ /** How the server resolved a cache-hinted `SELECT`. */
9
+ export declare const CamusCacheStatus: {
10
+ /** The statement carried no hint, so the cache was not consulted. */
11
+ readonly None: "none";
12
+ /** A stored result answered the statement. */
13
+ readonly Hit: "hit";
14
+ /** No stored result answered it; this one may now be stored. */
15
+ readonly Miss: "miss";
16
+ /** The cache path was entered and abandoned. `bypassReason` says why. */
17
+ readonly Bypass: "bypass";
18
+ /** A stored result was past its age and was recomputed. */
19
+ readonly StaleRevalidated: "stale-revalidated";
20
+ /** The computed result was dropped before it could be stored. */
21
+ readonly EvictedBeforePublish: "evicted-before-publish";
22
+ /** A status this driver does not know. Read `rawStatus`. */
23
+ readonly Unknown: "unknown";
24
+ };
25
+ export type CamusCacheStatus = (typeof CamusCacheStatus)[keyof typeof CamusCacheStatus];
26
+ /**
27
+ * What the server reported about a cache-hinted `SELECT`.
28
+ *
29
+ * It is present only when the statement entered the cache path, so `undefined` means the statement
30
+ * carried no `{cache=…}` hint. A hinted statement that skipped the cache reports
31
+ * `status: 'bypass'` with a `bypassReason`.
32
+ */
33
+ export interface CamusCacheMetadata {
34
+ /** The parsed status. */
35
+ readonly status: CamusCacheStatus;
36
+ /** The status exactly as the server wrote it. Read it when `status` is `unknown`. */
37
+ readonly rawStatus?: string | undefined;
38
+ /** Why the cache was skipped, or why the result was not stored. Absent otherwise. */
39
+ readonly bypassReason?: string | undefined;
40
+ /** The logical cache family from the hint. Always set when this object is present. */
41
+ readonly name?: string | undefined;
42
+ /** When a served result was computed. Present only on a hit. */
43
+ readonly cachedAtHlc?: CamusHlcTimestamp | undefined;
44
+ /** Roughly how old a served result is, in milliseconds. Present only on a hit. */
45
+ readonly ageMs?: number | undefined;
46
+ /** True when a stored result answered the statement. */
47
+ readonly isHit: boolean;
48
+ }
49
+ /** Builds the public object from the parts a transport decoded. */
50
+ export declare function makeCacheMetadata(parts: {
51
+ rawStatus?: string | undefined;
52
+ bypassReason?: string | undefined;
53
+ name?: string | undefined;
54
+ cachedAtHlc?: CamusHlcTimestamp | undefined;
55
+ ageMs?: number | undefined;
56
+ }): CamusCacheMetadata;
57
+ /**
58
+ * Builds the `{cache=…}` hint a `SELECT` carries to ask for its result to be cached.
59
+ *
60
+ * Put the returned text **immediately after the table reference**, and after its alias when it has
61
+ * one. The hint applies to the whole statement, not only to the table it is attached to, and only
62
+ * one hint per statement is allowed.
63
+ *
64
+ * ```ts
65
+ * const hint = cacheHint('recent_orders', { ttlMs: 30_000 });
66
+ * const result = await client.query(`SELECT id, total FROM orders ${hint} WHERE status = @status`, {
67
+ * status: 1,
68
+ * });
69
+ * ```
70
+ *
71
+ * @param name the logical cache family. It is written into the statement as a bare identifier, so
72
+ * it must be one: a letter or an underscore, then letters, digits, or underscores. A hyphen, a dot
73
+ * and a colon are all parse errors on the server, and are refused here rather than sent.
74
+ * @param options.ttlMs how long a stored result stays fresh, in milliseconds.
75
+ * @param options.strict when true, the server validates each hit against live storage.
76
+ */
77
+ export declare function cacheHint(name: string, options?: {
78
+ ttlMs?: number;
79
+ strict?: boolean;
80
+ }): string;
81
+ /**
82
+ * The statement that drops every cached result in one family, for the current database.
83
+ *
84
+ * The family name is a quoted string here rather than a bare identifier, so it accepts more than
85
+ * `cacheHint` does — a name minted elsewhere, with a hyphen in it, can still be evicted.
86
+ */
87
+ export declare function evictCacheStatement(name: string): string;
88
+ /** The statement that drops every cached result for the current database. */
89
+ export declare function evictAllCacheStatement(): string;
90
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD,uDAAuD;AACvD,eAAO,MAAM,gBAAgB;IAC3B,qEAAqE;;IAErE,8CAA8C;;IAE9C,gEAAgE;;IAEhE,yEAAyE;;IAEzE,2DAA2D;;IAE3D,iEAAiE;;IAEjE,4DAA4D;;CAEpD,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAExF;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAElC,qFAAqF;IACrF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAExC,qFAAqF;IACrF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3C,sFAAsF;IACtF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC,gEAAgE;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAErD,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEpC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,GAAG,kBAAkB,CAYrB;AAuBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAkB9F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD;AAsBD,6EAA6E;AAC7E,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C"}
package/dist/cache.js ADDED
@@ -0,0 +1,121 @@
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 { validateBareName } from './sql-syntax.js';
8
+ /** How the server resolved a cache-hinted `SELECT`. */
9
+ export const CamusCacheStatus = {
10
+ /** The statement carried no hint, so the cache was not consulted. */
11
+ None: 'none',
12
+ /** A stored result answered the statement. */
13
+ Hit: 'hit',
14
+ /** No stored result answered it; this one may now be stored. */
15
+ Miss: 'miss',
16
+ /** The cache path was entered and abandoned. `bypassReason` says why. */
17
+ Bypass: 'bypass',
18
+ /** A stored result was past its age and was recomputed. */
19
+ StaleRevalidated: 'stale-revalidated',
20
+ /** The computed result was dropped before it could be stored. */
21
+ EvictedBeforePublish: 'evicted-before-publish',
22
+ /** A status this driver does not know. Read `rawStatus`. */
23
+ Unknown: 'unknown',
24
+ };
25
+ /** Builds the public object from the parts a transport decoded. */
26
+ export function makeCacheMetadata(parts) {
27
+ const status = parseCacheStatus(parts.rawStatus);
28
+ return {
29
+ status,
30
+ rawStatus: parts.rawStatus,
31
+ bypassReason: parts.bypassReason,
32
+ name: parts.name,
33
+ cachedAtHlc: parts.cachedAtHlc,
34
+ ageMs: parts.ageMs,
35
+ isHit: status === CamusCacheStatus.Hit,
36
+ };
37
+ }
38
+ function parseCacheStatus(status) {
39
+ switch (status) {
40
+ case undefined:
41
+ return CamusCacheStatus.None;
42
+ case 'hit':
43
+ return CamusCacheStatus.Hit;
44
+ case 'miss':
45
+ return CamusCacheStatus.Miss;
46
+ case 'bypass':
47
+ return CamusCacheStatus.Bypass;
48
+ case 'stale-revalidated':
49
+ return CamusCacheStatus.StaleRevalidated;
50
+ case 'evicted-before-publish':
51
+ return CamusCacheStatus.EvictedBeforePublish;
52
+ default:
53
+ return CamusCacheStatus.Unknown;
54
+ }
55
+ }
56
+ const MAX_CACHE_NAME_LENGTH = 128;
57
+ /**
58
+ * Builds the `{cache=…}` hint a `SELECT` carries to ask for its result to be cached.
59
+ *
60
+ * Put the returned text **immediately after the table reference**, and after its alias when it has
61
+ * one. The hint applies to the whole statement, not only to the table it is attached to, and only
62
+ * one hint per statement is allowed.
63
+ *
64
+ * ```ts
65
+ * const hint = cacheHint('recent_orders', { ttlMs: 30_000 });
66
+ * const result = await client.query(`SELECT id, total FROM orders ${hint} WHERE status = @status`, {
67
+ * status: 1,
68
+ * });
69
+ * ```
70
+ *
71
+ * @param name the logical cache family. It is written into the statement as a bare identifier, so
72
+ * it must be one: a letter or an underscore, then letters, digits, or underscores. A hyphen, a dot
73
+ * and a colon are all parse errors on the server, and are refused here rather than sent.
74
+ * @param options.ttlMs how long a stored result stays fresh, in milliseconds.
75
+ * @param options.strict when true, the server validates each hit against live storage.
76
+ */
77
+ export function cacheHint(name, options) {
78
+ validateCacheFamilyIdentifier(name);
79
+ let hint = `{cache=${name}`;
80
+ if (options?.ttlMs !== undefined) {
81
+ const ttl = options.ttlMs;
82
+ if (!Number.isInteger(ttl) || ttl <= 0 || ttl > 2_147_483_647) {
83
+ throw new RangeError('ttlMs must be a positive whole number of milliseconds below 2^31.');
84
+ }
85
+ hint += `, ttl=${String(ttl)}`;
86
+ }
87
+ if (options?.strict === true)
88
+ hint += ', strict';
89
+ return `${hint}}`;
90
+ }
91
+ /**
92
+ * The statement that drops every cached result in one family, for the current database.
93
+ *
94
+ * The family name is a quoted string here rather than a bare identifier, so it accepts more than
95
+ * `cacheHint` does — a name minted elsewhere, with a hyphen in it, can still be evicted.
96
+ */
97
+ export function evictCacheStatement(name) {
98
+ validateBareName(name, MAX_CACHE_NAME_LENGTH, 'name');
99
+ return `EVICT CACHE '${name}'`;
100
+ }
101
+ /**
102
+ * Refuses a family name the server's hint grammar cannot read.
103
+ *
104
+ * The name goes into the statement as a bare identifier, with nothing around it to escape it, so a
105
+ * character outside the identifier set is a parse error rather than an oddly named family. Refusing
106
+ * it here reports the problem where the name was written, rather than as a syntax error naming a
107
+ * column position.
108
+ */
109
+ function validateCacheFamilyIdentifier(name) {
110
+ validateBareName(name, MAX_CACHE_NAME_LENGTH, 'name');
111
+ if (!/^[\p{L}_][\p{L}\p{Nd}_]*$/u.test(name)) {
112
+ throw new TypeError(`The cache family '${name}' is not a bare identifier. A hint writes the name into the ` +
113
+ 'statement unquoted, so it must start with a letter or an underscore and hold only ' +
114
+ 'letters, digits, and underscores.');
115
+ }
116
+ }
117
+ /** The statement that drops every cached result for the current database. */
118
+ export function evictAllCacheStatement() {
119
+ return 'EVICT CACHE ALL';
120
+ }
121
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,uDAAuD;AACvD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,qEAAqE;IACrE,IAAI,EAAE,MAAM;IACZ,8CAA8C;IAC9C,GAAG,EAAE,KAAK;IACV,gEAAgE;IAChE,IAAI,EAAE,MAAM;IACZ,yEAAyE;IACzE,MAAM,EAAE,QAAQ;IAChB,2DAA2D;IAC3D,gBAAgB,EAAE,mBAAmB;IACrC,iEAAiE;IACjE,oBAAoB,EAAE,wBAAwB;IAC9C,4DAA4D;IAC5D,OAAO,EAAE,SAAS;CACV,CAAC;AAkCX,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,KAMjC;IACC,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEjD,OAAO;QACL,MAAM;QACN,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,MAAM,KAAK,gBAAgB,CAAC,GAAG;KACvC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,MAA0B;IAClD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,gBAAgB,CAAC,IAAI,CAAC;QAC/B,KAAK,KAAK;YACR,OAAO,gBAAgB,CAAC,GAAG,CAAC;QAC9B,KAAK,MAAM;YACT,OAAO,gBAAgB,CAAC,IAAI,CAAC;QAC/B,KAAK,QAAQ;YACX,OAAO,gBAAgB,CAAC,MAAM,CAAC;QACjC,KAAK,mBAAmB;YACtB,OAAO,gBAAgB,CAAC,gBAAgB,CAAC;QAC3C,KAAK,wBAAwB;YAC3B,OAAO,gBAAgB,CAAC,oBAAoB,CAAC;QAC/C;YACE,OAAO,gBAAgB,CAAC,OAAO,CAAC;IACpC,CAAC;AACH,CAAC;AAED,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAA8C;IACpF,6BAA6B,CAAC,IAAI,CAAC,CAAC;IAEpC,IAAI,IAAI,GAAG,UAAU,IAAI,EAAE,CAAC;IAE5B,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC;QAE1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,aAAa,EAAE,CAAC;YAC9D,MAAM,IAAI,UAAU,CAAC,mEAAmE,CAAC,CAAC;QAC5F,CAAC;QAED,IAAI,IAAI,SAAS,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACjC,CAAC;IAED,IAAI,OAAO,EAAE,MAAM,KAAK,IAAI;QAAE,IAAI,IAAI,UAAU,CAAC;IAEjD,OAAO,GAAG,IAAI,GAAG,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,gBAAgB,CAAC,IAAI,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACtD,OAAO,gBAAgB,IAAI,GAAG,CAAC;AACjC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,6BAA6B,CAAC,IAAY;IACjD,gBAAgB,CAAC,IAAI,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAEtD,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,SAAS,CACjB,qBAAqB,IAAI,8DAA8D;YACrF,oFAAoF;YACpF,mCAAmC,CACtC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CAAC;AAC3B,CAAC"}