pocketbase-zod-schema 0.2.4 → 0.3.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 +15 -0
- package/README.md +209 -24
- package/dist/cli/index.cjs +406 -294
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +3 -1
- package/dist/cli/index.d.ts +3 -1
- package/dist/cli/index.js +406 -294
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +406 -294
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +406 -294
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/utils/index.d.cts +3 -1
- package/dist/cli/utils/index.d.ts +3 -1
- package/dist/fields-UcOPu1OQ.d.cts +364 -0
- package/dist/fields-UcOPu1OQ.d.ts +364 -0
- package/dist/index.cjs +633 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +619 -101
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +44 -0
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +2 -1
- package/dist/migration/analyzer.d.ts +2 -1
- package/dist/migration/analyzer.js +44 -0
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/diff.cjs +76 -1
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.d.cts +3 -1
- package/dist/migration/diff.d.ts +3 -1
- package/dist/migration/diff.js +76 -1
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/generator.cjs +323 -46
- package/dist/migration/generator.cjs.map +1 -1
- package/dist/migration/generator.d.cts +60 -11
- package/dist/migration/generator.d.ts +60 -11
- package/dist/migration/generator.js +319 -47
- package/dist/migration/generator.js.map +1 -1
- package/dist/migration/index.cjs +433 -47
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +3 -2
- package/dist/migration/index.d.ts +3 -2
- package/dist/migration/index.js +432 -48
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.d.cts +3 -1
- package/dist/migration/snapshot.d.ts +3 -1
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/migration/utils/index.cjs +80 -0
- package/dist/migration/utils/index.cjs.map +1 -1
- package/dist/migration/utils/index.d.cts +39 -202
- package/dist/migration/utils/index.d.ts +39 -202
- package/dist/migration/utils/index.js +77 -1
- package/dist/migration/utils/index.js.map +1 -1
- package/dist/schema.cjs +200 -61
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +2 -85
- package/dist/schema.d.ts +2 -85
- package/dist/schema.js +186 -50
- package/dist/schema.js.map +1 -1
- package/dist/type-mapper-DrQmtznD.d.cts +208 -0
- package/dist/type-mapper-n231Fspm.d.ts +208 -0
- package/dist/{types-z1Dkjg8m.d.ts → types-Ds3NQvny.d.ts} +33 -2
- package/dist/{types-BbTgmg6H.d.cts → types-YoBjsa-A.d.cts} +33 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import * as fs3 from 'fs';
|
|
3
3
|
import * as path5 from 'path';
|
|
4
|
+
import { randomBytes } from 'crypto';
|
|
4
5
|
import chalk from 'chalk';
|
|
5
6
|
import ora from 'ora';
|
|
6
7
|
|
|
@@ -366,46 +367,6 @@ var inputImageFileSchema = {
|
|
|
366
367
|
var omitImageFilesSchema = {
|
|
367
368
|
imageFiles: true
|
|
368
369
|
};
|
|
369
|
-
function textField(options) {
|
|
370
|
-
let schema = z.string();
|
|
371
|
-
if (options?.min !== void 0) schema = schema.min(options.min);
|
|
372
|
-
if (options?.max !== void 0) schema = schema.max(options.max);
|
|
373
|
-
if (options?.pattern !== void 0) schema = schema.regex(options.pattern);
|
|
374
|
-
return schema;
|
|
375
|
-
}
|
|
376
|
-
function emailField() {
|
|
377
|
-
return z.string().email();
|
|
378
|
-
}
|
|
379
|
-
function urlField() {
|
|
380
|
-
return z.string().url();
|
|
381
|
-
}
|
|
382
|
-
function numberField(options) {
|
|
383
|
-
let schema = z.number();
|
|
384
|
-
if (options?.min !== void 0) schema = schema.min(options.min);
|
|
385
|
-
if (options?.max !== void 0) schema = schema.max(options.max);
|
|
386
|
-
return schema;
|
|
387
|
-
}
|
|
388
|
-
function boolField() {
|
|
389
|
-
return z.boolean();
|
|
390
|
-
}
|
|
391
|
-
function dateField() {
|
|
392
|
-
return z.date();
|
|
393
|
-
}
|
|
394
|
-
function selectField(values) {
|
|
395
|
-
return z.enum(values);
|
|
396
|
-
}
|
|
397
|
-
function jsonField(schema) {
|
|
398
|
-
return schema ?? z.record(z.any());
|
|
399
|
-
}
|
|
400
|
-
function fileField() {
|
|
401
|
-
return z.instanceof(File);
|
|
402
|
-
}
|
|
403
|
-
function filesField(options) {
|
|
404
|
-
let schema = z.array(z.instanceof(File));
|
|
405
|
-
if (options?.min !== void 0) schema = schema.min(options.min);
|
|
406
|
-
if (options?.max !== void 0) schema = schema.max(options.max);
|
|
407
|
-
return schema;
|
|
408
|
-
}
|
|
409
370
|
var RELATION_METADATA_KEY = "__pocketbase_relation__";
|
|
410
371
|
function RelationField(config) {
|
|
411
372
|
const metadata = {
|
|
@@ -449,15 +410,6 @@ function extractRelationMetadata(description) {
|
|
|
449
410
|
}
|
|
450
411
|
return null;
|
|
451
412
|
}
|
|
452
|
-
function editorField() {
|
|
453
|
-
return z.string();
|
|
454
|
-
}
|
|
455
|
-
function geoPointField() {
|
|
456
|
-
return z.object({
|
|
457
|
-
lon: z.number(),
|
|
458
|
-
lat: z.number()
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
413
|
function withPermissions(schema, config) {
|
|
462
414
|
const metadata = {
|
|
463
415
|
permissions: config
|
|
@@ -497,6 +449,191 @@ function defineCollection(config) {
|
|
|
497
449
|
}
|
|
498
450
|
return schema.describe(JSON.stringify(metadata));
|
|
499
451
|
}
|
|
452
|
+
var FIELD_METADATA_KEY = "__pocketbase_field__";
|
|
453
|
+
function extractFieldMetadata(description) {
|
|
454
|
+
if (!description) return null;
|
|
455
|
+
try {
|
|
456
|
+
const parsed = JSON.parse(description);
|
|
457
|
+
if (parsed[FIELD_METADATA_KEY]) {
|
|
458
|
+
return parsed[FIELD_METADATA_KEY];
|
|
459
|
+
}
|
|
460
|
+
} catch {
|
|
461
|
+
}
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
function BoolField() {
|
|
465
|
+
const metadata = {
|
|
466
|
+
[FIELD_METADATA_KEY]: {
|
|
467
|
+
type: "bool"
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
return z.boolean().describe(JSON.stringify(metadata));
|
|
471
|
+
}
|
|
472
|
+
function NumberField(options) {
|
|
473
|
+
if (options?.min !== void 0 && options?.max !== void 0) {
|
|
474
|
+
if (options.min > options.max) {
|
|
475
|
+
throw new Error("NumberField: min cannot be greater than max");
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
let schema = z.number();
|
|
479
|
+
if (options?.min !== void 0) {
|
|
480
|
+
schema = schema.min(options.min);
|
|
481
|
+
}
|
|
482
|
+
if (options?.max !== void 0) {
|
|
483
|
+
schema = schema.max(options.max);
|
|
484
|
+
}
|
|
485
|
+
const metadata = {
|
|
486
|
+
[FIELD_METADATA_KEY]: {
|
|
487
|
+
type: "number",
|
|
488
|
+
options: options || {}
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
return schema.describe(JSON.stringify(metadata));
|
|
492
|
+
}
|
|
493
|
+
function TextField(options) {
|
|
494
|
+
if (options?.min !== void 0 && options?.max !== void 0) {
|
|
495
|
+
if (options.min > options.max) {
|
|
496
|
+
throw new Error("TextField: min cannot be greater than max");
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
let schema = z.string();
|
|
500
|
+
if (options?.min !== void 0) {
|
|
501
|
+
schema = schema.min(options.min);
|
|
502
|
+
}
|
|
503
|
+
if (options?.max !== void 0) {
|
|
504
|
+
schema = schema.max(options.max);
|
|
505
|
+
}
|
|
506
|
+
if (options?.pattern !== void 0) {
|
|
507
|
+
const pattern = options.pattern instanceof RegExp ? options.pattern : new RegExp(options.pattern);
|
|
508
|
+
schema = schema.regex(pattern);
|
|
509
|
+
}
|
|
510
|
+
const metadata = {
|
|
511
|
+
[FIELD_METADATA_KEY]: {
|
|
512
|
+
type: "text",
|
|
513
|
+
options: options || {}
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
return schema.describe(JSON.stringify(metadata));
|
|
517
|
+
}
|
|
518
|
+
function EmailField() {
|
|
519
|
+
const metadata = {
|
|
520
|
+
[FIELD_METADATA_KEY]: {
|
|
521
|
+
type: "email"
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
return z.string().email().describe(JSON.stringify(metadata));
|
|
525
|
+
}
|
|
526
|
+
function URLField() {
|
|
527
|
+
const metadata = {
|
|
528
|
+
[FIELD_METADATA_KEY]: {
|
|
529
|
+
type: "url"
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
return z.string().url().describe(JSON.stringify(metadata));
|
|
533
|
+
}
|
|
534
|
+
function EditorField() {
|
|
535
|
+
const metadata = {
|
|
536
|
+
[FIELD_METADATA_KEY]: {
|
|
537
|
+
type: "editor"
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
return z.string().describe(JSON.stringify(metadata));
|
|
541
|
+
}
|
|
542
|
+
function DateField(options) {
|
|
543
|
+
if (options?.min !== void 0 && options?.max !== void 0) {
|
|
544
|
+
const minDate = typeof options.min === "string" ? new Date(options.min) : options.min;
|
|
545
|
+
const maxDate = typeof options.max === "string" ? new Date(options.max) : options.max;
|
|
546
|
+
if (minDate > maxDate) {
|
|
547
|
+
throw new Error("DateField: min cannot be greater than max");
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const schema = z.string();
|
|
551
|
+
const metadata = {
|
|
552
|
+
[FIELD_METADATA_KEY]: {
|
|
553
|
+
type: "date",
|
|
554
|
+
options: options || {}
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
return schema.describe(JSON.stringify(metadata));
|
|
558
|
+
}
|
|
559
|
+
function AutodateField(options) {
|
|
560
|
+
const schema = z.string();
|
|
561
|
+
const metadata = {
|
|
562
|
+
[FIELD_METADATA_KEY]: {
|
|
563
|
+
type: "autodate",
|
|
564
|
+
options: options || {}
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
return schema.describe(JSON.stringify(metadata));
|
|
568
|
+
}
|
|
569
|
+
function SelectField(values, options) {
|
|
570
|
+
const enumSchema = z.enum(values);
|
|
571
|
+
const metadata = {
|
|
572
|
+
[FIELD_METADATA_KEY]: {
|
|
573
|
+
type: "select",
|
|
574
|
+
options: {
|
|
575
|
+
values,
|
|
576
|
+
maxSelect: options?.maxSelect ?? 1
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
if (options?.maxSelect && options.maxSelect > 1) {
|
|
581
|
+
return z.array(enumSchema).describe(JSON.stringify(metadata));
|
|
582
|
+
}
|
|
583
|
+
return enumSchema.describe(JSON.stringify(metadata));
|
|
584
|
+
}
|
|
585
|
+
function FileField(options) {
|
|
586
|
+
const schema = z.instanceof(File);
|
|
587
|
+
const metadata = {
|
|
588
|
+
[FIELD_METADATA_KEY]: {
|
|
589
|
+
type: "file",
|
|
590
|
+
options: options || {}
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
return schema.describe(JSON.stringify(metadata));
|
|
594
|
+
}
|
|
595
|
+
function FilesField(options) {
|
|
596
|
+
if (options?.minSelect !== void 0 && options?.maxSelect !== void 0) {
|
|
597
|
+
if (options.minSelect > options.maxSelect) {
|
|
598
|
+
throw new Error("FilesField: minSelect cannot be greater than maxSelect");
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
let schema = z.array(z.instanceof(File));
|
|
602
|
+
if (options?.minSelect !== void 0) {
|
|
603
|
+
schema = schema.min(options.minSelect);
|
|
604
|
+
}
|
|
605
|
+
if (options?.maxSelect !== void 0) {
|
|
606
|
+
schema = schema.max(options.maxSelect);
|
|
607
|
+
}
|
|
608
|
+
const metadata = {
|
|
609
|
+
[FIELD_METADATA_KEY]: {
|
|
610
|
+
type: "file",
|
|
611
|
+
options: options || {}
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
return schema.describe(JSON.stringify(metadata));
|
|
615
|
+
}
|
|
616
|
+
function JSONField(schema) {
|
|
617
|
+
const baseSchema2 = schema ?? z.record(z.string(), z.any());
|
|
618
|
+
const metadata = {
|
|
619
|
+
[FIELD_METADATA_KEY]: {
|
|
620
|
+
type: "json"
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
return baseSchema2.describe(JSON.stringify(metadata));
|
|
624
|
+
}
|
|
625
|
+
function GeoPointField() {
|
|
626
|
+
const schema = z.object({
|
|
627
|
+
lon: z.number(),
|
|
628
|
+
lat: z.number()
|
|
629
|
+
});
|
|
630
|
+
const metadata = {
|
|
631
|
+
[FIELD_METADATA_KEY]: {
|
|
632
|
+
type: "geoPoint"
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
return schema.describe(JSON.stringify(metadata));
|
|
636
|
+
}
|
|
500
637
|
|
|
501
638
|
// src/utils/permission-templates.ts
|
|
502
639
|
var PermissionTemplates = {
|
|
@@ -2117,6 +2254,38 @@ function isAuthCollection(fields) {
|
|
|
2117
2254
|
return hasEmail && hasPassword;
|
|
2118
2255
|
}
|
|
2119
2256
|
function buildFieldDefinition(fieldName, zodType) {
|
|
2257
|
+
const fieldMetadata = extractFieldMetadata(zodType.description);
|
|
2258
|
+
if (fieldMetadata) {
|
|
2259
|
+
let required2;
|
|
2260
|
+
if (fieldMetadata.type === "number") {
|
|
2261
|
+
if (fieldMetadata.options?.required !== void 0) {
|
|
2262
|
+
required2 = fieldMetadata.options.required;
|
|
2263
|
+
} else {
|
|
2264
|
+
required2 = false;
|
|
2265
|
+
}
|
|
2266
|
+
} else {
|
|
2267
|
+
required2 = isFieldRequired(zodType);
|
|
2268
|
+
}
|
|
2269
|
+
const { required: _required, ...options2 } = fieldMetadata.options || {};
|
|
2270
|
+
const fieldDef2 = {
|
|
2271
|
+
name: fieldName,
|
|
2272
|
+
type: fieldMetadata.type,
|
|
2273
|
+
required: required2,
|
|
2274
|
+
options: Object.keys(options2).length > 0 ? options2 : void 0
|
|
2275
|
+
};
|
|
2276
|
+
if (fieldMetadata.type === "relation") {
|
|
2277
|
+
const relationMetadata2 = extractRelationMetadata(zodType.description);
|
|
2278
|
+
if (relationMetadata2) {
|
|
2279
|
+
fieldDef2.relation = {
|
|
2280
|
+
collection: relationMetadata2.collection,
|
|
2281
|
+
maxSelect: relationMetadata2.maxSelect,
|
|
2282
|
+
minSelect: relationMetadata2.minSelect,
|
|
2283
|
+
cascadeDelete: relationMetadata2.cascadeDelete
|
|
2284
|
+
};
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
return fieldDef2;
|
|
2288
|
+
}
|
|
2120
2289
|
const fieldType = mapZodTypeToPocketBase(zodType, fieldName);
|
|
2121
2290
|
const required = isFieldRequired(zodType);
|
|
2122
2291
|
const options = extractFieldOptions(zodType);
|
|
@@ -3098,6 +3267,65 @@ var SnapshotManager = class {
|
|
|
3098
3267
|
return validateSnapshot(snapshot);
|
|
3099
3268
|
}
|
|
3100
3269
|
};
|
|
3270
|
+
function generateCollectionId() {
|
|
3271
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
3272
|
+
const idLength = 15;
|
|
3273
|
+
const bytes = randomBytes(idLength);
|
|
3274
|
+
let id = "pb_";
|
|
3275
|
+
for (let i = 0; i < idLength; i++) {
|
|
3276
|
+
const index = bytes[i] % chars.length;
|
|
3277
|
+
id += chars[index];
|
|
3278
|
+
}
|
|
3279
|
+
return id;
|
|
3280
|
+
}
|
|
3281
|
+
var CollectionIdRegistry = class {
|
|
3282
|
+
ids;
|
|
3283
|
+
constructor() {
|
|
3284
|
+
this.ids = /* @__PURE__ */ new Set();
|
|
3285
|
+
}
|
|
3286
|
+
/**
|
|
3287
|
+
* Generates a unique collection ID for a given collection name
|
|
3288
|
+
* Special case: Returns constant "_pb_users_auth_" for users collection
|
|
3289
|
+
* Retries up to 10 times if collision occurs (extremely rare)
|
|
3290
|
+
*
|
|
3291
|
+
* @param collectionName - The name of the collection
|
|
3292
|
+
* @returns A unique collection ID
|
|
3293
|
+
* @throws Error if unable to generate unique ID after max attempts
|
|
3294
|
+
*/
|
|
3295
|
+
generate(collectionName) {
|
|
3296
|
+
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
3297
|
+
const usersId = "_pb_users_auth_";
|
|
3298
|
+
this.register(usersId);
|
|
3299
|
+
return usersId;
|
|
3300
|
+
}
|
|
3301
|
+
const maxAttempts = 10;
|
|
3302
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
3303
|
+
const id = generateCollectionId();
|
|
3304
|
+
if (!this.has(id)) {
|
|
3305
|
+
this.register(id);
|
|
3306
|
+
return id;
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
throw new Error("Failed to generate unique collection ID after maximum attempts");
|
|
3310
|
+
}
|
|
3311
|
+
/**
|
|
3312
|
+
* Checks if an ID has already been registered
|
|
3313
|
+
*
|
|
3314
|
+
* @param id - The collection ID to check
|
|
3315
|
+
* @returns True if the ID exists in the registry
|
|
3316
|
+
*/
|
|
3317
|
+
has(id) {
|
|
3318
|
+
return this.ids.has(id);
|
|
3319
|
+
}
|
|
3320
|
+
/**
|
|
3321
|
+
* Registers a collection ID in the registry
|
|
3322
|
+
*
|
|
3323
|
+
* @param id - The collection ID to register
|
|
3324
|
+
*/
|
|
3325
|
+
register(id) {
|
|
3326
|
+
this.ids.add(id);
|
|
3327
|
+
}
|
|
3328
|
+
};
|
|
3101
3329
|
|
|
3102
3330
|
// src/migration/diff.ts
|
|
3103
3331
|
var DEFAULT_CONFIG3 = {
|
|
@@ -3440,6 +3668,18 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
3440
3668
|
const filteredCollectionsToDelete = collectionsToDelete.filter(
|
|
3441
3669
|
(collection) => !isSystemCollection(collection.name, config)
|
|
3442
3670
|
);
|
|
3671
|
+
const registry = new CollectionIdRegistry();
|
|
3672
|
+
const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
|
|
3673
|
+
if (collection.id) {
|
|
3674
|
+
registry.register(collection.id);
|
|
3675
|
+
return collection;
|
|
3676
|
+
}
|
|
3677
|
+
const id = registry.generate(collection.name);
|
|
3678
|
+
return {
|
|
3679
|
+
...collection,
|
|
3680
|
+
id
|
|
3681
|
+
};
|
|
3682
|
+
});
|
|
3443
3683
|
const collectionsToModify = [];
|
|
3444
3684
|
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
3445
3685
|
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
@@ -3449,7 +3689,7 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
3449
3689
|
}
|
|
3450
3690
|
}
|
|
3451
3691
|
return {
|
|
3452
|
-
collectionsToCreate:
|
|
3692
|
+
collectionsToCreate: collectionsWithIds,
|
|
3453
3693
|
collectionsToDelete: filteredCollectionsToDelete,
|
|
3454
3694
|
collectionsToModify
|
|
3455
3695
|
};
|
|
@@ -3685,6 +3925,49 @@ function generateTimestamp(config) {
|
|
|
3685
3925
|
}
|
|
3686
3926
|
return Math.floor(Date.now() / 1e3).toString();
|
|
3687
3927
|
}
|
|
3928
|
+
function splitDiffByCollection(diff, baseTimestamp) {
|
|
3929
|
+
const operations = [];
|
|
3930
|
+
let currentTimestamp = parseInt(baseTimestamp, 10);
|
|
3931
|
+
for (const collection of diff.collectionsToCreate) {
|
|
3932
|
+
operations.push({
|
|
3933
|
+
type: "create",
|
|
3934
|
+
collection,
|
|
3935
|
+
timestamp: currentTimestamp.toString()
|
|
3936
|
+
});
|
|
3937
|
+
currentTimestamp += 1;
|
|
3938
|
+
}
|
|
3939
|
+
for (const modification of diff.collectionsToModify) {
|
|
3940
|
+
operations.push({
|
|
3941
|
+
type: "modify",
|
|
3942
|
+
collection: modification.collection,
|
|
3943
|
+
modifications: modification,
|
|
3944
|
+
timestamp: currentTimestamp.toString()
|
|
3945
|
+
});
|
|
3946
|
+
currentTimestamp += 1;
|
|
3947
|
+
}
|
|
3948
|
+
for (const collection of diff.collectionsToDelete) {
|
|
3949
|
+
operations.push({
|
|
3950
|
+
type: "delete",
|
|
3951
|
+
collection: collection.name || collection,
|
|
3952
|
+
// Handle both object and string
|
|
3953
|
+
timestamp: currentTimestamp.toString()
|
|
3954
|
+
});
|
|
3955
|
+
currentTimestamp += 1;
|
|
3956
|
+
}
|
|
3957
|
+
return operations;
|
|
3958
|
+
}
|
|
3959
|
+
function generateCollectionMigrationFilename(operation) {
|
|
3960
|
+
const timestamp = operation.timestamp;
|
|
3961
|
+
const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
|
|
3962
|
+
let collectionName;
|
|
3963
|
+
if (typeof operation.collection === "string") {
|
|
3964
|
+
collectionName = operation.collection;
|
|
3965
|
+
} else {
|
|
3966
|
+
collectionName = operation.collection.name;
|
|
3967
|
+
}
|
|
3968
|
+
const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
|
|
3969
|
+
return `${timestamp}_${operationType}_${sanitizedName}.js`;
|
|
3970
|
+
}
|
|
3688
3971
|
function generateMigrationDescription(diff) {
|
|
3689
3972
|
const parts = [];
|
|
3690
3973
|
if (diff.collectionsToCreate.length > 0) {
|
|
@@ -3792,14 +4075,13 @@ function formatValue(value) {
|
|
|
3792
4075
|
return "null";
|
|
3793
4076
|
}
|
|
3794
4077
|
if (typeof value === "string") {
|
|
3795
|
-
return
|
|
4078
|
+
return JSON.stringify(value);
|
|
3796
4079
|
}
|
|
3797
4080
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
3798
4081
|
return String(value);
|
|
3799
4082
|
}
|
|
3800
4083
|
if (Array.isArray(value)) {
|
|
3801
|
-
|
|
3802
|
-
return `[${items}]`;
|
|
4084
|
+
return JSON.stringify(value).replace(/","/g, '", "');
|
|
3803
4085
|
}
|
|
3804
4086
|
if (typeof value === "object") {
|
|
3805
4087
|
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
@@ -3807,7 +4089,7 @@ function formatValue(value) {
|
|
|
3807
4089
|
}
|
|
3808
4090
|
return String(value);
|
|
3809
4091
|
}
|
|
3810
|
-
function generateFieldDefinitionObject(field) {
|
|
4092
|
+
function generateFieldDefinitionObject(field, collectionIdMap) {
|
|
3811
4093
|
const parts = [];
|
|
3812
4094
|
parts.push(` name: "${field.name}"`);
|
|
3813
4095
|
parts.push(` type: "${field.type}"`);
|
|
@@ -3815,34 +4097,47 @@ function generateFieldDefinitionObject(field) {
|
|
|
3815
4097
|
if (field.unique !== void 0) {
|
|
3816
4098
|
parts.push(` unique: ${field.unique}`);
|
|
3817
4099
|
}
|
|
4100
|
+
if (field.type === "select") {
|
|
4101
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
4102
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4103
|
+
const values = field.options?.values ?? [];
|
|
4104
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
4105
|
+
}
|
|
3818
4106
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
3819
4107
|
for (const [key, value] of Object.entries(field.options)) {
|
|
4108
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
4109
|
+
continue;
|
|
4110
|
+
}
|
|
3820
4111
|
parts.push(` ${key}: ${formatValue(value)}`);
|
|
3821
4112
|
}
|
|
3822
4113
|
}
|
|
3823
4114
|
if (field.relation) {
|
|
3824
4115
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
}
|
|
3833
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
3834
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
4116
|
+
let collectionIdValue;
|
|
4117
|
+
if (isUsersCollection) {
|
|
4118
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
4119
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
4120
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
4121
|
+
} else {
|
|
4122
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3835
4123
|
}
|
|
4124
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
4125
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
4126
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4127
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
4128
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
4129
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
4130
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
3836
4131
|
}
|
|
3837
4132
|
return ` {
|
|
3838
4133
|
${parts.join(",\n")},
|
|
3839
4134
|
}`;
|
|
3840
4135
|
}
|
|
3841
|
-
function generateFieldsArray(fields) {
|
|
4136
|
+
function generateFieldsArray(fields, collectionIdMap) {
|
|
3842
4137
|
if (fields.length === 0) {
|
|
3843
4138
|
return "[]";
|
|
3844
4139
|
}
|
|
3845
|
-
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
|
|
4140
|
+
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
|
|
3846
4141
|
return `[
|
|
3847
4142
|
${fieldObjects.join(",\n")},
|
|
3848
4143
|
]`;
|
|
@@ -3901,7 +4196,7 @@ function generateIndexesArray(indexes) {
|
|
|
3901
4196
|
if (!indexes || indexes.length === 0) {
|
|
3902
4197
|
return "[]";
|
|
3903
4198
|
}
|
|
3904
|
-
const indexStrings = indexes.map((idx) =>
|
|
4199
|
+
const indexStrings = indexes.map((idx) => JSON.stringify(idx));
|
|
3905
4200
|
return `[
|
|
3906
4201
|
${indexStrings.join(",\n ")},
|
|
3907
4202
|
]`;
|
|
@@ -3955,7 +4250,7 @@ function getSystemFields() {
|
|
|
3955
4250
|
}
|
|
3956
4251
|
];
|
|
3957
4252
|
}
|
|
3958
|
-
function generateCollectionCreation(collection, varName = "collection", isLast = false) {
|
|
4253
|
+
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
3959
4254
|
const lines = [];
|
|
3960
4255
|
lines.push(` const ${varName} = new Collection({`);
|
|
3961
4256
|
lines.push(` name: "${collection.name}",`);
|
|
@@ -3969,7 +4264,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3969
4264
|
}
|
|
3970
4265
|
const systemFields = getSystemFields();
|
|
3971
4266
|
const allFields = [...systemFields, ...collection.fields];
|
|
3972
|
-
lines.push(` fields: ${generateFieldsArray(allFields)},`);
|
|
4267
|
+
lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
3973
4268
|
lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
|
|
3974
4269
|
lines.push(` });`);
|
|
3975
4270
|
lines.push(``);
|
|
@@ -3991,42 +4286,59 @@ function getFieldConstructorName(fieldType) {
|
|
|
3991
4286
|
};
|
|
3992
4287
|
return constructorMap[fieldType] || "TextField";
|
|
3993
4288
|
}
|
|
3994
|
-
function generateFieldConstructorOptions(field) {
|
|
4289
|
+
function generateFieldConstructorOptions(field, collectionIdMap) {
|
|
3995
4290
|
const parts = [];
|
|
3996
4291
|
parts.push(` name: "${field.name}"`);
|
|
3997
4292
|
parts.push(` required: ${field.required}`);
|
|
3998
4293
|
if (field.unique !== void 0) {
|
|
3999
4294
|
parts.push(` unique: ${field.unique}`);
|
|
4000
4295
|
}
|
|
4296
|
+
if (field.type === "select") {
|
|
4297
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
4298
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4299
|
+
const values = field.options?.values ?? [];
|
|
4300
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
4301
|
+
}
|
|
4001
4302
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
4002
4303
|
for (const [key, value] of Object.entries(field.options)) {
|
|
4003
|
-
|
|
4304
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
4305
|
+
continue;
|
|
4306
|
+
}
|
|
4307
|
+
if (field.type === "number" && key === "noDecimal") {
|
|
4308
|
+
parts.push(` onlyInt: ${formatValue(value)}`);
|
|
4309
|
+
} else {
|
|
4310
|
+
parts.push(` ${key}: ${formatValue(value)}`);
|
|
4311
|
+
}
|
|
4004
4312
|
}
|
|
4005
4313
|
}
|
|
4006
4314
|
if (field.relation && field.type === "relation") {
|
|
4007
4315
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
}
|
|
4016
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
4017
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
4316
|
+
let collectionIdValue;
|
|
4317
|
+
if (isUsersCollection) {
|
|
4318
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
4319
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
4320
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
4321
|
+
} else {
|
|
4322
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
4018
4323
|
}
|
|
4324
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
4325
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
4326
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4327
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
4328
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
4329
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
4330
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
4019
4331
|
}
|
|
4020
4332
|
return parts.join(",\n");
|
|
4021
4333
|
}
|
|
4022
|
-
function generateFieldAddition(collectionName, field, varName, isLast = false) {
|
|
4334
|
+
function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
|
|
4023
4335
|
const lines = [];
|
|
4024
4336
|
const constructorName = getFieldConstructorName(field.type);
|
|
4025
4337
|
const collectionVar = varName || `collection_${collectionName}_${field.name}`;
|
|
4026
4338
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4027
4339
|
lines.push(``);
|
|
4028
4340
|
lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
|
|
4029
|
-
lines.push(generateFieldConstructorOptions(field));
|
|
4341
|
+
lines.push(generateFieldConstructorOptions(field, collectionIdMap));
|
|
4030
4342
|
lines.push(` }));`);
|
|
4031
4343
|
lines.push(``);
|
|
4032
4344
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
@@ -4076,7 +4388,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
|
|
|
4076
4388
|
const lines = [];
|
|
4077
4389
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
4078
4390
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4079
|
-
lines.push(` ${collectionVar}.indexes.push(
|
|
4391
|
+
lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
|
|
4080
4392
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4081
4393
|
return lines.join("\n");
|
|
4082
4394
|
}
|
|
@@ -4085,7 +4397,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
|
|
|
4085
4397
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
4086
4398
|
const indexVar = `${collectionVar}_indexToRemove`;
|
|
4087
4399
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4088
|
-
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx ===
|
|
4400
|
+
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
|
|
4089
4401
|
lines.push(` if (${indexVar} !== -1) {`);
|
|
4090
4402
|
lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
|
|
4091
4403
|
lines.push(` }`);
|
|
@@ -4114,16 +4426,179 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
|
|
|
4114
4426
|
lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
|
|
4115
4427
|
return lines.join("\n");
|
|
4116
4428
|
}
|
|
4429
|
+
function generateOperationUpMigration(operation, collectionIdMap) {
|
|
4430
|
+
const lines = [];
|
|
4431
|
+
if (operation.type === "create") {
|
|
4432
|
+
const collection = operation.collection;
|
|
4433
|
+
const varName = `collection_${collection.name}`;
|
|
4434
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
4435
|
+
} else if (operation.type === "modify") {
|
|
4436
|
+
const modification = operation.modifications;
|
|
4437
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4438
|
+
let operationCount = 0;
|
|
4439
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
4440
|
+
for (const field of modification.fieldsToAdd) {
|
|
4441
|
+
operationCount++;
|
|
4442
|
+
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
4443
|
+
const isLast = operationCount === totalOperations;
|
|
4444
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
4445
|
+
if (!isLast) lines.push("");
|
|
4446
|
+
}
|
|
4447
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
4448
|
+
operationCount++;
|
|
4449
|
+
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
4450
|
+
const isLast = operationCount === totalOperations;
|
|
4451
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
|
|
4452
|
+
if (!isLast) lines.push("");
|
|
4453
|
+
}
|
|
4454
|
+
for (const field of modification.fieldsToRemove) {
|
|
4455
|
+
operationCount++;
|
|
4456
|
+
const varName = `collection_${collectionName}_remove_${field.name}`;
|
|
4457
|
+
const isLast = operationCount === totalOperations;
|
|
4458
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
4459
|
+
if (!isLast) lines.push("");
|
|
4460
|
+
}
|
|
4461
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
4462
|
+
operationCount++;
|
|
4463
|
+
const index = modification.indexesToAdd[i];
|
|
4464
|
+
const varName = `collection_${collectionName}_addidx_${i}`;
|
|
4465
|
+
const isLast = operationCount === totalOperations;
|
|
4466
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
4467
|
+
if (!isLast) lines.push("");
|
|
4468
|
+
}
|
|
4469
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
4470
|
+
operationCount++;
|
|
4471
|
+
const index = modification.indexesToRemove[i];
|
|
4472
|
+
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
4473
|
+
const isLast = operationCount === totalOperations;
|
|
4474
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
4475
|
+
if (!isLast) lines.push("");
|
|
4476
|
+
}
|
|
4477
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4478
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
4479
|
+
operationCount++;
|
|
4480
|
+
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
4481
|
+
const isLast = operationCount === totalOperations;
|
|
4482
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
|
|
4483
|
+
if (!isLast) lines.push("");
|
|
4484
|
+
}
|
|
4485
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
4486
|
+
for (const rule of modification.rulesToUpdate) {
|
|
4487
|
+
operationCount++;
|
|
4488
|
+
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
4489
|
+
const isLast = operationCount === totalOperations;
|
|
4490
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
|
|
4491
|
+
if (!isLast) lines.push("");
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4494
|
+
} else if (operation.type === "delete") {
|
|
4495
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
4496
|
+
const varName = `collection_${collectionName}`;
|
|
4497
|
+
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
4498
|
+
}
|
|
4499
|
+
return lines.join("\n");
|
|
4500
|
+
}
|
|
4501
|
+
function generateOperationDownMigration(operation, collectionIdMap) {
|
|
4502
|
+
const lines = [];
|
|
4503
|
+
if (operation.type === "create") {
|
|
4504
|
+
const collection = operation.collection;
|
|
4505
|
+
const varName = `collection_${collection.name}`;
|
|
4506
|
+
lines.push(generateCollectionDeletion(collection.name, varName, true));
|
|
4507
|
+
} else if (operation.type === "modify") {
|
|
4508
|
+
const modification = operation.modifications;
|
|
4509
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4510
|
+
let operationCount = 0;
|
|
4511
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
4512
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4513
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
4514
|
+
operationCount++;
|
|
4515
|
+
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
4516
|
+
const isLast = operationCount === totalOperations;
|
|
4517
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
|
|
4518
|
+
if (!isLast) lines.push("");
|
|
4519
|
+
}
|
|
4520
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
4521
|
+
for (const rule of modification.rulesToUpdate) {
|
|
4522
|
+
operationCount++;
|
|
4523
|
+
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
4524
|
+
const isLast = operationCount === totalOperations;
|
|
4525
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
|
|
4526
|
+
if (!isLast) lines.push("");
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
4530
|
+
operationCount++;
|
|
4531
|
+
const index = modification.indexesToRemove[i];
|
|
4532
|
+
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
4533
|
+
const isLast = operationCount === totalOperations;
|
|
4534
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
4535
|
+
if (!isLast) lines.push("");
|
|
4536
|
+
}
|
|
4537
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
4538
|
+
operationCount++;
|
|
4539
|
+
const index = modification.indexesToAdd[i];
|
|
4540
|
+
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
4541
|
+
const isLast = operationCount === totalOperations;
|
|
4542
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
4543
|
+
if (!isLast) lines.push("");
|
|
4544
|
+
}
|
|
4545
|
+
for (const field of modification.fieldsToRemove) {
|
|
4546
|
+
operationCount++;
|
|
4547
|
+
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
4548
|
+
const isLast = operationCount === totalOperations;
|
|
4549
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
4550
|
+
if (!isLast) lines.push("");
|
|
4551
|
+
}
|
|
4552
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
4553
|
+
operationCount++;
|
|
4554
|
+
const reverseChanges = fieldMod.changes.map((change) => ({
|
|
4555
|
+
property: change.property,
|
|
4556
|
+
oldValue: change.newValue,
|
|
4557
|
+
newValue: change.oldValue
|
|
4558
|
+
}));
|
|
4559
|
+
const reverseMod = {
|
|
4560
|
+
fieldName: fieldMod.fieldName,
|
|
4561
|
+
currentDefinition: fieldMod.newDefinition,
|
|
4562
|
+
newDefinition: fieldMod.currentDefinition,
|
|
4563
|
+
changes: reverseChanges
|
|
4564
|
+
};
|
|
4565
|
+
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
4566
|
+
const isLast = operationCount === totalOperations;
|
|
4567
|
+
lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
|
|
4568
|
+
if (!isLast) lines.push("");
|
|
4569
|
+
}
|
|
4570
|
+
for (const field of modification.fieldsToAdd) {
|
|
4571
|
+
operationCount++;
|
|
4572
|
+
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
4573
|
+
const isLast = operationCount === totalOperations;
|
|
4574
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
4575
|
+
if (!isLast) lines.push("");
|
|
4576
|
+
}
|
|
4577
|
+
} else if (operation.type === "delete") {
|
|
4578
|
+
const collection = operation.collection;
|
|
4579
|
+
if (typeof collection !== "string") {
|
|
4580
|
+
const varName = `collection_${collection.name}`;
|
|
4581
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
return lines.join("\n");
|
|
4585
|
+
}
|
|
4117
4586
|
function generateUpMigration(diff) {
|
|
4118
4587
|
const lines = [];
|
|
4119
4588
|
lines.push(` // UP MIGRATION`);
|
|
4120
4589
|
lines.push(``);
|
|
4590
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4591
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4592
|
+
if (collection.id) {
|
|
4593
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4594
|
+
}
|
|
4595
|
+
}
|
|
4121
4596
|
if (diff.collectionsToCreate.length > 0) {
|
|
4122
4597
|
lines.push(` // Create new collections`);
|
|
4123
4598
|
for (let i = 0; i < diff.collectionsToCreate.length; i++) {
|
|
4124
4599
|
const collection = diff.collectionsToCreate[i];
|
|
4125
4600
|
const varName = `collection_${collection.name}_create`;
|
|
4126
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
4601
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
4127
4602
|
lines.push(``);
|
|
4128
4603
|
}
|
|
4129
4604
|
}
|
|
@@ -4135,7 +4610,7 @@ function generateUpMigration(diff) {
|
|
|
4135
4610
|
lines.push(` // Add fields to ${collectionName}`);
|
|
4136
4611
|
for (const field of modification.fieldsToAdd) {
|
|
4137
4612
|
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
4138
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
4613
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
4139
4614
|
lines.push(``);
|
|
4140
4615
|
}
|
|
4141
4616
|
}
|
|
@@ -4226,12 +4701,23 @@ function generateDownMigration(diff) {
|
|
|
4226
4701
|
const lines = [];
|
|
4227
4702
|
lines.push(` // DOWN MIGRATION (ROLLBACK)`);
|
|
4228
4703
|
lines.push(``);
|
|
4704
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4705
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4706
|
+
if (collection.id) {
|
|
4707
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4710
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4711
|
+
if (collection.id) {
|
|
4712
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4229
4715
|
if (diff.collectionsToDelete.length > 0) {
|
|
4230
4716
|
lines.push(` // Recreate deleted collections`);
|
|
4231
4717
|
for (let i = 0; i < diff.collectionsToDelete.length; i++) {
|
|
4232
4718
|
const collection = diff.collectionsToDelete[i];
|
|
4233
4719
|
const varName = `collection_${collection.name}_recreate`;
|
|
4234
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
4720
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
4235
4721
|
lines.push(``);
|
|
4236
4722
|
}
|
|
4237
4723
|
}
|
|
@@ -4276,7 +4762,7 @@ function generateDownMigration(diff) {
|
|
|
4276
4762
|
lines.push(` // Restore fields to ${collectionName}`);
|
|
4277
4763
|
for (const field of modification.fieldsToRemove) {
|
|
4278
4764
|
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
4279
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
4765
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
4280
4766
|
lines.push(``);
|
|
4281
4767
|
}
|
|
4282
4768
|
}
|
|
@@ -4345,12 +4831,33 @@ function generate(diff, config) {
|
|
|
4345
4831
|
const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
|
|
4346
4832
|
try {
|
|
4347
4833
|
const migrationDir = resolveMigrationDir(normalizedConfig);
|
|
4348
|
-
const
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
const
|
|
4353
|
-
|
|
4834
|
+
const hasChanges4 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
|
|
4835
|
+
if (!hasChanges4) {
|
|
4836
|
+
return [];
|
|
4837
|
+
}
|
|
4838
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4839
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4840
|
+
if (collection.id) {
|
|
4841
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4842
|
+
}
|
|
4843
|
+
}
|
|
4844
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4845
|
+
if (collection.id) {
|
|
4846
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4847
|
+
}
|
|
4848
|
+
}
|
|
4849
|
+
const baseTimestamp = generateTimestamp(normalizedConfig);
|
|
4850
|
+
const operations = splitDiffByCollection(diff, baseTimestamp);
|
|
4851
|
+
const filePaths = [];
|
|
4852
|
+
for (const operation of operations) {
|
|
4853
|
+
const upCode = generateOperationUpMigration(operation, collectionIdMap);
|
|
4854
|
+
const downCode = generateOperationDownMigration(operation, collectionIdMap);
|
|
4855
|
+
const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
|
|
4856
|
+
const filename = generateCollectionMigrationFilename(operation);
|
|
4857
|
+
const filePath = writeMigrationFile(migrationDir, filename, content);
|
|
4858
|
+
filePaths.push(filePath);
|
|
4859
|
+
}
|
|
4860
|
+
return filePaths;
|
|
4354
4861
|
} catch (error) {
|
|
4355
4862
|
if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
|
|
4356
4863
|
throw error;
|
|
@@ -4368,7 +4875,8 @@ var MigrationGenerator = class {
|
|
|
4368
4875
|
this.config = mergeConfig4(config);
|
|
4369
4876
|
}
|
|
4370
4877
|
/**
|
|
4371
|
-
* Generates
|
|
4878
|
+
* Generates migration files from a schema diff
|
|
4879
|
+
* Returns array of file paths (one per collection operation)
|
|
4372
4880
|
*/
|
|
4373
4881
|
generate(diff) {
|
|
4374
4882
|
return generate(diff, this.config);
|
|
@@ -4972,15 +5480,25 @@ async function executeGenerate(options) {
|
|
|
4972
5480
|
process.exit(1);
|
|
4973
5481
|
}
|
|
4974
5482
|
logSection("\u{1F4DD} Generating Migration");
|
|
4975
|
-
const
|
|
5483
|
+
const migrationPaths = await withProgress(
|
|
4976
5484
|
"Creating migration file...",
|
|
4977
5485
|
() => Promise.resolve(generate(diff, migrationsDir))
|
|
4978
5486
|
);
|
|
4979
|
-
|
|
5487
|
+
if (migrationPaths.length === 0) {
|
|
5488
|
+
logWarning("No migration files were generated (no changes detected).");
|
|
5489
|
+
return;
|
|
5490
|
+
}
|
|
5491
|
+
if (migrationPaths.length === 1) {
|
|
5492
|
+
logSuccess(`Migration file created: ${path5.basename(migrationPaths[0])}`);
|
|
5493
|
+
} else {
|
|
5494
|
+
logSuccess(`Created ${migrationPaths.length} migration files`);
|
|
5495
|
+
}
|
|
4980
5496
|
logSection("\u2705 Next Steps");
|
|
4981
5497
|
console.log();
|
|
4982
|
-
console.log(" 1. Review the generated migration file:");
|
|
4983
|
-
|
|
5498
|
+
console.log(" 1. Review the generated migration file(s):");
|
|
5499
|
+
migrationPaths.forEach((migrationPath) => {
|
|
5500
|
+
console.log(` ${migrationPath}`);
|
|
5501
|
+
});
|
|
4984
5502
|
console.log();
|
|
4985
5503
|
console.log(" 2. Apply the migration by running PocketBase:");
|
|
4986
5504
|
console.log(" yarn pb");
|
|
@@ -5243,6 +5761,6 @@ async function executeStatus(options) {
|
|
|
5243
5761
|
}
|
|
5244
5762
|
}
|
|
5245
5763
|
|
|
5246
|
-
export { BaseMutator, CLIUsageError, ConfigurationError, DiffEngine, FIELD_TYPE_INFO, FileSystemError, MigrationError, MigrationGenerationError, MigrationGenerator, POCKETBASE_FIELD_TYPES, PermissionTemplates, RelationField, RelationsField, SchemaAnalyzer, SchemaParsingError, SnapshotError, SnapshotManager, StatusEnum, aggregateChanges, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps,
|
|
5764
|
+
export { AutodateField, BaseMutator, BoolField, CLIUsageError, ConfigurationError, DateField, DiffEngine, EditorField, EmailField, FIELD_METADATA_KEY, FIELD_TYPE_INFO, FileField, FileSystemError, FilesField, GeoPointField, JSONField, MigrationError, MigrationGenerationError, MigrationGenerator, NumberField, POCKETBASE_FIELD_TYPES, PermissionTemplates, RelationField, RelationsField, SchemaAnalyzer, SchemaParsingError, SelectField, SnapshotError, SnapshotManager, StatusEnum, TextField, URLField, aggregateChanges, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, createPermissions, defineCollection, detectDestructiveChanges, detectFieldChanges, discoverSchemaFiles, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldMetadata, extractFieldOptions, extractIndexes, extractRelationMetadata, extractSchemaDefinitions, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, formatChangeSummary, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, executeGenerate as generateMigration, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, executeStatus as getMigrationStatus, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, importSchemaModule, inputImageFileSchema, isArrayType, isAuthCollection, isEditorField, isFieldRequired, isFileFieldByName, isGeoPointType, isMultipleRelationField, isPermissionSchema, isRelationField, isSingleRelationField, isSystemCollection, isTemplateConfig, loadBaseMigration, loadConfig, loadSnapshot, loadSnapshotIfExists, loadSnapshotWithMigrations, logError, logInfo, logSection, logSuccess, logWarning, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergePermissions, mergeSnapshots, omitImageFilesSchema, parseSchemaFiles, pluralize, requiresForceFlag, resolveTargetCollection, resolveTemplate, saveSnapshot, selectSchemaForCollection, singularize, snapshotExists, toCollectionName, unwrapZodType, validatePermissionConfig, validateRuleExpression, validateSnapshot, withIndexes, withPermissions, withProgress, writeMigrationFile };
|
|
5247
5765
|
//# sourceMappingURL=index.js.map
|
|
5248
5766
|
//# sourceMappingURL=index.js.map
|