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
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var fs3 = require('fs');
|
|
5
|
+
var path5 = require('path');
|
|
6
6
|
var chalk = require('chalk');
|
|
7
7
|
var ora = require('ora');
|
|
8
8
|
|
|
@@ -26,8 +26,8 @@ function _interopNamespace(e) {
|
|
|
26
26
|
return Object.freeze(n);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
var
|
|
30
|
-
var
|
|
29
|
+
var fs3__namespace = /*#__PURE__*/_interopNamespace(fs3);
|
|
30
|
+
var path5__namespace = /*#__PURE__*/_interopNamespace(path5);
|
|
31
31
|
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
32
32
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
33
33
|
|
|
@@ -396,6 +396,26 @@ function mergePermissions(...schemas) {
|
|
|
396
396
|
}
|
|
397
397
|
return merged;
|
|
398
398
|
}
|
|
399
|
+
var ProjectInputSchema = zod.z.object({
|
|
400
|
+
// Required fields
|
|
401
|
+
title: zod.z.string(),
|
|
402
|
+
content: zod.z.string(),
|
|
403
|
+
status: StatusEnum,
|
|
404
|
+
summary: zod.z.string().optional(),
|
|
405
|
+
OwnerUser: relationField({ collection: "Users" }),
|
|
406
|
+
SubscriberUsers: relationsField({ collection: "Users" })
|
|
407
|
+
}).extend(inputImageFileSchema);
|
|
408
|
+
var ProjectSchema = withPermissions(
|
|
409
|
+
ProjectInputSchema.omit(omitImageFilesSchema).extend(baseImageFileSchema),
|
|
410
|
+
{
|
|
411
|
+
template: "owner-only",
|
|
412
|
+
ownerField: "OwnerUser",
|
|
413
|
+
customRules: {
|
|
414
|
+
listRule: '@request.auth.id != ""',
|
|
415
|
+
viewRule: '@request.auth.id != "" && (OwnerUser = @request.auth.id || SubscriberUsers ?= @request.auth.id)'
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
);
|
|
399
419
|
var UserInputSchema = zod.z.object({
|
|
400
420
|
name: zod.z.string().optional(),
|
|
401
421
|
email: zod.z.string().email(),
|
|
@@ -871,10 +891,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
|
|
|
871
891
|
operation;
|
|
872
892
|
code;
|
|
873
893
|
originalError;
|
|
874
|
-
constructor(message,
|
|
894
|
+
constructor(message, path7, operation, code, originalError) {
|
|
875
895
|
super(message);
|
|
876
896
|
this.name = "FileSystemError";
|
|
877
|
-
this.path =
|
|
897
|
+
this.path = path7;
|
|
878
898
|
this.operation = operation;
|
|
879
899
|
this.code = code;
|
|
880
900
|
this.originalError = originalError;
|
|
@@ -1977,20 +1997,20 @@ function mergeConfig(config) {
|
|
|
1977
1997
|
}
|
|
1978
1998
|
function resolveSchemaDir(config) {
|
|
1979
1999
|
const workspaceRoot = config.workspaceRoot || process.cwd();
|
|
1980
|
-
if (
|
|
2000
|
+
if (path5__namespace.isAbsolute(config.schemaDir)) {
|
|
1981
2001
|
return config.schemaDir;
|
|
1982
2002
|
}
|
|
1983
|
-
return
|
|
2003
|
+
return path5__namespace.join(workspaceRoot, config.schemaDir);
|
|
1984
2004
|
}
|
|
1985
2005
|
function discoverSchemaFiles(config) {
|
|
1986
2006
|
const normalizedConfig = typeof config === "string" ? { schemaDir: config } : config;
|
|
1987
2007
|
const mergedConfig = mergeConfig(normalizedConfig);
|
|
1988
2008
|
const schemaDir = resolveSchemaDir(normalizedConfig);
|
|
1989
2009
|
try {
|
|
1990
|
-
if (!
|
|
2010
|
+
if (!fs3__namespace.existsSync(schemaDir)) {
|
|
1991
2011
|
throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, "access", "ENOENT");
|
|
1992
2012
|
}
|
|
1993
|
-
const files =
|
|
2013
|
+
const files = fs3__namespace.readdirSync(schemaDir);
|
|
1994
2014
|
const schemaFiles = files.filter((file) => {
|
|
1995
2015
|
const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));
|
|
1996
2016
|
if (!hasValidExtension) return false;
|
|
@@ -2006,7 +2026,7 @@ function discoverSchemaFiles(config) {
|
|
|
2006
2026
|
});
|
|
2007
2027
|
return schemaFiles.map((file) => {
|
|
2008
2028
|
const ext = mergedConfig.includeExtensions.find((ext2) => file.endsWith(ext2)) || ".ts";
|
|
2009
|
-
return
|
|
2029
|
+
return path5__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
|
|
2010
2030
|
});
|
|
2011
2031
|
} catch (error) {
|
|
2012
2032
|
if (error instanceof FileSystemError) {
|
|
@@ -2040,19 +2060,19 @@ async function importSchemaModule(filePath, config) {
|
|
|
2040
2060
|
let resolvedPath = null;
|
|
2041
2061
|
const jsPath = `${importPath}.js`;
|
|
2042
2062
|
const tsPath = `${importPath}.ts`;
|
|
2043
|
-
if (
|
|
2063
|
+
if (fs3__namespace.existsSync(jsPath)) {
|
|
2044
2064
|
resolvedPath = jsPath;
|
|
2045
|
-
} else if (
|
|
2065
|
+
} else if (fs3__namespace.existsSync(tsPath)) {
|
|
2046
2066
|
resolvedPath = tsPath;
|
|
2047
2067
|
} else {
|
|
2048
2068
|
resolvedPath = jsPath;
|
|
2049
2069
|
}
|
|
2050
|
-
const fileUrl = new URL(`file://${
|
|
2070
|
+
const fileUrl = new URL(`file://${path5__namespace.resolve(resolvedPath)}`);
|
|
2051
2071
|
const module = await import(fileUrl.href);
|
|
2052
2072
|
return module;
|
|
2053
2073
|
} catch (error) {
|
|
2054
2074
|
const tsPath = `${filePath}.ts`;
|
|
2055
|
-
const isTypeScriptFile =
|
|
2075
|
+
const isTypeScriptFile = fs3__namespace.existsSync(tsPath);
|
|
2056
2076
|
if (isTypeScriptFile) {
|
|
2057
2077
|
throw new SchemaParsingError(
|
|
2058
2078
|
`Failed to import TypeScript schema file. Node.js cannot import TypeScript files directly.
|
|
@@ -2071,7 +2091,7 @@ Please either:
|
|
|
2071
2091
|
}
|
|
2072
2092
|
}
|
|
2073
2093
|
function getCollectionNameFromFile(filePath) {
|
|
2074
|
-
const filename =
|
|
2094
|
+
const filename = path5__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
2075
2095
|
return toCollectionName(filename);
|
|
2076
2096
|
}
|
|
2077
2097
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
|
|
@@ -2236,7 +2256,7 @@ async function buildSchemaDefinition(config) {
|
|
|
2236
2256
|
importPath = normalizedConfig.pathTransformer(filePath);
|
|
2237
2257
|
} else if (mergedConfig.useCompiledFiles) {
|
|
2238
2258
|
const distPath = filePath.replace(/\/src\//, "/dist/");
|
|
2239
|
-
if (
|
|
2259
|
+
if (fs3__namespace.existsSync(`${distPath}.js`) || fs3__namespace.existsSync(`${distPath}.mjs`)) {
|
|
2240
2260
|
importPath = distPath;
|
|
2241
2261
|
} else {
|
|
2242
2262
|
importPath = filePath;
|
|
@@ -2292,7 +2312,359 @@ var SchemaAnalyzer = class {
|
|
|
2292
2312
|
return convertZodSchemaToCollectionSchema(name, schema);
|
|
2293
2313
|
}
|
|
2294
2314
|
};
|
|
2315
|
+
|
|
2316
|
+
// src/migration/pocketbase-converter.ts
|
|
2295
2317
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
2318
|
+
function resolveCollectionIdToName(collectionId) {
|
|
2319
|
+
if (collectionId === "_pb_users_auth_") {
|
|
2320
|
+
return "Users";
|
|
2321
|
+
}
|
|
2322
|
+
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
2323
|
+
if (nameMatch) {
|
|
2324
|
+
return nameMatch[1];
|
|
2325
|
+
}
|
|
2326
|
+
return collectionId;
|
|
2327
|
+
}
|
|
2328
|
+
function convertPocketBaseCollection(pbCollection) {
|
|
2329
|
+
const fields = [];
|
|
2330
|
+
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
2331
|
+
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
2332
|
+
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2333
|
+
for (const pbField of pbCollection.fields) {
|
|
2334
|
+
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
2335
|
+
continue;
|
|
2336
|
+
}
|
|
2337
|
+
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
2338
|
+
continue;
|
|
2339
|
+
}
|
|
2340
|
+
const field = {
|
|
2341
|
+
name: pbField.name,
|
|
2342
|
+
type: pbField.type,
|
|
2343
|
+
required: pbField.required || false
|
|
2344
|
+
};
|
|
2345
|
+
field.options = pbField.options ? { ...pbField.options } : {};
|
|
2346
|
+
if (pbField.type === "select") {
|
|
2347
|
+
if (pbField.values && Array.isArray(pbField.values)) {
|
|
2348
|
+
field.options.values = pbField.values;
|
|
2349
|
+
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
2350
|
+
field.options.values = pbField.options.values;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
if (pbField.type === "relation") {
|
|
2354
|
+
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
2355
|
+
const collectionName = resolveCollectionIdToName(collectionId);
|
|
2356
|
+
field.relation = {
|
|
2357
|
+
collection: collectionName,
|
|
2358
|
+
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
2359
|
+
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
2360
|
+
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
2364
|
+
if (Object.keys(field.options).length === 0) {
|
|
2365
|
+
delete field.options;
|
|
2366
|
+
} else if (pbField.type === "select" && hasOnlyValues) ;
|
|
2367
|
+
fields.push(field);
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
const schema = {
|
|
2371
|
+
name: pbCollection.name,
|
|
2372
|
+
type: pbCollection.type || "base",
|
|
2373
|
+
fields
|
|
2374
|
+
};
|
|
2375
|
+
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2376
|
+
schema.indexes = pbCollection.indexes;
|
|
2377
|
+
}
|
|
2378
|
+
const rules = {};
|
|
2379
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
2380
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
2381
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
2382
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
2383
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
2384
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
2385
|
+
if (Object.keys(rules).length > 0) {
|
|
2386
|
+
schema.rules = rules;
|
|
2387
|
+
schema.permissions = { ...rules };
|
|
2388
|
+
}
|
|
2389
|
+
return schema;
|
|
2390
|
+
}
|
|
2391
|
+
function convertPocketBaseMigration(migrationContent) {
|
|
2392
|
+
try {
|
|
2393
|
+
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
2394
|
+
if (!snapshotMatch) {
|
|
2395
|
+
throw new Error("Could not find snapshot array in migration file");
|
|
2396
|
+
}
|
|
2397
|
+
const snapshotArrayStr = snapshotMatch[1];
|
|
2398
|
+
let snapshotArray;
|
|
2399
|
+
try {
|
|
2400
|
+
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
2401
|
+
} catch (parseError) {
|
|
2402
|
+
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
2403
|
+
}
|
|
2404
|
+
if (!Array.isArray(snapshotArray)) {
|
|
2405
|
+
throw new Error("Snapshot is not an array");
|
|
2406
|
+
}
|
|
2407
|
+
const collections = /* @__PURE__ */ new Map();
|
|
2408
|
+
for (const pbCollection of snapshotArray) {
|
|
2409
|
+
if (!pbCollection.name) {
|
|
2410
|
+
console.warn("Skipping collection without name");
|
|
2411
|
+
continue;
|
|
2412
|
+
}
|
|
2413
|
+
const schema = convertPocketBaseCollection(pbCollection);
|
|
2414
|
+
collections.set(pbCollection.name, schema);
|
|
2415
|
+
}
|
|
2416
|
+
return {
|
|
2417
|
+
version: SNAPSHOT_VERSION,
|
|
2418
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2419
|
+
collections
|
|
2420
|
+
};
|
|
2421
|
+
} catch (error) {
|
|
2422
|
+
throw new SnapshotError(
|
|
2423
|
+
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
2424
|
+
void 0,
|
|
2425
|
+
"parse",
|
|
2426
|
+
error instanceof Error ? error : void 0
|
|
2427
|
+
);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
// src/migration/migration-parser.ts
|
|
2432
|
+
function extractTimestampFromFilename(filename) {
|
|
2433
|
+
const match = filename.match(/^(\d+)_/);
|
|
2434
|
+
if (match) {
|
|
2435
|
+
return parseInt(match[1], 10);
|
|
2436
|
+
}
|
|
2437
|
+
return null;
|
|
2438
|
+
}
|
|
2439
|
+
function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
2440
|
+
try {
|
|
2441
|
+
if (!fs3__namespace.existsSync(migrationsPath)) {
|
|
2442
|
+
return [];
|
|
2443
|
+
}
|
|
2444
|
+
const files = fs3__namespace.readdirSync(migrationsPath);
|
|
2445
|
+
const migrationFiles = [];
|
|
2446
|
+
for (const file of files) {
|
|
2447
|
+
if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
|
|
2448
|
+
continue;
|
|
2449
|
+
}
|
|
2450
|
+
if (!file.endsWith(".js")) {
|
|
2451
|
+
continue;
|
|
2452
|
+
}
|
|
2453
|
+
const timestamp = extractTimestampFromFilename(file);
|
|
2454
|
+
if (timestamp && timestamp > snapshotTimestamp) {
|
|
2455
|
+
migrationFiles.push({
|
|
2456
|
+
path: path5__namespace.join(migrationsPath, file),
|
|
2457
|
+
timestamp
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
|
|
2462
|
+
return migrationFiles.map((f) => f.path);
|
|
2463
|
+
} catch (error) {
|
|
2464
|
+
console.warn(`Error finding migrations after snapshot: ${error}`);
|
|
2465
|
+
return [];
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
function parseMigrationOperationsFromContent(content) {
|
|
2469
|
+
const collectionsToCreate = [];
|
|
2470
|
+
const collectionsToDelete = [];
|
|
2471
|
+
try {
|
|
2472
|
+
let searchIndex = 0;
|
|
2473
|
+
while (true) {
|
|
2474
|
+
const collectionStart = content.indexOf("new Collection(", searchIndex);
|
|
2475
|
+
if (collectionStart === -1) {
|
|
2476
|
+
break;
|
|
2477
|
+
}
|
|
2478
|
+
const openParen = collectionStart + "new Collection(".length;
|
|
2479
|
+
let braceCount = 0;
|
|
2480
|
+
let parenCount = 1;
|
|
2481
|
+
let inString = false;
|
|
2482
|
+
let stringChar = null;
|
|
2483
|
+
let i = openParen;
|
|
2484
|
+
while (i < content.length && /\s/.test(content[i])) {
|
|
2485
|
+
i++;
|
|
2486
|
+
}
|
|
2487
|
+
if (content[i] !== "{") {
|
|
2488
|
+
searchIndex = i + 1;
|
|
2489
|
+
continue;
|
|
2490
|
+
}
|
|
2491
|
+
const objectStart = i;
|
|
2492
|
+
braceCount = 1;
|
|
2493
|
+
i++;
|
|
2494
|
+
while (i < content.length && (braceCount > 0 || parenCount > 0)) {
|
|
2495
|
+
const char = content[i];
|
|
2496
|
+
const prevChar = i > 0 ? content[i - 1] : "";
|
|
2497
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
2498
|
+
inString = true;
|
|
2499
|
+
stringChar = char;
|
|
2500
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
2501
|
+
inString = false;
|
|
2502
|
+
stringChar = null;
|
|
2503
|
+
}
|
|
2504
|
+
if (!inString) {
|
|
2505
|
+
if (char === "{") braceCount++;
|
|
2506
|
+
if (char === "}") braceCount--;
|
|
2507
|
+
if (char === "(") parenCount++;
|
|
2508
|
+
if (char === ")") parenCount--;
|
|
2509
|
+
}
|
|
2510
|
+
i++;
|
|
2511
|
+
}
|
|
2512
|
+
if (braceCount === 0 && parenCount === 0) {
|
|
2513
|
+
const objectContent = content.substring(objectStart, i - 1);
|
|
2514
|
+
try {
|
|
2515
|
+
const collectionObj = new Function(`return ${objectContent}`)();
|
|
2516
|
+
if (collectionObj && collectionObj.name) {
|
|
2517
|
+
const schema = convertPocketBaseCollection(collectionObj);
|
|
2518
|
+
collectionsToCreate.push(schema);
|
|
2519
|
+
}
|
|
2520
|
+
} catch (error) {
|
|
2521
|
+
console.warn(`Failed to parse collection definition: ${error}`);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
searchIndex = i;
|
|
2525
|
+
}
|
|
2526
|
+
const deleteMatches = content.matchAll(
|
|
2527
|
+
/app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
|
|
2528
|
+
);
|
|
2529
|
+
for (const match of deleteMatches) {
|
|
2530
|
+
if (match[1]) {
|
|
2531
|
+
collectionsToDelete.push(match[1]);
|
|
2532
|
+
} else {
|
|
2533
|
+
const varNameMatch = match[0].match(/collection_(\w+)/);
|
|
2534
|
+
if (varNameMatch) {
|
|
2535
|
+
const varName = `collection_${varNameMatch[1]}`;
|
|
2536
|
+
const deleteIndex = content.indexOf(match[0]);
|
|
2537
|
+
const beforeDelete = content.substring(0, deleteIndex);
|
|
2538
|
+
const varDefMatch = beforeDelete.match(
|
|
2539
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
|
|
2540
|
+
);
|
|
2541
|
+
if (varDefMatch && varDefMatch.length > 0) {
|
|
2542
|
+
const collectionDefMatch = beforeDelete.match(
|
|
2543
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
|
|
2544
|
+
);
|
|
2545
|
+
if (collectionDefMatch) {
|
|
2546
|
+
try {
|
|
2547
|
+
const collectionDefStr = collectionDefMatch[1];
|
|
2548
|
+
const collectionObj = new Function(`return ${collectionDefStr}`)();
|
|
2549
|
+
if (collectionObj && collectionObj.name) {
|
|
2550
|
+
collectionsToDelete.push(collectionObj.name);
|
|
2551
|
+
}
|
|
2552
|
+
} catch {
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
const findAndDeleteMatches = content.matchAll(
|
|
2560
|
+
/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
|
|
2561
|
+
);
|
|
2562
|
+
for (const match of findAndDeleteMatches) {
|
|
2563
|
+
collectionsToDelete.push(match[1]);
|
|
2564
|
+
}
|
|
2565
|
+
} catch (error) {
|
|
2566
|
+
console.warn(`Failed to parse migration operations from content: ${error}`);
|
|
2567
|
+
}
|
|
2568
|
+
return { collectionsToCreate, collectionsToDelete };
|
|
2569
|
+
}
|
|
2570
|
+
function parseMigrationOperations(migrationContent) {
|
|
2571
|
+
try {
|
|
2572
|
+
const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
|
|
2573
|
+
if (!migrateMatch) {
|
|
2574
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2575
|
+
}
|
|
2576
|
+
const startIndex = migrateMatch.index + migrateMatch[0].length;
|
|
2577
|
+
let i = startIndex;
|
|
2578
|
+
let parenCount = 0;
|
|
2579
|
+
let foundFirstParen = false;
|
|
2580
|
+
while (i < migrationContent.length) {
|
|
2581
|
+
const char = migrationContent[i];
|
|
2582
|
+
if (char === "(") {
|
|
2583
|
+
parenCount++;
|
|
2584
|
+
foundFirstParen = true;
|
|
2585
|
+
i++;
|
|
2586
|
+
break;
|
|
2587
|
+
}
|
|
2588
|
+
i++;
|
|
2589
|
+
}
|
|
2590
|
+
if (!foundFirstParen) {
|
|
2591
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2592
|
+
}
|
|
2593
|
+
let inString = false;
|
|
2594
|
+
let stringChar = null;
|
|
2595
|
+
let foundBrace = false;
|
|
2596
|
+
let braceStart = -1;
|
|
2597
|
+
while (i < migrationContent.length && !foundBrace) {
|
|
2598
|
+
const char = migrationContent[i];
|
|
2599
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2600
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
2601
|
+
inString = true;
|
|
2602
|
+
stringChar = char;
|
|
2603
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
2604
|
+
inString = false;
|
|
2605
|
+
stringChar = null;
|
|
2606
|
+
}
|
|
2607
|
+
if (!inString) {
|
|
2608
|
+
if (char === "(") parenCount++;
|
|
2609
|
+
if (char === ")") {
|
|
2610
|
+
parenCount--;
|
|
2611
|
+
if (parenCount === 0) {
|
|
2612
|
+
i++;
|
|
2613
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
2614
|
+
i++;
|
|
2615
|
+
}
|
|
2616
|
+
if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
|
|
2617
|
+
i += 2;
|
|
2618
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
2619
|
+
i++;
|
|
2620
|
+
}
|
|
2621
|
+
if (i < migrationContent.length && migrationContent[i] === "{") {
|
|
2622
|
+
foundBrace = true;
|
|
2623
|
+
braceStart = i + 1;
|
|
2624
|
+
break;
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
i++;
|
|
2631
|
+
}
|
|
2632
|
+
if (!foundBrace || braceStart === -1) {
|
|
2633
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2634
|
+
}
|
|
2635
|
+
let braceCount = 1;
|
|
2636
|
+
i = braceStart;
|
|
2637
|
+
inString = false;
|
|
2638
|
+
stringChar = null;
|
|
2639
|
+
while (i < migrationContent.length && braceCount > 0) {
|
|
2640
|
+
const char = migrationContent[i];
|
|
2641
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2642
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
2643
|
+
inString = true;
|
|
2644
|
+
stringChar = char;
|
|
2645
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
2646
|
+
inString = false;
|
|
2647
|
+
stringChar = null;
|
|
2648
|
+
}
|
|
2649
|
+
if (!inString) {
|
|
2650
|
+
if (char === "{") braceCount++;
|
|
2651
|
+
if (char === "}") braceCount--;
|
|
2652
|
+
}
|
|
2653
|
+
i++;
|
|
2654
|
+
}
|
|
2655
|
+
if (braceCount === 0) {
|
|
2656
|
+
const upMigrationContent = migrationContent.substring(braceStart, i - 1);
|
|
2657
|
+
return parseMigrationOperationsFromContent(upMigrationContent);
|
|
2658
|
+
}
|
|
2659
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2660
|
+
} catch (error) {
|
|
2661
|
+
console.warn(`Failed to parse migration operations: ${error}`);
|
|
2662
|
+
return { collectionsToCreate: [], collectionsToDelete: [] };
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
// src/migration/snapshot.ts
|
|
2667
|
+
var SNAPSHOT_VERSION2 = "1.0.0";
|
|
2296
2668
|
var DEFAULT_SNAPSHOT_FILENAME = ".migration-snapshot.json";
|
|
2297
2669
|
var SNAPSHOT_MIGRATIONS = [
|
|
2298
2670
|
// Add migrations here as the format evolves
|
|
@@ -2307,7 +2679,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
2307
2679
|
snapshotPath: DEFAULT_SNAPSHOT_FILENAME,
|
|
2308
2680
|
workspaceRoot: process.cwd(),
|
|
2309
2681
|
autoMigrate: true,
|
|
2310
|
-
version:
|
|
2682
|
+
version: SNAPSHOT_VERSION2
|
|
2311
2683
|
};
|
|
2312
2684
|
function mergeConfig2(config = {}) {
|
|
2313
2685
|
return {
|
|
@@ -2319,15 +2691,15 @@ function getSnapshotPath(config = {}) {
|
|
|
2319
2691
|
const mergedConfig = mergeConfig2(config);
|
|
2320
2692
|
const workspaceRoot = mergedConfig.workspaceRoot;
|
|
2321
2693
|
const snapshotFilename = mergedConfig.snapshotPath;
|
|
2322
|
-
if (
|
|
2694
|
+
if (path5__namespace.isAbsolute(snapshotFilename)) {
|
|
2323
2695
|
return snapshotFilename;
|
|
2324
2696
|
}
|
|
2325
|
-
return
|
|
2697
|
+
return path5__namespace.join(workspaceRoot, snapshotFilename);
|
|
2326
2698
|
}
|
|
2327
2699
|
function snapshotExists(config = {}) {
|
|
2328
2700
|
try {
|
|
2329
2701
|
const snapshotPath = getSnapshotPath(config);
|
|
2330
|
-
return
|
|
2702
|
+
return fs3__namespace.existsSync(snapshotPath);
|
|
2331
2703
|
} catch {
|
|
2332
2704
|
return false;
|
|
2333
2705
|
}
|
|
@@ -2386,13 +2758,13 @@ function addSnapshotMetadata(schema, config) {
|
|
|
2386
2758
|
function saveSnapshot(schema, config = {}) {
|
|
2387
2759
|
const snapshotPath = getSnapshotPath(config);
|
|
2388
2760
|
try {
|
|
2389
|
-
const snapshotDir =
|
|
2390
|
-
if (!
|
|
2391
|
-
|
|
2761
|
+
const snapshotDir = path5__namespace.dirname(snapshotPath);
|
|
2762
|
+
if (!fs3__namespace.existsSync(snapshotDir)) {
|
|
2763
|
+
fs3__namespace.mkdirSync(snapshotDir, { recursive: true });
|
|
2392
2764
|
}
|
|
2393
2765
|
const snapshotData = addSnapshotMetadata(schema, config);
|
|
2394
2766
|
const jsonContent = JSON.stringify(snapshotData, null, 2);
|
|
2395
|
-
|
|
2767
|
+
fs3__namespace.writeFileSync(snapshotPath, jsonContent, "utf-8");
|
|
2396
2768
|
} catch (error) {
|
|
2397
2769
|
handleFileSystemError(error, "write", snapshotPath);
|
|
2398
2770
|
}
|
|
@@ -2487,7 +2859,7 @@ function deserializeSnapshot(data) {
|
|
|
2487
2859
|
function loadSnapshot(config = {}) {
|
|
2488
2860
|
const snapshotPath = getSnapshotPath(config);
|
|
2489
2861
|
try {
|
|
2490
|
-
const jsonContent =
|
|
2862
|
+
const jsonContent = fs3__namespace.readFileSync(snapshotPath, "utf-8");
|
|
2491
2863
|
const data = parseAndValidateSnapshot(jsonContent, snapshotPath);
|
|
2492
2864
|
const migratedData = migrateSnapshotFormat(data, config);
|
|
2493
2865
|
return deserializeSnapshot(migratedData);
|
|
@@ -2522,10 +2894,10 @@ function mergeSnapshots(baseSnapshot, customSnapshot) {
|
|
|
2522
2894
|
}
|
|
2523
2895
|
function findLatestSnapshot(migrationsPath) {
|
|
2524
2896
|
try {
|
|
2525
|
-
if (!
|
|
2897
|
+
if (!fs3__namespace.existsSync(migrationsPath)) {
|
|
2526
2898
|
return null;
|
|
2527
2899
|
}
|
|
2528
|
-
const files =
|
|
2900
|
+
const files = fs3__namespace.readdirSync(migrationsPath);
|
|
2529
2901
|
const snapshotFiles = files.filter(
|
|
2530
2902
|
(file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
|
|
2531
2903
|
);
|
|
@@ -2537,20 +2909,74 @@ function findLatestSnapshot(migrationsPath) {
|
|
|
2537
2909
|
if (!latestSnapshot) {
|
|
2538
2910
|
return null;
|
|
2539
2911
|
}
|
|
2540
|
-
return
|
|
2912
|
+
return path5__namespace.join(migrationsPath, latestSnapshot);
|
|
2541
2913
|
} catch (error) {
|
|
2542
2914
|
console.warn(`Error finding latest snapshot: ${error}`);
|
|
2543
2915
|
return null;
|
|
2544
2916
|
}
|
|
2545
2917
|
}
|
|
2918
|
+
function applyMigrationOperations(snapshot, operations) {
|
|
2919
|
+
const updatedCollections = new Map(snapshot.collections);
|
|
2920
|
+
for (const collectionName of operations.collectionsToDelete) {
|
|
2921
|
+
updatedCollections.delete(collectionName);
|
|
2922
|
+
}
|
|
2923
|
+
for (const collection of operations.collectionsToCreate) {
|
|
2924
|
+
updatedCollections.set(collection.name, collection);
|
|
2925
|
+
}
|
|
2926
|
+
return {
|
|
2927
|
+
...snapshot,
|
|
2928
|
+
collections: updatedCollections
|
|
2929
|
+
};
|
|
2930
|
+
}
|
|
2931
|
+
function loadSnapshotWithMigrations(config = {}) {
|
|
2932
|
+
const migrationsPath = config.migrationsPath;
|
|
2933
|
+
if (!migrationsPath) {
|
|
2934
|
+
return null;
|
|
2935
|
+
}
|
|
2936
|
+
if (fs3__namespace.existsSync(migrationsPath) && fs3__namespace.statSync(migrationsPath).isFile()) {
|
|
2937
|
+
try {
|
|
2938
|
+
const migrationContent = fs3__namespace.readFileSync(migrationsPath, "utf-8");
|
|
2939
|
+
return convertPocketBaseMigration(migrationContent);
|
|
2940
|
+
} catch (error) {
|
|
2941
|
+
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
2942
|
+
return null;
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
2946
|
+
if (!latestSnapshotPath) {
|
|
2947
|
+
return null;
|
|
2948
|
+
}
|
|
2949
|
+
try {
|
|
2950
|
+
const migrationContent = fs3__namespace.readFileSync(latestSnapshotPath, "utf-8");
|
|
2951
|
+
let snapshot = convertPocketBaseMigration(migrationContent);
|
|
2952
|
+
const snapshotFilename = path5__namespace.basename(latestSnapshotPath);
|
|
2953
|
+
const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
|
|
2954
|
+
if (snapshotTimestamp) {
|
|
2955
|
+
const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
|
|
2956
|
+
for (const migrationFile of migrationFiles) {
|
|
2957
|
+
try {
|
|
2958
|
+
const migrationContent2 = fs3__namespace.readFileSync(migrationFile, "utf-8");
|
|
2959
|
+
const operations = parseMigrationOperations(migrationContent2);
|
|
2960
|
+
snapshot = applyMigrationOperations(snapshot, operations);
|
|
2961
|
+
} catch (error) {
|
|
2962
|
+
console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
return snapshot;
|
|
2967
|
+
} catch (error) {
|
|
2968
|
+
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
2969
|
+
return null;
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2546
2972
|
function loadSnapshotIfExists(config = {}) {
|
|
2547
2973
|
const migrationsPath = config.migrationsPath;
|
|
2548
2974
|
if (!migrationsPath) {
|
|
2549
2975
|
return null;
|
|
2550
2976
|
}
|
|
2551
|
-
if (
|
|
2977
|
+
if (fs3__namespace.existsSync(migrationsPath) && fs3__namespace.statSync(migrationsPath).isFile()) {
|
|
2552
2978
|
try {
|
|
2553
|
-
const migrationContent =
|
|
2979
|
+
const migrationContent = fs3__namespace.readFileSync(migrationsPath, "utf-8");
|
|
2554
2980
|
return convertPocketBaseMigration(migrationContent);
|
|
2555
2981
|
} catch (error) {
|
|
2556
2982
|
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
@@ -2560,7 +2986,7 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
2560
2986
|
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
2561
2987
|
if (latestSnapshotPath) {
|
|
2562
2988
|
try {
|
|
2563
|
-
const migrationContent =
|
|
2989
|
+
const migrationContent = fs3__namespace.readFileSync(latestSnapshotPath, "utf-8");
|
|
2564
2990
|
return convertPocketBaseMigration(migrationContent);
|
|
2565
2991
|
} catch (error) {
|
|
2566
2992
|
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
@@ -2569,100 +2995,9 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
2569
2995
|
}
|
|
2570
2996
|
return null;
|
|
2571
2997
|
}
|
|
2572
|
-
function convertPocketBaseCollection(pbCollection) {
|
|
2573
|
-
const fields = [];
|
|
2574
|
-
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
2575
|
-
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
2576
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2577
|
-
for (const pbField of pbCollection.fields) {
|
|
2578
|
-
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
2579
|
-
continue;
|
|
2580
|
-
}
|
|
2581
|
-
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
2582
|
-
continue;
|
|
2583
|
-
}
|
|
2584
|
-
const field = {
|
|
2585
|
-
name: pbField.name,
|
|
2586
|
-
type: pbField.type,
|
|
2587
|
-
required: pbField.required || false
|
|
2588
|
-
};
|
|
2589
|
-
if (pbField.options) {
|
|
2590
|
-
field.options = pbField.options;
|
|
2591
|
-
}
|
|
2592
|
-
if (pbField.type === "relation") {
|
|
2593
|
-
field.relation = {
|
|
2594
|
-
collection: pbField.options?.collectionId || "",
|
|
2595
|
-
cascadeDelete: pbField.options?.cascadeDelete || false,
|
|
2596
|
-
maxSelect: pbField.options?.maxSelect,
|
|
2597
|
-
minSelect: pbField.options?.minSelect
|
|
2598
|
-
};
|
|
2599
|
-
}
|
|
2600
|
-
fields.push(field);
|
|
2601
|
-
}
|
|
2602
|
-
}
|
|
2603
|
-
const schema = {
|
|
2604
|
-
name: pbCollection.name,
|
|
2605
|
-
type: pbCollection.type || "base",
|
|
2606
|
-
fields
|
|
2607
|
-
};
|
|
2608
|
-
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2609
|
-
schema.indexes = pbCollection.indexes;
|
|
2610
|
-
}
|
|
2611
|
-
const rules = {};
|
|
2612
|
-
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
2613
|
-
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
2614
|
-
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
2615
|
-
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
2616
|
-
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
2617
|
-
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
2618
|
-
if (Object.keys(rules).length > 0) {
|
|
2619
|
-
schema.rules = rules;
|
|
2620
|
-
schema.permissions = { ...rules };
|
|
2621
|
-
}
|
|
2622
|
-
return schema;
|
|
2623
|
-
}
|
|
2624
|
-
function convertPocketBaseMigration(migrationContent) {
|
|
2625
|
-
try {
|
|
2626
|
-
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
2627
|
-
if (!snapshotMatch) {
|
|
2628
|
-
throw new Error("Could not find snapshot array in migration file");
|
|
2629
|
-
}
|
|
2630
|
-
const snapshotArrayStr = snapshotMatch[1];
|
|
2631
|
-
let snapshotArray;
|
|
2632
|
-
try {
|
|
2633
|
-
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
2634
|
-
} catch (parseError) {
|
|
2635
|
-
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
2636
|
-
}
|
|
2637
|
-
if (!Array.isArray(snapshotArray)) {
|
|
2638
|
-
throw new Error("Snapshot is not an array");
|
|
2639
|
-
}
|
|
2640
|
-
const collections = /* @__PURE__ */ new Map();
|
|
2641
|
-
for (const pbCollection of snapshotArray) {
|
|
2642
|
-
if (!pbCollection.name) {
|
|
2643
|
-
console.warn("Skipping collection without name");
|
|
2644
|
-
continue;
|
|
2645
|
-
}
|
|
2646
|
-
const schema = convertPocketBaseCollection(pbCollection);
|
|
2647
|
-
collections.set(pbCollection.name, schema);
|
|
2648
|
-
}
|
|
2649
|
-
return {
|
|
2650
|
-
version: SNAPSHOT_VERSION,
|
|
2651
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2652
|
-
collections
|
|
2653
|
-
};
|
|
2654
|
-
} catch (error) {
|
|
2655
|
-
throw new SnapshotError(
|
|
2656
|
-
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
2657
|
-
void 0,
|
|
2658
|
-
"parse",
|
|
2659
|
-
error instanceof Error ? error : void 0
|
|
2660
|
-
);
|
|
2661
|
-
}
|
|
2662
|
-
}
|
|
2663
2998
|
function loadBaseMigration(migrationPath) {
|
|
2664
2999
|
try {
|
|
2665
|
-
if (!
|
|
3000
|
+
if (!fs3__namespace.existsSync(migrationPath)) {
|
|
2666
3001
|
throw new SnapshotError(
|
|
2667
3002
|
`Base migration file not found: ${migrationPath}
|
|
2668
3003
|
|
|
@@ -2673,7 +3008,7 @@ If the file exists in a different location, update the configuration.`,
|
|
|
2673
3008
|
"read"
|
|
2674
3009
|
);
|
|
2675
3010
|
}
|
|
2676
|
-
const migrationContent =
|
|
3011
|
+
const migrationContent = fs3__namespace.readFileSync(migrationPath, "utf-8");
|
|
2677
3012
|
const snapshot = convertPocketBaseMigration(migrationContent);
|
|
2678
3013
|
return snapshot;
|
|
2679
3014
|
} catch (error) {
|
|
@@ -2709,14 +3044,14 @@ Please ensure PocketBase is properly set up by running 'yarn setup'.`,
|
|
|
2709
3044
|
}
|
|
2710
3045
|
}
|
|
2711
3046
|
function getSnapshotVersion() {
|
|
2712
|
-
return
|
|
3047
|
+
return SNAPSHOT_VERSION2;
|
|
2713
3048
|
}
|
|
2714
3049
|
function validateSnapshot(snapshot) {
|
|
2715
3050
|
const issues = [];
|
|
2716
3051
|
if (!snapshot.version) {
|
|
2717
3052
|
issues.push("Missing version field");
|
|
2718
|
-
} else if (compareVersions(snapshot.version,
|
|
2719
|
-
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${
|
|
3053
|
+
} else if (compareVersions(snapshot.version, SNAPSHOT_VERSION2) > 0) {
|
|
3054
|
+
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION2}`);
|
|
2720
3055
|
}
|
|
2721
3056
|
if (!snapshot.timestamp) {
|
|
2722
3057
|
issues.push("Missing timestamp field");
|
|
@@ -2935,6 +3270,9 @@ function compareFieldOptions(currentField, previousField) {
|
|
|
2935
3270
|
for (const key of allKeys) {
|
|
2936
3271
|
const currentValue = currentOptions[key];
|
|
2937
3272
|
const previousValue = previousOptions[key];
|
|
3273
|
+
if (currentValue === void 0 && previousValue === void 0) {
|
|
3274
|
+
continue;
|
|
3275
|
+
}
|
|
2938
3276
|
if (!areValuesEqual(currentValue, previousValue)) {
|
|
2939
3277
|
changes.push({
|
|
2940
3278
|
property: `options.${key}`,
|
|
@@ -2955,11 +3293,26 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
2955
3293
|
if (!currentRelation || !previousRelation) {
|
|
2956
3294
|
return changes;
|
|
2957
3295
|
}
|
|
2958
|
-
|
|
3296
|
+
const normalizeCollection = (collection) => {
|
|
3297
|
+
if (!collection) return collection;
|
|
3298
|
+
if (collection === "_pb_users_auth_") {
|
|
3299
|
+
return "Users";
|
|
3300
|
+
}
|
|
3301
|
+
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
3302
|
+
if (nameMatch) {
|
|
3303
|
+
return nameMatch[1];
|
|
3304
|
+
}
|
|
3305
|
+
return collection;
|
|
3306
|
+
};
|
|
3307
|
+
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
3308
|
+
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
3309
|
+
if (normalizedCurrent !== normalizedPrevious) {
|
|
2959
3310
|
changes.push({
|
|
2960
3311
|
property: "relation.collection",
|
|
2961
|
-
oldValue:
|
|
2962
|
-
|
|
3312
|
+
oldValue: normalizedPrevious,
|
|
3313
|
+
// Use normalized value for clarity
|
|
3314
|
+
newValue: normalizedCurrent
|
|
3315
|
+
// Use normalized value for clarity
|
|
2963
3316
|
});
|
|
2964
3317
|
}
|
|
2965
3318
|
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
@@ -3332,10 +3685,10 @@ function mergeConfig4(config) {
|
|
|
3332
3685
|
}
|
|
3333
3686
|
function resolveMigrationDir(config) {
|
|
3334
3687
|
const workspaceRoot = config.workspaceRoot || process.cwd();
|
|
3335
|
-
if (
|
|
3688
|
+
if (path5__namespace.isAbsolute(config.migrationDir)) {
|
|
3336
3689
|
return config.migrationDir;
|
|
3337
3690
|
}
|
|
3338
|
-
return
|
|
3691
|
+
return path5__namespace.join(workspaceRoot, config.migrationDir);
|
|
3339
3692
|
}
|
|
3340
3693
|
function generateTimestamp(config) {
|
|
3341
3694
|
if (config?.timestampGenerator) {
|
|
@@ -3393,9 +3746,9 @@ function createMigrationFileStructure(upCode, downCode, config) {
|
|
|
3393
3746
|
}
|
|
3394
3747
|
function writeMigrationFile(migrationDir, filename, content) {
|
|
3395
3748
|
try {
|
|
3396
|
-
if (!
|
|
3749
|
+
if (!fs3__namespace.existsSync(migrationDir)) {
|
|
3397
3750
|
try {
|
|
3398
|
-
|
|
3751
|
+
fs3__namespace.mkdirSync(migrationDir, { recursive: true });
|
|
3399
3752
|
} catch (error) {
|
|
3400
3753
|
const fsError = error;
|
|
3401
3754
|
if (fsError.code === "EACCES" || fsError.code === "EPERM") {
|
|
@@ -3416,15 +3769,15 @@ function writeMigrationFile(migrationDir, filename, content) {
|
|
|
3416
3769
|
);
|
|
3417
3770
|
}
|
|
3418
3771
|
}
|
|
3419
|
-
const filePath =
|
|
3420
|
-
|
|
3772
|
+
const filePath = path5__namespace.join(migrationDir, filename);
|
|
3773
|
+
fs3__namespace.writeFileSync(filePath, content, "utf-8");
|
|
3421
3774
|
return filePath;
|
|
3422
3775
|
} catch (error) {
|
|
3423
3776
|
if (error instanceof FileSystemError) {
|
|
3424
3777
|
throw error;
|
|
3425
3778
|
}
|
|
3426
3779
|
const fsError = error;
|
|
3427
|
-
const filePath =
|
|
3780
|
+
const filePath = path5__namespace.join(migrationDir, filename);
|
|
3428
3781
|
if (fsError.code === "EACCES" || fsError.code === "EPERM") {
|
|
3429
3782
|
throw new FileSystemError(
|
|
3430
3783
|
`Permission denied writing migration file. Check file and directory permissions.`,
|
|
@@ -4168,8 +4521,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
4168
4521
|
};
|
|
4169
4522
|
function findConfigFile(directory) {
|
|
4170
4523
|
for (const fileName of CONFIG_FILE_NAMES) {
|
|
4171
|
-
const filePath =
|
|
4172
|
-
if (
|
|
4524
|
+
const filePath = path5__namespace.join(directory, fileName);
|
|
4525
|
+
if (fs3__namespace.existsSync(filePath)) {
|
|
4173
4526
|
return filePath;
|
|
4174
4527
|
}
|
|
4175
4528
|
}
|
|
@@ -4177,7 +4530,7 @@ function findConfigFile(directory) {
|
|
|
4177
4530
|
}
|
|
4178
4531
|
function loadJsonConfig(configPath) {
|
|
4179
4532
|
try {
|
|
4180
|
-
const content =
|
|
4533
|
+
const content = fs3__namespace.readFileSync(configPath, "utf-8");
|
|
4181
4534
|
return JSON.parse(content);
|
|
4182
4535
|
} catch (error) {
|
|
4183
4536
|
if (error instanceof SyntaxError) {
|
|
@@ -4206,10 +4559,10 @@ async function loadJsConfig(configPath) {
|
|
|
4206
4559
|
}
|
|
4207
4560
|
}
|
|
4208
4561
|
async function loadConfigFile(configPath) {
|
|
4209
|
-
if (!
|
|
4562
|
+
if (!fs3__namespace.existsSync(configPath)) {
|
|
4210
4563
|
return null;
|
|
4211
4564
|
}
|
|
4212
|
-
const ext =
|
|
4565
|
+
const ext = path5__namespace.extname(configPath).toLowerCase();
|
|
4213
4566
|
if (ext === ".json") {
|
|
4214
4567
|
return loadJsonConfig(configPath);
|
|
4215
4568
|
} else if (ext === ".js" || ext === ".mjs") {
|
|
@@ -4276,10 +4629,10 @@ function validateConfig(config, configPath) {
|
|
|
4276
4629
|
}
|
|
4277
4630
|
const cwd = process.cwd();
|
|
4278
4631
|
const possiblePaths = [
|
|
4279
|
-
|
|
4280
|
-
|
|
4632
|
+
path5__namespace.resolve(cwd, config.schema.directory),
|
|
4633
|
+
path5__namespace.resolve(cwd, "shared", config.schema.directory)
|
|
4281
4634
|
];
|
|
4282
|
-
const schemaDir = possiblePaths.find((p) =>
|
|
4635
|
+
const schemaDir = possiblePaths.find((p) => fs3__namespace.existsSync(p));
|
|
4283
4636
|
if (!schemaDir) {
|
|
4284
4637
|
throw new ConfigurationError(`Schema directory not found. Tried: ${possiblePaths.join(", ")}`, configPath, [
|
|
4285
4638
|
"schema.directory"
|
|
@@ -4291,15 +4644,15 @@ async function loadConfig(options = {}) {
|
|
|
4291
4644
|
let configFilePath;
|
|
4292
4645
|
const cwd = process.cwd();
|
|
4293
4646
|
if (options.config) {
|
|
4294
|
-
const explicitPath =
|
|
4295
|
-
if (!
|
|
4647
|
+
const explicitPath = path5__namespace.resolve(cwd, options.config);
|
|
4648
|
+
if (!fs3__namespace.existsSync(explicitPath)) {
|
|
4296
4649
|
throw new ConfigurationError(`Configuration file not found: ${explicitPath}`, explicitPath);
|
|
4297
4650
|
}
|
|
4298
4651
|
configFilePath = explicitPath;
|
|
4299
4652
|
} else {
|
|
4300
|
-
const searchDirs = [cwd,
|
|
4653
|
+
const searchDirs = [cwd, path5__namespace.join(cwd, "shared")];
|
|
4301
4654
|
for (const dir of searchDirs) {
|
|
4302
|
-
if (
|
|
4655
|
+
if (fs3__namespace.existsSync(dir)) {
|
|
4303
4656
|
const found = findConfigFile(dir);
|
|
4304
4657
|
if (found) {
|
|
4305
4658
|
configFilePath = found;
|
|
@@ -4328,18 +4681,18 @@ async function loadConfig(options = {}) {
|
|
|
4328
4681
|
function getSchemaDirectory(config) {
|
|
4329
4682
|
const cwd = process.cwd();
|
|
4330
4683
|
const possiblePaths = [
|
|
4331
|
-
|
|
4332
|
-
|
|
4684
|
+
path5__namespace.resolve(cwd, config.schema.directory),
|
|
4685
|
+
path5__namespace.resolve(cwd, "shared", config.schema.directory)
|
|
4333
4686
|
];
|
|
4334
|
-
return possiblePaths.find((p) =>
|
|
4687
|
+
return possiblePaths.find((p) => fs3__namespace.existsSync(p)) || possiblePaths[0];
|
|
4335
4688
|
}
|
|
4336
4689
|
function getMigrationsDirectory(config) {
|
|
4337
4690
|
const cwd = process.cwd();
|
|
4338
4691
|
const possiblePaths = [
|
|
4339
|
-
|
|
4340
|
-
|
|
4692
|
+
path5__namespace.resolve(cwd, config.migrations.directory),
|
|
4693
|
+
path5__namespace.resolve(cwd, "shared", config.migrations.directory)
|
|
4341
4694
|
];
|
|
4342
|
-
return possiblePaths.find((p) =>
|
|
4695
|
+
return possiblePaths.find((p) => fs3__namespace.existsSync(p)) || possiblePaths[0];
|
|
4343
4696
|
}
|
|
4344
4697
|
var currentVerbosity = "normal";
|
|
4345
4698
|
function setVerbosity(level) {
|
|
@@ -4556,7 +4909,7 @@ async function executeGenerate(options) {
|
|
|
4556
4909
|
const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
|
|
4557
4910
|
logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
|
|
4558
4911
|
logInfo("Loading previous snapshot...");
|
|
4559
|
-
const previousSnapshot =
|
|
4912
|
+
const previousSnapshot = loadSnapshotWithMigrations({
|
|
4560
4913
|
migrationsPath: migrationsDir,
|
|
4561
4914
|
workspaceRoot: process.cwd()
|
|
4562
4915
|
});
|
|
@@ -4583,7 +4936,7 @@ async function executeGenerate(options) {
|
|
|
4583
4936
|
"Creating migration file...",
|
|
4584
4937
|
() => Promise.resolve(generate(diff, migrationsDir))
|
|
4585
4938
|
);
|
|
4586
|
-
logSuccess(`Migration file created: ${
|
|
4939
|
+
logSuccess(`Migration file created: ${path5__namespace.basename(migrationPath)}`);
|
|
4587
4940
|
logSection("\u2705 Next Steps");
|
|
4588
4941
|
console.log();
|
|
4589
4942
|
console.log(" 1. Review the generated migration file:");
|
|
@@ -4749,7 +5102,7 @@ async function executeStatus(options) {
|
|
|
4749
5102
|
const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
|
|
4750
5103
|
logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
|
|
4751
5104
|
logInfo("Loading previous snapshot...");
|
|
4752
|
-
const previousSnapshot =
|
|
5105
|
+
const previousSnapshot = loadSnapshotWithMigrations({
|
|
4753
5106
|
migrationsPath: migrationsDir,
|
|
4754
5107
|
workspaceRoot: process.cwd()
|
|
4755
5108
|
});
|
|
@@ -4860,6 +5213,8 @@ exports.MigrationGenerationError = MigrationGenerationError;
|
|
|
4860
5213
|
exports.MigrationGenerator = MigrationGenerator;
|
|
4861
5214
|
exports.POCKETBASE_FIELD_TYPES = POCKETBASE_FIELD_TYPES;
|
|
4862
5215
|
exports.PermissionTemplates = PermissionTemplates;
|
|
5216
|
+
exports.ProjectInputSchema = ProjectInputSchema;
|
|
5217
|
+
exports.ProjectSchema = ProjectSchema;
|
|
4863
5218
|
exports.SchemaAnalyzer = SchemaAnalyzer;
|
|
4864
5219
|
exports.SchemaParsingError = SchemaParsingError;
|
|
4865
5220
|
exports.SnapshotError = SnapshotError;
|
|
@@ -4955,6 +5310,7 @@ exports.loadBaseMigration = loadBaseMigration;
|
|
|
4955
5310
|
exports.loadConfig = loadConfig;
|
|
4956
5311
|
exports.loadSnapshot = loadSnapshot;
|
|
4957
5312
|
exports.loadSnapshotIfExists = loadSnapshotIfExists;
|
|
5313
|
+
exports.loadSnapshotWithMigrations = loadSnapshotWithMigrations;
|
|
4958
5314
|
exports.logError = logError;
|
|
4959
5315
|
exports.logInfo = logInfo;
|
|
4960
5316
|
exports.logSection = logSection;
|