@evolu/common 6.0.1-preview.2 → 6.0.1-preview.21

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.
Files changed (154) hide show
  1. package/dist/src/Assert.d.ts +6 -3
  2. package/dist/src/Assert.d.ts.map +1 -1
  3. package/dist/src/Assert.js +7 -4
  4. package/dist/src/Brand.d.ts +75 -0
  5. package/dist/src/Brand.d.ts.map +1 -0
  6. package/dist/src/Brand.js +1 -0
  7. package/dist/src/Buffer.d.ts +1 -1
  8. package/dist/src/Buffer.d.ts.map +1 -1
  9. package/dist/src/Buffer.js +1 -1
  10. package/dist/src/CallbackRegistry.d.ts +53 -0
  11. package/dist/src/CallbackRegistry.d.ts.map +1 -0
  12. package/dist/src/CallbackRegistry.js +25 -0
  13. package/dist/src/Console.d.ts +31 -6
  14. package/dist/src/Console.d.ts.map +1 -1
  15. package/dist/src/Console.js +72 -9
  16. package/dist/src/Crypto.d.ts +61 -34
  17. package/dist/src/Crypto.d.ts.map +1 -1
  18. package/dist/src/Crypto.js +29 -42
  19. package/dist/src/Evolu/Db.d.ts +159 -66
  20. package/dist/src/Evolu/Db.d.ts.map +1 -1
  21. package/dist/src/Evolu/Db.js +300 -705
  22. package/dist/src/Evolu/Diff.d.ts +3 -3
  23. package/dist/src/Evolu/Diff.d.ts.map +1 -1
  24. package/dist/src/Evolu/Diff.js +7 -5
  25. package/dist/src/Evolu/Evolu.d.ts +200 -115
  26. package/dist/src/Evolu/Evolu.d.ts.map +1 -1
  27. package/dist/src/Evolu/Evolu.js +287 -157
  28. package/dist/src/Evolu/Internal.d.ts +0 -2
  29. package/dist/src/Evolu/Internal.d.ts.map +1 -1
  30. package/dist/src/Evolu/Internal.js +0 -2
  31. package/dist/src/Evolu/LocalAuth.d.ts +144 -0
  32. package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
  33. package/dist/src/Evolu/LocalAuth.js +171 -0
  34. package/dist/src/Evolu/Owner.d.ts +209 -124
  35. package/dist/src/Evolu/Owner.d.ts.map +1 -1
  36. package/dist/src/Evolu/Owner.js +118 -104
  37. package/dist/src/Evolu/Platform.d.ts +9 -7
  38. package/dist/src/Evolu/Platform.d.ts.map +1 -1
  39. package/dist/src/Evolu/Protocol.d.ts +256 -211
  40. package/dist/src/Evolu/Protocol.d.ts.map +1 -1
  41. package/dist/src/Evolu/Protocol.js +558 -359
  42. package/dist/src/Evolu/Public.d.ts +6 -8
  43. package/dist/src/Evolu/Public.d.ts.map +1 -1
  44. package/dist/src/Evolu/Public.js +2 -3
  45. package/dist/src/Evolu/PublicKysely.js +3 -3
  46. package/dist/src/Evolu/Query.d.ts +2 -1
  47. package/dist/src/Evolu/Query.d.ts.map +1 -1
  48. package/dist/src/Evolu/Relay.d.ts +72 -4
  49. package/dist/src/Evolu/Relay.d.ts.map +1 -1
  50. package/dist/src/Evolu/Relay.js +124 -13
  51. package/dist/src/Evolu/Schema.d.ts +129 -73
  52. package/dist/src/Evolu/Schema.d.ts.map +1 -1
  53. package/dist/src/Evolu/Schema.js +169 -89
  54. package/dist/src/Evolu/Storage.d.ts +159 -14
  55. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  56. package/dist/src/Evolu/Storage.js +42 -32
  57. package/dist/src/Evolu/Sync.d.ts +68 -13
  58. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  59. package/dist/src/Evolu/Sync.js +414 -20
  60. package/dist/src/Evolu/Timestamp.d.ts +35 -27
  61. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  62. package/dist/src/Evolu/Timestamp.js +27 -18
  63. package/dist/src/ManyToManyMap.d.ts +74 -10
  64. package/dist/src/ManyToManyMap.d.ts.map +1 -1
  65. package/dist/src/ManyToManyMap.js +41 -6
  66. package/dist/src/Number.d.ts +2 -1
  67. package/dist/src/Number.d.ts.map +1 -1
  68. package/dist/src/Random.d.ts +3 -2
  69. package/dist/src/Random.d.ts.map +1 -1
  70. package/dist/src/RefCountedResourceManager.d.ts +119 -0
  71. package/dist/src/RefCountedResourceManager.d.ts.map +1 -0
  72. package/dist/src/RefCountedResourceManager.js +197 -0
  73. package/dist/src/Result.d.ts +176 -51
  74. package/dist/src/Result.d.ts.map +1 -1
  75. package/dist/src/Result.js +30 -241
  76. package/dist/src/Sqlite.d.ts +21 -4
  77. package/dist/src/Sqlite.d.ts.map +1 -1
  78. package/dist/src/Sqlite.js +50 -8
  79. package/dist/src/Task.d.ts +511 -0
  80. package/dist/src/Task.d.ts.map +1 -0
  81. package/dist/src/Task.js +410 -0
  82. package/dist/src/Time.d.ts +59 -0
  83. package/dist/src/Time.d.ts.map +1 -1
  84. package/dist/src/Time.js +87 -4
  85. package/dist/src/Type.d.ts +474 -327
  86. package/dist/src/Type.d.ts.map +1 -1
  87. package/dist/src/Type.js +502 -436
  88. package/dist/src/Types.d.ts +0 -74
  89. package/dist/src/Types.d.ts.map +1 -1
  90. package/dist/src/WebSocket.d.ts +5 -2
  91. package/dist/src/WebSocket.d.ts.map +1 -1
  92. package/dist/src/WebSocket.js +12 -13
  93. package/dist/src/Worker.d.ts +39 -11
  94. package/dist/src/Worker.d.ts.map +1 -1
  95. package/dist/src/Worker.js +22 -4
  96. package/dist/src/index.d.ts +3 -3
  97. package/dist/src/index.d.ts.map +1 -1
  98. package/dist/src/index.js +3 -3
  99. package/package.json +14 -13
  100. package/src/Assert.ts +8 -7
  101. package/src/Brand.ts +75 -0
  102. package/src/Buffer.ts +1 -1
  103. package/src/CallbackRegistry.ts +84 -0
  104. package/src/Console.ts +91 -11
  105. package/src/Crypto.ts +94 -79
  106. package/src/Evolu/Db.ts +528 -1027
  107. package/src/Evolu/Diff.ts +7 -5
  108. package/src/Evolu/Evolu.ts +682 -329
  109. package/src/Evolu/Internal.ts +0 -2
  110. package/src/Evolu/LocalAuth.ts +422 -0
  111. package/src/Evolu/Owner.ts +282 -227
  112. package/src/Evolu/Platform.ts +9 -9
  113. package/src/Evolu/Protocol.ts +788 -640
  114. package/src/Evolu/Public.ts +7 -14
  115. package/src/Evolu/PublicKysely.ts +3 -3
  116. package/src/Evolu/Query.ts +2 -1
  117. package/src/Evolu/Relay.ts +238 -18
  118. package/src/Evolu/Schema.ts +391 -191
  119. package/src/Evolu/Storage.ts +275 -55
  120. package/src/Evolu/Sync.ts +708 -37
  121. package/src/Evolu/Timestamp.ts +38 -35
  122. package/src/ManyToManyMap.ts +127 -24
  123. package/src/Number.ts +2 -6
  124. package/src/Random.ts +3 -2
  125. package/src/RefCountedResourceManager.ts +368 -0
  126. package/src/Result.ts +183 -53
  127. package/src/Sqlite.ts +59 -23
  128. package/src/Task.ts +779 -0
  129. package/src/Time.ts +168 -4
  130. package/src/Type.ts +708 -660
  131. package/src/Types.ts +0 -76
  132. package/src/WebSocket.ts +23 -17
  133. package/src/Worker.ts +72 -23
  134. package/src/index.ts +3 -3
  135. package/dist/src/Callbacks.d.ts +0 -20
  136. package/dist/src/Callbacks.d.ts.map +0 -1
  137. package/dist/src/Callbacks.js +0 -18
  138. package/dist/src/Evolu/Config.d.ts +0 -69
  139. package/dist/src/Evolu/Config.d.ts.map +0 -1
  140. package/dist/src/Evolu/Config.js +0 -9
  141. package/dist/src/Evolu/Kysely.d.ts +0 -6
  142. package/dist/src/Evolu/Kysely.d.ts.map +0 -1
  143. package/dist/src/Evolu/Kysely.js +0 -21
  144. package/dist/src/NanoId.d.ts +0 -27
  145. package/dist/src/NanoId.d.ts.map +0 -1
  146. package/dist/src/NanoId.js +0 -6
  147. package/dist/src/Promise.d.ts +0 -180
  148. package/dist/src/Promise.d.ts.map +0 -1
  149. package/dist/src/Promise.js +0 -176
  150. package/src/Callbacks.ts +0 -43
  151. package/src/Evolu/Config.ts +0 -83
  152. package/src/Evolu/Kysely.ts +0 -38
  153. package/src/NanoId.ts +0 -39
  154. package/src/Promise.ts +0 -295
