@blinkk/root-cms 3.0.1-beta.3 → 3.0.1-beta.4
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 +3 -2
- package/dist/{chunk-F4SODS5S.js → chunk-2BSW7SIH.js} +295 -4
- package/dist/chunk-BGTUWIV6.js +187 -0
- package/dist/{chunk-TRM4MQHU.js → chunk-C245C557.js} +14 -192
- package/dist/{chunk-NXEXOHBD.js → chunk-MVS2NLZM.js} +243 -16
- package/dist/cli.js +1 -2
- package/dist/client.js +1 -2
- package/dist/core.js +1 -2
- package/dist/functions.js +3 -3
- package/dist/plugin.js +29 -12
- package/dist/ui/ui.js +161 -161
- package/package.json +3 -3
- package/dist/chunk-CRK7N6RR.js +0 -298
package/dist/app.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getServerVersion,
|
|
3
3
|
serializeAiConfig
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-MVS2NLZM.js";
|
|
5
|
+
import "./chunk-C245C557.js";
|
|
6
|
+
import "./chunk-2BSW7SIH.js";
|
|
6
7
|
import {
|
|
7
8
|
getCollectionSchema,
|
|
8
9
|
getProjectSchemas
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
validateFields
|
|
3
|
-
} from "./chunk-CRK7N6RR.js";
|
|
4
|
-
|
|
5
1
|
// core/client.ts
|
|
6
2
|
import crypto from "crypto";
|
|
7
3
|
import {
|
|
@@ -362,6 +358,301 @@ function buildTranslationsLocaleDocDbPath(options) {
|
|
|
362
358
|
).replace("{mode}", options.mode).replace("{id}", normalizeSlug(options.id)).replace("{locale}", options.locale);
|
|
363
359
|
}
|
|
364
360
|
|
|
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
|
+
|
|
365
656
|
// core/values.ts
|
|
366
657
|
function setValueAtPath(obj, path, value) {
|
|
367
658
|
const keys = path.split(".");
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SearchIndexService
|
|
3
|
+
} from "./chunk-C245C557.js";
|
|
4
|
+
import {
|
|
5
|
+
RootCMSClient,
|
|
6
|
+
getCmsPlugin
|
|
7
|
+
} from "./chunk-2BSW7SIH.js";
|
|
8
|
+
|
|
9
|
+
// core/cron.ts
|
|
10
|
+
import { Timestamp as Timestamp2 } from "firebase-admin/firestore";
|
|
11
|
+
|
|
12
|
+
// core/versions.ts
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { Timestamp } from "firebase-admin/firestore";
|
|
16
|
+
import glob from "tiny-glob";
|
|
17
|
+
var DOCUMENT_SAVE_OFFSET = 5 * 60 * 1e3;
|
|
18
|
+
var VersionsService = class {
|
|
19
|
+
constructor(rootConfig) {
|
|
20
|
+
this.rootConfig = rootConfig;
|
|
21
|
+
const cmsPlugin = getCmsPlugin(rootConfig);
|
|
22
|
+
const cmsPluginOptions = cmsPlugin.getConfig();
|
|
23
|
+
const projectId = cmsPluginOptions.id || "default";
|
|
24
|
+
this.projectId = projectId;
|
|
25
|
+
this.db = cmsPlugin.getFirestore();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Saves a version of all documents that have been edited since the last run.
|
|
29
|
+
*/
|
|
30
|
+
async saveVersions() {
|
|
31
|
+
const lastRun = await this.getLastRun();
|
|
32
|
+
const lastRunWithOffset = lastRun === 0 ? lastRun : lastRun - DOCUMENT_SAVE_OFFSET;
|
|
33
|
+
const changedDocs = await this.getDocsModifiedAfter(lastRunWithOffset);
|
|
34
|
+
const now = Timestamp.now().toMillis();
|
|
35
|
+
const versions = changedDocs.filter((doc) => {
|
|
36
|
+
const modifiedAt = doc.sys.modifiedAt.toMillis();
|
|
37
|
+
if (modifiedAt > now - DOCUMENT_SAVE_OFFSET) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const publishedAt = doc.sys.publishedAt?.toMillis?.();
|
|
41
|
+
if (publishedAt && Math.abs(publishedAt - modifiedAt) < 5e3) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
});
|
|
46
|
+
if (versions.length > 0) {
|
|
47
|
+
this.saveVersionsToFirestore(versions);
|
|
48
|
+
}
|
|
49
|
+
this.saveLastRun(now);
|
|
50
|
+
}
|
|
51
|
+
async saveVersionsToFirestore(versions) {
|
|
52
|
+
const batch = this.db.batch();
|
|
53
|
+
versions.forEach((version) => {
|
|
54
|
+
if (!version.collection || !version.slug || !version.sys?.modifiedAt) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const modifiedAtMillis = version.sys.modifiedAt.toMillis();
|
|
58
|
+
const versionPath = `Projects/${this.projectId}/Collections/${version.collection}/Drafts/${version.slug}/Versions/${modifiedAtMillis}`;
|
|
59
|
+
console.log(versionPath);
|
|
60
|
+
const versionRef = this.db.doc(versionPath);
|
|
61
|
+
batch.set(versionRef, version);
|
|
62
|
+
});
|
|
63
|
+
await batch.commit();
|
|
64
|
+
console.log(`versions: saved ${versions.length} versions`);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns the last time (in millis) saveVersions() was run, or 0 if has
|
|
68
|
+
* never been run.
|
|
69
|
+
*/
|
|
70
|
+
async getLastRun() {
|
|
71
|
+
const projectDocRef = this.db.collection("Projects").doc(this.projectId);
|
|
72
|
+
const projectDoc = await projectDocRef.get();
|
|
73
|
+
if (projectDoc.exists) {
|
|
74
|
+
const data = projectDoc.data() || {};
|
|
75
|
+
const ts = data.versionsLastRun;
|
|
76
|
+
if (ts) {
|
|
77
|
+
return ts.toMillis();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Saves {versionLastRun: <timestamp>} to the Projects/<projectId> doc.
|
|
84
|
+
*/
|
|
85
|
+
async saveLastRun(millis) {
|
|
86
|
+
const ts = Timestamp.fromMillis(millis);
|
|
87
|
+
const projectDocRef = this.db.collection("Projects").doc(this.projectId);
|
|
88
|
+
await projectDocRef.set({ versionsLastRun: ts }, { merge: true });
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns a list of all docs that were edited after a certain time.
|
|
92
|
+
*/
|
|
93
|
+
async getDocsModifiedAfter(millis) {
|
|
94
|
+
const ts = Timestamp.fromMillis(millis);
|
|
95
|
+
const results = [];
|
|
96
|
+
const collectionIds = await this.listCollections();
|
|
97
|
+
for (const collectionId of collectionIds) {
|
|
98
|
+
const collectionPath = `Projects/${this.projectId}/Collections/${collectionId}/Drafts`;
|
|
99
|
+
const query = this.db.collection(collectionPath).where("sys.modifiedAt", ">=", ts);
|
|
100
|
+
const querySnapshot = await query.get();
|
|
101
|
+
querySnapshot.forEach((doc) => {
|
|
102
|
+
results.push(doc.data());
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return results;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Returns a list of collection ids for the Root project.
|
|
109
|
+
*/
|
|
110
|
+
async listCollections() {
|
|
111
|
+
const collectionsDir = path.join(this.rootConfig.rootDir, "collections");
|
|
112
|
+
if (!fs.existsSync(collectionsDir)) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
const collectionIds = [];
|
|
116
|
+
const collectionFileNames = await glob("*.schema.ts", {
|
|
117
|
+
cwd: collectionsDir
|
|
118
|
+
});
|
|
119
|
+
collectionFileNames.forEach((filename) => {
|
|
120
|
+
collectionIds.push(filename.slice(0, -10));
|
|
121
|
+
});
|
|
122
|
+
return collectionIds;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// core/cron.ts
|
|
127
|
+
var SEARCH_INDEX_MIN_INTERVAL_MS = 5 * 60 * 1e3;
|
|
128
|
+
async function runCronJobs(rootConfig, options = {}) {
|
|
129
|
+
await Promise.all([
|
|
130
|
+
runCronJob("publishScheduledDocs", runPublishScheduledDocs, rootConfig),
|
|
131
|
+
runCronJob(
|
|
132
|
+
"syncScheduledDataSources",
|
|
133
|
+
runSyncScheduledDataSources,
|
|
134
|
+
rootConfig
|
|
135
|
+
),
|
|
136
|
+
runCronJob("saveVersions", runSaveVersions, rootConfig),
|
|
137
|
+
runCronJob(
|
|
138
|
+
"incrementalSearchIndex",
|
|
139
|
+
runIncrementalSearchIndex,
|
|
140
|
+
rootConfig,
|
|
141
|
+
options.loadSchema
|
|
142
|
+
)
|
|
143
|
+
]);
|
|
144
|
+
}
|
|
145
|
+
async function runCronJob(name, fn, ...args) {
|
|
146
|
+
try {
|
|
147
|
+
await fn(...args);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
console.log(`cron failed: ${name}`);
|
|
150
|
+
console.error(String(err.stack || err));
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function runPublishScheduledDocs(rootConfig) {
|
|
155
|
+
const cmsClient = new RootCMSClient(rootConfig);
|
|
156
|
+
await cmsClient.publishScheduledDocs();
|
|
157
|
+
await cmsClient.publishScheduledReleases();
|
|
158
|
+
}
|
|
159
|
+
async function runSyncScheduledDataSources(rootConfig) {
|
|
160
|
+
const cmsClient = new RootCMSClient(rootConfig);
|
|
161
|
+
await cmsClient.syncScheduledDataSources();
|
|
162
|
+
}
|
|
163
|
+
async function runSaveVersions(rootConfig) {
|
|
164
|
+
const service = new VersionsService(rootConfig);
|
|
165
|
+
await service.saveVersions();
|
|
166
|
+
}
|
|
167
|
+
async function runIncrementalSearchIndex(rootConfig, loadSchema) {
|
|
168
|
+
const service = new SearchIndexService(rootConfig, loadSchema);
|
|
169
|
+
const status = await service.getStatus();
|
|
170
|
+
if (status.lastRun !== null) {
|
|
171
|
+
const elapsed = Date.now() - status.lastRun;
|
|
172
|
+
if (elapsed < SEARCH_INDEX_MIN_INTERVAL_MS) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const hasChanges = await service.hasChangesSince(
|
|
176
|
+
Timestamp2.fromMillis(status.lastRun)
|
|
177
|
+
);
|
|
178
|
+
if (!hasChanges) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
await service.rebuildIndex({ force: false });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export {
|
|
186
|
+
runCronJobs
|
|
187
|
+
};
|