pocketbase-zod-schema 1.0.0 → 1.0.2
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/CHANGELOG.md +16 -0
- package/README.md +28 -69
- package/dist/cli/migrate.cjs +548 -674
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +545 -671
- package/dist/cli/migrate.js.map +1 -1
- package/dist/index.cjs +37 -555
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +903 -6
- package/dist/index.d.ts +903 -6
- package/dist/index.js +38 -540
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +674 -2614
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1344 -18
- package/dist/server.d.ts +1344 -18
- package/dist/server.js +673 -2481
- package/dist/server.js.map +1 -1
- package/package.json +2 -64
- package/dist/cli/index.cjs +0 -7873
- package/dist/cli/index.cjs.map +0 -1
- package/dist/cli/index.d.cts +0 -32
- package/dist/cli/index.d.ts +0 -32
- package/dist/cli/index.js +0 -7819
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/utils/index.cjs +0 -596
- package/dist/cli/utils/index.cjs.map +0 -1
- package/dist/cli/utils/index.d.cts +0 -282
- package/dist/cli/utils/index.d.ts +0 -282
- package/dist/cli/utils/index.js +0 -542
- package/dist/cli/utils/index.js.map +0 -1
- package/dist/enums.cjs +0 -19
- package/dist/enums.cjs.map +0 -1
- package/dist/enums.d.cts +0 -11
- package/dist/enums.d.ts +0 -11
- package/dist/enums.js +0 -17
- package/dist/enums.js.map +0 -1
- package/dist/fields-B96iGprI.d.cts +0 -480
- package/dist/fields-B96iGprI.d.ts +0 -480
- package/dist/migration/analyzer.cjs +0 -1725
- package/dist/migration/analyzer.cjs.map +0 -1
- package/dist/migration/analyzer.d.cts +0 -245
- package/dist/migration/analyzer.d.ts +0 -245
- package/dist/migration/analyzer.js +0 -1684
- package/dist/migration/analyzer.js.map +0 -1
- package/dist/migration/diff.cjs +0 -943
- package/dist/migration/diff.cjs.map +0 -1
- package/dist/migration/diff.d.cts +0 -370
- package/dist/migration/diff.d.ts +0 -370
- package/dist/migration/diff.js +0 -911
- package/dist/migration/diff.js.map +0 -1
- package/dist/migration/engine.cjs +0 -3263
- package/dist/migration/engine.cjs.map +0 -1
- package/dist/migration/engine.d.cts +0 -105
- package/dist/migration/engine.d.ts +0 -105
- package/dist/migration/engine.js +0 -3173
- package/dist/migration/engine.js.map +0 -1
- package/dist/migration/generator.cjs +0 -1596
- package/dist/migration/generator.cjs.map +0 -1
- package/dist/migration/generator.d.cts +0 -493
- package/dist/migration/generator.d.ts +0 -493
- package/dist/migration/generator.js +0 -1529
- package/dist/migration/generator.js.map +0 -1
- package/dist/migration/index.cjs +0 -8190
- package/dist/migration/index.cjs.map +0 -1
- package/dist/migration/index.d.cts +0 -193
- package/dist/migration/index.d.ts +0 -193
- package/dist/migration/index.js +0 -8015
- package/dist/migration/index.js.map +0 -1
- package/dist/migration/snapshot.cjs +0 -2814
- package/dist/migration/snapshot.cjs.map +0 -1
- package/dist/migration/snapshot.d.cts +0 -186
- package/dist/migration/snapshot.d.ts +0 -186
- package/dist/migration/snapshot.js +0 -2779
- package/dist/migration/snapshot.js.map +0 -1
- package/dist/migration/utils/index.cjs +0 -891
- package/dist/migration/utils/index.cjs.map +0 -1
- package/dist/migration/utils/index.d.cts +0 -66
- package/dist/migration/utils/index.d.ts +0 -66
- package/dist/migration/utils/index.js +0 -854
- package/dist/migration/utils/index.js.map +0 -1
- package/dist/mutator.cjs +0 -355
- package/dist/mutator.cjs.map +0 -1
- package/dist/mutator.d.cts +0 -164
- package/dist/mutator.d.ts +0 -164
- package/dist/mutator.js +0 -353
- package/dist/mutator.js.map +0 -1
- package/dist/schema.cjs +0 -715
- package/dist/schema.cjs.map +0 -1
- package/dist/schema.d.cts +0 -563
- package/dist/schema.d.ts +0 -563
- package/dist/schema.js +0 -674
- package/dist/schema.js.map +0 -1
- package/dist/type-mapper-BSPTj8t5.d.cts +0 -216
- package/dist/type-mapper-D31WYDee.d.ts +0 -216
- package/dist/types-B_MLb1Ob.d.ts +0 -475
- package/dist/types-CnzfX6JH.d.cts +0 -148
- package/dist/types-Do3jyFBm.d.ts +0 -148
- package/dist/types-upZBVMfb.d.cts +0 -475
- package/dist/verify-BF72n2df.d.ts +0 -402
- package/dist/verify-DTzYpiXX.d.cts +0 -402
package/dist/migration/diff.js
DELETED
|
@@ -1,911 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from 'crypto';
|
|
2
|
-
|
|
3
|
-
// src/migration/utils/collection-id-generator.ts
|
|
4
|
-
function generateCollectionId() {
|
|
5
|
-
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
6
|
-
const idLength = 15;
|
|
7
|
-
const bytes = randomBytes(idLength);
|
|
8
|
-
let id = "pb_";
|
|
9
|
-
for (let i = 0; i < idLength; i++) {
|
|
10
|
-
const index = bytes[i] % chars.length;
|
|
11
|
-
id += chars[index];
|
|
12
|
-
}
|
|
13
|
-
return id;
|
|
14
|
-
}
|
|
15
|
-
var CollectionIdRegistry = class {
|
|
16
|
-
ids;
|
|
17
|
-
constructor() {
|
|
18
|
-
this.ids = /* @__PURE__ */ new Set();
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Generates a unique collection ID for a given collection name
|
|
22
|
-
* Retries up to 10 times if collision occurs (extremely rare)
|
|
23
|
-
* Special case: returns "_pb_users_auth_" for users collection
|
|
24
|
-
*
|
|
25
|
-
* @param collectionName - The name of the collection (optional)
|
|
26
|
-
* @returns A unique collection ID
|
|
27
|
-
* @throws Error if unable to generate unique ID after max attempts
|
|
28
|
-
*/
|
|
29
|
-
generate(collectionName) {
|
|
30
|
-
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
31
|
-
const usersId = "_pb_users_auth_";
|
|
32
|
-
if (!this.has(usersId)) {
|
|
33
|
-
this.register(usersId);
|
|
34
|
-
}
|
|
35
|
-
return usersId;
|
|
36
|
-
}
|
|
37
|
-
const maxAttempts = 10;
|
|
38
|
-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
39
|
-
const id = generateCollectionId();
|
|
40
|
-
if (!this.has(id)) {
|
|
41
|
-
this.register(id);
|
|
42
|
-
return id;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
throw new Error("Failed to generate unique collection ID after maximum attempts");
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Checks if an ID has already been registered
|
|
49
|
-
*
|
|
50
|
-
* @param id - The collection ID to check
|
|
51
|
-
* @returns True if the ID exists in the registry
|
|
52
|
-
*/
|
|
53
|
-
has(id) {
|
|
54
|
-
return this.ids.has(id);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Registers a collection ID in the registry
|
|
58
|
-
*
|
|
59
|
-
* @param id - The collection ID to register
|
|
60
|
-
*/
|
|
61
|
-
register(id) {
|
|
62
|
-
this.ids.add(id);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// src/migration/diff/config.ts
|
|
67
|
-
var DEFAULT_CONFIG = {
|
|
68
|
-
warnOnDelete: true,
|
|
69
|
-
requireForceForDestructive: true,
|
|
70
|
-
severityThreshold: "high",
|
|
71
|
-
systemCollections: ["_mfas", "_otps", "_externalAuths", "_authOrigins", "_superusers"],
|
|
72
|
-
usersSystemFields: ["id", "password", "tokenKey", "email", "emailVisibility", "verified", "created", "updated"]
|
|
73
|
-
};
|
|
74
|
-
function mergeConfig(config) {
|
|
75
|
-
return {
|
|
76
|
-
...DEFAULT_CONFIG,
|
|
77
|
-
...config
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// src/migration/diff/utils.ts
|
|
82
|
-
function isSystemCollection(collectionName, config) {
|
|
83
|
-
const mergedConfig = mergeConfig(config);
|
|
84
|
-
return mergedConfig.systemCollections.includes(collectionName);
|
|
85
|
-
}
|
|
86
|
-
function getUsersSystemFields(config) {
|
|
87
|
-
const mergedConfig = mergeConfig(config);
|
|
88
|
-
return new Set(mergedConfig.usersSystemFields);
|
|
89
|
-
}
|
|
90
|
-
function areValuesEqual(a, b) {
|
|
91
|
-
if (a === b) return true;
|
|
92
|
-
if (a == null || b == null) return false;
|
|
93
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
94
|
-
if (a.length !== b.length) return false;
|
|
95
|
-
return a.every((val, idx) => areValuesEqual(val, b[idx]));
|
|
96
|
-
}
|
|
97
|
-
if (typeof a === "object" && typeof b === "object") {
|
|
98
|
-
const keysA = Object.keys(a);
|
|
99
|
-
const keysB = Object.keys(b);
|
|
100
|
-
if (keysA.length !== keysB.length) return false;
|
|
101
|
-
return keysA.every((key) => areValuesEqual(a[key], b[key]));
|
|
102
|
-
}
|
|
103
|
-
return a === b;
|
|
104
|
-
}
|
|
105
|
-
var OPTION_ZERO_VALUES = {
|
|
106
|
-
autogeneratePattern: "",
|
|
107
|
-
pattern: "",
|
|
108
|
-
primaryKey: false,
|
|
109
|
-
convertURLs: false,
|
|
110
|
-
cost: 0,
|
|
111
|
-
hidden: false,
|
|
112
|
-
presentable: false,
|
|
113
|
-
system: false
|
|
114
|
-
};
|
|
115
|
-
function normalizeOptionValue(key, value, fieldType) {
|
|
116
|
-
if (OPTION_ZERO_VALUES[key] !== void 0 && value === OPTION_ZERO_VALUES[key]) {
|
|
117
|
-
return void 0;
|
|
118
|
-
}
|
|
119
|
-
if (key === "maxSelect" && value === 1 && (fieldType === "select" || fieldType === "file")) {
|
|
120
|
-
return void 0;
|
|
121
|
-
}
|
|
122
|
-
if (key === "maxSize" && value === 0 && fieldType === "file") {
|
|
123
|
-
return void 0;
|
|
124
|
-
}
|
|
125
|
-
if (key === "min" && value === 1 && fieldType === "number") {
|
|
126
|
-
return void 0;
|
|
127
|
-
}
|
|
128
|
-
if (fieldType === "file") {
|
|
129
|
-
if (key === "mimeTypes" && Array.isArray(value) && value.length === 0) {
|
|
130
|
-
return void 0;
|
|
131
|
-
}
|
|
132
|
-
if (key === "thumbs" && Array.isArray(value) && value.length === 0) {
|
|
133
|
-
return void 0;
|
|
134
|
-
}
|
|
135
|
-
if (key === "protected" && value === false) {
|
|
136
|
-
return void 0;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (fieldType === "autodate") {
|
|
140
|
-
if (key === "onCreate" && value === true) {
|
|
141
|
-
return void 0;
|
|
142
|
-
}
|
|
143
|
-
if (key === "onUpdate" && value === false) {
|
|
144
|
-
return void 0;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
return value;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// src/migration/diff/fields.ts
|
|
151
|
-
function findNewFields(currentFields, previousFields) {
|
|
152
|
-
const newFields = [];
|
|
153
|
-
const previousFieldNames = new Set(previousFields.map((f) => f.name));
|
|
154
|
-
for (const currentField of currentFields) {
|
|
155
|
-
if (!previousFieldNames.has(currentField.name)) {
|
|
156
|
-
newFields.push(currentField);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return newFields;
|
|
160
|
-
}
|
|
161
|
-
function findRemovedFields(currentFields, previousFields) {
|
|
162
|
-
const removedFields = [];
|
|
163
|
-
const currentFieldNames = new Set(currentFields.map((f) => f.name));
|
|
164
|
-
for (const previousField of previousFields) {
|
|
165
|
-
if (!currentFieldNames.has(previousField.name)) {
|
|
166
|
-
removedFields.push(previousField);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return removedFields;
|
|
170
|
-
}
|
|
171
|
-
function matchFieldsByName(currentFields, previousFields) {
|
|
172
|
-
const matches = [];
|
|
173
|
-
const previousFieldMap = /* @__PURE__ */ new Map();
|
|
174
|
-
for (const previousField of previousFields) {
|
|
175
|
-
previousFieldMap.set(previousField.name, previousField);
|
|
176
|
-
}
|
|
177
|
-
for (const currentField of currentFields) {
|
|
178
|
-
const previousField = previousFieldMap.get(currentField.name);
|
|
179
|
-
if (previousField) {
|
|
180
|
-
matches.push([currentField, previousField]);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return matches;
|
|
184
|
-
}
|
|
185
|
-
function compareFieldTypes(currentField, previousField) {
|
|
186
|
-
if (currentField.type !== previousField.type) {
|
|
187
|
-
return {
|
|
188
|
-
property: "type",
|
|
189
|
-
oldValue: previousField.type,
|
|
190
|
-
newValue: currentField.type
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
function compareFieldConstraints(currentField, previousField) {
|
|
196
|
-
const changes = [];
|
|
197
|
-
if (currentField.required !== previousField.required) {
|
|
198
|
-
changes.push({
|
|
199
|
-
property: "required",
|
|
200
|
-
oldValue: previousField.required,
|
|
201
|
-
newValue: currentField.required
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
if (currentField.unique !== previousField.unique) {
|
|
205
|
-
changes.push({
|
|
206
|
-
property: "unique",
|
|
207
|
-
oldValue: previousField.unique,
|
|
208
|
-
newValue: currentField.unique
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
return changes;
|
|
212
|
-
}
|
|
213
|
-
function compareFieldOptions(currentField, previousField) {
|
|
214
|
-
const changes = [];
|
|
215
|
-
const currentOptions = currentField.options || {};
|
|
216
|
-
const previousOptions = previousField.options || {};
|
|
217
|
-
const allKeys = /* @__PURE__ */ new Set([...Object.keys(currentOptions), ...Object.keys(previousOptions)]);
|
|
218
|
-
const fieldType = currentField.type;
|
|
219
|
-
for (const key of allKeys) {
|
|
220
|
-
const currentValue = currentOptions[key];
|
|
221
|
-
const previousValue = previousOptions[key];
|
|
222
|
-
const normalizedCurrent = normalizeOptionValue(key, currentValue, fieldType);
|
|
223
|
-
const normalizedPrevious = normalizeOptionValue(key, previousValue, fieldType);
|
|
224
|
-
if (normalizedCurrent === void 0 && normalizedPrevious === void 0) {
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
if (!areValuesEqual(normalizedCurrent, normalizedPrevious)) {
|
|
228
|
-
changes.push({
|
|
229
|
-
property: `options.${key}`,
|
|
230
|
-
oldValue: previousValue,
|
|
231
|
-
newValue: currentValue
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return changes;
|
|
236
|
-
}
|
|
237
|
-
function compareRelationConfigurations(currentField, previousField, collectionIdToName) {
|
|
238
|
-
const changes = [];
|
|
239
|
-
const currentRelation = currentField.relation;
|
|
240
|
-
const previousRelation = previousField.relation;
|
|
241
|
-
if (!currentRelation && !previousRelation) {
|
|
242
|
-
return changes;
|
|
243
|
-
}
|
|
244
|
-
if (!currentRelation || !previousRelation) {
|
|
245
|
-
return changes;
|
|
246
|
-
}
|
|
247
|
-
const normalizeCollection = (collection) => {
|
|
248
|
-
if (!collection) return collection;
|
|
249
|
-
if (collectionIdToName && collectionIdToName.has(collection)) {
|
|
250
|
-
return collectionIdToName.get(collection);
|
|
251
|
-
}
|
|
252
|
-
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
253
|
-
if (nameMatch) {
|
|
254
|
-
return nameMatch[1];
|
|
255
|
-
}
|
|
256
|
-
return collection;
|
|
257
|
-
};
|
|
258
|
-
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
259
|
-
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
260
|
-
if (normalizedCurrent.toLowerCase() !== normalizedPrevious.toLowerCase()) {
|
|
261
|
-
changes.push({
|
|
262
|
-
property: "relation.collection",
|
|
263
|
-
oldValue: previousRelation.collection,
|
|
264
|
-
newValue: currentRelation.collection
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
268
|
-
changes.push({
|
|
269
|
-
property: "relation.cascadeDelete",
|
|
270
|
-
oldValue: previousRelation.cascadeDelete,
|
|
271
|
-
newValue: currentRelation.cascadeDelete
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
const normalizeMax = (val) => val === 1 ? null : val;
|
|
275
|
-
const currentMax = normalizeMax(currentRelation.maxSelect);
|
|
276
|
-
const previousMax = normalizeMax(previousRelation.maxSelect);
|
|
277
|
-
if (currentMax != previousMax) {
|
|
278
|
-
changes.push({
|
|
279
|
-
property: "relation.maxSelect",
|
|
280
|
-
oldValue: previousRelation.maxSelect,
|
|
281
|
-
newValue: currentRelation.maxSelect
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
const normalizeMin = (val) => val === 0 ? null : val;
|
|
285
|
-
const currentMin = normalizeMin(currentRelation.minSelect);
|
|
286
|
-
const previousMin = normalizeMin(previousRelation.minSelect);
|
|
287
|
-
if (currentMin != previousMin) {
|
|
288
|
-
changes.push({
|
|
289
|
-
property: "relation.minSelect",
|
|
290
|
-
oldValue: previousRelation.minSelect,
|
|
291
|
-
newValue: currentRelation.minSelect
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
return changes;
|
|
295
|
-
}
|
|
296
|
-
function detectFieldChanges(currentField, previousField, collectionIdToName) {
|
|
297
|
-
const changes = [];
|
|
298
|
-
const typeChange = compareFieldTypes(currentField, previousField);
|
|
299
|
-
if (typeChange) {
|
|
300
|
-
changes.push(typeChange);
|
|
301
|
-
}
|
|
302
|
-
changes.push(...compareFieldConstraints(currentField, previousField));
|
|
303
|
-
changes.push(...compareFieldOptions(currentField, previousField));
|
|
304
|
-
if (currentField.type === "relation" && previousField.type === "relation") {
|
|
305
|
-
changes.push(...compareRelationConfigurations(currentField, previousField, collectionIdToName));
|
|
306
|
-
}
|
|
307
|
-
return changes;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// src/migration/diff/indexes.ts
|
|
311
|
-
function compareIndexes(currentIndexes = [], previousIndexes = []) {
|
|
312
|
-
const currentSet = new Set(currentIndexes);
|
|
313
|
-
const previousSet = new Set(previousIndexes);
|
|
314
|
-
const indexesToAdd = currentIndexes.filter((idx) => !previousSet.has(idx));
|
|
315
|
-
const indexesToRemove = previousIndexes.filter((idx) => !currentSet.has(idx));
|
|
316
|
-
return { indexesToAdd, indexesToRemove };
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// src/migration/diff/rules.ts
|
|
320
|
-
function compareRules(currentRules, previousRules, currentPermissions, previousPermissions) {
|
|
321
|
-
const updates = [];
|
|
322
|
-
const ruleTypes = [
|
|
323
|
-
"listRule",
|
|
324
|
-
"viewRule",
|
|
325
|
-
"createRule",
|
|
326
|
-
"updateRule",
|
|
327
|
-
"deleteRule",
|
|
328
|
-
"manageRule"
|
|
329
|
-
];
|
|
330
|
-
for (const ruleType of ruleTypes) {
|
|
331
|
-
const currentValue = currentRules?.[ruleType] ?? currentPermissions?.[ruleType] ?? null;
|
|
332
|
-
const previousValue = previousRules?.[ruleType] ?? previousPermissions?.[ruleType] ?? null;
|
|
333
|
-
if (currentValue !== previousValue) {
|
|
334
|
-
updates.push({
|
|
335
|
-
ruleType,
|
|
336
|
-
oldValue: previousValue,
|
|
337
|
-
newValue: currentValue
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
return updates;
|
|
342
|
-
}
|
|
343
|
-
function comparePermissions(currentPermissions, previousPermissions) {
|
|
344
|
-
const changes = [];
|
|
345
|
-
const ruleTypes = ["listRule", "viewRule", "createRule", "updateRule", "deleteRule", "manageRule"];
|
|
346
|
-
for (const ruleType of ruleTypes) {
|
|
347
|
-
const currentValue = currentPermissions?.[ruleType] ?? null;
|
|
348
|
-
const previousValue = previousPermissions?.[ruleType] ?? null;
|
|
349
|
-
if (currentValue !== previousValue) {
|
|
350
|
-
changes.push({
|
|
351
|
-
ruleType,
|
|
352
|
-
oldValue: previousValue,
|
|
353
|
-
newValue: currentValue
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
return changes;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// src/migration/diff/collections.ts
|
|
361
|
-
function filterSystemCollections(schema, config) {
|
|
362
|
-
const filteredCollections = /* @__PURE__ */ new Map();
|
|
363
|
-
for (const [collectionName, collectionSchema] of schema.collections) {
|
|
364
|
-
if (!isSystemCollection(collectionName, config)) {
|
|
365
|
-
filteredCollections.set(collectionName, collectionSchema);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return {
|
|
369
|
-
collections: filteredCollections
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
function findNewCollections(currentSchema, previousSnapshot) {
|
|
373
|
-
const newCollections = [];
|
|
374
|
-
if (!previousSnapshot) {
|
|
375
|
-
return Array.from(currentSchema.collections.values());
|
|
376
|
-
}
|
|
377
|
-
for (const [collectionName, collectionSchema] of currentSchema.collections) {
|
|
378
|
-
if (!previousSnapshot.collections.has(collectionName)) {
|
|
379
|
-
newCollections.push(collectionSchema);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
return newCollections;
|
|
383
|
-
}
|
|
384
|
-
function findRemovedCollections(currentSchema, previousSnapshot) {
|
|
385
|
-
const removedCollections = [];
|
|
386
|
-
if (!previousSnapshot) {
|
|
387
|
-
return removedCollections;
|
|
388
|
-
}
|
|
389
|
-
for (const [collectionName, collectionSchema] of previousSnapshot.collections) {
|
|
390
|
-
if (!currentSchema.collections.has(collectionName)) {
|
|
391
|
-
removedCollections.push(collectionSchema);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
return removedCollections;
|
|
395
|
-
}
|
|
396
|
-
function matchCollectionsByName(currentSchema, previousSnapshot) {
|
|
397
|
-
const matches = [];
|
|
398
|
-
if (!previousSnapshot) {
|
|
399
|
-
return matches;
|
|
400
|
-
}
|
|
401
|
-
const previousCollectionsLower = /* @__PURE__ */ new Map();
|
|
402
|
-
for (const [name, collection] of previousSnapshot.collections) {
|
|
403
|
-
previousCollectionsLower.set(name.toLowerCase(), [name, collection]);
|
|
404
|
-
}
|
|
405
|
-
for (const [collectionName, currentCollection] of currentSchema.collections) {
|
|
406
|
-
const previousEntry = previousCollectionsLower.get(collectionName.toLowerCase());
|
|
407
|
-
if (previousEntry) {
|
|
408
|
-
const [, previousCollection] = previousEntry;
|
|
409
|
-
matches.push([currentCollection, previousCollection]);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return matches;
|
|
413
|
-
}
|
|
414
|
-
function compareCollectionFields(currentCollection, previousCollection, config, collectionIdToName) {
|
|
415
|
-
let fieldsToAdd = findNewFields(currentCollection.fields, previousCollection.fields);
|
|
416
|
-
let fieldsToRemove = findRemovedFields(currentCollection.fields, previousCollection.fields);
|
|
417
|
-
const fieldsToModify = [];
|
|
418
|
-
if (currentCollection.name === "users") {
|
|
419
|
-
const systemFields = getUsersSystemFields(config);
|
|
420
|
-
fieldsToAdd = fieldsToAdd.filter((field) => !systemFields.has(field.name));
|
|
421
|
-
}
|
|
422
|
-
const matchedFields = matchFieldsByName(currentCollection.fields, previousCollection.fields);
|
|
423
|
-
for (const [currentField, previousField] of matchedFields) {
|
|
424
|
-
const changes = detectFieldChanges(currentField, previousField, collectionIdToName);
|
|
425
|
-
if (changes.length > 0) {
|
|
426
|
-
fieldsToModify.push({
|
|
427
|
-
fieldName: currentField.name,
|
|
428
|
-
currentDefinition: previousField,
|
|
429
|
-
newDefinition: currentField,
|
|
430
|
-
changes
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
const processedAddIndices = /* @__PURE__ */ new Set();
|
|
435
|
-
const processedRemoveIndices = /* @__PURE__ */ new Set();
|
|
436
|
-
const resolveCollectionName = (val) => {
|
|
437
|
-
if (!val) return val;
|
|
438
|
-
if (collectionIdToName && collectionIdToName.has(val)) return collectionIdToName.get(val);
|
|
439
|
-
const match = val.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
440
|
-
return match ? match[1] : val;
|
|
441
|
-
};
|
|
442
|
-
const addedByType = /* @__PURE__ */ new Map();
|
|
443
|
-
fieldsToAdd.forEach((field, index) => {
|
|
444
|
-
const type = field.type;
|
|
445
|
-
if (!addedByType.has(type)) addedByType.set(type, []);
|
|
446
|
-
addedByType.get(type).push(index);
|
|
447
|
-
});
|
|
448
|
-
const removedByType = /* @__PURE__ */ new Map();
|
|
449
|
-
fieldsToRemove.forEach((field, index) => {
|
|
450
|
-
const type = field.type;
|
|
451
|
-
if (!removedByType.has(type)) removedByType.set(type, []);
|
|
452
|
-
removedByType.get(type).push(index);
|
|
453
|
-
});
|
|
454
|
-
for (const [type, removedIndices] of removedByType) {
|
|
455
|
-
const addedIndices = addedByType.get(type);
|
|
456
|
-
if (addedIndices && addedIndices.length === 1 && removedIndices.length === 1) {
|
|
457
|
-
const addedIndex = addedIndices[0];
|
|
458
|
-
const removedIndex = removedIndices[0];
|
|
459
|
-
const addedField = fieldsToAdd[addedIndex];
|
|
460
|
-
const removedField = fieldsToRemove[removedIndex];
|
|
461
|
-
let isMatch = true;
|
|
462
|
-
if (type === "relation") {
|
|
463
|
-
const addedTarget = resolveCollectionName(addedField.relation?.collection || "");
|
|
464
|
-
const removedTarget = resolveCollectionName(removedField.relation?.collection || "");
|
|
465
|
-
if (addedTarget.toLowerCase() !== removedTarget.toLowerCase()) {
|
|
466
|
-
isMatch = false;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
if (isMatch) {
|
|
470
|
-
processedAddIndices.add(addedIndex);
|
|
471
|
-
processedRemoveIndices.add(removedIndex);
|
|
472
|
-
const changes = detectFieldChanges(addedField, removedField, collectionIdToName);
|
|
473
|
-
changes.push({
|
|
474
|
-
property: "name",
|
|
475
|
-
oldValue: removedField.name,
|
|
476
|
-
newValue: addedField.name
|
|
477
|
-
});
|
|
478
|
-
fieldsToModify.push({
|
|
479
|
-
fieldName: removedField.name,
|
|
480
|
-
// Use OLD name so generator can find it
|
|
481
|
-
currentDefinition: removedField,
|
|
482
|
-
// OLD definition
|
|
483
|
-
newDefinition: addedField,
|
|
484
|
-
// NEW definition
|
|
485
|
-
changes
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
fieldsToAdd = fieldsToAdd.filter((_, index) => !processedAddIndices.has(index));
|
|
491
|
-
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
492
|
-
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
493
|
-
}
|
|
494
|
-
function normalizeSql(query) {
|
|
495
|
-
if (!query) {
|
|
496
|
-
return "";
|
|
497
|
-
}
|
|
498
|
-
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
499
|
-
}
|
|
500
|
-
function compareViewQuery(currentCollection, previousCollection) {
|
|
501
|
-
const newValue = currentCollection.viewQuery;
|
|
502
|
-
if (typeof newValue !== "string") {
|
|
503
|
-
return void 0;
|
|
504
|
-
}
|
|
505
|
-
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
506
|
-
return void 0;
|
|
507
|
-
}
|
|
508
|
-
return {
|
|
509
|
-
oldValue: previousCollection.viewQuery ?? null,
|
|
510
|
-
newValue
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
514
|
-
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
515
|
-
if (isView) {
|
|
516
|
-
return {
|
|
517
|
-
collection: currentCollection.name,
|
|
518
|
-
fieldsToAdd: [],
|
|
519
|
-
fieldsToRemove: [],
|
|
520
|
-
fieldsToModify: [],
|
|
521
|
-
indexesToAdd: [],
|
|
522
|
-
indexesToRemove: [],
|
|
523
|
-
rulesToUpdate: compareRules(
|
|
524
|
-
currentCollection.rules,
|
|
525
|
-
previousCollection.rules,
|
|
526
|
-
currentCollection.permissions,
|
|
527
|
-
previousCollection.permissions
|
|
528
|
-
),
|
|
529
|
-
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
530
|
-
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
534
|
-
currentCollection,
|
|
535
|
-
previousCollection,
|
|
536
|
-
config,
|
|
537
|
-
collectionIdToName
|
|
538
|
-
);
|
|
539
|
-
const { indexesToAdd, indexesToRemove } = compareIndexes(currentCollection.indexes, previousCollection.indexes);
|
|
540
|
-
const rulesToUpdate = compareRules(
|
|
541
|
-
currentCollection.rules,
|
|
542
|
-
previousCollection.rules,
|
|
543
|
-
currentCollection.permissions,
|
|
544
|
-
previousCollection.permissions
|
|
545
|
-
);
|
|
546
|
-
const permissionsToUpdate = comparePermissions(currentCollection.permissions, previousCollection.permissions);
|
|
547
|
-
return {
|
|
548
|
-
collection: currentCollection.name,
|
|
549
|
-
fieldsToAdd,
|
|
550
|
-
fieldsToRemove,
|
|
551
|
-
fieldsToModify,
|
|
552
|
-
indexesToAdd,
|
|
553
|
-
indexesToRemove,
|
|
554
|
-
rulesToUpdate,
|
|
555
|
-
permissionsToUpdate
|
|
556
|
-
};
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// src/migration/diff/destructiveness.ts
|
|
560
|
-
function detectDestructiveChanges(diff, config) {
|
|
561
|
-
const destructiveChanges = [];
|
|
562
|
-
const mergedConfig = mergeConfig(config);
|
|
563
|
-
for (const collection of diff.collectionsToDelete) {
|
|
564
|
-
if (collection.type === "view") {
|
|
565
|
-
continue;
|
|
566
|
-
}
|
|
567
|
-
destructiveChanges.push({
|
|
568
|
-
type: "collection_delete",
|
|
569
|
-
severity: "high",
|
|
570
|
-
collection: collection.name,
|
|
571
|
-
description: `Delete collection: ${collection.name}`
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
for (const modification of diff.collectionsToModify) {
|
|
575
|
-
const collectionName = modification.collection;
|
|
576
|
-
for (const field of modification.fieldsToRemove) {
|
|
577
|
-
destructiveChanges.push({
|
|
578
|
-
type: "field_delete",
|
|
579
|
-
severity: "high",
|
|
580
|
-
collection: collectionName,
|
|
581
|
-
field: field.name,
|
|
582
|
-
description: `Delete field: ${collectionName}.${field.name}`
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
for (const fieldMod of modification.fieldsToModify) {
|
|
586
|
-
const typeChange = fieldMod.changes.find((c) => c.property === "type");
|
|
587
|
-
const requiredChange = fieldMod.changes.find((c) => c.property === "required" && c.newValue === true);
|
|
588
|
-
if (typeChange) {
|
|
589
|
-
destructiveChanges.push({
|
|
590
|
-
type: "type_change",
|
|
591
|
-
severity: "high",
|
|
592
|
-
collection: collectionName,
|
|
593
|
-
field: fieldMod.fieldName,
|
|
594
|
-
description: `Change field type: ${collectionName}.${fieldMod.fieldName} (${typeChange.oldValue} \u2192 ${typeChange.newValue})`,
|
|
595
|
-
oldValue: typeChange.oldValue,
|
|
596
|
-
newValue: typeChange.newValue
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
if (requiredChange && mergedConfig.severityThreshold !== "high") {
|
|
600
|
-
destructiveChanges.push({
|
|
601
|
-
type: "required_change",
|
|
602
|
-
severity: "medium",
|
|
603
|
-
collection: collectionName,
|
|
604
|
-
field: fieldMod.fieldName,
|
|
605
|
-
description: `Make field required: ${collectionName}.${fieldMod.fieldName}`,
|
|
606
|
-
oldValue: false,
|
|
607
|
-
newValue: true
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
if (mergedConfig.severityThreshold === "low") {
|
|
611
|
-
const otherChanges = fieldMod.changes.filter((c) => c.property !== "type" && c.property !== "required");
|
|
612
|
-
for (const change of otherChanges) {
|
|
613
|
-
destructiveChanges.push({
|
|
614
|
-
type: "constraint_change",
|
|
615
|
-
severity: "low",
|
|
616
|
-
collection: collectionName,
|
|
617
|
-
field: fieldMod.fieldName,
|
|
618
|
-
description: `Change constraint: ${collectionName}.${fieldMod.fieldName}.${change.property}`,
|
|
619
|
-
oldValue: change.oldValue,
|
|
620
|
-
newValue: change.newValue
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
return destructiveChanges;
|
|
627
|
-
}
|
|
628
|
-
function requiresForceFlag(diff, config) {
|
|
629
|
-
const mergedConfig = mergeConfig(config);
|
|
630
|
-
if (!mergedConfig.requireForceForDestructive) {
|
|
631
|
-
return false;
|
|
632
|
-
}
|
|
633
|
-
const destructiveChanges = detectDestructiveChanges(diff, config);
|
|
634
|
-
const relevantChanges = destructiveChanges.filter((change) => {
|
|
635
|
-
switch (mergedConfig.severityThreshold) {
|
|
636
|
-
case "high":
|
|
637
|
-
return change.severity === "high";
|
|
638
|
-
case "medium":
|
|
639
|
-
return change.severity === "high" || change.severity === "medium";
|
|
640
|
-
case "low":
|
|
641
|
-
return true;
|
|
642
|
-
default:
|
|
643
|
-
return change.severity === "high";
|
|
644
|
-
}
|
|
645
|
-
});
|
|
646
|
-
return relevantChanges.length > 0;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
// src/migration/diff/summary.ts
|
|
650
|
-
function categorizeChangesBySeverity(diff, _config) {
|
|
651
|
-
const destructive = [];
|
|
652
|
-
const nonDestructive = [];
|
|
653
|
-
for (const collection of diff.collectionsToDelete) {
|
|
654
|
-
if (collection.type === "view") {
|
|
655
|
-
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
656
|
-
} else {
|
|
657
|
-
destructive.push(`Delete collection: ${collection.name}`);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
for (const collection of diff.collectionsToCreate) {
|
|
661
|
-
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
662
|
-
}
|
|
663
|
-
for (const modification of diff.collectionsToModify) {
|
|
664
|
-
const collectionName = modification.collection;
|
|
665
|
-
for (const field of modification.fieldsToRemove) {
|
|
666
|
-
destructive.push(`Delete field: ${collectionName}.${field.name}`);
|
|
667
|
-
}
|
|
668
|
-
for (const field of modification.fieldsToAdd) {
|
|
669
|
-
nonDestructive.push(`Add field: ${collectionName}.${field.name}`);
|
|
670
|
-
}
|
|
671
|
-
for (const fieldMod of modification.fieldsToModify) {
|
|
672
|
-
const hasTypeChange = fieldMod.changes.some((c) => c.property === "type");
|
|
673
|
-
const hasRequiredChange = fieldMod.changes.some((c) => c.property === "required" && c.newValue === true);
|
|
674
|
-
if (hasTypeChange) {
|
|
675
|
-
destructive.push(
|
|
676
|
-
`Change field type: ${collectionName}.${fieldMod.fieldName} (${fieldMod.changes.find((c) => c.property === "type")?.oldValue} \u2192 ${fieldMod.changes.find((c) => c.property === "type")?.newValue})`
|
|
677
|
-
);
|
|
678
|
-
} else if (hasRequiredChange) {
|
|
679
|
-
destructive.push(`Make field required: ${collectionName}.${fieldMod.fieldName}`);
|
|
680
|
-
} else {
|
|
681
|
-
nonDestructive.push(`Modify field: ${collectionName}.${fieldMod.fieldName}`);
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
for (const _index of modification.indexesToAdd) {
|
|
685
|
-
nonDestructive.push(`Add index: ${collectionName}`);
|
|
686
|
-
}
|
|
687
|
-
for (const _index of modification.indexesToRemove) {
|
|
688
|
-
nonDestructive.push(`Remove index: ${collectionName}`);
|
|
689
|
-
}
|
|
690
|
-
for (const rule of modification.rulesToUpdate) {
|
|
691
|
-
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
692
|
-
}
|
|
693
|
-
if (modification.viewQueryUpdate) {
|
|
694
|
-
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
return { destructive, nonDestructive };
|
|
698
|
-
}
|
|
699
|
-
function generateChangeSummary(diff, config) {
|
|
700
|
-
const destructiveChanges = detectDestructiveChanges(diff, config);
|
|
701
|
-
const { nonDestructive } = categorizeChangesBySeverity(diff);
|
|
702
|
-
let fieldsToAdd = 0;
|
|
703
|
-
let fieldsToRemove = 0;
|
|
704
|
-
let fieldsToModify = 0;
|
|
705
|
-
let indexChanges = 0;
|
|
706
|
-
let ruleChanges = 0;
|
|
707
|
-
let permissionChanges = 0;
|
|
708
|
-
let viewQueryChanges = 0;
|
|
709
|
-
for (const modification of diff.collectionsToModify) {
|
|
710
|
-
fieldsToAdd += modification.fieldsToAdd.length;
|
|
711
|
-
fieldsToRemove += modification.fieldsToRemove.length;
|
|
712
|
-
fieldsToModify += modification.fieldsToModify.length;
|
|
713
|
-
indexChanges += modification.indexesToAdd.length + modification.indexesToRemove.length;
|
|
714
|
-
ruleChanges += modification.rulesToUpdate.length;
|
|
715
|
-
permissionChanges += modification.permissionsToUpdate.length;
|
|
716
|
-
if (modification.viewQueryUpdate) {
|
|
717
|
-
viewQueryChanges += 1;
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
return {
|
|
721
|
-
totalChanges: diff.collectionsToCreate.length + diff.collectionsToDelete.length + diff.collectionsToModify.length,
|
|
722
|
-
collectionsToCreate: diff.collectionsToCreate.length,
|
|
723
|
-
collectionsToDelete: diff.collectionsToDelete.length,
|
|
724
|
-
collectionsToModify: diff.collectionsToModify.length,
|
|
725
|
-
fieldsToAdd,
|
|
726
|
-
fieldsToRemove,
|
|
727
|
-
fieldsToModify,
|
|
728
|
-
indexChanges,
|
|
729
|
-
ruleChanges,
|
|
730
|
-
permissionChanges,
|
|
731
|
-
viewQueryChanges,
|
|
732
|
-
destructiveChanges,
|
|
733
|
-
nonDestructiveChanges: nonDestructive
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// src/migration/diff/filter.ts
|
|
738
|
-
function matchesPattern(text, patterns) {
|
|
739
|
-
if (!patterns || patterns.length === 0) return true;
|
|
740
|
-
return patterns.some((pattern) => {
|
|
741
|
-
try {
|
|
742
|
-
const regex = new RegExp(pattern);
|
|
743
|
-
return regex.test(text);
|
|
744
|
-
} catch {
|
|
745
|
-
return text.includes(pattern);
|
|
746
|
-
}
|
|
747
|
-
});
|
|
748
|
-
}
|
|
749
|
-
function isDestructiveFieldModification(mod) {
|
|
750
|
-
const typeChange = mod.changes.find((c) => c.property === "type");
|
|
751
|
-
const requiredChange = mod.changes.find((c) => c.property === "required" && c.newValue === true);
|
|
752
|
-
return !!(typeChange || requiredChange);
|
|
753
|
-
}
|
|
754
|
-
function filterDiff(diff, options) {
|
|
755
|
-
const { patterns = [], skipDestructive = false } = options;
|
|
756
|
-
const collectionsToCreate = diff.collectionsToCreate.filter((col) => {
|
|
757
|
-
return matchesPattern(col.name, patterns);
|
|
758
|
-
});
|
|
759
|
-
let collectionsToDelete = diff.collectionsToDelete;
|
|
760
|
-
if (skipDestructive) {
|
|
761
|
-
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
762
|
-
}
|
|
763
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
764
|
-
return matchesPattern(col.name, patterns);
|
|
765
|
-
});
|
|
766
|
-
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
767
|
-
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
768
|
-
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
769
|
-
return collectionMatches || matchesPattern(`${mod.collection}.${field.name}`, patterns);
|
|
770
|
-
});
|
|
771
|
-
let fieldsToRemove = mod.fieldsToRemove;
|
|
772
|
-
if (skipDestructive) {
|
|
773
|
-
fieldsToRemove = [];
|
|
774
|
-
} else {
|
|
775
|
-
fieldsToRemove = fieldsToRemove.filter((field) => {
|
|
776
|
-
return collectionMatches || matchesPattern(`${mod.collection}.${field.name}`, patterns);
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
let fieldsToModify = mod.fieldsToModify;
|
|
780
|
-
if (skipDestructive) {
|
|
781
|
-
fieldsToModify = fieldsToModify.filter((f) => !isDestructiveFieldModification(f));
|
|
782
|
-
}
|
|
783
|
-
fieldsToModify = fieldsToModify.filter((f) => {
|
|
784
|
-
return collectionMatches || matchesPattern(`${mod.collection}.${f.fieldName}`, patterns);
|
|
785
|
-
});
|
|
786
|
-
const indexesToAdd = collectionMatches ? mod.indexesToAdd : [];
|
|
787
|
-
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
788
|
-
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
789
|
-
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
790
|
-
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
791
|
-
return {
|
|
792
|
-
...mod,
|
|
793
|
-
fieldsToAdd,
|
|
794
|
-
fieldsToRemove,
|
|
795
|
-
fieldsToModify,
|
|
796
|
-
indexesToAdd,
|
|
797
|
-
indexesToRemove,
|
|
798
|
-
rulesToUpdate,
|
|
799
|
-
permissionsToUpdate,
|
|
800
|
-
viewQueryUpdate
|
|
801
|
-
};
|
|
802
|
-
}).filter((mod) => {
|
|
803
|
-
return mod.fieldsToAdd.length > 0 || mod.fieldsToRemove.length > 0 || mod.fieldsToModify.length > 0 || mod.indexesToAdd.length > 0 || mod.indexesToRemove.length > 0 || mod.rulesToUpdate.length > 0 || mod.permissionsToUpdate.length > 0 || mod.viewQueryUpdate !== void 0;
|
|
804
|
-
});
|
|
805
|
-
return {
|
|
806
|
-
...diff,
|
|
807
|
-
collectionsToCreate,
|
|
808
|
-
collectionsToDelete,
|
|
809
|
-
collectionsToModify
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
// src/migration/diff/index.ts
|
|
814
|
-
function hasChanges(modification) {
|
|
815
|
-
return modification.fieldsToAdd.length > 0 || modification.fieldsToRemove.length > 0 || modification.fieldsToModify.length > 0 || modification.indexesToAdd.length > 0 || modification.indexesToRemove.length > 0 || modification.rulesToUpdate.length > 0 || modification.permissionsToUpdate.length > 0 || modification.viewQueryUpdate !== void 0;
|
|
816
|
-
}
|
|
817
|
-
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
818
|
-
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
819
|
-
if (previousSnapshot) {
|
|
820
|
-
for (const [name, collection] of previousSnapshot.collections) {
|
|
821
|
-
if (collection.id) {
|
|
822
|
-
collectionIdToName.set(collection.id, name);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
const collectionsToCreate = findNewCollections(currentSchema, previousSnapshot);
|
|
827
|
-
const collectionsToDelete = findRemovedCollections(currentSchema, previousSnapshot);
|
|
828
|
-
const filteredCollectionsToCreate = collectionsToCreate.filter(
|
|
829
|
-
(collection) => !isSystemCollection(collection.name, config)
|
|
830
|
-
);
|
|
831
|
-
const filteredCollectionsToDelete = collectionsToDelete.filter(
|
|
832
|
-
(collection) => !isSystemCollection(collection.name, config)
|
|
833
|
-
);
|
|
834
|
-
const registry = new CollectionIdRegistry();
|
|
835
|
-
const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
|
|
836
|
-
if (collection.id) {
|
|
837
|
-
registry.register(collection.id);
|
|
838
|
-
return collection;
|
|
839
|
-
}
|
|
840
|
-
const id = registry.generate(collection.name);
|
|
841
|
-
return {
|
|
842
|
-
...collection,
|
|
843
|
-
id
|
|
844
|
-
};
|
|
845
|
-
});
|
|
846
|
-
const collectionsToModify = [];
|
|
847
|
-
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
848
|
-
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
849
|
-
const modification = buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName);
|
|
850
|
-
if (hasChanges(modification)) {
|
|
851
|
-
collectionsToModify.push(modification);
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
const existingCollectionIds = /* @__PURE__ */ new Map();
|
|
855
|
-
if (previousSnapshot) {
|
|
856
|
-
for (const [name, collection] of previousSnapshot.collections) {
|
|
857
|
-
if (collection.id) {
|
|
858
|
-
existingCollectionIds.set(name, collection.id);
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
return {
|
|
863
|
-
collectionsToCreate: collectionsWithIds,
|
|
864
|
-
collectionsToDelete: filteredCollectionsToDelete,
|
|
865
|
-
collectionsToModify,
|
|
866
|
-
existingCollectionIds
|
|
867
|
-
};
|
|
868
|
-
}
|
|
869
|
-
function compare(currentSchema, previousSnapshot, config) {
|
|
870
|
-
return aggregateChanges(currentSchema, previousSnapshot, config);
|
|
871
|
-
}
|
|
872
|
-
var DiffEngine = class {
|
|
873
|
-
config;
|
|
874
|
-
constructor(config) {
|
|
875
|
-
this.config = mergeConfig(config);
|
|
876
|
-
}
|
|
877
|
-
/**
|
|
878
|
-
* Compares current schema with previous snapshot
|
|
879
|
-
*/
|
|
880
|
-
compare(currentSchema, previousSnapshot) {
|
|
881
|
-
return compare(currentSchema, previousSnapshot, this.config);
|
|
882
|
-
}
|
|
883
|
-
/**
|
|
884
|
-
* Detects destructive changes in a diff
|
|
885
|
-
*/
|
|
886
|
-
detectDestructiveChanges(diff) {
|
|
887
|
-
return detectDestructiveChanges(diff, this.config);
|
|
888
|
-
}
|
|
889
|
-
/**
|
|
890
|
-
* Categorizes changes by severity
|
|
891
|
-
*/
|
|
892
|
-
categorizeChangesBySeverity(diff) {
|
|
893
|
-
return categorizeChangesBySeverity(diff, this.config);
|
|
894
|
-
}
|
|
895
|
-
/**
|
|
896
|
-
* Generates a summary of changes
|
|
897
|
-
*/
|
|
898
|
-
generateChangeSummary(diff) {
|
|
899
|
-
return generateChangeSummary(diff, this.config);
|
|
900
|
-
}
|
|
901
|
-
/**
|
|
902
|
-
* Checks if force flag is required
|
|
903
|
-
*/
|
|
904
|
-
requiresForceFlag(diff) {
|
|
905
|
-
return requiresForceFlag(diff, this.config);
|
|
906
|
-
}
|
|
907
|
-
};
|
|
908
|
-
|
|
909
|
-
export { DEFAULT_CONFIG, DiffEngine, aggregateChanges, areValuesEqual, buildCollectionModification, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, compareIndexes, comparePermissions, compareRelationConfigurations, compareRules, detectDestructiveChanges, detectFieldChanges, filterDiff, filterSystemCollections, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, generateChangeSummary, getUsersSystemFields, isSystemCollection, matchCollectionsByName, matchFieldsByName, mergeConfig, normalizeOptionValue, normalizeSql, requiresForceFlag };
|
|
910
|
-
//# sourceMappingURL=diff.js.map
|
|
911
|
-
//# sourceMappingURL=diff.js.map
|