@@ -1,24 +1,16 @@
1
- import { Kysely, SelectQueryBuilder } from "kysely";
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, BrandType, InferErrors, InferInput, InferType, MergeObjectTypeErrors, NullableToOptionalProps, ObjectType, OptionalType, Type, TypeError } from "../Type.js";
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 { DbSchema } from "./Db.js";
8
- import { DbIndexesBuilder } from "./Kysely.js";
9
- import { ShardOwner, SharedOwner } from "./Owner.js";
10
- import { BinaryId } from "./Protocol.js";
7
+ import { OwnerId } from "./Owner.js";
11
8
  import { Query, Row } from "./Query.js";
12
- import { BinaryTimestamp } from "./Timestamp.js";
9
+ import { DbChange } from "./Storage.js";
10
+ import { TimestampBytes } from "./Timestamp.js";
13
11
  /**
14
12
  * Defines the schema of an Evolu database.
15
13
  *
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
14
  * Table schema defines columns that are required for table rows. For not
23
15
  * required columns, use {@link nullOr}.
24
16
  *
@@ -50,64 +42,104 @@ import { BinaryTimestamp } from "./Timestamp.js";
50
42
  * };
51
43
  * ```
52
44
  */
53
- export type EvoluSchema = ReadonlyRecord<string, ReadonlyRecord<string, Type<any, any, any, any, any>> & {
54
- readonly id: Type<any, any, any, any, any>;
55
- }>;
56
- export type CreateQuery<S extends EvoluSchema> = <R extends Row>(queryCallback: (db: Pick<Kysely<{
45
+ export type EvoluSchema = ReadonlyRecord<string, ReadonlyRecord<string, Type<any, any, any, any, any, any>>>;
46
+ /**
47
+ * Validates an {@link EvoluSchema} at compile time, returning the first error
48
+ * found as a readable string literal type. This approach provides much clearer
49
+ * and more actionable TypeScript errors than the default, which are often hard
50
+ * to read.
51
+ *
52
+ * Validates the following schema requirements:
53
+ *
54
+ * 1. All tables must have an 'id' column
55
+ * 2. The 'id' column must be a branded ID type (created with id() function)
56
+ * 3. Tables cannot use default column names (createdAt, updatedAt, isDeleted)
57
+ * 4. All column types must be compatible with SQLite (extend SqliteValue)
58
+ */
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>;
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;
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;
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;
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;
64
+ /** Schema validation error that shows clear, readable messages */
65
+ export type SchemaValidationError<Message extends string> = `❌ Schema Error: ${Message}`;
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<{
57
69
  [Table in keyof S]: {
58
70
  readonly [Column in keyof S[Table]]: Column extends "id" | "createdAt" | "updatedAt" ? InferType<S[Table][Column]> : InferType<S[Table][Column]> | null;
59
71
  } & DefaultColumns;
60
72
  } & {
61
73
  readonly evolu_history: {
62
- readonly timestamp: BinaryTimestamp;
74
+ readonly timestamp: TimestampBytes;
63
75
  readonly table: keyof S;
64
- readonly row: BinaryId;
76
+ readonly id: IdBytes;
65
77
  readonly column: string;
66
78
  readonly value: SqliteValue;
67
79
  };
68
- }>, "selectFrom" | "fn" | "with" | "withRecursive">) => SelectQueryBuilder<any, any, R>, options?: SqliteQueryOptions) => Query<Simplify<R>>;
69
- export declare const DefaultColumns: ObjectType<{
70
- createdAt: BrandType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "DateIso", import("../Type.js").DateIsoStringError, import("../Type.js").StringError>;
71
- updatedAt: BrandType<Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "DateIso", import("../Type.js").DateIsoStringError, import("../Type.js").StringError>;
72
- 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
- }>;
74
- export type DefaultColumns = typeof DefaultColumns.Type;
80
+ }>, "selectFrom" | "fn" | "with" | "withRecursive">) => Kysely.SelectQueryBuilder<any, any, R>, options?: SqliteQueryOptions) => Query<Simplify<R>>;
75
81
  /**
76
- * Valid {@link EvoluSchema}.
82
+ * Default columns automatically added to all tables.
77
83
  *
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.
84
+ * - `createdAt`: Set by Evolu when `insert` is called, or can be custom with
85
+ * `upsert`.
86
+ * - `updatedAt`: Always set by Evolu, derived from {@link CrdtMessage} timestamp.
87
+ * If you defer sync to avoid leaking time activity, use a custom column to
88
+ * preserve real update time.
89
+ * - `isDeleted`: Soft delete flag.
81
90
  */
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;
91
+ export declare const DefaultColumns: ObjectType<{
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
+ }>;
96
+ export type DefaultColumns = typeof DefaultColumns.Type;
104
97
  export type MutationKind = "insert" | "update" | "upsert";
