@proseql/rpc 0.2.3 → 0.2.4
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 +557 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
# @proseql/rpc
|
|
2
|
+
|
|
3
|
+
Type-safe Effect RPC integration for ProseQL databases. Derive typed RPC procedures from your database config with full error inference.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @proseql/rpc
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { Effect, Schema } from "effect"
|
|
15
|
+
import { createEffectDatabase } from "@proseql/core"
|
|
16
|
+
import { makeRpcGroup, makeRpcHandlers } from "@proseql/rpc"
|
|
17
|
+
|
|
18
|
+
const BookSchema = Schema.Struct({
|
|
19
|
+
id: Schema.String,
|
|
20
|
+
title: Schema.String,
|
|
21
|
+
author: Schema.String,
|
|
22
|
+
year: Schema.Number,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const config = {
|
|
26
|
+
books: {
|
|
27
|
+
schema: BookSchema,
|
|
28
|
+
relationships: {},
|
|
29
|
+
},
|
|
30
|
+
} as const
|
|
31
|
+
|
|
32
|
+
// 1. Derive RPC group from your database config
|
|
33
|
+
const rpcs = makeRpcGroup(config)
|
|
34
|
+
|
|
35
|
+
// 2. Create handler implementations
|
|
36
|
+
const program = Effect.gen(function* () {
|
|
37
|
+
const handlers = yield* makeRpcHandlers(config, {
|
|
38
|
+
books: [{ id: "1", title: "Dune", author: "Frank Herbert", year: 1965 }],
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// 3. Use handlers directly or wire to RPC transport
|
|
42
|
+
const book = yield* handlers.books.findById({ id: "1" })
|
|
43
|
+
console.log(book.title) // "Dune"
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
await Effect.runPromise(program)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
For the full query and mutation API, see [`@proseql/core`](https://www.npmjs.com/package/@proseql/core).
|
|
50
|
+
|
|
51
|
+
## RPC Group Derivation
|
|
52
|
+
|
|
53
|
+
`makeRpcGroup` derives typed RPC request schemas from your database config. Each collection gets request classes for all CRUD and batch operations.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { makeRpcGroup } from "@proseql/rpc"
|
|
57
|
+
|
|
58
|
+
const rpcs = makeRpcGroup(config)
|
|
59
|
+
// rpcs.books.FindByIdRequest
|
|
60
|
+
// rpcs.books.QueryRequest
|
|
61
|
+
// rpcs.books.CreateRequest
|
|
62
|
+
// rpcs.books.UpdateRequest
|
|
63
|
+
// rpcs.books.DeleteRequest
|
|
64
|
+
// rpcs.books.AggregateRequest
|
|
65
|
+
// rpcs.books.CreateManyRequest
|
|
66
|
+
// rpcs.books.UpdateManyRequest
|
|
67
|
+
// rpcs.books.DeleteManyRequest
|
|
68
|
+
// rpcs.books.UpsertRequest
|
|
69
|
+
// rpcs.books.UpsertManyRequest
|
|
70
|
+
// rpcs.books.QueryStreamRequest
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Request Tags
|
|
74
|
+
|
|
75
|
+
Each request class is tagged with the collection and operation name:
|
|
76
|
+
|
|
77
|
+
| Request Class | Tag |
|
|
78
|
+
|--------------|-----|
|
|
79
|
+
| `FindByIdRequest` | `books.findById` |
|
|
80
|
+
| `QueryRequest` | `books.query` |
|
|
81
|
+
| `QueryStreamRequest` | `books.queryStream` |
|
|
82
|
+
| `CreateRequest` | `books.create` |
|
|
83
|
+
| `UpdateRequest` | `books.update` |
|
|
84
|
+
| `DeleteRequest` | `books.delete` |
|
|
85
|
+
| `AggregateRequest` | `books.aggregate` |
|
|
86
|
+
| `CreateManyRequest` | `books.createMany` |
|
|
87
|
+
| `UpdateManyRequest` | `books.updateMany` |
|
|
88
|
+
| `DeleteManyRequest` | `books.deleteMany` |
|
|
89
|
+
| `UpsertRequest` | `books.upsert` |
|
|
90
|
+
| `UpsertManyRequest` | `books.upsertMany` |
|
|
91
|
+
|
|
92
|
+
### Creating Request Instances
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const rpcs = makeRpcGroup(config)
|
|
96
|
+
|
|
97
|
+
// FindById
|
|
98
|
+
const findById = new rpcs.books.FindByIdRequest({ id: "1" })
|
|
99
|
+
|
|
100
|
+
// Query with filters and sorting
|
|
101
|
+
const query = new rpcs.books.QueryRequest({
|
|
102
|
+
where: { year: { $gt: 1980 } },
|
|
103
|
+
sort: { year: "desc" },
|
|
104
|
+
limit: 10,
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// Create
|
|
108
|
+
const create = new rpcs.books.CreateRequest({
|
|
109
|
+
data: { title: "Neuromancer", author: "William Gibson", year: 1984 },
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// Update
|
|
113
|
+
const update = new rpcs.books.UpdateRequest({
|
|
114
|
+
id: "1",
|
|
115
|
+
updates: { genre: "classic" },
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// Delete
|
|
119
|
+
const deleteReq = new rpcs.books.DeleteRequest({ id: "1" })
|
|
120
|
+
|
|
121
|
+
// Aggregate
|
|
122
|
+
const aggregate = new rpcs.books.AggregateRequest({
|
|
123
|
+
count: true,
|
|
124
|
+
groupBy: "author",
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## RPC Handlers
|
|
129
|
+
|
|
130
|
+
### `makeRpcHandlers`
|
|
131
|
+
|
|
132
|
+
Creates handler implementations from a database config. Returns an Effect that produces handlers for all collections.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { Effect } from "effect"
|
|
136
|
+
import { makeRpcHandlers } from "@proseql/rpc"
|
|
137
|
+
|
|
138
|
+
const program = Effect.gen(function* () {
|
|
139
|
+
const handlers = yield* makeRpcHandlers(config, {
|
|
140
|
+
books: [{ id: "1", title: "Dune", author: "Frank Herbert", year: 1965 }],
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// Use handlers
|
|
144
|
+
const book = yield* handlers.books.findById({ id: "1" })
|
|
145
|
+
const allBooks = yield* handlers.books.query({})
|
|
146
|
+
const created = yield* handlers.books.create({
|
|
147
|
+
data: { title: "New Book", author: "Author", year: 2024 },
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `makeRpcHandlersFromDatabase`
|
|
153
|
+
|
|
154
|
+
Creates handlers from an existing database instance. Use this when you need file persistence or want to share a database across multiple transports.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { Effect, Layer } from "effect"
|
|
158
|
+
import { createPersistentEffectDatabase, NodeStorageLayer, makeSerializerLayer, jsonCodec } from "@proseql/node"
|
|
159
|
+
import { makeRpcHandlersFromDatabase } from "@proseql/rpc"
|
|
160
|
+
|
|
161
|
+
const config = {
|
|
162
|
+
books: {
|
|
163
|
+
schema: BookSchema,
|
|
164
|
+
file: "./data/books.json",
|
|
165
|
+
relationships: {},
|
|
166
|
+
},
|
|
167
|
+
} as const
|
|
168
|
+
|
|
169
|
+
const program = Effect.gen(function* () {
|
|
170
|
+
// Create persistent database
|
|
171
|
+
const db = yield* createPersistentEffectDatabase(config, { books: [] })
|
|
172
|
+
|
|
173
|
+
// Wire RPC handlers to the persistent database
|
|
174
|
+
const handlers = makeRpcHandlersFromDatabase(config, db)
|
|
175
|
+
|
|
176
|
+
// Mutations through RPC now trigger persistence automatically
|
|
177
|
+
yield* handlers.books.create({
|
|
178
|
+
data: { id: "1", title: "Dune", author: "Frank Herbert", year: 1965 },
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Flush to ensure data is written
|
|
182
|
+
yield* Effect.promise(() => db.flush())
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
const PersistenceLayer = Layer.merge(
|
|
186
|
+
NodeStorageLayer,
|
|
187
|
+
makeSerializerLayer([jsonCodec()]),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
await Effect.runPromise(
|
|
191
|
+
program.pipe(Effect.provide(PersistenceLayer), Effect.scoped),
|
|
192
|
+
)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### `makeRpcHandlersLayer`
|
|
196
|
+
|
|
197
|
+
Creates an Effect Layer providing a `DatabaseContext` service.
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
import { Effect } from "effect"
|
|
201
|
+
import { makeRpcHandlersLayer, makeDatabaseContextTag } from "@proseql/rpc"
|
|
202
|
+
|
|
203
|
+
const layer = makeRpcHandlersLayer(config, { books: initialBooks })
|
|
204
|
+
|
|
205
|
+
const DatabaseContextTag = makeDatabaseContextTag<typeof config>()
|
|
206
|
+
|
|
207
|
+
const program = Effect.gen(function* () {
|
|
208
|
+
const ctx = yield* DatabaseContextTag
|
|
209
|
+
const book = yield* ctx.db.books.findById("1")
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
await Effect.runPromise(program.pipe(Effect.provide(layer)))
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Error Schemas
|
|
216
|
+
|
|
217
|
+
All ProseQL errors have RPC-safe schemas for transport. Errors maintain their `_tag` through the RPC layer, enabling `Effect.catchTag` on the client side.
|
|
218
|
+
|
|
219
|
+
### CRUD Errors
|
|
220
|
+
|
|
221
|
+
| Error | When |
|
|
222
|
+
|-------|------|
|
|
223
|
+
| `NotFoundError` | Entity with ID doesn't exist |
|
|
224
|
+
| `ValidationError` | Schema validation failed |
|
|
225
|
+
| `DuplicateKeyError` | Entity with same ID already exists |
|
|
226
|
+
| `UniqueConstraintError` | Unique field constraint violated |
|
|
227
|
+
| `ForeignKeyError` | Referenced entity doesn't exist |
|
|
228
|
+
| `HookError` | Lifecycle hook rejected the operation |
|
|
229
|
+
| `OperationError` | Operation not allowed (e.g., update on append-only) |
|
|
230
|
+
| `ConcurrencyError` | Concurrent modification conflict |
|
|
231
|
+
| `TransactionError` | Transaction operation failed |
|
|
232
|
+
|
|
233
|
+
### Query Errors
|
|
234
|
+
|
|
235
|
+
| Error | When |
|
|
236
|
+
|-------|------|
|
|
237
|
+
| `DanglingReferenceError` | Referenced entity no longer exists |
|
|
238
|
+
| `CollectionNotFoundError` | Collection doesn't exist in config |
|
|
239
|
+
| `PopulationError` | Relationship population failed |
|
|
240
|
+
|
|
241
|
+
### Error Handling
|
|
242
|
+
|
|
243
|
+
Errors flow through the RPC layer with their tags preserved:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
import { Effect } from "effect"
|
|
247
|
+
|
|
248
|
+
const result = await Effect.runPromise(
|
|
249
|
+
handlers.books.findById({ id: "nonexistent" }).pipe(
|
|
250
|
+
Effect.catchTag("NotFoundError", (error) =>
|
|
251
|
+
Effect.succeed({
|
|
252
|
+
status: "not_found",
|
|
253
|
+
collection: error.collection,
|
|
254
|
+
id: error.id,
|
|
255
|
+
}),
|
|
256
|
+
),
|
|
257
|
+
Effect.catchTag("ValidationError", (error) =>
|
|
258
|
+
Effect.succeed({
|
|
259
|
+
status: "validation_failed",
|
|
260
|
+
issues: error.issues,
|
|
261
|
+
}),
|
|
262
|
+
),
|
|
263
|
+
),
|
|
264
|
+
)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Or use `Effect.catchTags` for multiple error types:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
const result = await Effect.runPromise(
|
|
271
|
+
handlers.books.findById({ id: "nonexistent" }).pipe(
|
|
272
|
+
Effect.catchTags({
|
|
273
|
+
NotFoundError: (e) => Effect.succeed({ status: "not_found", id: e.id }),
|
|
274
|
+
ValidationError: (e) => Effect.succeed({ status: "invalid", issues: e.issues }),
|
|
275
|
+
}),
|
|
276
|
+
),
|
|
277
|
+
)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Payload Schemas
|
|
281
|
+
|
|
282
|
+
Request payloads are defined using Effect Schema for type-safe serialization.
|
|
283
|
+
|
|
284
|
+
### Query Payload
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
import { QueryPayloadSchema } from "@proseql/rpc"
|
|
288
|
+
|
|
289
|
+
// Supports:
|
|
290
|
+
// - where: filter conditions
|
|
291
|
+
// - sort: field ordering
|
|
292
|
+
// - select: field selection
|
|
293
|
+
// - populate: relationship population
|
|
294
|
+
// - limit/offset: pagination
|
|
295
|
+
// - cursor: cursor-based pagination
|
|
296
|
+
// - streamingOptions: for queryStream
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### CRUD Payloads
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
import {
|
|
303
|
+
FindByIdPayloadSchema,
|
|
304
|
+
CreatePayloadSchema,
|
|
305
|
+
UpdatePayloadSchema,
|
|
306
|
+
DeletePayloadSchema,
|
|
307
|
+
AggregatePayloadSchema,
|
|
308
|
+
} from "@proseql/rpc"
|
|
309
|
+
|
|
310
|
+
// FindById: { id: string }
|
|
311
|
+
// Create: { data: Record<string, unknown> }
|
|
312
|
+
// Update: { id: string, updates: Record<string, unknown> }
|
|
313
|
+
// Delete: { id: string }
|
|
314
|
+
// Aggregate: { where?, groupBy?, count?, sum?, avg?, min?, max? }
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Batch Payloads
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
import {
|
|
321
|
+
CreateManyPayloadSchema,
|
|
322
|
+
UpdateManyPayloadSchema,
|
|
323
|
+
DeleteManyPayloadSchema,
|
|
324
|
+
UpsertPayloadSchema,
|
|
325
|
+
UpsertManyPayloadSchema,
|
|
326
|
+
} from "@proseql/rpc"
|
|
327
|
+
|
|
328
|
+
// CreateMany: { data: Array<Record>, options?: { skipDuplicates? } }
|
|
329
|
+
// UpdateMany: { where: Record, updates: Record }
|
|
330
|
+
// DeleteMany: { where: Record, options?: { limit? } }
|
|
331
|
+
// Upsert: { where: Record, create: Record, update: Record }
|
|
332
|
+
// UpsertMany: { data: Array<{ where, create, update }> }
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Streaming Queries
|
|
336
|
+
|
|
337
|
+
Use `QueryStreamRequest` for incremental result delivery over RPC transport.
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
import { Stream, Chunk } from "effect"
|
|
341
|
+
|
|
342
|
+
const rpcs = makeRpcGroup(config)
|
|
343
|
+
const handlers = await Effect.runPromise(makeRpcHandlers(config, initialData))
|
|
344
|
+
|
|
345
|
+
// queryStream returns a Stream instead of collecting to array
|
|
346
|
+
const stream = handlers.books.queryStream({
|
|
347
|
+
where: { genre: "sci-fi" },
|
|
348
|
+
streamingOptions: { chunkSize: 100 }, // batch items before sending
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
// Collect results
|
|
352
|
+
const results = await Effect.runPromise(
|
|
353
|
+
Stream.runCollect(stream).pipe(Effect.map(Chunk.toReadonlyArray)),
|
|
354
|
+
)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Streaming Options
|
|
358
|
+
|
|
359
|
+
| Option | Description |
|
|
360
|
+
|--------|-------------|
|
|
361
|
+
| `chunkSize` | Number of items to batch before sending (default: 1) |
|
|
362
|
+
| `bufferSize` | Client-side buffer size for backpressure (default: 16) |
|
|
363
|
+
|
|
364
|
+
## Result Schemas
|
|
365
|
+
|
|
366
|
+
Response types for batch and aggregate operations.
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
import {
|
|
370
|
+
AggregateResultSchema,
|
|
371
|
+
GroupedAggregateResultSchema,
|
|
372
|
+
CreateManyResultSchema,
|
|
373
|
+
UpdateManyResultSchema,
|
|
374
|
+
DeleteManyResultSchema,
|
|
375
|
+
UpsertResultSchema,
|
|
376
|
+
UpsertManyResultSchema,
|
|
377
|
+
CursorPageResultSchema,
|
|
378
|
+
} from "@proseql/rpc"
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Aggregate Results
|
|
382
|
+
|
|
383
|
+
```ts
|
|
384
|
+
// Scalar aggregation
|
|
385
|
+
type AggregateResult = {
|
|
386
|
+
count?: number
|
|
387
|
+
sum?: Record<string, number>
|
|
388
|
+
avg?: Record<string, number | null>
|
|
389
|
+
min?: Record<string, unknown>
|
|
390
|
+
max?: Record<string, unknown>
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Grouped aggregation
|
|
394
|
+
type GroupedAggregateResult = Array<{
|
|
395
|
+
group: Record<string, unknown>
|
|
396
|
+
count?: number
|
|
397
|
+
sum?: Record<string, number>
|
|
398
|
+
avg?: Record<string, number | null>
|
|
399
|
+
min?: Record<string, unknown>
|
|
400
|
+
max?: Record<string, unknown>
|
|
401
|
+
}>
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Batch Results
|
|
405
|
+
|
|
406
|
+
```ts
|
|
407
|
+
// CreateMany
|
|
408
|
+
type CreateManyResult = {
|
|
409
|
+
created: Array<Entity>
|
|
410
|
+
skipped?: Array<{ data: unknown; reason: string }>
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// UpdateMany
|
|
414
|
+
type UpdateManyResult = {
|
|
415
|
+
count: number
|
|
416
|
+
updated: Array<Entity>
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// DeleteMany
|
|
420
|
+
type DeleteManyResult = {
|
|
421
|
+
count: number
|
|
422
|
+
deleted: Array<Entity>
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Upsert
|
|
426
|
+
type UpsertResult = Entity & { __action: "created" | "updated" }
|
|
427
|
+
|
|
428
|
+
// UpsertMany
|
|
429
|
+
type UpsertManyResult = {
|
|
430
|
+
created: Array<Entity>
|
|
431
|
+
updated: Array<Entity>
|
|
432
|
+
unchanged: Array<Entity>
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
## Building an RPC Router
|
|
437
|
+
|
|
438
|
+
Use `RpcRouter` from `@effect/rpc` to compose handlers into a router:
|
|
439
|
+
|
|
440
|
+
```ts
|
|
441
|
+
import { Rpc, RpcRouter } from "@effect/rpc"
|
|
442
|
+
import { makeRpcGroup, makeRpcHandlers } from "@proseql/rpc"
|
|
443
|
+
|
|
444
|
+
const rpcs = makeRpcGroup(config)
|
|
445
|
+
|
|
446
|
+
const program = Effect.gen(function* () {
|
|
447
|
+
const handlers = yield* makeRpcHandlers(config, initialData)
|
|
448
|
+
|
|
449
|
+
// Create RPC handlers using Rpc.effect
|
|
450
|
+
const findBookById = Rpc.effect(rpcs.books.FindByIdRequest, (req) =>
|
|
451
|
+
handlers.books.findById({ id: req.id }),
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
const queryBooks = Rpc.effect(rpcs.books.QueryRequest, (req) =>
|
|
455
|
+
handlers.books.query({
|
|
456
|
+
where: req.where,
|
|
457
|
+
sort: req.sort,
|
|
458
|
+
limit: req.limit,
|
|
459
|
+
offset: req.offset,
|
|
460
|
+
}),
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
const createBook = Rpc.effect(rpcs.books.CreateRequest, (req) =>
|
|
464
|
+
handlers.books.create({ data: req.data }),
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
// Build router
|
|
468
|
+
const router = RpcRouter.make(findBookById, queryBooks, createBook)
|
|
469
|
+
})
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
## API Reference
|
|
473
|
+
|
|
474
|
+
### Exports
|
|
475
|
+
|
|
476
|
+
| Export | Description |
|
|
477
|
+
|--------|-------------|
|
|
478
|
+
| `makeRpcGroup` | Derive RPC request schemas from database config |
|
|
479
|
+
| `makeRpcHandlers` | Create handlers from config + initial data |
|
|
480
|
+
| `makeRpcHandlersFromDatabase` | Create handlers from existing database |
|
|
481
|
+
| `makeRpcHandlersLayer` | Create Layer providing DatabaseContext |
|
|
482
|
+
| `makeRpcHandlersLayerFromDatabase` | Create Layer from existing database |
|
|
483
|
+
| `makeDatabaseContextTag` | Create Context.Tag for database service |
|
|
484
|
+
| `RpcRouter` | Re-exported from @effect/rpc |
|
|
485
|
+
|
|
486
|
+
### Request Factories
|
|
487
|
+
|
|
488
|
+
| Factory | Description |
|
|
489
|
+
|---------|-------------|
|
|
490
|
+
| `makeFindByIdRequest` | Create FindById request class |
|
|
491
|
+
| `makeQueryRequest` | Create Query request class |
|
|
492
|
+
| `makeQueryStreamRequest` | Create streaming Query request class |
|
|
493
|
+
| `makeCreateRequest` | Create Create request class |
|
|
494
|
+
| `makeUpdateRequest` | Create Update request class |
|
|
495
|
+
| `makeDeleteRequest` | Create Delete request class |
|
|
496
|
+
| `makeAggregateRequest` | Create Aggregate request class |
|
|
497
|
+
| `makeCreateManyRequest` | Create CreateMany request class |
|
|
498
|
+
| `makeUpdateManyRequest` | Create UpdateMany request class |
|
|
499
|
+
| `makeDeleteManyRequest` | Create DeleteMany request class |
|
|
500
|
+
| `makeUpsertRequest` | Create Upsert request class |
|
|
501
|
+
| `makeUpsertManyRequest` | Create UpsertMany request class |
|
|
502
|
+
| `makeCollectionRpcs` | Create all request classes for a collection |
|
|
503
|
+
|
|
504
|
+
### Error Schemas
|
|
505
|
+
|
|
506
|
+
| Schema | Description |
|
|
507
|
+
|--------|-------------|
|
|
508
|
+
| `NotFoundErrorSchema` | Entity not found |
|
|
509
|
+
| `ValidationErrorSchema` | Schema validation failed |
|
|
510
|
+
| `DuplicateKeyErrorSchema` | Duplicate ID |
|
|
511
|
+
| `UniqueConstraintErrorSchema` | Unique constraint violated |
|
|
512
|
+
| `ForeignKeyErrorSchema` | Foreign key constraint violated |
|
|
513
|
+
| `HookErrorSchema` | Lifecycle hook rejected |
|
|
514
|
+
| `OperationErrorSchema` | Operation not allowed |
|
|
515
|
+
| `ConcurrencyErrorSchema` | Concurrent modification |
|
|
516
|
+
| `TransactionErrorSchema` | Transaction failed |
|
|
517
|
+
| `DanglingReferenceErrorSchema` | Dangling reference |
|
|
518
|
+
| `CollectionNotFoundErrorSchema` | Collection not found |
|
|
519
|
+
| `PopulationErrorSchema` | Population failed |
|
|
520
|
+
| `CrudErrorSchema` | Union of CRUD errors |
|
|
521
|
+
| `QueryErrorSchema` | Union of query errors |
|
|
522
|
+
| `RpcErrorSchema` | Union of all RPC errors |
|
|
523
|
+
|
|
524
|
+
### Payload Schemas
|
|
525
|
+
|
|
526
|
+
| Schema | Description |
|
|
527
|
+
|--------|-------------|
|
|
528
|
+
| `FindByIdPayloadSchema` | FindById payload |
|
|
529
|
+
| `QueryPayloadSchema` | Query payload |
|
|
530
|
+
| `CreatePayloadSchema` | Create payload |
|
|
531
|
+
| `UpdatePayloadSchema` | Update payload |
|
|
532
|
+
| `DeletePayloadSchema` | Delete payload |
|
|
533
|
+
| `AggregatePayloadSchema` | Aggregate payload |
|
|
534
|
+
| `CreateManyPayloadSchema` | CreateMany payload |
|
|
535
|
+
| `UpdateManyPayloadSchema` | UpdateMany payload |
|
|
536
|
+
| `DeleteManyPayloadSchema` | DeleteMany payload |
|
|
537
|
+
| `UpsertPayloadSchema` | Upsert payload |
|
|
538
|
+
| `UpsertManyPayloadSchema` | UpsertMany payload |
|
|
539
|
+
| `StreamingOptionsSchema` | Streaming options |
|
|
540
|
+
|
|
541
|
+
### Result Schemas
|
|
542
|
+
|
|
543
|
+
| Schema | Description |
|
|
544
|
+
|--------|-------------|
|
|
545
|
+
| `AggregateResultSchema` | Scalar aggregate result |
|
|
546
|
+
| `GroupedAggregateResultSchema` | Grouped aggregate result |
|
|
547
|
+
| `CreateManyResultSchema` | CreateMany result |
|
|
548
|
+
| `UpdateManyResultSchema` | UpdateMany result |
|
|
549
|
+
| `DeleteManyResultSchema` | DeleteMany result |
|
|
550
|
+
| `UpsertResultSchema` | Upsert result |
|
|
551
|
+
| `UpsertManyResultSchema` | UpsertMany result |
|
|
552
|
+
| `CursorPageResultSchema` | Cursor pagination result |
|
|
553
|
+
| `CursorPageInfoSchema` | Cursor page info |
|
|
554
|
+
|
|
555
|
+
## License
|
|
556
|
+
|
|
557
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proseql/rpc",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Effect RPC integration for ProseQL type-safe in-memory database",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"sideEffects": false,
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@proseql/core": "^0.2.
|
|
44
|
+
"@proseql/core": "^0.2.4"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"effect": "^3.15.0",
|