tapimo 0.4.1 → 0.4.4
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 +1 -1
- package/dist/ApiKey.d.ts +1 -9
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +2 -3
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +53 -27
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +32 -17
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +1990 -1442
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +23 -9
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +10 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +4 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Auth.d.ts +2 -1
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js +2 -1
- package/dist/Auth.js.map +1 -1
- package/dist/Scope.d.ts +40 -15
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +44 -13
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +560 -9
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +38 -6
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +10 -24
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +10 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +833 -0
- package/dist/admin/apps/organizations.d.ts.map +1 -0
- package/dist/admin/apps/organizations.js +733 -0
- package/dist/admin/apps/organizations.js.map +1 -0
- package/dist/admin/apps/scopes.d.ts +8 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +57 -57
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +53 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +10 -0
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +8 -0
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +9 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +14 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +1304 -1304
- package/dist/apps/data/FundingRouteProviders.d.ts +4 -22
- package/dist/apps/data/FundingRouteProviders.d.ts.map +1 -1
- package/dist/apps/data/FundingRouteProviders.js +10 -120
- package/dist/apps/data/FundingRouteProviders.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +38 -38
- package/dist/apps/data/routes/addresses.d.ts +24 -24
- package/dist/apps/data/routes/blocks.d.ts +39 -39
- package/dist/apps/data/routes/fee-amm.d.ts +20 -20
- package/dist/apps/data/routes/funding.js +7 -7
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/tokenlist.d.ts +12 -12
- package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
- package/dist/apps/management/App.d.ts +808 -267
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -2
- package/dist/apps/management/Billing.d.ts +3 -0
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +7 -2
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +116 -100
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +41 -30
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +182 -50
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +14 -14
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +93 -20
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +12 -15
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +89 -18
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +10 -10
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +100 -40
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +19 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +122 -33
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +12 -13
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts +4 -18
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +6 -7
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +63 -19
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +9 -10
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +38 -4
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/relay/App.d.ts +26 -4
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +17 -14
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/cloudflare.d.ts +2 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +4 -0
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +5 -3
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +52 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +13 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +16 -1
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/adminAuditLogs.d.ts +27 -0
- package/dist/db/tables/adminAuditLogs.d.ts.map +1 -0
- package/dist/db/tables/adminAuditLogs.js +19 -0
- package/dist/db/tables/adminAuditLogs.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +1 -1
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/memberships.d.ts +32 -4
- package/dist/db/tables/memberships.d.ts.map +1 -1
- package/dist/db/tables/memberships.js +31 -0
- package/dist/db/tables/memberships.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +43 -1
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +103 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +25 -0
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +22 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts +26 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +37 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/internal/Auth.d.ts +46 -40
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +118 -69
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cursor.d.ts +1 -1
- package/dist/internal/Cursor.d.ts.map +1 -1
- package/dist/internal/Cursor.js +4 -0
- package/dist/internal/Cursor.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +2 -0
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Errors.d.ts +6 -0
- package/dist/internal/Errors.d.ts.map +1 -0
- package/dist/internal/Errors.js +16 -0
- package/dist/internal/Errors.js.map +1 -0
- package/dist/internal/FundingRoutes.d.ts +15 -43
- package/dist/internal/FundingRoutes.d.ts.map +1 -1
- package/dist/internal/FundingRoutes.js +8 -17
- package/dist/internal/FundingRoutes.js.map +1 -1
- package/dist/internal/Log.d.ts +16 -1
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +5 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/Store.d.ts +61 -16
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +72 -17
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Viem.d.ts +1 -1
- package/dist/internal/index.d.ts +27 -0
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +27 -0
- package/dist/internal/index.js.map +1 -0
- package/package.json +8 -3
- package/src/ApiKey.ts +2 -3
- package/src/ApiKeys.ts +95 -17
- package/src/App.test.ts +104 -6
- package/src/App.ts +29 -9
- package/src/Assets.ts +8 -0
- package/src/Auth.test-d.ts +36 -0
- package/src/Auth.ts +20 -1
- package/src/Client.test-d.ts +17 -17
- package/src/Scope.test.ts +34 -0
- package/src/Scope.ts +53 -17
- package/src/admin/App.test.ts +33 -3
- package/src/admin/App.ts +49 -14
- package/src/admin/apps/api-keys.ts +10 -3
- package/src/admin/apps/organizations.test.ts +455 -0
- package/src/admin/apps/organizations.ts +953 -0
- package/src/admin/apps/scopes.test.ts +10 -0
- package/src/admin/ui/plugin.ts +1 -1
- package/src/admin/ui/src/components/MobileProfile.tsx +2 -0
- package/src/admin/ui/src/components/ThemeToggle.tsx +20 -0
- package/src/admin/ui/src/lib/api-keys.ts +36 -19
- package/src/admin/ui/src/lib/config.ts +2 -3
- package/src/admin/ui/src/lib/organizations.test.ts +89 -0
- package/src/admin/ui/src/lib/organizations.ts +262 -0
- package/src/admin/ui/src/lib/query-client.ts +3 -1
- package/src/admin/ui/src/lib/theme.ts +57 -0
- package/src/admin/ui/src/routeTree.gen.ts +47 -4
- package/src/admin/ui/src/routes/__root.tsx +18 -3
- package/src/admin/ui/src/routes/api-keys.tsx +52 -7
- package/src/admin/ui/src/routes/index.tsx +1 -1
- package/src/admin/ui/src/routes/organizations.tsx +158 -0
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +710 -0
- package/src/admin/ui/src/start.ts +6 -0
- package/src/admin/ui.generated.ts +63 -13
- package/src/analytics/Analytics.ts +25 -0
- package/src/analytics/tables/requestEvents.ts +33 -0
- package/src/apps/composition.test.ts +82 -2
- package/src/apps/data/FundingRouteProviders.test.ts +37 -93
- package/src/apps/data/FundingRouteProviders.ts +14 -161
- package/src/apps/data/routes/funding.test.ts +7 -42
- package/src/apps/data/routes/funding.ts +8 -8
- package/src/apps/data/routes/indexer.test.ts +2 -2
- package/src/apps/data/routes/webhooks.test.ts +2 -2
- package/src/apps/management/App.ts +2 -2
- package/src/apps/management/Billing.ts +10 -2
- package/src/apps/management/routes/api-keys.test.ts +137 -1
- package/src/apps/management/routes/api-keys.ts +63 -38
- package/src/apps/management/routes/billing.ts +14 -14
- package/src/apps/management/routes/invitations.test.ts +102 -1
- package/src/apps/management/routes/invitations.ts +13 -15
- package/src/apps/management/routes/members.ts +10 -10
- package/src/apps/management/routes/orgs.test.ts +78 -16
- package/src/apps/management/routes/orgs.ts +21 -20
- package/src/apps/management/routes/projects.ts +12 -13
- package/src/apps/management/routes/scopes.test.ts +16 -0
- package/src/apps/management/routes/scopes.ts +6 -7
- package/src/apps/management/routes/usage.ts +9 -14
- package/src/apps/mcp.test.ts +72 -7
- package/src/apps/mcp.ts +46 -4
- package/src/apps/relay/App.test.ts +23 -18
- package/src/apps/relay/App.ts +35 -14
- package/src/cloudflare.ts +5 -0
- package/src/db/Db.ts +59 -3
- package/src/db/Schema.ts +20 -1
- package/src/db/tables/adminAuditLogs.ts +47 -0
- package/src/db/tables/invitations.ts +1 -1
- package/src/db/tables/memberships.ts +59 -3
- package/src/db/tables/organizations.ts +148 -1
- package/src/db/tables/projects.ts +47 -0
- package/src/db/tables/webhookDeliveries.ts +83 -0
- package/src/internal/Auth.test.ts +571 -23
- package/src/internal/Auth.ts +166 -94
- package/src/internal/Cursor.test.ts +10 -0
- package/src/internal/Cursor.ts +5 -1
- package/src/internal/EdgeCache.test.ts +11 -0
- package/src/internal/EdgeCache.ts +2 -0
- package/src/internal/FundingRoutes.test.ts +8 -8
- package/src/internal/FundingRoutes.ts +25 -29
- package/src/internal/Log.test.ts +41 -3
- package/src/internal/Log.ts +23 -4
- package/src/internal/Store.test-d.ts +15 -0
- package/src/internal/Store.test.ts +153 -2
- package/src/internal/Store.ts +157 -41
- package/src/internal/index.test.ts +34 -0
- package/src/internal/index.ts +26 -0
package/src/internal/Store.ts
CHANGED
|
@@ -1,9 +1,52 @@
|
|
|
1
1
|
import { Json } from 'ox'
|
|
2
2
|
|
|
3
|
+
/** Key-to-value map used by typed stores. */
|
|
4
|
+
export type StoreItemMap = Record<string, unknown>
|
|
5
|
+
|
|
6
|
+
/** Result of an atomic store update. */
|
|
7
|
+
export type Change<value, result> =
|
|
8
|
+
| {
|
|
9
|
+
/** Leaves the value unchanged. */
|
|
10
|
+
op: 'noop'
|
|
11
|
+
/** Value returned by the update. */
|
|
12
|
+
result: result
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
/** Replaces the stored value. */
|
|
16
|
+
op: 'set'
|
|
17
|
+
/** Value returned by the update. */
|
|
18
|
+
result: result
|
|
19
|
+
/** New stored value. */
|
|
20
|
+
value: value
|
|
21
|
+
}
|
|
22
|
+
| {
|
|
23
|
+
/** Deletes the stored value. */
|
|
24
|
+
op: 'delete'
|
|
25
|
+
/** Value returned by the update. */
|
|
26
|
+
result: result
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Typed store with atomic read-modify-write support. */
|
|
30
|
+
export type AtomicStore<itemMap extends StoreItemMap = StoreItemMap> = {
|
|
31
|
+
/** Deletes a key. */
|
|
32
|
+
delete<key extends keyof itemMap & string>(key: key): Promise<void>
|
|
33
|
+
/** Gets a typed value. */
|
|
34
|
+
get<key extends keyof itemMap & string>(key: key): Promise<itemMap[key] | null>
|
|
35
|
+
/** Writes a typed value. */
|
|
36
|
+
put<key extends keyof itemMap & string>(key: key, value: itemMap[key]): Promise<void>
|
|
37
|
+
/** Atomically updates a typed value. */
|
|
38
|
+
update<key extends keyof itemMap & string, result>(
|
|
39
|
+
key: key,
|
|
40
|
+
fn: (current: itemMap[key] | null) => Change<itemMap[key], result>,
|
|
41
|
+
): Promise<result>
|
|
42
|
+
}
|
|
43
|
+
|
|
3
44
|
/** Minimal string store contract used by Tempo API internals. */
|
|
4
45
|
export type Store = {
|
|
5
46
|
/** Deletes a key. */
|
|
6
47
|
delete(key: string): Promise<void>
|
|
48
|
+
/** Deletes a key only when its value matches `expected`. */
|
|
49
|
+
deleteIf?: ((key: string, expected: null | string) => Promise<boolean>) | undefined
|
|
7
50
|
/** Gets a string value. Returns `null` for missing or expired keys. */
|
|
8
51
|
get(key: string): Promise<null | string>
|
|
9
52
|
/**
|
|
@@ -77,6 +120,9 @@ export namespace Store {
|
|
|
77
120
|
*/
|
|
78
121
|
export type State = Store & { type: 'state' }
|
|
79
122
|
|
|
123
|
+
/** Authoritative string state that also supports typed atomic operations. */
|
|
124
|
+
export type AtomicState<itemMap extends StoreItemMap = StoreItemMap> = AtomicStore<itemMap> & State
|
|
125
|
+
|
|
80
126
|
/**
|
|
81
127
|
* Wraps store operations into a {@link Store}, defaulting to an authoritative
|
|
82
128
|
* {@link State} store. Omit `type` for the common authoritative case; pass
|
|
@@ -136,7 +182,7 @@ export async function update(
|
|
|
136
182
|
fn: (current: null | string) => string,
|
|
137
183
|
options: update.Options = {},
|
|
138
184
|
): Promise<string> {
|
|
139
|
-
const { attempts =
|
|
185
|
+
const { attempts = updateAttempts, ...put } = options
|
|
140
186
|
|
|
141
187
|
if (!store.swap) {
|
|
142
188
|
const next = fn(await store.get(key))
|
|
@@ -152,6 +198,8 @@ export async function update(
|
|
|
152
198
|
throw new UpdateContentionError(key, attempts)
|
|
153
199
|
}
|
|
154
200
|
|
|
201
|
+
const updateAttempts = 8
|
|
202
|
+
|
|
155
203
|
export declare namespace update {
|
|
156
204
|
/** Options for {@link update}. */
|
|
157
205
|
type Options = Store.PutOptions & {
|
|
@@ -187,6 +235,11 @@ export function memory(options: memory.Options = {}): State {
|
|
|
187
235
|
async delete(key) {
|
|
188
236
|
cells.delete(key)
|
|
189
237
|
},
|
|
238
|
+
async deleteIf(key, expected) {
|
|
239
|
+
if ((read(key)?.value ?? null) !== expected) return false
|
|
240
|
+
cells.delete(key)
|
|
241
|
+
return true
|
|
242
|
+
},
|
|
190
243
|
async get(key) {
|
|
191
244
|
return read(key)?.value ?? null
|
|
192
245
|
},
|
|
@@ -347,21 +400,26 @@ export declare namespace cloudflareKv {
|
|
|
347
400
|
}
|
|
348
401
|
}
|
|
349
402
|
|
|
350
|
-
|
|
403
|
+
/** Creates typed atomic state over namespace RPC, or raw object storage state. */
|
|
404
|
+
export function durableObject(namespace: durableObject.Namespace): durableObject.ReturnValue
|
|
351
405
|
export function durableObject(
|
|
352
406
|
namespace: durableObject.Namespace,
|
|
353
407
|
options: durableObject.Options,
|
|
354
|
-
):
|
|
355
|
-
|
|
408
|
+
): durableObject.ReturnValue
|
|
409
|
+
export function durableObject<const itemMap extends StoreItemMap>(
|
|
410
|
+
namespace: durableObject.Namespace,
|
|
411
|
+
): AtomicState<itemMap>
|
|
412
|
+
export function durableObject<const itemMap extends StoreItemMap>(
|
|
413
|
+
namespace: durableObject.Namespace,
|
|
414
|
+
options: durableObject.Options,
|
|
415
|
+
): AtomicState<itemMap>
|
|
416
|
+
export function durableObject(storage: durableObject.Storage): State
|
|
356
417
|
export function durableObject(
|
|
357
418
|
target: durableObject.Namespace | durableObject.Storage,
|
|
358
|
-
options
|
|
359
|
-
): State {
|
|
360
|
-
if (durableObjectNamespace(target))
|
|
361
|
-
|
|
362
|
-
if (name === undefined) throw new TypeError('Durable Object name is required')
|
|
363
|
-
return durableObjectStub(target, name)
|
|
364
|
-
}
|
|
419
|
+
options: durableObject.Options = {},
|
|
420
|
+
): durableObject.ReturnValue | State {
|
|
421
|
+
if (durableObjectNamespace(target))
|
|
422
|
+
return durableObjectStub(target, options.name ?? ((key) => key))
|
|
365
423
|
return durableObjectStorage(target)
|
|
366
424
|
}
|
|
367
425
|
|
|
@@ -370,6 +428,13 @@ function durableObjectStorage(storage: durableObject.Storage): State {
|
|
|
370
428
|
async delete(key) {
|
|
371
429
|
await storage.delete(key)
|
|
372
430
|
},
|
|
431
|
+
// Storage input gates prevent writes between comparison and deletion.
|
|
432
|
+
async deleteIf(key, expected) {
|
|
433
|
+
const current = (await durableObjectRead(storage, key, await storage.get(key)))?.value ?? null
|
|
434
|
+
if (current !== expected) return false
|
|
435
|
+
await storage.delete(key)
|
|
436
|
+
return true
|
|
437
|
+
},
|
|
373
438
|
async get(key) {
|
|
374
439
|
return (await durableObjectRead(storage, key, await storage.get(key)))?.value ?? null
|
|
375
440
|
},
|
|
@@ -408,6 +473,19 @@ function durableObjectStorage(storage: durableObject.Storage): State {
|
|
|
408
473
|
}
|
|
409
474
|
|
|
410
475
|
export declare namespace durableObject {
|
|
476
|
+
/** Durable Object state assignable to any typed item map. */
|
|
477
|
+
type ReturnValue = State & {
|
|
478
|
+
/** Gets a contextually typed value. */
|
|
479
|
+
get<value = unknown>(key: string): Promise<value | null>
|
|
480
|
+
/** Writes a typed value. */
|
|
481
|
+
put<value>(key: string, value: value, options?: Store.PutOptions): Promise<void>
|
|
482
|
+
/** Atomically updates a contextually typed value. */
|
|
483
|
+
update<value, result>(
|
|
484
|
+
key: string,
|
|
485
|
+
fn: (current: value | null) => Change<value, result>,
|
|
486
|
+
): Promise<result>
|
|
487
|
+
}
|
|
488
|
+
|
|
411
489
|
/** Minimal Durable Object namespace shape used by this adapter. */
|
|
412
490
|
type Namespace = {
|
|
413
491
|
/** Gets the Durable Object stub for a stable object name. */
|
|
@@ -416,13 +494,8 @@ export declare namespace durableObject {
|
|
|
416
494
|
|
|
417
495
|
/** Options for creating a store from a Durable Object namespace. */
|
|
418
496
|
type Options = {
|
|
419
|
-
/**
|
|
420
|
-
|
|
421
|
-
* (enumerable via `list`). A resolver function shards keys across objects
|
|
422
|
-
* (`name(key)` per operation) so each key's object is created near the
|
|
423
|
-
* traffic that uses it — sharded stores cannot `list`.
|
|
424
|
-
*/
|
|
425
|
-
name: string | ((key: string) => string)
|
|
497
|
+
/** Static pins all keys; a resolver shards them; omission shards by key. */
|
|
498
|
+
name?: string | ((key: string) => string) | undefined
|
|
426
499
|
}
|
|
427
500
|
|
|
428
501
|
/** Minimal Cloudflare Durable Object storage shape used by this adapter. */
|
|
@@ -440,14 +513,10 @@ export declare namespace durableObject {
|
|
|
440
513
|
put<value>(key: string, value: value): Promise<void>
|
|
441
514
|
}
|
|
442
515
|
|
|
443
|
-
/**
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
* `tapimo/cloudflare` `DurableObject` class, whose RPC surface implements
|
|
448
|
-
* them.
|
|
449
|
-
*/
|
|
450
|
-
type Stub = Omit<Store, 'increment' | 'swap' | 'type'> & {
|
|
516
|
+
/** RPC store operations used by the namespace adapter. */
|
|
517
|
+
type Stub = Omit<Store, 'deleteIf' | 'increment' | 'swap' | 'type'> & {
|
|
518
|
+
/** Atomically deletes a matching value inside the object. */
|
|
519
|
+
deleteIf(key: string, expected: null | string): Promise<boolean>
|
|
451
520
|
/** Atomically increments an integer counter inside the object. */
|
|
452
521
|
increment(key: string, options?: Store.PutOptions): Promise<number>
|
|
453
522
|
/** Atomically compares-and-swaps a value inside the object. */
|
|
@@ -533,40 +602,58 @@ function durableObjectNamespace(
|
|
|
533
602
|
function durableObjectStub(
|
|
534
603
|
namespace: durableObject.Namespace,
|
|
535
604
|
name: string | ((key: string) => string),
|
|
536
|
-
):
|
|
605
|
+
): durableObject.ReturnValue {
|
|
537
606
|
// Durable Object stubs are request-scoped I/O objects in Workers, so
|
|
538
607
|
// resolve the stub inside each store operation instead of caching it.
|
|
539
608
|
const stub = (key: string) => namespace.getByName(typeof name === 'function' ? name(key) : name)
|
|
540
609
|
|
|
541
|
-
return
|
|
542
|
-
async delete(key) {
|
|
610
|
+
return {
|
|
611
|
+
async delete(key: string) {
|
|
543
612
|
await durableObjectRetry(() => stub(key).delete(key))
|
|
544
613
|
},
|
|
545
|
-
async
|
|
546
|
-
|
|
614
|
+
async deleteIf(key: string, expected: null | string) {
|
|
615
|
+
const encoded = expected === null ? null : durableObjectEncode(expected)
|
|
616
|
+
return stub(key).deleteIf(key, encoded)
|
|
617
|
+
},
|
|
618
|
+
async get(key: string) {
|
|
619
|
+
return durableObjectDecode(await durableObjectRetry(() => stub(key).get(key)))
|
|
547
620
|
},
|
|
548
621
|
// Native RPC increment: the read-modify-write runs inside the object
|
|
549
622
|
// (one round trip, atomic) instead of the get + put fallback (two).
|
|
550
|
-
async increment(key, options) {
|
|
623
|
+
async increment(key: string, options?: Store.PutOptions) {
|
|
551
624
|
return durableObjectRetry(() => stub(key).increment(key, options))
|
|
552
625
|
},
|
|
553
|
-
async list(options) {
|
|
626
|
+
async list(options?: Parameters<Store['list']>[0]) {
|
|
554
627
|
// A sharded store scatters keys across objects, so no single object can
|
|
555
628
|
// enumerate them.
|
|
556
629
|
if (typeof name === 'function')
|
|
557
630
|
throw new TypeError('cannot list a sharded Durable Object store')
|
|
558
631
|
return durableObjectRetry(() => stub('').list(options))
|
|
559
632
|
},
|
|
560
|
-
async put(key, value, options) {
|
|
561
|
-
await durableObjectRetry(() => stub(key).put(key, value, options))
|
|
633
|
+
async put(key: string, value: unknown, options?: Store.PutOptions) {
|
|
634
|
+
await durableObjectRetry(() => stub(key).put(key, durableObjectEncode(value), options))
|
|
562
635
|
},
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
async swap(key, expected, next, options) {
|
|
567
|
-
return durableObjectRetry(() => stub(key).swap(key, expected, next, options))
|
|
636
|
+
async swap(key: string, expected: null | string, next: string, options?: Store.PutOptions) {
|
|
637
|
+
const encoded = expected === null ? null : durableObjectEncode(expected)
|
|
638
|
+
return stub(key).swap(key, encoded, durableObjectEncode(next), options)
|
|
568
639
|
},
|
|
569
|
-
|
|
640
|
+
type: 'state' as const,
|
|
641
|
+
async update<result>(key: string, fn: (current: unknown) => Change<unknown, result>) {
|
|
642
|
+
for (let attempt = 0; attempt < updateAttempts; attempt++) {
|
|
643
|
+
const current = await durableObjectRetry(() => stub(key).get(key))
|
|
644
|
+
const change = fn(durableObjectDecode(current))
|
|
645
|
+
if (change.op === 'noop') return change.result
|
|
646
|
+
|
|
647
|
+
// Retrying an ambiguous CAS can apply the transform twice.
|
|
648
|
+
const changed =
|
|
649
|
+
change.op === 'set'
|
|
650
|
+
? await stub(key).swap(key, current, durableObjectEncode(change.value))
|
|
651
|
+
: await stub(key).deleteIf(key, current)
|
|
652
|
+
if (changed) return change.result
|
|
653
|
+
}
|
|
654
|
+
throw new UpdateContentionError(key, updateAttempts)
|
|
655
|
+
},
|
|
656
|
+
} as durableObject.ReturnValue
|
|
570
657
|
}
|
|
571
658
|
|
|
572
659
|
/**
|
|
@@ -588,6 +675,26 @@ async function durableObjectRetry<value>(call: () => Promise<value>): Promise<va
|
|
|
588
675
|
}
|
|
589
676
|
}
|
|
590
677
|
|
|
678
|
+
const durableObjectCodecRoot = 'tempo-api:store:json:'
|
|
679
|
+
const durableObjectCodecVersion = 'v1'
|
|
680
|
+
const durableObjectCodecPrefix = `${durableObjectCodecRoot}${durableObjectCodecVersion}:`
|
|
681
|
+
|
|
682
|
+
function durableObjectEncode(value: unknown): string {
|
|
683
|
+
if (typeof value === 'string' && !value.startsWith(durableObjectCodecRoot)) return value
|
|
684
|
+
const encoded = Json.stringify(value)
|
|
685
|
+
if (encoded === undefined) throw new TypeError('Durable Object store value is not serializable')
|
|
686
|
+
return `${durableObjectCodecPrefix}${encoded}`
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
function durableObjectDecode(value: null | string): unknown {
|
|
690
|
+
if (value === null || !value.startsWith(durableObjectCodecRoot)) return value
|
|
691
|
+
if (!value.startsWith(durableObjectCodecPrefix)) {
|
|
692
|
+
const [version] = value.slice(durableObjectCodecRoot.length).split(':')
|
|
693
|
+
throw new DurableObjectCodecError(version)
|
|
694
|
+
}
|
|
695
|
+
return Json.parse(value.slice(durableObjectCodecPrefix.length))
|
|
696
|
+
}
|
|
697
|
+
|
|
591
698
|
function cloudflareKvExpirationTtl(ttl: number | undefined) {
|
|
592
699
|
if (ttl === undefined) return undefined
|
|
593
700
|
if (ttl <= 0) return 0
|
|
@@ -649,3 +756,12 @@ export class UpdateContentionError extends Error {
|
|
|
649
756
|
super(`Store update on "${key}" lost ${attempts} compare-and-swap attempts.`)
|
|
650
757
|
}
|
|
651
758
|
}
|
|
759
|
+
|
|
760
|
+
/** Thrown when Durable Object state uses an unsupported codec. */
|
|
761
|
+
export class DurableObjectCodecError extends Error {
|
|
762
|
+
override name = 'Store.DurableObjectCodecError'
|
|
763
|
+
|
|
764
|
+
constructor(version: unknown) {
|
|
765
|
+
super(`Unsupported Durable Object store codec version: ${String(version)}`)
|
|
766
|
+
}
|
|
767
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as Internal from './index.js'
|
|
2
|
+
|
|
3
|
+
test('exports internal modules', () => {
|
|
4
|
+
expect(Object.keys(Internal)).toMatchInlineSnapshot(`
|
|
5
|
+
[
|
|
6
|
+
"Auth",
|
|
7
|
+
"Cache",
|
|
8
|
+
"Cursor",
|
|
9
|
+
"EdgeCache",
|
|
10
|
+
"Errors",
|
|
11
|
+
"Fees",
|
|
12
|
+
"FundingRoutes",
|
|
13
|
+
"Id",
|
|
14
|
+
"Log",
|
|
15
|
+
"MetricSink",
|
|
16
|
+
"Mpp",
|
|
17
|
+
"OpenApi",
|
|
18
|
+
"Path",
|
|
19
|
+
"RateLimit",
|
|
20
|
+
"Response",
|
|
21
|
+
"RpcSchema",
|
|
22
|
+
"Schema",
|
|
23
|
+
"Store",
|
|
24
|
+
"Tidx",
|
|
25
|
+
"Timing",
|
|
26
|
+
"Ttl",
|
|
27
|
+
"Value",
|
|
28
|
+
"VerifiedTokens",
|
|
29
|
+
"Viem",
|
|
30
|
+
"WebhookDestination",
|
|
31
|
+
"Webhooks",
|
|
32
|
+
]
|
|
33
|
+
`)
|
|
34
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * as Auth from './Auth.js'
|
|
2
|
+
export * as Cache from './Cache.js'
|
|
3
|
+
export * as Cursor from './Cursor.js'
|
|
4
|
+
export * as EdgeCache from './EdgeCache.js'
|
|
5
|
+
export * as Errors from './Errors.js'
|
|
6
|
+
export * as Fees from './Fees.js'
|
|
7
|
+
export * as FundingRoutes from './FundingRoutes.js'
|
|
8
|
+
export * as Id from './Id.js'
|
|
9
|
+
export * as Log from './Log.js'
|
|
10
|
+
export * as MetricSink from './MetricSink.js'
|
|
11
|
+
export * as Mpp from './Mpp.js'
|
|
12
|
+
export * as OpenApi from './OpenApi.js'
|
|
13
|
+
export * as Path from './Path.js'
|
|
14
|
+
export * as RateLimit from './RateLimit.js'
|
|
15
|
+
export * as Response from './Response.js'
|
|
16
|
+
export * as RpcSchema from './RpcSchema.js'
|
|
17
|
+
export * as Schema from './Schema.js'
|
|
18
|
+
export * as Store from './Store.js'
|
|
19
|
+
export * as Tidx from './Tidx.js'
|
|
20
|
+
export * as Timing from './Timing.js'
|
|
21
|
+
export * as Ttl from './Ttl.js'
|
|
22
|
+
export * as Value from './Value.js'
|
|
23
|
+
export * as VerifiedTokens from './VerifiedTokens.js'
|
|
24
|
+
export * as Viem from './Viem.js'
|
|
25
|
+
export * as WebhookDestination from './WebhookDestination.js'
|
|
26
|
+
export * as Webhooks from './Webhooks.js'
|