pocketbase-zod-schema 0.1.3 → 0.1.4
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 +7 -0
- package/dist/cli/index.cjs +406 -102
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +404 -100
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +409 -105
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +404 -100
- package/dist/cli/migrate.js.map +1 -1
- package/dist/index.cjs +515 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +511 -158
- package/dist/index.js.map +1 -1
- package/dist/migration/diff.cjs +21 -3
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.js +21 -3
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/index.cjs +457 -123
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +1 -1
- package/dist/migration/index.d.ts +1 -1
- package/dist/migration/index.js +456 -123
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs +432 -118
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.d.cts +34 -12
- package/dist/migration/snapshot.d.ts +34 -12
- package/dist/migration/snapshot.js +430 -117
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/mutator.d.cts +3 -3
- package/dist/mutator.d.ts +3 -3
- package/dist/schema.cjs +34 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +33 -1
- package/dist/schema.js.map +1 -1
- package/dist/types.d.cts +5 -2
- package/dist/types.d.ts +5 -2
- package/dist/user-_AM523hb.d.cts +123 -0
- package/dist/user-_AM523hb.d.ts +123 -0
- package/package.json +2 -3
- package/dist/user-C39DQ40N.d.cts +0 -53
- package/dist/user-C39DQ40N.d.ts +0 -53
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var fs2 = require('fs');
|
|
4
|
+
var path2 = require('path');
|
|
5
5
|
|
|
6
6
|
function _interopNamespace(e) {
|
|
7
7
|
if (e && e.__esModule) return e;
|
|
@@ -21,8 +21,8 @@ function _interopNamespace(e) {
|
|
|
21
21
|
return Object.freeze(n);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
var
|
|
25
|
-
var
|
|
24
|
+
var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
|
|
25
|
+
var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
|
|
26
26
|
|
|
27
27
|
// src/migration/snapshot.ts
|
|
28
28
|
|
|
@@ -71,10 +71,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
|
|
|
71
71
|
operation;
|
|
72
72
|
code;
|
|
73
73
|
originalError;
|
|
74
|
-
constructor(message,
|
|
74
|
+
constructor(message, path3, operation, code, originalError) {
|
|
75
75
|
super(message);
|
|
76
76
|
this.name = "FileSystemError";
|
|
77
|
-
this.path =
|
|
77
|
+
this.path = path3;
|
|
78
78
|
this.operation = operation;
|
|
79
79
|
this.code = code;
|
|
80
80
|
this.originalError = originalError;
|
|
@@ -105,8 +105,358 @@ Cause: ${this.originalError.message}`);
|
|
|
105
105
|
}
|
|
106
106
|
};
|
|
107
107
|
|
|
108
|
-
// src/migration/
|
|
108
|
+
// src/migration/pocketbase-converter.ts
|
|
109
109
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
110
|
+
function resolveCollectionIdToName(collectionId) {
|
|
111
|
+
if (collectionId === "_pb_users_auth_") {
|
|
112
|
+
return "Users";
|
|
113
|
+
}
|
|
114
|
+
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
115
|
+
if (nameMatch) {
|
|
116
|
+
return nameMatch[1];
|
|
117
|
+
}
|
|
118
|
+
return collectionId;
|
|
119
|
+
}
|
|
120
|
+
function convertPocketBaseCollection(pbCollection) {
|
|
121
|
+
const fields = [];
|
|
122
|
+
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
123
|
+
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
124
|
+
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
125
|
+
for (const pbField of pbCollection.fields) {
|
|
126
|
+
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const field = {
|
|
133
|
+
name: pbField.name,
|
|
134
|
+
type: pbField.type,
|
|
135
|
+
required: pbField.required || false
|
|
136
|
+
};
|
|
137
|
+
field.options = pbField.options ? { ...pbField.options } : {};
|
|
138
|
+
if (pbField.type === "select") {
|
|
139
|
+
if (pbField.values && Array.isArray(pbField.values)) {
|
|
140
|
+
field.options.values = pbField.values;
|
|
141
|
+
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
142
|
+
field.options.values = pbField.options.values;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (pbField.type === "relation") {
|
|
146
|
+
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
147
|
+
const collectionName = resolveCollectionIdToName(collectionId);
|
|
148
|
+
field.relation = {
|
|
149
|
+
collection: collectionName,
|
|
150
|
+
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
151
|
+
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
152
|
+
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
156
|
+
if (Object.keys(field.options).length === 0) {
|
|
157
|
+
delete field.options;
|
|
158
|
+
} else if (pbField.type === "select" && hasOnlyValues) ;
|
|
159
|
+
fields.push(field);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const schema = {
|
|
163
|
+
name: pbCollection.name,
|
|
164
|
+
type: pbCollection.type || "base",
|
|
165
|
+
fields
|
|
166
|
+
};
|
|
167
|
+
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
168
|
+
schema.indexes = pbCollection.indexes;
|
|
169
|
+
}
|
|
170
|
+
const rules = {};
|
|
171
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
172
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
173
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
174
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
175
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
176
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
177
|
+
if (Object.keys(rules).length > 0) {
|
|
178
|
+
schema.rules = rules;
|
|
179
|
+
schema.permissions = { ...rules };
|
|
180
|
+
}
|
|
181
|
+
return schema;
|
|
182
|
+
}
|
|
183
|
+
function convertPocketBaseMigration(migrationContent) {
|
|
184
|
+
try {
|
|
185
|
+
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
186
|
+
if (!snapshotMatch) {
|
|
187
|
+
throw new Error("Could not find snapshot array in migration file");
|
|
188
|
+
}
|
|
189
|
+
const snapshotArrayStr = snapshotMatch[1];
|
|
190
|
+
let snapshotArray;
|
|
191
|
+
try {
|
|
192
|
+
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
193
|
+
} catch (parseError) {
|
|
194
|
+
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
195
|
+
}
|
|
196
|
+
if (!Array.isArray(snapshotArray)) {
|
|
197
|
+
throw new Error("Snapshot is not an array");
|
|
198
|
+
}
|
|
199
|
+
const collections = /* @__PURE__ */ new Map();
|
|
200
|
+
for (const pbCollection of snapshotArray) {
|
|
201
|
+
if (!pbCollection.name) {
|
|
202
|
+
console.warn("Skipping collection without name");
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const schema = convertPocketBaseCollection(pbCollection);
|
|
206
|
+
collections.set(pbCollection.name, schema);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
version: SNAPSHOT_VERSION,
|
|
210
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
211
|
+
collections
|
|
212
|
+
};
|
|
213
|
+
} catch (error) {
|
|
214
|
+
throw new SnapshotError(
|
|
215
|
+
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
216
|
+
void 0,
|
|
217
|
+
"parse",
|
|
218
|
+
error instanceof Error ? error : void 0
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/migration/migration-parser.ts
|
|
224
|
+
function extractTimestampFromFilename(filename) {
|
|
225
|
+
const match = filename.match(/^(\d+)_/);
|
|
226
|
+
if (match) {
|
|
227
|
+
return parseInt(match[1], 10);
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
232
|
+
try {
|
|
233
|
+
if (!fs2__namespace.existsSync(migrationsPath)) {
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
const files = fs2__namespace.readdirSync(migrationsPath);
|
|
237
|
+
const migrationFiles = [];
|
|
238
|
+
for (const file of files) {
|
|
239
|
+
if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (!file.endsWith(".js")) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
const timestamp = extractTimestampFromFilename(file);
|
|
246
|
+
if (timestamp && timestamp > snapshotTimestamp) {
|
|
247
|
+
migrationFiles.push({
|
|
248
|
+
path: path2__namespace.join(migrationsPath, file),
|
|
249
|
+
timestamp
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
|
|
254
|
+
return migrationFiles.map((f) => f.path);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.warn(`Error finding migrations after snapshot: ${error}`);
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function parseMigrationOperationsFromContent(content) {
|
|
261
|
+
const collectionsToCreate = [];
|
|
262
|
+
const collectionsToDelete = [];
|
|
263
|
+
try {
|
|
264
|
+
let searchIndex = 0;
|
|
265
|
+
while (true) {
|
|
266
|
+
const collectionStart = content.indexOf("new Collection(", searchIndex);
|
|
267
|
+
if (collectionStart === -1) {
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
const openParen = collectionStart + "new Collection(".length;
|
|
271
|
+
let braceCount = 0;
|
|
272
|
+
let parenCount = 1;
|
|
273
|
+
let inString = false;
|
|
274
|
+
let stringChar = null;
|
|
275
|
+
let i = openParen;
|
|
276
|
+
while (i < content.length && /\s/.test(content[i])) {
|
|
277
|
+
i++;
|
|
278
|
+
}
|
|
279
|
+
if (content[i] !== "{") {
|
|
280
|
+
searchIndex = i + 1;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
const objectStart = i;
|
|
284
|
+
braceCount = 1;
|
|
285
|
+
i++;
|
|
286
|
+
while (i < content.length && (braceCount > 0 || parenCount > 0)) {
|
|
287
|
+
const char = content[i];
|
|
288
|
+
const prevChar = i > 0 ? content[i - 1] : "";
|
|
289
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
290
|
+
inString = true;
|
|
291
|
+
stringChar = char;
|
|
292
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
293
|
+
inString = false;
|
|
294
|
+
stringChar = null;
|
|
295
|
+
}
|
|
296
|
+
if (!inString) {
|
|
297
|
+
if (char === "{") braceCount++;
|
|
298
|
+
if (char === "}") braceCount--;
|
|
299
|
+
if (char === "(") parenCount++;
|
|
300
|
+
if (char === ")") parenCount--;
|
|
301
|
+
}
|
|
302
|
+
i++;
|
|
303
|
+
}
|
|
304
|
+
if (braceCount === 0 && parenCount === 0) {
|
|
305
|
+
const objectContent = content.substring(objectStart, i - 1);
|
|
306
|
+
try {
|
|
307
|
+
const collectionObj = new Function(`return ${objectContent}`)();
|
|
308
|
+
if (collectionObj && collectionObj.name) {
|
|
309
|
+
const schema = convertPocketBaseCollection(collectionObj);
|
|
310
|
+
collectionsToCreate.push(schema);
|
|
311
|
+
}
|
|
312
|
+
} catch (error) {
|
|
313
|
+
console.warn(`Failed to parse collection definition: ${error}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
searchIndex = i;
|
|
317
|
+
}
|
|
318
|
+
const deleteMatches = content.matchAll(
|
|
319
|
+
/app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
|
|
320
|
+
);
|
|
321
|
+
for (const match of deleteMatches) {
|
|
322
|
+
if (match[1]) {
|
|
323
|
+
collectionsToDelete.push(match[1]);
|
|
324
|
+
} else {
|
|
325
|
+
const varNameMatch = match[0].match(/collection_(\w+)/);
|
|
326
|
+
if (varNameMatch) {
|
|
327
|
+
const varName = `collection_${varNameMatch[1]}`;
|
|
328
|
+
const deleteIndex = content.indexOf(match[0]);
|
|
329
|
+
const beforeDelete = content.substring(0, deleteIndex);
|
|
330
|
+
const varDefMatch = beforeDelete.match(
|
|
331
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
|
|
332
|
+
);
|
|
333
|
+
if (varDefMatch && varDefMatch.length > 0) {
|
|
334
|
+
const collectionDefMatch = beforeDelete.match(
|
|
335
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
|
|
336
|
+
);
|
|
337
|
+
if (collectionDefMatch) {
|
|
338
|
+
try {
|
|
339
|
+
const collectionDefStr = collectionDefMatch[1];
|
|
340
|
+
const collectionObj = new Function(`return ${collectionDefStr}`)();
|
|
341
|
+
if (collectionObj && collectionObj.name) {
|
|
342
|
+
collectionsToDelete.push(collectionObj.name);
|
|
343
|
+
}
|
|
344
|
+
} catch {
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const findAndDeleteMatches = content.matchAll(
|
|
352
|
+
/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
|
|
353
|
+
);
|
|
354
|
+
for (const match of findAndDeleteMatches) {
|
|
355
|
+
collectionsToDelete.push(match[1]);
|
|
356
|
+
}
|
|
357
|
+
} catch (error) {
|
|
358
|
+
console.warn(`Failed to parse migration operations from content: ${error}`);
|
|
359
|
+
}
|
|
360
|
+
return { collectionsToCreate, collectionsToDelete };
|
|
361
|
+
}
|
|
362
|
+
function parseMigrationOperations(migrationContent) {
|
|
363
|
+
try {
|
|
364
|
+
const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
|
|
365
|
+
if (!migrateMatch) {
|
|
366
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
367
|
+
}
|
|
368
|
+
const startIndex = migrateMatch.index + migrateMatch[0].length;
|
|
369
|
+
let i = startIndex;
|
|
370
|
+
let parenCount = 0;
|
|
371
|
+
let foundFirstParen = false;
|
|
372
|
+
while (i < migrationContent.length) {
|
|
373
|
+
const char = migrationContent[i];
|
|
374
|
+
if (char === "(") {
|
|
375
|
+
parenCount++;
|
|
376
|
+
foundFirstParen = true;
|
|
377
|
+
i++;
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
i++;
|
|
381
|
+
}
|
|
382
|
+
if (!foundFirstParen) {
|
|
383
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
384
|
+
}
|
|
385
|
+
let inString = false;
|
|
386
|
+
let stringChar = null;
|
|
387
|
+
let foundBrace = false;
|
|
388
|
+
let braceStart = -1;
|
|
389
|
+
while (i < migrationContent.length && !foundBrace) {
|
|
390
|
+
const char = migrationContent[i];
|
|
391
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
392
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
393
|
+
inString = true;
|
|
394
|
+
stringChar = char;
|
|
395
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
396
|
+
inString = false;
|
|
397
|
+
stringChar = null;
|
|
398
|
+
}
|
|
399
|
+
if (!inString) {
|
|
400
|
+
if (char === "(") parenCount++;
|
|
401
|
+
if (char === ")") {
|
|
402
|
+
parenCount--;
|
|
403
|
+
if (parenCount === 0) {
|
|
404
|
+
i++;
|
|
405
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
406
|
+
i++;
|
|
407
|
+
}
|
|
408
|
+
if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
|
|
409
|
+
i += 2;
|
|
410
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
411
|
+
i++;
|
|
412
|
+
}
|
|
413
|
+
if (i < migrationContent.length && migrationContent[i] === "{") {
|
|
414
|
+
foundBrace = true;
|
|
415
|
+
braceStart = i + 1;
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
i++;
|
|
423
|
+
}
|
|
424
|
+
if (!foundBrace || braceStart === -1) {
|
|
425
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
426
|
+
}
|
|
427
|
+
let braceCount = 1;
|
|
428
|
+
i = braceStart;
|
|
429
|
+
inString = false;
|
|
430
|
+
stringChar = null;
|
|
431
|
+
while (i < migrationContent.length && braceCount > 0) {
|
|
432
|
+
const char = migrationContent[i];
|
|
433
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
434
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
435
|
+
inString = true;
|
|
436
|
+
stringChar = char;
|
|
437
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
438
|
+
inString = false;
|
|
439
|
+
stringChar = null;
|
|
440
|
+
}
|
|
441
|
+
if (!inString) {
|
|
442
|
+
if (char === "{") braceCount++;
|
|
443
|
+
if (char === "}") braceCount--;
|
|
444
|
+
}
|
|
445
|
+
i++;
|
|
446
|
+
}
|
|
447
|
+
if (braceCount === 0) {
|
|
448
|
+
const upMigrationContent = migrationContent.substring(braceStart, i - 1);
|
|
449
|
+
return parseMigrationOperationsFromContent(upMigrationContent);
|
|
450
|
+
}
|
|
451
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
452
|
+
} catch (error) {
|
|
453
|
+
console.warn(`Failed to parse migration operations: ${error}`);
|
|
454
|
+
return { collectionsToCreate: [], collectionsToDelete: [] };
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/migration/snapshot.ts
|
|
459
|
+
var SNAPSHOT_VERSION2 = "1.0.0";
|
|
110
460
|
var DEFAULT_SNAPSHOT_FILENAME = ".migration-snapshot.json";
|
|
111
461
|
var SNAPSHOT_MIGRATIONS = [
|
|
112
462
|
// Add migrations here as the format evolves
|
|
@@ -121,7 +471,7 @@ var DEFAULT_CONFIG = {
|
|
|
121
471
|
snapshotPath: DEFAULT_SNAPSHOT_FILENAME,
|
|
122
472
|
workspaceRoot: process.cwd(),
|
|
123
473
|
autoMigrate: true,
|
|
124
|
-
version:
|
|
474
|
+
version: SNAPSHOT_VERSION2
|
|
125
475
|
};
|
|
126
476
|
function mergeConfig(config = {}) {
|
|
127
477
|
return {
|
|
@@ -133,15 +483,15 @@ function getSnapshotPath(config = {}) {
|
|
|
133
483
|
const mergedConfig = mergeConfig(config);
|
|
134
484
|
const workspaceRoot = mergedConfig.workspaceRoot;
|
|
135
485
|
const snapshotFilename = mergedConfig.snapshotPath;
|
|
136
|
-
if (
|
|
486
|
+
if (path2__namespace.isAbsolute(snapshotFilename)) {
|
|
137
487
|
return snapshotFilename;
|
|
138
488
|
}
|
|
139
|
-
return
|
|
489
|
+
return path2__namespace.join(workspaceRoot, snapshotFilename);
|
|
140
490
|
}
|
|
141
491
|
function snapshotExists(config = {}) {
|
|
142
492
|
try {
|
|
143
493
|
const snapshotPath = getSnapshotPath(config);
|
|
144
|
-
return
|
|
494
|
+
return fs2__namespace.existsSync(snapshotPath);
|
|
145
495
|
} catch {
|
|
146
496
|
return false;
|
|
147
497
|
}
|
|
@@ -200,13 +550,13 @@ function addSnapshotMetadata(schema, config) {
|
|
|
200
550
|
function saveSnapshot(schema, config = {}) {
|
|
201
551
|
const snapshotPath = getSnapshotPath(config);
|
|
202
552
|
try {
|
|
203
|
-
const snapshotDir =
|
|
204
|
-
if (!
|
|
205
|
-
|
|
553
|
+
const snapshotDir = path2__namespace.dirname(snapshotPath);
|
|
554
|
+
if (!fs2__namespace.existsSync(snapshotDir)) {
|
|
555
|
+
fs2__namespace.mkdirSync(snapshotDir, { recursive: true });
|
|
206
556
|
}
|
|
207
557
|
const snapshotData = addSnapshotMetadata(schema, config);
|
|
208
558
|
const jsonContent = JSON.stringify(snapshotData, null, 2);
|
|
209
|
-
|
|
559
|
+
fs2__namespace.writeFileSync(snapshotPath, jsonContent, "utf-8");
|
|
210
560
|
} catch (error) {
|
|
211
561
|
handleFileSystemError(error, "write", snapshotPath);
|
|
212
562
|
}
|
|
@@ -301,7 +651,7 @@ function deserializeSnapshot(data) {
|
|
|
301
651
|
function loadSnapshot(config = {}) {
|
|
302
652
|
const snapshotPath = getSnapshotPath(config);
|
|
303
653
|
try {
|
|
304
|
-
const jsonContent =
|
|
654
|
+
const jsonContent = fs2__namespace.readFileSync(snapshotPath, "utf-8");
|
|
305
655
|
const data = parseAndValidateSnapshot(jsonContent, snapshotPath);
|
|
306
656
|
const migratedData = migrateSnapshotFormat(data, config);
|
|
307
657
|
return deserializeSnapshot(migratedData);
|
|
@@ -336,10 +686,10 @@ function mergeSnapshots(baseSnapshot, customSnapshot) {
|
|
|
336
686
|
}
|
|
337
687
|
function findLatestSnapshot(migrationsPath) {
|
|
338
688
|
try {
|
|
339
|
-
if (!
|
|
689
|
+
if (!fs2__namespace.existsSync(migrationsPath)) {
|
|
340
690
|
return null;
|
|
341
691
|
}
|
|
342
|
-
const files =
|
|
692
|
+
const files = fs2__namespace.readdirSync(migrationsPath);
|
|
343
693
|
const snapshotFiles = files.filter(
|
|
344
694
|
(file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
|
|
345
695
|
);
|
|
@@ -351,20 +701,74 @@ function findLatestSnapshot(migrationsPath) {
|
|
|
351
701
|
if (!latestSnapshot) {
|
|
352
702
|
return null;
|
|
353
703
|
}
|
|
354
|
-
return
|
|
704
|
+
return path2__namespace.join(migrationsPath, latestSnapshot);
|
|
355
705
|
} catch (error) {
|
|
356
706
|
console.warn(`Error finding latest snapshot: ${error}`);
|
|
357
707
|
return null;
|
|
358
708
|
}
|
|
359
709
|
}
|
|
710
|
+
function applyMigrationOperations(snapshot, operations) {
|
|
711
|
+
const updatedCollections = new Map(snapshot.collections);
|
|
712
|
+
for (const collectionName of operations.collectionsToDelete) {
|
|
713
|
+
updatedCollections.delete(collectionName);
|
|
714
|
+
}
|
|
715
|
+
for (const collection of operations.collectionsToCreate) {
|
|
716
|
+
updatedCollections.set(collection.name, collection);
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
...snapshot,
|
|
720
|
+
collections: updatedCollections
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
function loadSnapshotWithMigrations(config = {}) {
|
|
724
|
+
const migrationsPath = config.migrationsPath;
|
|
725
|
+
if (!migrationsPath) {
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
if (fs2__namespace.existsSync(migrationsPath) && fs2__namespace.statSync(migrationsPath).isFile()) {
|
|
729
|
+
try {
|
|
730
|
+
const migrationContent = fs2__namespace.readFileSync(migrationsPath, "utf-8");
|
|
731
|
+
return convertPocketBaseMigration(migrationContent);
|
|
732
|
+
} catch (error) {
|
|
733
|
+
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
734
|
+
return null;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
738
|
+
if (!latestSnapshotPath) {
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
try {
|
|
742
|
+
const migrationContent = fs2__namespace.readFileSync(latestSnapshotPath, "utf-8");
|
|
743
|
+
let snapshot = convertPocketBaseMigration(migrationContent);
|
|
744
|
+
const snapshotFilename = path2__namespace.basename(latestSnapshotPath);
|
|
745
|
+
const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
|
|
746
|
+
if (snapshotTimestamp) {
|
|
747
|
+
const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
|
|
748
|
+
for (const migrationFile of migrationFiles) {
|
|
749
|
+
try {
|
|
750
|
+
const migrationContent2 = fs2__namespace.readFileSync(migrationFile, "utf-8");
|
|
751
|
+
const operations = parseMigrationOperations(migrationContent2);
|
|
752
|
+
snapshot = applyMigrationOperations(snapshot, operations);
|
|
753
|
+
} catch (error) {
|
|
754
|
+
console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return snapshot;
|
|
759
|
+
} catch (error) {
|
|
760
|
+
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
761
|
+
return null;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
360
764
|
function loadSnapshotIfExists(config = {}) {
|
|
361
765
|
const migrationsPath = config.migrationsPath;
|
|
362
766
|
if (!migrationsPath) {
|
|
363
767
|
return null;
|
|
364
768
|
}
|
|
365
|
-
if (
|
|
769
|
+
if (fs2__namespace.existsSync(migrationsPath) && fs2__namespace.statSync(migrationsPath).isFile()) {
|
|
366
770
|
try {
|
|
367
|
-
const migrationContent =
|
|
771
|
+
const migrationContent = fs2__namespace.readFileSync(migrationsPath, "utf-8");
|
|
368
772
|
return convertPocketBaseMigration(migrationContent);
|
|
369
773
|
} catch (error) {
|
|
370
774
|
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
@@ -374,7 +778,7 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
374
778
|
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
375
779
|
if (latestSnapshotPath) {
|
|
376
780
|
try {
|
|
377
|
-
const migrationContent =
|
|
781
|
+
const migrationContent = fs2__namespace.readFileSync(latestSnapshotPath, "utf-8");
|
|
378
782
|
return convertPocketBaseMigration(migrationContent);
|
|
379
783
|
} catch (error) {
|
|
380
784
|
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
@@ -383,100 +787,9 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
383
787
|
}
|
|
384
788
|
return null;
|
|
385
789
|
}
|
|
386
|
-
function convertPocketBaseCollection(pbCollection) {
|
|
387
|
-
const fields = [];
|
|
388
|
-
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
389
|
-
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
390
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
391
|
-
for (const pbField of pbCollection.fields) {
|
|
392
|
-
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
393
|
-
continue;
|
|
394
|
-
}
|
|
395
|
-
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
const field = {
|
|
399
|
-
name: pbField.name,
|
|
400
|
-
type: pbField.type,
|
|
401
|
-
required: pbField.required || false
|
|
402
|
-
};
|
|
403
|
-
if (pbField.options) {
|
|
404
|
-
field.options = pbField.options;
|
|
405
|
-
}
|
|
406
|
-
if (pbField.type === "relation") {
|
|
407
|
-
field.relation = {
|
|
408
|
-
collection: pbField.options?.collectionId || "",
|
|
409
|
-
cascadeDelete: pbField.options?.cascadeDelete || false,
|
|
410
|
-
maxSelect: pbField.options?.maxSelect,
|
|
411
|
-
minSelect: pbField.options?.minSelect
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
fields.push(field);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
const schema = {
|
|
418
|
-
name: pbCollection.name,
|
|
419
|
-
type: pbCollection.type || "base",
|
|
420
|
-
fields
|
|
421
|
-
};
|
|
422
|
-
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
423
|
-
schema.indexes = pbCollection.indexes;
|
|
424
|
-
}
|
|
425
|
-
const rules = {};
|
|
426
|
-
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
427
|
-
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
428
|
-
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
429
|
-
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
430
|
-
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
431
|
-
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
432
|
-
if (Object.keys(rules).length > 0) {
|
|
433
|
-
schema.rules = rules;
|
|
434
|
-
schema.permissions = { ...rules };
|
|
435
|
-
}
|
|
436
|
-
return schema;
|
|
437
|
-
}
|
|
438
|
-
function convertPocketBaseMigration(migrationContent) {
|
|
439
|
-
try {
|
|
440
|
-
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
441
|
-
if (!snapshotMatch) {
|
|
442
|
-
throw new Error("Could not find snapshot array in migration file");
|
|
443
|
-
}
|
|
444
|
-
const snapshotArrayStr = snapshotMatch[1];
|
|
445
|
-
let snapshotArray;
|
|
446
|
-
try {
|
|
447
|
-
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
448
|
-
} catch (parseError) {
|
|
449
|
-
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
450
|
-
}
|
|
451
|
-
if (!Array.isArray(snapshotArray)) {
|
|
452
|
-
throw new Error("Snapshot is not an array");
|
|
453
|
-
}
|
|
454
|
-
const collections = /* @__PURE__ */ new Map();
|
|
455
|
-
for (const pbCollection of snapshotArray) {
|
|
456
|
-
if (!pbCollection.name) {
|
|
457
|
-
console.warn("Skipping collection without name");
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
const schema = convertPocketBaseCollection(pbCollection);
|
|
461
|
-
collections.set(pbCollection.name, schema);
|
|
462
|
-
}
|
|
463
|
-
return {
|
|
464
|
-
version: SNAPSHOT_VERSION,
|
|
465
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
466
|
-
collections
|
|
467
|
-
};
|
|
468
|
-
} catch (error) {
|
|
469
|
-
throw new SnapshotError(
|
|
470
|
-
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
471
|
-
void 0,
|
|
472
|
-
"parse",
|
|
473
|
-
error instanceof Error ? error : void 0
|
|
474
|
-
);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
790
|
function loadBaseMigration(migrationPath) {
|
|
478
791
|
try {
|
|
479
|
-
if (!
|
|
792
|
+
if (!fs2__namespace.existsSync(migrationPath)) {
|
|
480
793
|
throw new SnapshotError(
|
|
481
794
|
`Base migration file not found: ${migrationPath}
|
|
482
795
|
|
|
@@ -487,7 +800,7 @@ If the file exists in a different location, update the configuration.`,
|
|
|
487
800
|
"read"
|
|
488
801
|
);
|
|
489
802
|
}
|
|
490
|
-
const migrationContent =
|
|
803
|
+
const migrationContent = fs2__namespace.readFileSync(migrationPath, "utf-8");
|
|
491
804
|
const snapshot = convertPocketBaseMigration(migrationContent);
|
|
492
805
|
return snapshot;
|
|
493
806
|
} catch (error) {
|
|
@@ -523,14 +836,14 @@ Please ensure PocketBase is properly set up by running 'yarn setup'.`,
|
|
|
523
836
|
}
|
|
524
837
|
}
|
|
525
838
|
function getSnapshotVersion() {
|
|
526
|
-
return
|
|
839
|
+
return SNAPSHOT_VERSION2;
|
|
527
840
|
}
|
|
528
841
|
function validateSnapshot(snapshot) {
|
|
529
842
|
const issues = [];
|
|
530
843
|
if (!snapshot.version) {
|
|
531
844
|
issues.push("Missing version field");
|
|
532
|
-
} else if (compareVersions(snapshot.version,
|
|
533
|
-
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${
|
|
845
|
+
} else if (compareVersions(snapshot.version, SNAPSHOT_VERSION2) > 0) {
|
|
846
|
+
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION2}`);
|
|
534
847
|
}
|
|
535
848
|
if (!snapshot.timestamp) {
|
|
536
849
|
issues.push("Missing timestamp field");
|
|
@@ -602,6 +915,7 @@ exports.getSnapshotVersion = getSnapshotVersion;
|
|
|
602
915
|
exports.loadBaseMigration = loadBaseMigration;
|
|
603
916
|
exports.loadSnapshot = loadSnapshot;
|
|
604
917
|
exports.loadSnapshotIfExists = loadSnapshotIfExists;
|
|
918
|
+
exports.loadSnapshotWithMigrations = loadSnapshotWithMigrations;
|
|
605
919
|
exports.mergeSnapshots = mergeSnapshots;
|
|
606
920
|
exports.saveSnapshot = saveSnapshot;
|
|
607
921
|
exports.snapshotExists = snapshotExists;
|