105
98
  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
99
  readonly id: S[TableName]["id"]["Type"];
107
100
  }, ValidMutationSizeError | MergeObjectTypeErrors<ObjectType<MutationMapping<S[TableName], Kind>>>>;
108
101
  export type MutationMapping<P extends Record<string, AnyType>, M extends MutationKind> = M extends "insert" ? InsertableProps<P> : M extends "update" ? UpdateableProps<P> : UpsertableProps<P>;
109
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
+ */
110
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;
111
143
  /**
112
144
  * Only validate, don't mutate.
113
145
  *
@@ -115,24 +147,11 @@ export interface MutationOptions {
115
147
  * `onlyValidate: true`.
116
148
  */
117
149
  readonly onlyValidate?: boolean;
118
- /**
119
- * The owner to use for this mutation. Can be a {@link ShardOwner} for sharding
120
- * app data or a {@link SharedOwner} for collaborative write access. If
121
- * omitted, defaults to the app's {@link AppOwner}.
122
- */
123
- readonly owner?: ShardOwner | SharedOwner;
124
150
  }
125
- /**
126
- * Evolu has to limit the maximum mutation size. Otherwise, sync couldn't use
127
- * the {@link maxProtocolMessageRangesSize}. The max size is 640KB in bytes,
128
- * measured via MessagePack. Evolu Protocol DbChange will be smaller thanks to
129
- * various optimizations.
130
- */
131
- export declare const maxMutationSize = 655360;
132
- 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;
133
154
  }
