@evolu/common 6.0.1-preview.19 → 6.0.1-preview.20
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/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +1 -1
- package/dist/src/Buffer.d.ts +1 -1
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +1 -1
- package/dist/src/CallbackRegistry.d.ts +53 -0
- package/dist/src/CallbackRegistry.d.ts.map +1 -0
- package/dist/src/CallbackRegistry.js +25 -0
- package/dist/src/Console.d.ts +31 -6
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +72 -9
- package/dist/src/Crypto.d.ts +48 -37
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +27 -50
- package/dist/src/Evolu/Db.d.ts +138 -66
- package/dist/src/Evolu/Db.d.ts.map +1 -1
- package/dist/src/Evolu/Db.js +248 -645
- package/dist/src/Evolu/Diff.d.ts +3 -3
- package/dist/src/Evolu/Diff.d.ts.map +1 -1
- package/dist/src/Evolu/Diff.js +7 -5
- package/dist/src/Evolu/Evolu.d.ts +79 -116
- package/dist/src/Evolu/Evolu.d.ts.map +1 -1
- package/dist/src/Evolu/Evolu.js +275 -132
- package/dist/src/Evolu/Internal.d.ts +0 -2
- package/dist/src/Evolu/Internal.d.ts.map +1 -1
- package/dist/src/Evolu/Internal.js +0 -2
- package/dist/src/Evolu/LocalAuth.d.ts +144 -0
- package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
- package/dist/src/Evolu/LocalAuth.js +171 -0
- package/dist/src/Evolu/Owner.d.ts +129 -83
- package/dist/src/Evolu/Owner.d.ts.map +1 -1
- package/dist/src/Evolu/Owner.js +80 -89
- package/dist/src/Evolu/Platform.d.ts +9 -7
- package/dist/src/Evolu/Platform.d.ts.map +1 -1
- package/dist/src/Evolu/Protocol.d.ts +114 -191
- package/dist/src/Evolu/Protocol.d.ts.map +1 -1
- package/dist/src/Evolu/Protocol.js +409 -416
- package/dist/src/Evolu/Public.d.ts +6 -8
- package/dist/src/Evolu/Public.d.ts.map +1 -1
- package/dist/src/Evolu/Public.js +2 -3
- package/dist/src/Evolu/PublicKysely.js +3 -3
- package/dist/src/Evolu/Relay.d.ts +1 -2
- package/dist/src/Evolu/Relay.d.ts.map +1 -1
- package/dist/src/Evolu/Relay.js +11 -9
- package/dist/src/Evolu/Schema.d.ts +88 -27
- package/dist/src/Evolu/Schema.d.ts.map +1 -1
- package/dist/src/Evolu/Schema.js +141 -24
- package/dist/src/Evolu/Storage.d.ts +158 -14
- package/dist/src/Evolu/Storage.d.ts.map +1 -1
- package/dist/src/Evolu/Storage.js +32 -32
- package/dist/src/Evolu/Sync.d.ts +77 -13
- package/dist/src/Evolu/Sync.d.ts.map +1 -1
- package/dist/src/Evolu/Sync.js +453 -20
- package/dist/src/Evolu/Timestamp.d.ts +29 -27
- package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
- package/dist/src/Evolu/Timestamp.js +20 -18
- package/dist/src/ManyToManyMap.d.ts +74 -10
- package/dist/src/ManyToManyMap.d.ts.map +1 -1
- package/dist/src/ManyToManyMap.js +41 -6
- package/dist/src/Random.d.ts +3 -2
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/RefCountedResourceManager.d.ts +119 -0
- package/dist/src/RefCountedResourceManager.d.ts.map +1 -0
- package/dist/src/RefCountedResourceManager.js +197 -0
- package/dist/src/Result.d.ts +144 -22
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +5 -2
- package/dist/src/Sqlite.d.ts +20 -4
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +50 -8
- package/dist/src/Task.d.ts +511 -0
- package/dist/src/Task.d.ts.map +1 -0
- package/dist/src/Task.js +410 -0
- package/dist/src/Time.d.ts +59 -0
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +87 -4
- package/dist/src/Type.d.ts +431 -341
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +458 -466
- package/dist/src/WebSocket.d.ts +5 -2
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +12 -13
- package/dist/src/Worker.d.ts +39 -11
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +22 -4
- package/dist/src/index.d.ts +2 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -3
- package/package.json +7 -7
- package/src/Assert.ts +2 -4
- package/src/Buffer.ts +1 -1
- package/src/CallbackRegistry.ts +84 -0
- package/src/Console.ts +91 -11
- package/src/Crypto.ts +78 -91
- package/src/Evolu/Db.ts +455 -947
- package/src/Evolu/Diff.ts +7 -5
- package/src/Evolu/Evolu.ts +545 -307
- package/src/Evolu/Internal.ts +0 -2
- package/src/Evolu/LocalAuth.ts +422 -0
- package/src/Evolu/Owner.ts +191 -131
- package/src/Evolu/Platform.ts +9 -9
- package/src/Evolu/Protocol.ts +536 -653
- package/src/Evolu/Public.ts +7 -9
- package/src/Evolu/PublicKysely.ts +3 -3
- package/src/Evolu/Relay.ts +17 -12
- package/src/Evolu/Schema.ts +271 -66
- package/src/Evolu/Storage.ts +263 -55
- package/src/Evolu/Sync.ts +758 -37
- package/src/Evolu/Timestamp.ts +30 -35
- package/src/ManyToManyMap.ts +127 -24
- package/src/Random.ts +3 -2
- package/src/RefCountedResourceManager.ts +368 -0
- package/src/Result.ts +149 -23
- package/src/Sqlite.ts +59 -24
- package/src/Task.ts +779 -0
- package/src/Time.ts +168 -4
- package/src/Type.ts +657 -695
- package/src/WebSocket.ts +23 -17
- package/src/Worker.ts +72 -23
- package/src/index.ts +2 -3
- package/dist/src/Callbacks.d.ts +0 -20
- package/dist/src/Callbacks.d.ts.map +0 -1
- package/dist/src/Callbacks.js +0 -18
- package/dist/src/Evolu/Config.d.ts +0 -82
- package/dist/src/Evolu/Config.d.ts.map +0 -1
- package/dist/src/Evolu/Config.js +0 -9
- package/dist/src/Evolu/Kysely.d.ts +0 -6
- package/dist/src/Evolu/Kysely.d.ts.map +0 -1
- package/dist/src/Evolu/Kysely.js +0 -21
- package/dist/src/NanoId.d.ts +0 -27
- package/dist/src/NanoId.d.ts.map +0 -1
- package/dist/src/NanoId.js +0 -6
- package/dist/src/Promise.d.ts +0 -180
- package/dist/src/Promise.d.ts.map +0 -1
- package/dist/src/Promise.js +0 -176
- package/src/Callbacks.ts +0 -43
- package/src/Evolu/Config.ts +0 -97
- package/src/Evolu/Kysely.ts +0 -38
- package/src/NanoId.ts +0 -39
- package/src/Promise.ts +0 -295
|
@@ -4,15 +4,13 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
export { createEvolu } from "./Evolu.js";
|
|
7
|
-
export type { Evolu, EvoluDeps, EvoluError } from "./Evolu.js";
|
|
7
|
+
export type { Evolu, EvoluConfig, EvoluDeps, EvoluError } from "./Evolu.js";
|
|
8
8
|
export * from "./Owner.js";
|
|
9
|
-
export
|
|
10
|
-
export type { BinaryId } from "./Protocol.js";
|
|
9
|
+
export * from "./LocalAuth.js";
|
|
11
10
|
export * as kysely from "./PublicKysely.js";
|
|
12
11
|
export type { InferRow, Query, QueryRows, Row } from "./Query.js";
|
|
13
|
-
export {
|
|
14
|
-
export type {
|
|
15
|
-
export
|
|
16
|
-
export {
|
|
17
|
-
export type { BinaryTimestamp, TimestampCounterOverflowError, TimestampDriftError, TimestampDuplicateNodeError, TimestampError, TimestampTimeOutOfRangeError, } from "./Timestamp.js";
|
|
12
|
+
export type { EvoluSchema } from "./Schema.js";
|
|
13
|
+
export type { NetworkError, PaymentRequiredError, ServerError, SyncOwner, SyncState, SyncStateInitial, SyncStateIsNotSynced, SyncStateIsSynced, SyncStateIsSyncing, } from "./Sync.js";
|
|
14
|
+
export { Timestamp, timestampBytesToTimestamp, timestampToTimestampBytes, } from "./Timestamp.js";
|
|
15
|
+
export type { TimestampBytes, TimestampCounterOverflowError, TimestampDriftError, TimestampError, TimestampTimeOutOfRangeError, } from "./Timestamp.js";
|
|
18
16
|
//# sourceMappingURL=Public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Public.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Public.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"Public.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Public.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5E,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACX,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,SAAS,EACT,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,cAAc,EACd,6BAA6B,EAC7B,mBAAmB,EACnB,cAAc,EACd,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC"}
|
package/dist/src/Evolu/Public.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export { createEvolu } from "./Evolu.js";
|
|
7
7
|
export * from "./Owner.js";
|
|
8
|
-
export
|
|
8
|
+
export * from "./LocalAuth.js";
|
|
9
9
|
export * as kysely from "./PublicKysely.js";
|
|
10
|
-
export {
|
|
11
|
-
export { binaryTimestampToTimestamp, Timestamp, timestampToBinaryTimestamp, } from "./Timestamp.js";
|
|
10
|
+
export { Timestamp, timestampBytesToTimestamp, timestampToTimestampBytes, } from "./Timestamp.js";
|
|
@@ -48,7 +48,7 @@ export { sql } from "kysely";
|
|
|
48
48
|
* from "person"
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
|
-
//
|
|
51
|
+
// Kysely expects strict AST.
|
|
52
52
|
// prettier-ignore
|
|
53
53
|
export function jsonArrayFrom(expr) {
|
|
54
54
|
return sql `(select ${sql.lit(kyselyJsonIdentifier)} || coalesce(json_group_array(json_object(${sql.join(getSqliteJsonObjectArgs(expr.toOperationNode(), 'agg'))})), '[]') from ${expr} as agg)`;
|
|
@@ -100,7 +100,7 @@ export function jsonArrayFrom(expr) {
|
|
|
100
100
|
* from "person";
|
|
101
101
|
* ```
|
|
102
102
|
*/
|
|
103
|
-
//
|
|
103
|
+
// Kysely expects strict AST.
|
|
104
104
|
// prettier-ignore
|
|
105
105
|
export function jsonObjectFrom(expr) {
|
|
106
106
|
return sql `(select ${sql.lit(kyselyJsonIdentifier)} || json_object(${sql.join(getSqliteJsonObjectArgs(expr.toOperationNode(), 'obj'))}) from ${expr} as obj)`;
|
|
@@ -145,7 +145,7 @@ export function jsonObjectFrom(expr) {
|
|
|
145
145
|
* from "person"
|
|
146
146
|
* ```
|
|
147
147
|
*/
|
|
148
|
-
//
|
|
148
|
+
// Kysely expects strict AST.
|
|
149
149
|
// prettier-ignore
|
|
150
150
|
export function jsonBuildObject(obj) {
|
|
151
151
|
return sql `${sql.lit(kyselyJsonIdentifier)} || json_object(${sql.join(Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]))})`;
|
|
@@ -3,8 +3,7 @@ import { TimingSafeEqualDep } from "../Crypto.js";
|
|
|
3
3
|
import { Result } from "../Result.js";
|
|
4
4
|
import { SqliteError } from "../Sqlite.js";
|
|
5
5
|
import { SimpleName } from "../Type.js";
|
|
6
|
-
import { Storage } from "./
|
|
7
|
-
import { CreateSqliteStorageBaseOptions, SqliteStorageDeps } from "./Storage.js";
|
|
6
|
+
import { CreateSqliteStorageBaseOptions, SqliteStorageDeps, Storage } from "./Storage.js";
|
|
8
7
|
export interface Relay extends Disposable {
|
|
9
8
|
}
|
|
10
9
|
export interface RelayConfig extends ConsoleConfig {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Relay.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAW,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAO,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,
|
|
1
|
+
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Relay.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAW,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAO,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAEL,8BAA8B,EAE9B,iBAAiB,EACjB,OAAO,EACR,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,KAAM,SAAQ,UAAU;CAAG;AAE5C,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;CAC5B;AAED,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAE5E,eAAO,MAAM,kBAAkB,GAC5B,MAAM,sBAAsB,MAC5B,SAAS,8BAA8B,KAAG,MAAM,CAAC,OAAO,EAAE,WAAW,CAiKrE,CAAC"}
|
package/dist/src/Evolu/Relay.js
CHANGED
|
@@ -2,7 +2,7 @@ import { isNonEmptyReadonlyArray } from "../Array.js";
|
|
|
2
2
|
import { err, ok } from "../Result.js";
|
|
3
3
|
import { sql } from "../Sqlite.js";
|
|
4
4
|
import { createSqliteStorageBase, } from "./Storage.js";
|
|
5
|
-
import {
|
|
5
|
+
import { timestampToTimestampBytes } from "./Timestamp.js";
|
|
6
6
|
export const createRelayStorage = (deps) => (options) => {
|
|
7
7
|
const sqliteStorageBase = createSqliteStorageBase(deps)(options);
|
|
8
8
|
if (!sqliteStorageBase.ok)
|
|
@@ -33,7 +33,7 @@ export const createRelayStorage = (deps) => (options) => {
|
|
|
33
33
|
return ok({
|
|
34
34
|
...sqliteStorageBase.value,
|
|
35
35
|
/**
|
|
36
|
-
* Lazily authorizes the initiator's {@link
|
|
36
|
+
* Lazily authorizes the initiator's {@link OwnerWriteKey} for the given
|
|
37
37
|
* {@link OwnerId}.
|
|
38
38
|
*
|
|
39
39
|
* - If the {@link OwnerId} does not exist, it is created and associated with
|
|
@@ -43,10 +43,10 @@ export const createRelayStorage = (deps) => (options) => {
|
|
|
43
43
|
*/
|
|
44
44
|
validateWriteKey: (ownerId, writeKey) => {
|
|
45
45
|
const selectWriteKey = deps.sqlite.exec(sql `
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
select writeKey
|
|
47
|
+
from evolu_writeKey
|
|
48
|
+
where ownerId = ${ownerId};
|
|
49
|
+
`);
|
|
50
50
|
if (!selectWriteKey.ok) {
|
|
51
51
|
options.onStorageError(selectWriteKey.error);
|
|
52
52
|
return false;
|
|
@@ -78,10 +78,12 @@ export const createRelayStorage = (deps) => (options) => {
|
|
|
78
78
|
}
|
|
79
79
|
return true;
|
|
80
80
|
},
|
|
81
|
-
|
|
81
|
+
// https://eslint.org/docs/latest/rules/require-await#when-not-to-use-it
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
83
|
+
writeMessages: async (ownerId, messages) => {
|
|
82
84
|
const result = deps.sqlite.transaction(() => {
|
|
83
85
|
for (const message of messages) {
|
|
84
|
-
const insertTimestampResult = sqliteStorageBase.value.insertTimestamp(ownerId,
|
|
86
|
+
const insertTimestampResult = sqliteStorageBase.value.insertTimestamp(ownerId, timestampToTimestampBytes(message.timestamp));
|
|
85
87
|
if (!insertTimestampResult.ok)
|
|
86
88
|
return insertTimestampResult;
|
|
87
89
|
const insertMessage = deps.sqlite.exec(sql `
|
|
@@ -89,7 +91,7 @@ export const createRelayStorage = (deps) => (options) => {
|
|
|
89
91
|
values
|
|
90
92
|
(
|
|
91
93
|
${ownerId},
|
|
92
|
-
${
|
|
94
|
+
${timestampToTimestampBytes(message.timestamp)},
|
|
93
95
|
${message.change}
|
|
94
96
|
)
|
|
95
97
|
on conflict do nothing;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Kysely from "kysely";
|
|
2
2
|
import { ReadonlyRecord } from "../Object.js";
|
|
3
3
|
import { Result } from "../Result.js";
|
|
4
|
-
import { SqliteBoolean, SqliteQueryOptions, SqliteValue } from "../Sqlite.js";
|
|
5
|
-
import { AnyType,
|
|
4
|
+
import { SqliteBoolean, SqliteDep, SqliteError, SqliteQueryOptions, SqliteValue } from "../Sqlite.js";
|
|
5
|
+
import { AnyType, DateIso, IdBytes, InferErrors, InferInput, InferType, MergeObjectTypeErrors, NullableToOptionalProps, ObjectType, OptionalType, TableId, Type, ValidMutationSize, ValidMutationSizeError } from "../Type.js";
|
|
6
6
|
import { Simplify } from "../Types.js";
|
|
7
|
-
import {
|
|
8
|
-
import { DbIndexesBuilder } from "./Kysely.js";
|
|
9
|
-
import { BinaryId } from "./Protocol.js";
|
|
7
|
+
import { OwnerId } from "./Owner.js";
|
|
10
8
|
import { Query, Row } from "./Query.js";
|
|
11
|
-
import {
|
|
9
|
+
import { DbChange } from "./Storage.js";
|
|
10
|
+
import { TimestampBytes } from "./Timestamp.js";
|
|
12
11
|
/**
|
|
13
12
|
* Defines the schema of an Evolu database.
|
|
14
13
|
*
|
|
@@ -43,7 +42,7 @@ import { BinaryTimestamp } from "./Timestamp.js";
|
|
|
43
42
|
* };
|
|
44
43
|
* ```
|
|
45
44
|
*/
|
|
46
|
-
export type EvoluSchema = ReadonlyRecord<string, ReadonlyRecord<string, Type<any, any, any, any, any>>>;
|
|
45
|
+
export type EvoluSchema = ReadonlyRecord<string, ReadonlyRecord<string, Type<any, any, any, any, any, any>>>;
|
|
47
46
|
/**
|
|
48
47
|
* Validates an {@link EvoluSchema} at compile time, returning the first error
|
|
49
48
|
* found as a readable string literal type. This approach provides much clearer
|
|
@@ -59,25 +58,26 @@ export type EvoluSchema = ReadonlyRecord<string, ReadonlyRecord<string, Type<any
|
|
|
59
58
|
*/
|
|
60
59
|
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>;
|
|
61
60
|
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;
|
|
62
|
-
export type ValidateIdColumnType<S extends EvoluSchema> = keyof S extends infer TableName ? TableName extends keyof S ? "id" extends keyof S[TableName] ? S[TableName]["id"] extends
|
|
61
|
+
export type ValidateIdColumnType<S extends EvoluSchema> = keyof S extends infer TableName ? TableName extends keyof S ? "id" extends keyof S[TableName] ? S[TableName]["id"] extends TableId<any> ? never : SchemaValidationError<`Table "${TableName & string}" id column must be a branded ID type (created with id("${TableName & string}")).`> : never : never : never;
|
|
63
62
|
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;
|
|
64
63
|
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;
|
|
65
64
|
/** Schema validation error that shows clear, readable messages */
|
|
66
65
|
export type SchemaValidationError<Message extends string> = `❌ Schema Error: ${Message}`;
|
|
67
|
-
export
|
|
68
|
-
export
|
|
66
|
+
export type IndexesConfig = (create: (indexName: string) => Kysely.CreateIndexBuilder) => ReadonlyArray<Kysely.CreateIndexBuilder<any>>;
|
|
67
|
+
export declare const evoluSchemaToDbSchema: (schema: EvoluSchema, indexesConfig?: IndexesConfig) => DbSchema;
|
|
68
|
+
export type CreateQuery<S extends EvoluSchema> = <R extends Row>(queryCallback: (db: Pick<Kysely.Kysely<{
|
|
69
69
|
[Table in keyof S]: {
|
|
70
70
|
readonly [Column in keyof S[Table]]: Column extends "id" | "createdAt" | "updatedAt" ? InferType<S[Table][Column]> : InferType<S[Table][Column]> | null;
|
|
71
71
|
} & DefaultColumns;
|
|
72
72
|
} & {
|
|
73
73
|
readonly evolu_history: {
|
|
74
|
-
readonly timestamp:
|
|
74
|
+
readonly timestamp: TimestampBytes;
|
|
75
75
|
readonly table: keyof S;
|
|
76
|
-
readonly id:
|
|
76
|
+
readonly id: IdBytes;
|
|
77
77
|
readonly column: string;
|
|
78
78
|
readonly value: SqliteValue;
|
|
79
79
|
};
|
|
80
|
-
}>, "selectFrom" | "fn" | "with" | "withRecursive">) => SelectQueryBuilder<any, any, R>, options?: SqliteQueryOptions) => Query<Simplify<R>>;
|
|
80
|
+
}>, "selectFrom" | "fn" | "with" | "withRecursive">) => Kysely.SelectQueryBuilder<any, any, R>, options?: SqliteQueryOptions) => Query<Simplify<R>>;
|
|
81
81
|
/**
|
|
82
82
|
* Default columns automatically added to all tables.
|
|
83
83
|
*
|
|
@@ -89,9 +89,9 @@ export type CreateQuery<S extends EvoluSchema> = <R extends Row>(queryCallback:
|
|
|
89
89
|
* - `isDeleted`: Soft delete flag.
|
|
90
90
|
*/
|
|
91
91
|
export declare const DefaultColumns: ObjectType<{
|
|
92
|
-
createdAt: BrandType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "DateIso", import("../Type.js").
|
|
93
|
-
updatedAt: BrandType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "DateIso", import("../Type.js").
|
|
94
|
-
isDeleted: import("../Type.js").UnionType<[Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").
|
|
92
|
+
createdAt: import("../Type.js").BrandType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "DateIso", import("../Type.js").DateIsoError, import("../Type.js").StringError>;
|
|
93
|
+
updatedAt: import("../Type.js").BrandType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "DateIso", import("../Type.js").DateIsoError, import("../Type.js").StringError>;
|
|
94
|
+
isDeleted: import("../Type.js").UnionType<[Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").UnionType<[import("../Type.js").LiteralType<0>, import("../Type.js").LiteralType<1>]>]>;
|
|
95
95
|
}>;
|
|
96
96
|
export type DefaultColumns = typeof DefaultColumns.Type;
|
|
97
97
|
export type MutationKind = "insert" | "update" | "upsert";
|
|
@@ -100,7 +100,46 @@ export type Mutation<S extends EvoluSchema, Kind extends MutationKind> = <TableN
|
|
|
100
100
|
}, ValidMutationSizeError | MergeObjectTypeErrors<ObjectType<MutationMapping<S[TableName], Kind>>>>;
|
|
101
101
|
export type MutationMapping<P extends Record<string, AnyType>, M extends MutationKind> = M extends "insert" ? InsertableProps<P> : M extends "update" ? UpdateableProps<P> : UpsertableProps<P>;
|
|
102
102
|
export interface MutationOptions {
|
|
103
|
+
/**
|
|
104
|
+
* Called after the mutation is completed and the local state is updated.
|
|
105
|
+
* Useful for triggering side effects (e.g., notifications, UI updates) after
|
|
106
|
+
* insert, update, or upsert.
|
|
107
|
+
*/
|
|
103
108
|
readonly onComplete?: () => void;
|
|
109
|
+
/**
|
|
110
|
+
* Specifies the owner ID for this mutation. If omitted, the default
|
|
111
|
+
* {@link AppOwner} is used.
|
|
112
|
+
*
|
|
113
|
+
* The owner must be used with `evolu.useOwner()` to enable sync. Mutations
|
|
114
|
+
* with unused owners are stored locally but not synced until the owner is
|
|
115
|
+
* used.
|
|
116
|
+
*
|
|
117
|
+
* ### Example
|
|
118
|
+
*
|
|
119
|
+
* ```ts
|
|
120
|
+
* // Partition your own data by project (derived from your AppOwner)
|
|
121
|
+
* const projectOwner = deriveShardOwner(appOwner, [
|
|
122
|
+
* "project",
|
|
123
|
+
* projectId,
|
|
124
|
+
* ]);
|
|
125
|
+
* evolu.insert(
|
|
126
|
+
* "task",
|
|
127
|
+
* { title: "Task 1" },
|
|
128
|
+
* { ownerId: projectOwner.id },
|
|
129
|
+
* );
|
|
130
|
+
*
|
|
131
|
+
* // Collaborative data (independent owner shared with others)
|
|
132
|
+
* const sharedOwner = createSharedOwner(sharedSecret);
|
|
133
|
+
* evolu.insert(
|
|
134
|
+
* "comment",
|
|
135
|
+
* { text: "Hello" },
|
|
136
|
+
* { ownerId: sharedOwner.id },
|
|
137
|
+
* );
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* @experimental
|
|
141
|
+
*/
|
|
142
|
+
readonly ownerId?: OwnerId;
|
|
104
143
|
/**
|
|
105
144
|
* Only validate, don't mutate.
|
|
106
145
|
*
|
|
@@ -109,17 +148,10 @@ export interface MutationOptions {
|
|
|
109
148
|
*/
|
|
110
149
|
readonly onlyValidate?: boolean;
|
|
111
150
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
* measured via MessagePack. Evolu Protocol DbChange will be smaller thanks to
|
|
116
|
-
* various optimizations.
|
|
117
|
-
*/
|
|
118
|
-
export declare const maxMutationSize = 655360;
|
|
119
|
-
export interface ValidMutationSizeError extends TypeError<"ValidMutationSize"> {
|
|
151
|
+
export interface MutationChange extends DbChange {
|
|
152
|
+
/** Owner of the change. If undefined, the change belongs to the AppOwner. */
|
|
153
|
+
readonly ownerId?: OwnerId | undefined;
|
|
120
154
|
}
|
|
121
|
-
export declare const formatValidMutationSizeError: import("../Type.js").TypeErrorFormatter<ValidMutationSizeError>;
|
|
122
|
-
export type ValidMutationSize<Props extends Record<string, AnyType>> = BrandType<ObjectType<Props>, "ValidMutationSize", ValidMutationSizeError, InferErrors<ObjectType<Props>>>;
|
|
123
155
|
/**
|
|
124
156
|
* Type Factory to create insertable {@link Type}. It makes nullable Types
|
|
125
157
|
* optional, omits Id, and ensures the {@link maxMutationSize}.
|
|
@@ -193,4 +225,33 @@ export type InferMutationTypeErrors<T extends Record<string, AnyType>> = InferCo
|
|
|
193
225
|
export type InferColumnErrors<T extends Record<string, AnyType>, M extends MutationKind> = {
|
|
194
226
|
[Column in keyof MutationMapping<T, M>]: InferErrors<MutationMapping<T, M>[Column]>;
|
|
195
227
|
}[keyof MutationMapping<T, M>];
|
|
228
|
+
export declare const DbTable: ObjectType<{
|
|
229
|
+
name: Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
230
|
+
columns: import("../Type.js").ArrayType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>>;
|
|
231
|
+
}>;
|
|
232
|
+
export type DbTable = typeof DbTable.Type;
|
|
233
|
+
export declare const DbIndex: ObjectType<{
|
|
234
|
+
name: Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
235
|
+
sql: Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
236
|
+
}>;
|
|
237
|
+
export type DbIndex = typeof DbIndex.Type;
|
|
238
|
+
export declare const DbSchema: ObjectType<{
|
|
239
|
+
tables: import("../Type.js").ArrayType<ObjectType<{
|
|
240
|
+
name: Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
241
|
+
columns: import("../Type.js").ArrayType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>>;
|
|
242
|
+
}>>;
|
|
243
|
+
indexes: import("../Type.js").ArrayType<ObjectType<{
|
|
244
|
+
name: Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
245
|
+
sql: Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
|
|
246
|
+
}>>;
|
|
247
|
+
}>;
|
|
248
|
+
export type DbSchema = typeof DbSchema.Type;
|
|
249
|
+
/** Get the current database schema by reading SQLite metadata. */
|
|
250
|
+
export declare const getDbSchema: (deps: SqliteDep) => ({ allIndexes }?: {
|
|
251
|
+
allIndexes?: boolean;
|
|
252
|
+
}) => Result<DbSchema, SqliteError>;
|
|
253
|
+
export declare const ensureDbSchema: (deps: SqliteDep) => (newSchema: DbSchema, currentSchema: DbSchema, options?: {
|
|
254
|
+
ignoreIndexes: boolean;
|
|
255
|
+
}) => Result<void, SqliteError>;
|
|
256
|
+
export declare const kysely: Kysely.Kysely<unknown>;
|
|
196
257
|
//# sourceMappingURL=Schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Schema.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAA8B,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAM,MAAM,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAGL,aAAa,EACb,SAAS,EACT,WAAW,EAEX,kBAAkB,EAClB,WAAW,EACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,OAAO,EAEP,OAAO,EACP,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EAET,qBAAqB,EAErB,uBAAuB,EAGvB,UAAU,EAGV,YAAY,EAEZ,OAAO,EACP,IAAI,EACJ,iBAAiB,EAEjB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAY,OAAO,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAe,QAAQ,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,MAAM,WAAW,GAAG,cAAc,CACtC,MAAM,EAEN,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAC3D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,WAAW,IAC9C,mBAAmB,CAAC,CAAC,CAAC,SAAS,KAAK,GAChC,oBAAoB,CAAC,CAAC,CAAC,SAAS,KAAK,GACnC,wBAAwB,CAAC,CAAC,CAAC,SAAS,KAAK,GACvC,mBAAmB,CAAC,CAAC,CAAC,SAAS,KAAK,GAClC,CAAC,GACD,mBAAmB,CAAC,CAAC,CAAC,GACxB,wBAAwB,CAAC,CAAC,CAAC,GAC7B,oBAAoB,CAAC,CAAC,CAAC,GACzB,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAE7B,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,WAAW,IACnD,MAAM,CAAC,SAAS,MAAM,SAAS,GAC3B,SAAS,SAAS,MAAM,CAAC,GACvB,IAAI,SAAS,MAAM,CAAC,CAAC,SAAS,CAAC,GAC7B,KAAK,GACL,qBAAqB,CAAC,UAAU,SAAS,GAAG,MAAM,kCAAkC,CAAC,GACvF,KAAK,GACP,KAAK,CAAC;AAEZ,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,WAAW,IACpD,MAAM,CAAC,SAAS,MAAM,SAAS,GAC3B,SAAS,SAAS,MAAM,CAAC,GACvB,IAAI,SAAS,MAAM,CAAC,CAAC,SAAS,CAAC,GAC7B,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,GACrC,KAAK,GACL,qBAAqB,CAAC,UAAU,SAAS,GAAG,MAAM,2DAA2D,SAAS,GAAG,MAAM,MAAM,CAAC,GACxI,KAAK,GACP,KAAK,GACP,KAAK,CAAC;AAEZ,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,WAAW,IACxD,MAAM,CAAC,SAAS,MAAM,SAAS,GAC3B,SAAS,SAAS,MAAM,CAAC,GACvB,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,MAAM,UAAU,GACzC,UAAU,SAAS,MAAM,CAAC,CAAC,SAAS,CAAC,GACnC,UAAU,SAAS,WAAW,GAAG,WAAW,GAAG,WAAW,GACxD,qBAAqB,CAAC,UAAU,SAAS,GAAG,MAAM,+BAA+B,UAAU,GAAG,MAAM,+EAA+E,CAAC,GACpL,KAAK,GACP,KAAK,GACP,KAAK,GACP,KAAK,GACP,KAAK,CAAC;AAEZ,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,WAAW,IACnD,MAAM,CAAC,SAAS,MAAM,SAAS,GAC3B,SAAS,SAAS,MAAM,CAAC,GACvB,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,MAAM,UAAU,GACzC,UAAU,SAAS,MAAM,CAAC,CAAC,SAAS,CAAC,GACnC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,SAAS,WAAW,GACrD,KAAK,GACL,qBAAqB,CAAC,UAAU,SAAS,GAAG,MAAM,aAAa,UAAU,GAAG,MAAM,mHAAmH,CAAC,GACxM,KAAK,GACP,KAAK,GACP,KAAK,GACP,KAAK,CAAC;AAEZ,kEAAkE;AAClE,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,IACtD,mBAAmB,OAAO,EAAE,CAAC;AAE/B,MAAM,MAAM,aAAa,GAAG,CAC1B,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,kBAAkB,KACrD,aAAa,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;AAEnD,eAAO,MAAM,qBAAqB,GAChC,QAAQ,WAAW,EACnB,gBAAgB,aAAa,KAC5B,QAkBF,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,SAAS,GAAG,EAC7D,aAAa,EAAE,CACb,EAAE,EAAE,IAAI,CACN,MAAM,CAAC,MAAM,CACX;KACG,KAAK,IAAI,MAAM,CAAC,GAAG;QAClB,QAAQ,EAAE,MAAM,IAAI,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,MAAM,SACvC,IAAI,GACJ,WAAW,GACX,WAAW,GACX,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAC3B,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI;KACvC,GAAG,cAAc;CACnB,GAAG;IACF,QAAQ,CAAC,aAAa,EAAE;QACtB,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;QACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACxB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;KAC7B,CAAC;CACH,CACF,EACD,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,eAAe,CAC/C,KACE,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAC3C,OAAO,CAAC,EAAE,kBAAkB,KACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAExB;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc;;;;EAIzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1D,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,SAAS,YAAY,IAAI,CACvE,SAAS,SAAS,MAAM,CAAC,EAEzB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAClE,OAAO,CAAC,EAAE,eAAe,KACtB,MAAM,CACT;IAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAA;CAAE,EACzC,sBAAsB,GACtB,qBAAqB,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CACzE,CAAC;AAEF,MAAM,MAAM,eAAe,CACzB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,SAAS,YAAY,IACpB,CAAC,SAAS,QAAQ,GAClB,eAAe,CAAC,CAAC,CAAC,GAClB,CAAC,SAAS,QAAQ,GAChB,eAAe,CAAC,CAAC,CAAC,GAClB,eAAe,CAAC,CAAC,CAAC,CAAC;AAEzB,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IAEjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,cAAe,SAAQ,QAAQ;IAC9C,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,OAAO,KAAK,KACX,iBAAiB,CAAC,eAAe,CAAC,KAAK,CAAC,CAI1C,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,CACvE,uBAAuB,CAAC,KAAK,CAAC,EAC9B,IAAI,CACL,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,UAAU,CACxE,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CACnC,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,OAAO,KAAK,KACX,iBAAiB,CAAC,eAAe,CAAC,KAAK,CAAC,CAM1C,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KAClE,CAAC,IAAI,MAAM,KAAK,GAAG,CAAC,SAAS,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CACvE,GAAG;IAAE,SAAS,EAAE,YAAY,CAAC,OAAO,aAAa,CAAC,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,UAAU,CACxE,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CACnC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,OAAO,KAAK,KACX,iBAAiB,CAAC,eAAe,CAAC,KAAK,CAAC,CAO1C,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D,uBAAuB,CACrB,KAAK,GAAG;IACN,SAAS,EAAE,YAAY,CAAC,OAAO,OAAO,CAAC,CAAC;IACxC,SAAS,EAAE,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;CAC/C,CACF,CAAC;AAEJ,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,UAAU,CACxE,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CACnC,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,WAAW,IAAI;KACxD,KAAK,IAAI,MAAM,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;CACtD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACjE,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC,GAC9B,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC,GAC9B,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAEnC,MAAM,MAAM,iBAAiB,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,SAAS,YAAY,IACpB;KACD,MAAM,IAAI,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW,CAClD,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAC9B;CACF,CAAC,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAE/B,eAAO,MAAM,OAAO;;;EAGlB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAC;AAE1C,eAAO,MAAM,OAAO;;;EAAwC,CAAC;AAC7D,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAC;AAE1C,eAAO,MAAM,QAAQ;;;;;;;;;EAGnB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAC;AAE5C,kEAAkE;AAClE,eAAO,MAAM,WAAW,GACrB,MAAM,SAAS,MACf,iBAAwB;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,KAAG,MAAM,CAC7D,QAAQ,EACR,WAAW,CA4DZ,CAAC;AAKJ,eAAO,MAAM,cAAc,GACxB,MAAM,SAAS,MAEd,WAAW,QAAQ,EACnB,eAAe,QAAQ,EACvB,UAAU;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,KACnC,MAAM,CAAC,IAAI,EAAE,WAAW,CAuD1B,CAAC;AAsBJ,eAAO,MAAM,MAAM,wBASjB,CAAC"}
|
package/dist/src/Evolu/Schema.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { assert } from "../Assert.js";
|
|
1
|
+
import * as Kysely from "kysely";
|
|
3
2
|
import { mapObject, objectToEntries } from "../Object.js";
|
|
4
|
-
import {
|
|
5
|
-
import { SqliteBoolean } from "../Sqlite.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import { createIndexes } from "./Kysely.js";
|
|
9
|
-
export const evoluSchemaToDbSchema = (schema, indexes) => {
|
|
3
|
+
import { ok } from "../Result.js";
|
|
4
|
+
import { sql, SqliteBoolean, } from "../Sqlite.js";
|
|
5
|
+
import { array, DateIso, nullableToOptional, nullOr, object, omit, optional, String, validMutationSize, } from "../Type.js";
|
|
6
|
+
export const evoluSchemaToDbSchema = (schema, indexesConfig) => {
|
|
10
7
|
const tables = objectToEntries(schema).map(([tableName, table]) => ({
|
|
11
8
|
name: tableName,
|
|
12
9
|
columns: objectToEntries(table)
|
|
13
10
|
.filter(([k]) => k !== "id")
|
|
14
11
|
.map(([k]) => k),
|
|
15
12
|
}));
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
const indexes = indexesConfig
|
|
14
|
+
? indexesConfig(createIndex).map((index) => ({
|
|
15
|
+
name: index.toOperationNode().name.name,
|
|
16
|
+
sql: index.compile().sql,
|
|
17
|
+
}))
|
|
18
|
+
: [];
|
|
19
|
+
return { tables, indexes };
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* Default columns automatically added to all tables.
|
|
@@ -28,21 +29,10 @@ export const evoluSchemaToDbSchema = (schema, indexes) => {
|
|
|
28
29
|
* - `isDeleted`: Soft delete flag.
|
|
29
30
|
*/
|
|
30
31
|
export const DefaultColumns = object({
|
|
31
|
-
createdAt:
|
|
32
|
-
updatedAt:
|
|
32
|
+
createdAt: DateIso,
|
|
33
|
+
updatedAt: DateIso,
|
|
33
34
|
isDeleted: nullOr(SqliteBoolean),
|
|
34
35
|
});
|
|
35
|
-
/**
|
|
36
|
-
* Evolu has to limit the maximum mutation size. Otherwise, sync couldn't use
|
|
37
|
-
* the {@link maxProtocolMessageRangesSize}. The max size is 640KB in bytes,
|
|
38
|
-
* measured via MessagePack. Evolu Protocol DbChange will be smaller thanks to
|
|
39
|
-
* various optimizations.
|
|
40
|
-
*/
|
|
41
|
-
export const maxMutationSize = 655360;
|
|
42
|
-
const validMutationSize = (type) => brand("ValidMutationSize", type, (value) => pack(value).byteLength <= maxMutationSize
|
|
43
|
-
? ok(value)
|
|
44
|
-
: err({ type: "ValidMutationSize", value }));
|
|
45
|
-
export const formatValidMutationSizeError = createTypeErrorFormatter((error) => `The mutation size exceeds the maximum limit of ${maxMutationSize} bytes. The provided mutation has a size of ${pack(error.value).byteLength} bytes.`);
|
|
46
36
|
/**
|
|
47
37
|
* Type Factory to create insertable {@link Type}. It makes nullable Types
|
|
48
38
|
* optional, omits Id, and ensures the {@link maxMutationSize}.
|
|
@@ -111,3 +101,130 @@ export const upsertable = (props) => {
|
|
|
111
101
|
};
|
|
112
102
|
return validMutationSize(nullableToOptional(propsWithDefaults));
|
|
113
103
|
};
|
|
104
|
+
export const DbTable = object({
|
|
105
|
+
name: String,
|
|
106
|
+
columns: array(String),
|
|
107
|
+
});
|
|
108
|
+
export const DbIndex = object({ name: String, sql: String });
|
|
109
|
+
export const DbSchema = object({
|
|
110
|
+
tables: array(DbTable),
|
|
111
|
+
indexes: array(DbIndex),
|
|
112
|
+
});
|
|
113
|
+
/** Get the current database schema by reading SQLite metadata. */
|
|
114
|
+
export const getDbSchema = (deps) => ({ allIndexes = false } = {}) => {
|
|
115
|
+
const map = new Map();
|
|
116
|
+
const tableAndColumnInfoRows = deps.sqlite.exec(sql `
|
|
117
|
+
select
|
|
118
|
+
sqlite_master.name as tableName,
|
|
119
|
+
table_info.name as columnName
|
|
120
|
+
from
|
|
121
|
+
sqlite_master
|
|
122
|
+
join pragma_table_info(sqlite_master.name) as table_info;
|
|
123
|
+
`);
|
|
124
|
+
if (!tableAndColumnInfoRows.ok)
|
|
125
|
+
return tableAndColumnInfoRows;
|
|
126
|
+
tableAndColumnInfoRows.value.rows.forEach((row) => {
|
|
127
|
+
const { tableName, columnName } = row;
|
|
128
|
+
if (!map.has(tableName))
|
|
129
|
+
map.set(tableName, []);
|
|
130
|
+
map.get(tableName)?.push(columnName);
|
|
131
|
+
});
|
|
132
|
+
const tables = Array.from(map, ([name, columns]) => ({ name, columns }));
|
|
133
|
+
const indexesRows = deps.sqlite.exec(allIndexes
|
|
134
|
+
? sql `
|
|
135
|
+
select name, sql
|
|
136
|
+
from sqlite_master
|
|
137
|
+
where type = 'index' and name not like 'sqlite_%';
|
|
138
|
+
`
|
|
139
|
+
: sql `
|
|
140
|
+
select name, sql
|
|
141
|
+
from sqlite_master
|
|
142
|
+
where
|
|
143
|
+
type = 'index'
|
|
144
|
+
and name not like 'sqlite_%'
|
|
145
|
+
and name not like 'evolu_%';
|
|
146
|
+
`);
|
|
147
|
+
if (!indexesRows.ok)
|
|
148
|
+
return indexesRows;
|
|
149
|
+
const indexes = indexesRows.value.rows.map((row) => ({
|
|
150
|
+
name: row.name,
|
|
151
|
+
/**
|
|
152
|
+
* SQLite returns "CREATE INDEX" for "create index" for some reason.
|
|
153
|
+
* Other keywords remain unchanged. We have to normalize the casing for
|
|
154
|
+
* {@link indexesAreEqual} manually.
|
|
155
|
+
*/
|
|
156
|
+
sql: row.sql
|
|
157
|
+
.replace("CREATE INDEX", "create index")
|
|
158
|
+
.replace("CREATE UNIQUE INDEX", "create unique index"),
|
|
159
|
+
}));
|
|
160
|
+
return ok({ tables, indexes });
|
|
161
|
+
};
|
|
162
|
+
const indexesAreEqual = (self, that) => self.name === that.name && self.sql === that.sql;
|
|
163
|
+
export const ensureDbSchema = (deps) => (newSchema, currentSchema, options) => {
|
|
164
|
+
const queries = [];
|
|
165
|
+
newSchema.tables.forEach((newTable) => {
|
|
166
|
+
const currentTable = currentSchema.tables.find((t) => t.name === newTable.name);
|
|
167
|
+
if (!currentTable) {
|
|
168
|
+
queries.push({
|
|
169
|
+
sql: createTableWithDefaultColumns(newTable.name, newTable.columns),
|
|
170
|
+
parameters: [],
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
newTable.columns
|
|
175
|
+
.filter((newColumn) => !currentTable.columns.includes(newColumn))
|
|
176
|
+
.forEach((newColumn) => {
|
|
177
|
+
queries.push(sql `
|
|
178
|
+
alter table ${sql.identifier(newTable.name)}
|
|
179
|
+
add column ${sql.identifier(newColumn)} blob;
|
|
180
|
+
`);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
if (options?.ignoreIndexes !== true) {
|
|
185
|
+
// Remove current indexes that are not in the newSchema.
|
|
186
|
+
currentSchema.indexes
|
|
187
|
+
.filter((currentIndex) => !newSchema.indexes.some((newIndex) => indexesAreEqual(newIndex, currentIndex)))
|
|
188
|
+
.forEach((index) => {
|
|
189
|
+
queries.push(sql `drop index ${sql.identifier(index.name)};`);
|
|
190
|
+
});
|
|
191
|
+
// Add new indexes that are not in the currentSchema.
|
|
192
|
+
newSchema.indexes
|
|
193
|
+
.filter((newIndex) => !currentSchema.indexes.some((currentIndex) => indexesAreEqual(newIndex, currentIndex)))
|
|
194
|
+
.forEach((newIndex) => {
|
|
195
|
+
queries.push({ sql: `${newIndex.sql};`, parameters: [] });
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
for (const query of queries) {
|
|
199
|
+
const result = deps.sqlite.exec(query);
|
|
200
|
+
if (!result.ok)
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
return ok();
|
|
204
|
+
};
|
|
205
|
+
const createTableWithDefaultColumns = (tableName, columns) => `
|
|
206
|
+
create table ${sql.identifier(tableName).sql} (
|
|
207
|
+
"id" text primary key,
|
|
208
|
+
${columns
|
|
209
|
+
// Add default columns.
|
|
210
|
+
.concat(["createdAt", "updatedAt", "isDeleted"])
|
|
211
|
+
.filter((c) => c !== "id")
|
|
212
|
+
// "A column with affinity BLOB does not prefer one storage class over another
|
|
213
|
+
// and no attempt is made to coerce data from one storage class into another."
|
|
214
|
+
// https://www.sqlite.org/datatype3.html
|
|
215
|
+
.map((name) => `${sql.identifier(name).sql} blob`)
|
|
216
|
+
.join(", ")}
|
|
217
|
+
);
|
|
218
|
+
`;
|
|
219
|
+
// https://kysely.dev/docs/recipes/splitting-query-building-and-execution
|
|
220
|
+
export const kysely = new Kysely.Kysely({
|
|
221
|
+
dialect: {
|
|
222
|
+
createAdapter: () => new Kysely.SqliteAdapter(),
|
|
223
|
+
createDriver: () => new Kysely.DummyDriver(),
|
|
224
|
+
createIntrospector() {
|
|
225
|
+
throw new Error("Not implemeneted");
|
|
226
|
+
},
|
|
227
|
+
createQueryCompiler: () => new Kysely.SqliteQueryCompiler(),
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
const createIndex = kysely.schema.createIndex.bind(kysely.schema);
|