@blinkk/root-cms 2.5.8 → 2.5.10
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 +11 -1
- package/dist/{chunk-4YTAYZTP.js → chunk-7QY6372S.js} +2 -2
- package/dist/{chunk-AFL5KJ4E.js → chunk-PKD2TDSV.js} +10 -1
- package/dist/{chunk-5N2KLMQH.js → chunk-YMUZ5H5C.js} +186 -3
- package/dist/cli.js +1 -1
- package/dist/{client-B3U47cNR.d.ts → client-CFCGhGA0.d.ts} +129 -3
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/core.d.ts +3 -3
- package/dist/core.js +1 -4
- package/dist/functions.js +2 -2
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.js +100 -5
- package/dist/project.d.ts +1 -1
- package/dist/{schema-Bht24XmU.d.ts → schema-D7MOj-YC.d.ts} +8 -1
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +150 -150
- package/dist/ui/ui.js.LEGAL.txt +1 -0
- package/package.json +3 -3
package/dist/plugin.js
CHANGED
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
} from "./chunk-T5UK2H24.js";
|
|
5
5
|
import {
|
|
6
6
|
getServerVersion
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-7QY6372S.js";
|
|
8
8
|
import {
|
|
9
9
|
runCronJobs
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PKD2TDSV.js";
|
|
11
11
|
import {
|
|
12
12
|
RootCMSClient,
|
|
13
13
|
parseDocId,
|
|
14
14
|
unmarshalData
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-YMUZ5H5C.js";
|
|
16
16
|
import "./chunk-MLKGABMK.js";
|
|
17
17
|
|
|
18
18
|
// core/plugin.ts
|
|
@@ -514,6 +514,96 @@ function api(server, options) {
|
|
|
514
514
|
res.status(500).json({ success: false, error: err.message || "UNKNOWN" });
|
|
515
515
|
}
|
|
516
516
|
});
|
|
517
|
+
server.use(
|
|
518
|
+
"/cms/api/translations.import",
|
|
519
|
+
async (req, res) => {
|
|
520
|
+
await handleTranslationServiceRequest(req, res, "import");
|
|
521
|
+
}
|
|
522
|
+
);
|
|
523
|
+
server.use(
|
|
524
|
+
"/cms/api/translations.export",
|
|
525
|
+
async (req, res) => {
|
|
526
|
+
await handleTranslationServiceRequest(req, res, "export");
|
|
527
|
+
}
|
|
528
|
+
);
|
|
529
|
+
async function handleTranslationServiceRequest(req, res, action) {
|
|
530
|
+
if (req.method !== "POST" || !String(req.get("content-type")).startsWith("application/json")) {
|
|
531
|
+
res.status(400).json({ success: false, error: "BAD_REQUEST" });
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (!req.user?.email) {
|
|
535
|
+
res.status(401).json({ success: false, error: "UNAUTHORIZED" });
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
const reqBody = req.body || {};
|
|
539
|
+
const serviceId = String(reqBody.serviceId || "").trim();
|
|
540
|
+
const docId = String(reqBody.docId || "").trim();
|
|
541
|
+
const data = Array.isArray(reqBody.data) ? reqBody.data : [];
|
|
542
|
+
for (const row of data) {
|
|
543
|
+
if (typeof row?.source !== "string" || typeof row?.translations !== "object" || row.translations === null || Array.isArray(row.translations)) {
|
|
544
|
+
res.status(400).json({ success: false, error: "INVALID_DATA_FORMAT" });
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
for (const value of Object.values(row.translations)) {
|
|
548
|
+
if (typeof value !== "string") {
|
|
549
|
+
res.status(400).json({ success: false, error: "INVALID_DATA_FORMAT" });
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (row.description !== void 0 && typeof row.description !== "string") {
|
|
554
|
+
res.status(400).json({ success: false, error: "INVALID_DATA_FORMAT" });
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (!serviceId || !docId) {
|
|
559
|
+
res.status(400).json({ success: false, error: "MISSING_REQUIRED_FIELD" });
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
const services = options.translations || [];
|
|
563
|
+
const service = services.find((s) => s.id === serviceId);
|
|
564
|
+
if (!service) {
|
|
565
|
+
res.status(404).json({ success: false, error: "SERVICE_NOT_FOUND" });
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
const handler = action === "import" ? service.onImport : service.onExport;
|
|
569
|
+
if (!handler) {
|
|
570
|
+
res.status(400).json({
|
|
571
|
+
success: false,
|
|
572
|
+
error: `SERVICE_DOES_NOT_SUPPORT_${action.toUpperCase()}`
|
|
573
|
+
});
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
let collectionId;
|
|
577
|
+
let slug;
|
|
578
|
+
try {
|
|
579
|
+
const parsed = parseDocId(docId);
|
|
580
|
+
collectionId = parsed.collection;
|
|
581
|
+
slug = parsed.slug;
|
|
582
|
+
} catch (err) {
|
|
583
|
+
console.error(err.stack || err);
|
|
584
|
+
res.status(400).json({ success: false, error: "INVALID_DOC_ID" });
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
try {
|
|
588
|
+
const cmsClient = new RootCMSClient(req.rootConfig);
|
|
589
|
+
const locales = req.rootConfig?.i18n?.locales || [];
|
|
590
|
+
const result = await handler(
|
|
591
|
+
{
|
|
592
|
+
rootConfig: req.rootConfig,
|
|
593
|
+
cmsClient,
|
|
594
|
+
docId,
|
|
595
|
+
collectionId,
|
|
596
|
+
slug,
|
|
597
|
+
locales
|
|
598
|
+
},
|
|
599
|
+
data
|
|
600
|
+
);
|
|
601
|
+
res.status(200).json({ success: true, data: result });
|
|
602
|
+
} catch (err) {
|
|
603
|
+
console.error(err.stack || err);
|
|
604
|
+
res.status(500).json({ success: false, error: err.message || "UNKNOWN" });
|
|
605
|
+
}
|
|
606
|
+
}
|
|
517
607
|
}
|
|
518
608
|
|
|
519
609
|
// core/sse.ts
|
|
@@ -701,11 +791,12 @@ function extractRichTextNodeText(node) {
|
|
|
701
791
|
}
|
|
702
792
|
return "";
|
|
703
793
|
}
|
|
704
|
-
function translationsCheck() {
|
|
794
|
+
function translationsCheck(options) {
|
|
705
795
|
return {
|
|
706
796
|
id: "root-cms/translations",
|
|
707
797
|
label: "Missing Translations",
|
|
708
798
|
description: "Checks that all translatable strings have translations for each enabled locale.",
|
|
799
|
+
collections: options?.collections,
|
|
709
800
|
run: async (ctx) => {
|
|
710
801
|
const { cmsClient, collectionId, slug, collectionSchema } = ctx;
|
|
711
802
|
const rawDoc = await cmsClient.getRawDoc(collectionId, slug, {
|
|
@@ -1160,7 +1251,11 @@ function cmsPlugin(options) {
|
|
|
1160
1251
|
if (sseData.sseBroadcast) {
|
|
1161
1252
|
sseBroadcast = sseData.sseBroadcast;
|
|
1162
1253
|
}
|
|
1163
|
-
api(server, {
|
|
1254
|
+
api(server, {
|
|
1255
|
+
getRenderer,
|
|
1256
|
+
checks: options.checks,
|
|
1257
|
+
translations: options.translations
|
|
1258
|
+
});
|
|
1164
1259
|
server.use("/cms", async (req, res) => {
|
|
1165
1260
|
try {
|
|
1166
1261
|
if (!req.user) {
|
package/dist/project.d.ts
CHANGED
|
@@ -21,7 +21,14 @@ type StringField = CommonFieldProps & {
|
|
|
21
21
|
type: 'string';
|
|
22
22
|
default?: string;
|
|
23
23
|
translate?: boolean;
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The UI variant to use for the string field.
|
|
26
|
+
* - `input`: A single-line text input (default).
|
|
27
|
+
* - `textarea`: A multi-line textarea.
|
|
28
|
+
* - `json`: A multi-line textarea that validates and auto-formats JSON on
|
|
29
|
+
* blur. The value is still stored as a string.
|
|
30
|
+
*/
|
|
31
|
+
variant?: 'input' | 'textarea' | 'json';
|
|
25
32
|
/** For textarea variant, the maximum number of rows of text to show. */
|
|
26
33
|
maxRows?: number;
|
|
27
34
|
/**
|