pocketbase-zod-schema 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/cli/index.cjs +64 -38
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +64 -38
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +64 -38
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +64 -38
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/utils/index.d.cts +2 -2
- package/dist/cli/utils/index.d.ts +2 -2
- package/dist/{fields-RVj26U-O.d.cts → fields-DBBm06VU.d.cts} +34 -7
- package/dist/{fields-RVj26U-O.d.ts → fields-DBBm06VU.d.ts} +34 -7
- package/dist/index.cjs +167 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +167 -75
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +2 -2
- package/dist/migration/analyzer.d.ts +2 -2
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/diff.cjs +10 -1
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.d.cts +2 -2
- package/dist/migration/diff.d.ts +2 -2
- package/dist/migration/diff.js +10 -1
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/generator.cjs +102 -68
- package/dist/migration/generator.cjs.map +1 -1
- package/dist/migration/generator.d.cts +3 -3
- package/dist/migration/generator.d.ts +3 -3
- package/dist/migration/generator.js +102 -68
- package/dist/migration/generator.js.map +1 -1
- package/dist/migration/index.cjs +112 -69
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +3 -3
- package/dist/migration/index.d.ts +3 -3
- package/dist/migration/index.js +112 -69
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.d.cts +2 -2
- package/dist/migration/snapshot.d.ts +2 -2
- package/dist/migration/utils/index.cjs.map +1 -1
- package/dist/migration/utils/index.d.cts +2 -2
- package/dist/migration/utils/index.d.ts +2 -2
- package/dist/migration/utils/index.js.map +1 -1
- package/dist/schema.cjs +55 -6
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +55 -6
- package/dist/schema.js.map +1 -1
- package/dist/{type-mapper-DaBe-1ph.d.cts → type-mapper-DsGgZwUo.d.cts} +1 -1
- package/dist/{type-mapper-CZzVeDj7.d.ts → type-mapper-Dvh4QTM-.d.ts} +1 -1
- package/dist/{types-CUVzgZ9k.d.ts → types-BWhwQxG-.d.ts} +6 -1
- package/dist/{types-D-Fsdn_O.d.cts → types-d0yBwHoN.d.cts} +6 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Ora } from 'ora';
|
|
2
|
-
import { e as SchemaDiff } from '../../types-
|
|
3
|
-
import '../../fields-
|
|
2
|
+
import { e as SchemaDiff } from '../../types-d0yBwHoN.cjs';
|
|
3
|
+
import '../../fields-DBBm06VU.cjs';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../../permissions-ZHafVSIx.cjs';
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Ora } from 'ora';
|
|
2
|
-
import { e as SchemaDiff } from '../../types-
|
|
3
|
-
import '../../fields-
|
|
2
|
+
import { e as SchemaDiff } from '../../types-BWhwQxG-.js';
|
|
3
|
+
import '../../fields-DBBm06VU.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../../permissions-ZHafVSIx.js';
|
|
6
6
|
|
|
@@ -116,6 +116,15 @@ interface SelectFieldOptions {
|
|
|
116
116
|
*/
|
|
117
117
|
maxSelect?: number;
|
|
118
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Human-friendly byte size input.
|
|
121
|
+
*
|
|
122
|
+
* - Use a number for raw bytes (e.g. `5242880`)
|
|
123
|
+
* - Use a string with unit suffix for kibibytes/mebibytes/gibibytes (e.g. `"5M"`, `"1G"`)
|
|
124
|
+
*
|
|
125
|
+
* Supported suffixes: `K`, `M`, `G` (case-insensitive).
|
|
126
|
+
*/
|
|
127
|
+
type ByteSize = number | `${number}${"K" | "M" | "G" | "k" | "m" | "g"}`;
|
|
119
128
|
/**
|
|
120
129
|
* File field configuration options
|
|
121
130
|
*/
|
|
@@ -126,9 +135,19 @@ interface FileFieldOptions {
|
|
|
126
135
|
*/
|
|
127
136
|
mimeTypes?: string[];
|
|
128
137
|
/**
|
|
129
|
-
* Maximum file size
|
|
138
|
+
* Maximum file size.
|
|
139
|
+
*
|
|
140
|
+
* - Provide a number for raw bytes
|
|
141
|
+
* - Or use a string with `K`, `M`, `G` suffix (case-insensitive)
|
|
142
|
+
*
|
|
143
|
+
* Max allowed is `8G`.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* maxSize: 5242880
|
|
147
|
+
* maxSize: "5M"
|
|
148
|
+
* maxSize: "1G"
|
|
130
149
|
*/
|
|
131
|
-
maxSize?:
|
|
150
|
+
maxSize?: ByteSize;
|
|
132
151
|
/**
|
|
133
152
|
* Thumbnail sizes to generate
|
|
134
153
|
* Example: ["100x100", "200x200"]
|
|
@@ -299,29 +318,37 @@ declare function SelectField<T extends [string, ...string[]]>(values: T, options
|
|
|
299
318
|
* Maps to PocketBase 'file' field type with maxSelect=1
|
|
300
319
|
*
|
|
301
320
|
* @param options - Optional file constraints
|
|
302
|
-
* @returns Zod File
|
|
321
|
+
* @returns Zod schema that accepts File on input and returns string when reading from database
|
|
303
322
|
*
|
|
304
323
|
* @example
|
|
305
324
|
* const ProductSchema = z.object({
|
|
306
325
|
* thumbnail: FileField({ mimeTypes: ["image/*"], maxSize: 5242880 }),
|
|
307
326
|
* document: FileField({ mimeTypes: ["application/pdf"] }),
|
|
308
327
|
* });
|
|
328
|
+
*
|
|
329
|
+
* @remarks
|
|
330
|
+
* - When creating/updating records: accepts File objects
|
|
331
|
+
* - When reading from PocketBase: returns string (filename)
|
|
309
332
|
*/
|
|
310
|
-
declare function FileField(options?: FileFieldOptions): z.ZodType<File>;
|
|
333
|
+
declare function FileField(options?: FileFieldOptions): z.ZodType<string, z.ZodTypeDef, File | string>;
|
|
311
334
|
/**
|
|
312
335
|
* Creates a multiple files field schema
|
|
313
336
|
* Maps to PocketBase 'file' field type with maxSelect>1
|
|
314
337
|
*
|
|
315
338
|
* @param options - Optional file constraints
|
|
316
|
-
* @returns Zod array
|
|
339
|
+
* @returns Zod array schema that accepts File[] on input and returns string[] when reading from database
|
|
317
340
|
*
|
|
318
341
|
* @example
|
|
319
342
|
* const ProductSchema = z.object({
|
|
320
343
|
* images: FilesField({ mimeTypes: ["image/*"], maxSelect: 5 }),
|
|
321
344
|
* attachments: FilesField({ minSelect: 1, maxSelect: 10 }),
|
|
322
345
|
* });
|
|
346
|
+
*
|
|
347
|
+
* @remarks
|
|
348
|
+
* - When creating/updating records: accepts File[]
|
|
349
|
+
* - When reading from PocketBase: returns string[] (filenames)
|
|
323
350
|
*/
|
|
324
|
-
declare function FilesField(options?: FilesFieldOptions): z.
|
|
351
|
+
declare function FilesField(options?: FilesFieldOptions): z.ZodType<string[], z.ZodTypeDef, (File | string)[]>;
|
|
325
352
|
/**
|
|
326
353
|
* Creates a JSON field schema with optional inner schema validation
|
|
327
354
|
* Maps to PocketBase 'json' field type
|
|
@@ -362,4 +389,4 @@ declare function GeoPointField(): z.ZodObject<{
|
|
|
362
389
|
lat: z.ZodNumber;
|
|
363
390
|
}>;
|
|
364
391
|
|
|
365
|
-
export { type AutodateFieldOptions as A,
|
|
392
|
+
export { type AutodateFieldOptions as A, type ByteSize as B, type DateFieldOptions as D, EmailField as E, FIELD_METADATA_KEY as F, GeoPointField as G, JSONField as J, type NumberFieldOptions as N, type PocketBaseFieldType as P, type SelectFieldOptions as S, type TextFieldOptions as T, URLField as U, type FieldMetadata as a, type FileFieldOptions as b, type FilesFieldOptions as c, BoolField as d, extractFieldMetadata as e, NumberField as f, TextField as g, EditorField as h, DateField as i, AutodateField as j, SelectField as k, FileField as l, FilesField as m };
|
|
@@ -116,6 +116,15 @@ interface SelectFieldOptions {
|
|
|
116
116
|
*/
|
|
117
117
|
maxSelect?: number;
|
|
118
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Human-friendly byte size input.
|
|
121
|
+
*
|
|
122
|
+
* - Use a number for raw bytes (e.g. `5242880`)
|
|
123
|
+
* - Use a string with unit suffix for kibibytes/mebibytes/gibibytes (e.g. `"5M"`, `"1G"`)
|
|
124
|
+
*
|
|
125
|
+
* Supported suffixes: `K`, `M`, `G` (case-insensitive).
|
|
126
|
+
*/
|
|
127
|
+
type ByteSize = number | `${number}${"K" | "M" | "G" | "k" | "m" | "g"}`;
|
|
119
128
|
/**
|
|
120
129
|
* File field configuration options
|
|
121
130
|
*/
|
|
@@ -126,9 +135,19 @@ interface FileFieldOptions {
|
|
|
126
135
|
*/
|
|
127
136
|
mimeTypes?: string[];
|
|
128
137
|
/**
|
|
129
|
-
* Maximum file size
|
|
138
|
+
* Maximum file size.
|
|
139
|
+
*
|
|
140
|
+
* - Provide a number for raw bytes
|
|
141
|
+
* - Or use a string with `K`, `M`, `G` suffix (case-insensitive)
|
|
142
|
+
*
|
|
143
|
+
* Max allowed is `8G`.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* maxSize: 5242880
|
|
147
|
+
* maxSize: "5M"
|
|
148
|
+
* maxSize: "1G"
|
|
130
149
|
*/
|
|
131
|
-
maxSize?:
|
|
150
|
+
maxSize?: ByteSize;
|
|
132
151
|
/**
|
|
133
152
|
* Thumbnail sizes to generate
|
|
134
153
|
* Example: ["100x100", "200x200"]
|
|
@@ -299,29 +318,37 @@ declare function SelectField<T extends [string, ...string[]]>(values: T, options
|
|
|
299
318
|
* Maps to PocketBase 'file' field type with maxSelect=1
|
|
300
319
|
*
|
|
301
320
|
* @param options - Optional file constraints
|
|
302
|
-
* @returns Zod File
|
|
321
|
+
* @returns Zod schema that accepts File on input and returns string when reading from database
|
|
303
322
|
*
|
|
304
323
|
* @example
|
|
305
324
|
* const ProductSchema = z.object({
|
|
306
325
|
* thumbnail: FileField({ mimeTypes: ["image/*"], maxSize: 5242880 }),
|
|
307
326
|
* document: FileField({ mimeTypes: ["application/pdf"] }),
|
|
308
327
|
* });
|
|
328
|
+
*
|
|
329
|
+
* @remarks
|
|
330
|
+
* - When creating/updating records: accepts File objects
|
|
331
|
+
* - When reading from PocketBase: returns string (filename)
|
|
309
332
|
*/
|
|
310
|
-
declare function FileField(options?: FileFieldOptions): z.ZodType<File>;
|
|
333
|
+
declare function FileField(options?: FileFieldOptions): z.ZodType<string, z.ZodTypeDef, File | string>;
|
|
311
334
|
/**
|
|
312
335
|
* Creates a multiple files field schema
|
|
313
336
|
* Maps to PocketBase 'file' field type with maxSelect>1
|
|
314
337
|
*
|
|
315
338
|
* @param options - Optional file constraints
|
|
316
|
-
* @returns Zod array
|
|
339
|
+
* @returns Zod array schema that accepts File[] on input and returns string[] when reading from database
|
|
317
340
|
*
|
|
318
341
|
* @example
|
|
319
342
|
* const ProductSchema = z.object({
|
|
320
343
|
* images: FilesField({ mimeTypes: ["image/*"], maxSelect: 5 }),
|
|
321
344
|
* attachments: FilesField({ minSelect: 1, maxSelect: 10 }),
|
|
322
345
|
* });
|
|
346
|
+
*
|
|
347
|
+
* @remarks
|
|
348
|
+
* - When creating/updating records: accepts File[]
|
|
349
|
+
* - When reading from PocketBase: returns string[] (filenames)
|
|
323
350
|
*/
|
|
324
|
-
declare function FilesField(options?: FilesFieldOptions): z.
|
|
351
|
+
declare function FilesField(options?: FilesFieldOptions): z.ZodType<string[], z.ZodTypeDef, (File | string)[]>;
|
|
325
352
|
/**
|
|
326
353
|
* Creates a JSON field schema with optional inner schema validation
|
|
327
354
|
* Maps to PocketBase 'json' field type
|
|
@@ -362,4 +389,4 @@ declare function GeoPointField(): z.ZodObject<{
|
|
|
362
389
|
lat: z.ZodNumber;
|
|
363
390
|
}>;
|
|
364
391
|
|
|
365
|
-
export { type AutodateFieldOptions as A,
|
|
392
|
+
export { type AutodateFieldOptions as A, type ByteSize as B, type DateFieldOptions as D, EmailField as E, FIELD_METADATA_KEY as F, GeoPointField as G, JSONField as J, type NumberFieldOptions as N, type PocketBaseFieldType as P, type SelectFieldOptions as S, type TextFieldOptions as T, URLField as U, type FieldMetadata as a, type FileFieldOptions as b, type FilesFieldOptions as c, BoolField as d, extractFieldMetadata as e, NumberField as f, TextField as g, EditorField as h, DateField as i, AutodateField as j, SelectField as k, FileField as l, FilesField as m };
|
package/dist/index.cjs
CHANGED
|
@@ -488,6 +488,45 @@ function extractFieldMetadata(description) {
|
|
|
488
488
|
}
|
|
489
489
|
return null;
|
|
490
490
|
}
|
|
491
|
+
var MAX_FILE_SIZE_BYTES = 8 * 1024 * 1024 * 1024;
|
|
492
|
+
function parseByteSizeToBytes(value, context) {
|
|
493
|
+
let bytes;
|
|
494
|
+
if (typeof value === "number") {
|
|
495
|
+
if (!Number.isFinite(value)) {
|
|
496
|
+
throw new Error(`${context}: maxSize must be a finite number of bytes`);
|
|
497
|
+
}
|
|
498
|
+
bytes = Math.round(value);
|
|
499
|
+
} else {
|
|
500
|
+
const trimmed = value.trim();
|
|
501
|
+
const match = /^(\d+(?:\.\d+)?)\s*([KMG])$/i.exec(trimmed);
|
|
502
|
+
if (!match) {
|
|
503
|
+
throw new Error(`${context}: maxSize string must be like "10K", "5M", or "1G" (case-insensitive)`);
|
|
504
|
+
}
|
|
505
|
+
const amount = Number(match[1]);
|
|
506
|
+
const unit = match[2].toUpperCase();
|
|
507
|
+
if (!Number.isFinite(amount)) {
|
|
508
|
+
throw new Error(`${context}: maxSize must be a valid number`);
|
|
509
|
+
}
|
|
510
|
+
const multiplier = unit === "K" ? 1024 : unit === "M" ? 1024 * 1024 : 1024 * 1024 * 1024;
|
|
511
|
+
bytes = Math.round(amount * multiplier);
|
|
512
|
+
}
|
|
513
|
+
if (bytes < 0) {
|
|
514
|
+
throw new Error(`${context}: maxSize must be >= 0`);
|
|
515
|
+
}
|
|
516
|
+
if (bytes > MAX_FILE_SIZE_BYTES) {
|
|
517
|
+
throw new Error(`${context}: maxSize cannot exceed 8G (${MAX_FILE_SIZE_BYTES} bytes)`);
|
|
518
|
+
}
|
|
519
|
+
return bytes;
|
|
520
|
+
}
|
|
521
|
+
function normalizeFileFieldOptions(options, context) {
|
|
522
|
+
if (!options) return options;
|
|
523
|
+
if (options.maxSize === void 0) return options;
|
|
524
|
+
return {
|
|
525
|
+
...options,
|
|
526
|
+
// PocketBase expects bytes; normalize any human-friendly inputs to bytes here.
|
|
527
|
+
maxSize: parseByteSizeToBytes(options.maxSize, context)
|
|
528
|
+
};
|
|
529
|
+
}
|
|
491
530
|
function BoolField() {
|
|
492
531
|
const metadata = {
|
|
493
532
|
[FIELD_METADATA_KEY]: {
|
|
@@ -610,11 +649,14 @@ function SelectField(values, options) {
|
|
|
610
649
|
return enumSchema.describe(JSON.stringify(metadata));
|
|
611
650
|
}
|
|
612
651
|
function FileField(options) {
|
|
613
|
-
const schema = zod.z.
|
|
652
|
+
const schema = zod.z.preprocess((val) => {
|
|
653
|
+
return val instanceof File ? val.name || "" : val;
|
|
654
|
+
}, zod.z.string());
|
|
655
|
+
const normalizedOptions = normalizeFileFieldOptions(options, "FileField");
|
|
614
656
|
const metadata = {
|
|
615
657
|
[FIELD_METADATA_KEY]: {
|
|
616
658
|
type: "file",
|
|
617
|
-
options:
|
|
659
|
+
options: normalizedOptions || {}
|
|
618
660
|
}
|
|
619
661
|
};
|
|
620
662
|
return schema.describe(JSON.stringify(metadata));
|
|
@@ -625,17 +667,24 @@ function FilesField(options) {
|
|
|
625
667
|
throw new Error("FilesField: minSelect cannot be greater than maxSelect");
|
|
626
668
|
}
|
|
627
669
|
}
|
|
628
|
-
let
|
|
670
|
+
let baseArraySchema = zod.z.array(zod.z.string());
|
|
629
671
|
if (options?.minSelect !== void 0) {
|
|
630
|
-
|
|
672
|
+
baseArraySchema = baseArraySchema.min(options.minSelect);
|
|
631
673
|
}
|
|
632
674
|
if (options?.maxSelect !== void 0) {
|
|
633
|
-
|
|
675
|
+
baseArraySchema = baseArraySchema.max(options.maxSelect);
|
|
634
676
|
}
|
|
677
|
+
const schema = zod.z.preprocess((val) => {
|
|
678
|
+
if (Array.isArray(val)) {
|
|
679
|
+
return val.map((item) => item instanceof File ? item.name || "" : item);
|
|
680
|
+
}
|
|
681
|
+
return val;
|
|
682
|
+
}, baseArraySchema);
|
|
683
|
+
const normalizedOptions = normalizeFileFieldOptions(options, "FilesField");
|
|
635
684
|
const metadata = {
|
|
636
685
|
[FIELD_METADATA_KEY]: {
|
|
637
686
|
type: "file",
|
|
638
|
-
options:
|
|
687
|
+
options: normalizedOptions || {}
|
|
639
688
|
}
|
|
640
689
|
};
|
|
641
690
|
return schema.describe(JSON.stringify(metadata));
|
|
@@ -3799,10 +3848,19 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
3799
3848
|
collectionsToModify.push(modification);
|
|
3800
3849
|
}
|
|
3801
3850
|
}
|
|
3851
|
+
const existingCollectionIds = /* @__PURE__ */ new Map();
|
|
3852
|
+
if (previousSnapshot) {
|
|
3853
|
+
for (const [name, collection] of previousSnapshot.collections) {
|
|
3854
|
+
if (collection.id) {
|
|
3855
|
+
existingCollectionIds.set(name, collection.id);
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3802
3859
|
return {
|
|
3803
3860
|
collectionsToCreate: collectionsWithIds,
|
|
3804
3861
|
collectionsToDelete: filteredCollectionsToDelete,
|
|
3805
|
-
collectionsToModify
|
|
3862
|
+
collectionsToModify,
|
|
3863
|
+
existingCollectionIds
|
|
3806
3864
|
};
|
|
3807
3865
|
}
|
|
3808
3866
|
function detectDestructiveChanges(diff, config) {
|
|
@@ -4195,7 +4253,7 @@ function formatValue(value) {
|
|
|
4195
4253
|
return JSON.stringify(value).replace(/","/g, '", "');
|
|
4196
4254
|
}
|
|
4197
4255
|
if (typeof value === "object") {
|
|
4198
|
-
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
4256
|
+
const entries = Object.entries(value).filter(([_k, v]) => v !== void 0).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
4199
4257
|
return `{ ${entries} }`;
|
|
4200
4258
|
}
|
|
4201
4259
|
return String(value);
|
|
@@ -4458,7 +4516,7 @@ function generateFieldAddition(collectionName, field, varName, isLast = false, c
|
|
|
4458
4516
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4459
4517
|
return lines.join("\n");
|
|
4460
4518
|
}
|
|
4461
|
-
function generateFieldModification(collectionName, modification, varName, isLast = false) {
|
|
4519
|
+
function generateFieldModification(collectionName, modification, varName, isLast = false, collectionIdMap) {
|
|
4462
4520
|
const lines = [];
|
|
4463
4521
|
const collectionVar = varName || `collection_${collectionName}_${modification.fieldName}`;
|
|
4464
4522
|
const fieldVar = `${collectionVar}_field`;
|
|
@@ -4473,7 +4531,14 @@ function generateFieldModification(collectionName, modification, varName, isLast
|
|
|
4473
4531
|
const relationKey = change.property.replace("relation.", "");
|
|
4474
4532
|
if (relationKey === "collection") {
|
|
4475
4533
|
const isUsersCollection = String(change.newValue).toLowerCase() === "users";
|
|
4476
|
-
|
|
4534
|
+
let collectionIdValue;
|
|
4535
|
+
if (isUsersCollection) {
|
|
4536
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
4537
|
+
} else if (collectionIdMap && collectionIdMap.has(String(change.newValue))) {
|
|
4538
|
+
collectionIdValue = `"${collectionIdMap.get(String(change.newValue))}"`;
|
|
4539
|
+
} else {
|
|
4540
|
+
collectionIdValue = `app.findCollectionByNameOrId("${change.newValue}").id`;
|
|
4541
|
+
}
|
|
4477
4542
|
lines.push(` ${fieldVar}.collectionId = ${collectionIdValue};`);
|
|
4478
4543
|
} else {
|
|
4479
4544
|
lines.push(` ${fieldVar}.${relationKey} = ${formatValue(change.newValue)};`);
|
|
@@ -4489,11 +4554,9 @@ function generateFieldModification(collectionName, modification, varName, isLast
|
|
|
4489
4554
|
function generateFieldDeletion(collectionName, fieldName, varName, isLast = false) {
|
|
4490
4555
|
const lines = [];
|
|
4491
4556
|
const collectionVar = varName || `collection_${collectionName}_${fieldName}`;
|
|
4492
|
-
const fieldVar = `${collectionVar}_field`;
|
|
4493
4557
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4494
|
-
lines.push(` const ${fieldVar} = ${collectionVar}.fields.getByName("${fieldName}");`);
|
|
4495
4558
|
lines.push(``);
|
|
4496
|
-
lines.push(` ${collectionVar}.fields.
|
|
4559
|
+
lines.push(` ${collectionVar}.fields.removeByName("${fieldName}");`);
|
|
4497
4560
|
lines.push(``);
|
|
4498
4561
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4499
4562
|
return lines.join("\n");
|
|
@@ -4551,9 +4614,10 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4551
4614
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4552
4615
|
let operationCount = 0;
|
|
4553
4616
|
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
4554
|
-
for (
|
|
4617
|
+
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
4618
|
+
const field = modification.fieldsToAdd[i];
|
|
4555
4619
|
operationCount++;
|
|
4556
|
-
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
4620
|
+
const varName = `collection_${collectionName}_add_${field.name}_${i}`;
|
|
4557
4621
|
const isLast = operationCount === totalOperations;
|
|
4558
4622
|
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
4559
4623
|
if (!isLast) lines.push("");
|
|
@@ -4562,7 +4626,7 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4562
4626
|
operationCount++;
|
|
4563
4627
|
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
4564
4628
|
const isLast = operationCount === totalOperations;
|
|
4565
|
-
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
|
|
4629
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast, collectionIdMap));
|
|
4566
4630
|
if (!isLast) lines.push("");
|
|
4567
4631
|
}
|
|
4568
4632
|
for (const field of modification.fieldsToRemove) {
|
|
@@ -4611,20 +4675,23 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4611
4675
|
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
4612
4676
|
}
|
|
4613
4677
|
let code = lines.join("\n");
|
|
4614
|
-
const
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
if (
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4678
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
4679
|
+
if (!hasReturnStatement) {
|
|
4680
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
4681
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
4682
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
4683
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
4684
|
+
const allMatches = [
|
|
4685
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
4686
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
4687
|
+
].sort((a, b) => b.index - a.index);
|
|
4688
|
+
if (allMatches.length > 0) {
|
|
4689
|
+
const lastMatch = allMatches[0];
|
|
4690
|
+
if (lastMatch.type === "save") {
|
|
4691
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4692
|
+
} else {
|
|
4693
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4694
|
+
}
|
|
4628
4695
|
}
|
|
4629
4696
|
}
|
|
4630
4697
|
return code;
|
|
@@ -4713,20 +4780,23 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
4713
4780
|
}
|
|
4714
4781
|
}
|
|
4715
4782
|
let code = lines.join("\n");
|
|
4716
|
-
const
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
if (
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4783
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
4784
|
+
if (!hasReturnStatement) {
|
|
4785
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
4786
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
4787
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
4788
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
4789
|
+
const allMatches = [
|
|
4790
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
4791
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
4792
|
+
].sort((a, b) => b.index - a.index);
|
|
4793
|
+
if (allMatches.length > 0) {
|
|
4794
|
+
const lastMatch = allMatches[0];
|
|
4795
|
+
if (lastMatch.type === "save") {
|
|
4796
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4797
|
+
} else {
|
|
4798
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4799
|
+
}
|
|
4730
4800
|
}
|
|
4731
4801
|
}
|
|
4732
4802
|
return code;
|
|
@@ -4741,6 +4811,11 @@ function generateUpMigration(diff) {
|
|
|
4741
4811
|
collectionIdMap.set(collection.name, collection.id);
|
|
4742
4812
|
}
|
|
4743
4813
|
}
|
|
4814
|
+
if (diff.existingCollectionIds) {
|
|
4815
|
+
for (const [name, id] of diff.existingCollectionIds) {
|
|
4816
|
+
collectionIdMap.set(name, id);
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4744
4819
|
if (diff.collectionsToCreate.length > 0) {
|
|
4745
4820
|
lines.push(` // Create new collections`);
|
|
4746
4821
|
for (let i = 0; i < diff.collectionsToCreate.length; i++) {
|
|
@@ -4756,8 +4831,9 @@ function generateUpMigration(diff) {
|
|
|
4756
4831
|
const collectionName = modification.collection;
|
|
4757
4832
|
if (modification.fieldsToAdd.length > 0) {
|
|
4758
4833
|
lines.push(` // Add fields to ${collectionName}`);
|
|
4759
|
-
for (
|
|
4760
|
-
const
|
|
4834
|
+
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
4835
|
+
const field = modification.fieldsToAdd[i];
|
|
4836
|
+
const varName = `collection_${collectionName}_add_${field.name}_${i}`;
|
|
4761
4837
|
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
4762
4838
|
lines.push(``);
|
|
4763
4839
|
}
|
|
@@ -4766,7 +4842,7 @@ function generateUpMigration(diff) {
|
|
|
4766
4842
|
lines.push(` // Modify fields in ${collectionName}`);
|
|
4767
4843
|
for (const fieldMod of modification.fieldsToModify) {
|
|
4768
4844
|
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
4769
|
-
lines.push(generateFieldModification(collectionName, fieldMod, varName));
|
|
4845
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, false, collectionIdMap));
|
|
4770
4846
|
lines.push(``);
|
|
4771
4847
|
}
|
|
4772
4848
|
}
|
|
@@ -4827,20 +4903,23 @@ function generateUpMigration(diff) {
|
|
|
4827
4903
|
lines.push(``);
|
|
4828
4904
|
}
|
|
4829
4905
|
let code = lines.join("\n");
|
|
4830
|
-
const
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
if (
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4906
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
4907
|
+
if (!hasReturnStatement) {
|
|
4908
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
4909
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
4910
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
4911
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
4912
|
+
const allMatches = [
|
|
4913
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
4914
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
4915
|
+
].sort((a, b) => b.index - a.index);
|
|
4916
|
+
if (allMatches.length > 0) {
|
|
4917
|
+
const lastMatch = allMatches[0];
|
|
4918
|
+
if (lastMatch.type === "save") {
|
|
4919
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4920
|
+
} else {
|
|
4921
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4922
|
+
}
|
|
4844
4923
|
}
|
|
4845
4924
|
}
|
|
4846
4925
|
return code;
|
|
@@ -4860,6 +4939,11 @@ function generateDownMigration(diff) {
|
|
|
4860
4939
|
collectionIdMap.set(collection.name, collection.id);
|
|
4861
4940
|
}
|
|
4862
4941
|
}
|
|
4942
|
+
if (diff.existingCollectionIds) {
|
|
4943
|
+
for (const [name, id] of diff.existingCollectionIds) {
|
|
4944
|
+
collectionIdMap.set(name, id);
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4863
4947
|
if (diff.collectionsToDelete.length > 0) {
|
|
4864
4948
|
lines.push(` // Recreate deleted collections`);
|
|
4865
4949
|
for (let i = 0; i < diff.collectionsToDelete.length; i++) {
|
|
@@ -4957,20 +5041,23 @@ function generateDownMigration(diff) {
|
|
|
4957
5041
|
lines.push(``);
|
|
4958
5042
|
}
|
|
4959
5043
|
let code = lines.join("\n");
|
|
4960
|
-
const
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
if (
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
5044
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
5045
|
+
if (!hasReturnStatement) {
|
|
5046
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
5047
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
5048
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
5049
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
5050
|
+
const allMatches = [
|
|
5051
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
5052
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
5053
|
+
].sort((a, b) => b.index - a.index);
|
|
5054
|
+
if (allMatches.length > 0) {
|
|
5055
|
+
const lastMatch = allMatches[0];
|
|
5056
|
+
if (lastMatch.type === "save") {
|
|
5057
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
5058
|
+
} else {
|
|
5059
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
5060
|
+
}
|
|
4974
5061
|
}
|
|
4975
5062
|
}
|
|
4976
5063
|
return code;
|
|
@@ -4994,6 +5081,11 @@ function generate(diff, config) {
|
|
|
4994
5081
|
collectionIdMap.set(collection.name, collection.id);
|
|
4995
5082
|
}
|
|
4996
5083
|
}
|
|
5084
|
+
if (diff.existingCollectionIds) {
|
|
5085
|
+
for (const [name, id] of diff.existingCollectionIds) {
|
|
5086
|
+
collectionIdMap.set(name, id);
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
4997
5089
|
const baseTimestamp = generateTimestamp(normalizedConfig);
|
|
4998
5090
|
const operations = splitDiffByCollection(diff, baseTimestamp);
|
|
4999
5091
|
const filePaths = [];
|