@verdant-web/common 1.15.2 → 1.15.3-next.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.
Files changed (163) hide show
  1. package/dist/cjs/EventSubscriber.d.ts +17 -17
  2. package/dist/cjs/EventSubscriber.js +66 -66
  3. package/dist/cjs/baseline.d.ts +5 -5
  4. package/dist/cjs/baseline.js +2 -2
  5. package/dist/cjs/batching.d.ts +42 -42
  6. package/dist/cjs/batching.js +91 -91
  7. package/dist/cjs/files.d.ts +19 -19
  8. package/dist/cjs/files.js +18 -18
  9. package/dist/cjs/files.test.d.ts +1 -0
  10. package/dist/cjs/files.test.js +81 -0
  11. package/dist/cjs/files.test.js.map +1 -0
  12. package/dist/cjs/index.d.ts +19 -18
  13. package/dist/cjs/index.js +41 -36
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/indexes.d.ts +17 -17
  16. package/dist/cjs/indexes.js +142 -142
  17. package/dist/cjs/indexes.test.d.ts +1 -1
  18. package/dist/cjs/indexes.test.js +127 -127
  19. package/dist/cjs/migration.d.ts +172 -172
  20. package/dist/cjs/migration.js +301 -301
  21. package/dist/cjs/oids.d.ts +100 -96
  22. package/dist/cjs/oids.js +457 -439
  23. package/dist/cjs/oids.js.map +1 -1
  24. package/dist/cjs/oids.test.d.ts +1 -1
  25. package/dist/cjs/oids.test.js +348 -272
  26. package/dist/cjs/oids.test.js.map +1 -1
  27. package/dist/cjs/operation.d.ts +139 -139
  28. package/dist/cjs/operation.js +545 -545
  29. package/dist/cjs/operation.test.d.ts +1 -1
  30. package/dist/cjs/operation.test.js +529 -529
  31. package/dist/cjs/patch.d.ts +26 -26
  32. package/dist/cjs/patch.js +226 -226
  33. package/dist/cjs/presence.d.ts +27 -27
  34. package/dist/cjs/presence.js +2 -2
  35. package/dist/cjs/protocol.d.ts +145 -145
  36. package/dist/cjs/protocol.js +3 -3
  37. package/dist/cjs/refs.d.ts +7 -5
  38. package/dist/cjs/refs.js +29 -21
  39. package/dist/cjs/refs.js.map +1 -1
  40. package/dist/cjs/replica.d.ts +28 -28
  41. package/dist/cjs/replica.js +28 -28
  42. package/dist/cjs/schema/defaults.d.ts +4 -0
  43. package/dist/cjs/schema/defaults.js +72 -0
  44. package/dist/cjs/schema/defaults.js.map +1 -0
  45. package/dist/cjs/schema/defaults.test.d.ts +1 -1
  46. package/dist/cjs/schema/defaults.test.js +20 -20
  47. package/dist/cjs/schema/fields.d.ts +9 -9
  48. package/dist/cjs/schema/fields.js +144 -144
  49. package/dist/cjs/schema/index.d.ts +8 -8
  50. package/dist/cjs/schema/index.js +51 -51
  51. package/dist/cjs/schema/indexFilters.d.ts +6 -6
  52. package/dist/cjs/schema/indexFilters.js +30 -30
  53. package/dist/cjs/schema/types/collection.d.ts +23 -23
  54. package/dist/cjs/schema/types/collection.js +2 -2
  55. package/dist/cjs/schema/types/compounds.d.ts +11 -11
  56. package/dist/cjs/schema/types/compounds.js +2 -2
  57. package/dist/cjs/schema/types/fields.d.ts +75 -75
  58. package/dist/cjs/schema/types/fields.js +2 -2
  59. package/dist/cjs/schema/types/filters.d.ts +29 -29
  60. package/dist/cjs/schema/types/filters.js +2 -2
  61. package/dist/cjs/schema/types/shapes.d.ts +21 -21
  62. package/dist/cjs/schema/types/shapes.js +2 -2
  63. package/dist/cjs/schema/types/synthetics.d.ts +37 -37
  64. package/dist/cjs/schema/types/synthetics.js +2 -2
  65. package/dist/cjs/schema/types.d.ts +18 -18
  66. package/dist/cjs/schema/types.js +22 -22
  67. package/dist/cjs/schema/validation.d.ts +3 -3
  68. package/dist/cjs/schema/validation.js +86 -86
  69. package/dist/cjs/timestamp.d.ts +50 -50
  70. package/dist/cjs/timestamp.js +251 -251
  71. package/dist/cjs/timestamp.test.d.ts +1 -1
  72. package/dist/cjs/timestamp.test.js +104 -104
  73. package/dist/cjs/undo.d.ts +3 -3
  74. package/dist/cjs/undo.js +198 -198
  75. package/dist/cjs/utils.d.ts +20 -20
  76. package/dist/cjs/utils.js +145 -145
  77. package/dist/cjs/utils.test.d.ts +1 -1
  78. package/dist/cjs/utils.test.js +36 -36
  79. package/dist/esm/EventSubscriber.d.ts +17 -17
  80. package/dist/esm/EventSubscriber.js +62 -62
  81. package/dist/esm/baseline.d.ts +5 -5
  82. package/dist/esm/baseline.js +1 -1
  83. package/dist/esm/batching.d.ts +42 -42
  84. package/dist/esm/batching.js +86 -86
  85. package/dist/esm/files.d.ts +19 -19
  86. package/dist/esm/files.js +12 -12
  87. package/dist/esm/files.test.d.ts +1 -0
  88. package/dist/esm/files.test.js +79 -0
  89. package/dist/esm/files.test.js.map +1 -0
  90. package/dist/esm/index.d.ts +19 -18
  91. package/dist/esm/index.js +16 -15
  92. package/dist/esm/index.js.map +1 -1
  93. package/dist/esm/indexes.d.ts +17 -17
  94. package/dist/esm/indexes.js +130 -130
  95. package/dist/esm/indexes.test.d.ts +1 -1
  96. package/dist/esm/indexes.test.js +125 -125
  97. package/dist/esm/migration.d.ts +172 -172
  98. package/dist/esm/migration.js +294 -294
  99. package/dist/esm/oids.d.ts +100 -96
  100. package/dist/esm/oids.js +422 -407
  101. package/dist/esm/oids.js.map +1 -1
  102. package/dist/esm/oids.test.d.ts +1 -1
  103. package/dist/esm/oids.test.js +346 -270
  104. package/dist/esm/oids.test.js.map +1 -1
  105. package/dist/esm/operation.d.ts +139 -139
  106. package/dist/esm/operation.js +530 -530
  107. package/dist/esm/operation.test.d.ts +1 -1
  108. package/dist/esm/operation.test.js +527 -527
  109. package/dist/esm/patch.d.ts +26 -26
  110. package/dist/esm/patch.js +222 -222
  111. package/dist/esm/presence.d.ts +27 -27
  112. package/dist/esm/presence.js +1 -1
  113. package/dist/esm/protocol.d.ts +145 -145
  114. package/dist/esm/protocol.js +2 -2
  115. package/dist/esm/refs.d.ts +7 -5
  116. package/dist/esm/refs.js +22 -16
  117. package/dist/esm/refs.js.map +1 -1
  118. package/dist/esm/replica.d.ts +28 -28
  119. package/dist/esm/replica.js +25 -25
  120. package/dist/esm/schema/defaults.d.ts +4 -0
  121. package/dist/esm/schema/defaults.js +66 -0
  122. package/dist/esm/schema/defaults.js.map +1 -0
  123. package/dist/esm/schema/defaults.test.d.ts +1 -1
  124. package/dist/esm/schema/defaults.test.js +18 -18
  125. package/dist/esm/schema/fields.d.ts +9 -9
  126. package/dist/esm/schema/fields.js +133 -133
  127. package/dist/esm/schema/index.d.ts +8 -8
  128. package/dist/esm/schema/index.js +32 -32
  129. package/dist/esm/schema/indexFilters.d.ts +6 -6
  130. package/dist/esm/schema/indexFilters.js +22 -22
  131. package/dist/esm/schema/types/collection.d.ts +23 -23
  132. package/dist/esm/schema/types/collection.js +1 -1
  133. package/dist/esm/schema/types/compounds.d.ts +11 -11
  134. package/dist/esm/schema/types/compounds.js +1 -1
  135. package/dist/esm/schema/types/fields.d.ts +75 -75
  136. package/dist/esm/schema/types/fields.js +1 -1
  137. package/dist/esm/schema/types/filters.d.ts +29 -29
  138. package/dist/esm/schema/types/filters.js +1 -1
  139. package/dist/esm/schema/types/shapes.d.ts +21 -21
  140. package/dist/esm/schema/types/shapes.js +1 -1
  141. package/dist/esm/schema/types/synthetics.d.ts +37 -37
  142. package/dist/esm/schema/types/synthetics.js +1 -1
  143. package/dist/esm/schema/types.d.ts +18 -18
  144. package/dist/esm/schema/types.js +6 -6
  145. package/dist/esm/schema/validation.d.ts +3 -3
  146. package/dist/esm/schema/validation.js +81 -81
  147. package/dist/esm/timestamp.d.ts +50 -50
  148. package/dist/esm/timestamp.js +234 -234
  149. package/dist/esm/timestamp.test.d.ts +1 -1
  150. package/dist/esm/timestamp.test.js +102 -102
  151. package/dist/esm/undo.d.ts +3 -3
  152. package/dist/esm/undo.js +194 -194
  153. package/dist/esm/utils.d.ts +20 -20
  154. package/dist/esm/utils.js +127 -127
  155. package/dist/esm/utils.test.d.ts +1 -1
  156. package/dist/esm/utils.test.js +34 -34
  157. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  158. package/dist/tsconfig.tsbuildinfo +1 -1
  159. package/package.json +1 -1
  160. package/src/index.ts +1 -0
  161. package/src/oids.test.ts +82 -0
  162. package/src/oids.ts +17 -0
  163. package/src/refs.ts +8 -0
