pocketbase-zod-schema 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/cli/index.cjs +3383 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +30 -0
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.js +3331 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/migrate.cjs +3380 -0
- package/dist/cli/migrate.cjs.map +1 -0
- package/dist/cli/migrate.d.cts +1 -0
- package/dist/cli/migrate.d.ts +1 -0
- package/dist/cli/migrate.js +3353 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/utils/index.cjs +540 -0
- package/dist/cli/utils/index.cjs.map +1 -0
- package/dist/cli/utils/index.d.cts +232 -0
- package/dist/cli/utils/index.d.ts +232 -0
- package/dist/cli/utils/index.js +487 -0
- package/dist/cli/utils/index.js.map +1 -0
- package/dist/enums.cjs +19 -0
- package/dist/enums.cjs.map +1 -0
- package/dist/enums.d.cts +6 -0
- package/dist/enums.d.ts +6 -0
- package/dist/enums.js +17 -0
- package/dist/enums.js.map +1 -0
- package/dist/index.cjs +4900 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +4726 -0
- package/dist/index.js.map +1 -0
- package/dist/migration/analyzer.cjs +1267 -0
- package/dist/migration/analyzer.cjs.map +1 -0
- package/dist/migration/analyzer.d.cts +186 -0
- package/dist/migration/analyzer.d.ts +186 -0
- package/dist/migration/analyzer.js +1232 -0
- package/dist/migration/analyzer.js.map +1 -0
- package/dist/migration/diff.cjs +557 -0
- package/dist/migration/diff.cjs.map +1 -0
- package/dist/migration/diff.d.cts +291 -0
- package/dist/migration/diff.d.ts +291 -0
- package/dist/migration/diff.js +534 -0
- package/dist/migration/diff.js.map +1 -0
- package/dist/migration/generator.cjs +778 -0
- package/dist/migration/generator.cjs.map +1 -0
- package/dist/migration/generator.d.cts +225 -0
- package/dist/migration/generator.d.ts +225 -0
- package/dist/migration/generator.js +737 -0
- package/dist/migration/generator.js.map +1 -0
- package/dist/migration/index.cjs +3390 -0
- package/dist/migration/index.cjs.map +1 -0
- package/dist/migration/index.d.cts +103 -0
- package/dist/migration/index.d.ts +103 -0
- package/dist/migration/index.js +3265 -0
- package/dist/migration/index.js.map +1 -0
- package/dist/migration/snapshot.cjs +609 -0
- package/dist/migration/snapshot.cjs.map +1 -0
- package/dist/migration/snapshot.d.cts +167 -0
- package/dist/migration/snapshot.d.ts +167 -0
- package/dist/migration/snapshot.js +575 -0
- package/dist/migration/snapshot.js.map +1 -0
- package/dist/migration/utils/index.cjs +672 -0
- package/dist/migration/utils/index.cjs.map +1 -0
- package/dist/migration/utils/index.d.cts +207 -0
- package/dist/migration/utils/index.d.ts +207 -0
- package/dist/migration/utils/index.js +641 -0
- package/dist/migration/utils/index.js.map +1 -0
- package/dist/mutator.cjs +427 -0
- package/dist/mutator.cjs.map +1 -0
- package/dist/mutator.d.cts +190 -0
- package/dist/mutator.d.ts +190 -0
- package/dist/mutator.js +425 -0
- package/dist/mutator.js.map +1 -0
- package/dist/permissions-ZHafVSIx.d.cts +71 -0
- package/dist/permissions-ZHafVSIx.d.ts +71 -0
- package/dist/schema.cjs +430 -0
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.cts +316 -0
- package/dist/schema.d.ts +316 -0
- package/dist/schema.js +396 -0
- package/dist/schema.js.map +1 -0
- package/dist/types-BbTgmg6H.d.cts +91 -0
- package/dist/types-z1Dkjg8m.d.ts +91 -0
- package/dist/types.cjs +4 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +14 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/user-jS1aYoeD.d.cts +123 -0
- package/dist/user-jS1aYoeD.d.ts +123 -0
- package/package.json +165 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
|
|
6
|
+
function _interopNamespace(e) {
|
|
7
|
+
if (e && e.__esModule) return e;
|
|
8
|
+
var n = Object.create(null);
|
|
9
|
+
if (e) {
|
|
10
|
+
Object.keys(e).forEach(function (k) {
|
|
11
|
+
if (k !== 'default') {
|
|
12
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () { return e[k]; }
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
25
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
26
|
+
|
|
27
|
+
// src/migration/snapshot.ts
|
|
28
|
+
|
|
29
|
+
// src/migration/errors.ts
|
|
30
|
+
var MigrationError = class _MigrationError extends Error {
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "MigrationError";
|
|
34
|
+
Object.setPrototypeOf(this, _MigrationError.prototype);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var SnapshotError = class _SnapshotError extends MigrationError {
|
|
38
|
+
snapshotPath;
|
|
39
|
+
operation;
|
|
40
|
+
originalError;
|
|
41
|
+
constructor(message, snapshotPath, operation, originalError) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "SnapshotError";
|
|
44
|
+
this.snapshotPath = snapshotPath;
|
|
45
|
+
this.operation = operation;
|
|
46
|
+
this.originalError = originalError;
|
|
47
|
+
Object.setPrototypeOf(this, _SnapshotError.prototype);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Creates a formatted error message with snapshot path and operation details
|
|
51
|
+
*/
|
|
52
|
+
getDetailedMessage() {
|
|
53
|
+
const parts = [this.message];
|
|
54
|
+
if (this.operation) {
|
|
55
|
+
parts.push(`
|
|
56
|
+
Operation: ${this.operation}`);
|
|
57
|
+
}
|
|
58
|
+
if (this.snapshotPath) {
|
|
59
|
+
parts.push(`
|
|
60
|
+
Snapshot: ${this.snapshotPath}`);
|
|
61
|
+
}
|
|
62
|
+
if (this.originalError) {
|
|
63
|
+
parts.push(`
|
|
64
|
+
Cause: ${this.originalError.message}`);
|
|
65
|
+
}
|
|
66
|
+
return parts.join("");
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var FileSystemError = class _FileSystemError extends MigrationError {
|
|
70
|
+
path;
|
|
71
|
+
operation;
|
|
72
|
+
code;
|
|
73
|
+
originalError;
|
|
74
|
+
constructor(message, path2, operation, code, originalError) {
|
|
75
|
+
super(message);
|
|
76
|
+
this.name = "FileSystemError";
|
|
77
|
+
this.path = path2;
|
|
78
|
+
this.operation = operation;
|
|
79
|
+
this.code = code;
|
|
80
|
+
this.originalError = originalError;
|
|
81
|
+
Object.setPrototypeOf(this, _FileSystemError.prototype);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Creates a formatted error message with path, operation, and error code details
|
|
85
|
+
*/
|
|
86
|
+
getDetailedMessage() {
|
|
87
|
+
const parts = [this.message];
|
|
88
|
+
if (this.operation) {
|
|
89
|
+
parts.push(`
|
|
90
|
+
Operation: ${this.operation}`);
|
|
91
|
+
}
|
|
92
|
+
if (this.path) {
|
|
93
|
+
parts.push(`
|
|
94
|
+
Path: ${this.path}`);
|
|
95
|
+
}
|
|
96
|
+
if (this.code) {
|
|
97
|
+
parts.push(`
|
|
98
|
+
Error Code: ${this.code}`);
|
|
99
|
+
}
|
|
100
|
+
if (this.originalError) {
|
|
101
|
+
parts.push(`
|
|
102
|
+
Cause: ${this.originalError.message}`);
|
|
103
|
+
}
|
|
104
|
+
return parts.join("");
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/migration/snapshot.ts
|
|
109
|
+
var SNAPSHOT_VERSION = "1.0.0";
|
|
110
|
+
var DEFAULT_SNAPSHOT_FILENAME = ".migration-snapshot.json";
|
|
111
|
+
var SNAPSHOT_MIGRATIONS = [
|
|
112
|
+
// Add migrations here as the format evolves
|
|
113
|
+
// Example:
|
|
114
|
+
// {
|
|
115
|
+
// fromVersion: '0.9.0',
|
|
116
|
+
// toVersion: '1.0.0',
|
|
117
|
+
// migrate: (data) => ({ ...data, newField: 'default' })
|
|
118
|
+
// }
|
|
119
|
+
];
|
|
120
|
+
var DEFAULT_CONFIG = {
|
|
121
|
+
snapshotPath: DEFAULT_SNAPSHOT_FILENAME,
|
|
122
|
+
workspaceRoot: process.cwd(),
|
|
123
|
+
autoMigrate: true,
|
|
124
|
+
version: SNAPSHOT_VERSION
|
|
125
|
+
};
|
|
126
|
+
function mergeConfig(config = {}) {
|
|
127
|
+
return {
|
|
128
|
+
...DEFAULT_CONFIG,
|
|
129
|
+
...config
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function getSnapshotPath(config = {}) {
|
|
133
|
+
const mergedConfig = mergeConfig(config);
|
|
134
|
+
const workspaceRoot = mergedConfig.workspaceRoot;
|
|
135
|
+
const snapshotFilename = mergedConfig.snapshotPath;
|
|
136
|
+
if (path__namespace.isAbsolute(snapshotFilename)) {
|
|
137
|
+
return snapshotFilename;
|
|
138
|
+
}
|
|
139
|
+
return path__namespace.join(workspaceRoot, snapshotFilename);
|
|
140
|
+
}
|
|
141
|
+
function snapshotExists(config = {}) {
|
|
142
|
+
try {
|
|
143
|
+
const snapshotPath = getSnapshotPath(config);
|
|
144
|
+
return fs__namespace.existsSync(snapshotPath);
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function handleFileSystemError(error, operation, filePath) {
|
|
150
|
+
const fsError = error;
|
|
151
|
+
if (fsError.code === "ENOENT") {
|
|
152
|
+
throw new SnapshotError(`Snapshot file not found: ${filePath}`, filePath, operation, error);
|
|
153
|
+
} else if (fsError.code === "EACCES" || fsError.code === "EPERM") {
|
|
154
|
+
throw new FileSystemError(
|
|
155
|
+
`Permission denied ${operation === "read" ? "reading" : "writing"} snapshot file. Check file permissions.`,
|
|
156
|
+
filePath,
|
|
157
|
+
operation,
|
|
158
|
+
fsError.code,
|
|
159
|
+
error
|
|
160
|
+
);
|
|
161
|
+
} else if (fsError.code === "ENOSPC") {
|
|
162
|
+
throw new FileSystemError(
|
|
163
|
+
`No space left on device when ${operation === "read" ? "reading" : "writing"} snapshot file.`,
|
|
164
|
+
filePath,
|
|
165
|
+
operation,
|
|
166
|
+
fsError.code,
|
|
167
|
+
error
|
|
168
|
+
);
|
|
169
|
+
} else {
|
|
170
|
+
throw new SnapshotError(`Failed to ${operation} snapshot file: ${error.message}`, filePath, operation, error);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function serializeMap(map) {
|
|
174
|
+
const obj = {};
|
|
175
|
+
for (const [key, value] of map.entries()) {
|
|
176
|
+
obj[key] = value;
|
|
177
|
+
}
|
|
178
|
+
return obj;
|
|
179
|
+
}
|
|
180
|
+
function deserializeMap(obj) {
|
|
181
|
+
const map = /* @__PURE__ */ new Map();
|
|
182
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
183
|
+
map.set(key, value);
|
|
184
|
+
}
|
|
185
|
+
return map;
|
|
186
|
+
}
|
|
187
|
+
function serializeSchemaDefinition(schema) {
|
|
188
|
+
return {
|
|
189
|
+
collections: serializeMap(schema.collections)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function addSnapshotMetadata(schema, config) {
|
|
193
|
+
const mergedConfig = mergeConfig(config);
|
|
194
|
+
return {
|
|
195
|
+
version: mergedConfig.version,
|
|
196
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
197
|
+
...serializeSchemaDefinition(schema)
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function saveSnapshot(schema, config = {}) {
|
|
201
|
+
const snapshotPath = getSnapshotPath(config);
|
|
202
|
+
try {
|
|
203
|
+
const snapshotDir = path__namespace.dirname(snapshotPath);
|
|
204
|
+
if (!fs__namespace.existsSync(snapshotDir)) {
|
|
205
|
+
fs__namespace.mkdirSync(snapshotDir, { recursive: true });
|
|
206
|
+
}
|
|
207
|
+
const snapshotData = addSnapshotMetadata(schema, config);
|
|
208
|
+
const jsonContent = JSON.stringify(snapshotData, null, 2);
|
|
209
|
+
fs__namespace.writeFileSync(snapshotPath, jsonContent, "utf-8");
|
|
210
|
+
} catch (error) {
|
|
211
|
+
handleFileSystemError(error, "write", snapshotPath);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function parseAndValidateSnapshot(jsonContent, snapshotPath) {
|
|
215
|
+
try {
|
|
216
|
+
const data = JSON.parse(jsonContent);
|
|
217
|
+
if (!data.version) {
|
|
218
|
+
throw new SnapshotError(
|
|
219
|
+
"Snapshot file is missing version field. The snapshot may be corrupted.",
|
|
220
|
+
snapshotPath,
|
|
221
|
+
"validate"
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
if (!data.timestamp) {
|
|
225
|
+
throw new SnapshotError(
|
|
226
|
+
"Snapshot file is missing timestamp field. The snapshot may be corrupted.",
|
|
227
|
+
snapshotPath,
|
|
228
|
+
"validate"
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
if (!data.collections) {
|
|
232
|
+
throw new SnapshotError(
|
|
233
|
+
"Snapshot file is missing collections field. The snapshot may be corrupted.",
|
|
234
|
+
snapshotPath,
|
|
235
|
+
"validate"
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
return data;
|
|
239
|
+
} catch (error) {
|
|
240
|
+
if (error instanceof SnapshotError) {
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
if (error instanceof SyntaxError) {
|
|
244
|
+
throw new SnapshotError(
|
|
245
|
+
`Invalid JSON in snapshot file. The file may be corrupted or manually edited incorrectly.`,
|
|
246
|
+
snapshotPath,
|
|
247
|
+
"parse",
|
|
248
|
+
error
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function compareVersions(a, b) {
|
|
255
|
+
const partsA = a.split(".").map(Number);
|
|
256
|
+
const partsB = b.split(".").map(Number);
|
|
257
|
+
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
258
|
+
const numA = partsA[i] || 0;
|
|
259
|
+
const numB = partsB[i] || 0;
|
|
260
|
+
if (numA < numB) return -1;
|
|
261
|
+
if (numA > numB) return 1;
|
|
262
|
+
}
|
|
263
|
+
return 0;
|
|
264
|
+
}
|
|
265
|
+
function migrateSnapshotFormat(data, config) {
|
|
266
|
+
const mergedConfig = mergeConfig(config);
|
|
267
|
+
const currentVersion = data.version;
|
|
268
|
+
const targetVersion = mergedConfig.version;
|
|
269
|
+
if (currentVersion === targetVersion) {
|
|
270
|
+
return data;
|
|
271
|
+
}
|
|
272
|
+
if (!mergedConfig.autoMigrate) {
|
|
273
|
+
console.warn(
|
|
274
|
+
`Snapshot version ${currentVersion} differs from current ${targetVersion}, but auto-migrate is disabled.`
|
|
275
|
+
);
|
|
276
|
+
return data;
|
|
277
|
+
}
|
|
278
|
+
let migratedData = { ...data };
|
|
279
|
+
let currentMigrationVersion = currentVersion;
|
|
280
|
+
const sortedMigrations = [...SNAPSHOT_MIGRATIONS].sort((a, b) => compareVersions(a.fromVersion, b.fromVersion));
|
|
281
|
+
for (const migration of sortedMigrations) {
|
|
282
|
+
if (compareVersions(currentMigrationVersion, migration.fromVersion) === 0) {
|
|
283
|
+
console.log(`Migrating snapshot from ${migration.fromVersion} to ${migration.toVersion}...`);
|
|
284
|
+
migratedData = migration.migrate(migratedData);
|
|
285
|
+
migratedData.version = migration.toVersion;
|
|
286
|
+
currentMigrationVersion = migration.toVersion;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (compareVersions(currentMigrationVersion, targetVersion) !== 0) {
|
|
290
|
+
console.warn(`Unknown snapshot version ${currentVersion}, attempting to load anyway...`);
|
|
291
|
+
}
|
|
292
|
+
return migratedData;
|
|
293
|
+
}
|
|
294
|
+
function deserializeSnapshot(data) {
|
|
295
|
+
return {
|
|
296
|
+
version: data.version,
|
|
297
|
+
timestamp: data.timestamp,
|
|
298
|
+
collections: deserializeMap(data.collections)
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function loadSnapshot(config = {}) {
|
|
302
|
+
const snapshotPath = getSnapshotPath(config);
|
|
303
|
+
try {
|
|
304
|
+
const jsonContent = fs__namespace.readFileSync(snapshotPath, "utf-8");
|
|
305
|
+
const data = parseAndValidateSnapshot(jsonContent, snapshotPath);
|
|
306
|
+
const migratedData = migrateSnapshotFormat(data, config);
|
|
307
|
+
return deserializeSnapshot(migratedData);
|
|
308
|
+
} catch (error) {
|
|
309
|
+
if (error instanceof SnapshotError || error instanceof FileSystemError) {
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
if (error.code === "ENOENT") {
|
|
313
|
+
throw new SnapshotError(
|
|
314
|
+
`Snapshot file not found. This may be the first migration run.`,
|
|
315
|
+
snapshotPath,
|
|
316
|
+
"read",
|
|
317
|
+
error
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
handleFileSystemError(error, "read", snapshotPath);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function mergeSnapshots(baseSnapshot, customSnapshot) {
|
|
324
|
+
if (!customSnapshot) {
|
|
325
|
+
return baseSnapshot;
|
|
326
|
+
}
|
|
327
|
+
const mergedCollections = new Map(baseSnapshot.collections);
|
|
328
|
+
for (const [name, schema] of customSnapshot.collections.entries()) {
|
|
329
|
+
mergedCollections.set(name, schema);
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
version: customSnapshot.version || baseSnapshot.version,
|
|
333
|
+
timestamp: customSnapshot.timestamp || baseSnapshot.timestamp,
|
|
334
|
+
collections: mergedCollections
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function findLatestSnapshot(migrationsPath) {
|
|
338
|
+
try {
|
|
339
|
+
if (!fs__namespace.existsSync(migrationsPath)) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
const files = fs__namespace.readdirSync(migrationsPath);
|
|
343
|
+
const snapshotFiles = files.filter(
|
|
344
|
+
(file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
|
|
345
|
+
);
|
|
346
|
+
if (snapshotFiles.length === 0) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
snapshotFiles.sort().reverse();
|
|
350
|
+
const latestSnapshot = snapshotFiles[0];
|
|
351
|
+
if (!latestSnapshot) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
return path__namespace.join(migrationsPath, latestSnapshot);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.warn(`Error finding latest snapshot: ${error}`);
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function loadSnapshotIfExists(config = {}) {
|
|
361
|
+
const migrationsPath = config.migrationsPath;
|
|
362
|
+
if (!migrationsPath) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
if (fs__namespace.existsSync(migrationsPath) && fs__namespace.statSync(migrationsPath).isFile()) {
|
|
366
|
+
try {
|
|
367
|
+
const migrationContent = fs__namespace.readFileSync(migrationsPath, "utf-8");
|
|
368
|
+
return convertPocketBaseMigration(migrationContent);
|
|
369
|
+
} catch (error) {
|
|
370
|
+
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
375
|
+
if (latestSnapshotPath) {
|
|
376
|
+
try {
|
|
377
|
+
const migrationContent = fs__namespace.readFileSync(latestSnapshotPath, "utf-8");
|
|
378
|
+
return convertPocketBaseMigration(migrationContent);
|
|
379
|
+
} catch (error) {
|
|
380
|
+
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
function convertPocketBaseCollection(pbCollection) {
|
|
387
|
+
const fields = [];
|
|
388
|
+
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
389
|
+
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
390
|
+
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
391
|
+
for (const pbField of pbCollection.fields) {
|
|
392
|
+
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
const field = {
|
|
399
|
+
name: pbField.name,
|
|
400
|
+
type: pbField.type,
|
|
401
|
+
required: pbField.required || false
|
|
402
|
+
};
|
|
403
|
+
if (pbField.options) {
|
|
404
|
+
field.options = pbField.options;
|
|
405
|
+
}
|
|
406
|
+
if (pbField.type === "relation") {
|
|
407
|
+
field.relation = {
|
|
408
|
+
collection: pbField.options?.collectionId || "",
|
|
409
|
+
cascadeDelete: pbField.options?.cascadeDelete || false,
|
|
410
|
+
maxSelect: pbField.options?.maxSelect,
|
|
411
|
+
minSelect: pbField.options?.minSelect
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
fields.push(field);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
const schema = {
|
|
418
|
+
name: pbCollection.name,
|
|
419
|
+
type: pbCollection.type || "base",
|
|
420
|
+
fields
|
|
421
|
+
};
|
|
422
|
+
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
423
|
+
schema.indexes = pbCollection.indexes;
|
|
424
|
+
}
|
|
425
|
+
const rules = {};
|
|
426
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
427
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
428
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
429
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
430
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
431
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
432
|
+
if (Object.keys(rules).length > 0) {
|
|
433
|
+
schema.rules = rules;
|
|
434
|
+
}
|
|
435
|
+
return schema;
|
|
436
|
+
}
|
|
437
|
+
function convertPocketBaseMigration(migrationContent) {
|
|
438
|
+
try {
|
|
439
|
+
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
440
|
+
if (!snapshotMatch) {
|
|
441
|
+
throw new Error("Could not find snapshot array in migration file");
|
|
442
|
+
}
|
|
443
|
+
const snapshotArrayStr = snapshotMatch[1];
|
|
444
|
+
let snapshotArray;
|
|
445
|
+
try {
|
|
446
|
+
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
447
|
+
} catch (parseError) {
|
|
448
|
+
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
449
|
+
}
|
|
450
|
+
if (!Array.isArray(snapshotArray)) {
|
|
451
|
+
throw new Error("Snapshot is not an array");
|
|
452
|
+
}
|
|
453
|
+
const collections = /* @__PURE__ */ new Map();
|
|
454
|
+
for (const pbCollection of snapshotArray) {
|
|
455
|
+
if (!pbCollection.name) {
|
|
456
|
+
console.warn("Skipping collection without name");
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
const schema = convertPocketBaseCollection(pbCollection);
|
|
460
|
+
collections.set(pbCollection.name, schema);
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
version: SNAPSHOT_VERSION,
|
|
464
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
465
|
+
collections
|
|
466
|
+
};
|
|
467
|
+
} catch (error) {
|
|
468
|
+
throw new SnapshotError(
|
|
469
|
+
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
470
|
+
void 0,
|
|
471
|
+
"parse",
|
|
472
|
+
error instanceof Error ? error : void 0
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function loadBaseMigration(migrationPath) {
|
|
477
|
+
try {
|
|
478
|
+
if (!fs__namespace.existsSync(migrationPath)) {
|
|
479
|
+
throw new SnapshotError(
|
|
480
|
+
`Base migration file not found: ${migrationPath}
|
|
481
|
+
|
|
482
|
+
This file should contain PocketBase's initial schema.
|
|
483
|
+
Please ensure PocketBase is properly set up by running 'yarn setup'.
|
|
484
|
+
If the file exists in a different location, update the configuration.`,
|
|
485
|
+
migrationPath,
|
|
486
|
+
"read"
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
const migrationContent = fs__namespace.readFileSync(migrationPath, "utf-8");
|
|
490
|
+
const snapshot = convertPocketBaseMigration(migrationContent);
|
|
491
|
+
return snapshot;
|
|
492
|
+
} catch (error) {
|
|
493
|
+
if (error instanceof SnapshotError) {
|
|
494
|
+
throw error;
|
|
495
|
+
}
|
|
496
|
+
if (error.code === "ENOENT") {
|
|
497
|
+
throw new SnapshotError(
|
|
498
|
+
`Base migration file not found: ${migrationPath}
|
|
499
|
+
|
|
500
|
+
This file should contain PocketBase's initial schema.
|
|
501
|
+
Please ensure PocketBase is properly set up by running 'yarn setup'.`,
|
|
502
|
+
migrationPath,
|
|
503
|
+
"read",
|
|
504
|
+
error
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
if (error.code === "EACCES" || error.code === "EPERM") {
|
|
508
|
+
throw new FileSystemError(
|
|
509
|
+
`Permission denied reading base migration file. Check file permissions.`,
|
|
510
|
+
migrationPath,
|
|
511
|
+
"read",
|
|
512
|
+
error.code,
|
|
513
|
+
error
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
throw new SnapshotError(
|
|
517
|
+
`Failed to load base migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
518
|
+
migrationPath,
|
|
519
|
+
"read",
|
|
520
|
+
error instanceof Error ? error : void 0
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function getSnapshotVersion() {
|
|
525
|
+
return SNAPSHOT_VERSION;
|
|
526
|
+
}
|
|
527
|
+
function validateSnapshot(snapshot) {
|
|
528
|
+
const issues = [];
|
|
529
|
+
if (!snapshot.version) {
|
|
530
|
+
issues.push("Missing version field");
|
|
531
|
+
} else if (compareVersions(snapshot.version, SNAPSHOT_VERSION) > 0) {
|
|
532
|
+
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION}`);
|
|
533
|
+
}
|
|
534
|
+
if (!snapshot.timestamp) {
|
|
535
|
+
issues.push("Missing timestamp field");
|
|
536
|
+
}
|
|
537
|
+
if (!snapshot.collections) {
|
|
538
|
+
issues.push("Missing collections field");
|
|
539
|
+
} else if (!(snapshot.collections instanceof Map)) {
|
|
540
|
+
issues.push("Collections field is not a Map");
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
valid: issues.length === 0,
|
|
544
|
+
issues
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
var SnapshotManager = class {
|
|
548
|
+
config;
|
|
549
|
+
constructor(config = {}) {
|
|
550
|
+
this.config = mergeConfig(config);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Loads the current snapshot
|
|
554
|
+
*/
|
|
555
|
+
loadSnapshot() {
|
|
556
|
+
return loadSnapshot(this.config);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Saves a schema as a snapshot
|
|
560
|
+
*/
|
|
561
|
+
saveSnapshot(schema) {
|
|
562
|
+
saveSnapshot(schema, this.config);
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Loads snapshot if it exists, returns null otherwise
|
|
566
|
+
*/
|
|
567
|
+
loadSnapshotIfExists() {
|
|
568
|
+
return loadSnapshotIfExists(this.config);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Checks if a snapshot exists
|
|
572
|
+
*/
|
|
573
|
+
snapshotExists() {
|
|
574
|
+
return snapshotExists(this.config);
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Converts a PocketBase migration to a snapshot
|
|
578
|
+
*/
|
|
579
|
+
convertPocketBaseMigration(content) {
|
|
580
|
+
return convertPocketBaseMigration(content);
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Gets the snapshot file path
|
|
584
|
+
*/
|
|
585
|
+
getSnapshotPath() {
|
|
586
|
+
return getSnapshotPath(this.config);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Validates a snapshot
|
|
590
|
+
*/
|
|
591
|
+
validateSnapshot(snapshot) {
|
|
592
|
+
return validateSnapshot(snapshot);
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
exports.SnapshotManager = SnapshotManager;
|
|
597
|
+
exports.convertPocketBaseMigration = convertPocketBaseMigration;
|
|
598
|
+
exports.findLatestSnapshot = findLatestSnapshot;
|
|
599
|
+
exports.getSnapshotPath = getSnapshotPath;
|
|
600
|
+
exports.getSnapshotVersion = getSnapshotVersion;
|
|
601
|
+
exports.loadBaseMigration = loadBaseMigration;
|
|
602
|
+
exports.loadSnapshot = loadSnapshot;
|
|
603
|
+
exports.loadSnapshotIfExists = loadSnapshotIfExists;
|
|
604
|
+
exports.mergeSnapshots = mergeSnapshots;
|
|
605
|
+
exports.saveSnapshot = saveSnapshot;
|
|
606
|
+
exports.snapshotExists = snapshotExists;
|
|
607
|
+
exports.validateSnapshot = validateSnapshot;
|
|
608
|
+
//# sourceMappingURL=snapshot.cjs.map
|
|
609
|
+
//# sourceMappingURL=snapshot.cjs.map
|