@usearete/sdk 0.1.5 → 0.3.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/README.md +331 -56
- package/dist/index.cjs +6664 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1521 -260
- package/dist/index.esm.js +4603 -1085
- package/dist/index.esm.js.map +1 -1
- package/dist/ssr/handlers.cjs +794 -0
- package/dist/ssr/handlers.cjs.map +1 -0
- package/dist/ssr/handlers.esm.js +523 -4
- package/dist/ssr/handlers.esm.js.map +1 -1
- package/dist/ssr/index.cjs +795 -0
- package/dist/ssr/index.cjs.map +1 -0
- package/dist/ssr/index.esm.js +523 -4
- package/dist/ssr/index.esm.js.map +1 -1
- package/dist/ssr/nextjs-app.cjs +859 -0
- package/dist/ssr/nextjs-app.cjs.map +1 -0
- package/dist/ssr/nextjs-app.esm.js +523 -4
- package/dist/ssr/nextjs-app.esm.js.map +1 -1
- package/dist/ssr/tanstack-start.cjs +881 -0
- package/dist/ssr/tanstack-start.cjs.map +1 -0
- package/dist/ssr/tanstack-start.esm.js +523 -4
- package/dist/ssr/tanstack-start.esm.js.map +1 -1
- package/dist/ssr/vite.cjs +887 -0
- package/dist/ssr/vite.cjs.map +1 -0
- package/dist/ssr/vite.esm.js +523 -4
- package/dist/ssr/vite.esm.js.map +1 -1
- package/package.json +10 -8
- package/dist/index.js +0 -3074
- package/dist/index.js.map +0 -1
- package/dist/ssr/handlers.js +0 -294
- package/dist/ssr/handlers.js.map +0 -1
- package/dist/ssr/index.js +0 -295
- package/dist/ssr/index.js.map +0 -1
- package/dist/ssr/nextjs-app.js +0 -359
- package/dist/ssr/nextjs-app.js.map +0 -1
- package/dist/ssr/tanstack-start.js +0 -381
- package/dist/ssr/tanstack-start.js.map +0 -1
- package/dist/ssr/vite.js +0 -387
- package/dist/ssr/vite.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Arete TypeScript SDK
|
|
2
2
|
|
|
3
|
-
Pure TypeScript SDK for
|
|
3
|
+
Pure TypeScript SDK for generated stack definitions, program SDKs, prepared operation execution, and chain reads.
|
|
4
|
+
|
|
5
|
+
Connected clients expose the typed six-route transaction relay as `client.transactions`. Wallet adapters receive it per invocation from `client.transaction` and `client.inspectOperation`, so a shared wallet can safely serve multiple clients. Sessions expose `session.transactions` and accept a `transactions` override. HTTP `u64` fields are decimal strings on the wire and `bigint` in the SDK; sends are never automatically retried.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -8,104 +10,377 @@ Pure TypeScript SDK for the Arete Solana streaming platform. Framework-agnostic
|
|
|
8
10
|
npm install @usearete/sdk
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createSession } from '@usearete/sdk';
|
|
17
|
+
import { MY_STACK } from './generated/my-stack';
|
|
18
|
+
|
|
19
|
+
const session = await createSession({
|
|
20
|
+
stacks: { myStack: MY_STACK },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
for await (const item of session.stacks.myStack.views.MyEntity.list.use()) {
|
|
24
|
+
console.log(item);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## SDK Shapes
|
|
29
|
+
|
|
30
|
+
### Mental Model
|
|
31
|
+
|
|
32
|
+
Think of a generated stack as a **cartridge**: it packages one domain's typed views, queries, programs, reads, and flows, plus any cross-program addresses, constants, defaults, or math. "Cartridge" is only a mental model; the public API continues to use the existing generated stack objects and types.
|
|
33
|
+
|
|
34
|
+
An Arete session is the **console**. Insert one or more generated stacks under `session.stacks`, optionally add standalone programs, and use the console's shared `session.programs`, `session.chain`, and `session.execute(...)` surfaces. Programs packaged by a stack are automatically promoted to `session.programs` without creating another connection or runtime.
|
|
35
|
+
|
|
36
|
+
Every semantic operation has an explicit cardinality:
|
|
37
|
+
|
|
38
|
+
- `instruction` - exactly one Solana instruction
|
|
39
|
+
- `transaction` - exactly one atomic transaction with one or more instructions
|
|
40
|
+
- `flow` - one or more sequential transactions
|
|
41
|
+
|
|
42
|
+
Every semantic operation exposes one pure entrypoint:
|
|
12
43
|
|
|
13
|
-
|
|
44
|
+
- `.prepare(input)`
|
|
14
45
|
|
|
15
|
-
|
|
16
|
-
import { Arete } from '@usearete/sdk';
|
|
17
|
-
import { SETTLEMENT_GAME_STACK } from './generated/settlement-game-stack';
|
|
46
|
+
Every connected client or session exposes one semantic execution entrypoint:
|
|
18
47
|
|
|
19
|
-
|
|
20
|
-
|
|
48
|
+
- `.execute(prepared, options?)`
|
|
49
|
+
|
|
50
|
+
There is no semantic `.resolve()`, `.build()`, `.stage()`, `.plan()`, or `.send()` projection surface anymore.
|
|
51
|
+
|
|
52
|
+
### Connected Stack Cartridges
|
|
53
|
+
|
|
54
|
+
Access a connected generated stack through `session.stacks.<name>`. Its stable namespaces are:
|
|
55
|
+
|
|
56
|
+
- `views` - typed streaming, list, and state views
|
|
57
|
+
- `queries` - stack-level HTTP queries
|
|
58
|
+
- `programs` - owner-scoped program SDKs; the same connected objects are promoted to `session.programs`
|
|
59
|
+
- `addresses` - domain address derivations, when defined
|
|
60
|
+
- `constants` - domain constants and enums, when defined
|
|
61
|
+
- `defaults` - reusable domain defaults, when defined
|
|
62
|
+
- `math` - pure domain calculations, when defined
|
|
63
|
+
- `read` - connected, domain-oriented reads, when defined
|
|
64
|
+
- `flows` - stack-level multi-transaction operations, when defined
|
|
65
|
+
|
|
66
|
+
These are namespaces on the existing connected stack object; no separate cartridge class or type is introduced.
|
|
67
|
+
|
|
68
|
+
### Program SDKs
|
|
69
|
+
|
|
70
|
+
Each packaged, attached, or standalone program is canonically available under `session.programs.<name>` and exposes these stable namespaces. The owner-scoped `session.stacks.<name>.programs.<program>` path remains available when disambiguation is needed.
|
|
71
|
+
|
|
72
|
+
- `programId` - the deployed Solana program address
|
|
73
|
+
- `schemas` - generated validation schemas
|
|
74
|
+
- `pdas` - exact generated PDA definitions
|
|
75
|
+
- `addresses` - semantic address derivations, when defined
|
|
76
|
+
- `accounts` - typed point reads for program accounts
|
|
77
|
+
- `queries` - program-level HTTP queries
|
|
78
|
+
- `raw` - exact IDL instruction builders with synchronous `.build(...)`
|
|
79
|
+
- `instructions` - semantic one-instruction operations with `.prepare(...)`
|
|
80
|
+
- `transactions` - semantic one-transaction operations with `.prepare(...)`
|
|
81
|
+
- `flows` - program-local multi-transaction operations with `.prepare(...)`
|
|
82
|
+
- `constants` - program constants and enums
|
|
83
|
+
- `defaults` - reusable program defaults
|
|
84
|
+
- `math` - pure protocol calculations
|
|
85
|
+
|
|
86
|
+
### Raw Instructions
|
|
87
|
+
|
|
88
|
+
Use raw handlers when you want exact wire control and will compose the transaction yourself:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const ix = session.programs.splToken.raw.InitializeMint2.build({
|
|
92
|
+
mint,
|
|
93
|
+
decimals: 6,
|
|
94
|
+
mint_authority: authority,
|
|
95
|
+
freeze_authority: null,
|
|
21
96
|
});
|
|
97
|
+
|
|
98
|
+
await session.transaction([ix]);
|
|
22
99
|
```
|
|
23
100
|
|
|
24
|
-
|
|
101
|
+
Raw builders are the exact IDL escape hatch. Instruction names, account names, argument names, and nested objects retain the generated IDL shape, including snake_case where the IDL uses it.
|
|
25
102
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
103
|
+
### Semantic Operations
|
|
104
|
+
|
|
105
|
+
Use semantic operations for normal application code. Their `.prepare(...)` methods accept semantic, camelCase object inputs, derive routine addresses, normalize amounts, and return prepared artifacts. Use `raw` only when you deliberately need the exact IDL surface.
|
|
106
|
+
|
|
107
|
+
Instruction example:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const prepared = await session.programs.tokenMetadata.instructions.createMetadataAccountV3.prepare({
|
|
111
|
+
mint,
|
|
112
|
+
mintAuthority,
|
|
113
|
+
payer,
|
|
114
|
+
updateAuthority,
|
|
115
|
+
name,
|
|
116
|
+
symbol,
|
|
117
|
+
uri,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
console.log(prepared.kind); // 'instruction'
|
|
121
|
+
console.log(prepared.instruction);
|
|
122
|
+
console.log(prepared.artifacts);
|
|
123
|
+
|
|
124
|
+
await session.execute(prepared);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Transaction example:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
const prepared = await session.programs.cpAmm.transactions.swap.exactIn.prepare({
|
|
131
|
+
pool,
|
|
132
|
+
payer,
|
|
133
|
+
inputTokenMint,
|
|
134
|
+
amountIn: { ui: '1.25' },
|
|
135
|
+
minimumAmountOut: 1n,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
console.log(prepared.kind); // 'transaction'
|
|
139
|
+
console.log(prepared.transaction.instructions.length);
|
|
140
|
+
|
|
141
|
+
await session.execute(prepared);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Flow example:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const prepared = await session.programs.presale.flows.escrow.depositPermissionless.prepare({
|
|
148
|
+
presale,
|
|
149
|
+
owner,
|
|
150
|
+
maxAmount: { ui: '1000' },
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
console.log(prepared.kind); // 'flow'
|
|
154
|
+
console.log(prepared.plan.transactions.length);
|
|
155
|
+
|
|
156
|
+
await session.execute(prepared);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Prepared Shapes
|
|
160
|
+
|
|
161
|
+
Prepared values are immutable and discriminated:
|
|
162
|
+
|
|
163
|
+
- `PreparedInstruction`
|
|
164
|
+
- `PreparedTransaction`
|
|
165
|
+
- `PreparedFlow`
|
|
166
|
+
|
|
167
|
+
All prepared values include:
|
|
168
|
+
|
|
169
|
+
- `kind`
|
|
170
|
+
- `name`
|
|
171
|
+
- `artifacts`
|
|
172
|
+
- `plan.transactions`
|
|
173
|
+
|
|
174
|
+
Instruction values also include `.instruction`, and transaction values include `.transaction`.
|
|
175
|
+
|
|
176
|
+
Prepared instructions can be composed directly into a transaction without
|
|
177
|
+
extracting `.instruction`:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
const transaction = createPreparedTransaction({
|
|
181
|
+
name: 'configureMint',
|
|
182
|
+
instructions: [initializeMint, setAuthority],
|
|
183
|
+
artifacts: { mint },
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Prepared instructions and prepared transactions can also be flattened into one
|
|
188
|
+
atomic transaction without reaching into their transaction bodies:
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
const transaction = createPreparedTransaction({
|
|
192
|
+
name: 'createAndConfigureMint',
|
|
193
|
+
operations: [createMint, createMetadata, setAuthority],
|
|
194
|
+
artifacts: { mint },
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Only single-transaction operations are accepted by `operations`. A
|
|
199
|
+
`PreparedFlow` must retain its ordered transaction boundaries.
|
|
200
|
+
|
|
201
|
+
Child signer and error metadata is inherited unless the transaction explicitly
|
|
202
|
+
provides `requiredSignerAddresses` or `errors`.
|
|
203
|
+
|
|
204
|
+
Every successful execution receipt exposes its signatures in transaction order:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
const receipt = await session.execute(prepared);
|
|
208
|
+
console.log(receipt.signatures);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Instruction and transaction receipts contain one signature. Flow receipts
|
|
212
|
+
contain one signature for each executed transaction.
|
|
213
|
+
|
|
214
|
+
Use `describePreparedOperation(prepared)` for a typed, JSON-safe description, or
|
|
215
|
+
`formatPreparedOperation(prepared)` for human-readable text.
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
const description = describePreparedOperation(prepared);
|
|
219
|
+
console.log(JSON.stringify(description, null, 2));
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Sessions
|
|
223
|
+
|
|
224
|
+
Use a session as the console for one or more generated stack cartridges and/or standalone programs behind one execution surface. Stack programs are promoted by reference; `session.programs.presale === session.stacks.presale.programs.presale`.
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import { createSession, createSignerRegistry } from '@usearete/sdk';
|
|
228
|
+
|
|
229
|
+
const signerRegistry = createSignerRegistry([
|
|
230
|
+
[creatorAddress, creatorSigner],
|
|
231
|
+
]);
|
|
232
|
+
|
|
233
|
+
const session = await createSession(
|
|
234
|
+
{
|
|
235
|
+
stacks: {
|
|
236
|
+
squads: SQUADS_V4_STREAM_STACK,
|
|
237
|
+
presale: METEORA_PRESALE_STREAM_STACK,
|
|
238
|
+
},
|
|
239
|
+
programs: {
|
|
240
|
+
splToken: SPL_TOKEN_PROGRAM,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
transport: 'http',
|
|
245
|
+
endpoints: { http: 'http://127.0.0.1:8081' },
|
|
246
|
+
wallet,
|
|
247
|
+
signerRegistry,
|
|
32
248
|
}
|
|
33
|
-
|
|
249
|
+
);
|
|
34
250
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
251
|
+
const prepared = await session.stacks.squads.flows.vaultProposal.prepare(...);
|
|
252
|
+
await session.execute(prepared);
|
|
253
|
+
|
|
254
|
+
// Signers can also be managed after session creation.
|
|
255
|
+
session.signerRegistry.register(memberAddress, memberSigner);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Equivalent entrypoints:
|
|
38
259
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
260
|
+
- `createSession(...)`
|
|
261
|
+
- `Arete.session(...)`
|
|
262
|
+
|
|
263
|
+
Session surface:
|
|
264
|
+
|
|
265
|
+
- `session.stacks.<name>` - connected generated stacks
|
|
266
|
+
- `session.programs.<name>` - connected packaged, attached, or standalone programs
|
|
267
|
+
- `session.chain` - canonical generic chain reads
|
|
268
|
+
- `session.signerRegistry`
|
|
269
|
+
- `session.transaction(...)`
|
|
270
|
+
- `session.execute(...)`
|
|
271
|
+
|
|
272
|
+
Prefer these connected paths in application code. `Arete.connect(STACK, ...)` remains available when a direct single-stack client is more convenient.
|
|
273
|
+
|
|
274
|
+
If multiple stacks package the same program key, the first stack in the session definition owns the promoted alias and the session emits a warning. Both owner-scoped stack paths remain available. An explicitly declared standalone program always owns its top-level key.
|
|
275
|
+
|
|
276
|
+
## Chain Reads
|
|
277
|
+
|
|
278
|
+
Generic chain reads use the console-level `session.chain` surface.
|
|
279
|
+
|
|
280
|
+
Available reads include:
|
|
281
|
+
|
|
282
|
+
- `exists(address)`
|
|
283
|
+
- `lamports(address)`
|
|
284
|
+
- `minimumBalanceForRentExemption(space)`
|
|
285
|
+
- `clock()`
|
|
286
|
+
- `account(address)`
|
|
287
|
+
- `mint(address)`
|
|
288
|
+
- `tokenAccount(address)`
|
|
289
|
+
- `balance({ owner, mint, tokenProgram? })`
|
|
290
|
+
|
|
291
|
+
Example:
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
const rentLamports = await session.chain.minimumBalanceForRentExemption(82);
|
|
295
|
+
const mintInfo = await session.chain.mint(mintAddress);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Streaming Views
|
|
299
|
+
|
|
300
|
+
Views are still the main streaming surface.
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
for await (const update of session.stacks.myStack.views.settlementGame.list.watch()) {
|
|
304
|
+
if (update.type === 'upsert') {
|
|
305
|
+
console.log(update.key, update.data);
|
|
43
306
|
}
|
|
44
307
|
}
|
|
308
|
+
|
|
309
|
+
const game = await session.stacks.myStack.views.settlementGame.state.get('game-123');
|
|
45
310
|
```
|
|
46
311
|
|
|
47
|
-
|
|
312
|
+
Every options object is a protocol v2 query with independent ordered membership. Different windows and filters on the same view can run concurrently, while equivalent normalized queries share one reference-counted wire subscription:
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
const rounds = session.stacks.ore.views.OreRound.latest;
|
|
48
316
|
|
|
49
|
-
|
|
50
|
-
const
|
|
317
|
+
const firstPage = rounds.watch({ take: 10 });
|
|
318
|
+
const secondPage = rounds.watch({ take: 10, skip: 10 });
|
|
51
319
|
|
|
52
|
-
const
|
|
320
|
+
for await (const update of firstPage) {
|
|
321
|
+
if (update.type === 'remove') {
|
|
322
|
+
console.log(`${update.key} left the first-page window`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
53
325
|
```
|
|
54
326
|
|
|
55
|
-
|
|
327
|
+
Completed authoritative snapshots replace membership for their exact query after reconnect. Cursor queries created with `after` receive incremental snapshots and merge without pruning.
|
|
56
328
|
|
|
57
|
-
|
|
58
|
-
console.log(a4.connectionState);
|
|
329
|
+
Low-level `QueryLease.refresh()` returns a `Promise<void>` that resolves after the refreshed subscription's next complete snapshot is committed. Registration, send, and subscription failures reject and are published on the lease's `QuerySnapshot.error`, with `isRefreshing` cleared. Subscriptions created with snapshots disabled resolve after the refresh request is sent.
|
|
59
330
|
|
|
60
|
-
|
|
61
|
-
console.log('Connection state:', state);
|
|
62
|
-
});
|
|
331
|
+
### Connection recovery
|
|
63
332
|
|
|
64
|
-
|
|
333
|
+
`autoConnect` and `autoReconnect` default to `true` and control separate lifecycle phases. Set `autoConnect: false` to create a disconnected client that the application connects later. Set `autoReconnect: false` when the application wants to handle post-disconnect recovery itself:
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
const client = await Arete.connect(MY_STACK, {
|
|
337
|
+
autoConnect: false,
|
|
338
|
+
autoReconnect: false,
|
|
339
|
+
});
|
|
65
340
|
```
|
|
66
341
|
|
|
67
|
-
|
|
342
|
+
The same independent options are available per stack member in `createSession(...)` and on React's `AreteProvider`.
|
|
343
|
+
|
|
344
|
+
### Caller-supplied schema diagnostics
|
|
68
345
|
|
|
69
|
-
|
|
346
|
+
Core view schemas continue to filter rejected entities. React view hooks additionally accept `onSchemaValidationError`, which reports `{ view, key?, entity, error }` without changing accepted data.
|
|
70
347
|
|
|
71
|
-
|
|
348
|
+
## Safe amount parsing
|
|
72
349
|
|
|
73
|
-
|
|
74
|
-
- `views` - Typed view accessors based on your stack definition
|
|
75
|
-
- `connectionState` - Current connection state
|
|
76
|
-
- `onConnectionStateChange(callback)` - Listen for connection changes
|
|
77
|
-
- `disconnect()` - Disconnect from the server
|
|
350
|
+
`toRawAmount(input, decimals)` throws when user input is invalid. Form and API boundaries can use `safeToRawAmount(input, decimals)` instead:
|
|
78
351
|
|
|
79
|
-
|
|
352
|
+
```ts
|
|
353
|
+
import { safeToRawAmount } from '@usearete/sdk';
|
|
80
354
|
|
|
81
|
-
|
|
355
|
+
const result = safeToRawAmount({ ui: amountText }, 9);
|
|
356
|
+
if (!result.success) {
|
|
357
|
+
console.error(result.error);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
82
360
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- `watchRich(key)` - AsyncIterable with before/after diffs
|
|
86
|
-
- `get(key)` - Get entity by key
|
|
87
|
-
- `getSync(key)` - Get entity synchronously (if available)
|
|
361
|
+
console.log(result.data); // bigint in raw base units
|
|
362
|
+
```
|
|
88
363
|
|
|
89
|
-
|
|
90
|
-
- `watch()` - AsyncIterable of all updates
|
|
91
|
-
- `watchRich()` - AsyncIterable with before/after diffs
|
|
92
|
-
- `get()` - Get all entities
|
|
93
|
-
- `getSync()` - Get all entities synchronously (if available)
|
|
364
|
+
It returns `{ success: true, data } | { success: false, error }` and never throws for an invalid amount input.
|
|
94
365
|
|
|
95
|
-
|
|
366
|
+
## Update Types
|
|
96
367
|
|
|
97
|
-
```
|
|
368
|
+
```ts
|
|
98
369
|
type Update<T> =
|
|
99
370
|
| { type: 'upsert'; key: string; data: T }
|
|
100
371
|
| { type: 'patch'; key: string; data: Partial<T> }
|
|
372
|
+
| { type: 'remove'; key: string }
|
|
101
373
|
| { type: 'delete'; key: string };
|
|
102
374
|
|
|
103
375
|
type RichUpdate<T> =
|
|
104
376
|
| { type: 'created'; key: string; data: T }
|
|
105
377
|
| { type: 'updated'; key: string; before: T; after: T; patch?: unknown }
|
|
378
|
+
| { type: 'removed'; key: string; lastKnown?: T }
|
|
106
379
|
| { type: 'deleted'; key: string; lastKnown?: T };
|
|
107
380
|
```
|
|
108
381
|
|
|
382
|
+
`remove` means an entity left only this query's filter or window. `delete` means the source entity was deleted and is removed from every query for that view.
|
|
383
|
+
|
|
109
384
|
## License
|
|
110
385
|
|
|
111
386
|
MIT
|