@@ -1,295 +1,295 @@
1
- import { stableStringify, addFieldDefaults, removeExtraProperties, assert, assignOid, getOid, hasDefault, } from './index.js';
2
- const emptySchema = {
3
- version: 0,
4
- collections: {},
5
- };
6
- export function migrate(oldSchemaOrNewSchema, newSchemaOrProcedure, procedureIfTwoSchemas) {
7
- const isProcedureSecondArgument = typeof newSchemaOrProcedure === 'function';
8
- const oldSchema = isProcedureSecondArgument
9
- ? emptySchema
10
- : oldSchemaOrNewSchema;
11
- const newSchema = isProcedureSecondArgument
12
- ? oldSchemaOrNewSchema
13
- : newSchemaOrProcedure;
14
- const procedure = isProcedureSecondArgument
15
- ? newSchemaOrProcedure
16
- : procedureIfTwoSchemas;
17
- // diff to determine changed collections
18
- const changedCollections = Object.keys(newSchema.collections).filter((key) => oldSchema.collections[key] &&
19
- stableStringify(oldSchema.collections[key]) !==
20
- stableStringify(newSchema.collections[key]));
21
- const removedCollections = Object.keys(oldSchema.collections).filter((key) => !newSchema.collections[key]);
22
- const addedCollections = Object.keys(newSchema.collections).filter((key) => !oldSchema.collections[key]);
23
- // collections which added one or more field defaults
24
- const autoMigratedCollections = new Set();
25
- for (const collection of changedCollections) {
26
- const oldFields = oldSchema.collections[collection].fields;
27
- const newFields = newSchema.collections[collection].fields;
28
- // a new default was added - we can auto-migrate it
29
- if (Object.keys(newFields).some((key) => { var _a, _b; return !((_a = oldFields[key]) === null || _a === void 0 ? void 0 : _a.default) && ((_b = newFields[key]) === null || _b === void 0 ? void 0 : _b.default); })) {
30
- autoMigratedCollections.add(collection);
31
- }
32
- // a field was removed - we can auto-migrate it
33
- if (Object.keys(oldFields).some((key) => !newFields[key])) {
34
- autoMigratedCollections.add(collection);
35
- }
36
- }
37
- const addedIndexes = {};
38
- const removedIndexes = {};
39
- for (const changed of [...changedCollections, ...addedCollections]) {
40
- const oldIndexes = getIndexes(oldSchema.collections[changed]);
41
- const newIndexes = getIndexes(newSchema.collections[changed]);
42
- const added = newIndexes.filter((index) => !oldIndexes.find((i) => i.name === index.name));
43
- const removed = oldIndexes.filter((index) => !newIndexes.find((i) => i.name === index.name));
44
- if (added.length > 0) {
45
- addedIndexes[changed] = added;
46
- // FIXME: don't o(n^2) this
47
- if (changedCollections.includes(changed)) {
48
- autoMigratedCollections.add(changed);
49
- }
50
- }
51
- if (removed.length > 0) {
52
- removedIndexes[changed] = removed;
53
- // FIXME: don't o(n^2) this
54
- if (changedCollections.includes(changed)) {
55
- autoMigratedCollections.add(changed);
56
- }
57
- }
58
- }
59
- const withDefaults = (collectionName, val) => {
60
- return addFieldDefaults(newSchema.collections[collectionName], val);
61
- };
62
- const autoMigration = (collectionName) => (val) => {
63
- const collection = newSchema.collections[collectionName];
64
- return addFieldDefaults(collection, removeExtraProperties(collection, val));
65
- };
66
- return {
67
- version: newSchema.version,
68
- migrate: async (engine) => {
69
- const migratedCollections = [];
70
- await procedure({
71
- migrate: async (collection, strategy) => {
72
- const auto = autoMigration(collection);
73
- const wrapped = async (val) => {
74
- const baseValue = await strategy(val);
75
- // assign OID from original value in case user's strategy
76
- // involves cloning
77
- assignOid(baseValue, getOid(val));
78
- const result = auto(baseValue);
79
- return result;
80
- };
81
- // @ts-ignore
82
- await engine.migrate(collection, wrapped);
83
- migratedCollections.push(collection);
84
- // since the user migrated this one and we wrap their
85
- // strategy with auto-migration, we can remove it from
86
- // the auto-migration list
87
- autoMigratedCollections.delete(collection);
88
- },
89
- identity: (val) => val,
90
- withDefaults,
91
- info: {
92
- changedCollections,
93
- addedCollections,
94
- removedCollections,
95
- },
96
- queries: engine.queries,
97
- mutations: engine.mutations,
98
- });
99
- // mandatory migration of fields which had defaults added or
100
- // fields removed but weren't migrated by the user
101
- if (newSchema.version > 1) {
102
- engine.log('debug', 'auto-migrating collections with new defaults', autoMigratedCollections);
103
- for (const name of autoMigratedCollections) {
104
- await engine.migrate(name, autoMigration(name));
105
- migratedCollections.push(name);
106
- }
107
- const unmigrated = changedCollections.filter((collection) => !migratedCollections.includes(collection));
108
- if (unmigrated.length > 0) {
109
- // TODO: does this deserve a full-on error?
110
- console.error(`Unmigrated changed collections from version ${oldSchema.version} to version ${newSchema.version}:`, unmigrated);
111
- }
112
- }
113
- },
114
- removedCollections,
115
- addedIndexes,
116
- removedIndexes,
117
- allCollections: Object.keys(newSchema.collections),
118
- changedCollections,
119
- addedCollections,
120
- oldCollections: Object.keys(oldSchema.collections),
121
- oldSchema,
122
- newSchema,
123
- };
124
- }
125
- export function migrationRange(from, to) {
126
- return [...Array(to - from).keys()].map((i) => 1 + i + from);
127
- }
128
- function getIndexes(collection) {
129
- if (!collection)
130
- return [];
131
- return [
132
- ...Object.keys(collection.indexes || {}).map((key) => ({
133
- name: key,
134
- multiEntry: ['array', 'string[]', 'number[]', 'boolean[]'].includes(collection.indexes[key].type),
135
- synthetic: true,
136
- compound: false,
137
- })),
138
- ...Object.keys(collection.compounds || {}).map((key) => ({
139
- name: key,
140
- multiEntry: collection.compounds[key].of.some((fieldName) => (collection.fields[fieldName] || collection.indexes[fieldName])
141
- .type === 'array'),
142
- synthetic: false,
143
- compound: true,
144
- })),
145
- ];
146
- }
147
- export function createDefaultMigration(schema, newSchema) {
148
- let oldSchema = newSchema
149
- ? schema
150
- : {
151
- version: 0,
152
- collections: {},
153
- };
154
- return migrate(oldSchema, newSchema || schema, async ({ migrate, info }) => {
155
- if ((newSchema || schema).version === 1)
156
- return;
157
- for (const collection of info.changedCollections) {
158
- // @ts-ignore indefinite type resolution
159
- await migrate(collection, (old) => old);
160
- }
161
- });
162
- }
163
- export function createMigration(maybeOldSchema, maybeNewSchemaOrProcedure, maybeProcedure) {
164
- const isProcedureSecondArgument = typeof maybeNewSchemaOrProcedure === 'function' ||
165
- maybeNewSchemaOrProcedure === undefined;
166
- const oldSchema = isProcedureSecondArgument ? emptySchema : maybeOldSchema;
167
- const newSchema = isProcedureSecondArgument
168
- ? maybeOldSchema
169
- : maybeNewSchemaOrProcedure;
170
- const procedure = isProcedureSecondArgument
171
- ? maybeNewSchemaOrProcedure
172
- : maybeProcedure;
173
- assert(oldSchema, 'Invalid arguments to createMigration');
174
- assert(newSchema, 'Invalid arguments to createMigration');
175
- const { changedCollections, addedCollections, removedCollections, addedIndexes, removedIndexes, autoMigratedCollections, autoMigration, } = getMigrationInfo(oldSchema, newSchema);
176
- return {
177
- version: newSchema.version,
178
- migrate: async (engine) => {
179
- const migratedCollections = [];
180
- const migrate = async (collection, strategy) => {
181
- const auto = autoMigration(collection);
182
- const wrapped = async (val) => {
183
- const baseValue = await strategy(val);
184
- // assign OID from original value in case user's strategy
185
- // involves cloning
186
- assignOid(baseValue, getOid(val));
187
- const result = auto(baseValue);
188
- return result;
189
- };
190
- // @ts-ignore
191
- await engine.migrate(collection, wrapped);
192
- migratedCollections.push(collection);
193
- // since the user migrated this one and we wrap their
194
- // strategy with auto-migration, we can remove it from
195
- // the auto-migration list
196
- autoMigratedCollections.delete(collection);
197
- };
198
- await (procedure === null || procedure === void 0 ? void 0 : procedure({
199
- migrate,
200
- info: {
201
- changedCollections,
202
- addedCollections,
203
- removedCollections,
204
- },
205
- queries: engine.queries,
206
- mutations: engine.mutations,
207
- }));
208
- // mandatory migration of fields which had defaults added or
209
- // fields removed but weren't migrated by the user
210
- if (newSchema.version > 1) {
211
- engine.log('debug', 'auto-migrating collections with new defaults', autoMigratedCollections);
212
- for (const name of autoMigratedCollections) {
213
- await engine.migrate(name, autoMigration(name));
214
- migratedCollections.push(name);
215
- }
216
- const unmigrated = changedCollections.filter((collection) => !migratedCollections.includes(collection));
217
- if (unmigrated.length > 0) {
218
- // TODO: does this deserve a full-on error?
219
- console.error(`Unmigrated changed collections from version ${oldSchema.version} to version ${newSchema.version}:`, unmigrated);
220
- }
221
- }
222
- },
223
- removedCollections,
224
- addedIndexes,
225
- removedIndexes,
226
- allCollections: Object.keys(newSchema.collections),
227
- changedCollections,
228
- addedCollections,
229
- oldCollections: Object.keys(oldSchema.collections),
230
- oldSchema,
231
- newSchema,
232
- };
233
- }
234
- // common tools
235
- function getMigrationInfo(oldSchema, newSchema) {
236
- const changedCollections = Object.keys(newSchema.collections).filter((key) => oldSchema.collections[key] &&
237
- stableStringify(oldSchema.collections[key]) !==
238
- stableStringify(newSchema.collections[key]));
239
- const removedCollections = Object.keys(oldSchema.collections).filter((key) => !newSchema.collections[key]);
240
- const addedCollections = Object.keys(newSchema.collections).filter((key) => !oldSchema.collections[key]);
241
- // collections which added one or more field defaults
242
- const autoMigratedCollections = new Set();
243
- for (const collection of changedCollections) {
244
- const oldFields = oldSchema.collections[collection].fields;
245
- const newFields = newSchema.collections[collection].fields;
246
- // a new default was added - we can auto-migrate it
247
- if (Object.keys(newFields).some((key) => !hasDefault(oldFields[key]) && hasDefault(newFields[key]))) {
248
- autoMigratedCollections.add(collection);
249
- }
250
- // a field was removed - we can auto-migrate it
251
- if (Object.keys(oldFields).some((key) => !newFields[key])) {
252
- autoMigratedCollections.add(collection);
253
- }
254
- }
255
- const addedIndexes = {};
256
- const removedIndexes = {};
257
- for (const changed of [...changedCollections, ...addedCollections]) {
258
- const oldIndexes = getIndexes(oldSchema.collections[changed]);
259
- const newIndexes = getIndexes(newSchema.collections[changed]);
260
- const added = newIndexes.filter((index) => !oldIndexes.find((i) => i.name === index.name));
261
- const removed = oldIndexes.filter((index) => !newIndexes.find((i) => i.name === index.name));
262
- if (added.length > 0) {
263
- addedIndexes[changed] = added;
264
- // FIXME: don't o(n^2) this
265
- if (changedCollections.includes(changed)) {
266
- autoMigratedCollections.add(changed);
267
- }
268
- }
269
- if (removed.length > 0) {
270
- removedIndexes[changed] = removed;
271
- // FIXME: don't o(n^2) this
272
- if (changedCollections.includes(changed)) {
273
- autoMigratedCollections.add(changed);
274
- }
275
- }
276
- }
277
- const withDefaults = (collectionName, val) => {
278
- return addFieldDefaults(newSchema.collections[collectionName], val);
279
- };
280
- const autoMigration = (collectionName) => (val) => {
281
- const collection = newSchema.collections[collectionName];
282
- return addFieldDefaults(collection, removeExtraProperties(collection, val));
283
- };
284
- return {
285
- changedCollections,
286
- addedCollections,
287
- removedCollections,
288
- addedIndexes,
289
- removedIndexes,
290
- autoMigratedCollections,
291
- withDefaults,
292
- autoMigration,
293
- };
294
- }
1
+ import { stableStringify, addFieldDefaults, removeExtraProperties, assert, assignOid, getOid, hasDefault, } from './index.js';
2
+ const emptySchema = {
3
+ version: 0,
4
+ collections: {},
5
+ };
6
+ export function migrate(oldSchemaOrNewSchema, newSchemaOrProcedure, procedureIfTwoSchemas) {
7
+ const isProcedureSecondArgument = typeof newSchemaOrProcedure === 'function';
8
+ const oldSchema = isProcedureSecondArgument
9
+ ? emptySchema
10
+ : oldSchemaOrNewSchema;
11
+ const newSchema = isProcedureSecondArgument
12
+ ? oldSchemaOrNewSchema
13
+ : newSchemaOrProcedure;
14
+ const procedure = isProcedureSecondArgument
15
+ ? newSchemaOrProcedure
16
+ : procedureIfTwoSchemas;
17
+ // diff to determine changed collections
18
+ const changedCollections = Object.keys(newSchema.collections).filter((key) => oldSchema.collections[key] &&
19
+ stableStringify(oldSchema.collections[key]) !==
20
+ stableStringify(newSchema.collections[key]));
21
+ const removedCollections = Object.keys(oldSchema.collections).filter((key) => !newSchema.collections[key]);
22
+ const addedCollections = Object.keys(newSchema.collections).filter((key) => !oldSchema.collections[key]);
23
+ // collections which added one or more field defaults
24
+ const autoMigratedCollections = new Set();
25
+ for (const collection of changedCollections) {
26
+ const oldFields = oldSchema.collections[collection].fields;
27
+ const newFields = newSchema.collections[collection].fields;
28
+ // a new default was added - we can auto-migrate it
29
+ if (Object.keys(newFields).some((key) => { var _a, _b; return !((_a = oldFields[key]) === null || _a === void 0 ? void 0 : _a.default) && ((_b = newFields[key]) === null || _b === void 0 ? void 0 : _b.default); })) {
30
+ autoMigratedCollections.add(collection);
31
+ }
32
+ // a field was removed - we can auto-migrate it
33
+ if (Object.keys(oldFields).some((key) => !newFields[key])) {
34
+ autoMigratedCollections.add(collection);
35
+ }
36
+ }
37
+ const addedIndexes = {};
38
+ const removedIndexes = {};
39
+ for (const changed of [...changedCollections, ...addedCollections]) {
40
+ const oldIndexes = getIndexes(oldSchema.collections[changed]);
41
+ const newIndexes = getIndexes(newSchema.collections[changed]);
42
+ const added = newIndexes.filter((index) => !oldIndexes.find((i) => i.name === index.name));
43
+ const removed = oldIndexes.filter((index) => !newIndexes.find((i) => i.name === index.name));
44
+ if (added.length > 0) {
45
+ addedIndexes[changed] = added;
46
+ // FIXME: don't o(n^2) this
47
+ if (changedCollections.includes(changed)) {
48
+ autoMigratedCollections.add(changed);
49
+ }
50
+ }
51
+ if (removed.length > 0) {
52
+ removedIndexes[changed] = removed;
53
+ // FIXME: don't o(n^2) this
54
+ if (changedCollections.includes(changed)) {
55
+ autoMigratedCollections.add(changed);
56
+ }
57
+ }
58
+ }
59
+ const withDefaults = (collectionName, val) => {
60
+ return addFieldDefaults(newSchema.collections[collectionName], val);
61
+ };
62
+ const autoMigration = (collectionName) => (val) => {
63
+ const collection = newSchema.collections[collectionName];
64
+ return addFieldDefaults(collection, removeExtraProperties(collection, val));
65
+ };
66
+ return {
67
+ version: newSchema.version,
68
+ migrate: async (engine) => {
69
+ const migratedCollections = [];
70
+ await procedure({
71
+ migrate: async (collection, strategy) => {
72
+ const auto = autoMigration(collection);
73
+ const wrapped = async (val) => {
74
+ const baseValue = await strategy(val);
75
+ // assign OID from original value in case user's strategy
76
+ // involves cloning
77
+ assignOid(baseValue, getOid(val));
78
+ const result = auto(baseValue);
79
+ return result;
80
+ };
81
+ // @ts-ignore
82
+ await engine.migrate(collection, wrapped);
83
+ migratedCollections.push(collection);
84
+ // since the user migrated this one and we wrap their
85
+ // strategy with auto-migration, we can remove it from
86
+ // the auto-migration list
87
+ autoMigratedCollections.delete(collection);
88
+ },
89
+ identity: (val) => val,
90
+ withDefaults,
91
+ info: {
92
+ changedCollections,
93
+ addedCollections,
94
+ removedCollections,
95
+ },
96
+ queries: engine.queries,
97
+ mutations: engine.mutations,
98
+ });
99
+ // mandatory migration of fields which had defaults added or
100
+ // fields removed but weren't migrated by the user
101
+ if (newSchema.version > 1) {
102
+ engine.log('debug', 'auto-migrating collections with new defaults', autoMigratedCollections);
103
+ for (const name of autoMigratedCollections) {
104
+ await engine.migrate(name, autoMigration(name));
105
+ migratedCollections.push(name);
106
+ }
107
+ const unmigrated = changedCollections.filter((collection) => !migratedCollections.includes(collection));
108
+ if (unmigrated.length > 0) {
109
+ // TODO: does this deserve a full-on error?
110
+ console.error(`Unmigrated changed collections from version ${oldSchema.version} to version ${newSchema.version}:`, unmigrated);
111
+ }
112
+ }
113
+ },
114
+ removedCollections,
115
+ addedIndexes,
116
+ removedIndexes,
117
+ allCollections: Object.keys(newSchema.collections),
118
+ changedCollections,
119
+ addedCollections,
120
+ oldCollections: Object.keys(oldSchema.collections),
121
+ oldSchema,
122
+ newSchema,
123
+ };
124
+ }
125
+ export function migrationRange(from, to) {
126
+ return [...Array(to - from).keys()].map((i) => 1 + i + from);
127
+ }
128
+ function getIndexes(collection) {
129
+ if (!collection)
130
+ return [];
131
+ return [
132
+ ...Object.keys(collection.indexes || {}).map((key) => ({
133
+ name: key,
134
+ multiEntry: ['array', 'string[]', 'number[]', 'boolean[]'].includes(collection.indexes[key].type),
135
+ synthetic: true,
136
+ compound: false,
137
+ })),
138
+ ...Object.keys(collection.compounds || {}).map((key) => ({
139
+ name: key,
140
+ multiEntry: collection.compounds[key].of.some((fieldName) => (collection.fields[fieldName] || collection.indexes[fieldName])
141
+ .type === 'array'),
142
+ synthetic: false,
143
+ compound: true,
144
+ })),
145
+ ];
146
+ }
147
+ export function createDefaultMigration(schema, newSchema) {
148
+ let oldSchema = newSchema
149
+ ? schema
150
+ : {
151
+ version: 0,
152
+ collections: {},
153
+ };
154
+ return migrate(oldSchema, newSchema || schema, async ({ migrate, info }) => {
155
+ if ((newSchema || schema).version === 1)
156
+ return;
157
+ for (const collection of info.changedCollections) {
158
+ // @ts-ignore indefinite type resolution
159
+ await migrate(collection, (old) => old);
160
+ }
161
+ });
162
+ }
163
+ export function createMigration(maybeOldSchema, maybeNewSchemaOrProcedure, maybeProcedure) {
164
+ const isProcedureSecondArgument = typeof maybeNewSchemaOrProcedure === 'function' ||
165
+ maybeNewSchemaOrProcedure === undefined;
166
+ const oldSchema = isProcedureSecondArgument ? emptySchema : maybeOldSchema;
167
+ const newSchema = isProcedureSecondArgument
168
+ ? maybeOldSchema
169
+ : maybeNewSchemaOrProcedure;
170
+ const procedure = isProcedureSecondArgument
171
+ ? maybeNewSchemaOrProcedure
172
+ : maybeProcedure;
173
+ assert(oldSchema, 'Invalid arguments to createMigration');
174
+ assert(newSchema, 'Invalid arguments to createMigration');
175
+ const { changedCollections, addedCollections, removedCollections, addedIndexes, removedIndexes, autoMigratedCollections, autoMigration, } = getMigrationInfo(oldSchema, newSchema);
176
+ return {
177
+ version: newSchema.version,
178
+ migrate: async (engine) => {
179
+ const migratedCollections = [];
180
+ const migrate = async (collection, strategy) => {
181
+ const auto = autoMigration(collection);
182
+ const wrapped = async (val) => {
183
+ const baseValue = await strategy(val);
184
+ // assign OID from original value in case user's strategy
185
+ // involves cloning
186
+ assignOid(baseValue, getOid(val));
187
+ const result = auto(baseValue);
188
+ return result;
189
+ };
190
+ // @ts-ignore
191
+ await engine.migrate(collection, wrapped);
192
+ migratedCollections.push(collection);
193
+ // since the user migrated this one and we wrap their
194
+ // strategy with auto-migration, we can remove it from
195
+ // the auto-migration list
196
+ autoMigratedCollections.delete(collection);
197
+ };
198
+ await (procedure === null || procedure === void 0 ? void 0 : procedure({
199
+ migrate,
200
+ info: {
201
+ changedCollections,
202
+ addedCollections,
203
+ removedCollections,
204
+ },
205
+ queries: engine.queries,
206
+ mutations: engine.mutations,
207
+ }));
208
+ // mandatory migration of fields which had defaults added or
209
+ // fields removed but weren't migrated by the user
210
+ if (newSchema.version > 1) {
211
+ engine.log('debug', 'auto-migrating collections with new defaults', autoMigratedCollections);
212
+ for (const name of autoMigratedCollections) {
213
+ await engine.migrate(name, autoMigration(name));
214
+ migratedCollections.push(name);
215
+ }
216
+ const unmigrated = changedCollections.filter((collection) => !migratedCollections.includes(collection));
217
+ if (unmigrated.length > 0) {
218
+ // TODO: does this deserve a full-on error?
219
+ console.error(`Unmigrated changed collections from version ${oldSchema.version} to version ${newSchema.version}:`, unmigrated);
220
+ }
221
+ }
222
+ },
223
+ removedCollections,
224
+ addedIndexes,
225
+ removedIndexes,
226
+ allCollections: Object.keys(newSchema.collections),
227
+ changedCollections,
228
+ addedCollections,
229
+ oldCollections: Object.keys(oldSchema.collections),
230
+ oldSchema,
231
+ newSchema,
232
+ };
233
+ }
234
+ // common tools
235
+ function getMigrationInfo(oldSchema, newSchema) {
236
+ const changedCollections = Object.keys(newSchema.collections).filter((key) => oldSchema.collections[key] &&
237
+ stableStringify(oldSchema.collections[key]) !==
238
+ stableStringify(newSchema.collections[key]));
239
+ const removedCollections = Object.keys(oldSchema.collections).filter((key) => !newSchema.collections[key]);
240
+ const addedCollections = Object.keys(newSchema.collections).filter((key) => !oldSchema.collections[key]);
241
+ // collections which added one or more field defaults
242
+ const autoMigratedCollections = new Set();
243
+ for (const collection of changedCollections) {
244
+ const oldFields = oldSchema.collections[collection].fields;
245
+ const newFields = newSchema.collections[collection].fields;
246
+ // a new default was added - we can auto-migrate it
247
+ if (Object.keys(newFields).some((key) => !hasDefault(oldFields[key]) && hasDefault(newFields[key]))) {
248
+ autoMigratedCollections.add(collection);
249
+ }
250
+ // a field was removed - we can auto-migrate it
251
+ if (Object.keys(oldFields).some((key) => !newFields[key])) {
252
+ autoMigratedCollections.add(collection);
253
+ }
254
+ }
255
+ const addedIndexes = {};
256
+ const removedIndexes = {};
257
+ for (const changed of [...changedCollections, ...addedCollections]) {
258
+ const oldIndexes = getIndexes(oldSchema.collections[changed]);
259
+ const newIndexes = getIndexes(newSchema.collections[changed]);
260
+ const added = newIndexes.filter((index) => !oldIndexes.find((i) => i.name === index.name));
261
+ const removed = oldIndexes.filter((index) => !newIndexes.find((i) => i.name === index.name));
262
+ if (added.length > 0) {
263
+ addedIndexes[changed] = added;
264
+ // FIXME: don't o(n^2) this
265
+ if (changedCollections.includes(changed)) {
266
+ autoMigratedCollections.add(changed);
267
+ }
268
+ }
269
+ if (removed.length > 0) {
270
+ removedIndexes[changed] = removed;
271
+ // FIXME: don't o(n^2) this
272
+ if (changedCollections.includes(changed)) {
273
+ autoMigratedCollections.add(changed);
274
+ }
275
+ }
276
+ }
277
+ const withDefaults = (collectionName, val) => {
278
+ return addFieldDefaults(newSchema.collections[collectionName], val);
279
+ };
280
+ const autoMigration = (collectionName) => (val) => {
281
+ const collection = newSchema.collections[collectionName];
282
+ return addFieldDefaults(collection, removeExtraProperties(collection, val));
283
+ };
284
+ return {
285
+ changedCollections,
286
+ addedCollections,
287
+ removedCollections,
288
+ addedIndexes,
289
+ removedIndexes,
290
+ autoMigratedCollections,
291
+ withDefaults,
292
+ autoMigration,
293
+ };
294
+ }
295
295
  //# sourceMappingURL=migration.js.map