@absolutejs/sync 0.8.0 → 0.10.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 +18 -4
- package/dist/crdt/index.d.ts +105 -0
- package/dist/crdt/index.js +256 -0
- package/dist/crdt/index.js.map +10 -0
- package/dist/engine/index.d.ts +3 -1
- package/dist/engine/index.js +68 -8
- package/dist/engine/index.js.map +5 -4
- package/dist/engine/schema.d.ts +39 -0
- package/dist/engine/syncEngine.d.ts +28 -0
- package/package.json +6 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarative, dependency-free row schemas keyed by table. The engine validates
|
|
3
|
+
* a mutation's writes against the schema before they're persisted (a bad write
|
|
4
|
+
* is rejected, like a permission deny), and lazily **migrates** rows on read —
|
|
5
|
+
* so changing a shape needs no up-front database migration. Field validators are
|
|
6
|
+
* plain `(value) => boolean` functions; the `field` kit covers the common cases.
|
|
7
|
+
*/
|
|
8
|
+
/** Validates one field's value. Optionality is encoded by the validator (see `field.optional`). */
|
|
9
|
+
export type FieldValidator = (value: unknown) => boolean;
|
|
10
|
+
export type TableSchema<Row = unknown> = {
|
|
11
|
+
/** Per-field validators. On insert every field is checked; on update, only
|
|
12
|
+
* the fields present in the payload. Extra fields not listed here are allowed. */
|
|
13
|
+
fields: Record<string, FieldValidator>;
|
|
14
|
+
/** Schema version, for documentation/migration bookkeeping. Default 1. */
|
|
15
|
+
version?: number;
|
|
16
|
+
/** Upcast a stored/raw row to the current shape — applied lazily on reads. */
|
|
17
|
+
migrate?: (row: Row) => Row;
|
|
18
|
+
};
|
|
19
|
+
/** A `table` → {@link TableSchema} map. */
|
|
20
|
+
export type SchemaDefinition = Record<string, TableSchema<any>>;
|
|
21
|
+
/**
|
|
22
|
+
* Define table schemas. Identity at runtime (for type inference). Pass to
|
|
23
|
+
* `createSyncEngine({ schemas })` or register with `engine.registerSchema`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const defineSchema: <S extends SchemaDefinition>(schemas: S) => S;
|
|
26
|
+
/** A small validator kit. Compose with `field.optional` / `field.array` / `field.enum`. */
|
|
27
|
+
export declare const field: {
|
|
28
|
+
string: FieldValidator;
|
|
29
|
+
number: FieldValidator;
|
|
30
|
+
boolean: FieldValidator;
|
|
31
|
+
/** Any defined value. */
|
|
32
|
+
any: FieldValidator;
|
|
33
|
+
/** Allow `undefined` (the field may be omitted), else delegate to `inner`. */
|
|
34
|
+
optional: (inner: FieldValidator) => FieldValidator;
|
|
35
|
+
/** An array whose every element satisfies `inner`. */
|
|
36
|
+
array: (inner: FieldValidator) => FieldValidator;
|
|
37
|
+
/** One of the given literal values. */
|
|
38
|
+
enum: (...values: unknown[]) => FieldValidator;
|
|
39
|
+
};
|
|
@@ -6,6 +6,7 @@ import type { PermissionsDefinition, TablePermissions } from './permissions';
|
|
|
6
6
|
import type { SearchCollectionDefinition } from './search';
|
|
7
7
|
import type { ScheduleDefinition } from './schedule';
|
|
8
8
|
import type { EngineActivity, EngineInspection } from './devtools';
|
|
9
|
+
import type { SchemaDefinition, TableSchema } from './schema';
|
|
9
10
|
import type { ClusterBus } from './cluster';
|
|
10
11
|
import type { ChangeSource, RowChange, ViewDiff } from './types';
|
|
11
12
|
/**
|
|
@@ -15,6 +16,13 @@ import type { ChangeSource, RowChange, ViewDiff } from './types';
|
|
|
15
16
|
export declare class UnauthorizedError extends Error {
|
|
16
17
|
constructor(subject: string);
|
|
17
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Thrown when a mutation's write fails its table's schema (see
|
|
21
|
+
* {@link defineSchema}). The message names the offending field.
|
|
22
|
+
*/
|
|
23
|
+
export declare class SchemaError extends Error {
|
|
24
|
+
constructor(table: string, fieldName: string);
|
|
25
|
+
}
|
|
18
26
|
export type SubscribeArgs<T, P, Ctx> = {
|
|
19
27
|
/** Registered collection name. */
|
|
20
28
|
collection: string;
|
|
@@ -127,6 +135,20 @@ export type SyncEngine = {
|
|
|
127
135
|
* `permissions` entry on {@link createSyncEngine}.
|
|
128
136
|
*/
|
|
129
137
|
registerPermissions: <Row = unknown, Ctx = CollectionContext>(table: string, rules: TablePermissions<Row, Ctx>) => void;
|
|
138
|
+
/**
|
|
139
|
+
* Register a `table`'s schema (see {@link defineSchema}): writes are validated
|
|
140
|
+
* against it (a bad write rejects the mutation with {@link SchemaError}), and
|
|
141
|
+
* its `migrate` lazily upcasts rows on read. Equivalent to a `schemas` entry
|
|
142
|
+
* on {@link createSyncEngine}.
|
|
143
|
+
*/
|
|
144
|
+
registerSchema: <Row = unknown>(table: string, schema: TableSchema<Row>) => void;
|
|
145
|
+
/**
|
|
146
|
+
* Apply a table's schema `migrate` to a raw/stored row (identity when there's
|
|
147
|
+
* no schema or migration). Use it wherever you read raw rows the engine
|
|
148
|
+
* doesn't (e.g. a search collection's `source`); the engine already migrates
|
|
149
|
+
* reactive `ctx.db` reads, view hydrates, and the one-shot hydrate.
|
|
150
|
+
*/
|
|
151
|
+
migrate: <Row = unknown>(table: string, row: Row) => Row;
|
|
130
152
|
/**
|
|
131
153
|
* Run a registered mutation: authorize, invoke its handler (which writes and
|
|
132
154
|
* emits changes via `applyChange`), and resolve with the handler's result.
|
|
@@ -169,6 +191,12 @@ export type SyncEngineOptions = {
|
|
|
169
191
|
* (it threads `ctx` untyped to your rules).
|
|
170
192
|
*/
|
|
171
193
|
permissions?: PermissionsDefinition<any>;
|
|
194
|
+
/**
|
|
195
|
+
* Declarative row schemas keyed by table (see {@link defineSchema}): writes
|
|
196
|
+
* are validated against them, and `migrate` lazily upcasts rows on read. Add
|
|
197
|
+
* more later with {@link SyncEngine.registerSchema}.
|
|
198
|
+
*/
|
|
199
|
+
schemas?: SchemaDefinition;
|
|
172
200
|
};
|
|
173
201
|
/**
|
|
174
202
|
* The Tier 3 sync engine: a registry of collections plus the view syncer. It is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absolutejs/sync",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Lightweight reactive-push and write-behind-cache primitives for Elysia and the AbsoluteJS ecosystem — kill polling and keep a remote store off your hot path, without adopting a whole sync-engine backend.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
"import": "./dist/client/index.js",
|
|
29
29
|
"default": "./dist/client/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./crdt": {
|
|
32
|
+
"types": "./dist/crdt/index.d.ts",
|
|
33
|
+
"import": "./dist/crdt/index.js",
|
|
34
|
+
"default": "./dist/crdt/index.js"
|
|
35
|
+
},
|
|
31
36
|
"./drizzle": {
|
|
32
37
|
"types": "./dist/adapters/drizzle/index.d.ts",
|
|
33
38
|
"import": "./dist/adapters/drizzle/index.js",
|