@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 +76 -0
- package/dist/BaseDAO.d.ts +33 -45
- package/dist/BaseDAO.d.ts.map +1 -1
- package/dist/BaseDAO.js +48 -56
- package/dist/BaseDAO.js.map +1 -1
- package/package.json +4 -3
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'
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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
|
|
30
|
+
protected run(sql: string, bindings?: unknown[]): Promise<D1Result>;
|
|
40
31
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
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
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
/** A scalar count from a `SELECT count(*)
|
|
49
|
-
protected count(
|
|
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
|
|
54
|
-
*
|
|
55
|
-
*
|
|
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[]
|
|
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). */
|
package/dist/BaseDAO.d.ts.map
CHANGED
|
@@ -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
|
|
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'
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
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(
|
|
37
|
-
return executeWithRetry(statement,
|
|
34
|
+
async run(sql, bindings = []) {
|
|
35
|
+
return executeWithRetry(() => this.statement(sql, bindings).run(), 'run statement');
|
|
38
36
|
}
|
|
39
37
|
/**
|
|
40
|
-
*
|
|
41
|
-
* error
|
|
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(
|
|
43
|
+
async first(sql, bindings = []) {
|
|
44
44
|
const envelope = await executeWithRetry(async () => {
|
|
45
|
-
const
|
|
46
|
-
return { success: true, value };
|
|
47
|
-
},
|
|
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
|
-
|
|
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
|
-
},
|
|
55
|
+
}, 'read rows');
|
|
60
56
|
return envelope.value;
|
|
61
57
|
}
|
|
62
|
-
/** A scalar count from a `SELECT count(*)
|
|
63
|
-
async count(
|
|
64
|
-
const row = await this.first(
|
|
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
|
|
69
|
-
*
|
|
70
|
-
*
|
|
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
|
|
68
|
+
async batch(statements) {
|
|
69
|
+
if (statements.length === 0)
|
|
70
|
+
return [];
|
|
73
71
|
if (this.database.batch === undefined) {
|
|
74
|
-
throw new DatabaseError(
|
|
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
|
-
|
|
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');
|
package/dist/BaseDAO.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseDAO.js","sourceRoot":"","sources":["../src/BaseDAO.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAWhE
|
|
1
|
+
{"version":3,"file":"BaseDAO.js","sourceRoot":"","sources":["../src/BaseDAO.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAWhE;;;;;;;;;;;;;;;GAeG;AACH,MAAe,OAAO;IACqB;IAAzC,YAAyC,QAAqB;QAArB,aAAQ,GAAR,QAAQ,CAAa;IAAG,CAAC;IAElE,2GAA2G;IACjG,SAAS,CAAC,GAAW,EAAE,WAAsB,EAAE;QACvD,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzG,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,WAAsB,EAAE;QACvD,OAAO,gBAAgB,CAAC,GAAsB,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;IACzG,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,KAAK,CAAI,GAAW,EAAE,WAAsB,EAAE;QAC5D,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,KAAK,IAA0C,EAAE;YACvF,MAAM,GAAG,GAAa,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,KAAK,EAAK,CAAC;YACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACvC,CAAC,EAAE,YAAY,CAAC,CAAC;QACjB,OAAO,QAAQ,CAAC,KAAK,IAAI,SAAS,CAAC;IACrC,CAAC;IAED,+EAA+E;IACrE,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,WAAsB,EAAE;QAC1D,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,KAAK,IAAqC,EAAE;YAClF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAK,CAAC;YAC1D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACtD,CAAC,EAAE,WAAW,CAAC,CAAC;QAChB,OAAO,QAAQ,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,kEAAkE;IACxD,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,WAAsB,EAAE;QACzD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAoB,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC/D,OAAO,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,KAAK,CAAC,UAAiC;QACrD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACtC,MAAM,IAAI,aAAa,CAAC,yFAAyF,CAAC,CAAC;QACrH,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,KAAK,IAA4C,EAAE;YACzF,MAAM,OAAO,GAAe,MAAO,IAAI,CAAC,QAAQ,CAAC,KAA2C,CAAC,UAAU,CAAC,CAAC;YACzG,MAAM,MAAM,GAAyB,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxF,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QACjF,CAAC,EAAE,aAAa,CAAC,CAAC;QAClB,OAAO,QAAQ,CAAC,KAAK,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACO,MAAM,CAAC,KAAK,CAAC,eAAe,CACpC,EAAe,EACf,KAAa,EACb,UAAkB,EAClB,MAAuB,EACvB,KAAa,EACb,QAAgB;QAEhB,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACpC,mBAAmB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAC9C,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAa,MAAM,gBAAgB,CAC7C,GAAsB,EAAE,CACtB,EAAE;aACC,OAAO,CACN,eAAe,KAAK;qBACX,QAAQ;wBACL,QAAQ,SAAS,KAAK;uBACvB,UAAU;;eAElB,CACJ;aACA,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;aACnB,GAAG,EAAE,EACV,wBAAwB,KAAK,EAAE,CAChC,CAAC;QACF,OAAQ,MAAM,CAAC,IAA6B,EAAE,OAAO,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED,8EAA8E;IACpE,MAAM,KAAK,aAAa;QAChC,OAAO,iBAAiB,CAAC;IAC3B,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,KAAa,EAAE,KAAa;IACvD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rexezuge/d1",
|
|
3
|
-
"version": "1.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/
|
|
29
|
-
"@rexezuge/
|
|
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",
|