experimental-a2 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +207 -0
- package/dist/ai-CFNeCrRl.d.ts +334 -0
- package/dist/ai-CFNeCrRl.d.ts.map +1 -0
- package/dist/ai-server.browser.js +2 -0
- package/dist/ai-server.browser.js.map +1 -0
- package/dist/ai-server.d.ts +49 -9
- package/dist/ai-server.d.ts.map +1 -0
- package/dist/ai-server.js +123 -49
- package/dist/ai-server.js.map +1 -0
- package/dist/ai.d.ts +2 -303
- package/dist/ai.js +233 -86
- package/dist/ai.js.map +1 -0
- package/dist/cli-B3VuxoDe.js +599 -0
- package/dist/cli-B3VuxoDe.js.map +1 -0
- package/dist/cli-bin.d.ts +1 -0
- package/dist/cli-bin.js +7 -0
- package/dist/cli-bin.js.map +1 -0
- package/dist/cli.d.ts +20 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2 -0
- package/dist/client-BKlyLiOU.js +1008 -0
- package/dist/client-BKlyLiOU.js.map +1 -0
- package/dist/client-D7mvIXrF.d.ts +191 -0
- package/dist/client-D7mvIXrF.d.ts.map +1 -0
- package/dist/client.d.ts +2 -90
- package/dist/client.js +1 -409
- package/dist/{contract-CG_adnu_.js → contract-48bUMgcL.js} +12 -2
- package/dist/contract-48bUMgcL.js.map +1 -0
- package/dist/{contract-C_3dIIEU.d.ts → contract-jIfaR085.d.ts} +63 -8
- package/dist/contract-jIfaR085.d.ts.map +1 -0
- package/dist/devtools-J_jZ2vQf.d.ts +152 -0
- package/dist/devtools-J_jZ2vQf.d.ts.map +1 -0
- package/dist/devtools-kJJaORn-.js +340 -0
- package/dist/devtools-kJJaORn-.js.map +1 -0
- package/dist/devtools-server.browser.js +3 -1
- package/dist/devtools-server.browser.js.map +1 -0
- package/dist/devtools-server.d.ts +4 -3
- package/dist/devtools-server.d.ts.map +1 -0
- package/dist/devtools-server.js +226 -43
- package/dist/devtools-server.js.map +1 -0
- package/dist/devtools.d.ts +2 -0
- package/dist/devtools.js +2 -0
- package/dist/{errors-BJRMd-h6.js → errors-BQuJpe82.js} +6 -4
- package/dist/errors-BQuJpe82.js.map +1 -0
- package/dist/{errors-xL_JTXsY.d.ts → errors-W6nwJ-fm.d.ts} +3 -2
- package/dist/errors-W6nwJ-fm.d.ts.map +1 -0
- package/dist/http.d.ts +135 -28
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +647 -61
- package/dist/http.js.map +1 -0
- package/dist/{idempotent-replay-BMyHrP0L.js → idempotent-replay-DuqEkYA7.js} +4 -2
- package/dist/idempotent-replay-DuqEkYA7.js.map +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/{inspection-E7qbD0Xj.js → inspection-DaxB5jM2.js} +4 -1
- package/dist/inspection-DaxB5jM2.js.map +1 -0
- package/dist/internal-DstsI6Re.js +211 -0
- package/dist/internal-DstsI6Re.js.map +1 -0
- package/dist/otel.d.ts +3 -2
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +2 -0
- package/dist/otel.js.map +1 -0
- package/dist/platform-B4TnJtWu.js +34 -0
- package/dist/platform-B4TnJtWu.js.map +1 -0
- package/dist/react.d.ts +47 -15
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +30 -15
- package/dist/react.js.map +1 -0
- package/dist/retryable-lazy-DZWmHpii.js +2 -0
- package/dist/retryable-lazy-DZWmHpii.js.map +1 -0
- package/dist/scheduler-qstash.d.ts +79 -0
- package/dist/scheduler-qstash.d.ts.map +1 -0
- package/dist/scheduler-qstash.js +501 -0
- package/dist/scheduler-qstash.js.map +1 -0
- package/dist/scheduler-task-BpzhPnRS.js +56 -0
- package/dist/scheduler-task-BpzhPnRS.js.map +1 -0
- package/dist/{recovery-vercel.d.ts → scheduler-vercel.d.ts} +18 -24
- package/dist/scheduler-vercel.d.ts.map +1 -0
- package/dist/scheduler-vercel.js +228 -0
- package/dist/scheduler-vercel.js.map +1 -0
- package/dist/server-C72KOw51.js +1457 -0
- package/dist/server-C72KOw51.js.map +1 -0
- package/dist/server-DUF9pjsx.d.ts +261 -0
- package/dist/server-DUF9pjsx.d.ts.map +1 -0
- package/dist/server.browser.js +2 -0
- package/dist/server.browser.js.map +1 -0
- package/dist/server.d.ts +4 -155
- package/dist/server.js +2 -2
- package/dist/{log-ldf5g8Cx.d.ts → store-DysUkTH3.d.ts} +120 -35
- package/dist/store-DysUkTH3.d.ts.map +1 -0
- package/dist/{log-yJbXUf72.js → store-N8PXxDAS.js} +3 -1
- package/dist/store-N8PXxDAS.js.map +1 -0
- package/dist/store-codec-DTG0Ftek.js +10 -0
- package/dist/store-codec-DTG0Ftek.js.map +1 -0
- package/dist/store-memory.d.ts +12 -0
- package/dist/store-memory.d.ts.map +1 -0
- package/dist/{log-memory.js → store-memory.js} +145 -34
- package/dist/store-memory.js.map +1 -0
- package/dist/{log-polling-DZ1MiKLg.js → store-polling-dSeLxzfb.js} +7 -5
- package/dist/store-polling-dSeLxzfb.js.map +1 -0
- package/dist/{log-postgres.d.ts → store-postgres.d.ts} +7 -6
- package/dist/store-postgres.d.ts.map +1 -0
- package/dist/{log-postgres.js → store-postgres.js} +214 -24
- package/dist/store-postgres.js.map +1 -0
- package/dist/{log-redis-core-CyJ5L8yR.js → store-redis-core-BFLwz0Wj.js} +271 -66
- package/dist/store-redis-core-BFLwz0Wj.js.map +1 -0
- package/dist/{log-redis-http.d.ts → store-redis-http.d.ts} +8 -7
- package/dist/store-redis-http.d.ts.map +1 -0
- package/dist/{log-redis-http.js → store-redis-http.js} +22 -12
- package/dist/store-redis-http.js.map +1 -0
- package/dist/{log-redis.d.ts → store-redis.d.ts} +7 -6
- package/dist/store-redis.d.ts.map +1 -0
- package/dist/{log-redis.js → store-redis.js} +101 -39
- package/dist/store-redis.js.map +1 -0
- package/dist/{log-sqlite.d.ts → store-sqlite.d.ts} +7 -6
- package/dist/store-sqlite.d.ts.map +1 -0
- package/dist/{log-sqlite.js → store-sqlite.js} +118 -22
- package/dist/store-sqlite.js.map +1 -0
- package/dist/{telemetry-Cso0qyHQ.d.ts → telemetry-BjYHTfh2.d.ts} +3 -2
- package/dist/telemetry-BjYHTfh2.d.ts.map +1 -0
- package/dist/testing.browser.d.ts +1 -0
- package/dist/testing.browser.js +6 -0
- package/dist/testing.browser.js.map +1 -0
- package/dist/testing.d.ts +32 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +103 -0
- package/dist/testing.js.map +1 -0
- package/dist/validate-XKT4FSNn.js +2 -0
- package/dist/validate-XKT4FSNn.js.map +1 -0
- package/dist/wire-BFQmSJ-9.js +284 -0
- package/dist/wire-BFQmSJ-9.js.map +1 -0
- package/docs/01-quickstart.mdx +3 -3
- package/docs/concepts/01-contracts.mdx +18 -13
- package/docs/concepts/02-handlers.mdx +7 -7
- package/docs/concepts/03-durability.mdx +21 -21
- package/docs/concepts/04-state.mdx +18 -21
- package/docs/guides/01-timers.mdx +154 -49
- package/docs/guides/02-cancellation.mdx +30 -4
- package/docs/guides/03-react.mdx +76 -57
- package/docs/guides/04-local-first.mdx +1 -1
- package/docs/guides/05-production.mdx +310 -61
- package/docs/guides/06-ai-agents.mdx +252 -74
- package/docs/guides/07-devtools.mdx +137 -12
- package/docs/guides/08-application-data.mdx +1 -1
- package/docs/guides/09-presence.mdx +263 -0
- package/docs/guides/10-transports.mdx +140 -0
- package/docs/index.mdx +18 -14
- package/docs/reference/01-api.mdx +839 -110
- package/docs/reference/02-errors.mdx +13 -6
- package/package.json +24 -7
- package/src/ai-coordinator.ts +358 -0
- package/src/ai-projector.ts +524 -0
- package/src/ai-sdk-step.ts +261 -0
- package/src/ai-server.browser.ts +5 -0
- package/src/ai-server.ts +1719 -0
- package/src/ai.ts +2155 -0
- package/src/cache-indexeddb.ts +10 -0
- package/src/cli-bin.ts +5 -0
- package/src/cli.ts +1046 -0
- package/src/client.ts +1826 -0
- package/src/contract.ts +206 -0
- package/src/deterministic-id.ts +72 -0
- package/src/devtools-app.ts +989 -0
- package/src/devtools-server.browser.ts +5 -0
- package/src/devtools-server.ts +604 -0
- package/src/devtools.ts +716 -0
- package/src/errors.ts +50 -0
- package/src/http.ts +394 -0
- package/src/idempotent-replay.ts +53 -0
- package/src/index.ts +37 -0
- package/src/inspection.ts +39 -0
- package/src/internal.ts +426 -0
- package/src/otel.ts +59 -0
- package/src/platform.ts +60 -0
- package/src/push-envelope.ts +137 -0
- package/src/react.ts +284 -0
- package/src/reducer.ts +108 -0
- package/src/retryable-lazy.ts +27 -0
- package/src/scheduler-qstash.ts +915 -0
- package/src/scheduler-task.ts +106 -0
- package/src/scheduler-vercel.ts +437 -0
- package/src/server.browser.ts +12 -0
- package/src/server.ts +2700 -0
- package/src/session-socket.ts +548 -0
- package/src/sse.ts +141 -0
- package/src/standard-schema.ts +77 -0
- package/src/store-codec.ts +10 -0
- package/src/store-memory.ts +788 -0
- package/src/store-polling.ts +102 -0
- package/src/store-postgres.ts +1212 -0
- package/src/store-redis-core.ts +1494 -0
- package/src/store-redis-http.ts +116 -0
- package/src/store-redis.ts +458 -0
- package/src/store-sqlite.ts +1108 -0
- package/src/store.ts +385 -0
- package/src/telemetry.ts +47 -0
- package/src/testing.browser.ts +5 -0
- package/src/testing.ts +185 -0
- package/src/validate.ts +39 -0
- package/src/wire.ts +454 -0
- package/dist/internal-gCd5qMry.js +0 -44
- package/dist/log-memory.d.ts +0 -11
- package/dist/recovery-vercel.js +0 -119
- package/dist/server-BcLa4RFL.js +0 -877
- package/dist/wire-BVsgR8o9.js +0 -62
package/src/contract.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract — a2's primary noun. A named event vocabulary, shared by
|
|
3
|
+
* everything: the server implements it (experimental-a2/server's `createServer`),
|
|
4
|
+
* reducers derive from it (`contract.reducer`), the browser types its
|
|
5
|
+
* pushes off it. Isomorphic by construction: this module imports
|
|
6
|
+
* nothing but schema plumbing.
|
|
7
|
+
*
|
|
8
|
+
* The contract says what can be *said*; the server says how it's
|
|
9
|
+
* *reacted to*; a reducer says how it's *seen*.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { makeReducerBuilder, type ReducerBuilder } from './reducer.ts'
|
|
13
|
+
import type { StandardSchemaV1 } from './standard-schema.ts'
|
|
14
|
+
import { assertSyncSchema } from './validate.ts'
|
|
15
|
+
|
|
16
|
+
/** The event vocabulary shape: event name → payload schema. */
|
|
17
|
+
export type EventDefs = Record<string, StandardSchemaV1>
|
|
18
|
+
|
|
19
|
+
/** The presence vocabulary shape: field name → value schema. */
|
|
20
|
+
export type PresenceDefs = Record<string, StandardSchemaV1>
|
|
21
|
+
|
|
22
|
+
/** One event of a contract, narrowed to type `K`. */
|
|
23
|
+
export type ContractEvent<
|
|
24
|
+
D extends EventDefs,
|
|
25
|
+
K extends keyof D & string = keyof D & string,
|
|
26
|
+
> = {
|
|
27
|
+
[T in keyof D & string]: {
|
|
28
|
+
id: string
|
|
29
|
+
type: T
|
|
30
|
+
payload: StandardSchemaV1.InferOutput<D[T]>
|
|
31
|
+
index: number
|
|
32
|
+
sessionId: string
|
|
33
|
+
createdAt: Date
|
|
34
|
+
}
|
|
35
|
+
}[K]
|
|
36
|
+
|
|
37
|
+
/** Input to `append`/`push`, typed against the contract's schemas. */
|
|
38
|
+
export type AppendInput<D extends EventDefs> = {
|
|
39
|
+
[T in keyof D & string]: {
|
|
40
|
+
type: T
|
|
41
|
+
payload: StandardSchemaV1.InferInput<D[T]>
|
|
42
|
+
id?: string
|
|
43
|
+
}
|
|
44
|
+
}[keyof D & string]
|
|
45
|
+
|
|
46
|
+
export type EventBatchFactory<D extends EventDefs> = <
|
|
47
|
+
const E extends readonly AppendInput<D>[],
|
|
48
|
+
>(
|
|
49
|
+
...events: E
|
|
50
|
+
) => E
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* One presence update: a participant's changed fields (`null` marks a
|
|
54
|
+
* cleared one), stamped with the sender's stream frontier (`seen`).
|
|
55
|
+
* This is what `stream({ presence: true })` interleaves with events.
|
|
56
|
+
*/
|
|
57
|
+
export type PresencePatch<P extends PresenceDefs = PresenceDefs> = {
|
|
58
|
+
participant: string
|
|
59
|
+
values: {
|
|
60
|
+
[F in keyof P & string]?: StandardSchemaV1.InferOutput<P[F]> | null
|
|
61
|
+
}
|
|
62
|
+
seen: number
|
|
63
|
+
at: Date
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The replicated ephemeral map: participant → field → latest value,
|
|
68
|
+
* last-writer-wins per field. Never stored in the log; how long a
|
|
69
|
+
* value stays painted is view logic, decided at render time against
|
|
70
|
+
* `at`.
|
|
71
|
+
*/
|
|
72
|
+
export type PresenceMap<P extends PresenceDefs = PresenceDefs> = {
|
|
73
|
+
[participant: string]: {
|
|
74
|
+
[F in keyof P & string]?: {
|
|
75
|
+
value: StandardSchemaV1.InferOutput<P[F]>
|
|
76
|
+
seen: number
|
|
77
|
+
at: Date
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The one item a presence stream yields before live patches: the
|
|
84
|
+
* current pruned map, per-field stamps exact. Discriminate
|
|
85
|
+
* structurally (`'snapshot' in item`).
|
|
86
|
+
*/
|
|
87
|
+
export type PresenceSnapshot<P extends PresenceDefs = PresenceDefs> = {
|
|
88
|
+
snapshot: PresenceMap<P>
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Intersect into a surface type to add `Members` only when the
|
|
93
|
+
* contract declares presence fields — on presence-less contracts the
|
|
94
|
+
* members do not exist, a type error rather than a runtime throw.
|
|
95
|
+
*/
|
|
96
|
+
export type WithPresence<
|
|
97
|
+
P extends PresenceDefs,
|
|
98
|
+
Members,
|
|
99
|
+
> = keyof P extends never ? unknown : Members
|
|
100
|
+
|
|
101
|
+
export type ReducerOptions<Seed, S> = {
|
|
102
|
+
/**
|
|
103
|
+
* Identity and snapshot cache key. Rename it when the fold's logic
|
|
104
|
+
* changes — snapshots under the old name are ignored and refolded.
|
|
105
|
+
*/
|
|
106
|
+
name: string
|
|
107
|
+
/**
|
|
108
|
+
* The seed the fold starts from. With a `stateSchema`, it's typed as
|
|
109
|
+
* the schema's *input*: validated at definition, and the validated
|
|
110
|
+
* output (defaults applied) is what the fold actually starts from.
|
|
111
|
+
*/
|
|
112
|
+
initialState: Seed
|
|
113
|
+
/**
|
|
114
|
+
* Optional: declares the state's shape (the fold's state type becomes
|
|
115
|
+
* the schema's output) and guards cached folds — server snapshots and
|
|
116
|
+
* the browser cache reject mismatching shapes and refold.
|
|
117
|
+
*/
|
|
118
|
+
stateSchema?: StandardSchemaV1<Seed, S>
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type Contract<
|
|
122
|
+
D extends EventDefs = EventDefs,
|
|
123
|
+
P extends PresenceDefs = Record<never, never>,
|
|
124
|
+
> = {
|
|
125
|
+
/** Identity — prefixes storage keys and queue messages. */
|
|
126
|
+
readonly name: string
|
|
127
|
+
/** The vocabulary. */
|
|
128
|
+
readonly events: Readonly<D>
|
|
129
|
+
/** The presence vocabulary — empty unless declared. */
|
|
130
|
+
readonly presence: Readonly<P>
|
|
131
|
+
/** Preserve literal types for a handler-returned event batch. */
|
|
132
|
+
readonly batch: EventBatchFactory<D>
|
|
133
|
+
/**
|
|
134
|
+
* Derive a view from this contract. The reducer's `name` is its
|
|
135
|
+
* identity and snapshot cache key: rename it when the fold's logic
|
|
136
|
+
* changes. Two steps by design: this call fixes the state and event
|
|
137
|
+
* types, so `.fold()` receives fully concrete types — literal unions
|
|
138
|
+
* in your state survive, with zero annotations. (A single call can't
|
|
139
|
+
* do this: TypeScript never contextually types the returns of a
|
|
140
|
+
* context-sensitive argument against generics inferred in the same
|
|
141
|
+
* call.)
|
|
142
|
+
*/
|
|
143
|
+
reducer<Seed, S = Seed>(
|
|
144
|
+
options: ReducerOptions<Seed, S>,
|
|
145
|
+
): ReducerBuilder<D, S, P>
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Define a contract: a name plus the events it understands. Validators
|
|
150
|
+
* must be synchronous — async ones are rejected here, at definition
|
|
151
|
+
* time. The result is a plain, importable, isomorphic value.
|
|
152
|
+
*/
|
|
153
|
+
export function contract<
|
|
154
|
+
D extends EventDefs,
|
|
155
|
+
P extends PresenceDefs = Record<never, never>,
|
|
156
|
+
>(options: {
|
|
157
|
+
/** Identity — prefixes storage keys and queue messages. */
|
|
158
|
+
name: string
|
|
159
|
+
/** The vocabulary: event name → payload schema (Standard Schema). */
|
|
160
|
+
events: D
|
|
161
|
+
/**
|
|
162
|
+
* Optional second vocabulary: presence field → value schema.
|
|
163
|
+
* Per-participant ephemeral state, replicated last-writer-wins and
|
|
164
|
+
* never stored in the log — reducers cannot see it.
|
|
165
|
+
*/
|
|
166
|
+
presence?: P
|
|
167
|
+
}): Contract<D, P> {
|
|
168
|
+
const { name } = options
|
|
169
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
170
|
+
throw new TypeError('contract name must be a non-empty string')
|
|
171
|
+
}
|
|
172
|
+
if (name.includes('\u001f')) {
|
|
173
|
+
throw new TypeError('contract name contains a reserved control character')
|
|
174
|
+
}
|
|
175
|
+
const defs = options.events
|
|
176
|
+
for (const [type, schema] of Object.entries(defs)) {
|
|
177
|
+
if (typeof schema?.['~standard']?.validate !== 'function') {
|
|
178
|
+
throw new TypeError(
|
|
179
|
+
`contract '${name}': the value for '${type}' is not a Standard Schema (expected an object with '~standard')`,
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
assertSyncSchema(schema, `event '${type}'`)
|
|
183
|
+
}
|
|
184
|
+
const events = Object.freeze({ ...defs })
|
|
185
|
+
|
|
186
|
+
const presenceDefs = options.presence ?? ({} as P)
|
|
187
|
+
for (const [field, schema] of Object.entries(presenceDefs)) {
|
|
188
|
+
if (typeof schema?.['~standard']?.validate !== 'function') {
|
|
189
|
+
throw new TypeError(
|
|
190
|
+
`contract '${name}': the value for presence field '${field}' is not a Standard Schema (expected an object with '~standard')`,
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
assertSyncSchema(schema, `presence field '${field}'`)
|
|
194
|
+
}
|
|
195
|
+
const presence = Object.freeze({ ...presenceDefs })
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
name,
|
|
199
|
+
events,
|
|
200
|
+
presence,
|
|
201
|
+
batch: (...items) => items,
|
|
202
|
+
reducer(reducerOptions) {
|
|
203
|
+
return makeReducerBuilder(events, presence, reducerOptions)
|
|
204
|
+
},
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic default ids for handler `session.append` calls. A handler
|
|
3
|
+
* re-run after a crash calls `session.append` again; giving
|
|
4
|
+
* each call a deterministic id — derived from the triggering event's id
|
|
5
|
+
* and the caller's stable name — makes the re-run a no-op via the store's
|
|
6
|
+
* unique index on event ids.
|
|
7
|
+
*
|
|
8
|
+
* The id is a UUIDv5-shaped SHA-1 over
|
|
9
|
+
* `(namespace, triggerEventId, name, itemOrdinal)`, computed with
|
|
10
|
+
* WebCrypto so it runs on any platform a2 core targets.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const APPEND_NAMESPACE = 'a2:handler-append:v2'
|
|
14
|
+
const RETURN_NAMESPACE = 'a2:handler-return:v1'
|
|
15
|
+
const SCHEDULE_NAMESPACE = 'a2:schedule:v1'
|
|
16
|
+
const SCHEDULED_EVENT_NAMESPACE = 'a2:scheduled-event:v1'
|
|
17
|
+
|
|
18
|
+
async function deterministicIdFromInput(input: string): Promise<string> {
|
|
19
|
+
const digest = await crypto.subtle.digest(
|
|
20
|
+
'SHA-1',
|
|
21
|
+
new TextEncoder().encode(input),
|
|
22
|
+
)
|
|
23
|
+
const bytes = new Uint8Array(digest).slice(0, 16)
|
|
24
|
+
bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x50
|
|
25
|
+
bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80
|
|
26
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')
|
|
27
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function deterministicId(parts: Array<string | number>): Promise<string> {
|
|
31
|
+
return deterministicIdFromInput(parts.join('\u0000'))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function deterministicEventId(
|
|
35
|
+
triggerEventId: string,
|
|
36
|
+
name: string,
|
|
37
|
+
itemOrdinal: number,
|
|
38
|
+
): Promise<string> {
|
|
39
|
+
if (name.length === 0) throw new TypeError('append name must not be empty')
|
|
40
|
+
return deterministicId([APPEND_NAMESPACE, triggerEventId, name, itemOrdinal])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function deterministicReturnedEventId(
|
|
44
|
+
triggerEventId: string,
|
|
45
|
+
itemOrdinal: number,
|
|
46
|
+
): Promise<string> {
|
|
47
|
+
return deterministicId([RETURN_NAMESPACE, triggerEventId, itemOrdinal])
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function deterministicScheduleId(
|
|
51
|
+
contract: string,
|
|
52
|
+
sessionId: string,
|
|
53
|
+
triggerEventId: string | null,
|
|
54
|
+
name: string,
|
|
55
|
+
): Promise<string> {
|
|
56
|
+
return deterministicIdFromInput(
|
|
57
|
+
JSON.stringify([
|
|
58
|
+
SCHEDULE_NAMESPACE,
|
|
59
|
+
contract,
|
|
60
|
+
sessionId,
|
|
61
|
+
triggerEventId,
|
|
62
|
+
name,
|
|
63
|
+
]),
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function deterministicScheduledEventId(
|
|
68
|
+
scheduleId: string,
|
|
69
|
+
itemOrdinal: number,
|
|
70
|
+
): Promise<string> {
|
|
71
|
+
return deterministicId([SCHEDULED_EVENT_NAMESPACE, scheduleId, itemOrdinal])
|
|
72
|
+
}
|