@easy-cms/core 1.28.0 → 1.30.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/dist/{chunk-QRHRDJN5.js → chunk-JTBPGZMF.js} +262 -37
- package/dist/{chunk-SYUQX2G6.js → chunk-X4SI2QB7.js} +15 -1
- package/dist/{config-BLNPAco2.d.ts → config-DGATdBdP.d.ts} +83 -4
- package/dist/{handler-d7cT0k4l.d.ts → handler-DsA868nd.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +36 -4
- package/dist/{plugin-B7pTgG5F.d.ts → plugin-B6lp3qVf.d.ts} +8 -2
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.js +1 -1
- package/package.json +1 -1
|
@@ -26,9 +26,12 @@ import {
|
|
|
26
26
|
imageDimensions,
|
|
27
27
|
isHasMany,
|
|
28
28
|
isPassingError,
|
|
29
|
+
isPolymorphic,
|
|
29
30
|
isPrivateKey,
|
|
30
31
|
mimeAllowed,
|
|
31
32
|
mimeAllowedBy,
|
|
33
|
+
polymorphicValue,
|
|
34
|
+
relationTargets,
|
|
32
35
|
rowFields,
|
|
33
36
|
sizeKey,
|
|
34
37
|
sniffMimeType,
|
|
@@ -38,7 +41,7 @@ import {
|
|
|
38
41
|
warnDeprecated,
|
|
39
42
|
withCharset,
|
|
40
43
|
withPrivacy
|
|
41
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-X4SI2QB7.js";
|
|
42
45
|
|
|
43
46
|
// src/access.ts
|
|
44
47
|
var isSystemAdmin = (user) => user?.role === "admin" && !user.apiKey && user.scoped !== true;
|
|
@@ -1742,6 +1745,33 @@ var SingleSignOn = class {
|
|
|
1742
1745
|
}
|
|
1743
1746
|
};
|
|
1744
1747
|
|
|
1748
|
+
// src/rich-text-blocks.ts
|
|
1749
|
+
var BLOCK_NODE = "block";
|
|
1750
|
+
function blockNodes(doc) {
|
|
1751
|
+
const found = [];
|
|
1752
|
+
const walk = (node, depth) => {
|
|
1753
|
+
if (!node || typeof node !== "object" || depth > 200) return;
|
|
1754
|
+
const { type, content } = node;
|
|
1755
|
+
if (type === BLOCK_NODE) {
|
|
1756
|
+
const n = node;
|
|
1757
|
+
if (!n.attrs || typeof n.attrs !== "object") n.attrs = {};
|
|
1758
|
+
found.push(n);
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
if (Array.isArray(content)) for (const child of content) walk(child, depth + 1);
|
|
1762
|
+
};
|
|
1763
|
+
walk(doc, 0);
|
|
1764
|
+
return found;
|
|
1765
|
+
}
|
|
1766
|
+
function blockOf(field, node) {
|
|
1767
|
+
return field.blocks?.find((block) => block.slug === node.attrs.blockType);
|
|
1768
|
+
}
|
|
1769
|
+
function blockFields(node) {
|
|
1770
|
+
const { fields } = node.attrs;
|
|
1771
|
+
return fields && typeof fields === "object" && !Array.isArray(fields) ? fields : {};
|
|
1772
|
+
}
|
|
1773
|
+
var hasBlocks = (field, value) => (field.blocks?.length ?? 0) > 0 && !!value && typeof value === "object" && value.type === "doc";
|
|
1774
|
+
|
|
1745
1775
|
// src/access-control.ts
|
|
1746
1776
|
async function evaluateAccess(access, args) {
|
|
1747
1777
|
const result = await (access ?? isStaff)(args);
|
|
@@ -1777,6 +1807,14 @@ var FieldAccessChecker = class {
|
|
|
1777
1807
|
return allowed2;
|
|
1778
1808
|
}
|
|
1779
1809
|
};
|
|
1810
|
+
async function mapBlocks(field, doc, map) {
|
|
1811
|
+
const copy = structuredClone(doc);
|
|
1812
|
+
for (const node of blockNodes(copy)) {
|
|
1813
|
+
const block = blockOf(field, node);
|
|
1814
|
+
if (block) node.attrs = { ...node.attrs, fields: await map(block.fields, blockFields(node)) };
|
|
1815
|
+
}
|
|
1816
|
+
return copy;
|
|
1817
|
+
}
|
|
1780
1818
|
async function stripFields(fields, doc, read2) {
|
|
1781
1819
|
const result = { ...doc };
|
|
1782
1820
|
for (const field of fields) {
|
|
@@ -1788,6 +1826,8 @@ async function stripFields(fields, doc, read2) {
|
|
|
1788
1826
|
const value = result[field.name];
|
|
1789
1827
|
if (field.type === "group" && value && typeof value === "object") {
|
|
1790
1828
|
result[field.name] = await stripFields(field.fields, value, read2);
|
|
1829
|
+
} else if (field.type === "richText" && hasBlocks(field, value)) {
|
|
1830
|
+
result[field.name] = await mapBlocks(field, value, (f, d) => stripFields(f, d, read2));
|
|
1791
1831
|
} else if (hasRows(field) && Array.isArray(value)) {
|
|
1792
1832
|
result[field.name] = await Promise.all(
|
|
1793
1833
|
value.map((row) => {
|
|
@@ -1810,6 +1850,8 @@ async function filterInput(fields, data, update2) {
|
|
|
1810
1850
|
const value = result[field.name];
|
|
1811
1851
|
if (field.type === "group" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
1812
1852
|
result[field.name] = await filterInput(field.fields, value, update2);
|
|
1853
|
+
} else if (field.type === "richText" && hasBlocks(field, value)) {
|
|
1854
|
+
result[field.name] = await mapBlocks(field, value, (f, d) => filterInput(f, d, update2));
|
|
1813
1855
|
} else if (hasRows(field) && Array.isArray(value)) {
|
|
1814
1856
|
result[field.name] = await Promise.all(
|
|
1815
1857
|
value.map((row) => {
|
|
@@ -2786,7 +2828,8 @@ async function normalizeValue(field, raw, path, options, fail, errors, reference
|
|
|
2786
2828
|
if (!isPlainObject(raw) || raw.type !== "doc")
|
|
2787
2829
|
return fail('must be a rich text document ({ type: "doc" })');
|
|
2788
2830
|
const marks = docLinkMarks(raw);
|
|
2789
|
-
|
|
2831
|
+
const nodes = blockNodes(raw);
|
|
2832
|
+
if (marks.length === 0 && nodes.length === 0) return raw;
|
|
2790
2833
|
const doc = structuredClone(raw);
|
|
2791
2834
|
for (const mark of docLinkMarks(doc)) {
|
|
2792
2835
|
const target = linkTarget(mark.attrs.doc);
|
|
@@ -2800,24 +2843,53 @@ async function normalizeValue(field, raw, path, options, fail, errors, reference
|
|
|
2800
2843
|
};
|
|
2801
2844
|
references2.push({ field: path, collection: target.relationTo, id, link: true });
|
|
2802
2845
|
}
|
|
2846
|
+
for (const node of blockNodes(doc)) {
|
|
2847
|
+
const { id: rawId, blockType } = node.attrs;
|
|
2848
|
+
const id = typeof rawId === "string" && rawId !== "" ? rawId : randomUUID();
|
|
2849
|
+
const block = blockOf(field, node);
|
|
2850
|
+
if (!block) {
|
|
2851
|
+
const known = field.blocks?.map((b) => `"${b.slug}"`).join(", ");
|
|
2852
|
+
errors.push({
|
|
2853
|
+
field: `${path}.${id}`,
|
|
2854
|
+
message: `has a block "${String(blockType)}" this field doesn't have${known ? `: use one of ${known}` : ""}`
|
|
2855
|
+
});
|
|
2856
|
+
continue;
|
|
2857
|
+
}
|
|
2858
|
+
const input = applyDefaults(block.fields, generateSlugs(block.fields, blockFields(node)));
|
|
2859
|
+
const sub = await validateFields(block.fields, input, options, `${path}.${id}.`);
|
|
2860
|
+
errors.push(...sub.errors);
|
|
2861
|
+
references2.push(...sub.references);
|
|
2862
|
+
node.attrs = { ...node.attrs, blockType: block.slug, id, fields: sub.data };
|
|
2863
|
+
}
|
|
2803
2864
|
return doc;
|
|
2804
2865
|
}
|
|
2805
2866
|
case "upload":
|
|
2806
2867
|
case "relationship": {
|
|
2807
|
-
const
|
|
2868
|
+
const targets = relationTargets(field);
|
|
2869
|
+
const poly = isPolymorphic(field);
|
|
2808
2870
|
const many = field.hasMany === true;
|
|
2809
2871
|
const values = many ? raw : [raw];
|
|
2810
|
-
if (!Array.isArray(values))
|
|
2872
|
+
if (!Array.isArray(values))
|
|
2873
|
+
return fail(poly ? "must be an array of { relationTo, value }" : "must be an array of ids");
|
|
2811
2874
|
if (many && field.minRows !== void 0 && values.length < field.minRows)
|
|
2812
2875
|
return fail(`must have at least ${itemsOf(field, field.minRows)}`);
|
|
2813
2876
|
if (many && field.maxRows !== void 0 && values.length > field.maxRows)
|
|
2814
2877
|
return fail(`must have at most ${itemsOf(field, field.maxRows)}`);
|
|
2815
|
-
const
|
|
2878
|
+
const out = [];
|
|
2816
2879
|
for (const item of values) {
|
|
2817
|
-
const
|
|
2880
|
+
const pair = poly ? polymorphicValue(item) : void 0;
|
|
2881
|
+
if (poly && (!pair || !targets.includes(pair.relationTo)))
|
|
2882
|
+
return fail(
|
|
2883
|
+
pair ? `can't link to "${pair.relationTo}": use one of ${targets.map((t) => `"${t}"`).join(", ")}` : `must be ${many ? "a list of" : ""} { relationTo, value } with relationTo one of ${targets.map((t) => `"${t}"`).join(", ")}`
|
|
2884
|
+
);
|
|
2885
|
+
const target = pair ? pair.relationTo : targets[0];
|
|
2886
|
+
const rawId = pair ? pair.value : item;
|
|
2887
|
+
const id = parseId(isPlainObject(rawId) ? rawId.id : rawId);
|
|
2818
2888
|
if (id === void 0)
|
|
2819
|
-
return fail(
|
|
2820
|
-
|
|
2889
|
+
return fail(
|
|
2890
|
+
poly ? `must have the id of a "${target}" document as value` : `must be ${many ? "ids" : "an id"} of "${target}" documents`
|
|
2891
|
+
);
|
|
2892
|
+
out.push(pair ? { relationTo: target, value: id } : id);
|
|
2821
2893
|
references2.push({
|
|
2822
2894
|
field: path,
|
|
2823
2895
|
collection: target,
|
|
@@ -2827,7 +2899,7 @@ async function normalizeValue(field, raw, path, options, fail, errors, reference
|
|
|
2827
2899
|
...field.type === "upload" && field.folder && field.folderOnly ? { folderOnly: field.folder } : {}
|
|
2828
2900
|
});
|
|
2829
2901
|
}
|
|
2830
|
-
return many ?
|
|
2902
|
+
return many ? out : out[0];
|
|
2831
2903
|
}
|
|
2832
2904
|
case "array": {
|
|
2833
2905
|
if (!Array.isArray(raw)) return fail("must be an array");
|
|
@@ -4005,8 +4077,16 @@ function collectSlots(fields, data, bySlug, slots, linkURL) {
|
|
|
4005
4077
|
collectSlots(fields2, row, bySlug, slots, linkURL);
|
|
4006
4078
|
}
|
|
4007
4079
|
}
|
|
4008
|
-
} else if (field.type === "richText"
|
|
4080
|
+
} else if (field.type === "richText") {
|
|
4009
4081
|
if (value.type !== "doc") continue;
|
|
4082
|
+
for (const node of blockNodes(value)) {
|
|
4083
|
+
const block = blockOf(field, node);
|
|
4084
|
+
if (!block) continue;
|
|
4085
|
+
const fields2 = { ...blockFields(node) };
|
|
4086
|
+
node.attrs = { ...node.attrs, fields: fields2 };
|
|
4087
|
+
collectSlots(block.fields, fields2, bySlug, slots, linkURL);
|
|
4088
|
+
}
|
|
4089
|
+
if (!linkURL) continue;
|
|
4010
4090
|
for (const mark of docLinkMarks(value)) {
|
|
4011
4091
|
const target = linkTarget(mark.attrs.doc);
|
|
4012
4092
|
const collection2 = target ? bySlug.get(target.relationTo) : void 0;
|
|
@@ -4021,9 +4101,34 @@ function collectSlots(fields, data, bySlug, slots, linkURL) {
|
|
|
4021
4101
|
}
|
|
4022
4102
|
});
|
|
4023
4103
|
}
|
|
4104
|
+
} else if (isPolymorphic(field)) {
|
|
4105
|
+
const many = Array.isArray(value);
|
|
4106
|
+
const items = (many ? value : [value]).map(polymorphicValue);
|
|
4107
|
+
if (items.some((item) => item === void 0)) continue;
|
|
4108
|
+
const pairs = items;
|
|
4109
|
+
const found = /* @__PURE__ */ new Map();
|
|
4110
|
+
let waiting = 0;
|
|
4111
|
+
for (const relationTo of new Set(pairs.map((p) => p.relationTo))) {
|
|
4112
|
+
if (!bySlug.has(relationTo)) continue;
|
|
4113
|
+
waiting++;
|
|
4114
|
+
slots.push({
|
|
4115
|
+
collection: relationTo,
|
|
4116
|
+
ids: pairs.filter((p) => p.relationTo === relationTo).map((p) => p.value),
|
|
4117
|
+
assign: (byId) => {
|
|
4118
|
+
found.set(relationTo, byId);
|
|
4119
|
+
if (--waiting > 0) return;
|
|
4120
|
+
const filled = pairs.map((p) => {
|
|
4121
|
+
if (!bySlug.has(p.relationTo)) return p;
|
|
4122
|
+
const doc = found.get(p.relationTo)?.get(p.value);
|
|
4123
|
+
return doc ? { relationTo: p.relationTo, value: doc } : void 0;
|
|
4124
|
+
}).filter((p) => p !== void 0);
|
|
4125
|
+
data[field.name] = many ? filled : filled[0] ?? null;
|
|
4126
|
+
}
|
|
4127
|
+
});
|
|
4128
|
+
}
|
|
4024
4129
|
} else if (field.type === "relationship" || field.type === "upload") {
|
|
4025
4130
|
if (typeof value === "object" && !Array.isArray(value)) continue;
|
|
4026
|
-
const collection2 = field
|
|
4131
|
+
const collection2 = relationTargets(field)[0];
|
|
4027
4132
|
if (!bySlug.has(collection2)) continue;
|
|
4028
4133
|
if (Array.isArray(value)) {
|
|
4029
4134
|
const ids = value;
|
|
@@ -5388,7 +5493,7 @@ var FIELD = {
|
|
|
5388
5493
|
json: keys(BASE_FIELD),
|
|
5389
5494
|
select: keys(`${BASE_FIELD} options hasMany minRows maxRows`),
|
|
5390
5495
|
slug: keys(`${BASE_FIELD} from`),
|
|
5391
|
-
richText: keys(BASE_FIELD),
|
|
5496
|
+
richText: keys(`${BASE_FIELD} blocks`),
|
|
5392
5497
|
upload: keys(`${BASE_FIELD} hasMany minRows maxRows mimeTypes folder folderOnly filterOptions`),
|
|
5393
5498
|
relationship: keys(`${BASE_FIELD} to hasMany minRows maxRows filterOptions`),
|
|
5394
5499
|
array: keys(`${BASE_FIELD} fields minRows maxRows`),
|
|
@@ -5617,8 +5722,13 @@ function textOf(field, value) {
|
|
|
5617
5722
|
return typeof value === "string" ? value : "";
|
|
5618
5723
|
case "select":
|
|
5619
5724
|
return [value].flat().filter((v) => typeof v === "string").join(" ");
|
|
5620
|
-
case "richText":
|
|
5621
|
-
|
|
5725
|
+
case "richText": {
|
|
5726
|
+
const blocks = hasBlocks(field, value) ? blockNodes(value).map((node) => {
|
|
5727
|
+
const block = blockOf(field, node);
|
|
5728
|
+
return block ? fieldsText(block.fields, blockFields(node)) : "";
|
|
5729
|
+
}) : [];
|
|
5730
|
+
return [richText(value), ...blocks].filter(Boolean).join("\n");
|
|
5731
|
+
}
|
|
5622
5732
|
case "group":
|
|
5623
5733
|
return typeof value === "object" ? fieldsText(field.fields, value) : "";
|
|
5624
5734
|
case "array":
|
|
@@ -6263,7 +6373,7 @@ function warnNestedUnique(config, push) {
|
|
|
6263
6373
|
severity: "warning"
|
|
6264
6374
|
});
|
|
6265
6375
|
if (field.type === "group" || field.type === "array") walk(field.fields, `${at}.fields`, true);
|
|
6266
|
-
if (field.type === "blocks")
|
|
6376
|
+
if (field.type === "blocks" || field.type === "richText")
|
|
6267
6377
|
for (const block of Array.isArray(field.blocks) ? field.blocks : [])
|
|
6268
6378
|
walk(block?.fields, `${at}.blocks.${String(block?.slug)}`, true);
|
|
6269
6379
|
}
|
|
@@ -6738,7 +6848,7 @@ function validateUpload(config, add) {
|
|
|
6738
6848
|
add(`${at}.folder`, "needs upload.folders: true", "upload: { folders: true }");
|
|
6739
6849
|
if ((field.type === "group" || field.type === "array") && Array.isArray(field.fields))
|
|
6740
6850
|
walk(field.fields, at);
|
|
6741
|
-
if (field.type === "blocks" && Array.isArray(field.blocks)) {
|
|
6851
|
+
if ((field.type === "blocks" || field.type === "richText") && Array.isArray(field.blocks)) {
|
|
6742
6852
|
for (const [b, block] of field.blocks.entries())
|
|
6743
6853
|
if (Array.isArray(block?.fields)) walk(block.fields, `${at}.blocks[${b}]`);
|
|
6744
6854
|
}
|
|
@@ -7346,16 +7456,24 @@ function validateField(field, path, siblings, collectionSlugs, add) {
|
|
|
7346
7456
|
}
|
|
7347
7457
|
}
|
|
7348
7458
|
break;
|
|
7349
|
-
case "relationship":
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7459
|
+
case "relationship": {
|
|
7460
|
+
const to = field.to;
|
|
7461
|
+
if (Array.isArray(to)) {
|
|
7462
|
+
if (to.length === 0) add(`${path}.to`, "needs at least one collection");
|
|
7463
|
+
if (new Set(to).size !== to.length) add(`${path}.to`, "names a collection twice");
|
|
7464
|
+
}
|
|
7465
|
+
for (const target of Array.isArray(to) ? to : [to]) {
|
|
7466
|
+
if (typeof target !== "string" || !collectionSlugs.has(target)) {
|
|
7467
|
+
add(
|
|
7468
|
+
`${path}.to`,
|
|
7469
|
+
`unknown collection ${JSON.stringify(target)}`,
|
|
7470
|
+
`use one of: ${[...collectionSlugs].join(", ")}`
|
|
7471
|
+
);
|
|
7472
|
+
}
|
|
7356
7473
|
}
|
|
7357
7474
|
validateManyRange(field, path, add);
|
|
7358
7475
|
break;
|
|
7476
|
+
}
|
|
7359
7477
|
case "upload":
|
|
7360
7478
|
validateManyRange(field, path, add);
|
|
7361
7479
|
if (field.folder !== void 0 && !FOLDER_KEY.test(String(field.folder)))
|
|
@@ -7449,6 +7567,57 @@ function validateField(field, path, siblings, collectionSlugs, add) {
|
|
|
7449
7567
|
}
|
|
7450
7568
|
break;
|
|
7451
7569
|
}
|
|
7570
|
+
case "richText": {
|
|
7571
|
+
const blocks = field.blocks;
|
|
7572
|
+
if (blocks === void 0) break;
|
|
7573
|
+
if (!Array.isArray(blocks) || blocks.length === 0) {
|
|
7574
|
+
add(
|
|
7575
|
+
`${path}.blocks`,
|
|
7576
|
+
"must be a list of at least one block",
|
|
7577
|
+
"blocks: [{ slug: 'callout', fields: [...] }]"
|
|
7578
|
+
);
|
|
7579
|
+
break;
|
|
7580
|
+
}
|
|
7581
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7582
|
+
for (const [i, block] of blocks.entries()) {
|
|
7583
|
+
const blockPath = `${path}.blocks[${i}]`;
|
|
7584
|
+
if (typeof block?.slug !== "string" || !SLUG_PATTERN.test(block.slug)) {
|
|
7585
|
+
add(
|
|
7586
|
+
`${blockPath}.slug`,
|
|
7587
|
+
'must be lowercase letters, digits, "-" or "_", starting with a letter'
|
|
7588
|
+
);
|
|
7589
|
+
} else if (seen.has(block.slug)) {
|
|
7590
|
+
add(`${blockPath}.slug`, `duplicate block "${block.slug}"`);
|
|
7591
|
+
} else {
|
|
7592
|
+
seen.add(block.slug);
|
|
7593
|
+
}
|
|
7594
|
+
const summary = block?.admin?.summary;
|
|
7595
|
+
if (summary !== void 0 && typeof summary !== "string" && typeof summary !== "function")
|
|
7596
|
+
add(`${blockPath}.admin.summary`, "must be a function or the tag of a custom element");
|
|
7597
|
+
if (!Array.isArray(block?.fields)) {
|
|
7598
|
+
add(`${blockPath}.fields`, "must be an array");
|
|
7599
|
+
continue;
|
|
7600
|
+
}
|
|
7601
|
+
const walk = (fields, at) => {
|
|
7602
|
+
for (const inner of fields) {
|
|
7603
|
+
const here = `${at}.${inner.name}`;
|
|
7604
|
+
if (inner.type === "richText" || inner.type === "blocks")
|
|
7605
|
+
add(here, `a ${inner.type} field can't be inside a rich text block`);
|
|
7606
|
+
if (inner.localized)
|
|
7607
|
+
add(
|
|
7608
|
+
`${here}.localized`,
|
|
7609
|
+
"fields in rich text blocks can't be localized",
|
|
7610
|
+
"set localized on the rich text field: its blocks follow its locale"
|
|
7611
|
+
);
|
|
7612
|
+
if ((inner.type === "group" || inner.type === "array") && Array.isArray(inner.fields))
|
|
7613
|
+
walk(inner.fields, `${here}.fields`);
|
|
7614
|
+
}
|
|
7615
|
+
};
|
|
7616
|
+
walk(block.fields, `${blockPath}.fields`);
|
|
7617
|
+
validateFields2(block.fields, `${blockPath}.fields`, /* @__PURE__ */ new Set(), collectionSlugs, add);
|
|
7618
|
+
}
|
|
7619
|
+
break;
|
|
7620
|
+
}
|
|
7452
7621
|
}
|
|
7453
7622
|
}
|
|
7454
7623
|
var ADMIN_COMPONENT_TAG = /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/;
|
|
@@ -7853,9 +8022,9 @@ function withoutUiFields(config) {
|
|
|
7853
8022
|
changed = true;
|
|
7854
8023
|
next = { ...field, fields: inner.data, [ADMIN_FIELDS]: inner.admin };
|
|
7855
8024
|
}
|
|
7856
|
-
} else if (field.type === "blocks") {
|
|
8025
|
+
} else if (field.type === "blocks" || field.type === "richText" && field.blocks) {
|
|
7857
8026
|
let blocksChanged = false;
|
|
7858
|
-
const blocks = field.blocks.map((block) => {
|
|
8027
|
+
const blocks = (field.blocks ?? []).map((block) => {
|
|
7859
8028
|
const inner = strip(block.fields);
|
|
7860
8029
|
if (!inner.changed) return block;
|
|
7861
8030
|
blocksChanged = true;
|
|
@@ -7932,7 +8101,7 @@ function cacheableResponse(request, body, status, headers, times, tags) {
|
|
|
7932
8101
|
}
|
|
7933
8102
|
|
|
7934
8103
|
// src/version.ts
|
|
7935
|
-
var VERSION = true ? "1.
|
|
8104
|
+
var VERSION = true ? "1.30.0" : "0.0.0-dev";
|
|
7936
8105
|
|
|
7937
8106
|
// src/telemetry.ts
|
|
7938
8107
|
var DB_CALLS = /* @__PURE__ */ new Set([
|
|
@@ -11048,9 +11217,14 @@ var EasyCMS = class {
|
|
|
11048
11217
|
for (const ref of references2) {
|
|
11049
11218
|
const filter = ref.filterOptions;
|
|
11050
11219
|
if (!filter) continue;
|
|
11051
|
-
|
|
11052
|
-
|
|
11053
|
-
|
|
11220
|
+
const byCollection = allowed2.get(filter) ?? /* @__PURE__ */ new Map();
|
|
11221
|
+
allowed2.set(filter, byCollection);
|
|
11222
|
+
if (!byCollection.has(ref.collection))
|
|
11223
|
+
byCollection.set(
|
|
11224
|
+
ref.collection,
|
|
11225
|
+
await filter({ id: selfId, relationTo: ref.collection, user, cms, context })
|
|
11226
|
+
);
|
|
11227
|
+
const where = byCollection.get(ref.collection);
|
|
11054
11228
|
if (where === true) continue;
|
|
11055
11229
|
const target = this.config.collections.find((c) => c.slug === ref.collection);
|
|
11056
11230
|
const localization = this.config.localization;
|
|
@@ -11487,10 +11661,11 @@ function ruleFields(fields) {
|
|
|
11487
11661
|
}
|
|
11488
11662
|
function references(fields, out = /* @__PURE__ */ new Set()) {
|
|
11489
11663
|
for (const field of fields) {
|
|
11490
|
-
if (field.type === "relationship"
|
|
11491
|
-
|
|
11664
|
+
if (field.type === "relationship" || field.type === "upload")
|
|
11665
|
+
for (const target of relationTargets(field)) out.add(target);
|
|
11492
11666
|
else if (field.type === "group" || field.type === "array") references(field.fields, out);
|
|
11493
|
-
else if (field.type === "blocks"
|
|
11667
|
+
else if (field.type === "blocks" || field.type === "richText")
|
|
11668
|
+
for (const b of field.blocks ?? []) references(b.fields, out);
|
|
11494
11669
|
}
|
|
11495
11670
|
return out;
|
|
11496
11671
|
}
|
|
@@ -12350,7 +12525,7 @@ async function serializeFields(fields, checks, localized, folderId, who) {
|
|
|
12350
12525
|
if (field.from) f.from = field.from;
|
|
12351
12526
|
break;
|
|
12352
12527
|
case "relationship":
|
|
12353
|
-
f.to = field.to;
|
|
12528
|
+
f.to = typeof field.to === "string" ? field.to : [...field.to];
|
|
12354
12529
|
if (field.hasMany) f.hasMany = true;
|
|
12355
12530
|
if (field.minRows !== void 0) f.minRows = field.minRows;
|
|
12356
12531
|
if (field.maxRows !== void 0) f.maxRows = field.maxRows;
|
|
@@ -12384,6 +12559,26 @@ async function serializeFields(fields, checks, localized, folderId, who) {
|
|
|
12384
12559
|
}))
|
|
12385
12560
|
);
|
|
12386
12561
|
break;
|
|
12562
|
+
case "richText":
|
|
12563
|
+
if (field.blocks)
|
|
12564
|
+
f.blocks = await Promise.all(
|
|
12565
|
+
field.blocks.map(async (block) => {
|
|
12566
|
+
const summary = block.admin?.summary;
|
|
12567
|
+
return {
|
|
12568
|
+
slug: block.slug,
|
|
12569
|
+
...block.labels ? { labels: block.labels } : {},
|
|
12570
|
+
fields: await serializeFields(
|
|
12571
|
+
adminFieldsOf(block),
|
|
12572
|
+
checks,
|
|
12573
|
+
localized,
|
|
12574
|
+
folderId,
|
|
12575
|
+
who
|
|
12576
|
+
),
|
|
12577
|
+
...summary !== void 0 ? { summary: typeof summary === "function" ? "server" : summary } : {}
|
|
12578
|
+
};
|
|
12579
|
+
})
|
|
12580
|
+
);
|
|
12581
|
+
break;
|
|
12387
12582
|
case "group":
|
|
12388
12583
|
f.fields = await serializeFields(adminFieldsOf(field), checks, localized, folderId, who);
|
|
12389
12584
|
break;
|
|
@@ -12902,15 +13097,38 @@ async function pickerFilter(cms, url, target, user, context = {}) {
|
|
|
12902
13097
|
const slug2 = dot > 0 ? spec.slice(0, dot) : "";
|
|
12903
13098
|
const owner = forCollection !== null ? cms.config.collections.find((c) => c.slug === slug2) : cms.config.globals.find((g) => g.slug === slug2);
|
|
12904
13099
|
const field = owner ? fieldAt2(owner.fields, spec.slice(dot + 1)) : void 0;
|
|
12905
|
-
|
|
12906
|
-
if (!field || field.type !== "relationship" && field.type !== "upload" || to !== target)
|
|
13100
|
+
if (!field || field.type !== "relationship" && field.type !== "upload" || !relationTargets(field).includes(target))
|
|
12907
13101
|
throw new QueryError(`filterFor: no relationship to "${target}" at "${spec}"`);
|
|
12908
13102
|
if (!field.filterOptions) return void 0;
|
|
12909
13103
|
const rawId = url.searchParams.get("filterId");
|
|
12910
13104
|
const id = rawId === null || rawId === "" ? void 0 : /^\d+$/.test(rawId) ? Number(rawId) : rawId;
|
|
12911
|
-
const where = await field.filterOptions({ id, user, cms, context });
|
|
13105
|
+
const where = await field.filterOptions({ id, relationTo: target, user, cms, context });
|
|
12912
13106
|
return where === true ? void 0 : where;
|
|
12913
13107
|
}
|
|
13108
|
+
async function blockSummaries(cms, user, body) {
|
|
13109
|
+
const input = body && typeof body === "object" ? body : {};
|
|
13110
|
+
const owner = typeof input.collection === "string" ? cms.config.collections.find((c) => c.slug === input.collection) : typeof input.global === "string" ? cms.config.globals.find((g) => g.slug === input.global) : void 0;
|
|
13111
|
+
const field = owner && typeof input.field === "string" ? fieldAt2(owner.fields, input.field) : void 0;
|
|
13112
|
+
if (!field || field.type !== "richText" || !field.blocks)
|
|
13113
|
+
throw new QueryError("block-summaries: no rich text field with blocks there");
|
|
13114
|
+
const summaries = {};
|
|
13115
|
+
for (const item of Array.isArray(input.blocks) ? input.blocks.slice(0, 200) : []) {
|
|
13116
|
+
const { id, blockType, fields } = item ?? {};
|
|
13117
|
+
const summary = field.blocks.find((b) => b.slug === blockType)?.admin?.summary;
|
|
13118
|
+
if (typeof id !== "string" || typeof summary !== "function") continue;
|
|
13119
|
+
try {
|
|
13120
|
+
const text3 = await summary({
|
|
13121
|
+
fields: fields && typeof fields === "object" ? fields : {},
|
|
13122
|
+
user,
|
|
13123
|
+
cms
|
|
13124
|
+
});
|
|
13125
|
+
if (typeof text3 === "string") summaries[id] = text3;
|
|
13126
|
+
} catch (error) {
|
|
13127
|
+
cms.logger.warn(`admin.summary of block "${String(blockType)}" failed: ${String(error)}`);
|
|
13128
|
+
}
|
|
13129
|
+
}
|
|
13130
|
+
return { summaries };
|
|
13131
|
+
}
|
|
12914
13132
|
|
|
12915
13133
|
// src/rest/query.ts
|
|
12916
13134
|
var MAX_DEPTH2 = 10;
|
|
@@ -13204,7 +13422,8 @@ var ADMIN_UI_ROUTES = /* @__PURE__ */ new Set([
|
|
|
13204
13422
|
"total",
|
|
13205
13423
|
"media-usage",
|
|
13206
13424
|
"owned",
|
|
13207
|
-
"sso"
|
|
13425
|
+
"sso",
|
|
13426
|
+
"block-summaries"
|
|
13208
13427
|
]);
|
|
13209
13428
|
var CORS_METHODS = "GET, HEAD, POST, PATCH, PUT, DELETE";
|
|
13210
13429
|
var CORS_HEADERS = `authorization, content-type, ${CSRF_HEADER}`;
|
|
@@ -13581,6 +13800,12 @@ async function route(cms, ctx, method, path, options) {
|
|
|
13581
13800
|
if (parsed === void 0) throw new HttpError("Not found", 404);
|
|
13582
13801
|
return { body: await cms.roles.owned(parsed) };
|
|
13583
13802
|
}
|
|
13803
|
+
if (first === "admin" && second === "block-summaries" && third === void 0) {
|
|
13804
|
+
if (!ctx.user) throw new UnauthorizedError();
|
|
13805
|
+
if (method !== "POST") throw methodNotAllowed(ctx, "POST");
|
|
13806
|
+
const body = await readJson(ctx.request);
|
|
13807
|
+
return { body: await blockSummaries(cms, ctx.user, body) };
|
|
13808
|
+
}
|
|
13584
13809
|
if (first === "admin" && second === "media-usage" && segments.length === 2) {
|
|
13585
13810
|
if (!ctx.user || ctx.user.apiKey) throw new UnauthorizedError();
|
|
13586
13811
|
if (method !== "GET") throw methodNotAllowed(ctx, "GET");
|
|
@@ -333,6 +333,17 @@ function mimeAllowedBy(mimeType, patterns) {
|
|
|
333
333
|
});
|
|
334
334
|
}
|
|
335
335
|
var SVG = "image/svg+xml";
|
|
336
|
+
var isPolymorphic = (field) => field.type === "relationship" && Array.isArray(field.to);
|
|
337
|
+
function relationTargets(field) {
|
|
338
|
+
if (field.type === "upload") return ["media"];
|
|
339
|
+
if (field.type !== "relationship") return [];
|
|
340
|
+
return typeof field.to === "string" ? [field.to] : field.to;
|
|
341
|
+
}
|
|
342
|
+
function polymorphicValue(value) {
|
|
343
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
344
|
+
const { relationTo } = value;
|
|
345
|
+
return typeof relationTo === "string" ? { relationTo, value: value.value } : void 0;
|
|
346
|
+
}
|
|
336
347
|
var hasRows = (field) => field.type === "array" || field.type === "blocks";
|
|
337
348
|
function rowFields(field, row) {
|
|
338
349
|
if (field.type === "array") return field.fields;
|
|
@@ -502,7 +513,7 @@ function applyFieldTypes(config) {
|
|
|
502
513
|
if (!type) {
|
|
503
514
|
if ((field.type === "group" || field.type === "array") && Array.isArray(field.fields))
|
|
504
515
|
return { ...field, fields: convert(field.fields, `${here}.fields`) };
|
|
505
|
-
if (field.type === "blocks" && Array.isArray(field.blocks))
|
|
516
|
+
if ((field.type === "blocks" || field.type === "richText") && Array.isArray(field.blocks))
|
|
506
517
|
return {
|
|
507
518
|
...field,
|
|
508
519
|
blocks: field.blocks.map((block, b) => ({
|
|
@@ -592,6 +603,9 @@ export {
|
|
|
592
603
|
uniqueWithinOf,
|
|
593
604
|
isHasMany,
|
|
594
605
|
mimeAllowedBy,
|
|
606
|
+
isPolymorphic,
|
|
607
|
+
relationTargets,
|
|
608
|
+
polymorphicValue,
|
|
595
609
|
hasRows,
|
|
596
610
|
rowFields,
|
|
597
611
|
TRIGRAM_LIKE_MIN,
|
|
@@ -905,6 +905,28 @@ interface RichTextDocument {
|
|
|
905
905
|
readonly content?: readonly unknown[];
|
|
906
906
|
}
|
|
907
907
|
interface RichTextField extends BaseField<'richText', RichTextDocument> {
|
|
908
|
+
/**
|
|
909
|
+
* Blocks editors place between paragraphs (#328): a card, a callout, a video. Each is a node
|
|
910
|
+
* `{ type: 'block', attrs: { blockType, id, fields } }` in the document.
|
|
911
|
+
*/
|
|
912
|
+
readonly blocks?: readonly RichTextBlock[];
|
|
913
|
+
}
|
|
914
|
+
/** Arguments of a rich text block's `admin.summary` function. */
|
|
915
|
+
interface BlockSummaryArgs {
|
|
916
|
+
readonly fields: Record<string, unknown>;
|
|
917
|
+
readonly user: AuthUser | null;
|
|
918
|
+
readonly cms: EasyCMS;
|
|
919
|
+
}
|
|
920
|
+
/** A block in rich text (`richText.blocks`): the fields of `Block`, and how its card reads. */
|
|
921
|
+
interface RichTextBlock extends Block {
|
|
922
|
+
readonly admin?: {
|
|
923
|
+
/**
|
|
924
|
+
* The text of the block's card in the editor: a function, run on the server, or the tag of a
|
|
925
|
+
* custom element from an admin module, which gets `fields`. Default: the block's label and
|
|
926
|
+
* its first value.
|
|
927
|
+
*/
|
|
928
|
+
readonly summary?: string | ((args: BlockSummaryArgs) => string | Promise<string>);
|
|
929
|
+
};
|
|
908
930
|
}
|
|
909
931
|
/** References a document in the built-in `media` collection: a file or an image. */
|
|
910
932
|
interface UploadField extends BaseField<'upload', never> {
|
|
@@ -933,6 +955,8 @@ interface UploadField extends BaseField<'upload', never> {
|
|
|
933
955
|
interface FilterOptionsArgs {
|
|
934
956
|
/** The document being edited; `undefined` while it is being created. */
|
|
935
957
|
readonly id: ID | undefined;
|
|
958
|
+
/** The collection the choices come from: one of the field's `to`. */
|
|
959
|
+
readonly relationTo: string;
|
|
936
960
|
readonly user: AuthUser | null;
|
|
937
961
|
readonly cms: EasyCMS;
|
|
938
962
|
/** The request's context (`onRequest`), `{}` when there is none. */
|
|
@@ -944,8 +968,11 @@ interface FilterOptionsArgs {
|
|
|
944
968
|
*/
|
|
945
969
|
type FilterOptions = (args: FilterOptionsArgs) => Where | true | Promise<Where | true>;
|
|
946
970
|
interface RelationshipField extends BaseField<'relationship', never> {
|
|
947
|
-
/**
|
|
948
|
-
|
|
971
|
+
/**
|
|
972
|
+
* Slug of the target collection, or several: then each value is `{ relationTo, value }`, the
|
|
973
|
+
* collection and the document's id (#327).
|
|
974
|
+
*/
|
|
975
|
+
readonly to: string | readonly string[];
|
|
949
976
|
readonly hasMany?: boolean;
|
|
950
977
|
/** With `hasMany`: the fewest documents. */
|
|
951
978
|
readonly minRows?: number;
|
|
@@ -989,6 +1016,17 @@ declare const isHasMany: (field: Field) => boolean;
|
|
|
989
1016
|
* carry scripts and is allowed only when listed by name: `image/svg+xml`).
|
|
990
1017
|
*/
|
|
991
1018
|
declare function mimeAllowedBy(mimeType: string, patterns: readonly string[]): boolean;
|
|
1019
|
+
/** A relationship to several collections: its values are `{ relationTo, value }` (#327). */
|
|
1020
|
+
declare const isPolymorphic: (field: Field) => field is RelationshipField & {
|
|
1021
|
+
readonly to: readonly string[];
|
|
1022
|
+
};
|
|
1023
|
+
/** The collections a relationship or upload field points to. */
|
|
1024
|
+
declare function relationTargets(field: Field): readonly string[];
|
|
1025
|
+
/** A `{ relationTo, value }` of a relationship to several collections, or `undefined`. */
|
|
1026
|
+
declare function polymorphicValue(value: unknown): {
|
|
1027
|
+
relationTo: string;
|
|
1028
|
+
value: unknown;
|
|
1029
|
+
} | undefined;
|
|
992
1030
|
/** Fields whose value is a list of rows: `array` and `blocks`. */
|
|
993
1031
|
declare const hasRows: (field: Field) => field is ArrayField | BlocksField;
|
|
994
1032
|
/** The fields of one row of an `array` or `blocks` field (`undefined` for an unknown block). */
|
|
@@ -1162,6 +1200,14 @@ type GlobalBySlug<C extends Config, S> = WithPluginFields<C, Extract<NonNullable
|
|
|
1162
1200
|
type RelationValue<C extends Config, S, A extends boolean> = [CollectionBySlug<C, S>] extends [
|
|
1163
1201
|
never
|
|
1164
1202
|
] ? ID | Record<string, unknown> : ID | CollectionDocument<C, S & string, A>;
|
|
1203
|
+
/**
|
|
1204
|
+
* A relationship to several collections (#327): `{ relationTo, value }` per collection, so
|
|
1205
|
+
* checking `relationTo` narrows `value`.
|
|
1206
|
+
*/
|
|
1207
|
+
type PolymorphicValue<C extends Config, To, V extends 'output' | 'input', A extends boolean> = To extends readonly (infer S)[] ? S extends string ? {
|
|
1208
|
+
relationTo: S;
|
|
1209
|
+
value: V extends 'input' ? ID : RelationValue<C, S, A>;
|
|
1210
|
+
} : never : never;
|
|
1165
1211
|
/** The content locales of a config (`localization.locales`); `string` when not literal. */
|
|
1166
1212
|
type LocaleOf<C extends Config> = C extends {
|
|
1167
1213
|
readonly localization: {
|
|
@@ -1174,6 +1220,11 @@ type LocaleOf<C extends Config> = C extends {
|
|
|
1174
1220
|
*/
|
|
1175
1221
|
type LocaleMap<F extends Field, C extends Config> = {
|
|
1176
1222
|
[L in LocaleOf<C>]?: (F extends {
|
|
1223
|
+
readonly type: 'relationship';
|
|
1224
|
+
readonly to: infer To extends readonly string[];
|
|
1225
|
+
} ? F extends {
|
|
1226
|
+
readonly hasMany: true;
|
|
1227
|
+
} ? PolymorphicValue<C, To, 'input', false>[] : PolymorphicValue<C, To, 'input', false> : F extends {
|
|
1177
1228
|
readonly type: 'relationship' | 'upload';
|
|
1178
1229
|
} ? F extends {
|
|
1179
1230
|
readonly hasMany: true;
|
|
@@ -1232,6 +1283,11 @@ type OneLocaleValue<F extends Field, C extends Config, A extends boolean> = F ex
|
|
|
1232
1283
|
} ? F extends {
|
|
1233
1284
|
readonly hasMany: true;
|
|
1234
1285
|
} ? (ID | MediaDocument)[] : ID | MediaDocument : F extends {
|
|
1286
|
+
readonly type: 'relationship';
|
|
1287
|
+
readonly to: infer To extends readonly string[];
|
|
1288
|
+
} ? F extends {
|
|
1289
|
+
readonly hasMany: true;
|
|
1290
|
+
} ? PolymorphicValue<C, To, 'output', A>[] : PolymorphicValue<C, To, 'output', A> : F extends {
|
|
1235
1291
|
readonly type: 'relationship';
|
|
1236
1292
|
readonly to: infer S;
|
|
1237
1293
|
} ? F extends {
|
|
@@ -1328,6 +1384,11 @@ type CollectionDocument<C extends Config, S extends CollectionSlug<C>, AllLocale
|
|
|
1328
1384
|
type GlobalDocument<C extends Config, S extends GlobalSlug<C>, AllLocales extends boolean = false> = InferGlobal<GlobalBySlug<C, S>, C, AllLocales>;
|
|
1329
1385
|
type InputValue<F extends Field> = F extends {
|
|
1330
1386
|
readonly type: 'relationship';
|
|
1387
|
+
readonly to: infer To extends readonly string[];
|
|
1388
|
+
} ? F extends {
|
|
1389
|
+
readonly hasMany: true;
|
|
1390
|
+
} ? readonly PolymorphicValue<Config, To, 'input', false>[] : PolymorphicValue<Config, To, 'input', false> : F extends {
|
|
1391
|
+
readonly type: 'relationship';
|
|
1331
1392
|
} ? F extends {
|
|
1332
1393
|
readonly hasMany: true;
|
|
1333
1394
|
} ? readonly ID[] : ID : F extends {
|
|
@@ -1392,6 +1453,24 @@ type CreateInput<C extends Config, S extends CollectionSlug<C>> = Simplify<Field
|
|
|
1392
1453
|
type UpdateInput<C extends Config, S extends CollectionSlug<C>> = Partial<CreateInput<C, S>>;
|
|
1393
1454
|
/** Data accepted by `updateGlobal`. */
|
|
1394
1455
|
type GlobalInput<C extends Config, S extends GlobalSlug<C>> = Partial<Simplify<FieldsInput<GlobalBySlug<C, S>['fields']> & StatusInput<GlobalBySlug<C, S>>>>;
|
|
1456
|
+
type BlocksOfField<F> = F extends {
|
|
1457
|
+
readonly type: 'richText';
|
|
1458
|
+
readonly blocks: readonly (infer B)[];
|
|
1459
|
+
} ? B : never;
|
|
1460
|
+
/**
|
|
1461
|
+
* The blocks of a rich text field, e.g. `RichTextBlocks<typeof config, 'posts', 'body'>`: a
|
|
1462
|
+
* union of `{ blockType, id, fields }`, for typed renderers in `@easy-cms/richtext`.
|
|
1463
|
+
*/
|
|
1464
|
+
type RichTextBlocks<C extends Config, S extends CollectionSlug<C>, F extends string> = BlocksOfField<Extract<CollectionBySlug<C, S>['fields'][number], {
|
|
1465
|
+
readonly name: F;
|
|
1466
|
+
}>> extends infer B ? B extends {
|
|
1467
|
+
readonly slug: infer Slug;
|
|
1468
|
+
readonly fields: infer Fs extends readonly Field[];
|
|
1469
|
+
} ? {
|
|
1470
|
+
blockType: Slug;
|
|
1471
|
+
id: string;
|
|
1472
|
+
fields: Simplify<FieldsValue<Fs, C, false>>;
|
|
1473
|
+
} : never : never;
|
|
1395
1474
|
|
|
1396
1475
|
/** What a role may do with a collection or global, ticked in Settings → Roles. */
|
|
1397
1476
|
declare const ROLE_OPERATIONS: readonly ["read", "create", "update", "delete", "publish"];
|
|
@@ -3821,5 +3900,5 @@ interface ResolvedConfig extends Omit<Config, 'cors' | 'localization' | 'routes'
|
|
|
3821
3900
|
*/
|
|
3822
3901
|
declare function defineConfig<const TConfig extends Config>(config: TConfig): TConfig;
|
|
3823
3902
|
|
|
3824
|
-
export { ADAPTER_API_VERSION as A, EasyCMS as E, AuditLog as _, Auth as a1, EasyCMSError as
|
|
3825
|
-
export type { AuditPage as $, AdminRoles as B, Config as C, AdminSso as D, Field as F, GlobalSlug as G, AdminSwitcher as H, ID as I, AdminViewAccess as J, AfterChangeHook as K, LocalizationConfig as L, AfterDeleteHook as M, AfterReadHook as N, ApiKeyContext as O, PaginatedDocs as P, ApiKeyGlobalOperation as Q, ResolvedConfig as R, ApiKeyOperation as S, ApiKeyPermissions as T, UncountedDocs as U, ArrayField as V, Where as W, AuditChange as X, AuditConfig as Y, AuditEntry as Z, CollectionSlug as a,
|
|
3903
|
+
export { ADAPTER_API_VERSION as A, EasyCMS as E, AuditLog as _, Auth as a1, EasyCMSError as aJ, FIELD_TYPES as aQ, ConfigError as as, ForbiddenError as b8, PLUGIN_API_VERSION as bF, PayloadTooLargeError as bK, QueryError as bQ, ROLE_OPERATIONS as bR, NotFoundError as bz, jsonLogger as c$, Roles as c1, SchemaError as c4, ValidationError as cE, WEBHOOK_EVENTS as cI, anyone as cM, consoleEmail as cN, consoleLogger as cO, createEasyCMS as cP, defineConfig as cQ, defineFieldType as cR, definePlugin as cS, diskStorage as cT, hasRows as cU, isAdmin as cV, isHasMany as cW, isPolymorphic as cX, isSignedIn as cY, isStaff as cZ, isSystemAdmin as c_, SingleSignOn as cj, TRIGRAM_LIKE_MIN as cq, TooManyRequestsError as cu, UnauthorizedError as cx, memorySearch as d0, mimeAllowedBy as d1, polymorphicValue as d2, relationTargets as d3, rowFields as d4, silentLogger as d5, uniqueWithinOf as d6, API_KEYS as d7, API_KEY_GLOBAL_OPERATIONS as d8, API_KEY_OPERATIONS as d9, DEFAULT_MAX_VERSIONS as da, DEFAULT_PASSWORD_EMAILS as db, FIELD_TYPE_BASES as dc, FOLDER_LEVELS as dd, MediaFolders as de, SSO_COOKIE as df, codeOfStatus as dh, isJsonLogger as di, keyAllows as dj, logFormat as dk, secretsOf as dl, ADMIN_ICONS as j };
|
|
3904
|
+
export type { AuditPage as $, AdminRoles as B, Config as C, AdminSso as D, Field as F, GlobalSlug as G, AdminSwitcher as H, ID as I, AdminViewAccess as J, AfterChangeHook as K, LocalizationConfig as L, AfterDeleteHook as M, AfterReadHook as N, ApiKeyContext as O, PaginatedDocs as P, ApiKeyGlobalOperation as Q, ResolvedConfig as R, ApiKeyOperation as S, ApiKeyPermissions as T, UncountedDocs as U, ArrayField as V, Where as W, AuditChange as X, AuditConfig as Y, AuditEntry as Z, CollectionSlug as a, FieldValue as a$, AuditVerification as a0, AuthConfig as a2, AuthProvider as a3, AuthProviderProfile as a4, AuthProviderRequest as a5, AuthUser as a6, BackupsConfig as a7, BeforeChangeHook as a8, BeforeDeleteHook as a9, Database as aA, DatabaseAdapter as aB, DatabaseInitArgs as aC, DatabaseTransfer as aD, DateField as aE, DepthOptions as aF, DirectUpload as aG, DiskStorageOptions as aH, DocumentOf as aI, EmailAdapter as aK, EmailField as aL, EmailMessage as aM, Endpoint as aN, EndpointRequest as aO, ErrorCode as aP, FieldAccess as aR, FieldAccessFn as aS, FieldAdmin as aT, FieldRule as aU, FieldType as aV, FieldTypeBase as aW, FieldTypeDefinition as aX, FieldTypeValidateContext as aY, FieldValidate as aZ, FieldValidateContext as a_, BeforeValidateHook as aa, Block as ab, BlockSummaryArgs as ac, BlocksField as ad, BooleanField as ae, BuiltinApiKeysCollection as af, BuiltinMediaCollection as ag, BuiltinMediaFoldersCollection as ah, BuiltinUsersCollection as ai, BundleHints as aj, CliCommand as ak, CollectionAccess as al, CollectionAdmin as am, CollectionCalendarAdmin as an, CollectionConfig as ao, CollectionHooks as ap, CollectionListAdmin as aq, CollectionSearch as ar, ConfigIssue as at, ContainerAdmin as au, CreateInput as av, CreateMigrationResult as aw, CustomField as ax, CustomFieldTypes as ay, DashboardWidget as az, CollectionDocument as b, RoleOperation as b$, FieldsInput as b0, FieldsValue as b1, FilterOptionsArgs as b2, FindAfterArgs as b3, FindArgs as b4, FindOptions as b5, FolderLevel as b6, FolderPermissions as b7, GlobalAccess as b9, NumberField as bA, OnRequest as bB, OnRequestArgs as bC, Operation as bD, OutboxRow as bE, PasswordEmail as bG, PasswordEmailArgs as bH, PasswordEmailFn as bI, PasswordLinkOptions as bJ, Plugin as bL, PluginInfo as bM, PluginTypes as bN, PreviewTarget as bO, PreviewURL as bP, RawDocument as bS, ReadOptions as bT, RelationshipField as bU, RequestContext as bV, RichTextBlock as bW, RichTextBlocks as bX, RichTextDocument as bY, RichTextField as bZ, Role as b_, GlobalConfig as ba, GlobalHooks as bb, GlobalInput as bc, GroupField as bd, ImageSize as be, IncrementOptions as bf, InferCollection as bg, InferGlobal as bh, JobConfig as bi, JsonField as bj, KeysetPage as bk, Label as bl, LayoutNode as bm, LivePreview as bn, LocaleOf as bo, LogDetails as bp, Logger as bq, LoginArgs as br, LogsConfig as bs, MediaDocument as bt, MediaSize as bu, MembersConfig as bv, MembersSignup as bw, MigrationInfo as bx, NavGroup as by, CursorDocs as c, RolePermissions as c0, RoutesConfig as c2, ScheduledPublish as c3, SchemaMode as c5, SearchAdapter as c6, SearchEntry as c7, SearchHits as c8, SearchOptions as c9, UploadConfig as cA, UploadField as cB, UploadFromURLConfig as cC, UserIdentity as cD, Version as cF, VersionSummary as cG, VersionsConfig as cH, WebhookConfig as cJ, WebhookEvent as cK, WhereOperators as cL, SearchQuery as ca, SearchResults as cb, SearchSetting as cc, SelectField as cd, SelectOption as ce, Session as cf, SidebarPanel as cg, SignupArgs as ch, SignupResult as ci, SlugField as ck, SlugOf as cl, SsoOutcome as cm, SsoProviderRef as cn, StorageAdapter as co, StoredFile as cp, TelemetryConfig as cr, TextField as cs, TextareaField as ct, TypedPlugin as cv, UiField as cw, UpdateInput as cy, UpdateOptions as cz, GlobalDocument as d, Secrets as dg, FieldError as e, FilterOptions as f, CreateEasyCMSOptions as g, EmailSetting as h, WebhookPayload as i, Access as k, AccessArgs as l, AccessOptions as m, AdminBrand as n, AdminCommand as o, AdminComponent as p, AdminConfig as q, AdminFieldArgs as r, AdminIcon as s, AdminLocale as t, AdminPage as u, AdminRole as v, AdminRoleChange as w, AdminRoleField as x, AdminRoleTarget as y, AdminRoleView as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as ID, C as Config, E as EasyCMS, L as LocalizationConfig, F as Field, e as FieldError, f as FilterOptions, g as CreateEasyCMSOptions, R as ResolvedConfig } from './config-
|
|
1
|
+
import { I as ID, C as Config, E as EasyCMS, L as LocalizationConfig, F as Field, e as FieldError, f as FilterOptions, g as CreateEasyCMSOptions, R as ResolvedConfig } from './config-DGATdBdP.js';
|
|
2
2
|
|
|
3
3
|
/** Decrypts a file from `encryptBackup`; throws for another key or a changed file. */
|
|
4
4
|
declare function decryptBackup(data: Uint8Array, encryptionKey: string): Uint8Array;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PaginatedDocs, I as ID, h as EmailSetting, i as WebhookPayload } from './config-
|
|
2
|
-
export { A as ADAPTER_API_VERSION, j as ADMIN_ICONS, k as Access, l as AccessArgs, m as AccessOptions, n as AdminBrand, o as AdminCommand, p as AdminComponent, q as AdminConfig, r as AdminFieldArgs, s as AdminIcon, t as AdminLocale, u as AdminPage, v as AdminRole, w as AdminRoleChange, x as AdminRoleField, y as AdminRoleTarget, z as AdminRoleView, B as AdminRoles, D as AdminSso, H as AdminSwitcher, J as AdminViewAccess, K as AfterChangeHook, M as AfterDeleteHook, N as AfterReadHook, O as ApiKeyContext, Q as ApiKeyGlobalOperation, S as ApiKeyOperation, T as ApiKeyPermissions, V as ArrayField, X as AuditChange, Y as AuditConfig, Z as AuditEntry, _ as AuditLog, $ as AuditPage, a0 as AuditVerification, a1 as Auth, a2 as AuthConfig, a3 as AuthProvider, a4 as AuthProviderProfile, a5 as AuthProviderRequest, a6 as AuthUser, a7 as BackupsConfig, a8 as BeforeChangeHook, a9 as BeforeDeleteHook, aa as BeforeValidateHook, ab as Block, ac as
|
|
3
|
-
export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-
|
|
4
|
-
export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler-
|
|
1
|
+
import { P as PaginatedDocs, I as ID, h as EmailSetting, i as WebhookPayload } from './config-DGATdBdP.js';
|
|
2
|
+
export { A as ADAPTER_API_VERSION, j as ADMIN_ICONS, k as Access, l as AccessArgs, m as AccessOptions, n as AdminBrand, o as AdminCommand, p as AdminComponent, q as AdminConfig, r as AdminFieldArgs, s as AdminIcon, t as AdminLocale, u as AdminPage, v as AdminRole, w as AdminRoleChange, x as AdminRoleField, y as AdminRoleTarget, z as AdminRoleView, B as AdminRoles, D as AdminSso, H as AdminSwitcher, J as AdminViewAccess, K as AfterChangeHook, M as AfterDeleteHook, N as AfterReadHook, O as ApiKeyContext, Q as ApiKeyGlobalOperation, S as ApiKeyOperation, T as ApiKeyPermissions, V as ArrayField, X as AuditChange, Y as AuditConfig, Z as AuditEntry, _ as AuditLog, $ as AuditPage, a0 as AuditVerification, a1 as Auth, a2 as AuthConfig, a3 as AuthProvider, a4 as AuthProviderProfile, a5 as AuthProviderRequest, a6 as AuthUser, a7 as BackupsConfig, a8 as BeforeChangeHook, a9 as BeforeDeleteHook, aa as BeforeValidateHook, ab as Block, ac as BlockSummaryArgs, ad as BlocksField, ae as BooleanField, af as BuiltinApiKeysCollection, ag as BuiltinMediaCollection, ah as BuiltinMediaFoldersCollection, ai as BuiltinUsersCollection, aj as BundleHints, ak as CliCommand, al as CollectionAccess, am as CollectionAdmin, an as CollectionCalendarAdmin, ao as CollectionConfig, b as CollectionDocument, ap as CollectionHooks, aq as CollectionListAdmin, ar as CollectionSearch, a as CollectionSlug, C as Config, as as ConfigError, at as ConfigIssue, au as ContainerAdmin, g as CreateEasyCMSOptions, av as CreateInput, aw as CreateMigrationResult, c as CursorDocs, ax as CustomField, ay as CustomFieldTypes, az as DashboardWidget, aA as Database, aB as DatabaseAdapter, aC as DatabaseInitArgs, aD as DatabaseTransfer, aE as DateField, aF as DepthOptions, aG as DirectUpload, aH as DiskStorageOptions, aI as DocumentOf, E as EasyCMS, aJ as EasyCMSError, aK as EmailAdapter, aL as EmailField, aM as EmailMessage, aN as Endpoint, aO as EndpointRequest, aP as ErrorCode, aQ as FIELD_TYPES, F as Field, aR as FieldAccess, aS as FieldAccessFn, aT as FieldAdmin, e as FieldError, aU as FieldRule, aV as FieldType, aW as FieldTypeBase, aX as FieldTypeDefinition, aY as FieldTypeValidateContext, aZ as FieldValidate, a_ as FieldValidateContext, a$ as FieldValue, b0 as FieldsInput, b1 as FieldsValue, f as FilterOptions, b2 as FilterOptionsArgs, b3 as FindAfterArgs, b4 as FindArgs, b5 as FindOptions, b6 as FolderLevel, b7 as FolderPermissions, b8 as ForbiddenError, b9 as GlobalAccess, ba as GlobalConfig, d as GlobalDocument, bb as GlobalHooks, bc as GlobalInput, G as GlobalSlug, bd as GroupField, be as ImageSize, bf as IncrementOptions, bg as InferCollection, bh as InferGlobal, bi as JobConfig, bj as JsonField, bk as KeysetPage, bl as Label, bm as LayoutNode, bn as LivePreview, bo as LocaleOf, L as LocalizationConfig, bp as LogDetails, bq as Logger, br as LoginArgs, bs as LogsConfig, bt as MediaDocument, bu as MediaSize, bv as MembersConfig, bw as MembersSignup, bx as MigrationInfo, by as NavGroup, bz as NotFoundError, bA as NumberField, bB as OnRequest, bC as OnRequestArgs, bD as Operation, bE as OutboxRow, bF as PLUGIN_API_VERSION, bG as PasswordEmail, bH as PasswordEmailArgs, bI as PasswordEmailFn, bJ as PasswordLinkOptions, bK as PayloadTooLargeError, bL as Plugin, bM as PluginInfo, bN as PluginTypes, bO as PreviewTarget, bP as PreviewURL, bQ as QueryError, bR as ROLE_OPERATIONS, bS as RawDocument, bT as ReadOptions, bU as RelationshipField, bV as RequestContext, R as ResolvedConfig, bW as RichTextBlock, bX as RichTextBlocks, bY as RichTextDocument, bZ as RichTextField, b_ as Role, b$ as RoleOperation, c0 as RolePermissions, c1 as Roles, c2 as RoutesConfig, c3 as ScheduledPublish, c4 as SchemaError, c5 as SchemaMode, c6 as SearchAdapter, c7 as SearchEntry, c8 as SearchHits, c9 as SearchOptions, ca as SearchQuery, cb as SearchResults, cc as SearchSetting, cd as SelectField, ce as SelectOption, cf as Session, cg as SidebarPanel, ch as SignupArgs, ci as SignupResult, cj as SingleSignOn, ck as SlugField, cl as SlugOf, cm as SsoOutcome, cn as SsoProviderRef, co as StorageAdapter, cp as StoredFile, cq as TRIGRAM_LIKE_MIN, cr as TelemetryConfig, cs as TextField, ct as TextareaField, cu as TooManyRequestsError, cv as TypedPlugin, cw as UiField, cx as UnauthorizedError, U as UncountedDocs, cy as UpdateInput, cz as UpdateOptions, cA as UploadConfig, cB as UploadField, cC as UploadFromURLConfig, cD as UserIdentity, cE as ValidationError, cF as Version, cG as VersionSummary, cH as VersionsConfig, cI as WEBHOOK_EVENTS, cJ as WebhookConfig, cK as WebhookEvent, W as Where, cL as WhereOperators, cM as anyone, cN as consoleEmail, cO as consoleLogger, cP as createEasyCMS, cQ as defineConfig, cR as defineFieldType, cS as definePlugin, cT as diskStorage, cU as hasRows, cV as isAdmin, cW as isHasMany, cX as isPolymorphic, cY as isSignedIn, cZ as isStaff, c_ as isSystemAdmin, c$ as jsonLogger, d0 as memorySearch, d1 as mimeAllowedBy, d2 as polymorphicValue, d3 as relationTargets, d4 as rowFields, d5 as silentLogger, d6 as uniqueWithinOf } from './config-DGATdBdP.js';
|
|
3
|
+
export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-B6lp3qVf.js';
|
|
4
|
+
export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler-DsA868nd.js';
|
|
5
5
|
export { FieldCondition, matchesCondition } from './conditions.js';
|
|
6
6
|
|
|
7
7
|
type DeliveryKind = 'webhook' | 'email';
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
silentLogger,
|
|
29
29
|
slugify,
|
|
30
30
|
verifyWebhook
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-JTBPGZMF.js";
|
|
32
32
|
import {
|
|
33
33
|
matchesCondition
|
|
34
34
|
} from "./chunk-U266LV4M.js";
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
defineFieldType,
|
|
54
54
|
definePlugin,
|
|
55
55
|
warnDeprecated
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-X4SI2QB7.js";
|
|
57
57
|
export {
|
|
58
58
|
ADAPTER_API_VERSION,
|
|
59
59
|
ADMIN_API_VERSION,
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Config, Database, EasyCMS, NavGroup, CollectionConfig, ID, RawDocument, Field, ResolvedConfig, ConfigIssue } from './index.js';
|
|
2
|
-
export {
|
|
3
|
-
export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as isEmail, y as mergeForUpdate, z as parseId, E as platformClientIp, F as readCookie, G as validateFields, H as writeBackupFile } from './handler-
|
|
2
|
+
export { d7 as API_KEYS, d8 as API_KEY_GLOBAL_OPERATIONS, d9 as API_KEY_OPERATIONS, da as DEFAULT_MAX_VERSIONS, db as DEFAULT_PASSWORD_EMAILS, dc as FIELD_TYPE_BASES, dd as FOLDER_LEVELS, de as MediaFolders, df as SSO_COOKIE, dg as Secrets, cq as TRIGRAM_LIKE_MIN, dh as codeOfStatus, cU as hasRows, cW as isHasMany, di as isJsonLogger, cX as isPolymorphic, dj as keyAllows, dk as logFormat, d1 as mimeAllowedBy, d2 as polymorphicValue, d3 as relationTargets, d4 as rowFields, dl as secretsOf, d6 as uniqueWithinOf } from './config-DGATdBdP.js';
|
|
3
|
+
export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as isEmail, y as mergeForUpdate, z as parseId, E as platformClientIp, F as readCookie, G as validateFields, H as writeBackupFile } from './handler-DsA868nd.js';
|
|
4
4
|
export { conditionIssues } from './conditions.js';
|
|
5
5
|
|
|
6
6
|
/** The session cookie the REST API sets at login. */
|
package/dist/internal.js
CHANGED
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
verifyPassword,
|
|
59
59
|
verifyTurnstile,
|
|
60
60
|
writeBackupFile
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-JTBPGZMF.js";
|
|
62
62
|
import {
|
|
63
63
|
conditionIssues
|
|
64
64
|
} from "./chunk-U266LV4M.js";
|
|
@@ -72,12 +72,15 @@ import {
|
|
|
72
72
|
hasRows,
|
|
73
73
|
imageDimensions,
|
|
74
74
|
isHasMany,
|
|
75
|
+
isPolymorphic,
|
|
75
76
|
mimeAllowed,
|
|
76
77
|
mimeAllowedBy,
|
|
78
|
+
polymorphicValue,
|
|
79
|
+
relationTargets,
|
|
77
80
|
rowFields,
|
|
78
81
|
sniffMimeType,
|
|
79
82
|
uniqueWithinOf
|
|
80
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-X4SI2QB7.js";
|
|
81
84
|
|
|
82
85
|
// src/typegen.ts
|
|
83
86
|
var pascal = (name) => name.split(/[^A-Za-z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
@@ -88,6 +91,7 @@ function singularize(word) {
|
|
|
88
91
|
return word.replace(/s$/i, "");
|
|
89
92
|
}
|
|
90
93
|
var quote = (value) => JSON.stringify(value);
|
|
94
|
+
var idOr = (type) => type ? `ID | ${type}` : "ID";
|
|
91
95
|
var key = (name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : quote(name);
|
|
92
96
|
function names(config) {
|
|
93
97
|
const taken = /* @__PURE__ */ new Set(["ID", "RichTextDocument", "MediaSize", "Collections", "Globals"]);
|
|
@@ -137,8 +141,9 @@ function fieldType(field, n, indent) {
|
|
|
137
141
|
return field.hasMany ? `(${one})[]` : one;
|
|
138
142
|
}
|
|
139
143
|
case "relationship": {
|
|
140
|
-
const
|
|
141
|
-
|
|
144
|
+
const one = typeof field.to === "string" ? idOr(n.collections.get(field.to)) : field.to.map(
|
|
145
|
+
(slug) => `{ relationTo: ${quote(slug)}; value: ${idOr(n.collections.get(slug))} }`
|
|
146
|
+
).join(" | ");
|
|
142
147
|
return field.hasMany ? `(${one})[]` : one;
|
|
143
148
|
}
|
|
144
149
|
case "group":
|
|
@@ -229,6 +234,30 @@ function generateTypes(config) {
|
|
|
229
234
|
for (const global of config.globals) {
|
|
230
235
|
parts.push("", globalInterface(global, n.globals.get(global.slug), n));
|
|
231
236
|
}
|
|
237
|
+
const owners = [
|
|
238
|
+
...config.collections.map((c) => ({ fields: c.fields, name: n.collections.get(c.slug) })),
|
|
239
|
+
...config.globals.map((g) => ({ fields: g.fields, name: n.globals.get(g.slug) }))
|
|
240
|
+
];
|
|
241
|
+
for (const { fields, name } of owners) {
|
|
242
|
+
if (!name) continue;
|
|
243
|
+
for (const field of fields) {
|
|
244
|
+
if (field.type !== "richText" || !field.blocks?.length) continue;
|
|
245
|
+
const kinds = field.blocks.map(
|
|
246
|
+
(block) => `{
|
|
247
|
+
blockType: ${quote(block.slug)}
|
|
248
|
+
id: string
|
|
249
|
+
fields: {
|
|
250
|
+
${fieldLines(block.fields, n, " ").join("\n")}
|
|
251
|
+
}
|
|
252
|
+
}`
|
|
253
|
+
);
|
|
254
|
+
parts.push(
|
|
255
|
+
"",
|
|
256
|
+
`/** A block in \`${name}.${field.name}\`: \`{ type: 'block', attrs }\` in the document. */`,
|
|
257
|
+
`export type ${name}${pascal(field.name)}Block = ${kinds.join(" | ")}`
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
232
261
|
const map = (entries) => [...entries].map(([slug, name]) => ` ${key(slug)}: ${name}`).join("\n");
|
|
233
262
|
parts.push(
|
|
234
263
|
"",
|
|
@@ -303,6 +332,7 @@ export {
|
|
|
303
332
|
isEmail,
|
|
304
333
|
isHasMany,
|
|
305
334
|
isJsonLogger,
|
|
335
|
+
isPolymorphic,
|
|
306
336
|
keyAllows,
|
|
307
337
|
logFormat,
|
|
308
338
|
mergeForUpdate,
|
|
@@ -310,9 +340,11 @@ export {
|
|
|
310
340
|
mimeAllowedBy,
|
|
311
341
|
parseId,
|
|
312
342
|
platformClientIp,
|
|
343
|
+
polymorphicValue,
|
|
313
344
|
populate,
|
|
314
345
|
rateKeys,
|
|
315
346
|
readCookie,
|
|
347
|
+
relationTargets,
|
|
316
348
|
resolveAdminModule,
|
|
317
349
|
rowFields,
|
|
318
350
|
secretsOf,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { bl as Label, F as Field, I as ID, t as AdminLocale, H as AdminSwitcher, cn as SsoProviderRef } from './config-DGATdBdP.js';
|
|
2
2
|
import { FieldCondition } from './conditions.js';
|
|
3
3
|
|
|
4
4
|
/** A Web Component from an admin module, with its `props` (plain JSON). */
|
|
@@ -67,7 +67,8 @@ interface AdminField {
|
|
|
67
67
|
value: string;
|
|
68
68
|
}[];
|
|
69
69
|
hasMany?: boolean;
|
|
70
|
-
to
|
|
70
|
+
/** Several for a relationship to several collections (#327). */
|
|
71
|
+
to?: string | string[];
|
|
71
72
|
/** An upload's allowed file types, e.g. `image/*`. */
|
|
72
73
|
mimeTypes?: string[];
|
|
73
74
|
/** An upload's media folder (`folder`): where its picker opens; `only`: nowhere else. */
|
|
@@ -89,6 +90,11 @@ interface AdminField {
|
|
|
89
90
|
plural?: Label;
|
|
90
91
|
};
|
|
91
92
|
fields: AdminField[];
|
|
93
|
+
/**
|
|
94
|
+
* Rich text blocks (#328): the card's text comes from the server (`'server'`, the block's
|
|
95
|
+
* `admin.summary` function) or a custom element (its tag).
|
|
96
|
+
*/
|
|
97
|
+
summary?: string;
|
|
92
98
|
}[];
|
|
93
99
|
/** The current user may not change this field. */
|
|
94
100
|
readOnly?: boolean;
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { j as ADMIN_ICONS, p as AdminComponent, s as AdminIcon, a6 as AuthUser,
|
|
2
|
-
export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-
|
|
1
|
+
export { j as ADMIN_ICONS, p as AdminComponent, s as AdminIcon, a6 as AuthUser, ak as CliCommand, al as CollectionAccess, ao as CollectionConfig, C as Config, as as ConfigError, az as DashboardWidget, aJ as EasyCMSError, aN as Endpoint, aO as EndpointRequest, aP as ErrorCode, F as Field, aR as FieldAccess, e as FieldError, aW as FieldTypeBase, aX as FieldTypeDefinition, aY as FieldTypeValidateContext, b8 as ForbiddenError, ba as GlobalConfig, I as ID, bi as JobConfig, bl as Label, by as NavGroup, bz as NotFoundError, bB as OnRequest, bC as OnRequestArgs, bF as PLUGIN_API_VERSION, bK as PayloadTooLargeError, bL as Plugin, bM as PluginInfo, bN as PluginTypes, bQ as QueryError, bV as RequestContext, cu as TooManyRequestsError, cv as TypedPlugin, cx as UnauthorizedError, cE as ValidationError, W as Where, cR as defineFieldType, cS as definePlugin } from './config-DGATdBdP.js';
|
|
2
|
+
export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-B6lp3qVf.js';
|
|
3
3
|
import './conditions.js';
|
package/dist/plugin.js
CHANGED