134
- export declare const formatValidMutationSizeError: import("../Type.js").TypeErrorFormatter<ValidMutationSizeError>;
135
- export type ValidMutationSize<Props extends Record<string, AnyType>> = BrandType<ObjectType<Props>, "ValidMutationSize", ValidMutationSizeError, InferErrors<ObjectType<Props>>>;
136
155
  /**
137
156
  * Type Factory to create insertable {@link Type}. It makes nullable Types
138
157
  * optional, omits Id, and ensures the {@link maxMutationSize}.
@@ -176,20 +195,28 @@ export type UpdateableProps<Props extends Record<string, AnyType>> = {
176
195
  };
177
196
  export type Updateable<Props extends Record<string, AnyType>> = InferInput<ObjectType<UpdateableProps<Props>>>;
178
197
  /**
179
- * Type Factory to create upsertable Type. It makes nullable Types optional and
180
- * ensures the {@link maxMutationSize}.
198
+ * Type Factory to create upsertable Type. It makes nullable Types optional,
199
+ * includes optional default columns (createdAt, isDeleted), and ensures the
200
+ * {@link maxMutationSize}.
181
201
  *
182
202
  * ### Example
183
203
  *
184
204
  * ```ts
185
205
  * const UpsertableTodo = upsertable(Schema.todo);
186
206
  * type UpsertableTodo = typeof UpsertableTodo.Type;
187
- * const todo = UpsertableTodo.from({ id, title });
207
+ * const todo = UpsertableTodo.from({
208
+ * id,
209
+ * title,
210
+ * createdAt: "2023-01-01T00:00:00.000Z",
211
+ * });
188
212
  * if (!todo.ok) return; // handle errors
189
213
  * ```
190
214
  */
