solid-objects 0.12.0 → 0.12.1
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 +13 -0
- package/README.md +53 -14
- package/dist/actor.d.ts.map +1 -1
- package/dist/actor.js +3 -3
- package/dist/actor.js.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/reminder-scheduler.d.ts +3 -1
- package/dist/reminder-scheduler.d.ts.map +1 -1
- package/dist/reminder-scheduler.js +11 -3
- package/dist/reminder-scheduler.js.map +1 -1
- package/dist/repository.d.ts +6 -2
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +19 -10
- package/dist/repository.js.map +1 -1
- package/dist/runtime.d.ts +3 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +2 -2
- package/dist/runtime.js.map +1 -1
- package/dist/test-helper.d.ts +5 -0
- package/dist/test-helper.d.ts.map +1 -1
- package/dist/test-helper.js +24 -0
- package/dist/test-helper.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/api.md +36 -4
- package/docs/browser-protocol.md +7 -0
- package/docs/configuration.md +19 -0
- package/docs/errors-and-recovery.md +16 -1
- package/docs/parity.md +13 -13
- package/docs/releasing.md +5 -4
- package/docs/state-and-lifecycle.md +4 -4
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-helper.d.ts","sourceRoot":"","sources":["../src/test-helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAIvD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,YAAY,CAAA;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAMD,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,mBAAmB;IAEnD,KAAK,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"test-helper.d.ts","sourceRoot":"","sources":["../src/test-helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAIvD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,YAAY,CAAA;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,IAAI,CAAA;IACT,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAMD,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,mBAAmB;IAEnD,KAAK,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBvE,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,YAAY;CAUrB"}
|
package/dist/test-helper.js
CHANGED
|
@@ -39,6 +39,30 @@ export class SolidObjectsTestHelper {
|
|
|
39
39
|
reset() {
|
|
40
40
|
return this.runtime.resetForTesting();
|
|
41
41
|
}
|
|
42
|
+
async runDueReminders(options) {
|
|
43
|
+
const nowMilliseconds = options.now.getTime();
|
|
44
|
+
if (!Number.isFinite(nowMilliseconds)) {
|
|
45
|
+
throw new TypeError("reminder test time must be a valid date");
|
|
46
|
+
}
|
|
47
|
+
const maxReminders = options.maxReminders ?? 10_000;
|
|
48
|
+
if (!Number.isSafeInteger(maxReminders) || maxReminders < 1) {
|
|
49
|
+
throw new TypeError("maxReminders must be a positive safe integer");
|
|
50
|
+
}
|
|
51
|
+
const scheduler = this.runtime.reminderScheduler();
|
|
52
|
+
let processed = 0;
|
|
53
|
+
try {
|
|
54
|
+
while (processed < maxReminders) {
|
|
55
|
+
const count = await scheduler.runOnce({ now: options.now });
|
|
56
|
+
if (count === 0)
|
|
57
|
+
return processed;
|
|
58
|
+
processed += count;
|
|
59
|
+
}
|
|
60
|
+
return processed;
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
await scheduler.stop();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
42
66
|
defaultRoles() {
|
|
43
67
|
const roles = ["reminders", "actors", "effects"];
|
|
44
68
|
if (broadcastsEnabled(this.runtime.settings))
|
package/dist/test-helper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-helper.js","sourceRoot":"","sources":["../src/test-helper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"test-helper.js","sourceRoot":"","sources":["../src/test-helper.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.12.
|
|
1
|
+
export declare const VERSION = "0.12.1";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.12.
|
|
1
|
+
export const VERSION = "0.12.1";
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/docs/api.md
CHANGED
|
@@ -31,6 +31,30 @@ generic signatures; this index explains the supported role of every export.
|
|
|
31
31
|
`PayloadBroadcasts`, and `PayloadBroadcastValue` describe actor-declared
|
|
32
32
|
transactional work and typed personalized projections.
|
|
33
33
|
|
|
34
|
+
`MessageReference` does not retain an invocation's authorization context.
|
|
35
|
+
Supply `authorizationContext` to each `status()`, `result()`, and `wait()` call;
|
|
36
|
+
the runtime reauthorizes the persisted operation every time. Durable results
|
|
37
|
+
are JSON, so an operation that returns `undefined` or is declared `void`
|
|
38
|
+
resolves as `null`.
|
|
39
|
+
|
|
40
|
+
Declare named payload return shapes with a `type` alias rather than an
|
|
41
|
+
`interface`. `PayloadBroadcastValue` requires the implicit string index
|
|
42
|
+
signature of a JSON object, which TypeScript gives object type aliases but not
|
|
43
|
+
interfaces.
|
|
44
|
+
|
|
45
|
+
Snapshots return `DeepReadonly`, so application helpers should accept readonly
|
|
46
|
+
structure rather than cast it away. A helper that only needs a session ID can
|
|
47
|
+
preserve its useful result type with a generic boundary:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
function playerForSession<PlayerType extends { sessionId: string }>(options: {
|
|
51
|
+
room: { readonly players: readonly PlayerType[] }
|
|
52
|
+
sessionId: string | null
|
|
53
|
+
}): PlayerType | undefined {
|
|
54
|
+
return options.room.players.find((player) => player.sessionId === options.sessionId)
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
34
58
|
### Runtime managers
|
|
35
59
|
|
|
36
60
|
Every manager below is available as a property on `SolidObjectsRuntime`; the
|
|
@@ -48,7 +72,7 @@ class and result types are also exported for integration typing.
|
|
|
48
72
|
- `runtime.doctor` / `Doctor`: `run({ roundTrip })` structured installation
|
|
49
73
|
report.
|
|
50
74
|
- `runtime.testing` / `SolidObjectsTestHelper`: deterministic `drain()` and
|
|
51
|
-
dependency-ordered `reset()`.
|
|
75
|
+
explicit-time `runDueReminders()`, plus dependency-ordered `reset()`.
|
|
52
76
|
- `runtime.realtime` / `RealtimeManager`: `connect()`, process-local
|
|
53
77
|
`publish()`, and `close()`.
|
|
54
78
|
|
|
@@ -60,11 +84,16 @@ The manager types are `DeadLetter`; `ReminderPage`, `ReminderPageOptions`,
|
|
|
60
84
|
`QuietReconciliationOptions`, `ReconciliationInstance`, `ReconciliationPage`,
|
|
61
85
|
`ReconciliationPageOptions`, and `ReconciliationStatesOptions`;
|
|
62
86
|
`RetentionOptions`, `RetentionResult`, and `RetentionTarget`; and
|
|
63
|
-
`TestDrainOptions
|
|
87
|
+
`RunDueRemindersOptions`, `TestDrainOptions`, and `TestHelperRole`.
|
|
88
|
+
`RealtimeConnectionOptions`,
|
|
64
89
|
`RealtimeSession`, and `SubscriptionRequest` define the server session API.
|
|
65
90
|
`AdministrationOptions` carries the application-owned authorization context
|
|
66
91
|
for administration calls.
|
|
67
92
|
|
|
93
|
+
`ProcessRecord.shutdownState` is `"running"`, `"draining"`, or `"stopped"`;
|
|
94
|
+
there is no separate `running` field. `RetentionResult.count` means eligible
|
|
95
|
+
rows for `preview()` and rows actually deleted for `prune()`.
|
|
96
|
+
|
|
68
97
|
### Registration and integration
|
|
69
98
|
|
|
70
99
|
- `runtime.register(ActorClass)`: validate and register an actor definition.
|
|
@@ -72,7 +101,9 @@ for administration calls.
|
|
|
72
101
|
isolated runtime.
|
|
73
102
|
- `runtime.registerEffect(name, handler)`: register an at-least-once external
|
|
74
103
|
effect handler. `EffectContext` carries the stable effect ID and source
|
|
75
|
-
identity.
|
|
104
|
+
identity. Success operations receive `{ effectId, arguments, result }` and
|
|
105
|
+
failure operations receive `{ effectId, arguments, error }`; `arguments` is
|
|
106
|
+
the JSON object originally staged by `emit()`.
|
|
76
107
|
- `runtime.registerCommitAction(name, handler)`: register a same-database
|
|
77
108
|
fenced transaction handler. `CommitActionContext` includes the active
|
|
78
109
|
`DatabaseConnection`.
|
|
@@ -134,7 +165,8 @@ The root exports `SolidObjectsError` and its supported subclasses:
|
|
|
134
165
|
- admission and payload failures: `MailboxFull`, `InvalidPayload`,
|
|
135
166
|
`PayloadTooLarge`, `IdempotencyConflict`, `InvalidPayloadBroadcast`, and
|
|
136
167
|
`UnknownPayloadBroadcast`;
|
|
137
|
-
- definition and execution failures: `InvalidActor`, `
|
|
168
|
+
- definition and execution failures: `InvalidActor`, `InvalidRejectionCode`,
|
|
169
|
+
`UnknownActorType`,
|
|
138
170
|
`UnknownOperation`, `ActorCallCycle`, `QueryMutatedState`,
|
|
139
171
|
`StateMigrationError`, `ApplicationWriteForbidden`, `UnknownEffect`, and
|
|
140
172
|
`UnknownCommitAction`;
|
package/docs/browser-protocol.md
CHANGED
|
@@ -5,6 +5,13 @@ subscription requests and receives JSON invalidation envelopes over WebSocket.
|
|
|
5
5
|
The application supplies the rendering callback and authenticated WebSocket
|
|
6
6
|
server; `runtime.realtime` supplies the server-side session protocol.
|
|
7
7
|
|
|
8
|
+
The `observables` object contains values, not only invalidation names, and every
|
|
9
|
+
subscriber authorized for that actor receives the same projection. This differs
|
|
10
|
+
from Ruby morph components, which re-fetch a signed endpoint without putting
|
|
11
|
+
observable values on the wire. Keep secrets and subscriber-specific state out
|
|
12
|
+
of `observables()`; use personalized payloads or an application endpoint that
|
|
13
|
+
reauthorizes the component request.
|
|
14
|
+
|
|
8
15
|
The 0.1 subscription request is:
|
|
9
16
|
|
|
10
17
|
```json
|
package/docs/configuration.md
CHANGED
|
@@ -96,6 +96,25 @@ server.
|
|
|
96
96
|
|
|
97
97
|
## Database adapters
|
|
98
98
|
|
|
99
|
+
### Database value mapping
|
|
100
|
+
|
|
101
|
+
`DatabaseConnection.get<Row>()` and `all<Row>()` trust the caller-supplied row
|
|
102
|
+
type; they do not validate or convert driver results. Type rows to the adapter's
|
|
103
|
+
runtime representation or normalize them at the application boundary.
|
|
104
|
+
|
|
105
|
+
| SQL value | SQLite (`node:sqlite`) | PostgreSQL (`pg`) | MySQL (`mysql2`) |
|
|
106
|
+
| ----------------------------------- | --------------------------- | ----------------------------------------------- | ----------------------------------- |
|
|
107
|
+
| ordinary integer | `bigint` | `number` for `int2`/`int4`; `bigint` for `int8` | `number` for ordinary integer types |
|
|
108
|
+
| arbitrary precision integer/decimal | `bigint` for SQLite INTEGER | `numeric` remains the driver's decimal string | `BIGINT` and `DECIMAL` are strings |
|
|
109
|
+
| floating point | `number` | `number` | `number` |
|
|
110
|
+
| text | `string` | `string` | `string` |
|
|
111
|
+
| binary | `Uint8Array` | `Buffer` | `Buffer` |
|
|
112
|
+
| null | `null` | `null` | `null` |
|
|
113
|
+
|
|
114
|
+
`RunResult.changes` is always a `number`. `lastInsertId`, when an adapter
|
|
115
|
+
provides it, is a decimal `string`; SQLite and MySQL set it for nonzero generated
|
|
116
|
+
IDs, while PostgreSQL callers should use `RETURNING` with `get()`.
|
|
117
|
+
|
|
99
118
|
### SQLite
|
|
100
119
|
|
|
101
120
|
`sqlite({ path, timeoutMilliseconds = 5_000, lockRetryAttempts = 10 })` uses
|
|
@@ -19,11 +19,18 @@ do not parse error messages.
|
|
|
19
19
|
| `PayloadTooLarge` | Arguments, state, result, snapshot getter, effect result, or personalized payload exceeded its configured limit. | Reduce the JSON value or deliberately raise the corresponding limit. |
|
|
20
20
|
| `SyncInsideTransaction` | A committed call or message wait would self-deadlock inside this adapter's transaction. | Finish the transaction first or stage actor-owned work through a commit action. |
|
|
21
21
|
|
|
22
|
+
`this.reject()` accepts codes matching `[A-Za-z_][A-Za-z0-9_]*`, including
|
|
23
|
+
camelCase. An invalid code throws the non-retryable `InvalidRejectionCode`; the
|
|
24
|
+
operation fails on its first attempt and a synchronous caller receives
|
|
25
|
+
`MessageFailed` instead of waiting through retry backoff.
|
|
26
|
+
|
|
22
27
|
`MessageReference.status()`, `result()`, and `wait()` reauthorize the stored
|
|
23
28
|
operation. `result()` returns `undefined` while work is nonterminal, returns the
|
|
24
29
|
committed result when complete, and raises `Rejected` or `MessageFailed` for a
|
|
25
30
|
terminal refusal or failure. `wait()` blocks until the same terminal outcomes
|
|
26
|
-
or its deadline.
|
|
31
|
+
or its deadline. A reference does not retain the authorization context used to
|
|
32
|
+
send it; supply the context to each of these methods so the stored operation is
|
|
33
|
+
reauthorized.
|
|
27
34
|
|
|
28
35
|
## Definition and programming errors
|
|
29
36
|
|
|
@@ -31,6 +38,8 @@ These errors normally require a code or deployment correction:
|
|
|
31
38
|
|
|
32
39
|
- `InvalidActor`: invalid actor type, state version, migration declaration,
|
|
33
40
|
member name, payload declaration, or duplicate registration.
|
|
41
|
+
- `InvalidRejectionCode`: `reject()` received a code outside the supported
|
|
42
|
+
identifier grammar. It is terminal because retrying cannot change actor code.
|
|
34
43
|
- `UnknownActorType`, `UnknownOperation`, `UnknownEffect`, and
|
|
35
44
|
`UnknownCommitAction`: deployed registration does not match durable work or
|
|
36
45
|
code attempted an undeclared operation.
|
|
@@ -87,3 +96,9 @@ linked replacement message; repeating the call returns the same replacement.
|
|
|
87
96
|
|
|
88
97
|
Effects are different: they execute outside the actor transaction and are at
|
|
89
98
|
least once. Deduplicate external work with the stable `EffectContext.id`.
|
|
99
|
+
Success and failure callback operations receive the originally staged
|
|
100
|
+
`arguments` for actor-state correlation. A retryable failure scheduled into the
|
|
101
|
+
future is correctly considered idle for the present pass, so
|
|
102
|
+
`runtime.testing.drain()` does not advance retry backoff; use a
|
|
103
|
+
`NonRetryableError` when a test needs to exercise the exhausted failure callback
|
|
104
|
+
without waiting.
|
package/docs/parity.md
CHANGED
|
@@ -6,7 +6,7 @@ not copying a Rails API into Node.
|
|
|
6
6
|
|
|
7
7
|
Reference: Ruby `solid_objects` 0.12.0 at commit `a01b6f5`.
|
|
8
8
|
|
|
9
|
-
The Node `0.12.
|
|
9
|
+
The Node `0.12.1` implementation has spiritual parity with that reference. Its
|
|
10
10
|
relational runtime, correctness boundaries, administration, diagnostics,
|
|
11
11
|
realtime projections, browser behavior, and supported adapters have native
|
|
12
12
|
equivalents. Rails engine and rendering surfaces are intentionally replaced by
|
|
@@ -32,11 +32,11 @@ missing Ruby capabilities.
|
|
|
32
32
|
| Actor registry, durable identity, JSON state, and adjacent state migrations | Native | Ordinary classes, static actor types, inferred state, explicit migrations, and isolated runtime context across every actor-instance callback. |
|
|
33
33
|
| Fluent committed calls and background delivery | Native | `await reference.operation()` and `reference.send.operation()`. |
|
|
34
34
|
| Ordered mailbox, sequence allocation, idempotency, retries, dead letters, leases, renewal, and fenced commits | Native | Relational ready/claimed membership tables, distinct generated request IDs and caller idempotency keys, durable history, and adapter-appropriate sequence locking. |
|
|
35
|
-
| Domain rejection and strict poison ordering | Native | Rejections roll back without retry; retryable failures block later operations until completion or dead-lettering.
|
|
35
|
+
| Domain rejection and strict poison ordering | Native | Rejections accept JavaScript identifier-style codes and roll back without retry; invalid codes fail terminally, while retryable failures block later operations until completion or dead-lettering. |
|
|
36
36
|
| Bounded activation passes and hot-actor fairness | Native | Configurable turn-count and elapsed-time budgets bound each pass, then move only that actor's already-due memberships behind actors already waiting. |
|
|
37
37
|
| Bounded claim candidate scan | Native | A configurable ordered scan continues to another ready actor when a worker loses the first candidate's lease race. |
|
|
38
38
|
| Idle activation cache | Native | Long-running workers retain hydrated actors under renewable fenced leases, restore public state after failed turns, and release on timeout, fairness yield, lease loss, or shutdown. |
|
|
39
|
-
| Transactional effects and outcome operations | Native | At-least-once handlers receive immutable stable effect, attempt, source-message, and actor identity; success and failure
|
|
39
|
+
| Transactional effects and outcome operations | Native | At-least-once handlers receive immutable stable effect, attempt, source-message, and actor identity; success and failure operations also receive the originally staged arguments for correlation. |
|
|
40
40
|
| Actor-to-actor delivery | Native | `sendTo(reference).operation()` stages delivery in the source actor commit. |
|
|
41
41
|
| One-shot and recurring reminders | Native | Scheduling, replacement events, catch-up policy, stale-claim recovery, pausing, authorized inspection, and idempotent resume are implemented. |
|
|
42
42
|
| Same-database commit actions | Native | Registered actions receive source-message identity, mailbox sequence, activation generation, and the fenced transaction connection. |
|
|
@@ -60,7 +60,7 @@ missing Ruby capabilities.
|
|
|
60
60
|
| Doctor and schema verification | Native | Structured checks cover configuration, schema/version shape, adapter server versions, neutral-context policy probes, live roles, and a targeted round trip. |
|
|
61
61
|
| CLI | Native | The packaged executable loads an application runtime and exposes start, diagnostics, processes, dead letters, reminders, and explicit retention pruning as JSON. |
|
|
62
62
|
| Structured instrumentation | Native | An isolated transport-neutral sink emits immutable lifecycle metadata and structurally excludes application payloads. |
|
|
63
|
-
| Public test helper | Native | `runtime.testing` provides role-selective deterministic draining and dependency-ordered reset without relying on cascades.
|
|
63
|
+
| Public test helper | Native | `runtime.testing` provides role-selective deterministic draining, explicit-time due-reminder execution, and dependency-ordered reset without relying on cascades. |
|
|
64
64
|
|
|
65
65
|
## Databases and wake-up
|
|
66
66
|
|
|
@@ -76,15 +76,15 @@ missing Ruby capabilities.
|
|
|
76
76
|
|
|
77
77
|
## Realtime and browser behavior
|
|
78
78
|
|
|
79
|
-
| Capability | Status | TypeScript shape or remaining work
|
|
80
|
-
| ------------------------------------------------------------ | -------------- |
|
|
81
|
-
| Explicit observable projection and durable invalidations | Native | `observables()` is opt-in;
|
|
82
|
-
| Action Cable channels and signed stream names | Not applicable | `runtime.realtime` provides authenticated transport-neutral sessions; the host owns its HTTP/WebSocket server and authentication.
|
|
83
|
-
| Authorized subscriptions | Native | Each request is denied by default and authorized before actor lookup; sessions replay committed observables and fence ordered durable revisions. Multi-process hosts explicitly bridge their shared transport.
|
|
84
|
-
| Turbo scalar replacement | Not applicable | The browser client exposes invalidations to application rendering code. Framework adapters can be separate packages.
|
|
85
|
-
| Keyed component refresh, morph/replace, and batch coalescing | Native | A typed framework-neutral registry selects explicit dependencies, coalesces batch requests, aborts superseded work, fences each target, and delegates synchronous application strategy to the host.
|
|
86
|
-
| Personalized payload broadcasts | Native | Static typed projections run against committed state under each fresh subscriber context, reauthorize as queries, isolate failures, and carry independent revision fences.
|
|
87
|
-
| Real-browser compatibility suite | Native | Playwright exercises subscription replay over native WebSocket, incarnation/revision fences, payload delivery, component batching, and cancellation in Chromium.
|
|
79
|
+
| Capability | Status | TypeScript shape or remaining work |
|
|
80
|
+
| ------------------------------------------------------------ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
81
|
+
| Explicit observable projection and durable invalidations | Native | `observables()` is opt-in; changed values enter invalidation envelopes and are visible to every authorized subscriber. Unlike Ruby morph refreshes, values cross the wire, so private or subscriber-specific state belongs in payloads or reauthorized component endpoints. |
|
|
82
|
+
| Action Cable channels and signed stream names | Not applicable | `runtime.realtime` provides authenticated transport-neutral sessions; the host owns its HTTP/WebSocket server and authentication. |
|
|
83
|
+
| Authorized subscriptions | Native | Each request is denied by default and authorized before actor lookup; sessions replay committed observables and fence ordered durable revisions. Multi-process hosts explicitly bridge their shared transport. |
|
|
84
|
+
| Turbo scalar replacement | Not applicable | The browser client exposes invalidations to application rendering code. Framework adapters can be separate packages. |
|
|
85
|
+
| Keyed component refresh, morph/replace, and batch coalescing | Native | A typed framework-neutral registry selects explicit dependencies, coalesces batch requests, aborts superseded work, fences each target, and delegates synchronous application strategy to the host. |
|
|
86
|
+
| Personalized payload broadcasts | Native | Static typed projections run against committed state under each fresh subscriber context, reauthorize as queries, isolate failures, and carry independent revision fences. |
|
|
87
|
+
| Real-browser compatibility suite | Native | Playwright exercises subscription replay over native WebSocket, incarnation/revision fences, payload delivery, component batching, and cancellation in Chromium. |
|
|
88
88
|
|
|
89
89
|
## Rails-specific surfaces
|
|
90
90
|
|
package/docs/releasing.md
CHANGED
|
@@ -26,8 +26,9 @@ npm trust github solid-objects \
|
|
|
26
26
|
|
|
27
27
|
## Release procedure
|
|
28
28
|
|
|
29
|
-
1. Update the version in `package.json` and `
|
|
30
|
-
release notes out of the Unreleased
|
|
29
|
+
1. Update the version in `package.json` and `src/version.ts`, refresh the
|
|
30
|
+
lockfile when needed, and move the release notes out of the Unreleased
|
|
31
|
+
section in `CHANGELOG.md`.
|
|
31
32
|
2. Run `pnpm run format:check`, `pnpm run check`, `pnpm run test:coverage`,
|
|
32
33
|
`pnpm run build`, `pnpm run pack:check`, and
|
|
33
34
|
`pnpm audit --audit-level=high`.
|
|
@@ -35,8 +36,8 @@ npm trust github solid-objects \
|
|
|
35
36
|
4. Create and push an annotated tag matching the package version:
|
|
36
37
|
|
|
37
38
|
```shell
|
|
38
|
-
git tag -a v0.
|
|
39
|
-
git push origin v0.
|
|
39
|
+
git tag -a v0.12.1 -m "Version 0.12.1"
|
|
40
|
+
git push origin v0.12.1
|
|
40
41
|
```
|
|
41
42
|
|
|
42
43
|
The tag runs the complete CI matrix. The publish job starts only after every
|
|
@@ -116,10 +116,10 @@ crash, so it cannot establish correctness.
|
|
|
116
116
|
## Domain rejection and failure
|
|
117
117
|
|
|
118
118
|
Call `this.reject(code, { message, details })` when an operation is valid but
|
|
119
|
-
the domain refuses it. Codes
|
|
120
|
-
|
|
121
|
-
`rejected`, and later mailbox work remains eligible. The caller
|
|
122
|
-
`Rejected` with the code, frozen JSON details, and durable message ID.
|
|
119
|
+
the domain refuses it. Codes use the same identifier rule as actor members:
|
|
120
|
+
`[A-Za-z_][A-Za-z0-9_]*`. The turn rolls back, staged work is discarded, the
|
|
121
|
+
message becomes `rejected`, and later mailbox work remains eligible. The caller
|
|
122
|
+
receives `Rejected` with the code, frozen JSON details, and durable message ID.
|
|
123
123
|
|
|
124
124
|
Throwing another error rolls the turn back and schedules a retry according to
|
|
125
125
|
`maxAttempts` and `retryDelayMilliseconds`. Throw a custom subclass of
|