experimental-a2 0.0.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/dist/ai-server.browser.d.ts +1 -0
  3. package/dist/ai-server.browser.js +4 -0
  4. package/dist/ai-server.d.ts +65 -0
  5. package/dist/ai-server.js +494 -0
  6. package/dist/ai.d.ts +282 -0
  7. package/dist/ai.js +922 -0
  8. package/dist/cache-indexeddb.d.ts +1 -0
  9. package/dist/cache-indexeddb.js +0 -0
  10. package/dist/client.d.ts +90 -0
  11. package/dist/client.js +410 -0
  12. package/dist/contract-B0kAXoaL.js +60 -0
  13. package/dist/contract-DL8btVd9.d.ts +161 -0
  14. package/dist/devtools-server.browser.d.ts +1 -0
  15. package/dist/devtools-server.browser.js +4 -0
  16. package/dist/devtools-server.d.ts +22 -0
  17. package/dist/devtools-server.js +1087 -0
  18. package/dist/errors-BJRMd-h6.js +23 -0
  19. package/dist/errors-xL_JTXsY.d.ts +20 -0
  20. package/dist/http.d.ts +44 -0
  21. package/dist/http.js +119 -0
  22. package/dist/index.d.ts +5 -0
  23. package/dist/index.js +3 -0
  24. package/dist/inspection-E7qbD0Xj.js +10 -0
  25. package/dist/internal-Dm8Ejnud.js +36 -0
  26. package/dist/log-Dg1I8NRr.d.ts +245 -0
  27. package/dist/log-memory.d.ts +11 -0
  28. package/dist/log-memory.js +345 -0
  29. package/dist/log-polling-RO7kclzR.js +83 -0
  30. package/dist/log-postgres.d.ts +40 -0
  31. package/dist/log-postgres.js +628 -0
  32. package/dist/log-redis.d.ts +31 -0
  33. package/dist/log-redis.js +711 -0
  34. package/dist/log-sqlite.d.ts +17 -0
  35. package/dist/log-sqlite.js +450 -0
  36. package/dist/log-yJbXUf72.js +5 -0
  37. package/dist/otel.d.ts +12 -0
  38. package/dist/otel.js +41 -0
  39. package/dist/react.d.ts +54 -0
  40. package/dist/react.js +85 -0
  41. package/dist/recovery-vercel.d.ts +60 -0
  42. package/dist/recovery-vercel.js +120 -0
  43. package/dist/retryable-lazy-DZWmHpii.js +19 -0
  44. package/dist/server-DYsnKTTy.js +780 -0
  45. package/dist/server.browser.d.ts +1 -0
  46. package/dist/server.browser.js +11 -0
  47. package/dist/server.d.ts +136 -0
  48. package/dist/server.js +2 -0
  49. package/dist/telemetry-C78al20p.d.ts +32 -0
  50. package/dist/validate-XKT4FSNn.js +28 -0
  51. package/dist/wire-2QpU1EtJ.js +62 -0
  52. package/docs/01-quickstart.mdx +214 -0
  53. package/docs/concepts/01-contracts.mdx +138 -0
  54. package/docs/concepts/02-handlers.mdx +146 -0
  55. package/docs/concepts/03-durability.mdx +230 -0
  56. package/docs/concepts/04-state.mdx +133 -0
  57. package/docs/guides/01-timers.mdx +85 -0
  58. package/docs/guides/02-cancellation.mdx +107 -0
  59. package/docs/guides/03-react.mdx +234 -0
  60. package/docs/guides/04-local-first.mdx +88 -0
  61. package/docs/guides/05-production.mdx +179 -0
  62. package/docs/guides/06-ai-agents.mdx +659 -0
  63. package/docs/guides/07-devtools.mdx +101 -0
  64. package/docs/guides/08-application-data.mdx +114 -0
  65. package/docs/index.mdx +282 -0
  66. package/docs/reference/01-api.mdx +637 -0
  67. package/docs/reference/02-errors.mdx +77 -0
  68. package/package.json +111 -0
