@rexezuge/d1 1.0.0 → 1.0.2

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/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # @rexezuge/d1
2
+
3
+ D1 retry engine, error classifier, `BaseDAO`, SQL splitter, and AES-GCM envelope.
4
+
5
+ Depends on `@rexezuge/errors` (failures surface as `DatabaseError` with the classifier's verdict in `retryable`) and `@rexezuge/shared` (base64 for the crypto envelope).
6
+
7
+ ```bash
8
+ pnpm add @rexezuge/d1
9
+ ```
10
+
11
+ ---
12
+
13
+ ## 1. Retry engine
14
+
15
+ One engine, one schedule — the seven consumer repos each spelled this differently, and divergent schedules were the drift:
16
+
17
+ ```ts
18
+ import { D1_RETRY_DEFAULTS, executeWithRetry } from '@rexezuge/d1';
19
+
20
+ const row = await executeWithRetry((db) => db.prepare('SELECT * FROM users WHERE id = ?').bind(id).first(), {
21
+ maxRetries: D1_RETRY_DEFAULTS.maxRetries, // 3, exponential backoff from 100ms via backoffMs()
22
+ });
23
+ ```
24
+
25
+ Both D1 failure shapes are handled: a resolved `success: false` result and a thrown transport error are classified from the message the same way (`isD1ErrorRetryable` / `RETRYABLE_PATTERNS` / `NON_RETRYABLE_PATTERNS`). `BaseDAO` is the intended caller; call it directly only for statements outside a DAO.
26
+
27
+ ## 2. `BaseDAO` and types
28
+
29
+ ```ts
30
+ import { BaseDAO, assertSqlIdentifier } from '@rexezuge/d1';
31
+
32
+ class UserDAO extends BaseDAO {
33
+ public getById(id: string) {
34
+ return this.first('SELECT * FROM users WHERE id = ?', [id]);
35
+ }
36
+ }
37
+ ```
38
+
39
+ `BaseDAO` wraps every statement in the retry engine. `D1Queryable` / `D1PreparedStatement` / `D1Result` are structural types, so fakes, Miniflare, and real D1 bindings all satisfy them. `assertSqlIdentifier` guards the one thing bindings cannot parameterize — table/column names.
40
+
41
+ ## 3. SQL splitting and schema errors
42
+
43
+ ```ts
44
+ import { executableStatements, isMissingSchemaError, splitSql } from '@rexezuge/d1';
45
+
46
+ const statements = executableStatements(migrationSql); // trigger-aware; comments/stripped, one batch per file
47
+ try {
48
+ await dao.get(normalized);
49
+ } catch (error: unknown) {
50
+ if (isMissingSchemaError(error)) return null; // migration hasn't run — the only safe fall-through
51
+ throw error; // every other failure is an outage, never a silent null
52
+ }
53
+ ```
54
+
55
+ `splitSql` / `isExecutable` power both migrations and `@rexezuge/tooling`'s integration-migration test helper, so a kit migration and a test suite can never disagree about where one statement ends.
56
+
57
+ ## 4. AES-GCM secrets
58
+
59
+ ```ts
60
+ import { decryptSecret, encryptSecret } from '@rexezuge/d1';
61
+
62
+ const { ciphertext, iv } = await encryptSecret(clientSecret, env.BACKUP_ENCRYPTION_KEY); // store the pair
63
+ const cleartext = await decryptSecret(ciphertext, iv, env.BACKUP_ENCRYPTION_KEY);
64
+ ```
65
+
66
+ Key material is base64 of exactly 32 bytes; a missing or wrong-sized key throws `AesGcmKeyError` rather than storing the secret in the clear. The IV is random per call — reusing one under a key destroys GCM's guarantees, which is why it is returned alongside the ciphertext instead of being internal.
67
+
68
+ ---
69
+
70
+ ## Verifying this package
71
+
72
+ ```bash
73
+ pnpm --filter @rexezuge/d1 exec tsc -p tsconfig.json
74
+ pnpm --filter @rexezuge/d1 typecheck
75
+ pnpm --filter @rexezuge/d1 test
76
+ ```
package/dist/BaseDAO.d.ts CHANGED
@@ -3,65 +3,53 @@ import type { D1PreparedStatement, D1Queryable, D1Result } from './D1Types';
3
3
  /**
4
4
  * Canonical DAO base: retry is a policy, methods are a promise.
5
5
  *
6
- * Converged from the nine consumer repos' `BaseDAO`s, which had drifted into
7
- * seven spellings of the same idea (`withRetry`, `runWithRetry`,
8
- * `runWriteStatement`, `firstWithRetry`, `allWithRetry`, `runWriteBatch`, plus
9
- * Mail-Meow's static `findById`). The kit ships one straight-line surface —
10
- * **clients adapt to these names** — with the non-DAO concerns extracted:
6
+ * Converged from the nine consumer repos' BaseDAOs. The API is the **sql-first**
7
+ * shape CalDAV-Bridge and ChordDHT-Tracker used, not the closure-first shape
8
+ * Durable-DAV's family used: a DAO states its SQL and bindings directly, and
9
+ * the retry/normalization wrapper is invisible at the call site. The closure
10
+ * form made every read site pay for a wrapper 90% of them never needed, and
11
+ * each of the two shapes drifted its own method names (`withRetry` vs
12
+ * `run(sql, bindings)`); the sql-first form is what survived.
11
13
  *
12
- * - cursor pagination moved to `@rexezuge/shared`'s `CursorCodec` (it is a
13
- * codec, not a DAO method);
14
- * - subrequest accounting became an injected concern, so the seven repos that
15
- * never needed it do not inherit it;
16
- * - retry policy lives in `D1Retry` — one schedule, one classifier, one place
17
- * the `Failed to <context>` prefix is added.
18
- *
19
- * Identifier safety: `table`/`column` names cannot be bound, so the two methods
20
- * that interpolate them (`deleteOlderThan`) allow-list each segment against
21
- * `/^[A-Za-z_][A-Za-z0-9_]*$/`. Everything else in a statement goes through
22
- * `.bind()`.
14
+ * Non-DAO concerns stay out: cursor pagination lives in `@rexezuge/shared`
15
+ * (`CursorCodec`), subrequest accounting is an injectable port. Retry policy
16
+ * lives in `D1Retry` — one schedule, one classifier, one place the
17
+ * `Failed to <context>` prefix is added.
23
18
  */
24
19
  declare abstract class BaseDAO {
25
20
  protected readonly database: D1Queryable;
26
21
  protected constructor(database: D1Queryable);
22
+ /** A prepared statement with its bindings applied. Bindings are always parameters, never interpolation. */
23
+ protected statement(sql: string, bindings?: unknown[]): D1PreparedStatement;
27
24
  /**
28
- * A mutating statement with retry and a guaranteed `DatabaseError` on
29
- * failure. Every write in this layer goes through here: hand-rolling
30
- * `.run()` plus `if (!result.success) throw` silently produced
31
- * `retryable: false` and skipped the retry entirely — which left the most
32
- * failure-sensitive writes with no recovery from a transient D1 lock.
33
- */
34
- protected run(statement: () => Promise<D1Result>, context: string): Promise<D1Result>;
35
- /**
36
- * A point read. `first()` resolving to `null` is "no row", a success, not an
37
- * error — only a rejected statement is retried and normalized.
25
+ * Run a statement. D1 reports a constraint violation or a missing table by
26
+ * returning `success: false` rather than by throwing, so both forms are
27
+ * normalized to a `DatabaseError` here — ignoring the result form is what
28
+ * let a `UNIQUE` failure reach a caller as an opaque 500.
38
29
  */
39
- protected first<T>(statement: () => Promise<T | null>, context: string): Promise<T | null>;
30
+ protected run(sql: string, bindings?: unknown[]): Promise<D1Result>;
40
31
  /**
41
- * A list read. `.all()` returning `[]` is a success like `first()`'s `null`.
42
- * Separate from `run` because that one is typed for a write's `D1Result`;
43
- * a list read had no retry at all in the drifted copies.
32
+ * Read one row. `first()` resolving to `null` is "no row", a success, not an
33
+ * error; only a rejected statement is retried and normalized. Callers get
34
+ * `undefined` — the shape every repo's row check (`row ? … : …`) already
35
+ * treats as absent, unlike a null.
44
36
  */
45
- protected all<T>(statement: () => Promise<{
46
- results?: T[];
47
- }>, context: string): Promise<T[]>;
48
- /** A scalar count from a `SELECT count(*) AS count` row; 0 when absent. */
49
- protected count(statement: () => Promise<{
50
- count: number;
51
- } | null>, context: string): Promise<number>;
37
+ protected first<T>(sql: string, bindings?: unknown[]): Promise<T | undefined>;
38
+ /** A list read. `.all()` returning `[]` is a success like `first()`'s null. */
39
+ protected all<T>(sql: string, bindings?: unknown[]): Promise<T[]>;
40
+ /** A scalar count from a `SELECT count(*)` row; 0 when absent. */
41
+ protected count(sql: string, bindings?: unknown[]): Promise<number>;
52
42
  /**
53
- * A batch of prepared statements, retried as a unit and unwrapped to the
54
- * per-statement results D1 returns. A single non-success result inside the
55
- * batch is what the engine classifies and retries.
43
+ * A batch of prepared statements — one transaction and one subrequest,
44
+ * however many statements it carries. Each result is checked, so a single
45
+ * failure inside the batch raises rather than passing silently.
56
46
  */
57
- protected batch(statements: D1PreparedStatement[], context: string): Promise<D1Result[]>;
47
+ protected batch(statements: D1PreparedStatement[]): Promise<D1Result[]>;
58
48
  /**
59
49
  * Generic batched delete of rows older than a cutoff, in ID order, with
60
50
  * retry. Mirrors the per-DAO `DELETE ... WHERE id IN (SELECT ... LIMIT ?)`
61
- * pattern that every repo re-implemented per table.
62
- *
63
- * `timeColumn` is compared against `<` — the cutoff is exclusive, so a
64
- * delete never touches a row at exactly the boundary timestamp.
51
+ * pattern that every repo re-implemented per table. The cutoff is exclusive:
52
+ * a delete never touches a row at exactly the boundary timestamp.
65
53
  */
66
54
  protected static deleteOlderThan(db: D1Queryable, table: string, timeColumn: string, cutoff: number | string, limit: number, idColumn: string): Promise<number>;
67
55
  /** The retry schedule, for callers that surface it (health checks, tests). */
@@ -1 +1 @@
1
- {"version":3,"file":"BaseDAO.d.ts","sourceRoot":"","sources":["../src/BaseDAO.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAU5E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,uBAAe,OAAO;IACE,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW;IAA9D,SAAS,aAAgC,QAAQ,EAAE,WAAW;IAE9D;;;;;;OAMG;cACa,GAAG,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI3F;;;OAGG;cACa,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAQhG;;;;OAIG;cACa,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQlG,2EAA2E;cAC3D,KAAK,CACnB,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,EAClD,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAKlB;;;;OAIG;cACa,KAAK,CAAC,UAAU,EAAE,mBAAmB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgB9F;;;;;;;OAOG;qBACoB,eAAe,CACpC,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC;IAsBlB,8EAA8E;IAC9E,SAAS,CAAC,MAAM,KAAK,aAAa,IAAI,OAAO,iBAAiB,CAE7D;CACF;AAED;;;;GAIG;AACH,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"BaseDAO.d.ts","sourceRoot":"","sources":["../src/BaseDAO.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAU5E;;;;;;;;;;;;;;;GAeG;AACH,uBAAe,OAAO;IACE,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW;IAA9D,SAAS,aAAgC,QAAQ,EAAE,WAAW;IAE9D,2GAA2G;IAC3G,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAO,EAAO,GAAG,mBAAmB;IAI/E;;;;;OAKG;cACa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI7E;;;;;OAKG;cACa,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAQvF,+EAA+E;cAC/D,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQ3E,kEAAkE;cAClD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7E;;;;OAIG;cACa,KAAK,CAAC,UAAU,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAa7E;;;;;OAKG;qBACoB,eAAe,CACpC,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC;IAsBlB,8EAA8E;IAC9E,SAAS,CAAC,MAAM,KAAK,aAAa,IAAI,OAAO,iBAAiB,CAE7D;CACF;AAED;;;;GAIG;AACH,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
package/dist/BaseDAO.js CHANGED
@@ -3,94 +3,86 @@ import { D1_RETRY_DEFAULTS, executeWithRetry } from './D1Retry';
3
3
  /**
4
4
  * Canonical DAO base: retry is a policy, methods are a promise.
5
5
  *
6
- * Converged from the nine consumer repos' `BaseDAO`s, which had drifted into
7
- * seven spellings of the same idea (`withRetry`, `runWithRetry`,
8
- * `runWriteStatement`, `firstWithRetry`, `allWithRetry`, `runWriteBatch`, plus
9
- * Mail-Meow's static `findById`). The kit ships one straight-line surface —
10
- * **clients adapt to these names** — with the non-DAO concerns extracted:
6
+ * Converged from the nine consumer repos' BaseDAOs. The API is the **sql-first**
7
+ * shape CalDAV-Bridge and ChordDHT-Tracker used, not the closure-first shape
8
+ * Durable-DAV's family used: a DAO states its SQL and bindings directly, and
9
+ * the retry/normalization wrapper is invisible at the call site. The closure
10
+ * form made every read site pay for a wrapper 90% of them never needed, and
11
+ * each of the two shapes drifted its own method names (`withRetry` vs
12
+ * `run(sql, bindings)`); the sql-first form is what survived.
11
13
  *
12
- * - cursor pagination moved to `@rexezuge/shared`'s `CursorCodec` (it is a
13
- * codec, not a DAO method);
14
- * - subrequest accounting became an injected concern, so the seven repos that
15
- * never needed it do not inherit it;
16
- * - retry policy lives in `D1Retry` — one schedule, one classifier, one place
17
- * the `Failed to <context>` prefix is added.
18
- *
19
- * Identifier safety: `table`/`column` names cannot be bound, so the two methods
20
- * that interpolate them (`deleteOlderThan`) allow-list each segment against
21
- * `/^[A-Za-z_][A-Za-z0-9_]*$/`. Everything else in a statement goes through
22
- * `.bind()`.
14
+ * Non-DAO concerns stay out: cursor pagination lives in `@rexezuge/shared`
15
+ * (`CursorCodec`), subrequest accounting is an injectable port. Retry policy
16
+ * lives in `D1Retry` — one schedule, one classifier, one place the
17
+ * `Failed to <context>` prefix is added.
23
18
  */
24
19
  class BaseDAO {
25
20
  database;
26
21
  constructor(database) {
27
22
  this.database = database;
28
23
  }
24
+ /** A prepared statement with its bindings applied. Bindings are always parameters, never interpolation. */
25
+ statement(sql, bindings = []) {
26
+ return bindings.length > 0 ? this.database.prepare(sql).bind(...bindings) : this.database.prepare(sql);
27
+ }
29
28
  /**
30
- * A mutating statement with retry and a guaranteed `DatabaseError` on
31
- * failure. Every write in this layer goes through here: hand-rolling
32
- * `.run()` plus `if (!result.success) throw` silently produced
33
- * `retryable: false` and skipped the retry entirely — which left the most
34
- * failure-sensitive writes with no recovery from a transient D1 lock.
29
+ * Run a statement. D1 reports a constraint violation or a missing table by
30
+ * returning `success: false` rather than by throwing, so both forms are
31
+ * normalized to a `DatabaseError` here — ignoring the result form is what
32
+ * let a `UNIQUE` failure reach a caller as an opaque 500.
35
33
  */
36
- async run(statement, context) {
37
- return executeWithRetry(statement, context);
34
+ async run(sql, bindings = []) {
35
+ return executeWithRetry(() => this.statement(sql, bindings).run(), 'run statement');
38
36
  }
39
37
  /**
40
- * A point read. `first()` resolving to `null` is "no row", a success, not an
41
- * error — only a rejected statement is retried and normalized.
38
+ * Read one row. `first()` resolving to `null` is "no row", a success, not an
39
+ * error; only a rejected statement is retried and normalized. Callers get
40
+ * `undefined` — the shape every repo's row check (`row ? … : …`) already
41
+ * treats as absent, unlike a null.
42
42
  */
43
- async first(statement, context) {
43
+ async first(sql, bindings = []) {
44
44
  const envelope = await executeWithRetry(async () => {
45
- const value = await statement();
46
- return { success: true, value };
47
- }, context);
48
- return envelope.value;
45
+ const row = await this.statement(sql, bindings).first();
46
+ return { success: true, value: row };
47
+ }, 'read a row');
48
+ return envelope.value ?? undefined;
49
49
  }
50
- /**
51
- * A list read. `.all()` returning `[]` is a success like `first()`'s `null`.
52
- * Separate from `run` because that one is typed for a write's `D1Result`;
53
- * a list read had no retry at all in the drifted copies.
54
- */
55
- async all(statement, context) {
50
+ /** A list read. `.all()` returning `[]` is a success like `first()`'s null. */
51
+ async all(sql, bindings = []) {
56
52
  const envelope = await executeWithRetry(async () => {
57
- const rows = await statement();
53
+ const rows = await this.statement(sql, bindings).all();
58
54
  return { success: true, value: rows.results ?? [] };
59
- }, context);
55
+ }, 'read rows');
60
56
  return envelope.value;
61
57
  }
62
- /** A scalar count from a `SELECT count(*) AS count` row; 0 when absent. */
63
- async count(statement, context) {
64
- const row = await this.first(statement, context);
58
+ /** A scalar count from a `SELECT count(*)` row; 0 when absent. */
59
+ async count(sql, bindings = []) {
60
+ const row = await this.first(sql, bindings);
65
61
  return row?.count ?? 0;
66
62
  }
67
63
  /**
68
- * A batch of prepared statements, retried as a unit and unwrapped to the
69
- * per-statement results D1 returns. A single non-success result inside the
70
- * batch is what the engine classifies and retries.
64
+ * A batch of prepared statements — one transaction and one subrequest,
65
+ * however many statements it carries. Each result is checked, so a single
66
+ * failure inside the batch raises rather than passing silently.
71
67
  */
72
- async batch(statements, context) {
68
+ async batch(statements) {
69
+ if (statements.length === 0)
70
+ return [];
73
71
  if (this.database.batch === undefined) {
74
- throw new DatabaseError(`Batch is not supported for ${context}: the D1 binding exposes no batch()`);
72
+ throw new DatabaseError('The D1 binding exposes no batch() — a multi-statement transaction is not available here');
75
73
  }
76
74
  const envelope = await executeWithRetry(async () => {
77
75
  const results = await this.database.batch(statements);
78
76
  const failed = results.find((result) => !result.success);
79
- return {
80
- success: failed === undefined,
81
- error: failed?.error,
82
- value: results,
83
- };
84
- }, context);
77
+ return { success: failed === undefined, error: failed?.error, value: results };
78
+ }, 'run a batch');
85
79
  return envelope.value;
86
80
  }
87
81
  /**
88
82
  * Generic batched delete of rows older than a cutoff, in ID order, with
89
83
  * retry. Mirrors the per-DAO `DELETE ... WHERE id IN (SELECT ... LIMIT ?)`
90
- * pattern that every repo re-implemented per table.
91
- *
92
- * `timeColumn` is compared against `<` — the cutoff is exclusive, so a
93
- * delete never touches a row at exactly the boundary timestamp.
84
+ * pattern that every repo re-implemented per table. The cutoff is exclusive:
85
+ * a delete never touches a row at exactly the boundary timestamp.
94
86
  */
95
87
  static async deleteOlderThan(db, table, timeColumn, cutoff, limit, idColumn) {
96
88
  assertSqlIdentifier(table, 'table');
@@ -1 +1 @@
1
- {"version":3,"file":"BaseDAO.js","sourceRoot":"","sources":["../src/BaseDAO.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BaseDAO.js","sourceRoot":"","sources":["../src/BaseDAO.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rexezuge/d1",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -25,14 +25,15 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "@rexezuge/shared": "1.0.0",
29
- "@rexezuge/errors": "1.0.0"
28
+ "@rexezuge/errors": "1.0.2",
29
+ "@rexezuge/shared": "1.0.2"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "26.6.4",
33
33
  "typescript": "6.0.3",
34
34
  "vitest": "4.1.11"
35
35
  },
36
+ "description": "D1 retry engine, error classifier, BaseDAO, SQL splitter, and AES-GCM envelope.",
36
37
  "scripts": {
37
38
  "build": "tsc -p tsconfig.json",
38
39
  "typecheck": "tsc -p tsconfig.test.json --noEmit",