@verdant-web/common 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cjs/EventSubscriber.d.ts +17 -0
- package/dist/cjs/EventSubscriber.js +67 -0
- package/dist/cjs/EventSubscriber.js.map +1 -0
- package/dist/cjs/baseline.d.ts +5 -0
- package/dist/cjs/baseline.js +3 -0
- package/dist/cjs/baseline.js.map +1 -0
- package/dist/cjs/batching.d.ts +41 -0
- package/dist/cjs/batching.js +89 -0
- package/dist/cjs/batching.js.map +1 -0
- package/dist/cjs/files.d.ts +19 -0
- package/dist/cjs/files.js +19 -0
- package/dist/cjs/files.js.map +1 -0
- package/dist/cjs/files.test.d.ts +1 -0
- package/dist/cjs/files.test.js +81 -0
- package/dist/cjs/files.test.js.map +1 -0
- package/dist/cjs/index.d.ts +18 -0
- package/dist/cjs/index.js +36 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/indexes.d.ts +14 -0
- package/dist/cjs/indexes.js +116 -0
- package/dist/cjs/indexes.js.map +1 -0
- package/dist/cjs/indexes.test.d.ts +1 -0
- package/dist/cjs/indexes.test.js +128 -0
- package/dist/cjs/indexes.test.js.map +1 -0
- package/dist/cjs/migration.d.ts +98 -0
- package/dist/cjs/migration.js +128 -0
- package/dist/cjs/migration.js.map +1 -0
- package/dist/cjs/oids.d.ts +87 -0
- package/dist/cjs/oids.js +375 -0
- package/dist/cjs/oids.js.map +1 -0
- package/dist/cjs/oids.test.d.ts +1 -0
- package/dist/cjs/oids.test.js +282 -0
- package/dist/cjs/oids.test.js.map +1 -0
- package/dist/cjs/operation.d.ts +139 -0
- package/dist/cjs/operation.js +533 -0
- package/dist/cjs/operation.js.map +1 -0
- package/dist/cjs/operation.test.d.ts +1 -0
- package/dist/cjs/operation.test.js +827 -0
- package/dist/cjs/operation.test.js.map +1 -0
- package/dist/cjs/patch.d.ts +26 -0
- package/dist/cjs/patch.js +227 -0
- package/dist/cjs/patch.js.map +1 -0
- package/dist/cjs/presence.d.ts +27 -0
- package/dist/cjs/presence.js +3 -0
- package/dist/cjs/presence.js.map +1 -0
- package/dist/cjs/protocol.d.ts +145 -0
- package/dist/cjs/protocol.js +4 -0
- package/dist/cjs/protocol.js.map +1 -0
- package/dist/cjs/refs.d.ts +5 -0
- package/dist/cjs/refs.js +22 -0
- package/dist/cjs/refs.js.map +1 -0
- package/dist/cjs/replica.d.ts +28 -0
- package/dist/cjs/replica.js +29 -0
- package/dist/cjs/replica.js.map +1 -0
- package/dist/cjs/schema/defaults.d.ts +4 -0
- package/dist/cjs/schema/defaults.js +72 -0
- package/dist/cjs/schema/defaults.js.map +1 -0
- package/dist/cjs/schema/defaults.test.d.ts +1 -0
- package/dist/cjs/schema/defaults.test.js +21 -0
- package/dist/cjs/schema/defaults.test.js.map +1 -0
- package/dist/cjs/schema/index.d.ts +8 -0
- package/dist/cjs/schema/index.js +29 -0
- package/dist/cjs/schema/index.js.map +1 -0
- package/dist/cjs/schema/indexFilters.d.ts +6 -0
- package/dist/cjs/schema/indexFilters.js +31 -0
- package/dist/cjs/schema/indexFilters.js.map +1 -0
- package/dist/cjs/schema/types/collection.d.ts +51 -0
- package/dist/cjs/schema/types/collection.js +3 -0
- package/dist/cjs/schema/types/collection.js.map +1 -0
- package/dist/cjs/schema/types/compounds.d.ts +12 -0
- package/dist/cjs/schema/types/compounds.js +3 -0
- package/dist/cjs/schema/types/compounds.js.map +1 -0
- package/dist/cjs/schema/types/fields.d.ts +59 -0
- package/dist/cjs/schema/types/fields.js +3 -0
- package/dist/cjs/schema/types/fields.js.map +1 -0
- package/dist/cjs/schema/types/filters.d.ts +29 -0
- package/dist/cjs/schema/types/filters.js +3 -0
- package/dist/cjs/schema/types/filters.js.map +1 -0
- package/dist/cjs/schema/types/shapes.d.ts +21 -0
- package/dist/cjs/schema/types/shapes.js +3 -0
- package/dist/cjs/schema/types/shapes.js.map +1 -0
- package/dist/cjs/schema/types/synthetics.d.ts +28 -0
- package/dist/cjs/schema/types/synthetics.js +3 -0
- package/dist/cjs/schema/types/synthetics.js.map +1 -0
- package/dist/cjs/schema/types.d.ts +18 -0
- package/dist/cjs/schema/types.js +23 -0
- package/dist/cjs/schema/types.js.map +1 -0
- package/dist/cjs/timestamp.d.ts +48 -0
- package/dist/cjs/timestamp.js +244 -0
- package/dist/cjs/timestamp.js.map +1 -0
- package/dist/cjs/timestamp.test.d.ts +1 -0
- package/dist/cjs/timestamp.test.js +94 -0
- package/dist/cjs/timestamp.test.js.map +1 -0
- package/dist/cjs/undo.d.ts +3 -0
- package/dist/cjs/undo.js +199 -0
- package/dist/cjs/undo.js.map +1 -0
- package/dist/cjs/utils.d.ts +15 -0
- package/dist/cjs/utils.js +128 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/cjs/utils.test.d.ts +1 -0
- package/dist/cjs/utils.test.js +37 -0
- package/dist/cjs/utils.test.js.map +1 -0
- package/dist/esm/EventSubscriber.d.ts +17 -0
- package/dist/esm/EventSubscriber.js +63 -0
- package/dist/esm/EventSubscriber.js.map +1 -0
- package/dist/esm/baseline.d.ts +5 -0
- package/dist/esm/baseline.js +2 -0
- package/dist/esm/baseline.js.map +1 -0
- package/dist/esm/batching.d.ts +41 -0
- package/dist/esm/batching.js +84 -0
- package/dist/esm/batching.js.map +1 -0
- package/dist/esm/files.d.ts +19 -0
- package/dist/esm/files.js +13 -0
- package/dist/esm/files.js.map +1 -0
- package/dist/esm/files.test.d.ts +1 -0
- package/dist/esm/files.test.js +79 -0
- package/dist/esm/files.test.js.map +1 -0
- package/dist/esm/index.d.ts +18 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/indexes.d.ts +14 -0
- package/dist/esm/indexes.js +106 -0
- package/dist/esm/indexes.js.map +1 -0
- package/dist/esm/indexes.test.d.ts +1 -0
- package/dist/esm/indexes.test.js +126 -0
- package/dist/esm/indexes.test.js.map +1 -0
- package/dist/esm/migration.d.ts +98 -0
- package/dist/esm/migration.js +122 -0
- package/dist/esm/migration.js.map +1 -0
- package/dist/esm/oids.d.ts +87 -0
- package/dist/esm/oids.js +348 -0
- package/dist/esm/oids.js.map +1 -0
- package/dist/esm/oids.test.d.ts +1 -0
- package/dist/esm/oids.test.js +280 -0
- package/dist/esm/oids.test.js.map +1 -0
- package/dist/esm/operation.d.ts +139 -0
- package/dist/esm/operation.js +518 -0
- package/dist/esm/operation.js.map +1 -0
- package/dist/esm/operation.test.d.ts +1 -0
- package/dist/esm/operation.test.js +825 -0
- package/dist/esm/operation.test.js.map +1 -0
- package/dist/esm/patch.d.ts +26 -0
- package/dist/esm/patch.js +223 -0
- package/dist/esm/patch.js.map +1 -0
- package/dist/esm/presence.d.ts +27 -0
- package/dist/esm/presence.js +2 -0
- package/dist/esm/presence.js.map +1 -0
- package/dist/esm/protocol.d.ts +145 -0
- package/dist/esm/protocol.js +3 -0
- package/dist/esm/protocol.js.map +1 -0
- package/dist/esm/refs.d.ts +5 -0
- package/dist/esm/refs.js +17 -0
- package/dist/esm/refs.js.map +1 -0
- package/dist/esm/replica.d.ts +28 -0
- package/dist/esm/replica.js +26 -0
- package/dist/esm/replica.js.map +1 -0
- package/dist/esm/schema/defaults.d.ts +4 -0
- package/dist/esm/schema/defaults.js +66 -0
- package/dist/esm/schema/defaults.js.map +1 -0
- package/dist/esm/schema/defaults.test.d.ts +1 -0
- package/dist/esm/schema/defaults.test.js +19 -0
- package/dist/esm/schema/defaults.test.js.map +1 -0
- package/dist/esm/schema/index.d.ts +8 -0
- package/dist/esm/schema/index.js +10 -0
- package/dist/esm/schema/index.js.map +1 -0
- package/dist/esm/schema/indexFilters.d.ts +6 -0
- package/dist/esm/schema/indexFilters.js +23 -0
- package/dist/esm/schema/indexFilters.js.map +1 -0
- package/dist/esm/schema/types/collection.d.ts +51 -0
- package/dist/esm/schema/types/collection.js +2 -0
- package/dist/esm/schema/types/collection.js.map +1 -0
- package/dist/esm/schema/types/compounds.d.ts +12 -0
- package/dist/esm/schema/types/compounds.js +2 -0
- package/dist/esm/schema/types/compounds.js.map +1 -0
- package/dist/esm/schema/types/fields.d.ts +59 -0
- package/dist/esm/schema/types/fields.js +2 -0
- package/dist/esm/schema/types/fields.js.map +1 -0
- package/dist/esm/schema/types/filters.d.ts +29 -0
- package/dist/esm/schema/types/filters.js +2 -0
- package/dist/esm/schema/types/filters.js.map +1 -0
- package/dist/esm/schema/types/shapes.d.ts +21 -0
- package/dist/esm/schema/types/shapes.js +2 -0
- package/dist/esm/schema/types/shapes.js.map +1 -0
- package/dist/esm/schema/types/synthetics.d.ts +28 -0
- package/dist/esm/schema/types/synthetics.js +2 -0
- package/dist/esm/schema/types/synthetics.js.map +1 -0
- package/dist/esm/schema/types.d.ts +18 -0
- package/dist/esm/schema/types.js +7 -0
- package/dist/esm/schema/types.js.map +1 -0
- package/dist/esm/timestamp.d.ts +48 -0
- package/dist/esm/timestamp.js +229 -0
- package/dist/esm/timestamp.js.map +1 -0
- package/dist/esm/timestamp.test.d.ts +1 -0
- package/dist/esm/timestamp.test.js +92 -0
- package/dist/esm/timestamp.test.js.map +1 -0
- package/dist/esm/undo.d.ts +3 -0
- package/dist/esm/undo.js +195 -0
- package/dist/esm/undo.js.map +1 -0
- package/dist/esm/utils.d.ts +15 -0
- package/dist/esm/utils.js +114 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/utils.test.d.ts +1 -0
- package/dist/esm/utils.test.js +35 -0
- package/dist/esm/utils.test.js.map +1 -0
- package/dist/tsconfig-cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +38 -0
- package/src/EventSubscriber.ts +81 -0
- package/src/baseline.ts +9 -0
- package/src/batching.ts +135 -0
- package/src/files.ts +34 -0
- package/src/index.ts +26 -0
- package/src/indexes.test.ts +158 -0
- package/src/indexes.ts +151 -0
- package/src/migration.ts +391 -0
- package/src/oids.test.ts +395 -0
- package/src/oids.ts +442 -0
- package/src/operation.test.ts +966 -0
- package/src/operation.ts +755 -0
- package/src/patch.ts +277 -0
- package/src/presence.ts +29 -0
- package/src/protocol.ts +184 -0
- package/src/refs.ts +16 -0
- package/src/replica.ts +29 -0
- package/src/schema/defaults.test.ts +19 -0
- package/src/schema/defaults.ts +72 -0
- package/src/schema/index.ts +28 -0
- package/src/schema/indexFilters.ts +49 -0
- package/src/schema/types/collection.ts +133 -0
- package/src/schema/types/compounds.ts +33 -0
- package/src/schema/types/fields.ts +85 -0
- package/src/schema/types/filters.ts +39 -0
- package/src/schema/types/shapes.ts +83 -0
- package/src/schema/types/synthetics.ts +45 -0
- package/src/schema/types.ts +28 -0
- package/src/timestamp.test.ts +113 -0
- package/src/timestamp.ts +284 -0
- package/src/undo.ts +205 -0
- package/src/utils.test.ts +38 -0
- package/src/utils.ts +137 -0
package/src/migration.ts
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stableStringify,
|
|
3
|
+
StorageCollectionSchema,
|
|
4
|
+
StorageSchema,
|
|
5
|
+
addFieldDefaults,
|
|
6
|
+
StorageDocument,
|
|
7
|
+
CollectionFilter,
|
|
8
|
+
StorageDocumentInit,
|
|
9
|
+
} from './index.js';
|
|
10
|
+
|
|
11
|
+
export interface DroppedCollectionMigrationStrategy<
|
|
12
|
+
Old extends StorageCollectionSchema<any, any, any>,
|
|
13
|
+
> {
|
|
14
|
+
(old: Old): void | Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export interface PreservedCollectionMigrationStrategy<
|
|
17
|
+
Old extends StorageCollectionSchema<any, any, any>,
|
|
18
|
+
New extends StorageCollectionSchema<any, any, any>,
|
|
19
|
+
> {
|
|
20
|
+
(old: StorageDocument<Old>):
|
|
21
|
+
| StorageDocument<New>
|
|
22
|
+
| Promise<StorageDocument<New>>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type MigrationStrategy<
|
|
26
|
+
Old extends StorageCollectionSchema<any, any, any>,
|
|
27
|
+
New extends StorageCollectionSchema<any, any, any>,
|
|
28
|
+
> =
|
|
29
|
+
| DroppedCollectionMigrationStrategy<Old>
|
|
30
|
+
| PreservedCollectionMigrationStrategy<Old, New>;
|
|
31
|
+
|
|
32
|
+
export type MigrationsKeyedOnCollection<
|
|
33
|
+
Old extends StorageSchema<any>,
|
|
34
|
+
New extends StorageSchema<any>,
|
|
35
|
+
> =
|
|
36
|
+
| PreservedCollectionMigrations<Old, New>
|
|
37
|
+
| DroppedCollectionMigrations<Old, New>;
|
|
38
|
+
|
|
39
|
+
type NotInSchema<
|
|
40
|
+
Name extends string | number | symbol,
|
|
41
|
+
Schema extends StorageSchema<any>,
|
|
42
|
+
> = Name extends keyof Schema['collections'] ? never : Name;
|
|
43
|
+
type InSchema<
|
|
44
|
+
Name extends string | number | symbol,
|
|
45
|
+
Schema extends StorageSchema<any>,
|
|
46
|
+
> = Name extends keyof Schema['collections'] ? Name : never;
|
|
47
|
+
|
|
48
|
+
type NewCollections<
|
|
49
|
+
Old extends StorageSchema<any>,
|
|
50
|
+
New extends StorageSchema<any>,
|
|
51
|
+
> = {
|
|
52
|
+
[Key in keyof New['collections'] as NotInSchema<
|
|
53
|
+
Key,
|
|
54
|
+
Old
|
|
55
|
+
>]: StorageCollectionSchema<any, any, any>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
type DroppedCollections<
|
|
59
|
+
Old extends StorageSchema<any>,
|
|
60
|
+
New extends StorageSchema<any>,
|
|
61
|
+
> = {
|
|
62
|
+
[Key in keyof Old['collections'] as NotInSchema<
|
|
63
|
+
Key,
|
|
64
|
+
New
|
|
65
|
+
>]: StorageCollectionSchema<any, any, any>;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
type PreservedCollections<
|
|
69
|
+
Old extends StorageSchema<any>,
|
|
70
|
+
New extends StorageSchema<any>,
|
|
71
|
+
> = {
|
|
72
|
+
[Key in keyof Old['collections'] as InSchema<
|
|
73
|
+
Key,
|
|
74
|
+
New
|
|
75
|
+
>]: StorageCollectionSchema<any, any, any>;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
type DroppedCollectionMigrations<
|
|
79
|
+
Old extends StorageSchema<any>,
|
|
80
|
+
New extends StorageSchema<any>,
|
|
81
|
+
> = {
|
|
82
|
+
[Key in keyof DroppedCollections<
|
|
83
|
+
Old,
|
|
84
|
+
New
|
|
85
|
+
>]: DroppedCollectionMigrationStrategy<Old['collections'][Key]>;
|
|
86
|
+
};
|
|
87
|
+
type PreservedCollectionMigrations<
|
|
88
|
+
Old extends StorageSchema<any>,
|
|
89
|
+
New extends StorageSchema<any>,
|
|
90
|
+
> = {
|
|
91
|
+
[Key in keyof PreservedCollections<
|
|
92
|
+
Old,
|
|
93
|
+
New
|
|
94
|
+
>]: PreservedCollectionMigrationStrategy<
|
|
95
|
+
Old['collections'][Key],
|
|
96
|
+
New['collections'][Key]
|
|
97
|
+
>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
type StrategyFor<
|
|
101
|
+
Key extends string,
|
|
102
|
+
Old extends StorageSchema<any>,
|
|
103
|
+
New extends StorageSchema<any>,
|
|
104
|
+
> = Key extends keyof New['collections']
|
|
105
|
+
? PreservedCollectionMigrationStrategy<
|
|
106
|
+
Old['collections'][Key],
|
|
107
|
+
New['collections'][Key]
|
|
108
|
+
>
|
|
109
|
+
: DroppedCollectionMigrationStrategy<Old['collections'][Key]>;
|
|
110
|
+
|
|
111
|
+
type MigrationRunner<
|
|
112
|
+
Old extends StorageSchema<any>,
|
|
113
|
+
New extends StorageSchema<any>,
|
|
114
|
+
> = <Collection extends Extract<keyof Old['collections'], string>>(
|
|
115
|
+
collection: Collection,
|
|
116
|
+
strategy: StrategyFor<Collection, Old, New>,
|
|
117
|
+
) => Promise<void>;
|
|
118
|
+
|
|
119
|
+
type MigrationQueryMaker<
|
|
120
|
+
Collection extends StorageCollectionSchema<any, any, any>,
|
|
121
|
+
> = {
|
|
122
|
+
get(primaryKey: string): Promise<StorageDocument<Collection> | undefined>;
|
|
123
|
+
findOne(
|
|
124
|
+
query: CollectionFilter,
|
|
125
|
+
): Promise<StorageDocument<Collection> | undefined>;
|
|
126
|
+
findAll(query?: CollectionFilter): Promise<StorageDocument<Collection>[]>;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
type MigrationQueries<Old extends StorageSchema<any>> = {
|
|
130
|
+
[Key in keyof Old['collections']]: MigrationQueryMaker<
|
|
131
|
+
Old['collections'][Key]
|
|
132
|
+
>;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
type MigrationMutations<New extends StorageSchema> = {
|
|
136
|
+
[Key in keyof New['collections']]: {
|
|
137
|
+
put(
|
|
138
|
+
document: StorageDocumentInit<New['collections'][Key]>,
|
|
139
|
+
): Promise<StorageDocument<New['collections'][Key]>>;
|
|
140
|
+
delete(primaryKey: string): Promise<void>;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export interface MigrationTools<
|
|
145
|
+
Old extends StorageSchema<any>,
|
|
146
|
+
New extends StorageSchema<any>,
|
|
147
|
+
> {
|
|
148
|
+
migrate: MigrationRunner<Old, New>;
|
|
149
|
+
identity: <T>(val: T) => T;
|
|
150
|
+
withDefaults: (collectionName: string, value: any) => any;
|
|
151
|
+
queries: MigrationQueries<Old>;
|
|
152
|
+
mutations: MigrationMutations<New>;
|
|
153
|
+
info: {
|
|
154
|
+
changedCollections: keyof Old['collections'][];
|
|
155
|
+
addedCollections: keyof New['collections'][];
|
|
156
|
+
removedCollections: keyof Old['collections'][];
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface MigrationEngine<
|
|
161
|
+
Old extends StorageSchema,
|
|
162
|
+
New extends StorageSchema,
|
|
163
|
+
> {
|
|
164
|
+
migrate: (
|
|
165
|
+
collection: string,
|
|
166
|
+
strategy: MigrationStrategy<any, any>,
|
|
167
|
+
) => Promise<void>;
|
|
168
|
+
queries: MigrationQueries<Old>;
|
|
169
|
+
mutations: MigrationMutations<New>;
|
|
170
|
+
/** OIDs of any new documents created during the migration */
|
|
171
|
+
newOids: string[];
|
|
172
|
+
/** Promises that should be resolved before completing the migration */
|
|
173
|
+
awaitables: Promise<any>[];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
type MigrationProcedure<
|
|
177
|
+
Old extends StorageSchema,
|
|
178
|
+
New extends StorageSchema,
|
|
179
|
+
> = (tools: MigrationTools<Old, New>) => Promise<void>;
|
|
180
|
+
|
|
181
|
+
type EmptySchema = {
|
|
182
|
+
version: 0;
|
|
183
|
+
collections: {};
|
|
184
|
+
};
|
|
185
|
+
const emptySchema: EmptySchema = {
|
|
186
|
+
version: 0,
|
|
187
|
+
collections: {},
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
export function migrate<Schema extends StorageSchema>(
|
|
191
|
+
schema: Schema,
|
|
192
|
+
procedure: MigrationProcedure<EmptySchema, Schema>,
|
|
193
|
+
): Migration<EmptySchema, Schema>;
|
|
194
|
+
export function migrate<Old extends StorageSchema, New extends StorageSchema>(
|
|
195
|
+
oldSchema: Old,
|
|
196
|
+
newSchema: New,
|
|
197
|
+
procedure: MigrationProcedure<Old, New>,
|
|
198
|
+
): Migration<Old, New>;
|
|
199
|
+
export function migrate(
|
|
200
|
+
oldSchemaOrNewSchema: any,
|
|
201
|
+
newSchemaOrProcedure: any,
|
|
202
|
+
procedureIfTwoSchemas?: any,
|
|
203
|
+
) {
|
|
204
|
+
const isProcedureSecondArgument = typeof newSchemaOrProcedure === 'function';
|
|
205
|
+
const oldSchema = isProcedureSecondArgument
|
|
206
|
+
? emptySchema
|
|
207
|
+
: oldSchemaOrNewSchema;
|
|
208
|
+
const newSchema = isProcedureSecondArgument
|
|
209
|
+
? oldSchemaOrNewSchema
|
|
210
|
+
: newSchemaOrProcedure;
|
|
211
|
+
const procedure = isProcedureSecondArgument
|
|
212
|
+
? newSchemaOrProcedure
|
|
213
|
+
: procedureIfTwoSchemas;
|
|
214
|
+
// diff to determine changed collections
|
|
215
|
+
const changedCollections: string[] = Object.keys(
|
|
216
|
+
newSchema.collections,
|
|
217
|
+
).filter(
|
|
218
|
+
(key) =>
|
|
219
|
+
oldSchema.collections[key] &&
|
|
220
|
+
stableStringify(oldSchema.collections[key]) !==
|
|
221
|
+
stableStringify(newSchema.collections[key]),
|
|
222
|
+
);
|
|
223
|
+
const removedCollections: string[] = Object.keys(
|
|
224
|
+
oldSchema.collections,
|
|
225
|
+
).filter((key) => !newSchema.collections[key]);
|
|
226
|
+
const addedCollections = Object.keys(newSchema.collections).filter(
|
|
227
|
+
(key) => !oldSchema.collections[key],
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const addedIndexes: Record<string, MigrationIndexDescription[]> = {};
|
|
231
|
+
const removedIndexes: Record<string, MigrationIndexDescription[]> = {};
|
|
232
|
+
for (const changed of [...changedCollections, ...addedCollections]) {
|
|
233
|
+
const oldIndexes = getIndexes(oldSchema.collections[changed]);
|
|
234
|
+
const newIndexes = getIndexes(newSchema.collections[changed]);
|
|
235
|
+
const added = newIndexes.filter(
|
|
236
|
+
(index) => !oldIndexes.find((i) => i.name === index.name),
|
|
237
|
+
);
|
|
238
|
+
const removed = oldIndexes.filter(
|
|
239
|
+
(index) => !newIndexes.find((i) => i.name === index.name),
|
|
240
|
+
);
|
|
241
|
+
if (added.length > 0) {
|
|
242
|
+
addedIndexes[changed] = added;
|
|
243
|
+
}
|
|
244
|
+
if (removed.length > 0) {
|
|
245
|
+
removedIndexes[changed] = removed;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
version: newSchema.version,
|
|
251
|
+
migrate: async (engine: MigrationEngine<any, any>) => {
|
|
252
|
+
const migratedCollections: string[] = [];
|
|
253
|
+
await procedure({
|
|
254
|
+
migrate: async (collection: any, strategy: any) => {
|
|
255
|
+
// @ts-ignore
|
|
256
|
+
await engine.migrate(collection, strategy);
|
|
257
|
+
migratedCollections.push(collection);
|
|
258
|
+
},
|
|
259
|
+
identity: (val: any) => val,
|
|
260
|
+
withDefaults: (collectionName: string, val: any) => {
|
|
261
|
+
return addFieldDefaults(newSchema.collections[collectionName], val);
|
|
262
|
+
},
|
|
263
|
+
info: {
|
|
264
|
+
changedCollections,
|
|
265
|
+
addedCollections,
|
|
266
|
+
removedCollections,
|
|
267
|
+
},
|
|
268
|
+
queries: engine.queries,
|
|
269
|
+
mutations: engine.mutations,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const unmigrated = changedCollections.filter(
|
|
273
|
+
(collection) => !migratedCollections.includes(collection),
|
|
274
|
+
);
|
|
275
|
+
if (unmigrated.length > 0) {
|
|
276
|
+
console.error('Unmigrated changed collections:', unmigrated);
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
removedCollections,
|
|
280
|
+
addedIndexes,
|
|
281
|
+
removedIndexes,
|
|
282
|
+
allCollections: Object.keys(newSchema.collections),
|
|
283
|
+
changedCollections,
|
|
284
|
+
addedCollections,
|
|
285
|
+
oldCollections: Object.keys(oldSchema.collections),
|
|
286
|
+
oldSchema,
|
|
287
|
+
newSchema,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export interface MigrationIndexDescription {
|
|
292
|
+
name: string;
|
|
293
|
+
multiEntry: boolean;
|
|
294
|
+
synthetic: boolean;
|
|
295
|
+
compound: boolean;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export interface Migration<
|
|
299
|
+
Old extends StorageSchema = any,
|
|
300
|
+
New extends StorageSchema = any,
|
|
301
|
+
> {
|
|
302
|
+
version: number;
|
|
303
|
+
oldSchema: Old;
|
|
304
|
+
newSchema: New;
|
|
305
|
+
migrate: (engine: MigrationEngine<Old, New>) => Promise<void>;
|
|
306
|
+
/** Collections which are added in the new schema and not present in the old */
|
|
307
|
+
addedCollections: string[];
|
|
308
|
+
/** Collections which were removed from the old schema */
|
|
309
|
+
removedCollections: string[];
|
|
310
|
+
/** All collections which exist after the migration has completed - i.e. the ones in the new schema */
|
|
311
|
+
allCollections: string[];
|
|
312
|
+
/** Only the collections which were in the old schema */
|
|
313
|
+
oldCollections: string[];
|
|
314
|
+
/** Collections whose fields or indexes changed between schemas */
|
|
315
|
+
changedCollections: string[];
|
|
316
|
+
// new indexes mapped by collection name
|
|
317
|
+
addedIndexes: Record<string, MigrationIndexDescription[]>;
|
|
318
|
+
// removed indexes mapped by collection name
|
|
319
|
+
removedIndexes: Record<string, MigrationIndexDescription[]>;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function migrationRange(from: number, to: number) {
|
|
323
|
+
return [...Array(to - from).keys()].map((i) => 1 + i + from);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function getIndexes<Coll extends StorageCollectionSchema<any, any, any>>(
|
|
327
|
+
collection: Coll | undefined,
|
|
328
|
+
): MigrationIndexDescription[] {
|
|
329
|
+
if (!collection) return [];
|
|
330
|
+
const fields = Object.keys(collection.fields)
|
|
331
|
+
.filter((key) => collection.fields[key].indexed)
|
|
332
|
+
.map((key) => ({
|
|
333
|
+
name: key,
|
|
334
|
+
multiEntry: collection.fields[key].type === 'array',
|
|
335
|
+
synthetic: false,
|
|
336
|
+
compound: false,
|
|
337
|
+
}));
|
|
338
|
+
|
|
339
|
+
return [
|
|
340
|
+
...fields,
|
|
341
|
+
...Object.keys(collection.synthetics || {}).map((key) => ({
|
|
342
|
+
name: key,
|
|
343
|
+
multiEntry: ['array', 'string[]', 'number[]', 'boolean[]'].includes(
|
|
344
|
+
collection.synthetics[key].type,
|
|
345
|
+
),
|
|
346
|
+
synthetic: true,
|
|
347
|
+
compound: false,
|
|
348
|
+
})),
|
|
349
|
+
...Object.keys(collection.compounds || {}).map((key) => ({
|
|
350
|
+
name: key,
|
|
351
|
+
multiEntry: collection.compounds[key].of.some(
|
|
352
|
+
(fieldName: string) =>
|
|
353
|
+
(collection.fields[fieldName] || collection.synthetics[fieldName])
|
|
354
|
+
.type === 'array',
|
|
355
|
+
),
|
|
356
|
+
synthetic: false,
|
|
357
|
+
compound: true,
|
|
358
|
+
})),
|
|
359
|
+
];
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export function createDefaultMigration(
|
|
363
|
+
schema: StorageSchema,
|
|
364
|
+
): Migration<{ version: 0; collections: {} }>;
|
|
365
|
+
export function createDefaultMigration<Old extends StorageSchema>(
|
|
366
|
+
oldSchema: Old,
|
|
367
|
+
newSchema: StorageSchema,
|
|
368
|
+
): Migration<Old>;
|
|
369
|
+
export function createDefaultMigration(
|
|
370
|
+
schema: StorageSchema,
|
|
371
|
+
newSchema?: StorageSchema<any>,
|
|
372
|
+
) {
|
|
373
|
+
let oldSchema = newSchema
|
|
374
|
+
? schema
|
|
375
|
+
: {
|
|
376
|
+
version: 0,
|
|
377
|
+
collections: {},
|
|
378
|
+
};
|
|
379
|
+
return migrate(
|
|
380
|
+
oldSchema,
|
|
381
|
+
newSchema || schema,
|
|
382
|
+
async ({ migrate, withDefaults, info }) => {
|
|
383
|
+
if ((newSchema || schema).version === 1) return;
|
|
384
|
+
|
|
385
|
+
for (const collection of info.changedCollections as any) {
|
|
386
|
+
// @ts-ignore indefinite type resolution
|
|
387
|
+
await migrate(collection, (old) => withDefaults(collection, old));
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
);
|
|
391
|
+
}
|