pocketbase-zod-schema 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +233 -98
- package/dist/cli/index.cjs +449 -108
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +447 -106
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +452 -111
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +447 -106
- package/dist/cli/migrate.js.map +1 -1
- package/dist/index.cjs +593 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +583 -172
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +44 -6
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +11 -1
- package/dist/migration/analyzer.d.ts +11 -1
- package/dist/migration/analyzer.js +44 -7
- package/dist/migration/analyzer.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 +500 -129
- 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 +499 -129
- 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.cjs +20 -21
- package/dist/mutator.cjs.map +1 -1
- package/dist/mutator.d.cts +4 -4
- package/dist/mutator.d.ts +4 -4
- package/dist/mutator.js +20 -21
- package/dist/mutator.js.map +1 -1
- package/dist/schema.cjs +69 -10
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +98 -8
- package/dist/schema.d.ts +98 -8
- package/dist/schema.js +62 -9
- package/dist/schema.js.map +1 -1
- package/dist/types.d.cts +5 -2
- package/dist/types.d.ts +5 -2
- package/dist/user-DTJQIj4K.d.cts +149 -0
- package/dist/user-DTJQIj4K.d.ts +149 -0
- package/package.json +3 -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
|
|
|
@@ -105,7 +105,7 @@ function filesField(options) {
|
|
|
105
105
|
return schema;
|
|
106
106
|
}
|
|
107
107
|
var RELATION_METADATA_KEY = "__pocketbase_relation__";
|
|
108
|
-
function
|
|
108
|
+
function RelationField(config) {
|
|
109
109
|
const metadata = {
|
|
110
110
|
[RELATION_METADATA_KEY]: {
|
|
111
111
|
type: "single",
|
|
@@ -117,7 +117,7 @@ function relationField(config) {
|
|
|
117
117
|
};
|
|
118
118
|
return zod.z.string().describe(JSON.stringify(metadata));
|
|
119
119
|
}
|
|
120
|
-
function
|
|
120
|
+
function RelationsField(config) {
|
|
121
121
|
const metadata = {
|
|
122
122
|
[RELATION_METADATA_KEY]: {
|
|
123
123
|
type: "multiple",
|
|
@@ -176,6 +176,22 @@ function withIndexes(schema, indexes) {
|
|
|
176
176
|
};
|
|
177
177
|
return schema.describe(JSON.stringify(metadata));
|
|
178
178
|
}
|
|
179
|
+
function defineCollection(config) {
|
|
180
|
+
const { collectionName, schema, permissions, indexes, ...futureOptions } = config;
|
|
181
|
+
const metadata = {
|
|
182
|
+
collectionName
|
|
183
|
+
};
|
|
184
|
+
if (permissions) {
|
|
185
|
+
metadata.permissions = permissions;
|
|
186
|
+
}
|
|
187
|
+
if (indexes) {
|
|
188
|
+
metadata.indexes = indexes;
|
|
189
|
+
}
|
|
190
|
+
if (Object.keys(futureOptions).length > 0) {
|
|
191
|
+
Object.assign(metadata, futureOptions);
|
|
192
|
+
}
|
|
193
|
+
return schema.describe(JSON.stringify(metadata));
|
|
194
|
+
}
|
|
179
195
|
|
|
180
196
|
// src/utils/permission-templates.ts
|
|
181
197
|
var PermissionTemplates = {
|
|
@@ -396,6 +412,28 @@ function mergePermissions(...schemas) {
|
|
|
396
412
|
}
|
|
397
413
|
return merged;
|
|
398
414
|
}
|
|
415
|
+
var ProjectInputSchema = zod.z.object({
|
|
416
|
+
// Required fields
|
|
417
|
+
title: zod.z.string(),
|
|
418
|
+
content: zod.z.string(),
|
|
419
|
+
status: StatusEnum,
|
|
420
|
+
summary: zod.z.string().optional(),
|
|
421
|
+
OwnerUser: RelationField({ collection: "Users" }),
|
|
422
|
+
SubscriberUsers: RelationsField({ collection: "Users" })
|
|
423
|
+
}).extend(inputImageFileSchema);
|
|
424
|
+
var ProjectSchema = ProjectInputSchema.omit(omitImageFilesSchema).extend(baseImageFileSchema);
|
|
425
|
+
var ProjectCollection = defineCollection({
|
|
426
|
+
collectionName: "Projects",
|
|
427
|
+
schema: ProjectSchema,
|
|
428
|
+
permissions: {
|
|
429
|
+
template: "owner-only",
|
|
430
|
+
ownerField: "OwnerUser",
|
|
431
|
+
customRules: {
|
|
432
|
+
listRule: '@request.auth.id != ""',
|
|
433
|
+
viewRule: '@request.auth.id != "" && (OwnerUser = @request.auth.id || SubscriberUsers ?= @request.auth.id)'
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
});
|
|
399
437
|
var UserInputSchema = zod.z.object({
|
|
400
438
|
name: zod.z.string().optional(),
|
|
401
439
|
email: zod.z.string().email(),
|
|
@@ -403,14 +441,17 @@ var UserInputSchema = zod.z.object({
|
|
|
403
441
|
passwordConfirm: zod.z.string(),
|
|
404
442
|
avatar: zod.z.instanceof(File).optional()
|
|
405
443
|
});
|
|
406
|
-
var
|
|
444
|
+
var UserCollectionSchema = zod.z.object({
|
|
407
445
|
name: zod.z.string().optional(),
|
|
408
446
|
email: zod.z.string().email(),
|
|
409
447
|
password: zod.z.string().min(8, "Password must be at least 8 characters"),
|
|
410
448
|
avatar: zod.z.instanceof(File).optional()
|
|
411
449
|
});
|
|
412
|
-
var UserSchema =
|
|
413
|
-
|
|
450
|
+
var UserSchema = UserCollectionSchema.extend(baseSchema);
|
|
451
|
+
var UserCollection = defineCollection({
|
|
452
|
+
collectionName: "Users",
|
|
453
|
+
schema: UserSchema,
|
|
454
|
+
permissions: {
|
|
414
455
|
// Users can list their own profile
|
|
415
456
|
listRule: "id = @request.auth.id",
|
|
416
457
|
// Users can view their own profile
|
|
@@ -422,13 +463,13 @@ var UserSchema = withIndexes(
|
|
|
422
463
|
// Users can only delete their own account
|
|
423
464
|
deleteRule: "id = @request.auth.id"
|
|
424
465
|
// manageRule is null in PocketBase default (not set)
|
|
425
|
-
}
|
|
426
|
-
[
|
|
466
|
+
},
|
|
467
|
+
indexes: [
|
|
427
468
|
// PocketBase's default indexes for auth collections
|
|
428
469
|
"CREATE UNIQUE INDEX `idx_tokenKey__pb_users_auth_` ON `users` (`tokenKey`)",
|
|
429
470
|
"CREATE UNIQUE INDEX `idx_email__pb_users_auth_` ON `users` (`email`) WHERE `email` != ''"
|
|
430
471
|
]
|
|
431
|
-
);
|
|
472
|
+
});
|
|
432
473
|
var BaseMutator = class {
|
|
433
474
|
pb;
|
|
434
475
|
// Define a default property that subclasses will override
|
|
@@ -871,10 +912,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
|
|
|
871
912
|
operation;
|
|
872
913
|
code;
|
|
873
914
|
originalError;
|
|
874
|
-
constructor(message,
|
|
915
|
+
constructor(message, path7, operation, code, originalError) {
|
|
875
916
|
super(message);
|
|
876
917
|
this.name = "FileSystemError";
|
|
877
|
-
this.path =
|
|
918
|
+
this.path = path7;
|
|
878
919
|
this.operation = operation;
|
|
879
920
|
this.code = code;
|
|
880
921
|
this.originalError = originalError;
|
|
@@ -1950,6 +1991,16 @@ function getFieldTypeInfo(zodType, fieldName) {
|
|
|
1950
1991
|
}
|
|
1951
1992
|
|
|
1952
1993
|
// src/migration/analyzer.ts
|
|
1994
|
+
var tsxLoaderRegistered = false;
|
|
1995
|
+
async function ensureTsxLoader() {
|
|
1996
|
+
if (tsxLoaderRegistered) return;
|
|
1997
|
+
try {
|
|
1998
|
+
await import('tsx/esm');
|
|
1999
|
+
tsxLoaderRegistered = true;
|
|
2000
|
+
} catch {
|
|
2001
|
+
tsxLoaderRegistered = false;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
1953
2004
|
var DEFAULT_CONFIG = {
|
|
1954
2005
|
workspaceRoot: process.cwd(),
|
|
1955
2006
|
excludePatterns: [
|
|
@@ -1977,20 +2028,20 @@ function mergeConfig(config) {
|
|
|
1977
2028
|
}
|
|
1978
2029
|
function resolveSchemaDir(config) {
|
|
1979
2030
|
const workspaceRoot = config.workspaceRoot || process.cwd();
|
|
1980
|
-
if (
|
|
2031
|
+
if (path5__namespace.isAbsolute(config.schemaDir)) {
|
|
1981
2032
|
return config.schemaDir;
|
|
1982
2033
|
}
|
|
1983
|
-
return
|
|
2034
|
+
return path5__namespace.join(workspaceRoot, config.schemaDir);
|
|
1984
2035
|
}
|
|
1985
2036
|
function discoverSchemaFiles(config) {
|
|
1986
2037
|
const normalizedConfig = typeof config === "string" ? { schemaDir: config } : config;
|
|
1987
2038
|
const mergedConfig = mergeConfig(normalizedConfig);
|
|
1988
2039
|
const schemaDir = resolveSchemaDir(normalizedConfig);
|
|
1989
2040
|
try {
|
|
1990
|
-
if (!
|
|
2041
|
+
if (!fs3__namespace.existsSync(schemaDir)) {
|
|
1991
2042
|
throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, "access", "ENOENT");
|
|
1992
2043
|
}
|
|
1993
|
-
const files =
|
|
2044
|
+
const files = fs3__namespace.readdirSync(schemaDir);
|
|
1994
2045
|
const schemaFiles = files.filter((file) => {
|
|
1995
2046
|
const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));
|
|
1996
2047
|
if (!hasValidExtension) return false;
|
|
@@ -2006,7 +2057,7 @@ function discoverSchemaFiles(config) {
|
|
|
2006
2057
|
});
|
|
2007
2058
|
return schemaFiles.map((file) => {
|
|
2008
2059
|
const ext = mergedConfig.includeExtensions.find((ext2) => file.endsWith(ext2)) || ".ts";
|
|
2009
|
-
return
|
|
2060
|
+
return path5__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
|
|
2010
2061
|
});
|
|
2011
2062
|
} catch (error) {
|
|
2012
2063
|
if (error instanceof FileSystemError) {
|
|
@@ -2040,40 +2091,66 @@ async function importSchemaModule(filePath, config) {
|
|
|
2040
2091
|
let resolvedPath = null;
|
|
2041
2092
|
const jsPath = `${importPath}.js`;
|
|
2042
2093
|
const tsPath = `${importPath}.ts`;
|
|
2043
|
-
if (
|
|
2094
|
+
if (fs3__namespace.existsSync(jsPath)) {
|
|
2044
2095
|
resolvedPath = jsPath;
|
|
2045
|
-
} else if (
|
|
2096
|
+
} else if (fs3__namespace.existsSync(tsPath)) {
|
|
2046
2097
|
resolvedPath = tsPath;
|
|
2047
2098
|
} else {
|
|
2048
2099
|
resolvedPath = jsPath;
|
|
2049
2100
|
}
|
|
2050
|
-
|
|
2101
|
+
if (resolvedPath.endsWith(".ts")) {
|
|
2102
|
+
await ensureTsxLoader();
|
|
2103
|
+
if (!tsxLoaderRegistered) {
|
|
2104
|
+
throw new SchemaParsingError(
|
|
2105
|
+
`Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
|
|
2106
|
+
Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
|
|
2107
|
+
Alternatively, compile your schema files to JavaScript first.`,
|
|
2108
|
+
filePath
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
const fileUrl = new URL(`file://${path5__namespace.resolve(resolvedPath)}`);
|
|
2051
2113
|
const module = await import(fileUrl.href);
|
|
2052
2114
|
return module;
|
|
2053
2115
|
} catch (error) {
|
|
2054
2116
|
const tsPath = `${filePath}.ts`;
|
|
2055
|
-
const isTypeScriptFile =
|
|
2117
|
+
const isTypeScriptFile = fs3__namespace.existsSync(tsPath);
|
|
2118
|
+
if (isTypeScriptFile && error instanceof SchemaParsingError) {
|
|
2119
|
+
throw error;
|
|
2120
|
+
}
|
|
2056
2121
|
if (isTypeScriptFile) {
|
|
2057
2122
|
throw new SchemaParsingError(
|
|
2058
|
-
`Failed to import TypeScript schema file.
|
|
2059
|
-
Please
|
|
2060
|
-
|
|
2061
|
-
2. Use tsx to run the migration tool (e.g., "npx tsx package/dist/cli/migrate.js status" or "tsx package/dist/cli/migrate.js status")`,
|
|
2123
|
+
`Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
|
|
2124
|
+
Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
|
|
2125
|
+
Alternatively, compile your schema files to JavaScript first.`,
|
|
2062
2126
|
filePath,
|
|
2063
2127
|
error
|
|
2064
2128
|
);
|
|
2065
2129
|
}
|
|
2066
2130
|
throw new SchemaParsingError(
|
|
2067
|
-
`Failed to import schema module. Make sure the schema files
|
|
2131
|
+
`Failed to import schema module. Make sure the schema files exist and are valid.`,
|
|
2068
2132
|
filePath,
|
|
2069
2133
|
error
|
|
2070
2134
|
);
|
|
2071
2135
|
}
|
|
2072
2136
|
}
|
|
2073
2137
|
function getCollectionNameFromFile(filePath) {
|
|
2074
|
-
const filename =
|
|
2138
|
+
const filename = path5__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
2075
2139
|
return toCollectionName(filename);
|
|
2076
2140
|
}
|
|
2141
|
+
function extractCollectionNameFromSchema(zodSchema) {
|
|
2142
|
+
if (!zodSchema.description) {
|
|
2143
|
+
return null;
|
|
2144
|
+
}
|
|
2145
|
+
try {
|
|
2146
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
2147
|
+
if (metadata.collectionName && typeof metadata.collectionName === "string") {
|
|
2148
|
+
return metadata.collectionName;
|
|
2149
|
+
}
|
|
2150
|
+
} catch {
|
|
2151
|
+
}
|
|
2152
|
+
return null;
|
|
2153
|
+
}
|
|
2077
2154
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
|
|
2078
2155
|
const result = {};
|
|
2079
2156
|
for (const [key, value] of Object.entries(module)) {
|
|
@@ -2236,7 +2313,7 @@ async function buildSchemaDefinition(config) {
|
|
|
2236
2313
|
importPath = normalizedConfig.pathTransformer(filePath);
|
|
2237
2314
|
} else if (mergedConfig.useCompiledFiles) {
|
|
2238
2315
|
const distPath = filePath.replace(/\/src\//, "/dist/");
|
|
2239
|
-
if (
|
|
2316
|
+
if (fs3__namespace.existsSync(`${distPath}.js`) || fs3__namespace.existsSync(`${distPath}.mjs`)) {
|
|
2240
2317
|
importPath = distPath;
|
|
2241
2318
|
} else {
|
|
2242
2319
|
importPath = filePath;
|
|
@@ -2249,7 +2326,8 @@ async function buildSchemaDefinition(config) {
|
|
|
2249
2326
|
console.warn(`No valid schema found in ${filePath}, skipping...`);
|
|
2250
2327
|
continue;
|
|
2251
2328
|
}
|
|
2252
|
-
const
|
|
2329
|
+
const collectionNameFromSchema = extractCollectionNameFromSchema(zodSchema);
|
|
2330
|
+
const collectionName = collectionNameFromSchema ?? getCollectionNameFromFile(filePath);
|
|
2253
2331
|
const collectionSchema = convertZodSchemaToCollectionSchema(collectionName, zodSchema);
|
|
2254
2332
|
collections.set(collectionName, collectionSchema);
|
|
2255
2333
|
} catch (error) {
|
|
@@ -2292,7 +2370,359 @@ var SchemaAnalyzer = class {
|
|
|
2292
2370
|
return convertZodSchemaToCollectionSchema(name, schema);
|
|
2293
2371
|
}
|
|
2294
2372
|
};
|
|
2373
|
+
|
|
2374
|
+
// src/migration/pocketbase-converter.ts
|
|
2295
2375
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
2376
|
+
function resolveCollectionIdToName(collectionId) {
|
|
2377
|
+
if (collectionId === "_pb_users_auth_") {
|
|
2378
|
+
return "Users";
|
|
2379
|
+
}
|
|
2380
|
+
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
2381
|
+
if (nameMatch) {
|
|
2382
|
+
return nameMatch[1];
|
|
2383
|
+
}
|
|
2384
|
+
return collectionId;
|
|
2385
|
+
}
|
|
2386
|
+
function convertPocketBaseCollection(pbCollection) {
|
|
2387
|
+
const fields = [];
|
|
2388
|
+
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
2389
|
+
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
2390
|
+
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2391
|
+
for (const pbField of pbCollection.fields) {
|
|
2392
|
+
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
2393
|
+
continue;
|
|
2394
|
+
}
|
|
2395
|
+
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
2396
|
+
continue;
|
|
2397
|
+
}
|
|
2398
|
+
const field = {
|
|
2399
|
+
name: pbField.name,
|
|
2400
|
+
type: pbField.type,
|
|
2401
|
+
required: pbField.required || false
|
|
2402
|
+
};
|
|
2403
|
+
field.options = pbField.options ? { ...pbField.options } : {};
|
|
2404
|
+
if (pbField.type === "select") {
|
|
2405
|
+
if (pbField.values && Array.isArray(pbField.values)) {
|
|
2406
|
+
field.options.values = pbField.values;
|
|
2407
|
+
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
2408
|
+
field.options.values = pbField.options.values;
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
if (pbField.type === "relation") {
|
|
2412
|
+
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
2413
|
+
const collectionName = resolveCollectionIdToName(collectionId);
|
|
2414
|
+
field.relation = {
|
|
2415
|
+
collection: collectionName,
|
|
2416
|
+
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
2417
|
+
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
2418
|
+
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
2419
|
+
};
|
|
2420
|
+
}
|
|
2421
|
+
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
2422
|
+
if (Object.keys(field.options).length === 0) {
|
|
2423
|
+
delete field.options;
|
|
2424
|
+
} else if (pbField.type === "select" && hasOnlyValues) ;
|
|
2425
|
+
fields.push(field);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
const schema = {
|
|
2429
|
+
name: pbCollection.name,
|
|
2430
|
+
type: pbCollection.type || "base",
|
|
2431
|
+
fields
|
|
2432
|
+
};
|
|
2433
|
+
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2434
|
+
schema.indexes = pbCollection.indexes;
|
|
2435
|
+
}
|
|
2436
|
+
const rules = {};
|
|
2437
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
2438
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
2439
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
2440
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
2441
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
2442
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
2443
|
+
if (Object.keys(rules).length > 0) {
|
|
2444
|
+
schema.rules = rules;
|
|
2445
|
+
schema.permissions = { ...rules };
|
|
2446
|
+
}
|
|
2447
|
+
return schema;
|
|
2448
|
+
}
|
|
2449
|
+
function convertPocketBaseMigration(migrationContent) {
|
|
2450
|
+
try {
|
|
2451
|
+
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
2452
|
+
if (!snapshotMatch) {
|
|
2453
|
+
throw new Error("Could not find snapshot array in migration file");
|
|
2454
|
+
}
|
|
2455
|
+
const snapshotArrayStr = snapshotMatch[1];
|
|
2456
|
+
let snapshotArray;
|
|
2457
|
+
try {
|
|
2458
|
+
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
2459
|
+
} catch (parseError) {
|
|
2460
|
+
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
2461
|
+
}
|
|
2462
|
+
if (!Array.isArray(snapshotArray)) {
|
|
2463
|
+
throw new Error("Snapshot is not an array");
|
|
2464
|
+
}
|
|
2465
|
+
const collections = /* @__PURE__ */ new Map();
|
|
2466
|
+
for (const pbCollection of snapshotArray) {
|
|
2467
|
+
if (!pbCollection.name) {
|
|
2468
|
+
console.warn("Skipping collection without name");
|
|
2469
|
+
continue;
|
|
2470
|
+
}
|
|
2471
|
+
const schema = convertPocketBaseCollection(pbCollection);
|
|
2472
|
+
collections.set(pbCollection.name, schema);
|
|
2473
|
+
}
|
|
2474
|
+
return {
|
|
2475
|
+
version: SNAPSHOT_VERSION,
|
|
2476
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2477
|
+
collections
|
|
2478
|
+
};
|
|
2479
|
+
} catch (error) {
|
|
2480
|
+
throw new SnapshotError(
|
|
2481
|
+
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
2482
|
+
void 0,
|
|
2483
|
+
"parse",
|
|
2484
|
+
error instanceof Error ? error : void 0
|
|
2485
|
+
);
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
// src/migration/migration-parser.ts
|
|
2490
|
+
function extractTimestampFromFilename(filename) {
|
|
2491
|
+
const match = filename.match(/^(\d+)_/);
|
|
2492
|
+
if (match) {
|
|
2493
|
+
return parseInt(match[1], 10);
|
|
2494
|
+
}
|
|
2495
|
+
return null;
|
|
2496
|
+
}
|
|
2497
|
+
function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
2498
|
+
try {
|
|
2499
|
+
if (!fs3__namespace.existsSync(migrationsPath)) {
|
|
2500
|
+
return [];
|
|
2501
|
+
}
|
|
2502
|
+
const files = fs3__namespace.readdirSync(migrationsPath);
|
|
2503
|
+
const migrationFiles = [];
|
|
2504
|
+
for (const file of files) {
|
|
2505
|
+
if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
|
|
2506
|
+
continue;
|
|
2507
|
+
}
|
|
2508
|
+
if (!file.endsWith(".js")) {
|
|
2509
|
+
continue;
|
|
2510
|
+
}
|
|
2511
|
+
const timestamp = extractTimestampFromFilename(file);
|
|
2512
|
+
if (timestamp && timestamp > snapshotTimestamp) {
|
|
2513
|
+
migrationFiles.push({
|
|
2514
|
+
path: path5__namespace.join(migrationsPath, file),
|
|
2515
|
+
timestamp
|
|
2516
|
+
});
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
|
|
2520
|
+
return migrationFiles.map((f) => f.path);
|
|
2521
|
+
} catch (error) {
|
|
2522
|
+
console.warn(`Error finding migrations after snapshot: ${error}`);
|
|
2523
|
+
return [];
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
function parseMigrationOperationsFromContent(content) {
|
|
2527
|
+
const collectionsToCreate = [];
|
|
2528
|
+
const collectionsToDelete = [];
|
|
2529
|
+
try {
|
|
2530
|
+
let searchIndex = 0;
|
|
2531
|
+
while (true) {
|
|
2532
|
+
const collectionStart = content.indexOf("new Collection(", searchIndex);
|
|
2533
|
+
if (collectionStart === -1) {
|
|
2534
|
+
break;
|
|
2535
|
+
}
|
|
2536
|
+
const openParen = collectionStart + "new Collection(".length;
|
|
2537
|
+
let braceCount = 0;
|
|
2538
|
+
let parenCount = 1;
|
|
2539
|
+
let inString = false;
|
|
2540
|
+
let stringChar = null;
|
|
2541
|
+
let i = openParen;
|
|
2542
|
+
while (i < content.length && /\s/.test(content[i])) {
|
|
2543
|
+
i++;
|
|
2544
|
+
}
|
|
2545
|
+
if (content[i] !== "{") {
|
|
2546
|
+
searchIndex = i + 1;
|
|
2547
|
+
continue;
|
|
2548
|
+
}
|
|
2549
|
+
const objectStart = i;
|
|
2550
|
+
braceCount = 1;
|
|
2551
|
+
i++;
|
|
2552
|
+
while (i < content.length && (braceCount > 0 || parenCount > 0)) {
|
|
2553
|
+
const char = content[i];
|
|
2554
|
+
const prevChar = i > 0 ? content[i - 1] : "";
|
|
2555
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
2556
|
+
inString = true;
|
|
2557
|
+
stringChar = char;
|
|
2558
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
2559
|
+
inString = false;
|
|
2560
|
+
stringChar = null;
|
|
2561
|
+
}
|
|
2562
|
+
if (!inString) {
|
|
2563
|
+
if (char === "{") braceCount++;
|
|
2564
|
+
if (char === "}") braceCount--;
|
|
2565
|
+
if (char === "(") parenCount++;
|
|
2566
|
+
if (char === ")") parenCount--;
|
|
2567
|
+
}
|
|
2568
|
+
i++;
|
|
2569
|
+
}
|
|
2570
|
+
if (braceCount === 0 && parenCount === 0) {
|
|
2571
|
+
const objectContent = content.substring(objectStart, i - 1);
|
|
2572
|
+
try {
|
|
2573
|
+
const collectionObj = new Function(`return ${objectContent}`)();
|
|
2574
|
+
if (collectionObj && collectionObj.name) {
|
|
2575
|
+
const schema = convertPocketBaseCollection(collectionObj);
|
|
2576
|
+
collectionsToCreate.push(schema);
|
|
2577
|
+
}
|
|
2578
|
+
} catch (error) {
|
|
2579
|
+
console.warn(`Failed to parse collection definition: ${error}`);
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
searchIndex = i;
|
|
2583
|
+
}
|
|
2584
|
+
const deleteMatches = content.matchAll(
|
|
2585
|
+
/app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
|
|
2586
|
+
);
|
|
2587
|
+
for (const match of deleteMatches) {
|
|
2588
|
+
if (match[1]) {
|
|
2589
|
+
collectionsToDelete.push(match[1]);
|
|
2590
|
+
} else {
|
|
2591
|
+
const varNameMatch = match[0].match(/collection_(\w+)/);
|
|
2592
|
+
if (varNameMatch) {
|
|
2593
|
+
const varName = `collection_${varNameMatch[1]}`;
|
|
2594
|
+
const deleteIndex = content.indexOf(match[0]);
|
|
2595
|
+
const beforeDelete = content.substring(0, deleteIndex);
|
|
2596
|
+
const varDefMatch = beforeDelete.match(
|
|
2597
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
|
|
2598
|
+
);
|
|
2599
|
+
if (varDefMatch && varDefMatch.length > 0) {
|
|
2600
|
+
const collectionDefMatch = beforeDelete.match(
|
|
2601
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
|
|
2602
|
+
);
|
|
2603
|
+
if (collectionDefMatch) {
|
|
2604
|
+
try {
|
|
2605
|
+
const collectionDefStr = collectionDefMatch[1];
|
|
2606
|
+
const collectionObj = new Function(`return ${collectionDefStr}`)();
|
|
2607
|
+
if (collectionObj && collectionObj.name) {
|
|
2608
|
+
collectionsToDelete.push(collectionObj.name);
|
|
2609
|
+
}
|
|
2610
|
+
} catch {
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
const findAndDeleteMatches = content.matchAll(
|
|
2618
|
+
/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
|
|
2619
|
+
);
|
|
2620
|
+
for (const match of findAndDeleteMatches) {
|
|
2621
|
+
collectionsToDelete.push(match[1]);
|
|
2622
|
+
}
|
|
2623
|
+
} catch (error) {
|
|
2624
|
+
console.warn(`Failed to parse migration operations from content: ${error}`);
|
|
2625
|
+
}
|
|
2626
|
+
return { collectionsToCreate, collectionsToDelete };
|
|
2627
|
+
}
|
|
2628
|
+
function parseMigrationOperations(migrationContent) {
|
|
2629
|
+
try {
|
|
2630
|
+
const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
|
|
2631
|
+
if (!migrateMatch) {
|
|
2632
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2633
|
+
}
|
|
2634
|
+
const startIndex = migrateMatch.index + migrateMatch[0].length;
|
|
2635
|
+
let i = startIndex;
|
|
2636
|
+
let parenCount = 0;
|
|
2637
|
+
let foundFirstParen = false;
|
|
2638
|
+
while (i < migrationContent.length) {
|
|
2639
|
+
const char = migrationContent[i];
|
|
2640
|
+
if (char === "(") {
|
|
2641
|
+
parenCount++;
|
|
2642
|
+
foundFirstParen = true;
|
|
2643
|
+
i++;
|
|
2644
|
+
break;
|
|
2645
|
+
}
|
|
2646
|
+
i++;
|
|
2647
|
+
}
|
|
2648
|
+
if (!foundFirstParen) {
|
|
2649
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2650
|
+
}
|
|
2651
|
+
let inString = false;
|
|
2652
|
+
let stringChar = null;
|
|
2653
|
+
let foundBrace = false;
|
|
2654
|
+
let braceStart = -1;
|
|
2655
|
+
while (i < migrationContent.length && !foundBrace) {
|
|
2656
|
+
const char = migrationContent[i];
|
|
2657
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2658
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
2659
|
+
inString = true;
|
|
2660
|
+
stringChar = char;
|
|
2661
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
2662
|
+
inString = false;
|
|
2663
|
+
stringChar = null;
|
|
2664
|
+
}
|
|
2665
|
+
if (!inString) {
|
|
2666
|
+
if (char === "(") parenCount++;
|
|
2667
|
+
if (char === ")") {
|
|
2668
|
+
parenCount--;
|
|
2669
|
+
if (parenCount === 0) {
|
|
2670
|
+
i++;
|
|
2671
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
2672
|
+
i++;
|
|
2673
|
+
}
|
|
2674
|
+
if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
|
|
2675
|
+
i += 2;
|
|
2676
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
2677
|
+
i++;
|
|
2678
|
+
}
|
|
2679
|
+
if (i < migrationContent.length && migrationContent[i] === "{") {
|
|
2680
|
+
foundBrace = true;
|
|
2681
|
+
braceStart = i + 1;
|
|
2682
|
+
break;
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
i++;
|
|
2689
|
+
}
|
|
2690
|
+
if (!foundBrace || braceStart === -1) {
|
|
2691
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2692
|
+
}
|
|
2693
|
+
let braceCount = 1;
|
|
2694
|
+
i = braceStart;
|
|
2695
|
+
inString = false;
|
|
2696
|
+
stringChar = null;
|
|
2697
|
+
while (i < migrationContent.length && braceCount > 0) {
|
|
2698
|
+
const char = migrationContent[i];
|
|
2699
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2700
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
2701
|
+
inString = true;
|
|
2702
|
+
stringChar = char;
|
|
2703
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
2704
|
+
inString = false;
|
|
2705
|
+
stringChar = null;
|
|
2706
|
+
}
|
|
2707
|
+
if (!inString) {
|
|
2708
|
+
if (char === "{") braceCount++;
|
|
2709
|
+
if (char === "}") braceCount--;
|
|
2710
|
+
}
|
|
2711
|
+
i++;
|
|
2712
|
+
}
|
|
2713
|
+
if (braceCount === 0) {
|
|
2714
|
+
const upMigrationContent = migrationContent.substring(braceStart, i - 1);
|
|
2715
|
+
return parseMigrationOperationsFromContent(upMigrationContent);
|
|
2716
|
+
}
|
|
2717
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2718
|
+
} catch (error) {
|
|
2719
|
+
console.warn(`Failed to parse migration operations: ${error}`);
|
|
2720
|
+
return { collectionsToCreate: [], collectionsToDelete: [] };
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2724
|
+
// src/migration/snapshot.ts
|
|
2725
|
+
var SNAPSHOT_VERSION2 = "1.0.0";
|
|
2296
2726
|
var DEFAULT_SNAPSHOT_FILENAME = ".migration-snapshot.json";
|
|
2297
2727
|
var SNAPSHOT_MIGRATIONS = [
|
|
2298
2728
|
// Add migrations here as the format evolves
|
|
@@ -2307,7 +2737,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
2307
2737
|
snapshotPath: DEFAULT_SNAPSHOT_FILENAME,
|
|
2308
2738
|
workspaceRoot: process.cwd(),
|
|
2309
2739
|
autoMigrate: true,
|
|
2310
|
-
version:
|
|
2740
|
+
version: SNAPSHOT_VERSION2
|
|
2311
2741
|
};
|
|
2312
2742
|
function mergeConfig2(config = {}) {
|
|
2313
2743
|
return {
|
|
@@ -2319,15 +2749,15 @@ function getSnapshotPath(config = {}) {
|
|
|
2319
2749
|
const mergedConfig = mergeConfig2(config);
|
|
2320
2750
|
const workspaceRoot = mergedConfig.workspaceRoot;
|
|
2321
2751
|
const snapshotFilename = mergedConfig.snapshotPath;
|
|
2322
|
-
if (
|
|
2752
|
+
if (path5__namespace.isAbsolute(snapshotFilename)) {
|
|
2323
2753
|
return snapshotFilename;
|
|
2324
2754
|
}
|
|
2325
|
-
return
|
|
2755
|
+
return path5__namespace.join(workspaceRoot, snapshotFilename);
|
|
2326
2756
|
}
|
|
2327
2757
|
function snapshotExists(config = {}) {
|
|
2328
2758
|
try {
|
|
2329
2759
|
const snapshotPath = getSnapshotPath(config);
|
|
2330
|
-
return
|
|
2760
|
+
return fs3__namespace.existsSync(snapshotPath);
|
|
2331
2761
|
} catch {
|
|
2332
2762
|
return false;
|
|
2333
2763
|
}
|
|
@@ -2386,13 +2816,13 @@ function addSnapshotMetadata(schema, config) {
|
|
|
2386
2816
|
function saveSnapshot(schema, config = {}) {
|
|
2387
2817
|
const snapshotPath = getSnapshotPath(config);
|
|
2388
2818
|
try {
|
|
2389
|
-
const snapshotDir =
|
|
2390
|
-
if (!
|
|
2391
|
-
|
|
2819
|
+
const snapshotDir = path5__namespace.dirname(snapshotPath);
|
|
2820
|
+
if (!fs3__namespace.existsSync(snapshotDir)) {
|
|
2821
|
+
fs3__namespace.mkdirSync(snapshotDir, { recursive: true });
|
|
2392
2822
|
}
|
|
2393
2823
|
const snapshotData = addSnapshotMetadata(schema, config);
|
|
2394
2824
|
const jsonContent = JSON.stringify(snapshotData, null, 2);
|
|
2395
|
-
|
|
2825
|
+
fs3__namespace.writeFileSync(snapshotPath, jsonContent, "utf-8");
|
|
2396
2826
|
} catch (error) {
|
|
2397
2827
|
handleFileSystemError(error, "write", snapshotPath);
|
|
2398
2828
|
}
|
|
@@ -2487,7 +2917,7 @@ function deserializeSnapshot(data) {
|
|
|
2487
2917
|
function loadSnapshot(config = {}) {
|
|
2488
2918
|
const snapshotPath = getSnapshotPath(config);
|
|
2489
2919
|
try {
|
|
2490
|
-
const jsonContent =
|
|
2920
|
+
const jsonContent = fs3__namespace.readFileSync(snapshotPath, "utf-8");
|
|
2491
2921
|
const data = parseAndValidateSnapshot(jsonContent, snapshotPath);
|
|
2492
2922
|
const migratedData = migrateSnapshotFormat(data, config);
|
|
2493
2923
|
return deserializeSnapshot(migratedData);
|
|
@@ -2522,10 +2952,10 @@ function mergeSnapshots(baseSnapshot, customSnapshot) {
|
|
|
2522
2952
|
}
|
|
2523
2953
|
function findLatestSnapshot(migrationsPath) {
|
|
2524
2954
|
try {
|
|
2525
|
-
if (!
|
|
2955
|
+
if (!fs3__namespace.existsSync(migrationsPath)) {
|
|
2526
2956
|
return null;
|
|
2527
2957
|
}
|
|
2528
|
-
const files =
|
|
2958
|
+
const files = fs3__namespace.readdirSync(migrationsPath);
|
|
2529
2959
|
const snapshotFiles = files.filter(
|
|
2530
2960
|
(file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
|
|
2531
2961
|
);
|
|
@@ -2537,20 +2967,74 @@ function findLatestSnapshot(migrationsPath) {
|
|
|
2537
2967
|
if (!latestSnapshot) {
|
|
2538
2968
|
return null;
|
|
2539
2969
|
}
|
|
2540
|
-
return
|
|
2970
|
+
return path5__namespace.join(migrationsPath, latestSnapshot);
|
|
2541
2971
|
} catch (error) {
|
|
2542
2972
|
console.warn(`Error finding latest snapshot: ${error}`);
|
|
2543
2973
|
return null;
|
|
2544
2974
|
}
|
|
2545
2975
|
}
|
|
2976
|
+
function applyMigrationOperations(snapshot, operations) {
|
|
2977
|
+
const updatedCollections = new Map(snapshot.collections);
|
|
2978
|
+
for (const collectionName of operations.collectionsToDelete) {
|
|
2979
|
+
updatedCollections.delete(collectionName);
|
|
2980
|
+
}
|
|
2981
|
+
for (const collection of operations.collectionsToCreate) {
|
|
2982
|
+
updatedCollections.set(collection.name, collection);
|
|
2983
|
+
}
|
|
2984
|
+
return {
|
|
2985
|
+
...snapshot,
|
|
2986
|
+
collections: updatedCollections
|
|
2987
|
+
};
|
|
2988
|
+
}
|
|
2989
|
+
function loadSnapshotWithMigrations(config = {}) {
|
|
2990
|
+
const migrationsPath = config.migrationsPath;
|
|
2991
|
+
if (!migrationsPath) {
|
|
2992
|
+
return null;
|
|
2993
|
+
}
|
|
2994
|
+
if (fs3__namespace.existsSync(migrationsPath) && fs3__namespace.statSync(migrationsPath).isFile()) {
|
|
2995
|
+
try {
|
|
2996
|
+
const migrationContent = fs3__namespace.readFileSync(migrationsPath, "utf-8");
|
|
2997
|
+
return convertPocketBaseMigration(migrationContent);
|
|
2998
|
+
} catch (error) {
|
|
2999
|
+
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
3000
|
+
return null;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
3004
|
+
if (!latestSnapshotPath) {
|
|
3005
|
+
return null;
|
|
3006
|
+
}
|
|
3007
|
+
try {
|
|
3008
|
+
const migrationContent = fs3__namespace.readFileSync(latestSnapshotPath, "utf-8");
|
|
3009
|
+
let snapshot = convertPocketBaseMigration(migrationContent);
|
|
3010
|
+
const snapshotFilename = path5__namespace.basename(latestSnapshotPath);
|
|
3011
|
+
const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
|
|
3012
|
+
if (snapshotTimestamp) {
|
|
3013
|
+
const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
|
|
3014
|
+
for (const migrationFile of migrationFiles) {
|
|
3015
|
+
try {
|
|
3016
|
+
const migrationContent2 = fs3__namespace.readFileSync(migrationFile, "utf-8");
|
|
3017
|
+
const operations = parseMigrationOperations(migrationContent2);
|
|
3018
|
+
snapshot = applyMigrationOperations(snapshot, operations);
|
|
3019
|
+
} catch (error) {
|
|
3020
|
+
console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
return snapshot;
|
|
3025
|
+
} catch (error) {
|
|
3026
|
+
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
3027
|
+
return null;
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
2546
3030
|
function loadSnapshotIfExists(config = {}) {
|
|
2547
3031
|
const migrationsPath = config.migrationsPath;
|
|
2548
3032
|
if (!migrationsPath) {
|
|
2549
3033
|
return null;
|
|
2550
3034
|
}
|
|
2551
|
-
if (
|
|
3035
|
+
if (fs3__namespace.existsSync(migrationsPath) && fs3__namespace.statSync(migrationsPath).isFile()) {
|
|
2552
3036
|
try {
|
|
2553
|
-
const migrationContent =
|
|
3037
|
+
const migrationContent = fs3__namespace.readFileSync(migrationsPath, "utf-8");
|
|
2554
3038
|
return convertPocketBaseMigration(migrationContent);
|
|
2555
3039
|
} catch (error) {
|
|
2556
3040
|
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
@@ -2560,7 +3044,7 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
2560
3044
|
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
2561
3045
|
if (latestSnapshotPath) {
|
|
2562
3046
|
try {
|
|
2563
|
-
const migrationContent =
|
|
3047
|
+
const migrationContent = fs3__namespace.readFileSync(latestSnapshotPath, "utf-8");
|
|
2564
3048
|
return convertPocketBaseMigration(migrationContent);
|
|
2565
3049
|
} catch (error) {
|
|
2566
3050
|
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
@@ -2569,100 +3053,9 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
2569
3053
|
}
|
|
2570
3054
|
return null;
|
|
2571
3055
|
}
|
|
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
3056
|
function loadBaseMigration(migrationPath) {
|
|
2664
3057
|
try {
|
|
2665
|
-
if (!
|
|
3058
|
+
if (!fs3__namespace.existsSync(migrationPath)) {
|
|
2666
3059
|
throw new SnapshotError(
|
|
2667
3060
|
`Base migration file not found: ${migrationPath}
|
|
2668
3061
|
|
|
@@ -2673,7 +3066,7 @@ If the file exists in a different location, update the configuration.`,
|
|
|
2673
3066
|
"read"
|
|
2674
3067
|
);
|
|
2675
3068
|
}
|
|
2676
|
-
const migrationContent =
|
|
3069
|
+
const migrationContent = fs3__namespace.readFileSync(migrationPath, "utf-8");
|
|
2677
3070
|
const snapshot = convertPocketBaseMigration(migrationContent);
|
|
2678
3071
|
return snapshot;
|
|
2679
3072
|
} catch (error) {
|
|
@@ -2709,14 +3102,14 @@ Please ensure PocketBase is properly set up by running 'yarn setup'.`,
|
|
|
2709
3102
|
}
|
|
2710
3103
|
}
|
|
2711
3104
|
function getSnapshotVersion() {
|
|
2712
|
-
return
|
|
3105
|
+
return SNAPSHOT_VERSION2;
|
|
2713
3106
|
}
|
|
2714
3107
|
function validateSnapshot(snapshot) {
|
|
2715
3108
|
const issues = [];
|
|
2716
3109
|
if (!snapshot.version) {
|
|
2717
3110
|
issues.push("Missing version field");
|
|
2718
|
-
} else if (compareVersions(snapshot.version,
|
|
2719
|
-
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${
|
|
3111
|
+
} else if (compareVersions(snapshot.version, SNAPSHOT_VERSION2) > 0) {
|
|
3112
|
+
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION2}`);
|
|
2720
3113
|
}
|
|
2721
3114
|
if (!snapshot.timestamp) {
|
|
2722
3115
|
issues.push("Missing timestamp field");
|
|
@@ -2935,6 +3328,9 @@ function compareFieldOptions(currentField, previousField) {
|
|
|
2935
3328
|
for (const key of allKeys) {
|
|
2936
3329
|
const currentValue = currentOptions[key];
|
|
2937
3330
|
const previousValue = previousOptions[key];
|
|
3331
|
+
if (currentValue === void 0 && previousValue === void 0) {
|
|
3332
|
+
continue;
|
|
3333
|
+
}
|
|
2938
3334
|
if (!areValuesEqual(currentValue, previousValue)) {
|
|
2939
3335
|
changes.push({
|
|
2940
3336
|
property: `options.${key}`,
|
|
@@ -2955,11 +3351,26 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
2955
3351
|
if (!currentRelation || !previousRelation) {
|
|
2956
3352
|
return changes;
|
|
2957
3353
|
}
|
|
2958
|
-
|
|
3354
|
+
const normalizeCollection = (collection) => {
|
|
3355
|
+
if (!collection) return collection;
|
|
3356
|
+
if (collection === "_pb_users_auth_") {
|
|
3357
|
+
return "Users";
|
|
3358
|
+
}
|
|
3359
|
+
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
3360
|
+
if (nameMatch) {
|
|
3361
|
+
return nameMatch[1];
|
|
3362
|
+
}
|
|
3363
|
+
return collection;
|
|
3364
|
+
};
|
|
3365
|
+
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
3366
|
+
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
3367
|
+
if (normalizedCurrent !== normalizedPrevious) {
|
|
2959
3368
|
changes.push({
|
|
2960
3369
|
property: "relation.collection",
|
|
2961
|
-
oldValue:
|
|
2962
|
-
|
|
3370
|
+
oldValue: normalizedPrevious,
|
|
3371
|
+
// Use normalized value for clarity
|
|
3372
|
+
newValue: normalizedCurrent
|
|
3373
|
+
// Use normalized value for clarity
|
|
2963
3374
|
});
|
|
2964
3375
|
}
|
|
2965
3376
|
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
@@ -3332,10 +3743,10 @@ function mergeConfig4(config) {
|
|
|
3332
3743
|
}
|
|
3333
3744
|
function resolveMigrationDir(config) {
|
|
3334
3745
|
const workspaceRoot = config.workspaceRoot || process.cwd();
|
|
3335
|
-
if (
|
|
3746
|
+
if (path5__namespace.isAbsolute(config.migrationDir)) {
|
|
3336
3747
|
return config.migrationDir;
|
|
3337
3748
|
}
|
|
3338
|
-
return
|
|
3749
|
+
return path5__namespace.join(workspaceRoot, config.migrationDir);
|
|
3339
3750
|
}
|
|
3340
3751
|
function generateTimestamp(config) {
|
|
3341
3752
|
if (config?.timestampGenerator) {
|
|
@@ -3393,9 +3804,9 @@ function createMigrationFileStructure(upCode, downCode, config) {
|
|
|
3393
3804
|
}
|
|
3394
3805
|
function writeMigrationFile(migrationDir, filename, content) {
|
|
3395
3806
|
try {
|
|
3396
|
-
if (!
|
|
3807
|
+
if (!fs3__namespace.existsSync(migrationDir)) {
|
|
3397
3808
|
try {
|
|
3398
|
-
|
|
3809
|
+
fs3__namespace.mkdirSync(migrationDir, { recursive: true });
|
|
3399
3810
|
} catch (error) {
|
|
3400
3811
|
const fsError = error;
|
|
3401
3812
|
if (fsError.code === "EACCES" || fsError.code === "EPERM") {
|
|
@@ -3416,15 +3827,15 @@ function writeMigrationFile(migrationDir, filename, content) {
|
|
|
3416
3827
|
);
|
|
3417
3828
|
}
|
|
3418
3829
|
}
|
|
3419
|
-
const filePath =
|
|
3420
|
-
|
|
3830
|
+
const filePath = path5__namespace.join(migrationDir, filename);
|
|
3831
|
+
fs3__namespace.writeFileSync(filePath, content, "utf-8");
|
|
3421
3832
|
return filePath;
|
|
3422
3833
|
} catch (error) {
|
|
3423
3834
|
if (error instanceof FileSystemError) {
|
|
3424
3835
|
throw error;
|
|
3425
3836
|
}
|
|
3426
3837
|
const fsError = error;
|
|
3427
|
-
const filePath =
|
|
3838
|
+
const filePath = path5__namespace.join(migrationDir, filename);
|
|
3428
3839
|
if (fsError.code === "EACCES" || fsError.code === "EPERM") {
|
|
3429
3840
|
throw new FileSystemError(
|
|
3430
3841
|
`Permission denied writing migration file. Check file and directory permissions.`,
|
|
@@ -4168,8 +4579,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
4168
4579
|
};
|
|
4169
4580
|
function findConfigFile(directory) {
|
|
4170
4581
|
for (const fileName of CONFIG_FILE_NAMES) {
|
|
4171
|
-
const filePath =
|
|
4172
|
-
if (
|
|
4582
|
+
const filePath = path5__namespace.join(directory, fileName);
|
|
4583
|
+
if (fs3__namespace.existsSync(filePath)) {
|
|
4173
4584
|
return filePath;
|
|
4174
4585
|
}
|
|
4175
4586
|
}
|
|
@@ -4177,7 +4588,7 @@ function findConfigFile(directory) {
|
|
|
4177
4588
|
}
|
|
4178
4589
|
function loadJsonConfig(configPath) {
|
|
4179
4590
|
try {
|
|
4180
|
-
const content =
|
|
4591
|
+
const content = fs3__namespace.readFileSync(configPath, "utf-8");
|
|
4181
4592
|
return JSON.parse(content);
|
|
4182
4593
|
} catch (error) {
|
|
4183
4594
|
if (error instanceof SyntaxError) {
|
|
@@ -4206,10 +4617,10 @@ async function loadJsConfig(configPath) {
|
|
|
4206
4617
|
}
|
|
4207
4618
|
}
|
|
4208
4619
|
async function loadConfigFile(configPath) {
|
|
4209
|
-
if (!
|
|
4620
|
+
if (!fs3__namespace.existsSync(configPath)) {
|
|
4210
4621
|
return null;
|
|
4211
4622
|
}
|
|
4212
|
-
const ext =
|
|
4623
|
+
const ext = path5__namespace.extname(configPath).toLowerCase();
|
|
4213
4624
|
if (ext === ".json") {
|
|
4214
4625
|
return loadJsonConfig(configPath);
|
|
4215
4626
|
} else if (ext === ".js" || ext === ".mjs") {
|
|
@@ -4276,10 +4687,10 @@ function validateConfig(config, configPath) {
|
|
|
4276
4687
|
}
|
|
4277
4688
|
const cwd = process.cwd();
|
|
4278
4689
|
const possiblePaths = [
|
|
4279
|
-
|
|
4280
|
-
|
|
4690
|
+
path5__namespace.resolve(cwd, config.schema.directory),
|
|
4691
|
+
path5__namespace.resolve(cwd, "shared", config.schema.directory)
|
|
4281
4692
|
];
|
|
4282
|
-
const schemaDir = possiblePaths.find((p) =>
|
|
4693
|
+
const schemaDir = possiblePaths.find((p) => fs3__namespace.existsSync(p));
|
|
4283
4694
|
if (!schemaDir) {
|
|
4284
4695
|
throw new ConfigurationError(`Schema directory not found. Tried: ${possiblePaths.join(", ")}`, configPath, [
|
|
4285
4696
|
"schema.directory"
|
|
@@ -4291,15 +4702,15 @@ async function loadConfig(options = {}) {
|
|
|
4291
4702
|
let configFilePath;
|
|
4292
4703
|
const cwd = process.cwd();
|
|
4293
4704
|
if (options.config) {
|
|
4294
|
-
const explicitPath =
|
|
4295
|
-
if (!
|
|
4705
|
+
const explicitPath = path5__namespace.resolve(cwd, options.config);
|
|
4706
|
+
if (!fs3__namespace.existsSync(explicitPath)) {
|
|
4296
4707
|
throw new ConfigurationError(`Configuration file not found: ${explicitPath}`, explicitPath);
|
|
4297
4708
|
}
|
|
4298
4709
|
configFilePath = explicitPath;
|
|
4299
4710
|
} else {
|
|
4300
|
-
const searchDirs = [cwd,
|
|
4711
|
+
const searchDirs = [cwd, path5__namespace.join(cwd, "shared")];
|
|
4301
4712
|
for (const dir of searchDirs) {
|
|
4302
|
-
if (
|
|
4713
|
+
if (fs3__namespace.existsSync(dir)) {
|
|
4303
4714
|
const found = findConfigFile(dir);
|
|
4304
4715
|
if (found) {
|
|
4305
4716
|
configFilePath = found;
|
|
@@ -4328,18 +4739,18 @@ async function loadConfig(options = {}) {
|
|
|
4328
4739
|
function getSchemaDirectory(config) {
|
|
4329
4740
|
const cwd = process.cwd();
|
|
4330
4741
|
const possiblePaths = [
|
|
4331
|
-
|
|
4332
|
-
|
|
4742
|
+
path5__namespace.resolve(cwd, config.schema.directory),
|
|
4743
|
+
path5__namespace.resolve(cwd, "shared", config.schema.directory)
|
|
4333
4744
|
];
|
|
4334
|
-
return possiblePaths.find((p) =>
|
|
4745
|
+
return possiblePaths.find((p) => fs3__namespace.existsSync(p)) || possiblePaths[0];
|
|
4335
4746
|
}
|
|
4336
4747
|
function getMigrationsDirectory(config) {
|
|
4337
4748
|
const cwd = process.cwd();
|
|
4338
4749
|
const possiblePaths = [
|
|
4339
|
-
|
|
4340
|
-
|
|
4750
|
+
path5__namespace.resolve(cwd, config.migrations.directory),
|
|
4751
|
+
path5__namespace.resolve(cwd, "shared", config.migrations.directory)
|
|
4341
4752
|
];
|
|
4342
|
-
return possiblePaths.find((p) =>
|
|
4753
|
+
return possiblePaths.find((p) => fs3__namespace.existsSync(p)) || possiblePaths[0];
|
|
4343
4754
|
}
|
|
4344
4755
|
var currentVerbosity = "normal";
|
|
4345
4756
|
function setVerbosity(level) {
|
|
@@ -4556,7 +4967,7 @@ async function executeGenerate(options) {
|
|
|
4556
4967
|
const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
|
|
4557
4968
|
logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
|
|
4558
4969
|
logInfo("Loading previous snapshot...");
|
|
4559
|
-
const previousSnapshot =
|
|
4970
|
+
const previousSnapshot = loadSnapshotWithMigrations({
|
|
4560
4971
|
migrationsPath: migrationsDir,
|
|
4561
4972
|
workspaceRoot: process.cwd()
|
|
4562
4973
|
});
|
|
@@ -4583,7 +4994,7 @@ async function executeGenerate(options) {
|
|
|
4583
4994
|
"Creating migration file...",
|
|
4584
4995
|
() => Promise.resolve(generate(diff, migrationsDir))
|
|
4585
4996
|
);
|
|
4586
|
-
logSuccess(`Migration file created: ${
|
|
4997
|
+
logSuccess(`Migration file created: ${path5__namespace.basename(migrationPath)}`);
|
|
4587
4998
|
logSection("\u2705 Next Steps");
|
|
4588
4999
|
console.log();
|
|
4589
5000
|
console.log(" 1. Review the generated migration file:");
|
|
@@ -4749,7 +5160,7 @@ async function executeStatus(options) {
|
|
|
4749
5160
|
const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
|
|
4750
5161
|
logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
|
|
4751
5162
|
logInfo("Loading previous snapshot...");
|
|
4752
|
-
const previousSnapshot =
|
|
5163
|
+
const previousSnapshot = loadSnapshotWithMigrations({
|
|
4753
5164
|
migrationsPath: migrationsDir,
|
|
4754
5165
|
workspaceRoot: process.cwd()
|
|
4755
5166
|
});
|
|
@@ -4860,11 +5271,18 @@ exports.MigrationGenerationError = MigrationGenerationError;
|
|
|
4860
5271
|
exports.MigrationGenerator = MigrationGenerator;
|
|
4861
5272
|
exports.POCKETBASE_FIELD_TYPES = POCKETBASE_FIELD_TYPES;
|
|
4862
5273
|
exports.PermissionTemplates = PermissionTemplates;
|
|
5274
|
+
exports.ProjectCollection = ProjectCollection;
|
|
5275
|
+
exports.ProjectInputSchema = ProjectInputSchema;
|
|
5276
|
+
exports.ProjectSchema = ProjectSchema;
|
|
5277
|
+
exports.RelationField = RelationField;
|
|
5278
|
+
exports.RelationsField = RelationsField;
|
|
4863
5279
|
exports.SchemaAnalyzer = SchemaAnalyzer;
|
|
4864
5280
|
exports.SchemaParsingError = SchemaParsingError;
|
|
4865
5281
|
exports.SnapshotError = SnapshotError;
|
|
4866
5282
|
exports.SnapshotManager = SnapshotManager;
|
|
4867
5283
|
exports.StatusEnum = StatusEnum;
|
|
5284
|
+
exports.UserCollection = UserCollection;
|
|
5285
|
+
exports.UserCollectionSchema = UserCollectionSchema;
|
|
4868
5286
|
exports.UserInputSchema = UserInputSchema;
|
|
4869
5287
|
exports.UserMutator = UserMutator;
|
|
4870
5288
|
exports.UserSchema = UserSchema;
|
|
@@ -4887,6 +5305,7 @@ exports.convertZodSchemaToCollectionSchema = convertZodSchemaToCollectionSchema;
|
|
|
4887
5305
|
exports.createMigrationFileStructure = createMigrationFileStructure;
|
|
4888
5306
|
exports.createPermissions = createPermissions;
|
|
4889
5307
|
exports.dateField = dateField;
|
|
5308
|
+
exports.defineCollection = defineCollection;
|
|
4890
5309
|
exports.detectDestructiveChanges = detectDestructiveChanges;
|
|
4891
5310
|
exports.detectFieldChanges = detectFieldChanges;
|
|
4892
5311
|
exports.discoverSchemaFiles = discoverSchemaFiles;
|
|
@@ -4955,6 +5374,7 @@ exports.loadBaseMigration = loadBaseMigration;
|
|
|
4955
5374
|
exports.loadConfig = loadConfig;
|
|
4956
5375
|
exports.loadSnapshot = loadSnapshot;
|
|
4957
5376
|
exports.loadSnapshotIfExists = loadSnapshotIfExists;
|
|
5377
|
+
exports.loadSnapshotWithMigrations = loadSnapshotWithMigrations;
|
|
4958
5378
|
exports.logError = logError;
|
|
4959
5379
|
exports.logInfo = logInfo;
|
|
4960
5380
|
exports.logSection = logSection;
|
|
@@ -4976,8 +5396,6 @@ exports.numberField = numberField;
|
|
|
4976
5396
|
exports.omitImageFilesSchema = omitImageFilesSchema;
|
|
4977
5397
|
exports.parseSchemaFiles = parseSchemaFiles;
|
|
4978
5398
|
exports.pluralize = pluralize;
|
|
4979
|
-
exports.relationField = relationField;
|
|
4980
|
-
exports.relationsField = relationsField;
|
|
4981
5399
|
exports.requiresForceFlag = requiresForceFlag;
|
|
4982
5400
|
exports.resolveTargetCollection = resolveTargetCollection;
|
|
4983
5401
|
exports.resolveTemplate = resolveTemplate;
|