191
215
  export declare const upsertable: <Props extends Record<string, AnyType>>(props: Props) => ValidMutationSize<UpsertableProps<Props>>;
192
- export type UpsertableProps<Props extends Record<string, AnyType>> = NullableToOptionalProps<Props>;
216
+ export type UpsertableProps<Props extends Record<string, AnyType>> = NullableToOptionalProps<Props & {
217
+ createdAt: OptionalType<typeof DateIso>;
218
+ isDeleted: OptionalType<typeof SqliteBoolean>;
219
+ }>;
193
220
  export type Upsertable<Props extends Record<string, AnyType>> = InferInput<ObjectType<UpsertableProps<Props>>>;
194
221
  export type InferEvoluSchemaError<S extends EvoluSchema> = {
195
222
  [Table in keyof S]: InferMutationTypeErrors<S[Table]>;
@@ -198,4 +225,33 @@ export type InferMutationTypeErrors<T extends Record<string, AnyType>> = InferCo
198
225
  export type InferColumnErrors<T extends Record<string, AnyType>, M extends MutationKind> = {
199
226
  [Column in keyof MutationMapping<T, M>]: InferErrors<MutationMapping<T, M>[Column]>;
200
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>;
201
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,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEpD,OAAO,EAA8B,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAW,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EACL,OAAO,EAEP,SAAS,EAKT,WAAW,EACX,UAAU,EACV,SAAS,EACT,qBAAqB,EAErB,uBAAuB,EAGvB,UAAU,EAGV,YAAY,EAEZ,IAAI,EACJ,SAAS,EAEV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAW,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAiB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAY,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAEL,QAAQ,EAET,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,MAAM,WAAW,GAAG,cAAc,CACtC,MAAM,EACN,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG;IACtD,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;CAC5C,CACF,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,SAAS,GAAG,EAC7D,aAAa,EAAE,CACb,EAAE,EAAE,IAAI,CACN,MAAM,CACJ;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,eAAe,CAAC;QACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACxB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;QACvB,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,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EACpC,OAAO,CAAC,EAAE,kBAAkB,KACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAExB,eAAO,MAAM,cAAc;;;;EAIzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAKxD;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;;;;;;4FAyB5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,OAAO,gBAAgB,CAAC,IAAI,CAAC;AAE5D,MAAM,WAAW,qBAAsB,SAAQ,SAAS,CAAC,kBAAkB,CAAC;IAC1E,QAAQ,CAAC,MAAM,EAAE;QACf,IAAI,EAAE,oBAAoB,CAAC;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,gBAOvD,CAAC;AAiCF,eAAO,MAAM,0BAA0B,GACrC,kBAAkB,gBAAgB,EAClC,UAAU,gBAAgB,KACzB,QAaF,CAAC;AAEF,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,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;CAC3C;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,SAAS,CAAC;AAStC,MAAM,WAAW,sBACf,SAAQ,SAAS,CAAC,mBAAmB,CAAC;CAAG;AAE3C,eAAO,MAAM,4BAA4B,iEAItC,CAAC;AAEJ,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACjE,SAAS,CACP,UAAU,CAAC,KAAK,CAAC,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAC/B,CAAC;AAEJ;;;;;;;;;;;;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;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,OAAO,KAAK,KACX,iBAAiB,CAAC,eAAe,CAAC,KAAK,CAAC,CACG,CAAC;AAE/C,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D,uBAAuB,CAAC,KAAK,CAAC,CAAC;AAEjC,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"}
1
+ {"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Schema.ts"],"names":[],"mappings":"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"}
@@ -1,97 +1,38 @@
1
- import { pack } from "msgpackr";
1
+ import * as Kysely from "kysely";
2
2
  import { mapObject, objectToEntries } from "../Object.js";
3
- import { err, ok } from "../Result.js";
4
- import { SqliteBoolean } from "../Sqlite.js";
5
- import { brand, createTypeErrorFormatter, DateIsoString, EvoluType, nullableToOptional, nullOr, object, omit, optional, record, Unknown, } from "../Type.js";
6
- import { createIndexes } from "./Kysely.js";
7
- import { Base64Url256, } from "./Protocol.js";
8
- export const DefaultColumns = object({
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]) => ({
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) => {
7
+ const tables = objectToEntries(schema).map(([tableName, table]) => ({
74
8
  name: tableName,
75
9
  columns: objectToEntries(table)
76
10
  .filter(([k]) => k !== "id")
77
11
  .map(([k]) => k),
78
12
  }));
79
- return {
80
- tables,
81
- indexes: createIndexes(indexes),
82
- };
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 };
83
20
  };
84
21
  /**
85
- * Evolu has to limit the maximum mutation size. Otherwise, sync couldn't use
86
- * the {@link maxProtocolMessageRangesSize}. The max size is 640KB in bytes,
87
- * measured via MessagePack. Evolu Protocol DbChange will be smaller thanks to
88
- * various optimizations.
22
+ * Default columns automatically added to all tables.
23
+ *
24
+ * - `createdAt`: Set by Evolu when `insert` is called, or can be custom with
25
+ * `upsert`.
26
+ * - `updatedAt`: Always set by Evolu, derived from {@link CrdtMessage} timestamp.
27
+ * If you defer sync to avoid leaking time activity, use a custom column to
28
+ * preserve real update time.
29
+ * - `isDeleted`: Soft delete flag.
89
30
  */
90
- export const maxMutationSize = 655360;
91
- const validMutationSize = (type) => brand("ValidMutationSize", type, (value) => pack(value).byteLength <= maxMutationSize
92
- ? ok(value)
93
- : err({ type: "ValidMutationSize", value }));
94
- 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.`);
31
+ export const DefaultColumns = object({
32
+ createdAt: DateIso,
33
+ updatedAt: DateIso,
34
+ isDeleted: nullOr(SqliteBoolean),
35
+ });
95
36
  /**
96
37
  * Type Factory to create insertable {@link Type}. It makes nullable Types
97
38
  * optional, omits Id, and ensures the {@link maxMutationSize}.
@@ -135,16 +76,155 @@ export const updateable = (props) => {
135
76
  return validMutationSize(object(updateableProps));
136
77
  };
137
78
  /**
138
- * Type Factory to create upsertable Type. It makes nullable Types optional and
139
- * ensures the {@link maxMutationSize}.
79
+ * Type Factory to create upsertable Type. It makes nullable Types optional,
80
+ * includes optional default columns (createdAt, isDeleted), and ensures the
81
+ * {@link maxMutationSize}.
140
82
  *
141
83
  * ### Example
142
84
  *
143
85
  * ```ts
144
86
  * const UpsertableTodo = upsertable(Schema.todo);
145
87
  * type UpsertableTodo = typeof UpsertableTodo.Type;
146
- * const todo = UpsertableTodo.from({ id, title });
88
+ * const todo = UpsertableTodo.from({
89
+ * id,
90
+ * title,
91
+ * createdAt: "2023-01-01T00:00:00.000Z",
92
+ * });
147
93
  * if (!todo.ok) return; // handle errors
148
94
  * ```
149
95
  */
150
- export const upsertable = (props) => validMutationSize(nullableToOptional(props));
96
+ export const upsertable = (props) => {
97
+ const propsWithDefaults = {
98
+ ...props,
99
+ createdAt: optional(DateIso),
100
+ isDeleted: optional(SqliteBoolean),
101
+ };
102
+ return validMutationSize(nullableToOptional(propsWithDefaults));
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);