@blinkk/root-cms 3.0.1-alpha.0 → 3.0.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +12 -6
- package/dist/chunk-ATPWU3CU.js +921 -0
- package/dist/chunk-CRK7N6RR.js +298 -0
- package/dist/{chunk-YMUZ5H5C.js → chunk-F4SODS5S.js} +108 -297
- package/dist/{chunk-MSJGHSR6.js → chunk-MAZA5B27.js} +23 -27
- package/dist/chunk-TRM4MQHU.js +1180 -0
- package/dist/{chunk-KDXHFMIH.js → chunk-XLX37FRL.js} +3 -0
- package/dist/cli.js +3 -2
- package/dist/{client-cP6yMgT8.d.ts → client-1puwLgNx.d.ts} +317 -24
- package/dist/client.d.ts +2 -2
- package/dist/client.js +2 -1
- package/dist/core.d.ts +3 -3
- package/dist/core.js +8 -1
- package/dist/functions.js +3 -2
- package/dist/{generate-types-MHWSSOWV.js → generate-types-SPV7I3A5.js} +1 -1
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.js +369 -79
- package/dist/project.d.ts +16 -3
- package/dist/project.js +3 -1
- package/dist/richtext.d.ts +25 -18
- package/dist/richtext.js +98 -43
- package/dist/{schema-D7MOj-YC.d.ts → schema-Db_xODoi.d.ts} +66 -1
- package/dist/ui/signin.css +1 -1
- package/dist/ui/signin.js +3 -3
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +259 -175
- package/dist/ui/ui.js.LEGAL.txt +16 -3
- package/package.json +12 -8
- package/dist/ai-OZY3JXDH.js +0 -19
- package/dist/altText-RDKJNVGH.js +0 -7
- package/dist/chunk-H6ZKML2S.js +0 -157
- package/dist/chunk-N4Z3O53K.js +0 -191
- package/dist/chunk-T5UK2H24.js +0 -419
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
validateFields
|
|
3
|
+
} from "./chunk-CRK7N6RR.js";
|
|
4
|
+
|
|
1
5
|
// core/client.ts
|
|
2
6
|
import crypto from "crypto";
|
|
3
7
|
import {
|
|
@@ -358,301 +362,6 @@ function buildTranslationsLocaleDocDbPath(options) {
|
|
|
358
362
|
).replace("{mode}", options.mode).replace("{id}", normalizeSlug(options.id)).replace("{locale}", options.locale);
|
|
359
363
|
}
|
|
360
364
|
|
|
361
|
-
// core/validation.ts
|
|
362
|
-
function validateFields(fieldsData, schema) {
|
|
363
|
-
if (fieldsData === null || fieldsData === void 0) {
|
|
364
|
-
return [];
|
|
365
|
-
}
|
|
366
|
-
if (typeof fieldsData !== "object" || Array.isArray(fieldsData)) {
|
|
367
|
-
return [
|
|
368
|
-
{
|
|
369
|
-
path: "",
|
|
370
|
-
message: "Expected object for fields data",
|
|
371
|
-
expected: "object",
|
|
372
|
-
received: getType(fieldsData)
|
|
373
|
-
}
|
|
374
|
-
];
|
|
375
|
-
}
|
|
376
|
-
const errors = [];
|
|
377
|
-
for (const field of schema.fields) {
|
|
378
|
-
if (!field.id) {
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
381
|
-
if (!(field.id in fieldsData)) {
|
|
382
|
-
continue;
|
|
383
|
-
}
|
|
384
|
-
const value = fieldsData[field.id];
|
|
385
|
-
errors.push(...validateValue(value, field, field.id));
|
|
386
|
-
}
|
|
387
|
-
return errors;
|
|
388
|
-
}
|
|
389
|
-
function validateValue(value, field, path) {
|
|
390
|
-
if (value === void 0) {
|
|
391
|
-
return [];
|
|
392
|
-
}
|
|
393
|
-
switch (field.type) {
|
|
394
|
-
case "string":
|
|
395
|
-
case "select":
|
|
396
|
-
if (typeof value !== "string") {
|
|
397
|
-
return [createError(path, "string", value)];
|
|
398
|
-
}
|
|
399
|
-
return [];
|
|
400
|
-
case "number":
|
|
401
|
-
if (typeof value !== "number") {
|
|
402
|
-
return [createError(path, "number", value)];
|
|
403
|
-
}
|
|
404
|
-
if (isNaN(value)) {
|
|
405
|
-
return [createError(path, "number", value)];
|
|
406
|
-
}
|
|
407
|
-
return [];
|
|
408
|
-
case "boolean":
|
|
409
|
-
if (typeof value !== "boolean") {
|
|
410
|
-
return [createError(path, "boolean", value)];
|
|
411
|
-
}
|
|
412
|
-
return [];
|
|
413
|
-
case "date":
|
|
414
|
-
case "datetime": {
|
|
415
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
416
|
-
return [createError(path, "object", value)];
|
|
417
|
-
}
|
|
418
|
-
const errors = [];
|
|
419
|
-
const seconds = value.seconds;
|
|
420
|
-
const nanoseconds = value.nanoseconds;
|
|
421
|
-
if (seconds === void 0) {
|
|
422
|
-
errors.push({
|
|
423
|
-
path: `${path}.seconds`,
|
|
424
|
-
message: "Required",
|
|
425
|
-
expected: "number",
|
|
426
|
-
received: "undefined"
|
|
427
|
-
});
|
|
428
|
-
} else if (typeof seconds !== "number") {
|
|
429
|
-
errors.push(createError(`${path}.seconds`, "number", seconds));
|
|
430
|
-
}
|
|
431
|
-
if (nanoseconds === void 0) {
|
|
432
|
-
errors.push({
|
|
433
|
-
path: `${path}.nanoseconds`,
|
|
434
|
-
message: "Required",
|
|
435
|
-
expected: "number",
|
|
436
|
-
received: "undefined"
|
|
437
|
-
});
|
|
438
|
-
} else if (typeof nanoseconds !== "number") {
|
|
439
|
-
errors.push(createError(`${path}.nanoseconds`, "number", nanoseconds));
|
|
440
|
-
}
|
|
441
|
-
return errors;
|
|
442
|
-
}
|
|
443
|
-
case "multiselect":
|
|
444
|
-
if (!Array.isArray(value)) {
|
|
445
|
-
return [createError(path, "array", value)];
|
|
446
|
-
}
|
|
447
|
-
return value.flatMap((item, index) => {
|
|
448
|
-
if (typeof item !== "string") {
|
|
449
|
-
return [createError(`${path}.${index}`, "string", item)];
|
|
450
|
-
}
|
|
451
|
-
return [];
|
|
452
|
-
});
|
|
453
|
-
case "image":
|
|
454
|
-
case "file": {
|
|
455
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
456
|
-
return [createError(path, "object", value)];
|
|
457
|
-
}
|
|
458
|
-
const errors = [];
|
|
459
|
-
if (value.src === void 0) {
|
|
460
|
-
errors.push({
|
|
461
|
-
path: `${path}.src`,
|
|
462
|
-
message: "Required",
|
|
463
|
-
expected: "string",
|
|
464
|
-
received: "undefined"
|
|
465
|
-
});
|
|
466
|
-
} else if (typeof value.src !== "string") {
|
|
467
|
-
errors.push(createError(`${path}.src`, "string", value.src));
|
|
468
|
-
}
|
|
469
|
-
if (value.alt !== void 0 && typeof value.alt !== "string") {
|
|
470
|
-
errors.push(createError(`${path}.alt`, "string", value.alt));
|
|
471
|
-
}
|
|
472
|
-
return errors;
|
|
473
|
-
}
|
|
474
|
-
case "object": {
|
|
475
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
476
|
-
return [createError(path, "object", value)];
|
|
477
|
-
}
|
|
478
|
-
const objectField = field;
|
|
479
|
-
const errors = [];
|
|
480
|
-
for (const nestedField of objectField.fields) {
|
|
481
|
-
if (!nestedField.id || !(nestedField.id in value)) {
|
|
482
|
-
continue;
|
|
483
|
-
}
|
|
484
|
-
errors.push(
|
|
485
|
-
...validateValue(
|
|
486
|
-
value[nestedField.id],
|
|
487
|
-
nestedField,
|
|
488
|
-
`${path}.${nestedField.id}`
|
|
489
|
-
)
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
return errors;
|
|
493
|
-
}
|
|
494
|
-
case "array": {
|
|
495
|
-
if (!Array.isArray(value)) {
|
|
496
|
-
return [createError(path, "array", value)];
|
|
497
|
-
}
|
|
498
|
-
const arrayField = field;
|
|
499
|
-
const itemField = arrayField.of;
|
|
500
|
-
return value.flatMap((item, index) => {
|
|
501
|
-
return validateValue(item, itemField, `${path}.${index}`);
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
case "oneof": {
|
|
505
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
506
|
-
return [createError(path, "object", value)];
|
|
507
|
-
}
|
|
508
|
-
const oneOfField = field;
|
|
509
|
-
const typeName = value._type;
|
|
510
|
-
const typeMap = /* @__PURE__ */ new Map();
|
|
511
|
-
const typeNames = [];
|
|
512
|
-
for (const type of oneOfField.types) {
|
|
513
|
-
if (typeof type === "string") {
|
|
514
|
-
typeNames.push(type);
|
|
515
|
-
continue;
|
|
516
|
-
}
|
|
517
|
-
typeMap.set(type.name, type);
|
|
518
|
-
typeNames.push(type.name);
|
|
519
|
-
}
|
|
520
|
-
if (!typeNames.includes(typeName)) {
|
|
521
|
-
const expectedStr = typeNames.map((t) => `'${t}'`).join(" | ");
|
|
522
|
-
return [
|
|
523
|
-
{
|
|
524
|
-
path: `${path}._type`,
|
|
525
|
-
message: `Invalid discriminator value. Expected ${expectedStr}`,
|
|
526
|
-
expected: "valid discriminator value",
|
|
527
|
-
received: typeName
|
|
528
|
-
}
|
|
529
|
-
];
|
|
530
|
-
}
|
|
531
|
-
const matchedSchema = typeMap.get(typeName);
|
|
532
|
-
if (!matchedSchema) {
|
|
533
|
-
return [];
|
|
534
|
-
}
|
|
535
|
-
const errors = [];
|
|
536
|
-
for (const nestedField of matchedSchema.fields) {
|
|
537
|
-
if (!nestedField.id || !(nestedField.id in value)) {
|
|
538
|
-
continue;
|
|
539
|
-
}
|
|
540
|
-
errors.push(
|
|
541
|
-
...validateValue(
|
|
542
|
-
value[nestedField.id],
|
|
543
|
-
nestedField,
|
|
544
|
-
`${path}.${nestedField.id}`
|
|
545
|
-
)
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
return errors;
|
|
549
|
-
}
|
|
550
|
-
case "richtext": {
|
|
551
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
552
|
-
return [createError(path, "object", value)];
|
|
553
|
-
}
|
|
554
|
-
const errors = [];
|
|
555
|
-
if (value.blocks === void 0) {
|
|
556
|
-
errors.push({
|
|
557
|
-
path: `${path}.blocks`,
|
|
558
|
-
message: "Required",
|
|
559
|
-
expected: "array",
|
|
560
|
-
received: "undefined"
|
|
561
|
-
});
|
|
562
|
-
} else if (!Array.isArray(value.blocks)) {
|
|
563
|
-
errors.push(createError(`${path}.blocks`, "array", value.blocks));
|
|
564
|
-
} else {
|
|
565
|
-
value.blocks.forEach((block, index) => {
|
|
566
|
-
if (typeof block !== "object" || block === null) {
|
|
567
|
-
errors.push(
|
|
568
|
-
createError(`${path}.blocks.${index}`, "object", block)
|
|
569
|
-
);
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
if (block.type === void 0) {
|
|
573
|
-
errors.push({
|
|
574
|
-
path: `${path}.blocks.${index}.type`,
|
|
575
|
-
message: "Required",
|
|
576
|
-
expected: "string",
|
|
577
|
-
received: "undefined"
|
|
578
|
-
});
|
|
579
|
-
} else if (typeof block.type !== "string") {
|
|
580
|
-
errors.push(
|
|
581
|
-
createError(`${path}.blocks.${index}.type`, "string", block.type)
|
|
582
|
-
);
|
|
583
|
-
}
|
|
584
|
-
});
|
|
585
|
-
}
|
|
586
|
-
return errors;
|
|
587
|
-
}
|
|
588
|
-
case "reference": {
|
|
589
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
590
|
-
return [createError(path, "object", value)];
|
|
591
|
-
}
|
|
592
|
-
const errors = [];
|
|
593
|
-
const requiredFields = ["id", "collection", "slug"];
|
|
594
|
-
for (const req of requiredFields) {
|
|
595
|
-
if (value[req] === void 0) {
|
|
596
|
-
errors.push({
|
|
597
|
-
path: `${path}.${req}`,
|
|
598
|
-
message: "Required",
|
|
599
|
-
expected: "string",
|
|
600
|
-
received: "undefined"
|
|
601
|
-
});
|
|
602
|
-
} else if (typeof value[req] !== "string") {
|
|
603
|
-
errors.push(createError(`${path}.${req}`, "string", value[req]));
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
return errors;
|
|
607
|
-
}
|
|
608
|
-
case "references": {
|
|
609
|
-
if (!Array.isArray(value)) {
|
|
610
|
-
return [createError(path, "array", value)];
|
|
611
|
-
}
|
|
612
|
-
return value.flatMap((item, index) => {
|
|
613
|
-
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
614
|
-
return [createError(`${path}.${index}`, "object", item)];
|
|
615
|
-
}
|
|
616
|
-
const errors = [];
|
|
617
|
-
const requiredFields = ["id", "collection", "slug"];
|
|
618
|
-
for (const req of requiredFields) {
|
|
619
|
-
if (item[req] === void 0) {
|
|
620
|
-
errors.push({
|
|
621
|
-
path: `${path}.${index}.${req}`,
|
|
622
|
-
message: "Required",
|
|
623
|
-
expected: "string",
|
|
624
|
-
received: "undefined"
|
|
625
|
-
});
|
|
626
|
-
} else if (typeof item[req] !== "string") {
|
|
627
|
-
errors.push(
|
|
628
|
-
createError(`${path}.${index}.${req}`, "string", item[req])
|
|
629
|
-
);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
return errors;
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
default:
|
|
636
|
-
console.warn(`Unknown field type: ${field.type}`);
|
|
637
|
-
return [];
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
function getType(value) {
|
|
641
|
-
if (value === null) return "null";
|
|
642
|
-
if (Array.isArray(value)) return "array";
|
|
643
|
-
if (typeof value === "number" && Number.isNaN(value)) return "nan";
|
|
644
|
-
return typeof value;
|
|
645
|
-
}
|
|
646
|
-
function createError(path, expected, receivedValue) {
|
|
647
|
-
const received = getType(receivedValue);
|
|
648
|
-
return {
|
|
649
|
-
path,
|
|
650
|
-
message: `Expected ${expected}, received ${received}`,
|
|
651
|
-
expected,
|
|
652
|
-
received
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
|
|
656
365
|
// core/values.ts
|
|
657
366
|
function setValueAtPath(obj, path, value) {
|
|
658
367
|
const keys = path.split(".");
|
|
@@ -1501,10 +1210,41 @@ ${errorMessages}`);
|
|
|
1501
1210
|
const docRef = this.db.doc(dbPath);
|
|
1502
1211
|
const doc = await docRef.get();
|
|
1503
1212
|
if (doc.exists) {
|
|
1504
|
-
|
|
1213
|
+
const dataSource = doc.data();
|
|
1214
|
+
if (dataSource.archivedAt) {
|
|
1215
|
+
console.warn(
|
|
1216
|
+
`warning: data source "${dataSourceId}" is archived` + (dataSource.archivedBy ? ` (archived by ${dataSource.archivedBy})` : "")
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
return dataSource;
|
|
1505
1220
|
}
|
|
1506
1221
|
return null;
|
|
1507
1222
|
}
|
|
1223
|
+
/**
|
|
1224
|
+
* Archives a data source. Archived data sources cannot be synced or published.
|
|
1225
|
+
*/
|
|
1226
|
+
async archiveDataSource(dataSourceId, options) {
|
|
1227
|
+
const dbPath = `Projects/${this.projectId}/DataSources/${dataSourceId}`;
|
|
1228
|
+
const docRef = this.db.doc(dbPath);
|
|
1229
|
+
const archivedBy = options?.archivedBy || "root-cms-client";
|
|
1230
|
+
await docRef.update({
|
|
1231
|
+
archivedAt: Timestamp2.now(),
|
|
1232
|
+
archivedBy
|
|
1233
|
+
});
|
|
1234
|
+
console.log(`archived data source: ${dataSourceId}`);
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Unarchives a data source.
|
|
1238
|
+
*/
|
|
1239
|
+
async unarchiveDataSource(dataSourceId) {
|
|
1240
|
+
const dbPath = `Projects/${this.projectId}/DataSources/${dataSourceId}`;
|
|
1241
|
+
const docRef = this.db.doc(dbPath);
|
|
1242
|
+
await docRef.update({
|
|
1243
|
+
archivedAt: FieldValue2.delete(),
|
|
1244
|
+
archivedBy: FieldValue2.delete()
|
|
1245
|
+
});
|
|
1246
|
+
console.log(`unarchived data source: ${dataSourceId}`);
|
|
1247
|
+
}
|
|
1508
1248
|
/**
|
|
1509
1249
|
* Syncs a data source to draft state.
|
|
1510
1250
|
*/
|
|
@@ -1513,6 +1253,9 @@ ${errorMessages}`);
|
|
|
1513
1253
|
if (!dataSource) {
|
|
1514
1254
|
throw new Error(`data source not found: ${dataSourceId}`);
|
|
1515
1255
|
}
|
|
1256
|
+
if (dataSource.archivedAt) {
|
|
1257
|
+
throw new Error(`data source is archived: ${dataSourceId}`);
|
|
1258
|
+
}
|
|
1516
1259
|
const result = await this.fetchData(dataSource);
|
|
1517
1260
|
const dataSourceDocRef = this.db.doc(
|
|
1518
1261
|
`Projects/${this.projectId}/DataSources/${dataSourceId}`
|
|
@@ -1545,6 +1288,9 @@ ${errorMessages}`);
|
|
|
1545
1288
|
if (!dataSource) {
|
|
1546
1289
|
throw new Error(`data source not found: ${dataSourceId}`);
|
|
1547
1290
|
}
|
|
1291
|
+
if (dataSource.archivedAt) {
|
|
1292
|
+
throw new Error(`data source is archived: ${dataSourceId}`);
|
|
1293
|
+
}
|
|
1548
1294
|
const dataSourceDocRef = this.db.doc(
|
|
1549
1295
|
`Projects/${this.projectId}/DataSources/${dataSourceId}`
|
|
1550
1296
|
);
|
|
@@ -1578,6 +1324,40 @@ ${errorMessages}`);
|
|
|
1578
1324
|
console.log(`published data ${dataSourceId}`);
|
|
1579
1325
|
console.log(`published by: ${publishedBy}`);
|
|
1580
1326
|
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Unpublishes a data source. Removes the `publishedAt`/`publishedBy`
|
|
1329
|
+
* metadata from the DataSource doc and deletes the `Data/published` doc.
|
|
1330
|
+
*/
|
|
1331
|
+
async unpublishDataSource(dataSourceId) {
|
|
1332
|
+
const dataSource = await this.getDataSource(dataSourceId);
|
|
1333
|
+
if (!dataSource) {
|
|
1334
|
+
throw new Error(`data source not found: ${dataSourceId}`);
|
|
1335
|
+
}
|
|
1336
|
+
const dataSourceDocRef = this.db.doc(
|
|
1337
|
+
`Projects/${this.projectId}/DataSources/${dataSourceId}`
|
|
1338
|
+
);
|
|
1339
|
+
const dataDocRefDraft = this.db.doc(
|
|
1340
|
+
`Projects/${this.projectId}/DataSources/${dataSourceId}/Data/draft`
|
|
1341
|
+
);
|
|
1342
|
+
const dataDocRefPublished = this.db.doc(
|
|
1343
|
+
`Projects/${this.projectId}/DataSources/${dataSourceId}/Data/published`
|
|
1344
|
+
);
|
|
1345
|
+
const batch = this.db.batch();
|
|
1346
|
+
batch.update(dataSourceDocRef, {
|
|
1347
|
+
publishedAt: FieldValue2.delete(),
|
|
1348
|
+
publishedBy: FieldValue2.delete()
|
|
1349
|
+
});
|
|
1350
|
+
const draftSnapshot = await dataDocRefDraft.get();
|
|
1351
|
+
if (draftSnapshot.exists) {
|
|
1352
|
+
batch.update(dataDocRefDraft, {
|
|
1353
|
+
"dataSource.publishedAt": FieldValue2.delete(),
|
|
1354
|
+
"dataSource.publishedBy": FieldValue2.delete()
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
batch.delete(dataDocRefPublished);
|
|
1358
|
+
await batch.commit();
|
|
1359
|
+
console.log(`unpublished data source: ${dataSourceId}`);
|
|
1360
|
+
}
|
|
1581
1361
|
async publishDataSources(dataSourceIds, options) {
|
|
1582
1362
|
const publishedBy = options?.publishedBy || "root-cms-client";
|
|
1583
1363
|
const batch = options?.batch || this.db.batch();
|
|
@@ -1586,6 +1366,9 @@ ${errorMessages}`);
|
|
|
1586
1366
|
if (!dataSource) {
|
|
1587
1367
|
throw new Error(`data source not found: ${id}`);
|
|
1588
1368
|
}
|
|
1369
|
+
if (dataSource.archivedAt) {
|
|
1370
|
+
throw new Error(`data source is archived: ${id}`);
|
|
1371
|
+
}
|
|
1589
1372
|
const dataSourceDocRef = this.db.doc(
|
|
1590
1373
|
`Projects/${this.projectId}/DataSources/${id}`
|
|
1591
1374
|
);
|
|
@@ -1751,7 +1534,14 @@ ${errorMessages}`);
|
|
|
1751
1534
|
const docRef = this.dbDataSourceDataRef(dataSourceId, { mode });
|
|
1752
1535
|
const doc = await docRef.get();
|
|
1753
1536
|
if (doc.exists) {
|
|
1754
|
-
|
|
1537
|
+
const dataSourceData = doc.data();
|
|
1538
|
+
if (dataSourceData.dataSource?.archivedAt) {
|
|
1539
|
+
const archivedBy = dataSourceData.dataSource.archivedBy;
|
|
1540
|
+
console.warn(
|
|
1541
|
+
`warning: data source "${dataSourceId}" is archived` + (archivedBy ? ` (archived by ${archivedBy})` : "")
|
|
1542
|
+
);
|
|
1543
|
+
}
|
|
1544
|
+
return dataSourceData;
|
|
1755
1545
|
}
|
|
1756
1546
|
return null;
|
|
1757
1547
|
}
|
|
@@ -1866,6 +1656,27 @@ ${errorMessages}`);
|
|
|
1866
1656
|
console.error(err);
|
|
1867
1657
|
}
|
|
1868
1658
|
}
|
|
1659
|
+
const notifications = cmsPluginConfig.notifications;
|
|
1660
|
+
if (notifications && notifications.length > 0) {
|
|
1661
|
+
const ctx = {
|
|
1662
|
+
rootConfig: this.rootConfig,
|
|
1663
|
+
cmsClient: this,
|
|
1664
|
+
user: data.by ? { email: data.by } : void 0
|
|
1665
|
+
};
|
|
1666
|
+
for (const service of notifications) {
|
|
1667
|
+
if (!service.onAction) {
|
|
1668
|
+
continue;
|
|
1669
|
+
}
|
|
1670
|
+
try {
|
|
1671
|
+
await service.onAction(ctx, data);
|
|
1672
|
+
} catch (err) {
|
|
1673
|
+
console.error(
|
|
1674
|
+
`notification service "${service.id}" onAction failed:`,
|
|
1675
|
+
err
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1869
1680
|
}
|
|
1870
1681
|
/**
|
|
1871
1682
|
* Creates a batch request that is capable of fetching one or more docs,
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
// core/project.ts
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
{ eager: true }
|
|
10
|
-
);
|
|
2
|
+
var _SCHEMA_MODULES = {};
|
|
3
|
+
try {
|
|
4
|
+
const mod = await import("virtual:root/schemas");
|
|
5
|
+
_SCHEMA_MODULES = mod.SCHEMA_MODULES || {};
|
|
6
|
+
} catch {
|
|
7
|
+
}
|
|
8
|
+
var SCHEMA_MODULES = _SCHEMA_MODULES;
|
|
11
9
|
function getProjectSchemas() {
|
|
12
10
|
const schemas = {};
|
|
13
11
|
for (const fileId in SCHEMA_MODULES) {
|
|
@@ -57,10 +55,10 @@ function testValidCollectionId(id) {
|
|
|
57
55
|
function isSchemaPattern(value) {
|
|
58
56
|
return typeof value === "object" && value !== null && "_schemaPattern" in value && value._schemaPattern === true;
|
|
59
57
|
}
|
|
60
|
-
function buildSchemaNameMap() {
|
|
58
|
+
function buildSchemaNameMap(schemaModules = SCHEMA_MODULES) {
|
|
61
59
|
const nameMap = {};
|
|
62
|
-
for (const fileId in
|
|
63
|
-
const module =
|
|
60
|
+
for (const fileId in schemaModules) {
|
|
61
|
+
const module = schemaModules[fileId];
|
|
64
62
|
if (module.default && module.default.name) {
|
|
65
63
|
nameMap[module.default.name] = module.default;
|
|
66
64
|
}
|
|
@@ -71,16 +69,16 @@ function globToRegex(pattern) {
|
|
|
71
69
|
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{DOUBLE_STAR}}").replace(/\*/g, "[^/]*").replace(/\{\{DOUBLE_STAR\}\}/g, ".*");
|
|
72
70
|
return new RegExp(`^${regexStr}$`);
|
|
73
71
|
}
|
|
74
|
-
function resolveSchemaPattern(pattern) {
|
|
72
|
+
function resolveSchemaPattern(pattern, schemaModules = SCHEMA_MODULES) {
|
|
75
73
|
const regex = globToRegex(pattern.pattern);
|
|
76
74
|
const excludeSet = new Set(pattern.exclude || []);
|
|
77
75
|
const names = [];
|
|
78
76
|
const schemas = {};
|
|
79
|
-
for (const fileId in
|
|
77
|
+
for (const fileId in schemaModules) {
|
|
80
78
|
if (!regex.test(fileId)) {
|
|
81
79
|
continue;
|
|
82
80
|
}
|
|
83
|
-
const module =
|
|
81
|
+
const module = schemaModules[fileId];
|
|
84
82
|
if (!module.default || !module.default.name) {
|
|
85
83
|
continue;
|
|
86
84
|
}
|
|
@@ -88,28 +86,25 @@ function resolveSchemaPattern(pattern) {
|
|
|
88
86
|
if (excludeSet.has(schemaName)) {
|
|
89
87
|
continue;
|
|
90
88
|
}
|
|
91
|
-
|
|
89
|
+
const schemaObj = structuredClone(module.default);
|
|
92
90
|
if (pattern.omitFields && pattern.omitFields.length > 0) {
|
|
93
91
|
const omitSet = new Set(pattern.omitFields);
|
|
94
|
-
schemaObj =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
(f) => !omitSet.has(f.id || "")
|
|
98
|
-
)
|
|
99
|
-
};
|
|
92
|
+
schemaObj.fields = schemaObj.fields.filter(
|
|
93
|
+
(f) => !omitSet.has(f.id || "")
|
|
94
|
+
);
|
|
100
95
|
}
|
|
101
96
|
names.push(schemaName);
|
|
102
97
|
schemas[schemaName] = schemaObj;
|
|
103
98
|
}
|
|
104
99
|
return { names, schemas };
|
|
105
100
|
}
|
|
106
|
-
function convertOneOfTypes(collection) {
|
|
101
|
+
function convertOneOfTypes(collection, schemaModules = SCHEMA_MODULES) {
|
|
107
102
|
const clone = structuredClone(collection);
|
|
108
103
|
const types = clone.types || {};
|
|
109
|
-
const schemaNameMap = buildSchemaNameMap();
|
|
104
|
+
const schemaNameMap = buildSchemaNameMap(schemaModules);
|
|
110
105
|
function handleOneOfField(field) {
|
|
111
106
|
if (isSchemaPattern(field.types)) {
|
|
112
|
-
const resolved = resolveSchemaPattern(field.types);
|
|
107
|
+
const resolved = resolveSchemaPattern(field.types, schemaModules);
|
|
113
108
|
for (const [name, schemaObj] of Object.entries(resolved.schemas)) {
|
|
114
109
|
if (!types[name]) {
|
|
115
110
|
types[name] = schemaObj;
|
|
@@ -126,7 +121,7 @@ function convertOneOfTypes(collection) {
|
|
|
126
121
|
if (typeof sub === "string") {
|
|
127
122
|
names.push(sub);
|
|
128
123
|
if (!types[sub] && schemaNameMap[sub]) {
|
|
129
|
-
const resolvedSchema = schemaNameMap[sub];
|
|
124
|
+
const resolvedSchema = structuredClone(schemaNameMap[sub]);
|
|
130
125
|
types[sub] = resolvedSchema;
|
|
131
126
|
if (resolvedSchema.fields) {
|
|
132
127
|
walk(resolvedSchema);
|
|
@@ -168,5 +163,6 @@ export {
|
|
|
168
163
|
SCHEMA_MODULES,
|
|
169
164
|
getProjectSchemas,
|
|
170
165
|
resolveOneOfPatterns,
|
|
171
|
-
getCollectionSchema
|
|
166
|
+
getCollectionSchema,
|
|
167
|
+
convertOneOfTypes
|
|
172
168
|
};
|