orez-lite 0.9.7
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 +12 -0
- package/dist/browser/generated/sqlite3-browser.wasm +0 -0
- package/dist/browser/generated/sync_wasm.js +922 -0
- package/dist/browser/generated/sync_wasm_bg.wasm +0 -0
- package/dist/browser/host.d.ts +10 -0
- package/dist/browser/host.d.ts.map +1 -0
- package/dist/browser/host.js +496 -0
- package/dist/browser/host.js.map +1 -0
- package/dist/browser/idb-snapshot.d.ts +11 -0
- package/dist/browser/idb-snapshot.d.ts.map +1 -0
- package/dist/browser/idb-snapshot.js +122 -0
- package/dist/browser/idb-snapshot.js.map +1 -0
- package/dist/browser/index.d.ts +5 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +5 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/message-port.d.ts +7 -0
- package/dist/browser/message-port.d.ts.map +1 -0
- package/dist/browser/message-port.js +188 -0
- package/dist/browser/message-port.js.map +1 -0
- package/dist/browser/sqlite-adapter.d.ts +53 -0
- package/dist/browser/sqlite-adapter.d.ts.map +1 -0
- package/dist/browser/sqlite-adapter.js +126 -0
- package/dist/browser/sqlite-adapter.js.map +1 -0
- package/dist/browser/types.d.ts +52 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/cf-deploy/bundle.d.ts +18 -0
- package/dist/cf-deploy/bundle.d.ts.map +1 -0
- package/dist/cf-deploy/bundle.js +273 -0
- package/dist/cf-deploy/bundle.js.map +1 -0
- package/dist/cf-deploy/config.d.ts +12 -0
- package/dist/cf-deploy/config.d.ts.map +1 -0
- package/dist/cf-deploy/config.js +11 -0
- package/dist/cf-deploy/config.js.map +1 -0
- package/dist/cf-deploy/index.d.ts +10 -0
- package/dist/cf-deploy/index.d.ts.map +1 -0
- package/dist/cf-deploy/index.js +12 -0
- package/dist/cf-deploy/index.js.map +1 -0
- package/dist/cf-deploy/leaves.d.ts +8 -0
- package/dist/cf-deploy/leaves.d.ts.map +1 -0
- package/dist/cf-deploy/leaves.js +66 -0
- package/dist/cf-deploy/leaves.js.map +1 -0
- package/dist/cf-deploy/migration.d.ts +27 -0
- package/dist/cf-deploy/migration.d.ts.map +1 -0
- package/dist/cf-deploy/migration.js +734 -0
- package/dist/cf-deploy/migration.js.map +1 -0
- package/dist/cf-deploy/nativeMigrations.d.ts +24 -0
- package/dist/cf-deploy/nativeMigrations.d.ts.map +1 -0
- package/dist/cf-deploy/nativeMigrations.js +185 -0
- package/dist/cf-deploy/nativeMigrations.js.map +1 -0
- package/dist/cf-deploy/prune.d.ts +14 -0
- package/dist/cf-deploy/prune.d.ts.map +1 -0
- package/dist/cf-deploy/prune.js +235 -0
- package/dist/cf-deploy/prune.js.map +1 -0
- package/dist/cf-deploy/readiness.d.ts +11 -0
- package/dist/cf-deploy/readiness.d.ts.map +1 -0
- package/dist/cf-deploy/readiness.js +56 -0
- package/dist/cf-deploy/readiness.js.map +1 -0
- package/dist/cf-deploy/sources.d.ts +3 -0
- package/dist/cf-deploy/sources.d.ts.map +1 -0
- package/dist/cf-deploy/sources.js +24 -0
- package/dist/cf-deploy/sources.js.map +1 -0
- package/dist/cf-deploy/wrangler.d.ts +9 -0
- package/dist/cf-deploy/wrangler.d.ts.map +1 -0
- package/dist/cf-deploy/wrangler.js +48 -0
- package/dist/cf-deploy/wrangler.js.map +1 -0
- package/dist/cf-do/application-sql.d.ts +49 -0
- package/dist/cf-do/application-sql.d.ts.map +1 -0
- package/dist/cf-do/application-sql.js +124 -0
- package/dist/cf-do/application-sql.js.map +1 -0
- package/dist/cf-do/cdc.d.ts +155 -0
- package/dist/cf-do/cdc.d.ts.map +1 -0
- package/dist/cf-do/cdc.js +723 -0
- package/dist/cf-do/cdc.js.map +1 -0
- package/dist/cf-do/cursor-pull.d.ts +27 -0
- package/dist/cf-do/cursor-pull.d.ts.map +1 -0
- package/dist/cf-do/cursor-pull.js +78 -0
- package/dist/cf-do/cursor-pull.js.map +1 -0
- package/dist/cf-do/lite-data-worker.d.ts +171 -0
- package/dist/cf-do/lite-data-worker.d.ts.map +1 -0
- package/dist/cf-do/lite-data-worker.js +685 -0
- package/dist/cf-do/lite-data-worker.js.map +1 -0
- package/dist/cf-do/namespace-backup.d.ts +85 -0
- package/dist/cf-do/namespace-backup.d.ts.map +1 -0
- package/dist/cf-do/namespace-backup.js +470 -0
- package/dist/cf-do/namespace-backup.js.map +1 -0
- package/dist/cf-do/row-undo.d.ts +36 -0
- package/dist/cf-do/row-undo.d.ts.map +1 -0
- package/dist/cf-do/row-undo.js +221 -0
- package/dist/cf-do/row-undo.js.map +1 -0
- package/dist/cf-do/tx-journal.d.ts +118 -0
- package/dist/cf-do/tx-journal.d.ts.map +1 -0
- package/dist/cf-do/tx-journal.js +717 -0
- package/dist/cf-do/tx-journal.js.map +1 -0
- package/dist/cf-do/watermark.d.ts +29 -0
- package/dist/cf-do/watermark.d.ts.map +1 -0
- package/dist/cf-do/watermark.js +105 -0
- package/dist/cf-do/watermark.js.map +1 -0
- package/dist/cf-do/worker.d.ts +282 -0
- package/dist/cf-do/worker.d.ts.map +1 -0
- package/dist/cf-do/worker.js +1999 -0
- package/dist/cf-do/worker.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -0
- package/dist/cloudflare-build.d.ts +9 -0
- package/dist/cloudflare-build.d.ts.map +1 -0
- package/dist/cloudflare-build.js +9 -0
- package/dist/cloudflare-build.js.map +1 -0
- package/dist/cloudflare-bun-wasm-loader.d.ts +2 -0
- package/dist/cloudflare-bun-wasm-loader.d.ts.map +1 -0
- package/dist/cloudflare-bun-wasm-loader.js +2 -0
- package/dist/cloudflare-bun-wasm-loader.js.map +1 -0
- package/dist/cloudflare-query-compiler.d.ts +2 -0
- package/dist/cloudflare-query-compiler.d.ts.map +1 -0
- package/dist/cloudflare-query-compiler.js +2 -0
- package/dist/cloudflare-query-compiler.js.map +1 -0
- package/dist/cloudflare-runtime.d.ts +15 -0
- package/dist/cloudflare-runtime.d.ts.map +1 -0
- package/dist/cloudflare-runtime.js +11 -0
- package/dist/cloudflare-runtime.js.map +1 -0
- package/dist/cloudflare-sync.d.ts +3 -0
- package/dist/cloudflare-sync.d.ts.map +1 -0
- package/dist/cloudflare-sync.js +3 -0
- package/dist/cloudflare-sync.js.map +1 -0
- package/dist/cloudflare-transaction-query.d.ts +2 -0
- package/dist/cloudflare-transaction-query.d.ts.map +1 -0
- package/dist/cloudflare-transaction-query.js +2 -0
- package/dist/cloudflare-transaction-query.js.map +1 -0
- package/dist/cloudflare-vite-wasm-loader.d.ts +2 -0
- package/dist/cloudflare-vite-wasm-loader.d.ts.map +1 -0
- package/dist/cloudflare-vite-wasm-loader.js +2 -0
- package/dist/cloudflare-vite-wasm-loader.js.map +1 -0
- package/dist/cloudflare.d.ts +3 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +3 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/do-sql-tracking.d.ts +114 -0
- package/dist/do-sql-tracking.d.ts.map +1 -0
- package/dist/do-sql-tracking.js +280 -0
- package/dist/do-sql-tracking.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/wake.d.ts +22 -0
- package/dist/wake.d.ts.map +1 -0
- package/dist/wake.js +114 -0
- package/dist/wake.js.map +1 -0
- package/dist/worker/cf-do-shim.d.ts +53 -0
- package/dist/worker/cf-do-shim.d.ts.map +1 -0
- package/dist/worker/cf-do-shim.js +66 -0
- package/dist/worker/cf-do-shim.js.map +1 -0
- package/dist/zero-http/encrypted-column-codec.d.ts +46 -0
- package/dist/zero-http/encrypted-column-codec.d.ts.map +1 -0
- package/dist/zero-http/encrypted-column-codec.js +676 -0
- package/dist/zero-http/encrypted-column-codec.js.map +1 -0
- package/dist/zero-http/encrypted-column-conformance.d.ts +7 -0
- package/dist/zero-http/encrypted-column-conformance.d.ts.map +1 -0
- package/dist/zero-http/encrypted-column-conformance.js +161 -0
- package/dist/zero-http/encrypted-column-conformance.js.map +1 -0
- package/dist/zero-http/fixture-schema.d.ts +127 -0
- package/dist/zero-http/fixture-schema.d.ts.map +1 -0
- package/dist/zero-http/fixture-schema.js +56 -0
- package/dist/zero-http/fixture-schema.js.map +1 -0
- package/dist/zero-http/mount.d.ts +71 -0
- package/dist/zero-http/mount.d.ts.map +1 -0
- package/dist/zero-http/mount.js +594 -0
- package/dist/zero-http/mount.js.map +1 -0
- package/dist/zero-http/payload-codec.d.ts +91 -0
- package/dist/zero-http/payload-codec.d.ts.map +1 -0
- package/dist/zero-http/payload-codec.js +10 -0
- package/dist/zero-http/payload-codec.js.map +1 -0
- package/dist/zero-http/server.d.ts +16 -0
- package/dist/zero-http/server.d.ts.map +1 -0
- package/dist/zero-http/server.js +270 -0
- package/dist/zero-http/server.js.map +1 -0
- package/dist/zero-http/test-harness.d.ts +32 -0
- package/dist/zero-http/test-harness.d.ts.map +1 -0
- package/dist/zero-http/test-harness.js +77 -0
- package/dist/zero-http/test-harness.js.map +1 -0
- package/dist/zero-http/transport.d.ts +71 -0
- package/dist/zero-http/transport.d.ts.map +1 -0
- package/dist/zero-http/transport.js +1106 -0
- package/dist/zero-http/transport.js.map +1 -0
- package/package.json +116 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
export const RETURNING_INTERNAL_PREFIX = '__orez_returning_';
|
|
2
|
+
/** Structured error used by CF-facing layers to return an HTTP 429. */
|
|
3
|
+
export class WriteBudgetExceededError extends Error {
|
|
4
|
+
windowRows;
|
|
5
|
+
budget;
|
|
6
|
+
windowMs;
|
|
7
|
+
error = 'writeBudgetExceeded';
|
|
8
|
+
constructor(windowRows, budget, windowMs) {
|
|
9
|
+
super(`row write budget exceeded: ${windowRows ?? 'unrecorded'}/${budget} rows in ${windowMs}ms`);
|
|
10
|
+
this.windowRows = windowRows;
|
|
11
|
+
this.budget = budget;
|
|
12
|
+
this.windowMs = windowMs;
|
|
13
|
+
this.name = 'WriteBudgetExceededError';
|
|
14
|
+
}
|
|
15
|
+
toJSON() {
|
|
16
|
+
return { error: this.error, windowRows: this.windowRows, budget: this.budget };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* In-memory rolling row counter for a single Durable Object isolate.
|
|
21
|
+
*
|
|
22
|
+
* Persistence is deliberately left to the owner and only needed when the
|
|
23
|
+
* circuit changes state. Updating a SQLite meter row for every application
|
|
24
|
+
* write would itself increase Durable Object rows-written and amplify a burn.
|
|
25
|
+
*/
|
|
26
|
+
export class RollingRowWriteBudget {
|
|
27
|
+
#budgetRows;
|
|
28
|
+
#windowMs;
|
|
29
|
+
#bucketMs;
|
|
30
|
+
#now;
|
|
31
|
+
#samples = [];
|
|
32
|
+
#billableRows = 0;
|
|
33
|
+
#logicalRows = 0;
|
|
34
|
+
#trip = null;
|
|
35
|
+
constructor(options) {
|
|
36
|
+
if (!Number.isSafeInteger(options.budgetRows) || options.budgetRows < 1)
|
|
37
|
+
throw new TypeError('budgetRows must be a positive safe integer');
|
|
38
|
+
if (!Number.isSafeInteger(options.windowMs) || options.windowMs < 1)
|
|
39
|
+
throw new TypeError('windowMs must be a positive safe integer');
|
|
40
|
+
this.#budgetRows = options.budgetRows;
|
|
41
|
+
this.#windowMs = options.windowMs;
|
|
42
|
+
this.#bucketMs = Math.min(1_000, options.windowMs);
|
|
43
|
+
this.#now = options.now;
|
|
44
|
+
}
|
|
45
|
+
#prune(now) {
|
|
46
|
+
const cutoff = now - this.#windowMs;
|
|
47
|
+
let remove = 0;
|
|
48
|
+
while (remove < this.#samples.length &&
|
|
49
|
+
this.#samples[remove].at + this.#bucketMs <= cutoff) {
|
|
50
|
+
this.#billableRows -= this.#samples[remove].billableRows;
|
|
51
|
+
this.#logicalRows -= this.#samples[remove].logicalRows;
|
|
52
|
+
remove++;
|
|
53
|
+
}
|
|
54
|
+
if (remove > 0)
|
|
55
|
+
this.#samples.splice(0, remove);
|
|
56
|
+
}
|
|
57
|
+
status() {
|
|
58
|
+
const now = this.#now();
|
|
59
|
+
this.#prune(now);
|
|
60
|
+
const windowStartedAt = this.#samples[0]?.at ?? null;
|
|
61
|
+
return {
|
|
62
|
+
windowRows: this.#billableRows,
|
|
63
|
+
billableRows: this.#billableRows,
|
|
64
|
+
logicalRows: this.#logicalRows,
|
|
65
|
+
budget: this.#budgetRows,
|
|
66
|
+
windowMs: this.#windowMs,
|
|
67
|
+
windowStartedAt,
|
|
68
|
+
windowEndsAt: windowStartedAt === null ? null : windowStartedAt + this.#windowMs,
|
|
69
|
+
tripped: this.#trip !== null,
|
|
70
|
+
trippedAt: this.#trip?.at ?? null,
|
|
71
|
+
trippedWindowRows: this.#trip?.windowRows ?? null,
|
|
72
|
+
trippedBudget: this.#trip?.budget ?? null,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** The trip to persist, so a restored object still reports what tripped it. */
|
|
76
|
+
trip() {
|
|
77
|
+
return this.#trip;
|
|
78
|
+
}
|
|
79
|
+
/** Trip immediately for an operator-requested, non-destructive write stop. */
|
|
80
|
+
forceTrip() {
|
|
81
|
+
if (this.#trip === null) {
|
|
82
|
+
this.#prune(this.#now());
|
|
83
|
+
this.#trip = {
|
|
84
|
+
at: this.#now(),
|
|
85
|
+
windowRows: this.#billableRows,
|
|
86
|
+
budget: this.#budgetRows,
|
|
87
|
+
windowMs: this.#windowMs,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return this.status();
|
|
91
|
+
}
|
|
92
|
+
assertOpen() {
|
|
93
|
+
const trip = this.#trip;
|
|
94
|
+
if (trip === null)
|
|
95
|
+
return;
|
|
96
|
+
throw new WriteBudgetExceededError(trip.windowRows, trip.budget, trip.windowMs);
|
|
97
|
+
}
|
|
98
|
+
#sample() {
|
|
99
|
+
const now = this.#now();
|
|
100
|
+
this.#prune(now);
|
|
101
|
+
const bucketAt = Math.floor(now / this.#bucketMs) * this.#bucketMs;
|
|
102
|
+
const last = this.#samples[this.#samples.length - 1];
|
|
103
|
+
if (last?.at === bucketAt)
|
|
104
|
+
return last;
|
|
105
|
+
const sample = { at: bucketAt, billableRows: 0, logicalRows: 0 };
|
|
106
|
+
this.#samples.push(sample);
|
|
107
|
+
return sample;
|
|
108
|
+
}
|
|
109
|
+
record(rowsWritten) {
|
|
110
|
+
return this.recordBillable(rowsWritten);
|
|
111
|
+
}
|
|
112
|
+
recordBillable(rowsWritten) {
|
|
113
|
+
this.assertOpen();
|
|
114
|
+
const rows = Number(rowsWritten);
|
|
115
|
+
if (!Number.isSafeInteger(rows) || rows <= 0)
|
|
116
|
+
return this.status();
|
|
117
|
+
const sample = this.#sample();
|
|
118
|
+
sample.billableRows += rows;
|
|
119
|
+
this.#billableRows += rows;
|
|
120
|
+
if (this.#billableRows > this.#budgetRows) {
|
|
121
|
+
this.#trip = {
|
|
122
|
+
at: this.#now(),
|
|
123
|
+
windowRows: this.#billableRows,
|
|
124
|
+
budget: this.#budgetRows,
|
|
125
|
+
windowMs: this.#windowMs,
|
|
126
|
+
};
|
|
127
|
+
throw new WriteBudgetExceededError(this.#billableRows, this.#budgetRows, this.#windowMs);
|
|
128
|
+
}
|
|
129
|
+
return this.status();
|
|
130
|
+
}
|
|
131
|
+
recordLogical(rowsWritten) {
|
|
132
|
+
const rows = Number(rowsWritten);
|
|
133
|
+
if (!Number.isSafeInteger(rows) || rows <= 0)
|
|
134
|
+
return this.status();
|
|
135
|
+
const sample = this.#sample();
|
|
136
|
+
sample.logicalRows += rows;
|
|
137
|
+
this.#logicalRows += rows;
|
|
138
|
+
return this.status();
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Restore a sticky trip from durable storage.
|
|
142
|
+
*
|
|
143
|
+
* Accepts the bare timestamp written before trip counts were persisted. That
|
|
144
|
+
* format cannot say how far over budget the object went, so its count stays
|
|
145
|
+
* unrecorded rather than being reported as zero. Those values disappear the
|
|
146
|
+
* first time the namespace is reopened, which is the only way out anyway.
|
|
147
|
+
*/
|
|
148
|
+
restoreTrip(persisted) {
|
|
149
|
+
const trip = typeof persisted === 'number' ? { at: persisted } : persisted;
|
|
150
|
+
const at = Number(trip?.at);
|
|
151
|
+
if (!Number.isFinite(at) || at <= 0)
|
|
152
|
+
return;
|
|
153
|
+
const windowRows = Number(trip.windowRows);
|
|
154
|
+
const budget = Number(trip.budget);
|
|
155
|
+
const windowMs = Number(trip.windowMs);
|
|
156
|
+
this.#trip = {
|
|
157
|
+
at,
|
|
158
|
+
windowRows: Number.isSafeInteger(windowRows) && windowRows > 0 ? windowRows : null,
|
|
159
|
+
budget: Number.isSafeInteger(budget) && budget > 0 ? budget : this.#budgetRows,
|
|
160
|
+
windowMs: Number.isSafeInteger(windowMs) && windowMs > 0 ? windowMs : this.#windowMs,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
reopen() {
|
|
164
|
+
this.#samples = [];
|
|
165
|
+
this.#billableRows = 0;
|
|
166
|
+
this.#logicalRows = 0;
|
|
167
|
+
this.#trip = null;
|
|
168
|
+
return this.status();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const SQL_MUTATION_RE = /(?:^|;)\s*(?:insert|update|delete|replace|create|alter|drop|truncate|vacuum|reindex)\b/i;
|
|
172
|
+
const SQL_ROW_MUTATION_RE = /(?:^|;)\s*(?:insert|update|delete|replace)\b/i;
|
|
173
|
+
const SQL_WITH_RE = /(?:^|;)\s*with\b/i;
|
|
174
|
+
const SQL_WITH_MUTATION_RE = /\b(?:insert|update|delete|replace)\b/i;
|
|
175
|
+
function sqlWithoutLeadingTrivia(sql) {
|
|
176
|
+
const text = String(sql ?? '');
|
|
177
|
+
if (!text.includes('--') && !text.includes('/*'))
|
|
178
|
+
return text;
|
|
179
|
+
return text.replace(/(^|;)\s*(?:(?:--[^\n]*(?:\n|$))|(?:\/\*[\s\S]*?\*\/))\s*/g, '$1');
|
|
180
|
+
}
|
|
181
|
+
/** Classify a statement once for the write gate, CDC, and logical accounting. */
|
|
182
|
+
export function classifySql(sql) {
|
|
183
|
+
// SqlStorage accepts comments before a statement. Remove only trivia at the
|
|
184
|
+
// beginning (and after statement separators) so a comment cannot bypass the
|
|
185
|
+
// pre-execution gate on a sticky circuit.
|
|
186
|
+
const text = sqlWithoutLeadingTrivia(sql);
|
|
187
|
+
const withMutation = SQL_WITH_RE.test(text) && SQL_WITH_MUTATION_RE.test(text);
|
|
188
|
+
return {
|
|
189
|
+
mutation: SQL_MUTATION_RE.test(text) || withMutation,
|
|
190
|
+
rowMutation: SQL_ROW_MUTATION_RE.test(text) || withMutation,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/** Conservative SQL classifier used to block writes before execution. */
|
|
194
|
+
export function isSqlMutation(sql) {
|
|
195
|
+
return classifySql(sql).mutation;
|
|
196
|
+
}
|
|
197
|
+
/** Row-level DML classifier used to decide when a CDC drain must be atomic. */
|
|
198
|
+
export function isSqlRowMutation(sql) {
|
|
199
|
+
return classifySql(sql).rowMutation;
|
|
200
|
+
}
|
|
201
|
+
/** Normalize Zero's optional PostgreSQL-style public schema prefix. */
|
|
202
|
+
export function stripPublicPrefix(tableName) {
|
|
203
|
+
return tableName.startsWith('public.') ? tableName.slice('public.'.length) : tableName;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Account a mutation cursor's final billing rows as it is consumed.
|
|
207
|
+
*
|
|
208
|
+
* Cloudflare's `rowsWritten` can increase during cursor iteration (notably for
|
|
209
|
+
* `... RETURNING` statements). Sampling only when `sql.exec()` returns misses
|
|
210
|
+
* those writes. This proxy records monotonic deltas after every consumption
|
|
211
|
+
* method while preserving the cursor's native `this` binding.
|
|
212
|
+
*/
|
|
213
|
+
export function trackSqlCursorRowsWritten(cursor, record) {
|
|
214
|
+
if (!cursor || typeof cursor !== 'object')
|
|
215
|
+
return cursor;
|
|
216
|
+
let accountedRows = 0;
|
|
217
|
+
const account = () => {
|
|
218
|
+
const current = Number(cursor.rowsWritten ?? 0);
|
|
219
|
+
if (!Number.isSafeInteger(current) || current <= accountedRows)
|
|
220
|
+
return;
|
|
221
|
+
const delta = current - accountedRows;
|
|
222
|
+
accountedRows = current;
|
|
223
|
+
record(delta);
|
|
224
|
+
};
|
|
225
|
+
const wrapIterator = (iterator) => new Proxy(iterator, {
|
|
226
|
+
get(target, property) {
|
|
227
|
+
const value = Reflect.get(target, property, target);
|
|
228
|
+
if (property === 'next' && typeof value === 'function') {
|
|
229
|
+
return (...args) => {
|
|
230
|
+
try {
|
|
231
|
+
return Reflect.apply(value, target, args);
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
account();
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
let proxy;
|
|
242
|
+
proxy = new Proxy(cursor, {
|
|
243
|
+
get(target, property) {
|
|
244
|
+
const value = Reflect.get(target, property, target);
|
|
245
|
+
if (property === Symbol.iterator) {
|
|
246
|
+
return () => proxy;
|
|
247
|
+
}
|
|
248
|
+
if ((property === 'next' || property === 'one' || property === 'toArray') &&
|
|
249
|
+
typeof value === 'function') {
|
|
250
|
+
return (...args) => {
|
|
251
|
+
try {
|
|
252
|
+
return Reflect.apply(value, target, args);
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
account();
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
if (property === 'raw' && typeof value === 'function') {
|
|
260
|
+
return (...args) => wrapIterator(Reflect.apply(value, target, args));
|
|
261
|
+
}
|
|
262
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
account();
|
|
266
|
+
return proxy;
|
|
267
|
+
}
|
|
268
|
+
export function trackedChangeRow(row, track) {
|
|
269
|
+
const allowed = track.rowColumns ? new Set(track.rowColumns) : null;
|
|
270
|
+
const out = {};
|
|
271
|
+
for (const [key, value] of Object.entries(row)) {
|
|
272
|
+
if (key.startsWith(RETURNING_INTERNAL_PREFIX))
|
|
273
|
+
continue;
|
|
274
|
+
if (allowed && !allowed.has(key))
|
|
275
|
+
continue;
|
|
276
|
+
out[key] = value;
|
|
277
|
+
}
|
|
278
|
+
return out;
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=do-sql-tracking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"do-sql-tracking.js","sourceRoot":"","sources":["../src/do-sql-tracking.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,eAAe,EACf,cAAc,GACf,MAAM,oBAAoB,CAAA;AAC3B,cAAc,yBAAyB,CAAA;AAEvC,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,eAAe,EACf,cAAc,GACf,MAAM,oBAAoB,CAAA;AAC3B,cAAc,yBAAyB,CAAA"}
|
package/dist/wake.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type WakeCapability = {
|
|
2
|
+
readonly namespace: string;
|
|
3
|
+
readonly identity: string;
|
|
4
|
+
readonly expiresAt: number;
|
|
5
|
+
};
|
|
6
|
+
export type MintWakeCapabilityOptions = {
|
|
7
|
+
readonly namespace: string;
|
|
8
|
+
readonly identity: string;
|
|
9
|
+
readonly ttlMs: number;
|
|
10
|
+
};
|
|
11
|
+
export type VerifyWakeCapabilityOptions = {
|
|
12
|
+
readonly namespace: string;
|
|
13
|
+
readonly ttlMs: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function timingSafeEqual(left: string | Uint8Array, right: string | Uint8Array): boolean;
|
|
16
|
+
export declare function verifySharedSecretHeader(request: Request, secret: string, headerName?: string): boolean;
|
|
17
|
+
export declare function mintWakeCapability(secret: string, options: MintWakeCapabilityOptions): Promise<{
|
|
18
|
+
readonly token: string;
|
|
19
|
+
readonly expiresAt: number;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function verifyWakeCapability(secret: string, token: string | null | undefined, options: VerifyWakeCapabilityOptions): Promise<WakeCapability | null>;
|
|
22
|
+
//# sourceMappingURL=wake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake.d.ts","sourceRoot":"","sources":["../src/wake.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAqDD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,WASpF;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,SAAgB,GACzB,OAAO,CAGT;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBjE;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAwChC"}
|
package/dist/wake.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const TOKEN_VERSION = 'v1';
|
|
2
|
+
const SIGNATURE_CONTEXT = 'orez-wake-capability-v1:';
|
|
3
|
+
const MAX_TOKEN_LENGTH = 2048;
|
|
4
|
+
const MAX_NAMESPACE_LENGTH = 200;
|
|
5
|
+
const MAX_IDENTITY_LENGTH = 200;
|
|
6
|
+
const encoder = new TextEncoder();
|
|
7
|
+
const decoder = new TextDecoder();
|
|
8
|
+
function validateSecret(secret) {
|
|
9
|
+
if (!secret)
|
|
10
|
+
throw new TypeError('wake capability secret must not be empty');
|
|
11
|
+
}
|
|
12
|
+
function validateNamespace(namespace) {
|
|
13
|
+
if (!namespace || namespace.length > MAX_NAMESPACE_LENGTH) {
|
|
14
|
+
throw new TypeError('wake capability namespace is invalid');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function validateIdentity(identity) {
|
|
18
|
+
if (!identity || identity.length > MAX_IDENTITY_LENGTH) {
|
|
19
|
+
throw new TypeError('wake capability identity is invalid');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function validateTtl(ttlMs) {
|
|
23
|
+
if (!Number.isSafeInteger(ttlMs) || ttlMs <= 0) {
|
|
24
|
+
throw new TypeError('wake capability ttlMs must be a positive integer');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function encodeBase64Url(bytes) {
|
|
28
|
+
let binary = '';
|
|
29
|
+
for (const byte of bytes)
|
|
30
|
+
binary += String.fromCharCode(byte);
|
|
31
|
+
return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '');
|
|
32
|
+
}
|
|
33
|
+
function decodeBase64Url(value) {
|
|
34
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value))
|
|
35
|
+
throw new TypeError('invalid base64url');
|
|
36
|
+
const base64 = value.replaceAll('-', '+').replaceAll('_', '/');
|
|
37
|
+
const binary = atob(base64.padEnd(Math.ceil(base64.length / 4) * 4, '='));
|
|
38
|
+
return Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
39
|
+
}
|
|
40
|
+
async function sign(secret, payload) {
|
|
41
|
+
const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
42
|
+
return new Uint8Array(await crypto.subtle.sign('HMAC', key, encoder.encode(SIGNATURE_CONTEXT + payload)));
|
|
43
|
+
}
|
|
44
|
+
export function timingSafeEqual(left, right) {
|
|
45
|
+
const leftBytes = typeof left === 'string' ? encoder.encode(left) : left;
|
|
46
|
+
const rightBytes = typeof right === 'string' ? encoder.encode(right) : right;
|
|
47
|
+
const length = Math.max(leftBytes.length, rightBytes.length);
|
|
48
|
+
let difference = leftBytes.length ^ rightBytes.length;
|
|
49
|
+
for (let index = 0; index < length; index++) {
|
|
50
|
+
difference |= (leftBytes[index] ?? 0) ^ (rightBytes[index] ?? 0);
|
|
51
|
+
}
|
|
52
|
+
return difference === 0;
|
|
53
|
+
}
|
|
54
|
+
export function verifySharedSecretHeader(request, secret, headerName = 'x-admin-key') {
|
|
55
|
+
const received = request.headers.get(headerName);
|
|
56
|
+
return received !== null && secret.length > 0 && timingSafeEqual(received, secret);
|
|
57
|
+
}
|
|
58
|
+
export async function mintWakeCapability(secret, options) {
|
|
59
|
+
validateSecret(secret);
|
|
60
|
+
validateNamespace(options.namespace);
|
|
61
|
+
validateIdentity(options.identity);
|
|
62
|
+
validateTtl(options.ttlMs);
|
|
63
|
+
const expiresAt = Date.now() + options.ttlMs;
|
|
64
|
+
const payload = encodeBase64Url(encoder.encode(JSON.stringify({
|
|
65
|
+
namespace: options.namespace,
|
|
66
|
+
identity: options.identity,
|
|
67
|
+
expiresAt,
|
|
68
|
+
})));
|
|
69
|
+
const signature = encodeBase64Url(await sign(secret, payload));
|
|
70
|
+
return { token: `${TOKEN_VERSION}.${payload}.${signature}`, expiresAt };
|
|
71
|
+
}
|
|
72
|
+
export async function verifyWakeCapability(secret, token, options) {
|
|
73
|
+
validateSecret(secret);
|
|
74
|
+
validateNamespace(options.namespace);
|
|
75
|
+
validateTtl(options.ttlMs);
|
|
76
|
+
if (!token || token.length > MAX_TOKEN_LENGTH)
|
|
77
|
+
return null;
|
|
78
|
+
const parts = token.split('.');
|
|
79
|
+
if (parts.length !== 3 || parts[0] !== TOKEN_VERSION)
|
|
80
|
+
return null;
|
|
81
|
+
const payload = parts[1];
|
|
82
|
+
const encodedSignature = parts[2];
|
|
83
|
+
if (!payload || !encodedSignature)
|
|
84
|
+
return null;
|
|
85
|
+
try {
|
|
86
|
+
const signature = decodeBase64Url(encodedSignature);
|
|
87
|
+
if (!timingSafeEqual(signature, await sign(secret, payload)))
|
|
88
|
+
return null;
|
|
89
|
+
const value = JSON.parse(decoder.decode(decodeBase64Url(payload)));
|
|
90
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
91
|
+
return null;
|
|
92
|
+
const capability = value;
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
if (capability.namespace !== options.namespace ||
|
|
95
|
+
typeof capability.identity !== 'string' ||
|
|
96
|
+
!capability.identity ||
|
|
97
|
+
capability.identity.length > MAX_IDENTITY_LENGTH ||
|
|
98
|
+
typeof capability.expiresAt !== 'number' ||
|
|
99
|
+
!Number.isSafeInteger(capability.expiresAt) ||
|
|
100
|
+
capability.expiresAt <= now ||
|
|
101
|
+
capability.expiresAt > now + options.ttlMs) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
namespace: options.namespace,
|
|
106
|
+
identity: capability.identity,
|
|
107
|
+
expiresAt: capability.expiresAt,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=wake.js.map
|
package/dist/wake.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake.js","sourceRoot":"","sources":["../src/wake.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* namespace routing primitives for the Cloudflare Durable Object deploy.
|
|
3
|
+
*
|
|
4
|
+
* a multi-tenant CF/orez deploy shards data into one DO instance per tenant
|
|
5
|
+
* namespace (`ns:<scope>-<id>`) plus a control-plane `singleton`. the worker
|
|
6
|
+
* tiers carry the chosen namespace in a header (and re-stamp it so an inbound
|
|
7
|
+
* value is never trusted) and must validate its shape before routing — an
|
|
8
|
+
* unvalidated namespace would let a client mint unbounded DO instances.
|
|
9
|
+
*
|
|
10
|
+
* The routing decision and security-relevant shape validation live here as
|
|
11
|
+
* pure functions so caller-owned worker entrypoints do not copy the validation
|
|
12
|
+
* regex at every routing site.
|
|
13
|
+
*/
|
|
14
|
+
export interface NamespaceRoutingOptions {
|
|
15
|
+
/** allowed namespace scope prefixes. default `['proj', 'test']`. */
|
|
16
|
+
scopes?: readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* namespace values that resolve to the control-plane `singleton` instance,
|
|
19
|
+
* in addition to the empty string (which is always the singleton).
|
|
20
|
+
*/
|
|
21
|
+
controlPlaneNamespaces?: readonly string[];
|
|
22
|
+
/** request header the worker tiers carry the namespace in. default `x-orez-ns`. */
|
|
23
|
+
nsHeader?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* true when `ns` is a structurally valid tenant namespace: a configured scope
|
|
27
|
+
* prefix followed by a 1-64 char `[A-Za-z0-9_-]` id. this is the gate that
|
|
28
|
+
* keeps a stray header from minting an unbounded DO instance, so every routing
|
|
29
|
+
* site that forwards a namespace should run it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isValidNamespace(ns: string, opts?: NamespaceRoutingOptions): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* resolve a raw namespace string to a DO instance name:
|
|
34
|
+
* - `''` or a control-plane alias -> `'singleton'`
|
|
35
|
+
* - a valid tenant namespace -> `'ns:<ns>'`
|
|
36
|
+
* - anything else -> `null` (caller should reject the request)
|
|
37
|
+
*/
|
|
38
|
+
export declare function doInstanceName(ns: string, opts?: NamespaceRoutingOptions): string | null;
|
|
39
|
+
interface HeaderReader {
|
|
40
|
+
get(name: string): string | null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* read the namespace from a request (the configured header, falling back to the
|
|
44
|
+
* `?ns=` query param) and resolve it to a DO instance name. returns `null` for a
|
|
45
|
+
* structurally invalid namespace so the worker can reply 400 instead of routing.
|
|
46
|
+
*/
|
|
47
|
+
export declare function doInstanceNameForRequest(request: {
|
|
48
|
+
headers: HeaderReader;
|
|
49
|
+
}, url: {
|
|
50
|
+
searchParams: HeaderReader;
|
|
51
|
+
}, opts?: NamespaceRoutingOptions): string | null;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=cf-do-shim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cf-do-shim.d.ts","sourceRoot":"","sources":["../../src/worker/cf-do-shim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1C,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAmBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAET;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,uBAA4B,GACjC,MAAM,GAAG,IAAI,CAOf;AAED,UAAU,YAAY;IACpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CACjC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,EAClC,GAAG,EAAE;IAAE,YAAY,EAAE,YAAY,CAAA;CAAE,EACnC,IAAI,GAAE,uBAA4B,GACjC,MAAM,GAAG,IAAI,CAIf"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* namespace routing primitives for the Cloudflare Durable Object deploy.
|
|
3
|
+
*
|
|
4
|
+
* a multi-tenant CF/orez deploy shards data into one DO instance per tenant
|
|
5
|
+
* namespace (`ns:<scope>-<id>`) plus a control-plane `singleton`. the worker
|
|
6
|
+
* tiers carry the chosen namespace in a header (and re-stamp it so an inbound
|
|
7
|
+
* value is never trusted) and must validate its shape before routing — an
|
|
8
|
+
* unvalidated namespace would let a client mint unbounded DO instances.
|
|
9
|
+
*
|
|
10
|
+
* The routing decision and security-relevant shape validation live here as
|
|
11
|
+
* pure functions so caller-owned worker entrypoints do not copy the validation
|
|
12
|
+
* regex at every routing site.
|
|
13
|
+
*/
|
|
14
|
+
/** default namespace scope prefixes (`proj-<id>`, `test-<id>`). */
|
|
15
|
+
const DEFAULT_SCOPES = ['proj', 'test'];
|
|
16
|
+
function escapeForRegExp(value) {
|
|
17
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
18
|
+
}
|
|
19
|
+
function namespacePattern(scopes) {
|
|
20
|
+
const key = scopes.join('\0');
|
|
21
|
+
let pattern = namespacePatterns.get(key);
|
|
22
|
+
if (!pattern) {
|
|
23
|
+
const group = scopes.map(escapeForRegExp).join('|');
|
|
24
|
+
pattern = new RegExp(`^(?:${group})-[A-Za-z0-9_-]{1,64}$`);
|
|
25
|
+
namespacePatterns.set(key, pattern);
|
|
26
|
+
}
|
|
27
|
+
return pattern;
|
|
28
|
+
}
|
|
29
|
+
const namespacePatterns = new Map();
|
|
30
|
+
/**
|
|
31
|
+
* true when `ns` is a structurally valid tenant namespace: a configured scope
|
|
32
|
+
* prefix followed by a 1-64 char `[A-Za-z0-9_-]` id. this is the gate that
|
|
33
|
+
* keeps a stray header from minting an unbounded DO instance, so every routing
|
|
34
|
+
* site that forwards a namespace should run it.
|
|
35
|
+
*/
|
|
36
|
+
export function isValidNamespace(ns, opts = {}) {
|
|
37
|
+
return namespacePattern(opts.scopes ?? DEFAULT_SCOPES).test(ns);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* resolve a raw namespace string to a DO instance name:
|
|
41
|
+
* - `''` or a control-plane alias -> `'singleton'`
|
|
42
|
+
* - a valid tenant namespace -> `'ns:<ns>'`
|
|
43
|
+
* - anything else -> `null` (caller should reject the request)
|
|
44
|
+
*/
|
|
45
|
+
export function doInstanceName(ns, opts = {}) {
|
|
46
|
+
if (!ns)
|
|
47
|
+
return 'singleton';
|
|
48
|
+
if (ns === 'singleton')
|
|
49
|
+
return 'singleton';
|
|
50
|
+
if ((opts.controlPlaneNamespaces ?? []).includes(ns))
|
|
51
|
+
return 'singleton';
|
|
52
|
+
const raw = ns.startsWith('ns:') ? ns.slice(3) : ns;
|
|
53
|
+
if (!isValidNamespace(raw, opts))
|
|
54
|
+
return null;
|
|
55
|
+
return 'ns:' + raw;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* read the namespace from a request (the configured header, falling back to the
|
|
59
|
+
* `?ns=` query param) and resolve it to a DO instance name. returns `null` for a
|
|
60
|
+
* structurally invalid namespace so the worker can reply 400 instead of routing.
|
|
61
|
+
*/
|
|
62
|
+
export function doInstanceNameForRequest(request, url, opts = {}) {
|
|
63
|
+
const ns = request.headers.get(opts.nsHeader ?? 'x-orez-ns') || url.searchParams.get('ns') || '';
|
|
64
|
+
return doInstanceName(ns, opts);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=cf-do-shim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cf-do-shim.js","sourceRoot":"","sources":["../../src/worker/cf-do-shim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,mEAAmE;AACnE,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,CAAU,CAAA;AAchD,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;AACrD,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAyB;IACjD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC7B,IAAI,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACnD,OAAO,GAAG,IAAI,MAAM,CAAC,OAAO,KAAK,wBAAwB,CAAC,CAAA;QAC1D,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACrC,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAA;AAEnD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,EAAU,EACV,OAAgC,EAAE;IAElC,OAAO,gBAAgB,CAAC,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACjE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,EAAU,EACV,OAAgC,EAAE;IAElC,IAAI,CAAC,EAAE;QAAE,OAAO,WAAW,CAAA;IAC3B,IAAI,EAAE,KAAK,WAAW;QAAE,OAAO,WAAW,CAAA;IAC1C,IAAI,CAAC,IAAI,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,WAAW,CAAA;IACxE,MAAM,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACnD,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAC7C,OAAO,KAAK,GAAG,GAAG,CAAA;AACpB,CAAC;AAMD;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAkC,EAClC,GAAmC,EACnC,OAAgC,EAAE;IAElC,MAAM,EAAE,GACN,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,WAAW,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IACvF,OAAO,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AACjC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { EncryptedColumnManifest, EncryptionKeyring, PayloadCodec } from './payload-codec.js';
|
|
2
|
+
export type { EncryptedColumnManifest, EncryptedRowBatch, EncryptionKeyring, JSONObject, JSONPrimitive, JSONValue, PayloadCodec, PullResponse, PushMutation, PushRequest, } from './payload-codec.js';
|
|
3
|
+
export type RandomBytes = (length: number) => Uint8Array;
|
|
4
|
+
export type X25519KeyPair = {
|
|
5
|
+
readonly privateKey: Uint8Array;
|
|
6
|
+
readonly publicKey: Uint8Array;
|
|
7
|
+
};
|
|
8
|
+
export type HPKECiphertext = {
|
|
9
|
+
readonly encapsulatedKey: Uint8Array;
|
|
10
|
+
readonly ciphertext: Uint8Array;
|
|
11
|
+
};
|
|
12
|
+
export declare function createEncryptedColumnCodec(options: {
|
|
13
|
+
readonly manifest: EncryptedColumnManifest;
|
|
14
|
+
readonly keyring: EncryptionKeyring;
|
|
15
|
+
}): PayloadCodec;
|
|
16
|
+
export declare function deriveX25519KeyPair(inputKeyMaterial: Uint8Array): X25519KeyPair;
|
|
17
|
+
export declare function generateX25519KeyPair(randomBytes: RandomBytes): X25519KeyPair;
|
|
18
|
+
export declare function hpkeSeal(options: {
|
|
19
|
+
readonly recipientPublicKey: Uint8Array;
|
|
20
|
+
readonly plaintext: Uint8Array;
|
|
21
|
+
readonly info?: Uint8Array;
|
|
22
|
+
readonly associatedData?: Uint8Array;
|
|
23
|
+
readonly randomBytes: RandomBytes;
|
|
24
|
+
}): HPKECiphertext;
|
|
25
|
+
export declare function hpkeOpen(options: {
|
|
26
|
+
readonly recipientPrivateKey: Uint8Array;
|
|
27
|
+
readonly encapsulatedKey: Uint8Array;
|
|
28
|
+
readonly ciphertext: Uint8Array;
|
|
29
|
+
readonly info?: Uint8Array;
|
|
30
|
+
readonly associatedData?: Uint8Array;
|
|
31
|
+
}): Uint8Array;
|
|
32
|
+
export declare function wrapContentKey(options: {
|
|
33
|
+
readonly recipientPublicKey: Uint8Array;
|
|
34
|
+
readonly contentKey: Uint8Array;
|
|
35
|
+
readonly info: Uint8Array;
|
|
36
|
+
readonly associatedData: Uint8Array;
|
|
37
|
+
readonly randomBytes: RandomBytes;
|
|
38
|
+
}): HPKECiphertext;
|
|
39
|
+
export declare function unwrapContentKey(options: {
|
|
40
|
+
readonly recipientPrivateKey: Uint8Array;
|
|
41
|
+
readonly encapsulatedKey: Uint8Array;
|
|
42
|
+
readonly ciphertext: Uint8Array;
|
|
43
|
+
readonly info: Uint8Array;
|
|
44
|
+
readonly associatedData: Uint8Array;
|
|
45
|
+
}): Uint8Array;
|
|
46
|
+
//# sourceMappingURL=encrypted-column-codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypted-column-codec.d.ts","sourceRoot":"","sources":["../../src/zero-http/encrypted-column-codec.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,uBAAuB,EAEvB,iBAAiB,EAGjB,YAAY,EAIb,MAAM,oBAAoB,CAAA;AAE3B,YAAY,EACV,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,oBAAoB,CAAA;AAoB3B,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,UAAU,CAAA;AAExD,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;CAChC,CAAA;AAoCD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE;IAClD,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAA;IAC1C,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;CACpC,GAAG,YAAY,CA+Ff;AAED,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,UAAU,GAAG,aAAa,CAU/E;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,CAE7E;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE;IAChC,QAAQ,CAAC,kBAAkB,EAAE,UAAU,CAAA;IACvC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAA;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,UAAU,CAAA;IACpC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;CAClC,GAAG,cAAc,CAqBjB;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE;IAChC,QAAQ,CAAC,mBAAmB,EAAE,UAAU,CAAA;IACxC,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,UAAU,CAAA;CACrC,GAAG,UAAU,CAiBb;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,QAAQ,CAAC,kBAAkB,EAAE,UAAU,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAA;IACnC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;CAClC,GAAG,cAAc,CASjB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,QAAQ,CAAC,mBAAmB,EAAE,UAAU,CAAA;IACxC,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAA;CACpC,GAAG,UAAU,CAIb"}
|