@@ -0,0 +1,77 @@
1
+ ---
2
+ title: Errors
3
+ description: One error class, five codes, and clear rules about what append will never throw for.
4
+ ---
5
+
6
+ ## `A2Error`
7
+
8
+ Everything A2 throws is an `A2Error`, a single class discriminated by
9
+ `code`, not a subclass hierarchy. One class serializes cleanly across the
10
+ push-route boundary and keeps `instanceof` working after bundling.
11
+
12
+ ```ts
13
+ // e.g. in a route handler:
14
+ import { A2Error } from 'experimental-a2'
15
+
16
+ export async function POST(req: Request) {
17
+ const { orderId, payload } = await req.json()
18
+ try {
19
+ const events = await ordersServer
20
+ .session(orderId)
21
+ .append({ type: 'created', payload })
22
+ return Response.json(events)
23
+ } catch (err) {
24
+ if (err instanceof A2Error && err.code === 'INVALID_PAYLOAD') {
25
+ // err.details carries the schema issues, in Standard Schema format
26
+ return Response.json({ issues: err.details }, { status: 400 })
27
+ }
28
+ throw err
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## The codes
34
+
35
+ | Code | Thrown when | Retryable |
36
+ | ------------------------- | ------------------------------------------------------------------ | --------- |
37
+ | `INVALID_PAYLOAD` | a payload fails its schema; nothing was written, and `details` carries the issues ([Standard Schema](https://standardschema.dev) format) | no |
38
+ | `UNKNOWN_EVENT_TYPE` | an event type isn't in the contract's `events` map | no |
39
+ | `PARTIAL_DUPLICATE_BATCH` | a batch mixed already-appended and fresh events | no |
40
+ | `LOG_UNAVAILABLE` | the log backend failed; nothing was written, original error as `cause` | **yes** |
41
+ | `LOG_NOT_CONFIGURED` | production boot with no `log` configured (during `next build` page collection, deferred to first use) | no |
42
+
43
+ Retryability is derivable from the code. `LOG_UNAVAILABLE` is the only one
44
+ worth retrying; the rest are deterministic caller bugs, and retrying them
45
+ is wasted work.
46
+
47
+ On `PARTIAL_DUPLICATE_BATCH`: retrying an *identical* batch is not an
48
+ error. It's an idempotent success, and you get the previously appended
49
+ events back. Mixing already-sent events with fresh ones in a single batch
50
+ is always a caller bug, so A2 refuses it rather than quietly reinterpret
51
+ what "atomic" meant. The same code covers two adjacent bugs: a batch that
52
+ contains the same id twice, and an id that was already used in a
53
+ *different* session (event ids are globally unique). In every case,
54
+ nothing is written.
55
+
56
+ ## What append never throws for
57
+
58
+ - **A failing handler.** Appends always land; handler failures are retried
59
+ and, if persistent, [dead-letter the event](/concepts/durability#when-a-handler-keeps-failing).
60
+ `append` never fails because a downstream handler is failing.
61
+ - **A duplicate of an identical batch.** That's a lost ack, not a bug.
62
+
63
+ ## Over the wire
64
+
65
+ The push route serializes an `A2Error` as:
66
+
67
+ ```json
68
+ { "error": { "code": "INVALID_PAYLOAD", "message": "...", "details": [] } }
69
+ ```
70
+
71
+ with a mapped status: `INVALID_PAYLOAD`, `UNKNOWN_EVENT_TYPE`, and
72
+ `PARTIAL_DUPLICATE_BATCH` are 400; `LOG_UNAVAILABLE` is 503.
73
+
74
+ The client's `push` deserializes the body back into an `A2Error`, so client
75
+ and server code branch on identical codes. `push` auto-retries only
76
+ `LOG_UNAVAILABLE`. The serializer pair ships in `experimental-a2/http`, alongside
77
+ `parsePushBody` and `sseResponse`.
package/package.json ADDED
@@ -0,0 +1,111 @@
1
+ {
2
+ "name": "experimental-a2",
3
+ "version": "0.0.0",
4
+ "description": "Durable sync and reactions for things with a lifecycle: one event log, derived state, and live client per session.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "engines": {
9
+ "node": ">=22.13"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/vercel-labs/a2.git",
14
+ "directory": "packages/a2"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public",
18
+ "registry": "https://registry.npmjs.org/"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "docs",
23
+ "CHANGELOG.md"
24
+ ],
25
+ "exports": {
26
+ ".": "./dist/index.js",
27
+ "./server": {
28
+ "browser": "./dist/server.browser.js",
29
+ "default": "./dist/server.js"
30
+ },
31
+ "./client": "./dist/client.js",
32
+ "./react": "./dist/react.js",
33
+ "./ai": "./dist/ai.js",
34
+ "./ai/server": {
35
+ "browser": "./dist/ai-server.browser.js",
36
+ "default": "./dist/ai-server.js"
37
+ },
38
+ "./http": "./dist/http.js",
39
+ "./log-memory": "./dist/log-memory.js",
40
+ "./log-sqlite": "./dist/log-sqlite.js",
41
+ "./log-postgres": "./dist/log-postgres.js",
42
+ "./log-redis": "./dist/log-redis.js",
43
+ "./recovery-vercel": "./dist/recovery-vercel.js",
44
+ "./cache-indexeddb": "./dist/cache-indexeddb.js",
45
+ "./otel": "./dist/otel.js",
46
+ "./devtools/server": {
47
+ "browser": "./dist/devtools-server.browser.js",
48
+ "default": "./dist/devtools-server.js"
49
+ },
50
+ "./package.json": "./package.json"
51
+ },
52
+ "scripts": {
53
+ "build": "tsdown",
54
+ "dev": "tsdown --watch",
55
+ "typecheck": "tsc --noEmit",
56
+ "test": "vitest run",
57
+ "test:watch": "vitest"
58
+ },
59
+ "peerDependencies": {
60
+ "@opentelemetry/api": "^1.9.0",
61
+ "@vercel/queue": "*",
62
+ "ai": "^7.0.0",
63
+ "ioredis": "^5.4.0",
64
+ "pg": "^8.11.0",
65
+ "react": "^19.0.0"
66
+ },
67
+ "peerDependenciesMeta": {
68
+ "@opentelemetry/api": {
69
+ "optional": true
70
+ },
71
+ "@vercel/queue": {
72
+ "optional": true
73
+ },
74
+ "ai": {
75
+ "optional": true
76
+ },
77
+ "ioredis": {
78
+ "optional": true
79
+ },
80
+ "pg": {
81
+ "optional": true
82
+ },
83
+ "react": {
84
+ "optional": true
85
+ }
86
+ },
87
+ "devDependencies": {
88
+ "@electric-sql/pglite": "catalog:",
89
+ "ai": "catalog:",
90
+ "ioredis": "catalog:",
91
+ "@opentelemetry/api": "catalog:",
92
+ "@types/pg": "catalog:",
93
+ "@vercel/queue": "catalog:",
94
+ "pg": "catalog:",
95
+ "@testing-library/react": "catalog:",
96
+ "@types/react": "catalog:",
97
+ "esbuild": "catalog:",
98
+ "@types/react-dom": "catalog:",
99
+ "jsdom": "catalog:",
100
+ "react": "catalog:",
101
+ "react-dom": "catalog:",
102
+ "@opentelemetry/context-async-hooks": "catalog:",
103
+ "@opentelemetry/sdk-trace-base": "catalog:",
104
+ "@types/node": "catalog:",
105
+ "publint": "catalog:",
106
+ "tsdown": "catalog:",
107
+ "typescript": "catalog:",
108
+ "vitest": "catalog:",
109
+ "zod": "catalog:"
110
+ }
111
+ }