@evolu/common 6.0.1-preview.3 → 6.0.1-preview.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/dist/src/Evolu/Db.d.ts +17 -9
- package/dist/src/Evolu/Db.d.ts.map +1 -1
- package/dist/src/Evolu/Db.js +12 -3
- package/dist/src/Evolu/Evolu.d.ts +2 -2
- package/dist/src/Evolu/Evolu.d.ts.map +1 -1
- package/dist/src/Evolu/Evolu.js +19 -24
- package/dist/src/Evolu/Protocol.d.ts +12 -12
- package/dist/src/Evolu/Protocol.d.ts.map +1 -1
- package/dist/src/Evolu/Protocol.js +16 -6
- package/dist/src/Evolu/Schema.d.ts +23 -39
- package/dist/src/Evolu/Schema.d.ts.map +1 -1
- package/dist/src/Evolu/Schema.js +13 -72
- package/package.json +1 -1
- package/src/Evolu/Db.ts +14 -11
- package/src/Evolu/Evolu.ts +34 -31
- package/src/Evolu/Protocol.ts +16 -13
- package/src/Evolu/Schema.ts +101 -129
package/dist/src/Evolu/Db.d.ts
CHANGED
|
@@ -14,24 +14,32 @@ import { Worker } from "../Worker.js";
|
|
|
14
14
|
import { Config } from "./Config.js";
|
|
15
15
|
import { QueryPatches } from "./Diff.js";
|
|
16
16
|
import { AppOwner, OwnerRow } from "./Owner.js";
|
|
17
|
-
import {
|
|
17
|
+
import { BinaryOwnerId, CrdtMessage, DbChange, ProtocolError, Storage } from "./Protocol.js";
|
|
18
18
|
import { Query } from "./Query.js";
|
|
19
19
|
import { SqliteStorageBase } from "./Storage.js";
|
|
20
20
|
import { CreateSyncDep } from "./Sync.js";
|
|
21
21
|
import { Timestamp, TimestampError } from "./Timestamp.js";
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
export
|
|
27
|
-
readonly name: Base64Url256;
|
|
28
|
-
readonly columns: ReadonlyArray<Base64Url256>;
|
|
29
|
-
}
|
|
22
|
+
export declare const DbTable: import("../Type.js").ObjectType<{
|
|
23
|
+
name: import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>;
|
|
24
|
+
columns: import("../Type.js").ArrayType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>>;
|
|
25
|
+
}>;
|
|
26
|
+
export type DbTable = typeof DbTable.Type;
|
|
30
27
|
export declare const DbIndex: import("../Type.js").ObjectType<{
|
|
31
28
|
name: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
32
29
|
sql: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
33
30
|
}>;
|
|
34
31
|
export type DbIndex = typeof DbIndex.Type;
|
|
32
|
+
export declare const DbSchema: import("../Type.js").ObjectType<{
|
|
33
|
+
tables: import("../Type.js").ArrayType<import("../Type.js").ObjectType<{
|
|
34
|
+
name: import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>;
|
|
35
|
+
columns: import("../Type.js").ArrayType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & import("../Types.js").Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>>;
|
|
36
|
+
}>>;
|
|
37
|
+
indexes: import("../Type.js").ArrayType<import("../Type.js").ObjectType<{
|
|
38
|
+
name: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
39
|
+
sql: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
40
|
+
}>>;
|
|
41
|
+
}>;
|
|
42
|
+
export type DbSchema = typeof DbSchema.Type;
|
|
35
43
|
export type DbWorker = Worker<DbWorkerInput, DbWorkerOutput>;
|
|
36
44
|
export type CreateDbWorker = (name: SimpleName) => DbWorker;
|
|
37
45
|
export interface CreateDbWorkerDep {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Db.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EAEpB,2BAA2B,EAE5B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAa,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAW,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAEL,qBAAqB,EAErB,OAAO,EAEP,SAAS,EACT,WAAW,EAEX,SAAS,EAEV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,
|
|
1
|
+
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Db.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Evolu/Db.js
CHANGED
|
@@ -7,15 +7,23 @@ import { objectToEntries } from "../Object.js";
|
|
|
7
7
|
import { createRef } from "../Ref.js";
|
|
8
8
|
import { err, ok } from "../Result.js";
|
|
9
9
|
import { createSqlite, explainSqliteQueryPlan, sql, } from "../Sqlite.js";
|
|
10
|
-
import { object, String } from "../Type.js";
|
|
10
|
+
import { array, object, String } from "../Type.js";
|
|
11
11
|
import { createInitializedWorker, } from "../Worker.js";
|
|
12
12
|
import { makePatches } from "./Diff.js";
|
|
13
13
|
import { createAppOwner, createOwnerRow, } from "./Owner.js";
|
|
14
|
-
import { applyProtocolMessageAsClient, binaryIdToId, createProtocolMessageForSync, createProtocolMessageFromCrdtMessages, decryptAndDecodeDbChange, encodeAndEncryptDbChange, idToBinaryId, ownerIdToBinaryOwnerId, protocolVersion, } from "./Protocol.js";
|
|
14
|
+
import { applyProtocolMessageAsClient, Base64Url256, binaryIdToId, createProtocolMessageForSync, createProtocolMessageFromCrdtMessages, decryptAndDecodeDbChange, encodeAndEncryptDbChange, idToBinaryId, ownerIdToBinaryOwnerId, protocolVersion, } from "./Protocol.js";
|
|
15
15
|
import { createQueryRowsCache, deserializeQuery, emptyRows, } from "./Query.js";
|
|
16
16
|
import { createSqliteStorageBase, } from "./Storage.js";
|
|
17
17
|
import { Millis, receiveTimestamp, sendTimestamp, timestampStringToTimestamp, timestampToBinaryTimestamp, timestampToTimestampString, } from "./Timestamp.js";
|
|
18
|
+
export const DbTable = object({
|
|
19
|
+
name: Base64Url256,
|
|
20
|
+
columns: array(Base64Url256),
|
|
21
|
+
});
|
|
18
22
|
export const DbIndex = object({ name: String, sql: String });
|
|
23
|
+
export const DbSchema = object({
|
|
24
|
+
tables: array(DbTable),
|
|
25
|
+
indexes: array(DbIndex),
|
|
26
|
+
});
|
|
19
27
|
export const createDbWorkerForPlatform = (platformDeps) => {
|
|
20
28
|
const tabQueryRowsCacheMap = new Map();
|
|
21
29
|
const getQueryRowsCache = (tabId) => {
|
|
@@ -448,6 +456,8 @@ const initializeDb = (deps) => (mnemonic) => {
|
|
|
448
456
|
)
|
|
449
457
|
strict;
|
|
450
458
|
`,
|
|
459
|
+
// Index for reading database changes by owner and timestamp.
|
|
460
|
+
// Timestamp always corresponds to a DbChange.
|
|
451
461
|
sql `
|
|
452
462
|
create index evolu_history_ownerId_timestamp on evolu_history (
|
|
453
463
|
"ownerId",
|
|
@@ -712,7 +722,6 @@ const createClientStorage = (deps) => (options) => {
|
|
|
712
722
|
validateWriteKey: constFalse,
|
|
713
723
|
writeMessages: (_ownerId, messages) => {
|
|
714
724
|
// TODO: Get owner by _ownerId when we support more.
|
|
715
|
-
// Use ownerId!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
716
725
|
const owner = deps.ownerRowRef.get();
|
|
717
726
|
const decodedAndDecryptedMessages = [];
|
|
718
727
|
for (const message of messages) {
|
|
@@ -12,7 +12,7 @@ import { AppOwner } from "./Owner.js";
|
|
|
12
12
|
import { CreateAppStateDep, FlushSyncDep } from "./Platform.js";
|
|
13
13
|
import { ProtocolError, ProtocolUnsupportedVersionError } from "./Protocol.js";
|
|
14
14
|
import { Queries, QueriesToQueryRowsPromises, Query, QueryRows, Row } from "./Query.js";
|
|
15
|
-
import { CreateQuery, EvoluSchema, Mutation } from "./Schema.js";
|
|
15
|
+
import { CreateQuery, EvoluSchema, Mutation, ValidateSchema } from "./Schema.js";
|
|
16
16
|
import { SyncState } from "./Sync.js";
|
|
17
17
|
import { TimestampError } from "./Timestamp.js";
|
|
18
18
|
export interface Evolu<S extends EvoluSchema = EvoluSchema> {
|
|
@@ -329,6 +329,6 @@ export interface EvoluForInitialData<S extends EvoluSchema = EvoluSchema> {
|
|
|
329
329
|
* const evolu = createEvolu(evoluReactDeps)(Schema);
|
|
330
330
|
* ```
|
|
331
331
|
*/
|
|
332
|
-
export declare const createEvolu: (deps: EvoluDeps) => <S extends EvoluSchema>(schema: S
|
|
332
|
+
export declare const createEvolu: (deps: EvoluDeps) => <S extends EvoluSchema>(schema: ValidateSchema<S> extends never ? S : ValidateSchema<S>, partialConfig?: Partial<EvoluConfigWithInitialData<S>>) => Evolu<S>;
|
|
333
333
|
export declare const createNamespaceName: (config: Config) => (name: string) => string;
|
|
334
334
|
//# sourceMappingURL=Evolu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Evolu.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAA0B,WAAW,EAAe,MAAM,cAAc,CAAC;AAChF,OAAO,EAAe,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAML,QAAQ,EAET,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAEL,aAAa,EACb,+BAA+B,EAChC,MAAM,eAAe,CAAC;AACvB,OAAO,EAGL,OAAO,EACP,0BAA0B,EAC1B,KAAK,EACL,SAAS,EAET,GAAG,EAGJ,MAAM,YAAY,CAAC;AACpB,OAAO,
|
|
1
|
+
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Evolu.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Evolu/Evolu.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNonEmptyArray, isNonEmptyReadonlyArray } from "../Array.js";
|
|
2
|
-
import { assertNonEmptyArray } from "../Assert.js";
|
|
2
|
+
import { assert, assertNonEmptyArray } from "../Assert.js";
|
|
3
3
|
import { createCallbacks } from "../Callbacks.js";
|
|
4
4
|
import { exhaustiveCheck } from "../Function.js";
|
|
5
5
|
import { err, ok } from "../Result.js";
|
|
@@ -9,8 +9,9 @@ import { createId, } from "../Type.js";
|
|
|
9
9
|
import { defaultConfig } from "./Config.js";
|
|
10
10
|
import { applyPatches } from "./Diff.js";
|
|
11
11
|
import { kysely } from "./Kysely.js";
|
|
12
|
+
import { DbChange, } from "./Protocol.js";
|
|
12
13
|
import { createSubscribedQueries, emptyRows, serializeQuery, } from "./Query.js";
|
|
13
|
-
import {
|
|
14
|
+
import { evoluSchemaToDbSchema, insertable, updateable, upsertable, } from "./Schema.js";
|
|
14
15
|
import { initialSyncState } from "./Sync.js";
|
|
15
16
|
// For hot reloading and Evolu multitenancy.
|
|
16
17
|
const evoluInstances = new Map();
|
|
@@ -62,10 +63,7 @@ let tabId = null;
|
|
|
62
63
|
* const evolu = createEvolu(evoluReactDeps)(Schema);
|
|
63
64
|
* ```
|
|
64
65
|
*/
|
|
65
|
-
export const createEvolu = (deps) => (
|
|
66
|
-
// TODO: Validate missing Id, unsupported types, used default types via TS types
|
|
67
|
-
// with type errors messages as we had it in the old Evolu.
|
|
68
|
-
schema, partialConfig = {}) => {
|
|
66
|
+
export const createEvolu = (deps) => (schema, partialConfig = {}) => {
|
|
69
67
|
const config = { ...defaultConfig, ...partialConfig };
|
|
70
68
|
let evolu = evoluInstances.get(config.name);
|
|
71
69
|
if (evolu == null) {
|
|
@@ -159,7 +157,7 @@ const createEvoluInstance = (deps) => (schema, evoluConfig) => {
|
|
|
159
157
|
exhaustiveCheck(message);
|
|
160
158
|
}
|
|
161
159
|
});
|
|
162
|
-
const dbSchema =
|
|
160
|
+
const dbSchema = evoluSchemaToDbSchema(schema, indexes);
|
|
163
161
|
const mutationTypesCache = new Map();
|
|
164
162
|
// Lazy create mutation Types like this: `insertable(Schema.todo)`
|
|
165
163
|
const getMutationType = (table, kind) => {
|
|
@@ -185,18 +183,15 @@ const createEvoluInstance = (deps) => (schema, evoluConfig) => {
|
|
|
185
183
|
if (initialData)
|
|
186
184
|
initialData({
|
|
187
185
|
insert: (table, props) => {
|
|
188
|
-
const Type = getMutationType(table, "insert");
|
|
189
186
|
const id = createId(deps);
|
|
190
|
-
const
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
values: result.value,
|
|
196
|
-
});
|
|
187
|
+
const values = getMutationType(table, "insert").fromUnknown(props);
|
|
188
|
+
if (values.ok) {
|
|
189
|
+
const dbChange = { table, id, values: values.value };
|
|
190
|
+
assertValidDbChange(dbChange);
|
|
191
|
+
initialDataDbChanges.push(dbChange);
|
|
197
192
|
return ok({ id });
|
|
198
193
|
}
|
|
199
|
-
return
|
|
194
|
+
return values;
|
|
200
195
|
},
|
|
201
196
|
});
|
|
202
197
|
dbWorker.postMessage({
|
|
@@ -222,9 +217,9 @@ const createEvoluInstance = (deps) => (schema, evoluConfig) => {
|
|
|
222
217
|
else {
|
|
223
218
|
// Remove `id` from values.
|
|
224
219
|
const { id: _id, ...values } = result.value;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
mutateMicrotaskQueue.push([
|
|
220
|
+
const dbChange = { table, id, values };
|
|
221
|
+
assertValidDbChange(dbChange);
|
|
222
|
+
mutateMicrotaskQueue.push([dbChange, options?.onComplete]);
|
|
228
223
|
}
|
|
229
224
|
if (mutateMicrotaskQueue.length === 1)
|
|
230
225
|
queueMicrotask(() => {
|
|
@@ -350,11 +345,8 @@ const createEvoluInstance = (deps) => (schema, evoluConfig) => {
|
|
|
350
345
|
},
|
|
351
346
|
ensureSchema: (schema) => {
|
|
352
347
|
mutationTypesCache.clear();
|
|
353
|
-
const
|
|
354
|
-
dbWorker.postMessage({
|
|
355
|
-
type: "ensureDbSchema",
|
|
356
|
-
dbSchema: validEvoluSchemaToDbSchema(validSchema),
|
|
357
|
-
});
|
|
348
|
+
const dbSchema = evoluSchemaToDbSchema(schema);
|
|
349
|
+
dbWorker.postMessage({ type: "ensureDbSchema", dbSchema });
|
|
358
350
|
},
|
|
359
351
|
exportDatabase: () => {
|
|
360
352
|
const { promise, resolve } = Promise.withResolvers();
|
|
@@ -432,3 +424,6 @@ const createLoadingPromises = (subscribedQueries) => {
|
|
|
432
424
|
};
|
|
433
425
|
return loadingPromises;
|
|
434
426
|
};
|
|
427
|
+
const assertValidDbChange = (dbChange) => {
|
|
428
|
+
assert(DbChange.is(dbChange), `Failed to create DbChange for table "${dbChange.table}". If you see this message, you either disabled EvoluSchema validation or Evolu has a bug - please report it.`);
|
|
429
|
+
};
|
|
@@ -123,7 +123,6 @@
|
|
|
123
123
|
import { NonEmptyReadonlyArray } from "../Array.js";
|
|
124
124
|
import { Buffer } from "../Buffer.js";
|
|
125
125
|
import { CreateRandomBytesDep, EncryptionKey, SymmetricCryptoDecryptError, SymmetricCryptoDep } from "../Crypto.js";
|
|
126
|
-
import { ReadonlyRecord } from "../Object.js";
|
|
127
126
|
import { Result } from "../Result.js";
|
|
128
127
|
import { SqliteValue } from "../Sqlite.js";
|
|
129
128
|
import { Id, NanoId, NonNegativeInt, PositiveInt } from "../Type.js";
|
|
@@ -199,15 +198,22 @@ export interface CrdtMessage {
|
|
|
199
198
|
readonly timestamp: Timestamp;
|
|
200
199
|
readonly change: DbChange;
|
|
201
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Base64Url string with maximum length of 256 characters. Encoding strings as
|
|
203
|
+
* Base64UrlString saves up to 25% in size compared to regular strings.
|
|
204
|
+
*/
|
|
205
|
+
export declare const Base64Url256: import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>;
|
|
206
|
+
export type Base64Url256 = typeof Base64Url256.Type;
|
|
202
207
|
/**
|
|
203
208
|
* A DbChange is a change to a table row. Together with a unique
|
|
204
209
|
* {@link Timestamp}, it forms a {@link CrdtMessage}.
|
|
205
210
|
*/
|
|
206
|
-
export
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
+
export declare const DbChange: import("../Type.js").ObjectType<{
|
|
212
|
+
table: import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>;
|
|
213
|
+
id: import("../Type.js").BrandType<import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "Id", import("../Type.js").RegexError<"Id">, import("../Type.js").StringError>;
|
|
214
|
+
values: import("../Type.js").RecordType<"Brand", string & Brand<"Base64Url"> & Brand<"MaxLength256">, string, import("../Type.js").MaxLengthError<256>, string & Brand<"Base64Url">, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">, import("../Type.js").UnionType<[import("../Type.js").Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, import("../Type.js").Type<"Number", number, number, import("../Type.js").NumberError, number, import("../Type.js").NumberError>, import("../Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError>]>>;
|
|
215
|
+
}>;
|
|
216
|
+
export type DbChange = typeof DbChange.Type;
|
|
211
217
|
export declare const RangeType: {
|
|
212
218
|
readonly Fingerprint: 1;
|
|
213
219
|
readonly Skip: 0;
|
|
@@ -356,12 +362,6 @@ export declare const binaryIdToId: (binaryId: BinaryId) => Id;
|
|
|
356
362
|
export type BinaryOwnerId = Uint8Array & Brand<"BinaryOwnerId">;
|
|
357
363
|
export declare const ownerIdToBinaryOwnerId: (ownerId: OwnerId) => BinaryOwnerId;
|
|
358
364
|
export declare const binaryOwnerIdToOwnerId: (binaryOwnerId: BinaryOwnerId) => OwnerId;
|
|
359
|
-
/**
|
|
360
|
-
* Base64Url string with maximum length of 256 characters. Encoding strings as
|
|
361
|
-
* Base64UrlString saves up to 25% in size compared to regular strings.
|
|
362
|
-
*/
|
|
363
|
-
export declare const Base64Url256: import("../Type.js").BrandType<import("../Type.js").Type<"Brand", string & Brand<"Base64Url">, string, import("../Type.js").RegexError<"Base64Url">, string, import("../Type.js").StringError>, "MaxLength256", import("../Type.js").MaxLengthError<256>, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">>;
|
|
364
|
-
export type Base64Url256 = typeof Base64Url256.Type;
|
|
365
365
|
/**
|
|
366
366
|
* Union type for all variants of Base64Url strings with limited length. All
|
|
367
367
|
* these types use Base64Url alphabet and are < 256 characters.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Protocol.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyHG;AAIH,OAAO,EAA2B,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EACL,MAAM,EAQP,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,aAAa,EAEb,2BAA2B,EAC3B,kBAAkB,EACnB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Protocol.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -130,7 +130,8 @@ import { eqArrayNumber } from "../Eq.js";
|
|
|
130
130
|
import { computeBalancedBuckets } from "../Number.js";
|
|
131
131
|
import { objectToEntries } from "../Object.js";
|
|
132
132
|
import { err, ok } from "../Result.js";
|
|
133
|
-
import {
|
|
133
|
+
import { SqliteValue } from "../Sqlite.js";
|
|
134
|
+
import { Base64Url, DateIsoString, Id, idTypeValueLength, JsonValueFromString, maxLength, NonNegativeInt, Number, object, record, } from "../Type.js";
|
|
134
135
|
import { writeKeyLength, } from "./Owner.js";
|
|
135
136
|
import { binaryTimestampToTimestamp, Counter, Millis, timestampToBinaryTimestamp, } from "./Timestamp.js";
|
|
136
137
|
/** Maximum size of the entire protocol message in bytes. */
|
|
@@ -148,6 +149,20 @@ export const ProtocolErrorCode = {
|
|
|
148
149
|
/** A code for {@link ProtocolSyncError}. */
|
|
149
150
|
SyncError: 3,
|
|
150
151
|
};
|
|
152
|
+
/**
|
|
153
|
+
* Base64Url string with maximum length of 256 characters. Encoding strings as
|
|
154
|
+
* Base64UrlString saves up to 25% in size compared to regular strings.
|
|
155
|
+
*/
|
|
156
|
+
export const Base64Url256 = maxLength(256)(Base64Url);
|
|
157
|
+
/**
|
|
158
|
+
* A DbChange is a change to a table row. Together with a unique
|
|
159
|
+
* {@link Timestamp}, it forms a {@link CrdtMessage}.
|
|
160
|
+
*/
|
|
161
|
+
export const DbChange = object({
|
|
162
|
+
table: Base64Url256,
|
|
163
|
+
id: Id,
|
|
164
|
+
values: record(Base64Url256, SqliteValue),
|
|
165
|
+
});
|
|
151
166
|
export const RangeType = {
|
|
152
167
|
Fingerprint: 1,
|
|
153
168
|
Skip: 0,
|
|
@@ -840,11 +855,6 @@ export const idToBinaryId = (id) => base64Url256ToBytes(id);
|
|
|
840
855
|
export const binaryIdToId = (binaryId) => decodeId(createBuffer(binaryId));
|
|
841
856
|
export const ownerIdToBinaryOwnerId = (ownerId) => base64Url256ToBytes(ownerId);
|
|
842
857
|
export const binaryOwnerIdToOwnerId = (binaryOwnerId) => decodeOwnerId(createBuffer(binaryOwnerId));
|
|
843
|
-
/**
|
|
844
|
-
* Base64Url string with maximum length of 256 characters. Encoding strings as
|
|
845
|
-
* Base64UrlString saves up to 25% in size compared to regular strings.
|
|
846
|
-
*/
|
|
847
|
-
export const Base64Url256 = maxLength(256)(Base64Url);
|
|
848
858
|
/**
|
|
849
859
|
* Alphabet used for Base64Url encoding. This is copied from the `nanoid`
|
|
850
860
|
* library to avoid dependency on a specific version of `nanoid`.
|
|
@@ -2,7 +2,7 @@ import { Kysely, SelectQueryBuilder } from "kysely";
|
|
|
2
2
|
import { ReadonlyRecord } from "../Object.js";
|
|
3
3
|
import { Result } from "../Result.js";
|
|
4
4
|
import { SqliteBoolean, SqliteQueryOptions, SqliteValue } from "../Sqlite.js";
|
|
5
|
-
import { AnyType, BrandType, InferErrors, InferInput, InferType, MergeObjectTypeErrors, NullableToOptionalProps, ObjectType, OptionalType, Type, TypeError } from "../Type.js";
|
|
5
|
+
import { AnyType, BrandType, IdType, InferErrors, InferInput, InferType, MergeObjectTypeErrors, NullableToOptionalProps, ObjectType, OptionalType, Type, TypeError } from "../Type.js";
|
|
6
6
|
import { Simplify } from "../Types.js";
|
|
7
7
|
import { DbSchema } from "./Db.js";
|
|
8
8
|
import { DbIndexesBuilder } from "./Kysely.js";
|
|
@@ -13,12 +13,6 @@ import { BinaryTimestamp } from "./Timestamp.js";
|
|
|
13
13
|
/**
|
|
14
14
|
* Defines the schema of an Evolu database.
|
|
15
15
|
*
|
|
16
|
-
* - Each top-level key represents a table name.
|
|
17
|
-
* - The value for each table name is a record of column names mapped to their
|
|
18
|
-
* respective data types, defined by {@link Type}.
|
|
19
|
-
* - Each table must include a mandatory `id` column of type {@link Id}.
|
|
20
|
-
* - No table may contain {@link DefaultColumns}.
|
|
21
|
-
*
|
|
22
16
|
* Table schema defines columns that are required for table rows. For not
|
|
23
17
|
* required columns, use {@link nullOr}.
|
|
24
18
|
*
|
|
@@ -50,9 +44,28 @@ import { BinaryTimestamp } from "./Timestamp.js";
|
|
|
50
44
|
* };
|
|
51
45
|
* ```
|
|
52
46
|
*/
|
|
53
|
-
export type EvoluSchema = ReadonlyRecord<string, ReadonlyRecord<string, Type<any, any, any, any, any
|
|
54
|
-
|
|
55
|
-
}
|
|
47
|
+
export type EvoluSchema = ReadonlyRecord<string, ReadonlyRecord<string, Type<any, any, any, any, any>>>;
|
|
48
|
+
/**
|
|
49
|
+
* Validates an {@link EvoluSchema} at compile time, returning the first error
|
|
50
|
+
* found as a readable string literal type. This approach provides much clearer
|
|
51
|
+
* and more actionable TypeScript errors than the default, which are often hard
|
|
52
|
+
* to read.
|
|
53
|
+
*
|
|
54
|
+
* Validates the following schema requirements:
|
|
55
|
+
*
|
|
56
|
+
* 1. All tables must have an 'id' column
|
|
57
|
+
* 2. The 'id' column must be a branded ID type (created with id() function)
|
|
58
|
+
* 3. Tables cannot use default column names (createdAt, updatedAt, isDeleted)
|
|
59
|
+
* 4. All column types must be compatible with SQLite (extend SqliteValue)
|
|
60
|
+
*/
|
|
61
|
+
export type ValidateSchema<S extends EvoluSchema> = ValidateSchemaHasId<S> extends never ? ValidateIdColumnType<S> extends never ? ValidateNoDefaultColumns<S> extends never ? ValidateColumnTypes<S> extends never ? S : ValidateColumnTypes<S> : ValidateNoDefaultColumns<S> : ValidateIdColumnType<S> : ValidateSchemaHasId<S>;
|
|
62
|
+
export type ValidateSchemaHasId<S extends EvoluSchema> = keyof S extends infer TableName ? TableName extends keyof S ? "id" extends keyof S[TableName] ? never : SchemaValidationError<`Table "${TableName & string}" is missing required id column.`> : never : never;
|
|
63
|
+
export type ValidateIdColumnType<S extends EvoluSchema> = keyof S extends infer TableName ? TableName extends keyof S ? "id" extends keyof S[TableName] ? S[TableName]["id"] extends IdType<any> ? never : SchemaValidationError<`Table "${TableName & string}" id column must be a branded ID type (created with id("${TableName & string}")).`> : never : never : never;
|
|
64
|
+
export type ValidateNoDefaultColumns<S extends EvoluSchema> = keyof S extends infer TableName ? TableName extends keyof S ? keyof S[TableName] extends infer ColumnName ? ColumnName extends keyof S[TableName] ? ColumnName extends "createdAt" | "updatedAt" | "isDeleted" ? SchemaValidationError<`Table "${TableName & string}" uses default column name "${ColumnName & string}". Default columns (createdAt, updatedAt, isDeleted) are added automatically.`> : never : never : never : never : never;
|
|
65
|
+
export type ValidateColumnTypes<S extends EvoluSchema> = keyof S extends infer TableName ? TableName extends keyof S ? keyof S[TableName] extends infer ColumnName ? ColumnName extends keyof S[TableName] ? InferType<S[TableName][ColumnName]> extends SqliteValue ? never : SchemaValidationError<`Table "${TableName & string}" column "${ColumnName & string}" type is not compatible with SQLite. Column types must extend SqliteValue (string, number, Uint8Array, or null).`> : never : never : never : never;
|
|
66
|
+
/** Schema validation error that shows clear, readable messages */
|
|
67
|
+
export type SchemaValidationError<Message extends string> = `❌ Schema Error: ${Message}`;
|
|
68
|
+
export declare const evoluSchemaToDbSchema: (schema: EvoluSchema, indexes?: DbIndexesBuilder) => DbSchema;
|
|
56
69
|
export type CreateQuery<S extends EvoluSchema> = <R extends Row>(queryCallback: (db: Pick<Kysely<{
|
|
57
70
|
[Table in keyof S]: {
|
|
58
71
|
readonly [Column in keyof S[Table]]: Column extends "id" | "createdAt" | "updatedAt" ? InferType<S[Table][Column]> : InferType<S[Table][Column]> | null;
|
|
@@ -72,35 +85,6 @@ export declare const DefaultColumns: ObjectType<{
|
|
|
72
85
|
isDeleted: import("../Type.js").UnionType<[Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").TransformType<Type<"Boolean", boolean, boolean, import("../Type.js").BooleanError, boolean, import("../Type.js").BooleanError>, import("../Type.js").UnionType<[import("../Type.js").LiteralType<0>, import("../Type.js").LiteralType<1>]>, never>]>;
|
|
73
86
|
}>;
|
|
74
87
|
export type DefaultColumns = typeof DefaultColumns.Type;
|
|
75
|
-
/**
|
|
76
|
-
* Valid {@link EvoluSchema}.
|
|
77
|
-
*
|
|
78
|
-
* - Table and column names must be Base64Url strings.
|
|
79
|
-
* - Each table must include an `id` column of type {@link Id}.
|
|
80
|
-
* - Default column names (`createdAt`, `updatedAt`, `isDeleted`) are not allowed.
|
|
81
|
-
*/
|
|
82
|
-
export declare const ValidEvoluSchema: BrandType<import("../Type.js").RecordType<"Brand", string & import("../Types.js").Brand<"Base64Url"> & import("../Types.js").Brand<"MaxLength256">, string, import("../Type.js").MaxLengthError<256>, string & import("../Types.js").Brand<"Base64Url">, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">, import("../Type.js").ObjectWithRecordType<{
|
|
83
|
-
id: Type<"EvoluType", AnyType, AnyType, import("../Type.js").EvoluTypeError, AnyType, import("../Type.js").EvoluTypeError>;
|
|
84
|
-
}, "Brand", string & import("../Types.js").Brand<"Base64Url"> & import("../Types.js").Brand<"MaxLength256">, string, import("../Type.js").MaxLengthError<256>, string & import("../Types.js").Brand<"Base64Url">, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">, Type<"Unknown", unknown, unknown, never, unknown, never>>>, "ValidEvoluSchema", ValidEvoluSchemaError, import("../Type.js").RecordError<import("../Type.js").MaxLengthError<256>, import("../Type.js").ObjectWithRecordError<{
|
|
85
|
-
id: import("../Type.js").EvoluTypeError;
|
|
86
|
-
}, import("../Type.js").MaxLengthError<256>, never>> | import("../Type.js").RecordError<import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">, import("../Type.js").ObjectWithRecordError<{
|
|
87
|
-
id: import("../Type.js").EvoluTypeError;
|
|
88
|
-
}, import("../Type.js").StringError | import("../Type.js").RegexError<"Base64Url">, never>>>;
|
|
89
|
-
export type ValidEvoluSchema = typeof ValidEvoluSchema.Type;
|
|
90
|
-
export interface ValidEvoluSchemaError extends TypeError<"ValidEvoluSchema"> {
|
|
91
|
-
readonly reason: {
|
|
92
|
-
kind: "DefaultColumnError";
|
|
93
|
-
tableName: string;
|
|
94
|
-
columnName: string;
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Asserts that the given value is {@link ValidEvoluSchema}.
|
|
99
|
-
*
|
|
100
|
-
* Throws an error if the value is not a valid Evolu schema.
|
|
101
|
-
*/
|
|
102
|
-
export declare const assertValidEvoluSchema: (value: unknown) => ValidEvoluSchema;
|
|
103
|
-
export declare const validEvoluSchemaToDbSchema: (validEvoluSchema: ValidEvoluSchema, indexes?: DbIndexesBuilder) => DbSchema;
|
|
104
88
|
export type MutationKind = "insert" | "update" | "upsert";
|
|
105
89
|
export type Mutation<S extends EvoluSchema, Kind extends MutationKind> = <TableName extends keyof S>(table: TableName, props: InferInput<ObjectType<MutationMapping<S[TableName], Kind>>>, options?: MutationOptions) => Result<{
|
|
106
90
|
readonly id: S[TableName]["id"]["Type"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Schema.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Evolu/Schema.js
CHANGED
|
@@ -1,86 +1,27 @@
|
|
|
1
1
|
import { pack } from "msgpackr";
|
|
2
|
+
import { assert } from "../Assert.js";
|
|
2
3
|
import { mapObject, objectToEntries } from "../Object.js";
|
|
3
4
|
import { err, ok } from "../Result.js";
|
|
4
5
|
import { SqliteBoolean } from "../Sqlite.js";
|
|
5
|
-
import { brand, createTypeErrorFormatter, DateIsoString,
|
|
6
|
+
import { brand, createTypeErrorFormatter, DateIsoString, nullableToOptional, nullOr, object, omit, optional, } from "../Type.js";
|
|
7
|
+
import { DbSchema } from "./Db.js";
|
|
6
8
|
import { createIndexes } from "./Kysely.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
createdAt: DateIsoString,
|
|
10
|
-
updatedAt: DateIsoString,
|
|
11
|
-
isDeleted: nullOr(SqliteBoolean),
|
|
12
|
-
});
|
|
13
|
-
const isDefaultColumnName = (value) => value === "createdAt" || value === "updatedAt" || value === "isDeleted";
|
|
14
|
-
/**
|
|
15
|
-
* Valid {@link EvoluSchema}.
|
|
16
|
-
*
|
|
17
|
-
* - Table and column names must be Base64Url strings.
|
|
18
|
-
* - Each table must include an `id` column of type {@link Id}.
|
|
19
|
-
* - Default column names (`createdAt`, `updatedAt`, `isDeleted`) are not allowed.
|
|
20
|
-
*/
|
|
21
|
-
export const ValidEvoluSchema = brand("ValidEvoluSchema", record(Base64Url256, object({ id: EvoluType }, record(Base64Url256, Unknown))), (value) => {
|
|
22
|
-
for (const tableName in value) {
|
|
23
|
-
for (const columnName in value[tableName]) {
|
|
24
|
-
if (isDefaultColumnName(columnName)) {
|
|
25
|
-
return err({
|
|
26
|
-
type: "ValidEvoluSchema",
|
|
27
|
-
value,
|
|
28
|
-
reason: {
|
|
29
|
-
kind: "DefaultColumnError",
|
|
30
|
-
tableName,
|
|
31
|
-
columnName,
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return ok(value);
|
|
38
|
-
});
|
|
39
|
-
/**
|
|
40
|
-
* Asserts that the given value is {@link ValidEvoluSchema}.
|
|
41
|
-
*
|
|
42
|
-
* Throws an error if the value is not a valid Evolu schema.
|
|
43
|
-
*/
|
|
44
|
-
export const assertValidEvoluSchema = (value) => {
|
|
45
|
-
const validEvoluSchema = ValidEvoluSchema.fromUnknown(value);
|
|
46
|
-
if (!validEvoluSchema.ok) {
|
|
47
|
-
const message = formatValidEvoluSchemaError(validEvoluSchema.error);
|
|
48
|
-
throw new Error(`Invalid Evolu schema: ${message}`);
|
|
49
|
-
}
|
|
50
|
-
return validEvoluSchema.value;
|
|
51
|
-
};
|
|
52
|
-
const formatValidEvoluSchemaError = (error) => {
|
|
53
|
-
if (error.type === "Record") {
|
|
54
|
-
if (error.reason.kind === "Key") {
|
|
55
|
-
return `The table "${error.reason.key}" has invalid name. A table name must be Base64Url256 string (A-Z, a-z, 0-9, -, _).`;
|
|
56
|
-
}
|
|
57
|
-
if (error.reason.kind === "Value" &&
|
|
58
|
-
error.reason.error.reason.kind === "Props" &&
|
|
59
|
-
error.reason.error.reason.errors.id?.type === "EvoluType") {
|
|
60
|
-
return `The table "${error.reason.key}" has invalid ID column. Check examples.`;
|
|
61
|
-
}
|
|
62
|
-
if (error.reason.kind === "Value" &&
|
|
63
|
-
error.reason.error.reason.kind === "IndexKey") {
|
|
64
|
-
return `The table "${error.reason.key}" has invalid column name "${error.reason.error.reason.key}". A column name must be Base64Url256 string (A-Z, a-z, 0-9, -, _).`;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (error.type === "ValidEvoluSchema") {
|
|
68
|
-
return `The table "${error.reason.tableName}" uses reserved column name "${error.reason.columnName}". Reserved column names are: createdAt, updatedAt, isDeleted.`;
|
|
69
|
-
}
|
|
70
|
-
return JSON.stringify(error, null, 2);
|
|
71
|
-
};
|
|
72
|
-
export const validEvoluSchemaToDbSchema = (validEvoluSchema, indexes) => {
|
|
73
|
-
const tables = objectToEntries(validEvoluSchema).map(([tableName, table]) => ({
|
|
9
|
+
export const evoluSchemaToDbSchema = (schema, indexes) => {
|
|
10
|
+
const tables = objectToEntries(schema).map(([tableName, table]) => ({
|
|
74
11
|
name: tableName,
|
|
75
12
|
columns: objectToEntries(table)
|
|
76
13
|
.filter(([k]) => k !== "id")
|
|
77
14
|
.map(([k]) => k),
|
|
78
15
|
}));
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
};
|
|
16
|
+
const dbSchema = { tables, indexes: createIndexes(indexes) };
|
|
17
|
+
assert(DbSchema.is(dbSchema), "Invalid EvoluSchema: Table and column names must use only characters A-Za-z0-9_- and be at most 256 characters long.");
|
|
18
|
+
return dbSchema;
|
|
83
19
|
};
|
|
20
|
+
export const DefaultColumns = object({
|
|
21
|
+
createdAt: DateIsoString,
|
|
22
|
+
updatedAt: DateIsoString,
|
|
23
|
+
isDeleted: nullOr(SqliteBoolean),
|
|
24
|
+
});
|
|
84
25
|
/**
|
|
85
26
|
* Evolu has to limit the maximum mutation size. Otherwise, sync couldn't use
|
|
86
27
|
* the {@link maxProtocolMessageRangesSize}. The max size is 640KB in bytes,
|
package/package.json
CHANGED
package/src/Evolu/Db.ts
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
SqliteValue,
|
|
35
35
|
} from "../Sqlite.js";
|
|
36
36
|
import { TimeDep } from "../Time.js";
|
|
37
|
-
import { Id, Mnemonic, object, SimpleName, String } from "../Type.js";
|
|
37
|
+
import { array, Id, Mnemonic, object, SimpleName, String } from "../Type.js";
|
|
38
38
|
import {
|
|
39
39
|
createInitializedWorker,
|
|
40
40
|
Worker,
|
|
@@ -97,19 +97,21 @@ import {
|
|
|
97
97
|
timestampToTimestampString,
|
|
98
98
|
} from "./Timestamp.js";
|
|
99
99
|
|
|
100
|
-
export
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface DbTable {
|
|
106
|
-
readonly name: Base64Url256;
|
|
107
|
-
readonly columns: ReadonlyArray<Base64Url256>;
|
|
108
|
-
}
|
|
100
|
+
export const DbTable = object({
|
|
101
|
+
name: Base64Url256,
|
|
102
|
+
columns: array(Base64Url256),
|
|
103
|
+
});
|
|
104
|
+
export type DbTable = typeof DbTable.Type;
|
|
109
105
|
|
|
110
106
|
export const DbIndex = object({ name: String, sql: String });
|
|
111
107
|
export type DbIndex = typeof DbIndex.Type;
|
|
112
108
|
|
|
109
|
+
export const DbSchema = object({
|
|
110
|
+
tables: array(DbTable),
|
|
111
|
+
indexes: array(DbIndex),
|
|
112
|
+
});
|
|
113
|
+
export type DbSchema = typeof DbSchema.Type;
|
|
114
|
+
|
|
113
115
|
export type DbWorker = Worker<DbWorkerInput, DbWorkerOutput>;
|
|
114
116
|
|
|
115
117
|
export type CreateDbWorker = (name: SimpleName) => DbWorker;
|
|
@@ -803,6 +805,8 @@ const initializeDb =
|
|
|
803
805
|
strict;
|
|
804
806
|
`,
|
|
805
807
|
|
|
808
|
+
// Index for reading database changes by owner and timestamp.
|
|
809
|
+
// Timestamp always corresponds to a DbChange.
|
|
806
810
|
sql`
|
|
807
811
|
create index evolu_history_ownerId_timestamp on evolu_history (
|
|
808
812
|
"ownerId",
|
|
@@ -1189,7 +1193,6 @@ const createClientStorage =
|
|
|
1189
1193
|
|
|
1190
1194
|
writeMessages: (_ownerId, messages) => {
|
|
1191
1195
|
// TODO: Get owner by _ownerId when we support more.
|
|
1192
|
-
// Use ownerId!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1193
1196
|
const owner = deps.ownerRowRef.get();
|
|
1194
1197
|
const decodedAndDecryptedMessages: Array<CrdtMessage> = [];
|
|
1195
1198
|
|
package/src/Evolu/Evolu.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNonEmptyArray, isNonEmptyReadonlyArray } from "../Array.js";
|
|
2
|
-
import { assertNonEmptyArray } from "../Assert.js";
|
|
2
|
+
import { assert, assertNonEmptyArray } from "../Assert.js";
|
|
3
3
|
import { createCallbacks } from "../Callbacks.js";
|
|
4
4
|
import { ConsoleDep } from "../Console.js";
|
|
5
5
|
import { SymmetricCryptoDecryptError } from "../Crypto.js";
|
|
@@ -44,9 +44,9 @@ import {
|
|
|
44
44
|
SubscribedQueries,
|
|
45
45
|
} from "./Query.js";
|
|
46
46
|
import {
|
|
47
|
-
assertValidEvoluSchema,
|
|
48
47
|
CreateQuery,
|
|
49
48
|
EvoluSchema,
|
|
49
|
+
evoluSchemaToDbSchema,
|
|
50
50
|
insertable,
|
|
51
51
|
Mutation,
|
|
52
52
|
MutationKind,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
MutationOptions,
|
|
55
55
|
updateable,
|
|
56
56
|
upsertable,
|
|
57
|
-
|
|
57
|
+
ValidateSchema,
|
|
58
58
|
ValidMutationSize,
|
|
59
59
|
ValidMutationSizeError,
|
|
60
60
|
} from "./Schema.js";
|
|
@@ -431,9 +431,7 @@ let tabId: Id | null = null;
|
|
|
431
431
|
export const createEvolu =
|
|
432
432
|
(deps: EvoluDeps) =>
|
|
433
433
|
<S extends EvoluSchema>(
|
|
434
|
-
|
|
435
|
-
// with type errors messages as we had it in the old Evolu.
|
|
436
|
-
schema: S,
|
|
434
|
+
schema: ValidateSchema<S> extends never ? S : ValidateSchema<S>,
|
|
437
435
|
partialConfig: Partial<EvoluConfigWithInitialData<S>> = {},
|
|
438
436
|
): Evolu<S> => {
|
|
439
437
|
const config = { ...defaultConfig, ...partialConfig };
|
|
@@ -441,11 +439,14 @@ export const createEvolu =
|
|
|
441
439
|
let evolu = evoluInstances.get(config.name);
|
|
442
440
|
|
|
443
441
|
if (evolu == null) {
|
|
444
|
-
evolu = createEvoluInstance(deps)(
|
|
442
|
+
evolu = createEvoluInstance(deps)(
|
|
443
|
+
schema as EvoluSchema,
|
|
444
|
+
config as IntentionalNever,
|
|
445
|
+
);
|
|
445
446
|
evoluInstances.set(config.name, evolu);
|
|
446
447
|
} else {
|
|
447
448
|
// Hot reloading. Note that indexes are intentionally omitted.
|
|
448
|
-
evolu.ensureSchema(schema);
|
|
449
|
+
evolu.ensureSchema(schema as EvoluSchema);
|
|
449
450
|
}
|
|
450
451
|
|
|
451
452
|
return evolu as IntentionalNever;
|
|
@@ -554,10 +555,7 @@ const createEvoluInstance =
|
|
|
554
555
|
}
|
|
555
556
|
});
|
|
556
557
|
|
|
557
|
-
const dbSchema =
|
|
558
|
-
assertValidEvoluSchema(schema),
|
|
559
|
-
indexes,
|
|
560
|
-
);
|
|
558
|
+
const dbSchema = evoluSchemaToDbSchema(schema, indexes);
|
|
561
559
|
|
|
562
560
|
const mutationTypesCache = new Map<
|
|
563
561
|
MutationKind,
|
|
@@ -592,21 +590,17 @@ const createEvoluInstance =
|
|
|
592
590
|
if (initialData)
|
|
593
591
|
initialData({
|
|
594
592
|
insert: (table, props) => {
|
|
595
|
-
const Type = getMutationType(table, "insert");
|
|
596
593
|
const id = createId(deps);
|
|
594
|
+
const values = getMutationType(table, "insert").fromUnknown(props);
|
|
597
595
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
initialDataDbChanges.push(
|
|
602
|
-
id,
|
|
603
|
-
table,
|
|
604
|
-
values: result.value,
|
|
605
|
-
} as unknown as DbChange);
|
|
596
|
+
if (values.ok) {
|
|
597
|
+
const dbChange = { table, id, values: values.value };
|
|
598
|
+
assertValidDbChange(dbChange);
|
|
599
|
+
initialDataDbChanges.push(dbChange);
|
|
606
600
|
return ok({ id });
|
|
607
601
|
}
|
|
608
602
|
|
|
609
|
-
return
|
|
603
|
+
return values;
|
|
610
604
|
},
|
|
611
605
|
});
|
|
612
606
|
|
|
@@ -654,14 +648,14 @@ const createEvoluInstance =
|
|
|
654
648
|
} else {
|
|
655
649
|
// Remove `id` from values.
|
|
656
650
|
const { id: _id, ...values } = result.value;
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
mutateMicrotaskQueue.push([
|
|
651
|
+
const dbChange = { table, id, values };
|
|
652
|
+
assertValidDbChange(dbChange);
|
|
653
|
+
mutateMicrotaskQueue.push([dbChange, options?.onComplete]);
|
|
660
654
|
}
|
|
661
655
|
|
|
662
656
|
if (mutateMicrotaskQueue.length === 1)
|
|
663
657
|
queueMicrotask(() => {
|
|
664
|
-
const changes = [];
|
|
658
|
+
const changes: Array<DbChange> = [];
|
|
665
659
|
const onCompletes = [];
|
|
666
660
|
|
|
667
661
|
for (const [change, onComplete] of mutateMicrotaskQueue) {
|
|
@@ -807,6 +801,7 @@ const createEvoluInstance =
|
|
|
807
801
|
const onCompleteId = callbacks.register(() => {
|
|
808
802
|
resolve();
|
|
809
803
|
});
|
|
804
|
+
|
|
810
805
|
dbWorker.postMessage({
|
|
811
806
|
type: "reset",
|
|
812
807
|
onCompleteId,
|
|
@@ -822,11 +817,8 @@ const createEvoluInstance =
|
|
|
822
817
|
|
|
823
818
|
ensureSchema: (schema) => {
|
|
824
819
|
mutationTypesCache.clear();
|
|
825
|
-
const
|
|
826
|
-
dbWorker.postMessage({
|
|
827
|
-
type: "ensureDbSchema",
|
|
828
|
-
dbSchema: validEvoluSchemaToDbSchema(validSchema),
|
|
829
|
-
});
|
|
820
|
+
const dbSchema = evoluSchemaToDbSchema(schema);
|
|
821
|
+
dbWorker.postMessage({ type: "ensureDbSchema", dbSchema });
|
|
830
822
|
},
|
|
831
823
|
|
|
832
824
|
exportDatabase: () => {
|
|
@@ -945,3 +937,14 @@ const createLoadingPromises = (
|
|
|
945
937
|
|
|
946
938
|
return loadingPromises;
|
|
947
939
|
};
|
|
940
|
+
|
|
941
|
+
const assertValidDbChange: (dbChange: {
|
|
942
|
+
table: string;
|
|
943
|
+
id: Id;
|
|
944
|
+
values: unknown;
|
|
945
|
+
}) => asserts dbChange is DbChange = (dbChange) => {
|
|
946
|
+
assert(
|
|
947
|
+
DbChange.is(dbChange),
|
|
948
|
+
`Failed to create DbChange for table "${dbChange.table}". If you see this message, you either disabled EvoluSchema validation or Evolu has a bug - please report it.`,
|
|
949
|
+
);
|
|
950
|
+
};
|
package/src/Evolu/Protocol.ts
CHANGED
|
@@ -144,7 +144,7 @@ import {
|
|
|
144
144
|
} from "../Crypto.js";
|
|
145
145
|
import { eqArrayNumber } from "../Eq.js";
|
|
146
146
|
import { computeBalancedBuckets } from "../Number.js";
|
|
147
|
-
import { objectToEntries
|
|
147
|
+
import { objectToEntries } from "../Object.js";
|
|
148
148
|
import { err, ok, Result } from "../Result.js";
|
|
149
149
|
import { SqliteValue } from "../Sqlite.js";
|
|
150
150
|
import {
|
|
@@ -157,7 +157,9 @@ import {
|
|
|
157
157
|
NanoId,
|
|
158
158
|
NonNegativeInt,
|
|
159
159
|
Number,
|
|
160
|
+
object,
|
|
160
161
|
PositiveInt,
|
|
162
|
+
record,
|
|
161
163
|
} from "../Type.js";
|
|
162
164
|
import { Brand, Predicate } from "../Types.js";
|
|
163
165
|
import {
|
|
@@ -293,15 +295,23 @@ export interface CrdtMessage {
|
|
|
293
295
|
readonly change: DbChange;
|
|
294
296
|
}
|
|
295
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Base64Url string with maximum length of 256 characters. Encoding strings as
|
|
300
|
+
* Base64UrlString saves up to 25% in size compared to regular strings.
|
|
301
|
+
*/
|
|
302
|
+
export const Base64Url256 = maxLength(256)(Base64Url);
|
|
303
|
+
export type Base64Url256 = typeof Base64Url256.Type;
|
|
304
|
+
|
|
296
305
|
/**
|
|
297
306
|
* A DbChange is a change to a table row. Together with a unique
|
|
298
307
|
* {@link Timestamp}, it forms a {@link CrdtMessage}.
|
|
299
308
|
*/
|
|
300
|
-
export
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
309
|
+
export const DbChange = object({
|
|
310
|
+
table: Base64Url256,
|
|
311
|
+
id: Id,
|
|
312
|
+
values: record(Base64Url256, SqliteValue),
|
|
313
|
+
});
|
|
314
|
+
export type DbChange = typeof DbChange.Type;
|
|
305
315
|
|
|
306
316
|
export const RangeType = {
|
|
307
317
|
Fingerprint: 1,
|
|
@@ -1434,13 +1444,6 @@ export const ownerIdToBinaryOwnerId = (ownerId: OwnerId): BinaryOwnerId =>
|
|
|
1434
1444
|
export const binaryOwnerIdToOwnerId = (binaryOwnerId: BinaryOwnerId): OwnerId =>
|
|
1435
1445
|
decodeOwnerId(createBuffer(binaryOwnerId));
|
|
1436
1446
|
|
|
1437
|
-
/**
|
|
1438
|
-
* Base64Url string with maximum length of 256 characters. Encoding strings as
|
|
1439
|
-
* Base64UrlString saves up to 25% in size compared to regular strings.
|
|
1440
|
-
*/
|
|
1441
|
-
export const Base64Url256 = maxLength(256)(Base64Url);
|
|
1442
|
-
export type Base64Url256 = typeof Base64Url256.Type;
|
|
1443
|
-
|
|
1444
1447
|
/**
|
|
1445
1448
|
* Union type for all variants of Base64Url strings with limited length. All
|
|
1446
1449
|
* these types use Base64Url alphabet and are < 256 characters.
|
package/src/Evolu/Schema.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Kysely, SelectQueryBuilder } from "kysely";
|
|
2
2
|
import { pack } from "msgpackr";
|
|
3
|
+
import { assert } from "../Assert.js";
|
|
3
4
|
import { mapObject, objectToEntries, ReadonlyRecord } from "../Object.js";
|
|
4
5
|
import { err, ok, Result } from "../Result.js";
|
|
5
6
|
import { SqliteBoolean, SqliteQueryOptions, SqliteValue } from "../Sqlite.js";
|
|
@@ -9,8 +10,7 @@ import {
|
|
|
9
10
|
BrandType,
|
|
10
11
|
createTypeErrorFormatter,
|
|
11
12
|
DateIsoString,
|
|
12
|
-
|
|
13
|
-
Id,
|
|
13
|
+
IdType,
|
|
14
14
|
InferErrors,
|
|
15
15
|
InferInput,
|
|
16
16
|
InferType,
|
|
@@ -23,32 +23,20 @@ import {
|
|
|
23
23
|
omit,
|
|
24
24
|
optional,
|
|
25
25
|
OptionalType,
|
|
26
|
-
record,
|
|
27
26
|
Type,
|
|
28
27
|
TypeError,
|
|
29
|
-
Unknown,
|
|
30
28
|
} from "../Type.js";
|
|
31
29
|
import { Simplify } from "../Types.js";
|
|
32
|
-
import { DbSchema
|
|
30
|
+
import { DbSchema } from "./Db.js";
|
|
33
31
|
import { createIndexes, DbIndexesBuilder } from "./Kysely.js";
|
|
34
32
|
import { AppOwner, ShardOwner, SharedOwner } from "./Owner.js";
|
|
35
|
-
import {
|
|
36
|
-
Base64Url256,
|
|
37
|
-
BinaryId,
|
|
38
|
-
maxProtocolMessageRangesSize,
|
|
39
|
-
} from "./Protocol.js";
|
|
33
|
+
import { BinaryId, maxProtocolMessageRangesSize } from "./Protocol.js";
|
|
40
34
|
import { Query, Row } from "./Query.js";
|
|
41
35
|
import { BinaryTimestamp } from "./Timestamp.js";
|
|
42
36
|
|
|
43
37
|
/**
|
|
44
38
|
* Defines the schema of an Evolu database.
|
|
45
39
|
*
|
|
46
|
-
* - Each top-level key represents a table name.
|
|
47
|
-
* - The value for each table name is a record of column names mapped to their
|
|
48
|
-
* respective data types, defined by {@link Type}.
|
|
49
|
-
* - Each table must include a mandatory `id` column of type {@link Id}.
|
|
50
|
-
* - No table may contain {@link DefaultColumns}.
|
|
51
|
-
*
|
|
52
40
|
* Table schema defines columns that are required for table rows. For not
|
|
53
41
|
* required columns, use {@link nullOr}.
|
|
54
42
|
*
|
|
@@ -82,11 +70,105 @@ import { BinaryTimestamp } from "./Timestamp.js";
|
|
|
82
70
|
*/
|
|
83
71
|
export type EvoluSchema = ReadonlyRecord<
|
|
84
72
|
string,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
73
|
+
// TypeScript errors are cryptic so we use ValidateSchema.
|
|
74
|
+
ReadonlyRecord<string, Type<any, any, any, any, any>>
|
|
88
75
|
>;
|
|
89
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Validates an {@link EvoluSchema} at compile time, returning the first error
|
|
79
|
+
* found as a readable string literal type. This approach provides much clearer
|
|
80
|
+
* and more actionable TypeScript errors than the default, which are often hard
|
|
81
|
+
* to read.
|
|
82
|
+
*
|
|
83
|
+
* Validates the following schema requirements:
|
|
84
|
+
*
|
|
85
|
+
* 1. All tables must have an 'id' column
|
|
86
|
+
* 2. The 'id' column must be a branded ID type (created with id() function)
|
|
87
|
+
* 3. Tables cannot use default column names (createdAt, updatedAt, isDeleted)
|
|
88
|
+
* 4. All column types must be compatible with SQLite (extend SqliteValue)
|
|
89
|
+
*/
|
|
90
|
+
export type ValidateSchema<S extends EvoluSchema> =
|
|
91
|
+
ValidateSchemaHasId<S> extends never
|
|
92
|
+
? ValidateIdColumnType<S> extends never
|
|
93
|
+
? ValidateNoDefaultColumns<S> extends never
|
|
94
|
+
? ValidateColumnTypes<S> extends never
|
|
95
|
+
? S
|
|
96
|
+
: ValidateColumnTypes<S>
|
|
97
|
+
: ValidateNoDefaultColumns<S>
|
|
98
|
+
: ValidateIdColumnType<S>
|
|
99
|
+
: ValidateSchemaHasId<S>;
|
|
100
|
+
|
|
101
|
+
export type ValidateSchemaHasId<S extends EvoluSchema> =
|
|
102
|
+
keyof S extends infer TableName
|
|
103
|
+
? TableName extends keyof S
|
|
104
|
+
? "id" extends keyof S[TableName]
|
|
105
|
+
? never
|
|
106
|
+
: SchemaValidationError<`Table "${TableName & string}" is missing required id column.`>
|
|
107
|
+
: never
|
|
108
|
+
: never;
|
|
109
|
+
|
|
110
|
+
export type ValidateIdColumnType<S extends EvoluSchema> =
|
|
111
|
+
keyof S extends infer TableName
|
|
112
|
+
? TableName extends keyof S
|
|
113
|
+
? "id" extends keyof S[TableName]
|
|
114
|
+
? S[TableName]["id"] extends IdType<any>
|
|
115
|
+
? never
|
|
116
|
+
: SchemaValidationError<`Table "${TableName & string}" id column must be a branded ID type (created with id("${TableName & string}")).`>
|
|
117
|
+
: never
|
|
118
|
+
: never
|
|
119
|
+
: never;
|
|
120
|
+
|
|
121
|
+
export type ValidateNoDefaultColumns<S extends EvoluSchema> =
|
|
122
|
+
keyof S extends infer TableName
|
|
123
|
+
? TableName extends keyof S
|
|
124
|
+
? keyof S[TableName] extends infer ColumnName
|
|
125
|
+
? ColumnName extends keyof S[TableName]
|
|
126
|
+
? ColumnName extends "createdAt" | "updatedAt" | "isDeleted"
|
|
127
|
+
? SchemaValidationError<`Table "${TableName & string}" uses default column name "${ColumnName & string}". Default columns (createdAt, updatedAt, isDeleted) are added automatically.`>
|
|
128
|
+
: never
|
|
129
|
+
: never
|
|
130
|
+
: never
|
|
131
|
+
: never
|
|
132
|
+
: never;
|
|
133
|
+
|
|
134
|
+
export type ValidateColumnTypes<S extends EvoluSchema> =
|
|
135
|
+
keyof S extends infer TableName
|
|
136
|
+
? TableName extends keyof S
|
|
137
|
+
? keyof S[TableName] extends infer ColumnName
|
|
138
|
+
? ColumnName extends keyof S[TableName]
|
|
139
|
+
? InferType<S[TableName][ColumnName]> extends SqliteValue
|
|
140
|
+
? never
|
|
141
|
+
: SchemaValidationError<`Table "${TableName & string}" column "${ColumnName & string}" type is not compatible with SQLite. Column types must extend SqliteValue (string, number, Uint8Array, or null).`>
|
|
142
|
+
: never
|
|
143
|
+
: never
|
|
144
|
+
: never
|
|
145
|
+
: never;
|
|
146
|
+
|
|
147
|
+
/** Schema validation error that shows clear, readable messages */
|
|
148
|
+
export type SchemaValidationError<Message extends string> =
|
|
149
|
+
`❌ Schema Error: ${Message}`;
|
|
150
|
+
|
|
151
|
+
export const evoluSchemaToDbSchema = (
|
|
152
|
+
schema: EvoluSchema,
|
|
153
|
+
indexes?: DbIndexesBuilder,
|
|
154
|
+
): DbSchema => {
|
|
155
|
+
const tables = objectToEntries(schema).map(([tableName, table]) => ({
|
|
156
|
+
name: tableName,
|
|
157
|
+
columns: objectToEntries(table)
|
|
158
|
+
.filter(([k]) => k !== "id")
|
|
159
|
+
.map(([k]) => k),
|
|
160
|
+
}));
|
|
161
|
+
|
|
162
|
+
const dbSchema = { tables, indexes: createIndexes(indexes) };
|
|
163
|
+
|
|
164
|
+
assert(
|
|
165
|
+
DbSchema.is(dbSchema),
|
|
166
|
+
"Invalid EvoluSchema: Table and column names must use only characters A-Za-z0-9_- and be at most 256 characters long.",
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
return dbSchema;
|
|
170
|
+
};
|
|
171
|
+
|
|
90
172
|
export type CreateQuery<S extends EvoluSchema> = <R extends Row>(
|
|
91
173
|
queryCallback: (
|
|
92
174
|
db: Pick<
|
|
@@ -123,116 +205,6 @@ export const DefaultColumns = object({
|
|
|
123
205
|
});
|
|
124
206
|
export type DefaultColumns = typeof DefaultColumns.Type;
|
|
125
207
|
|
|
126
|
-
const isDefaultColumnName = (value: string): boolean =>
|
|
127
|
-
value === "createdAt" || value === "updatedAt" || value === "isDeleted";
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Valid {@link EvoluSchema}.
|
|
131
|
-
*
|
|
132
|
-
* - Table and column names must be Base64Url strings.
|
|
133
|
-
* - Each table must include an `id` column of type {@link Id}.
|
|
134
|
-
* - Default column names (`createdAt`, `updatedAt`, `isDeleted`) are not allowed.
|
|
135
|
-
*/
|
|
136
|
-
export const ValidEvoluSchema = brand(
|
|
137
|
-
"ValidEvoluSchema",
|
|
138
|
-
record(
|
|
139
|
-
Base64Url256,
|
|
140
|
-
object({ id: EvoluType }, record(Base64Url256, Unknown)),
|
|
141
|
-
),
|
|
142
|
-
(value) => {
|
|
143
|
-
for (const tableName in value) {
|
|
144
|
-
for (const columnName in value[tableName as never]) {
|
|
145
|
-
if (isDefaultColumnName(columnName)) {
|
|
146
|
-
return err<ValidEvoluSchemaError>({
|
|
147
|
-
type: "ValidEvoluSchema",
|
|
148
|
-
value,
|
|
149
|
-
reason: {
|
|
150
|
-
kind: "DefaultColumnError",
|
|
151
|
-
tableName,
|
|
152
|
-
columnName,
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return ok(value);
|
|
160
|
-
},
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
export type ValidEvoluSchema = typeof ValidEvoluSchema.Type;
|
|
164
|
-
|
|
165
|
-
export interface ValidEvoluSchemaError extends TypeError<"ValidEvoluSchema"> {
|
|
166
|
-
readonly reason: {
|
|
167
|
-
kind: "DefaultColumnError";
|
|
168
|
-
tableName: string;
|
|
169
|
-
columnName: string;
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Asserts that the given value is {@link ValidEvoluSchema}.
|
|
175
|
-
*
|
|
176
|
-
* Throws an error if the value is not a valid Evolu schema.
|
|
177
|
-
*/
|
|
178
|
-
export const assertValidEvoluSchema = (value: unknown): ValidEvoluSchema => {
|
|
179
|
-
const validEvoluSchema = ValidEvoluSchema.fromUnknown(value);
|
|
180
|
-
if (!validEvoluSchema.ok) {
|
|
181
|
-
const message = formatValidEvoluSchemaError(validEvoluSchema.error);
|
|
182
|
-
throw new Error(`Invalid Evolu schema: ${message}`);
|
|
183
|
-
}
|
|
184
|
-
return validEvoluSchema.value;
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
const formatValidEvoluSchemaError = (
|
|
188
|
-
error: typeof ValidEvoluSchema.Error | typeof ValidEvoluSchema.ParentError,
|
|
189
|
-
): string => {
|
|
190
|
-
if (error.type === "Record") {
|
|
191
|
-
if (error.reason.kind === "Key") {
|
|
192
|
-
return `The table "${error.reason.key}" has invalid name. A table name must be Base64Url256 string (A-Z, a-z, 0-9, -, _).`;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (
|
|
196
|
-
error.reason.kind === "Value" &&
|
|
197
|
-
error.reason.error.reason.kind === "Props" &&
|
|
198
|
-
error.reason.error.reason.errors.id?.type === "EvoluType"
|
|
199
|
-
) {
|
|
200
|
-
return `The table "${error.reason.key}" has invalid ID column. Check examples.`;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (
|
|
204
|
-
error.reason.kind === "Value" &&
|
|
205
|
-
error.reason.error.reason.kind === "IndexKey"
|
|
206
|
-
) {
|
|
207
|
-
return `The table "${error.reason.key}" has invalid column name "${error.reason.error.reason.key}". A column name must be Base64Url256 string (A-Z, a-z, 0-9, -, _).`;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (error.type === "ValidEvoluSchema") {
|
|
212
|
-
return `The table "${error.reason.tableName}" uses reserved column name "${error.reason.columnName}". Reserved column names are: createdAt, updatedAt, isDeleted.`;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return JSON.stringify(error, null, 2);
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
export const validEvoluSchemaToDbSchema = (
|
|
219
|
-
validEvoluSchema: ValidEvoluSchema,
|
|
220
|
-
indexes?: DbIndexesBuilder,
|
|
221
|
-
): DbSchema => {
|
|
222
|
-
const tables = objectToEntries(validEvoluSchema).map(
|
|
223
|
-
([tableName, table]): DbTable => ({
|
|
224
|
-
name: tableName,
|
|
225
|
-
columns: objectToEntries(table)
|
|
226
|
-
.filter(([k]) => k !== "id")
|
|
227
|
-
.map(([k]) => k as Base64Url256),
|
|
228
|
-
}),
|
|
229
|
-
);
|
|
230
|
-
return {
|
|
231
|
-
tables,
|
|
232
|
-
indexes: createIndexes(indexes),
|
|
233
|
-
};
|
|
234
|
-
};
|
|
235
|
-
|
|
236
208
|
export type MutationKind = "insert" | "update" | "upsert";
|
|
237
209
|
|
|
238
210
|
export type Mutation<S extends EvoluSchema, Kind extends MutationKind> = <
|