experimental-a2 0.14.1 → 0.15.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 +8 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -0
- package/docs/reference/01-api.mdx +25 -0
- package/examples/playground/package.json +1 -1
- package/package.json +1 -1
- package/src/idempotent-id.ts +11 -0
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.15.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 197b719: Add `idempotentId(...parts: string[])` to derive stable UUIDv8 event IDs from
|
|
8
|
+
ordered strings in server and browser code. Existing IDs and automatic ID
|
|
9
|
+
generation are unchanged.
|
|
10
|
+
|
|
3
11
|
## 0.14.1
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,8 @@ import { a as ContractEvent, c as PresenceDefs, d as PresenceSnapshot, f as Redu
|
|
|
2
2
|
import { i as Event } from "./store-D_yhNdPz.js";
|
|
3
3
|
import { i as NonRetriableError, n as A2ErrorCode, r as A2ServerErrorCode, t as A2Error } from "./errors-DvhSXnxk.js";
|
|
4
4
|
import { i as A2Telemetry, n as A2SpanHandle, r as A2SpanName, t as A2AttributeValue } from "./telemetry-CpeclqB2.js";
|
|
5
|
-
|
|
5
|
+
//#region src/idempotent-id.d.ts
|
|
6
|
+
declare function idempotentId(...parts: string[]): Promise<string>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { type A2AttributeValue, A2Error, type A2ErrorCode, type A2ServerErrorCode, type A2SpanHandle, type A2SpanName, type A2Telemetry, type AppendInput, type Contract, type ContractEvent, type Event, type EventBatchFactory, type EventDefs, NonRetriableError, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceSnapshot, type Reducer, type ReducerBuilder, type ReducerOptions, type StandardSchemaV1, contract, idempotentId };
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/idempotent-id.ts"],"mappings":";;;;;iBAAsB,gBAAgB,kBAAkB"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
import { t as contract } from "./contract-CKRg_E4q.js";
|
|
2
2
|
import { n as NonRetriableError, t as A2Error } from "./errors-DCk6ch5n.js";
|
|
3
|
-
|
|
3
|
+
//#region src/idempotent-id.ts
|
|
4
|
+
async function idempotentId(...parts) {
|
|
5
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify(parts)));
|
|
6
|
+
const bytes = new Uint8Array(digest).slice(0, 16);
|
|
7
|
+
bytes[6] = bytes[6] & 15 | 128;
|
|
8
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
9
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
10
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { A2Error, NonRetriableError, contract, idempotentId };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/idempotent-id.ts"],"sourcesContent":["export async function idempotentId(...parts: string[]): Promise<string> {\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n new TextEncoder().encode(JSON.stringify(parts)),\n )\n const bytes = new Uint8Array(digest).slice(0, 16)\n bytes[6] = (bytes[6]! & 0x0f) | 0x80\n bytes[8] = (bytes[8]! & 0x3f) | 0x80\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n"],"mappings":";;;AAAA,eAAsB,aAAa,GAAG,OAAkC;CACtE,MAAM,SAAS,MAAM,OAAO,OAAO,OACjC,WACA,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,KAAK,CAAC,CAChD;CACA,MAAM,QAAQ,IAAI,WAAW,MAAM,CAAC,CAAC,MAAM,GAAG,EAAE;CAChD,MAAM,KAAM,MAAM,KAAM,KAAQ;CAChC,MAAM,KAAM,MAAM,KAAM,KAAQ;CAChC,MAAM,MAAM,MAAM,KAAK,QAAQ,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;CAC7E,OAAO,GAAG,IAAI,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE;AAC7G"}
|
|
@@ -63,6 +63,31 @@ The shared base for A2 failures, discriminated by `code`. The session
|
|
|
63
63
|
client exposes its `A2ClientError` subclass. See
|
|
64
64
|
[Errors](/reference/errors).
|
|
65
65
|
|
|
66
|
+
### `idempotentId(...parts)`
|
|
67
|
+
|
|
68
|
+
`idempotentId(...parts: string[]): Promise<string>` derives a stable UUIDv8
|
|
69
|
+
from an ordered tuple of strings. It runs on the server and in the browser.
|
|
70
|
+
|
|
71
|
+
```ts shared/request-id.ts
|
|
72
|
+
import { idempotentId } from 'experimental-a2'
|
|
73
|
+
|
|
74
|
+
export const id = await idempotentId('orders', 'shop-7', 'request-42')
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Pass the result as an event's `id` when retries should converge on the same
|
|
78
|
+
event. The same tuple produces the same ID across runtimes and A2 versions.
|
|
79
|
+
String boundaries, order, and case matter; strings are not normalized.
|
|
80
|
+
Empty strings and an empty tuple are valid inputs.
|
|
81
|
+
|
|
82
|
+
Every argument has the same role. A prefix such as `'orders'` is a namespace
|
|
83
|
+
by convention. Include enough context to distinguish operations across
|
|
84
|
+
contracts and sessions, since event IDs are globally unique within a store.
|
|
85
|
+
|
|
86
|
+
The helper performs no I/O. A2 preserves explicit IDs and keeps its automatic
|
|
87
|
+
ID generation unchanged. Changing an existing application's ID recipe changes
|
|
88
|
+
retry identity, so retries of previously committed requests need to retain
|
|
89
|
+
their original IDs.
|
|
90
|
+
|
|
66
91
|
## `experimental-a2/server`
|
|
67
92
|
|
|
68
93
|
### `handler(entry)`
|
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export async function idempotentId(...parts: string[]): Promise<string> {
|
|
2
|
+
const digest = await crypto.subtle.digest(
|
|
3
|
+
'SHA-256',
|
|
4
|
+
new TextEncoder().encode(JSON.stringify(parts)),
|
|
5
|
+
)
|
|
6
|
+
const bytes = new Uint8Array(digest).slice(0, 16)
|
|
7
|
+
bytes[6] = (bytes[6]! & 0x0f) | 0x80
|
|
8
|
+
bytes[8] = (bytes[8]! & 0x3f) | 0x80
|
|
9
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')
|
|
10
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`
|
|
11
|
+
}
|