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.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var zod = require('zod');
|
|
4
4
|
var fs3 = require('fs');
|
|
5
5
|
var path5 = require('path');
|
|
6
|
+
var crypto = require('crypto');
|
|
6
7
|
var chalk = require('chalk');
|
|
7
8
|
var ora = require('ora');
|
|
8
9
|
|
|
@@ -393,46 +394,6 @@ var inputImageFileSchema = {
|
|
|
393
394
|
var omitImageFilesSchema = {
|
|
394
395
|
imageFiles: true
|
|
395
396
|
};
|
|
396
|
-
function textField(options) {
|
|
397
|
-
let schema = zod.z.string();
|
|
398
|
-
if (options?.min !== void 0) schema = schema.min(options.min);
|
|
399
|
-
if (options?.max !== void 0) schema = schema.max(options.max);
|
|
400
|
-
if (options?.pattern !== void 0) schema = schema.regex(options.pattern);
|
|
401
|
-
return schema;
|
|
402
|
-
}
|
|
403
|
-
function emailField() {
|
|
404
|
-
return zod.z.string().email();
|
|
405
|
-
}
|
|
406
|
-
function urlField() {
|
|
407
|
-
return zod.z.string().url();
|
|
408
|
-
}
|
|
409
|
-
function numberField(options) {
|
|
410
|
-
let schema = zod.z.number();
|
|
411
|
-
if (options?.min !== void 0) schema = schema.min(options.min);
|
|
412
|
-
if (options?.max !== void 0) schema = schema.max(options.max);
|
|
413
|
-
return schema;
|
|
414
|
-
}
|
|
415
|
-
function boolField() {
|
|
416
|
-
return zod.z.boolean();
|
|
417
|
-
}
|
|
418
|
-
function dateField() {
|
|
419
|
-
return zod.z.date();
|
|
420
|
-
}
|
|
421
|
-
function selectField(values) {
|
|
422
|
-
return zod.z.enum(values);
|
|
423
|
-
}
|
|
424
|
-
function jsonField(schema) {
|
|
425
|
-
return schema ?? zod.z.record(zod.z.any());
|
|
426
|
-
}
|
|
427
|
-
function fileField() {
|
|
428
|
-
return zod.z.instanceof(File);
|
|
429
|
-
}
|
|
430
|
-
function filesField(options) {
|
|
431
|
-
let schema = zod.z.array(zod.z.instanceof(File));
|
|
432
|
-
if (options?.min !== void 0) schema = schema.min(options.min);
|
|
433
|
-
if (options?.max !== void 0) schema = schema.max(options.max);
|
|
434
|
-
return schema;
|
|
435
|
-
}
|
|
436
397
|
var RELATION_METADATA_KEY = "__pocketbase_relation__";
|
|
437
398
|
function RelationField(config) {
|
|
438
399
|
const metadata = {
|
|
@@ -476,15 +437,6 @@ function extractRelationMetadata(description) {
|
|
|
476
437
|
}
|
|
477
438
|
return null;
|
|
478
439
|
}
|
|
479
|
-
function editorField() {
|
|
480
|
-
return zod.z.string();
|
|
481
|
-
}
|
|
482
|
-
function geoPointField() {
|
|
483
|
-
return zod.z.object({
|
|
484
|
-
lon: zod.z.number(),
|
|
485
|
-
lat: zod.z.number()
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
440
|
function withPermissions(schema, config) {
|
|
489
441
|
const metadata = {
|
|
490
442
|
permissions: config
|
|
@@ -524,6 +476,191 @@ function defineCollection(config) {
|
|
|
524
476
|
}
|
|
525
477
|
return schema.describe(JSON.stringify(metadata));
|
|
526
478
|
}
|
|
479
|
+
var FIELD_METADATA_KEY = "__pocketbase_field__";
|
|
480
|
+
function extractFieldMetadata(description) {
|
|
481
|
+
if (!description) return null;
|
|
482
|
+
try {
|
|
483
|
+
const parsed = JSON.parse(description);
|
|
484
|
+
if (parsed[FIELD_METADATA_KEY]) {
|
|
485
|
+
return parsed[FIELD_METADATA_KEY];
|
|
486
|
+
}
|
|
487
|
+
} catch {
|
|
488
|
+
}
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
function BoolField() {
|
|
492
|
+
const metadata = {
|
|
493
|
+
[FIELD_METADATA_KEY]: {
|
|
494
|
+
type: "bool"
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
return zod.z.boolean().describe(JSON.stringify(metadata));
|
|
498
|
+
}
|
|
499
|
+
function NumberField(options) {
|
|
500
|
+
if (options?.min !== void 0 && options?.max !== void 0) {
|
|
501
|
+
if (options.min > options.max) {
|
|
502
|
+
throw new Error("NumberField: min cannot be greater than max");
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
let schema = zod.z.number();
|
|
506
|
+
if (options?.min !== void 0) {
|
|
507
|
+
schema = schema.min(options.min);
|
|
508
|
+
}
|
|
509
|
+
if (options?.max !== void 0) {
|
|
510
|
+
schema = schema.max(options.max);
|
|
511
|
+
}
|
|
512
|
+
const metadata = {
|
|
513
|
+
[FIELD_METADATA_KEY]: {
|
|
514
|
+
type: "number",
|
|
515
|
+
options: options || {}
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
return schema.describe(JSON.stringify(metadata));
|
|
519
|
+
}
|
|
520
|
+
function TextField(options) {
|
|
521
|
+
if (options?.min !== void 0 && options?.max !== void 0) {
|
|
522
|
+
if (options.min > options.max) {
|
|
523
|
+
throw new Error("TextField: min cannot be greater than max");
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
let schema = zod.z.string();
|
|
527
|
+
if (options?.min !== void 0) {
|
|
528
|
+
schema = schema.min(options.min);
|
|
529
|
+
}
|
|
530
|
+
if (options?.max !== void 0) {
|
|
531
|
+
schema = schema.max(options.max);
|
|
532
|
+
}
|
|
533
|
+
if (options?.pattern !== void 0) {
|
|
534
|
+
const pattern = options.pattern instanceof RegExp ? options.pattern : new RegExp(options.pattern);
|
|
535
|
+
schema = schema.regex(pattern);
|
|
536
|
+
}
|
|
537
|
+
const metadata = {
|
|
538
|
+
[FIELD_METADATA_KEY]: {
|
|
539
|
+
type: "text",
|
|
540
|
+
options: options || {}
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
return schema.describe(JSON.stringify(metadata));
|
|
544
|
+
}
|
|
545
|
+
function EmailField() {
|
|
546
|
+
const metadata = {
|
|
547
|
+
[FIELD_METADATA_KEY]: {
|
|
548
|
+
type: "email"
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
return zod.z.string().email().describe(JSON.stringify(metadata));
|
|
552
|
+
}
|
|
553
|
+
function URLField() {
|
|
554
|
+
const metadata = {
|
|
555
|
+
[FIELD_METADATA_KEY]: {
|
|
556
|
+
type: "url"
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
return zod.z.string().url().describe(JSON.stringify(metadata));
|
|
560
|
+
}
|
|
561
|
+
function EditorField() {
|
|
562
|
+
const metadata = {
|
|
563
|
+
[FIELD_METADATA_KEY]: {
|
|
564
|
+
type: "editor"
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
return zod.z.string().describe(JSON.stringify(metadata));
|
|
568
|
+
}
|
|
569
|
+
function DateField(options) {
|
|
570
|
+
if (options?.min !== void 0 && options?.max !== void 0) {
|
|
571
|
+
const minDate = typeof options.min === "string" ? new Date(options.min) : options.min;
|
|
572
|
+
const maxDate = typeof options.max === "string" ? new Date(options.max) : options.max;
|
|
573
|
+
if (minDate > maxDate) {
|
|
574
|
+
throw new Error("DateField: min cannot be greater than max");
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
const schema = zod.z.string();
|
|
578
|
+
const metadata = {
|
|
579
|
+
[FIELD_METADATA_KEY]: {
|
|
580
|
+
type: "date",
|
|
581
|
+
options: options || {}
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
return schema.describe(JSON.stringify(metadata));
|
|
585
|
+
}
|
|
586
|
+
function AutodateField(options) {
|
|
587
|
+
const schema = zod.z.string();
|
|
588
|
+
const metadata = {
|
|
589
|
+
[FIELD_METADATA_KEY]: {
|
|
590
|
+
type: "autodate",
|
|
591
|
+
options: options || {}
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
return schema.describe(JSON.stringify(metadata));
|
|
595
|
+
}
|
|
596
|
+
function SelectField(values, options) {
|
|
597
|
+
const enumSchema = zod.z.enum(values);
|
|
598
|
+
const metadata = {
|
|
599
|
+
[FIELD_METADATA_KEY]: {
|
|
600
|
+
type: "select",
|
|
601
|
+
options: {
|
|
602
|
+
values,
|
|
603
|
+
maxSelect: options?.maxSelect ?? 1
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
if (options?.maxSelect && options.maxSelect > 1) {
|
|
608
|
+
return zod.z.array(enumSchema).describe(JSON.stringify(metadata));
|
|
609
|
+
}
|
|
610
|
+
return enumSchema.describe(JSON.stringify(metadata));
|
|
611
|
+
}
|
|
612
|
+
function FileField(options) {
|
|
613
|
+
const schema = zod.z.instanceof(File);
|
|
614
|
+
const metadata = {
|
|
615
|
+
[FIELD_METADATA_KEY]: {
|
|
616
|
+
type: "file",
|
|
617
|
+
options: options || {}
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
return schema.describe(JSON.stringify(metadata));
|
|
621
|
+
}
|
|
622
|
+
function FilesField(options) {
|
|
623
|
+
if (options?.minSelect !== void 0 && options?.maxSelect !== void 0) {
|
|
624
|
+
if (options.minSelect > options.maxSelect) {
|
|
625
|
+
throw new Error("FilesField: minSelect cannot be greater than maxSelect");
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
let schema = zod.z.array(zod.z.instanceof(File));
|
|
629
|
+
if (options?.minSelect !== void 0) {
|
|
630
|
+
schema = schema.min(options.minSelect);
|
|
631
|
+
}
|
|
632
|
+
if (options?.maxSelect !== void 0) {
|
|
633
|
+
schema = schema.max(options.maxSelect);
|
|
634
|
+
}
|
|
635
|
+
const metadata = {
|
|
636
|
+
[FIELD_METADATA_KEY]: {
|
|
637
|
+
type: "file",
|
|
638
|
+
options: options || {}
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
return schema.describe(JSON.stringify(metadata));
|
|
642
|
+
}
|
|
643
|
+
function JSONField(schema) {
|
|
644
|
+
const baseSchema2 = schema ?? zod.z.record(zod.z.string(), zod.z.any());
|
|
645
|
+
const metadata = {
|
|
646
|
+
[FIELD_METADATA_KEY]: {
|
|
647
|
+
type: "json"
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
return baseSchema2.describe(JSON.stringify(metadata));
|
|
651
|
+
}
|
|
652
|
+
function GeoPointField() {
|
|
653
|
+
const schema = zod.z.object({
|
|
654
|
+
lon: zod.z.number(),
|
|
655
|
+
lat: zod.z.number()
|
|
656
|
+
});
|
|
657
|
+
const metadata = {
|
|
658
|
+
[FIELD_METADATA_KEY]: {
|
|
659
|
+
type: "geoPoint"
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
return schema.describe(JSON.stringify(metadata));
|
|
663
|
+
}
|
|
527
664
|
|
|
528
665
|
// src/utils/permission-templates.ts
|
|
529
666
|
var PermissionTemplates = {
|
|
@@ -2144,6 +2281,38 @@ function isAuthCollection(fields) {
|
|
|
2144
2281
|
return hasEmail && hasPassword;
|
|
2145
2282
|
}
|
|
2146
2283
|
function buildFieldDefinition(fieldName, zodType) {
|
|
2284
|
+
const fieldMetadata = extractFieldMetadata(zodType.description);
|
|
2285
|
+
if (fieldMetadata) {
|
|
2286
|
+
let required2;
|
|
2287
|
+
if (fieldMetadata.type === "number") {
|
|
2288
|
+
if (fieldMetadata.options?.required !== void 0) {
|
|
2289
|
+
required2 = fieldMetadata.options.required;
|
|
2290
|
+
} else {
|
|
2291
|
+
required2 = false;
|
|
2292
|
+
}
|
|
2293
|
+
} else {
|
|
2294
|
+
required2 = isFieldRequired(zodType);
|
|
2295
|
+
}
|
|
2296
|
+
const { required: _required, ...options2 } = fieldMetadata.options || {};
|
|
2297
|
+
const fieldDef2 = {
|
|
2298
|
+
name: fieldName,
|
|
2299
|
+
type: fieldMetadata.type,
|
|
2300
|
+
required: required2,
|
|
2301
|
+
options: Object.keys(options2).length > 0 ? options2 : void 0
|
|
2302
|
+
};
|
|
2303
|
+
if (fieldMetadata.type === "relation") {
|
|
2304
|
+
const relationMetadata2 = extractRelationMetadata(zodType.description);
|
|
2305
|
+
if (relationMetadata2) {
|
|
2306
|
+
fieldDef2.relation = {
|
|
2307
|
+
collection: relationMetadata2.collection,
|
|
2308
|
+
maxSelect: relationMetadata2.maxSelect,
|
|
2309
|
+
minSelect: relationMetadata2.minSelect,
|
|
2310
|
+
cascadeDelete: relationMetadata2.cascadeDelete
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
return fieldDef2;
|
|
2315
|
+
}
|
|
2147
2316
|
const fieldType = mapZodTypeToPocketBase(zodType, fieldName);
|
|
2148
2317
|
const required = isFieldRequired(zodType);
|
|
2149
2318
|
const options = extractFieldOptions(zodType);
|
|
@@ -3125,6 +3294,65 @@ var SnapshotManager = class {
|
|
|
3125
3294
|
return validateSnapshot(snapshot);
|
|
3126
3295
|
}
|
|
3127
3296
|
};
|
|
3297
|
+
function generateCollectionId() {
|
|
3298
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
3299
|
+
const idLength = 15;
|
|
3300
|
+
const bytes = crypto.randomBytes(idLength);
|
|
3301
|
+
let id = "pb_";
|
|
3302
|
+
for (let i = 0; i < idLength; i++) {
|
|
3303
|
+
const index = bytes[i] % chars.length;
|
|
3304
|
+
id += chars[index];
|
|
3305
|
+
}
|
|
3306
|
+
return id;
|
|
3307
|
+
}
|
|
3308
|
+
var CollectionIdRegistry = class {
|
|
3309
|
+
ids;
|
|
3310
|
+
constructor() {
|
|
3311
|
+
this.ids = /* @__PURE__ */ new Set();
|
|
3312
|
+
}
|
|
3313
|
+
/**
|
|
3314
|
+
* Generates a unique collection ID for a given collection name
|
|
3315
|
+
* Special case: Returns constant "_pb_users_auth_" for users collection
|
|
3316
|
+
* Retries up to 10 times if collision occurs (extremely rare)
|
|
3317
|
+
*
|
|
3318
|
+
* @param collectionName - The name of the collection
|
|
3319
|
+
* @returns A unique collection ID
|
|
3320
|
+
* @throws Error if unable to generate unique ID after max attempts
|
|
3321
|
+
*/
|
|
3322
|
+
generate(collectionName) {
|
|
3323
|
+
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
3324
|
+
const usersId = "_pb_users_auth_";
|
|
3325
|
+
this.register(usersId);
|
|
3326
|
+
return usersId;
|
|
3327
|
+
}
|
|
3328
|
+
const maxAttempts = 10;
|
|
3329
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
3330
|
+
const id = generateCollectionId();
|
|
3331
|
+
if (!this.has(id)) {
|
|
3332
|
+
this.register(id);
|
|
3333
|
+
return id;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
throw new Error("Failed to generate unique collection ID after maximum attempts");
|
|
3337
|
+
}
|
|
3338
|
+
/**
|
|
3339
|
+
* Checks if an ID has already been registered
|
|
3340
|
+
*
|
|
3341
|
+
* @param id - The collection ID to check
|
|
3342
|
+
* @returns True if the ID exists in the registry
|
|
3343
|
+
*/
|
|
3344
|
+
has(id) {
|
|
3345
|
+
return this.ids.has(id);
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* Registers a collection ID in the registry
|
|
3349
|
+
*
|
|
3350
|
+
* @param id - The collection ID to register
|
|
3351
|
+
*/
|
|
3352
|
+
register(id) {
|
|
3353
|
+
this.ids.add(id);
|
|
3354
|
+
}
|
|
3355
|
+
};
|
|
3128
3356
|
|
|
3129
3357
|
// src/migration/diff.ts
|
|
3130
3358
|
var DEFAULT_CONFIG3 = {
|
|
@@ -3467,6 +3695,18 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
3467
3695
|
const filteredCollectionsToDelete = collectionsToDelete.filter(
|
|
3468
3696
|
(collection) => !isSystemCollection(collection.name, config)
|
|
3469
3697
|
);
|
|
3698
|
+
const registry = new CollectionIdRegistry();
|
|
3699
|
+
const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
|
|
3700
|
+
if (collection.id) {
|
|
3701
|
+
registry.register(collection.id);
|
|
3702
|
+
return collection;
|
|
3703
|
+
}
|
|
3704
|
+
const id = registry.generate(collection.name);
|
|
3705
|
+
return {
|
|
3706
|
+
...collection,
|
|
3707
|
+
id
|
|
3708
|
+
};
|
|
3709
|
+
});
|
|
3470
3710
|
const collectionsToModify = [];
|
|
3471
3711
|
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
3472
3712
|
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
@@ -3476,7 +3716,7 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
3476
3716
|
}
|
|
3477
3717
|
}
|
|
3478
3718
|
return {
|
|
3479
|
-
collectionsToCreate:
|
|
3719
|
+
collectionsToCreate: collectionsWithIds,
|
|
3480
3720
|
collectionsToDelete: filteredCollectionsToDelete,
|
|
3481
3721
|
collectionsToModify
|
|
3482
3722
|
};
|
|
@@ -3712,6 +3952,49 @@ function generateTimestamp(config) {
|
|
|
3712
3952
|
}
|
|
3713
3953
|
return Math.floor(Date.now() / 1e3).toString();
|
|
3714
3954
|
}
|
|
3955
|
+
function splitDiffByCollection(diff, baseTimestamp) {
|
|
3956
|
+
const operations = [];
|
|
3957
|
+
let currentTimestamp = parseInt(baseTimestamp, 10);
|
|
3958
|
+
for (const collection of diff.collectionsToCreate) {
|
|
3959
|
+
operations.push({
|
|
3960
|
+
type: "create",
|
|
3961
|
+
collection,
|
|
3962
|
+
timestamp: currentTimestamp.toString()
|
|
3963
|
+
});
|
|
3964
|
+
currentTimestamp += 1;
|
|
3965
|
+
}
|
|
3966
|
+
for (const modification of diff.collectionsToModify) {
|
|
3967
|
+
operations.push({
|
|
3968
|
+
type: "modify",
|
|
3969
|
+
collection: modification.collection,
|
|
3970
|
+
modifications: modification,
|
|
3971
|
+
timestamp: currentTimestamp.toString()
|
|
3972
|
+
});
|
|
3973
|
+
currentTimestamp += 1;
|
|
3974
|
+
}
|
|
3975
|
+
for (const collection of diff.collectionsToDelete) {
|
|
3976
|
+
operations.push({
|
|
3977
|
+
type: "delete",
|
|
3978
|
+
collection: collection.name || collection,
|
|
3979
|
+
// Handle both object and string
|
|
3980
|
+
timestamp: currentTimestamp.toString()
|
|
3981
|
+
});
|
|
3982
|
+
currentTimestamp += 1;
|
|
3983
|
+
}
|
|
3984
|
+
return operations;
|
|
3985
|
+
}
|
|
3986
|
+
function generateCollectionMigrationFilename(operation) {
|
|
3987
|
+
const timestamp = operation.timestamp;
|
|
3988
|
+
const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
|
|
3989
|
+
let collectionName;
|
|
3990
|
+
if (typeof operation.collection === "string") {
|
|
3991
|
+
collectionName = operation.collection;
|
|
3992
|
+
} else {
|
|
3993
|
+
collectionName = operation.collection.name;
|
|
3994
|
+
}
|
|
3995
|
+
const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
|
|
3996
|
+
return `${timestamp}_${operationType}_${sanitizedName}.js`;
|
|
3997
|
+
}
|
|
3715
3998
|
function generateMigrationDescription(diff) {
|
|
3716
3999
|
const parts = [];
|
|
3717
4000
|
if (diff.collectionsToCreate.length > 0) {
|
|
@@ -3819,14 +4102,13 @@ function formatValue(value) {
|
|
|
3819
4102
|
return "null";
|
|
3820
4103
|
}
|
|
3821
4104
|
if (typeof value === "string") {
|
|
3822
|
-
return
|
|
4105
|
+
return JSON.stringify(value);
|
|
3823
4106
|
}
|
|
3824
4107
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
3825
4108
|
return String(value);
|
|
3826
4109
|
}
|
|
3827
4110
|
if (Array.isArray(value)) {
|
|
3828
|
-
|
|
3829
|
-
return `[${items}]`;
|
|
4111
|
+
return JSON.stringify(value).replace(/","/g, '", "');
|
|
3830
4112
|
}
|
|
3831
4113
|
if (typeof value === "object") {
|
|
3832
4114
|
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
@@ -3834,7 +4116,7 @@ function formatValue(value) {
|
|
|
3834
4116
|
}
|
|
3835
4117
|
return String(value);
|
|
3836
4118
|
}
|
|
3837
|
-
function generateFieldDefinitionObject(field) {
|
|
4119
|
+
function generateFieldDefinitionObject(field, collectionIdMap) {
|
|
3838
4120
|
const parts = [];
|
|
3839
4121
|
parts.push(` name: "${field.name}"`);
|
|
3840
4122
|
parts.push(` type: "${field.type}"`);
|
|
@@ -3842,34 +4124,47 @@ function generateFieldDefinitionObject(field) {
|
|
|
3842
4124
|
if (field.unique !== void 0) {
|
|
3843
4125
|
parts.push(` unique: ${field.unique}`);
|
|
3844
4126
|
}
|
|
4127
|
+
if (field.type === "select") {
|
|
4128
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
4129
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4130
|
+
const values = field.options?.values ?? [];
|
|
4131
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
4132
|
+
}
|
|
3845
4133
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
3846
4134
|
for (const [key, value] of Object.entries(field.options)) {
|
|
4135
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
4136
|
+
continue;
|
|
4137
|
+
}
|
|
3847
4138
|
parts.push(` ${key}: ${formatValue(value)}`);
|
|
3848
4139
|
}
|
|
3849
4140
|
}
|
|
3850
4141
|
if (field.relation) {
|
|
3851
4142
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
}
|
|
3860
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
3861
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
4143
|
+
let collectionIdValue;
|
|
4144
|
+
if (isUsersCollection) {
|
|
4145
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
4146
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
4147
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
4148
|
+
} else {
|
|
4149
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3862
4150
|
}
|
|
4151
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
4152
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
4153
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4154
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
4155
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
4156
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
4157
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
3863
4158
|
}
|
|
3864
4159
|
return ` {
|
|
3865
4160
|
${parts.join(",\n")},
|
|
3866
4161
|
}`;
|
|
3867
4162
|
}
|
|
3868
|
-
function generateFieldsArray(fields) {
|
|
4163
|
+
function generateFieldsArray(fields, collectionIdMap) {
|
|
3869
4164
|
if (fields.length === 0) {
|
|
3870
4165
|
return "[]";
|
|
3871
4166
|
}
|
|
3872
|
-
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
|
|
4167
|
+
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
|
|
3873
4168
|
return `[
|
|
3874
4169
|
${fieldObjects.join(",\n")},
|
|
3875
4170
|
]`;
|
|
@@ -3928,7 +4223,7 @@ function generateIndexesArray(indexes) {
|
|
|
3928
4223
|
if (!indexes || indexes.length === 0) {
|
|
3929
4224
|
return "[]";
|
|
3930
4225
|
}
|
|
3931
|
-
const indexStrings = indexes.map((idx) =>
|
|
4226
|
+
const indexStrings = indexes.map((idx) => JSON.stringify(idx));
|
|
3932
4227
|
return `[
|
|
3933
4228
|
${indexStrings.join(",\n ")},
|
|
3934
4229
|
]`;
|
|
@@ -3982,7 +4277,7 @@ function getSystemFields() {
|
|
|
3982
4277
|
}
|
|
3983
4278
|
];
|
|
3984
4279
|
}
|
|
3985
|
-
function generateCollectionCreation(collection, varName = "collection", isLast = false) {
|
|
4280
|
+
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
3986
4281
|
const lines = [];
|
|
3987
4282
|
lines.push(` const ${varName} = new Collection({`);
|
|
3988
4283
|
lines.push(` name: "${collection.name}",`);
|
|
@@ -3996,7 +4291,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3996
4291
|
}
|
|
3997
4292
|
const systemFields = getSystemFields();
|
|
3998
4293
|
const allFields = [...systemFields, ...collection.fields];
|
|
3999
|
-
lines.push(` fields: ${generateFieldsArray(allFields)},`);
|
|
4294
|
+
lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
4000
4295
|
lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
|
|
4001
4296
|
lines.push(` });`);
|
|
4002
4297
|
lines.push(``);
|
|
@@ -4018,42 +4313,59 @@ function getFieldConstructorName(fieldType) {
|
|
|
4018
4313
|
};
|
|
4019
4314
|
return constructorMap[fieldType] || "TextField";
|
|
4020
4315
|
}
|
|
4021
|
-
function generateFieldConstructorOptions(field) {
|
|
4316
|
+
function generateFieldConstructorOptions(field, collectionIdMap) {
|
|
4022
4317
|
const parts = [];
|
|
4023
4318
|
parts.push(` name: "${field.name}"`);
|
|
4024
4319
|
parts.push(` required: ${field.required}`);
|
|
4025
4320
|
if (field.unique !== void 0) {
|
|
4026
4321
|
parts.push(` unique: ${field.unique}`);
|
|
4027
4322
|
}
|
|
4323
|
+
if (field.type === "select") {
|
|
4324
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
4325
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4326
|
+
const values = field.options?.values ?? [];
|
|
4327
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
4328
|
+
}
|
|
4028
4329
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
4029
4330
|
for (const [key, value] of Object.entries(field.options)) {
|
|
4030
|
-
|
|
4331
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
4332
|
+
continue;
|
|
4333
|
+
}
|
|
4334
|
+
if (field.type === "number" && key === "noDecimal") {
|
|
4335
|
+
parts.push(` onlyInt: ${formatValue(value)}`);
|
|
4336
|
+
} else {
|
|
4337
|
+
parts.push(` ${key}: ${formatValue(value)}`);
|
|
4338
|
+
}
|
|
4031
4339
|
}
|
|
4032
4340
|
}
|
|
4033
4341
|
if (field.relation && field.type === "relation") {
|
|
4034
4342
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
}
|
|
4043
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
4044
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
4343
|
+
let collectionIdValue;
|
|
4344
|
+
if (isUsersCollection) {
|
|
4345
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
4346
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
4347
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
4348
|
+
} else {
|
|
4349
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
4045
4350
|
}
|
|
4351
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
4352
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
4353
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
4354
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
4355
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
4356
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
4357
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
4046
4358
|
}
|
|
4047
4359
|
return parts.join(",\n");
|
|
4048
4360
|
}
|
|
4049
|
-
function generateFieldAddition(collectionName, field, varName, isLast = false) {
|
|
4361
|
+
function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
|
|
4050
4362
|
const lines = [];
|
|
4051
4363
|
const constructorName = getFieldConstructorName(field.type);
|
|
4052
4364
|
const collectionVar = varName || `collection_${collectionName}_${field.name}`;
|
|
4053
4365
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4054
4366
|
lines.push(``);
|
|
4055
4367
|
lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
|
|
4056
|
-
lines.push(generateFieldConstructorOptions(field));
|
|
4368
|
+
lines.push(generateFieldConstructorOptions(field, collectionIdMap));
|
|
4057
4369
|
lines.push(` }));`);
|
|
4058
4370
|
lines.push(``);
|
|
4059
4371
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
@@ -4103,7 +4415,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
|
|
|
4103
4415
|
const lines = [];
|
|
4104
4416
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
4105
4417
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4106
|
-
lines.push(` ${collectionVar}.indexes.push(
|
|
4418
|
+
lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
|
|
4107
4419
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4108
4420
|
return lines.join("\n");
|
|
4109
4421
|
}
|
|
@@ -4112,7 +4424,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
|
|
|
4112
4424
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
4113
4425
|
const indexVar = `${collectionVar}_indexToRemove`;
|
|
4114
4426
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4115
|
-
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx ===
|
|
4427
|
+
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
|
|
4116
4428
|
lines.push(` if (${indexVar} !== -1) {`);
|
|
4117
4429
|
lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
|
|
4118
4430
|
lines.push(` }`);
|
|
@@ -4141,16 +4453,179 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
|
|
|
4141
4453
|
lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
|
|
4142
4454
|
return lines.join("\n");
|
|
4143
4455
|
}
|
|
4456
|
+
function generateOperationUpMigration(operation, collectionIdMap) {
|
|
4457
|
+
const lines = [];
|
|
4458
|
+
if (operation.type === "create") {
|
|
4459
|
+
const collection = operation.collection;
|
|
4460
|
+
const varName = `collection_${collection.name}`;
|
|
4461
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
4462
|
+
} else if (operation.type === "modify") {
|
|
4463
|
+
const modification = operation.modifications;
|
|
4464
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4465
|
+
let operationCount = 0;
|
|
4466
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
4467
|
+
for (const field of modification.fieldsToAdd) {
|
|
4468
|
+
operationCount++;
|
|
4469
|
+
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
4470
|
+
const isLast = operationCount === totalOperations;
|
|
4471
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
4472
|
+
if (!isLast) lines.push("");
|
|
4473
|
+
}
|
|
4474
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
4475
|
+
operationCount++;
|
|
4476
|
+
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
4477
|
+
const isLast = operationCount === totalOperations;
|
|
4478
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
|
|
4479
|
+
if (!isLast) lines.push("");
|
|
4480
|
+
}
|
|
4481
|
+
for (const field of modification.fieldsToRemove) {
|
|
4482
|
+
operationCount++;
|
|
4483
|
+
const varName = `collection_${collectionName}_remove_${field.name}`;
|
|
4484
|
+
const isLast = operationCount === totalOperations;
|
|
4485
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
4486
|
+
if (!isLast) lines.push("");
|
|
4487
|
+
}
|
|
4488
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
4489
|
+
operationCount++;
|
|
4490
|
+
const index = modification.indexesToAdd[i];
|
|
4491
|
+
const varName = `collection_${collectionName}_addidx_${i}`;
|
|
4492
|
+
const isLast = operationCount === totalOperations;
|
|
4493
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
4494
|
+
if (!isLast) lines.push("");
|
|
4495
|
+
}
|
|
4496
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
4497
|
+
operationCount++;
|
|
4498
|
+
const index = modification.indexesToRemove[i];
|
|
4499
|
+
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
4500
|
+
const isLast = operationCount === totalOperations;
|
|
4501
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
4502
|
+
if (!isLast) lines.push("");
|
|
4503
|
+
}
|
|
4504
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4505
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
4506
|
+
operationCount++;
|
|
4507
|
+
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
4508
|
+
const isLast = operationCount === totalOperations;
|
|
4509
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
|
|
4510
|
+
if (!isLast) lines.push("");
|
|
4511
|
+
}
|
|
4512
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
4513
|
+
for (const rule of modification.rulesToUpdate) {
|
|
4514
|
+
operationCount++;
|
|
4515
|
+
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
4516
|
+
const isLast = operationCount === totalOperations;
|
|
4517
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
|
|
4518
|
+
if (!isLast) lines.push("");
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
} else if (operation.type === "delete") {
|
|
4522
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
4523
|
+
const varName = `collection_${collectionName}`;
|
|
4524
|
+
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
4525
|
+
}
|
|
4526
|
+
return lines.join("\n");
|
|
4527
|
+
}
|
|
4528
|
+
function generateOperationDownMigration(operation, collectionIdMap) {
|
|
4529
|
+
const lines = [];
|
|
4530
|
+
if (operation.type === "create") {
|
|
4531
|
+
const collection = operation.collection;
|
|
4532
|
+
const varName = `collection_${collection.name}`;
|
|
4533
|
+
lines.push(generateCollectionDeletion(collection.name, varName, true));
|
|
4534
|
+
} else if (operation.type === "modify") {
|
|
4535
|
+
const modification = operation.modifications;
|
|
4536
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4537
|
+
let operationCount = 0;
|
|
4538
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
4539
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4540
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
4541
|
+
operationCount++;
|
|
4542
|
+
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
4543
|
+
const isLast = operationCount === totalOperations;
|
|
4544
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
|
|
4545
|
+
if (!isLast) lines.push("");
|
|
4546
|
+
}
|
|
4547
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
4548
|
+
for (const rule of modification.rulesToUpdate) {
|
|
4549
|
+
operationCount++;
|
|
4550
|
+
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
4551
|
+
const isLast = operationCount === totalOperations;
|
|
4552
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
|
|
4553
|
+
if (!isLast) lines.push("");
|
|
4554
|
+
}
|
|
4555
|
+
}
|
|
4556
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
4557
|
+
operationCount++;
|
|
4558
|
+
const index = modification.indexesToRemove[i];
|
|
4559
|
+
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
4560
|
+
const isLast = operationCount === totalOperations;
|
|
4561
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
4562
|
+
if (!isLast) lines.push("");
|
|
4563
|
+
}
|
|
4564
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
4565
|
+
operationCount++;
|
|
4566
|
+
const index = modification.indexesToAdd[i];
|
|
4567
|
+
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
4568
|
+
const isLast = operationCount === totalOperations;
|
|
4569
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
4570
|
+
if (!isLast) lines.push("");
|
|
4571
|
+
}
|
|
4572
|
+
for (const field of modification.fieldsToRemove) {
|
|
4573
|
+
operationCount++;
|
|
4574
|
+
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
4575
|
+
const isLast = operationCount === totalOperations;
|
|
4576
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
4577
|
+
if (!isLast) lines.push("");
|
|
4578
|
+
}
|
|
4579
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
4580
|
+
operationCount++;
|
|
4581
|
+
const reverseChanges = fieldMod.changes.map((change) => ({
|
|
4582
|
+
property: change.property,
|
|
4583
|
+
oldValue: change.newValue,
|
|
4584
|
+
newValue: change.oldValue
|
|
4585
|
+
}));
|
|
4586
|
+
const reverseMod = {
|
|
4587
|
+
fieldName: fieldMod.fieldName,
|
|
4588
|
+
currentDefinition: fieldMod.newDefinition,
|
|
4589
|
+
newDefinition: fieldMod.currentDefinition,
|
|
4590
|
+
changes: reverseChanges
|
|
4591
|
+
};
|
|
4592
|
+
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
4593
|
+
const isLast = operationCount === totalOperations;
|
|
4594
|
+
lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
|
|
4595
|
+
if (!isLast) lines.push("");
|
|
4596
|
+
}
|
|
4597
|
+
for (const field of modification.fieldsToAdd) {
|
|
4598
|
+
operationCount++;
|
|
4599
|
+
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
4600
|
+
const isLast = operationCount === totalOperations;
|
|
4601
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
4602
|
+
if (!isLast) lines.push("");
|
|
4603
|
+
}
|
|
4604
|
+
} else if (operation.type === "delete") {
|
|
4605
|
+
const collection = operation.collection;
|
|
4606
|
+
if (typeof collection !== "string") {
|
|
4607
|
+
const varName = `collection_${collection.name}`;
|
|
4608
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
return lines.join("\n");
|
|
4612
|
+
}
|
|
4144
4613
|
function generateUpMigration(diff) {
|
|
4145
4614
|
const lines = [];
|
|
4146
4615
|
lines.push(` // UP MIGRATION`);
|
|
4147
4616
|
lines.push(``);
|
|
4617
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4618
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4619
|
+
if (collection.id) {
|
|
4620
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4148
4623
|
if (diff.collectionsToCreate.length > 0) {
|
|
4149
4624
|
lines.push(` // Create new collections`);
|
|
4150
4625
|
for (let i = 0; i < diff.collectionsToCreate.length; i++) {
|
|
4151
4626
|
const collection = diff.collectionsToCreate[i];
|
|
4152
4627
|
const varName = `collection_${collection.name}_create`;
|
|
4153
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
4628
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
4154
4629
|
lines.push(``);
|
|
4155
4630
|
}
|
|
4156
4631
|
}
|
|
@@ -4162,7 +4637,7 @@ function generateUpMigration(diff) {
|
|
|
4162
4637
|
lines.push(` // Add fields to ${collectionName}`);
|
|
4163
4638
|
for (const field of modification.fieldsToAdd) {
|
|
4164
4639
|
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
4165
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
4640
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
4166
4641
|
lines.push(``);
|
|
4167
4642
|
}
|
|
4168
4643
|
}
|
|
@@ -4253,12 +4728,23 @@ function generateDownMigration(diff) {
|
|
|
4253
4728
|
const lines = [];
|
|
4254
4729
|
lines.push(` // DOWN MIGRATION (ROLLBACK)`);
|
|
4255
4730
|
lines.push(``);
|
|
4731
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4732
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4733
|
+
if (collection.id) {
|
|
4734
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4735
|
+
}
|
|
4736
|
+
}
|
|
4737
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4738
|
+
if (collection.id) {
|
|
4739
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4740
|
+
}
|
|
4741
|
+
}
|
|
4256
4742
|
if (diff.collectionsToDelete.length > 0) {
|
|
4257
4743
|
lines.push(` // Recreate deleted collections`);
|
|
4258
4744
|
for (let i = 0; i < diff.collectionsToDelete.length; i++) {
|
|
4259
4745
|
const collection = diff.collectionsToDelete[i];
|
|
4260
4746
|
const varName = `collection_${collection.name}_recreate`;
|
|
4261
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
4747
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
4262
4748
|
lines.push(``);
|
|
4263
4749
|
}
|
|
4264
4750
|
}
|
|
@@ -4303,7 +4789,7 @@ function generateDownMigration(diff) {
|
|
|
4303
4789
|
lines.push(` // Restore fields to ${collectionName}`);
|
|
4304
4790
|
for (const field of modification.fieldsToRemove) {
|
|
4305
4791
|
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
4306
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
4792
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
4307
4793
|
lines.push(``);
|
|
4308
4794
|
}
|
|
4309
4795
|
}
|
|
@@ -4372,12 +4858,33 @@ function generate(diff, config) {
|
|
|
4372
4858
|
const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
|
|
4373
4859
|
try {
|
|
4374
4860
|
const migrationDir = resolveMigrationDir(normalizedConfig);
|
|
4375
|
-
const
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
const
|
|
4380
|
-
|
|
4861
|
+
const hasChanges4 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
|
|
4862
|
+
if (!hasChanges4) {
|
|
4863
|
+
return [];
|
|
4864
|
+
}
|
|
4865
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4866
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4867
|
+
if (collection.id) {
|
|
4868
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4872
|
+
if (collection.id) {
|
|
4873
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
const baseTimestamp = generateTimestamp(normalizedConfig);
|
|
4877
|
+
const operations = splitDiffByCollection(diff, baseTimestamp);
|
|
4878
|
+
const filePaths = [];
|
|
4879
|
+
for (const operation of operations) {
|
|
4880
|
+
const upCode = generateOperationUpMigration(operation, collectionIdMap);
|
|
4881
|
+
const downCode = generateOperationDownMigration(operation, collectionIdMap);
|
|
4882
|
+
const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
|
|
4883
|
+
const filename = generateCollectionMigrationFilename(operation);
|
|
4884
|
+
const filePath = writeMigrationFile(migrationDir, filename, content);
|
|
4885
|
+
filePaths.push(filePath);
|
|
4886
|
+
}
|
|
4887
|
+
return filePaths;
|
|
4381
4888
|
} catch (error) {
|
|
4382
4889
|
if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
|
|
4383
4890
|
throw error;
|
|
@@ -4395,7 +4902,8 @@ var MigrationGenerator = class {
|
|
|
4395
4902
|
this.config = mergeConfig4(config);
|
|
4396
4903
|
}
|
|
4397
4904
|
/**
|
|
4398
|
-
* Generates
|
|
4905
|
+
* Generates migration files from a schema diff
|
|
4906
|
+
* Returns array of file paths (one per collection operation)
|
|
4399
4907
|
*/
|
|
4400
4908
|
generate(diff) {
|
|
4401
4909
|
return generate(diff, this.config);
|
|
@@ -4999,15 +5507,25 @@ async function executeGenerate(options) {
|
|
|
4999
5507
|
process.exit(1);
|
|
5000
5508
|
}
|
|
5001
5509
|
logSection("\u{1F4DD} Generating Migration");
|
|
5002
|
-
const
|
|
5510
|
+
const migrationPaths = await withProgress(
|
|
5003
5511
|
"Creating migration file...",
|
|
5004
5512
|
() => Promise.resolve(generate(diff, migrationsDir))
|
|
5005
5513
|
);
|
|
5006
|
-
|
|
5514
|
+
if (migrationPaths.length === 0) {
|
|
5515
|
+
logWarning("No migration files were generated (no changes detected).");
|
|
5516
|
+
return;
|
|
5517
|
+
}
|
|
5518
|
+
if (migrationPaths.length === 1) {
|
|
5519
|
+
logSuccess(`Migration file created: ${path5__namespace.basename(migrationPaths[0])}`);
|
|
5520
|
+
} else {
|
|
5521
|
+
logSuccess(`Created ${migrationPaths.length} migration files`);
|
|
5522
|
+
}
|
|
5007
5523
|
logSection("\u2705 Next Steps");
|
|
5008
5524
|
console.log();
|
|
5009
|
-
console.log(" 1. Review the generated migration file:");
|
|
5010
|
-
|
|
5525
|
+
console.log(" 1. Review the generated migration file(s):");
|
|
5526
|
+
migrationPaths.forEach((migrationPath) => {
|
|
5527
|
+
console.log(` ${migrationPath}`);
|
|
5528
|
+
});
|
|
5011
5529
|
console.log();
|
|
5012
5530
|
console.log(" 2. Apply the migration by running PocketBase:");
|
|
5013
5531
|
console.log(" yarn pb");
|
|
@@ -5270,29 +5788,42 @@ async function executeStatus(options) {
|
|
|
5270
5788
|
}
|
|
5271
5789
|
}
|
|
5272
5790
|
|
|
5791
|
+
exports.AutodateField = AutodateField;
|
|
5273
5792
|
exports.BaseMutator = BaseMutator;
|
|
5793
|
+
exports.BoolField = BoolField;
|
|
5274
5794
|
exports.CLIUsageError = CLIUsageError;
|
|
5275
5795
|
exports.ConfigurationError = ConfigurationError;
|
|
5796
|
+
exports.DateField = DateField;
|
|
5276
5797
|
exports.DiffEngine = DiffEngine;
|
|
5798
|
+
exports.EditorField = EditorField;
|
|
5799
|
+
exports.EmailField = EmailField;
|
|
5800
|
+
exports.FIELD_METADATA_KEY = FIELD_METADATA_KEY;
|
|
5277
5801
|
exports.FIELD_TYPE_INFO = FIELD_TYPE_INFO;
|
|
5802
|
+
exports.FileField = FileField;
|
|
5278
5803
|
exports.FileSystemError = FileSystemError;
|
|
5804
|
+
exports.FilesField = FilesField;
|
|
5805
|
+
exports.GeoPointField = GeoPointField;
|
|
5806
|
+
exports.JSONField = JSONField;
|
|
5279
5807
|
exports.MigrationError = MigrationError;
|
|
5280
5808
|
exports.MigrationGenerationError = MigrationGenerationError;
|
|
5281
5809
|
exports.MigrationGenerator = MigrationGenerator;
|
|
5810
|
+
exports.NumberField = NumberField;
|
|
5282
5811
|
exports.POCKETBASE_FIELD_TYPES = POCKETBASE_FIELD_TYPES;
|
|
5283
5812
|
exports.PermissionTemplates = PermissionTemplates;
|
|
5284
5813
|
exports.RelationField = RelationField;
|
|
5285
5814
|
exports.RelationsField = RelationsField;
|
|
5286
5815
|
exports.SchemaAnalyzer = SchemaAnalyzer;
|
|
5287
5816
|
exports.SchemaParsingError = SchemaParsingError;
|
|
5817
|
+
exports.SelectField = SelectField;
|
|
5288
5818
|
exports.SnapshotError = SnapshotError;
|
|
5289
5819
|
exports.SnapshotManager = SnapshotManager;
|
|
5290
5820
|
exports.StatusEnum = StatusEnum;
|
|
5821
|
+
exports.TextField = TextField;
|
|
5822
|
+
exports.URLField = URLField;
|
|
5291
5823
|
exports.aggregateChanges = aggregateChanges;
|
|
5292
5824
|
exports.baseImageFileSchema = baseImageFileSchema;
|
|
5293
5825
|
exports.baseSchema = baseSchema;
|
|
5294
5826
|
exports.baseSchemaWithTimestamps = baseSchemaWithTimestamps;
|
|
5295
|
-
exports.boolField = boolField;
|
|
5296
5827
|
exports.buildFieldDefinition = buildFieldDefinition;
|
|
5297
5828
|
exports.buildSchemaDefinition = buildSchemaDefinition;
|
|
5298
5829
|
exports.categorizeChangesBySeverity = categorizeChangesBySeverity;
|
|
@@ -5306,21 +5837,17 @@ exports.convertPocketBaseMigration = convertPocketBaseMigration;
|
|
|
5306
5837
|
exports.convertZodSchemaToCollectionSchema = convertZodSchemaToCollectionSchema;
|
|
5307
5838
|
exports.createMigrationFileStructure = createMigrationFileStructure;
|
|
5308
5839
|
exports.createPermissions = createPermissions;
|
|
5309
|
-
exports.dateField = dateField;
|
|
5310
5840
|
exports.defineCollection = defineCollection;
|
|
5311
5841
|
exports.detectDestructiveChanges = detectDestructiveChanges;
|
|
5312
5842
|
exports.detectFieldChanges = detectFieldChanges;
|
|
5313
5843
|
exports.discoverSchemaFiles = discoverSchemaFiles;
|
|
5314
|
-
exports.editorField = editorField;
|
|
5315
|
-
exports.emailField = emailField;
|
|
5316
5844
|
exports.extractComprehensiveFieldOptions = extractComprehensiveFieldOptions;
|
|
5317
5845
|
exports.extractFieldDefinitions = extractFieldDefinitions;
|
|
5846
|
+
exports.extractFieldMetadata = extractFieldMetadata;
|
|
5318
5847
|
exports.extractFieldOptions = extractFieldOptions;
|
|
5319
5848
|
exports.extractIndexes = extractIndexes;
|
|
5320
5849
|
exports.extractRelationMetadata = extractRelationMetadata;
|
|
5321
5850
|
exports.extractSchemaDefinitions = extractSchemaDefinitions;
|
|
5322
|
-
exports.fileField = fileField;
|
|
5323
|
-
exports.filesField = filesField;
|
|
5324
5851
|
exports.filterSystemCollections = filterSystemCollections;
|
|
5325
5852
|
exports.findLatestSnapshot = findLatestSnapshot;
|
|
5326
5853
|
exports.findNewCollections = findNewCollections;
|
|
@@ -5346,7 +5873,6 @@ exports.generateMigrationFilename = generateMigrationFilename;
|
|
|
5346
5873
|
exports.generatePermissionUpdate = generatePermissionUpdate;
|
|
5347
5874
|
exports.generateTimestamp = generateTimestamp;
|
|
5348
5875
|
exports.generateUpMigration = generateUpMigration;
|
|
5349
|
-
exports.geoPointField = geoPointField;
|
|
5350
5876
|
exports.getArrayElementType = getArrayElementType;
|
|
5351
5877
|
exports.getCollectionNameFromFile = getCollectionNameFromFile;
|
|
5352
5878
|
exports.getDefaultValue = getDefaultValue;
|
|
@@ -5371,7 +5897,6 @@ exports.isRelationField = isRelationField;
|
|
|
5371
5897
|
exports.isSingleRelationField = isSingleRelationField;
|
|
5372
5898
|
exports.isSystemCollection = isSystemCollection;
|
|
5373
5899
|
exports.isTemplateConfig = isTemplateConfig;
|
|
5374
|
-
exports.jsonField = jsonField;
|
|
5375
5900
|
exports.loadBaseMigration = loadBaseMigration;
|
|
5376
5901
|
exports.loadConfig = loadConfig;
|
|
5377
5902
|
exports.loadSnapshot = loadSnapshot;
|
|
@@ -5394,7 +5919,6 @@ exports.matchCollectionsByName = matchCollectionsByName;
|
|
|
5394
5919
|
exports.matchFieldsByName = matchFieldsByName;
|
|
5395
5920
|
exports.mergePermissions = mergePermissions;
|
|
5396
5921
|
exports.mergeSnapshots = mergeSnapshots;
|
|
5397
|
-
exports.numberField = numberField;
|
|
5398
5922
|
exports.omitImageFilesSchema = omitImageFilesSchema;
|
|
5399
5923
|
exports.parseSchemaFiles = parseSchemaFiles;
|
|
5400
5924
|
exports.pluralize = pluralize;
|
|
@@ -5402,14 +5926,11 @@ exports.requiresForceFlag = requiresForceFlag;
|
|
|
5402
5926
|
exports.resolveTargetCollection = resolveTargetCollection;
|
|
5403
5927
|
exports.resolveTemplate = resolveTemplate;
|
|
5404
5928
|
exports.saveSnapshot = saveSnapshot;
|
|
5405
|
-
exports.selectField = selectField;
|
|
5406
5929
|
exports.selectSchemaForCollection = selectSchemaForCollection;
|
|
5407
5930
|
exports.singularize = singularize;
|
|
5408
5931
|
exports.snapshotExists = snapshotExists;
|
|
5409
|
-
exports.textField = textField;
|
|
5410
5932
|
exports.toCollectionName = toCollectionName;
|
|
5411
5933
|
exports.unwrapZodType = unwrapZodType;
|
|
5412
|
-
exports.urlField = urlField;
|
|
5413
5934
|
exports.validatePermissionConfig = validatePermissionConfig;
|
|
5414
5935
|
exports.validateRuleExpression = validateRuleExpression;
|
|
5415
5936
|
exports.validateSnapshot = validateSnapshot;
|