@bison-lab/payload-core 3.12.0 → 3.14.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/README.md +70 -16
- package/dist/access-B3LglN2J.mjs +662 -0
- package/dist/access-B3LglN2J.mjs.map +1 -0
- package/dist/admin.d.mts +49 -10
- package/dist/admin.d.mts.map +1 -1
- package/dist/admin.mjs +761 -73
- package/dist/admin.mjs.map +1 -1
- package/dist/{identity-DZOb3_Gk.mjs → identity-Dwyq8519.mjs} +48 -2
- package/dist/identity-Dwyq8519.mjs.map +1 -0
- package/dist/index.d.mts +309 -64
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +316 -278
- package/dist/index.mjs.map +1 -1
- package/dist/looks-BbL309kO.mjs.map +1 -1
- package/dist/{looks-CLxXwASa.d.mts → looks-Xs6v5vYU.d.mts} +21 -2
- package/dist/looks-Xs6v5vYU.d.mts.map +1 -0
- package/dist/metadata.d.mts +1 -1
- package/dist/metadata.mjs +1 -1
- package/dist/{share-image-C4ILz4p2.mjs → share-image-BlFAJLnd.mjs} +1 -1
- package/dist/{share-image-C4ILz4p2.mjs.map → share-image-BlFAJLnd.mjs.map} +1 -1
- package/dist/theme.d.mts +2 -2
- package/dist/theme.mjs +2 -2
- package/dist/{title-B2-gWQZd.d.mts → title-sWwcCqHT.d.mts} +1 -1
- package/dist/{title-B2-gWQZd.d.mts.map → title-sWwcCqHT.d.mts.map} +1 -1
- package/package.json +3 -3
- package/dist/identity-DZOb3_Gk.mjs.map +0 -1
- package/dist/looks-CLxXwASa.d.mts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
1
|
+
import { $ as defaultFeaturesFieldValue, A as ROLES_SLUG, B as CAPABILITIES, C as DUPLICATE_ROLE_NAME_MESSAGE, D as MISSING_SEED_ROLES_MESSAGE, E as LAST_USERS_TICK_MESSAGE, F as resetRolesMatrix, G as THEME_FEATURE_SLUGS, H as DEFAULT_ROLE_GRANTS, I as roleDescription, J as isRoleSlug, K as isRole, L as roleSelectOptions, M as defaultRolesFieldValue, N as normalizeStoredRoles, O as ROLES_FIELD_DESCRIPTION, P as parseRolesMatrix, Q as MISSING_PACKAGE_FEATURES_MESSAGE, R as seedRoleRows, S as DEVELOPER_DESCRIPTION, T as INVALID_ROLE_NAME_MESSAGE, U as ROLES, V as CAPABILITY_FEATURES, W as ROLE_LABELS, X as sanitizeRoleNameInput, Y as roleLabel, Z as slugifyRoleName, _ as isDeveloper, a as hideUnlessFeature, at as FEATURES_SLUG, b as storedRoles, c as canManageContent, ct as PACKAGE_FEATURES, d as hasCapability, dt as isFeatureSlug, et as featureCatalogue, f as hasGrant, ft as isLockedFeature, g as isAuthenticated, h as isAdminOrSelf, i as hasFeature, it as validateFeaturesMatrix, j as applyRoleSlugsFromNames, k as ROLES_GLOBAL_DESCRIPTION, l as canPublish, lt as PACKAGE_FEATURE_SLUGS, m as isAdmin, n as canUseFeature, nt as parseFeaturesMatrix, o as authenticatedOrPublished, ot as FEATURE_GROUPS, p as hasRole, pt as isPackageFeatureSlug, q as isRoleName, r as getFeaturesMatrix, rt as stampFeatureCatalogue, s as canManageBrand, st as FEATURE_GROUP_LABELS, tt as featureGroupLabel, u as getRolesMatrix, ut as isFeatureGroupId, v as isDeveloperTab, w as DUPLICATE_ROLE_SLUG_MESSAGE, x as DEFAULT_ROLE_MATRIX, y as isPrivilegedRole, z as validateRolesMatrix } from "./access-B3LglN2J.mjs";
|
|
2
|
+
import { n as documentTitle, r as titleTemplate, t as SHARE_IMAGE_SIZE } from "./share-image-BlFAJLnd.mjs";
|
|
3
|
+
import { A as THEME_FONT_FIELD, C as validateThemeHex, D as THEME_COLOR_SCALE_FIELD, E as THEME_COLOR_FIELD, F as THEME_PUBLISH_FIELD, I as THEME_SAVE_BUTTON, L as THEME_SECTION_HEADING, M as THEME_IDENTITY_FALLBACK, N as THEME_LIBRARY_FIELD, O as THEME_CONTRAST_REPORT, P as THEME_PAIRING_FIELD, R as headingSelectValue, S as validateSourceIncluded, T as THEME_APPEARANCE_FIELD, _ as THEME_SLUG, a as pageEditorLooks, c as findColorTokens, d as rewriteColorToken, f as themeColorKeys, g as THEME_IDENTITY_SLUG, h as THEME_COLORS_SLUG, i as PAGE_EDITOR_SYSTEM_KEYS, j as THEME_GREY_SCALE_FIELD, k as THEME_DOCUMENT_CONTROLS, l as rewriteColorTokens, m as THEME_APPEARANCE_SLUG, n as colorTokenField, o as pageEditorTokens, p as SYSTEM_COLOR_KEYS, r as lookField, s as themeLibraryFromDoc, t as resolveThemeIdentity, u as deleteLibraryColor, v as THEME_TYPOGRAPHY_SLUG, w as LOOK_FIELD, x as themeConfigFromDoc, y as docFromConfig } from "./identity-Dwyq8519.mjs";
|
|
3
4
|
import { seoPlugin as seoPlugin$1 } from "@payloadcms/plugin-seo";
|
|
4
5
|
import { catalog } from "@bison-lab/fonts";
|
|
5
6
|
import { DESTRUCTIVE_SCALE_HEX, SHADE_STEPS, presetHints } from "@bison-lab/tokens";
|
|
@@ -164,6 +165,145 @@ const APPEARANCE_CHOICES = {
|
|
|
164
165
|
}
|
|
165
166
|
};
|
|
166
167
|
//#endregion
|
|
168
|
+
//#region src/theme/color-usages.ts
|
|
169
|
+
/** Theme-store REST path. LibraryField calls `/api/globals/theme` + this. */
|
|
170
|
+
const COLOR_USAGES_PATH = "/color-usages";
|
|
171
|
+
/**
|
|
172
|
+
* Walk every current document in the named collections and globals
|
|
173
|
+
* (drafts included). A color only on an unpublished page is still in use.
|
|
174
|
+
*/
|
|
175
|
+
async function findColorUsages(payload, scopes, key) {
|
|
176
|
+
const usages = [];
|
|
177
|
+
for (const collection of scopes?.collections ?? []) for await (const doc of eachCollectionDoc(payload, collection)) for (const hit of findColorTokens(doc, key)) usages.push({
|
|
178
|
+
collection,
|
|
179
|
+
id: idOf(doc),
|
|
180
|
+
path: hit.path,
|
|
181
|
+
token: hit.token
|
|
182
|
+
});
|
|
183
|
+
for (const slug of scopes?.globals ?? []) {
|
|
184
|
+
const doc = await payload.findGlobal({
|
|
185
|
+
slug,
|
|
186
|
+
draft: true,
|
|
187
|
+
depth: 0,
|
|
188
|
+
overrideAccess: true
|
|
189
|
+
});
|
|
190
|
+
if (!doc) continue;
|
|
191
|
+
for (const hit of findColorTokens(doc, key)) usages.push({
|
|
192
|
+
global: slug,
|
|
193
|
+
path: hit.path,
|
|
194
|
+
token: hit.token
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return usages;
|
|
198
|
+
}
|
|
199
|
+
async function rewriteColorUsages(payload, scopes, fromKey, toKey) {
|
|
200
|
+
for (const collection of scopes?.collections ?? []) for await (const doc of eachCollectionDoc(payload, collection)) {
|
|
201
|
+
if (findColorTokens(doc, fromKey).length === 0) continue;
|
|
202
|
+
const { id: _id, ...data } = rewriteColorTokens(doc, fromKey, toKey);
|
|
203
|
+
const id = idOf(doc);
|
|
204
|
+
if (id == null) continue;
|
|
205
|
+
await payload.update({
|
|
206
|
+
collection,
|
|
207
|
+
id,
|
|
208
|
+
data,
|
|
209
|
+
draft: true,
|
|
210
|
+
overrideAccess: true
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
for (const slug of scopes?.globals ?? []) {
|
|
214
|
+
const doc = await payload.findGlobal({
|
|
215
|
+
slug,
|
|
216
|
+
draft: true,
|
|
217
|
+
depth: 0,
|
|
218
|
+
overrideAccess: true
|
|
219
|
+
});
|
|
220
|
+
if (!doc || findColorTokens(doc, fromKey).length === 0) continue;
|
|
221
|
+
await payload.updateGlobal({
|
|
222
|
+
slug,
|
|
223
|
+
data: rewriteColorTokens(doc, fromKey, toKey),
|
|
224
|
+
draft: true,
|
|
225
|
+
overrideAccess: true
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async function replacementKeys(payload, except) {
|
|
230
|
+
return pageEditorLooks(await payload.findGlobal({
|
|
231
|
+
slug: THEME_SLUG,
|
|
232
|
+
depth: 0,
|
|
233
|
+
overrideAccess: true
|
|
234
|
+
})).map((look) => look.value).filter((key) => key !== except);
|
|
235
|
+
}
|
|
236
|
+
async function* eachCollectionDoc(payload, collection) {
|
|
237
|
+
let page = 1;
|
|
238
|
+
for (;;) {
|
|
239
|
+
const result = await payload.find({
|
|
240
|
+
collection,
|
|
241
|
+
draft: true,
|
|
242
|
+
depth: 0,
|
|
243
|
+
limit: 100,
|
|
244
|
+
page,
|
|
245
|
+
overrideAccess: true
|
|
246
|
+
});
|
|
247
|
+
for (const doc of result.docs) yield doc;
|
|
248
|
+
const totalPages = result.totalPages ?? (result.docs.length < 100 ? page : page + 1);
|
|
249
|
+
if (page >= totalPages || result.docs.length === 0) break;
|
|
250
|
+
page += 1;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function idOf(doc) {
|
|
254
|
+
const id = doc.id;
|
|
255
|
+
return typeof id === "string" || typeof id === "number" ? id : void 0;
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/theme/color-usage-endpoints.ts
|
|
259
|
+
function colorUsageEndpoints(access, scopes) {
|
|
260
|
+
return [{
|
|
261
|
+
path: COLOR_USAGES_PATH,
|
|
262
|
+
method: "get",
|
|
263
|
+
handler: async (req) => {
|
|
264
|
+
const denied = await denyUnlessUpdate(req, access.update);
|
|
265
|
+
if (denied) return denied;
|
|
266
|
+
const key = queryKey(req);
|
|
267
|
+
if (!key) return Response.json({ error: "key is required" }, { status: 400 });
|
|
268
|
+
const usages = await findColorUsages(req.payload, scopes, key);
|
|
269
|
+
return Response.json({ usages });
|
|
270
|
+
}
|
|
271
|
+
}, {
|
|
272
|
+
path: COLOR_USAGES_PATH,
|
|
273
|
+
method: "post",
|
|
274
|
+
handler: async (req) => {
|
|
275
|
+
const denied = await denyUnlessUpdate(req, access.update);
|
|
276
|
+
if (denied) return denied;
|
|
277
|
+
const body = await readJson(req);
|
|
278
|
+
const key = typeof body?.key === "string" ? body.key : "";
|
|
279
|
+
const replacement = typeof body?.replacement === "string" ? body.replacement : "";
|
|
280
|
+
if (!key || !replacement) return Response.json({ error: "key and replacement are required" }, { status: 400 });
|
|
281
|
+
if (!(await replacementKeys(req.payload, key)).includes(replacement)) return Response.json({ error: "Replacement must be a different live system or remaining custom key" }, { status: 400 });
|
|
282
|
+
await rewriteColorUsages(req.payload, scopes, key, replacement);
|
|
283
|
+
return Response.json({ ok: true });
|
|
284
|
+
}
|
|
285
|
+
}];
|
|
286
|
+
}
|
|
287
|
+
async function denyUnlessUpdate(req, update) {
|
|
288
|
+
if (await update({ req })) return null;
|
|
289
|
+
return Response.json({ error: "Forbidden" }, { status: 403 });
|
|
290
|
+
}
|
|
291
|
+
function queryKey(req) {
|
|
292
|
+
const fromQuery = req.query?.key;
|
|
293
|
+
if (typeof fromQuery === "string") return fromQuery;
|
|
294
|
+
if (Array.isArray(fromQuery) && typeof fromQuery[0] === "string") return fromQuery[0];
|
|
295
|
+
if (req.url) try {
|
|
296
|
+
return new URL(req.url, "http://local").searchParams.get("key") ?? "";
|
|
297
|
+
} catch {
|
|
298
|
+
return "";
|
|
299
|
+
}
|
|
300
|
+
return "";
|
|
301
|
+
}
|
|
302
|
+
async function readJson(req) {
|
|
303
|
+
if (typeof req.json === "function") return req.json();
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
//#endregion
|
|
167
307
|
//#region src/theme/publish.ts
|
|
168
308
|
/**
|
|
169
309
|
* Publishing a child writes that slice only. Other responsibilities stay
|
|
@@ -570,7 +710,7 @@ function pageHooks(child) {
|
|
|
570
710
|
function createTheme(options) {
|
|
571
711
|
const access = requireAccess$1(options);
|
|
572
712
|
const destructive = requireDestructive(options);
|
|
573
|
-
const { seed, fonts = catalog, fontsBaseUrl = "/fonts", contrastTarget = 7, logo, identity, onPublish } = options;
|
|
713
|
+
const { seed, fonts = catalog, fontsBaseUrl = "/fonts", contrastTarget = 7, logo, identity, onPublish, colorUsages } = options;
|
|
574
714
|
const adminCustom = {
|
|
575
715
|
contrastTarget,
|
|
576
716
|
fontsBaseUrl,
|
|
@@ -599,6 +739,7 @@ function createTheme(options) {
|
|
|
599
739
|
...lookFields,
|
|
600
740
|
...markFields
|
|
601
741
|
],
|
|
742
|
+
endpoints: colorUsageEndpoints(access, colorUsages),
|
|
602
743
|
hooks: { afterChange: [async ({ doc }) => {
|
|
603
744
|
if (!onPublish) return;
|
|
604
745
|
const themeDoc = doc;
|
|
@@ -612,6 +753,7 @@ function createTheme(options) {
|
|
|
612
753
|
lockDocuments: false,
|
|
613
754
|
admin: {
|
|
614
755
|
group: "Theme",
|
|
756
|
+
hidden: hideUnlessFeature("theme"),
|
|
615
757
|
hideAPIURL: true,
|
|
616
758
|
custom: adminCustom,
|
|
617
759
|
components: preview ? { elements: { beforeDocumentControls: [THEME_DOCUMENT_CONTROLS] } } : void 0
|
|
@@ -779,309 +921,190 @@ const THEME_PREVIEW_BREAKPOINTS = [
|
|
|
779
921
|
}
|
|
780
922
|
];
|
|
781
923
|
//#endregion
|
|
782
|
-
//#region src/roles/
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
const
|
|
789
|
-
"developer",
|
|
790
|
-
"admin",
|
|
791
|
-
"designer",
|
|
792
|
-
"author"
|
|
793
|
-
];
|
|
794
|
-
const ROLE_LABELS = {
|
|
795
|
-
developer: "Developer",
|
|
796
|
-
admin: "Admin",
|
|
797
|
-
designer: "Designer",
|
|
798
|
-
author: "Author"
|
|
799
|
-
};
|
|
800
|
-
const CAPABILITIES = [
|
|
801
|
-
"content",
|
|
802
|
-
"brand",
|
|
803
|
-
"publish",
|
|
804
|
-
"users"
|
|
805
|
-
];
|
|
806
|
-
function isRole(value) {
|
|
807
|
-
return typeof value === "string" && ROLES.includes(value);
|
|
808
|
-
}
|
|
924
|
+
//#region src/roles/fields.ts
|
|
925
|
+
const ROLES_MATRIX_FIELD = "@bison-lab/payload-core/admin#RolesMatrixField";
|
|
926
|
+
const ROLES_ROW_LABEL = "@bison-lab/payload-core/admin#RolesRowLabel";
|
|
927
|
+
const ROLE_SLUG_FIELD = "@bison-lab/payload-core/admin#RoleSlugField";
|
|
928
|
+
const ROLE_NAME_FIELD = "@bison-lab/payload-core/admin#RoleNameField";
|
|
929
|
+
const ROLES_FIELD = "@bison-lab/payload-core/admin#RolesField";
|
|
930
|
+
const ROLES_GRANTS_FIELD = "@bison-lab/payload-core/admin#RolesGrantsField";
|
|
809
931
|
//#endregion
|
|
810
|
-
//#region src/roles/
|
|
811
|
-
const
|
|
932
|
+
//#region src/roles/global.ts
|
|
933
|
+
const roleSlugValidate = (value) => {
|
|
934
|
+
if (typeof value !== "string" || value === "") return true;
|
|
935
|
+
return isRoleSlug(value) || "Each role needs a unique slug.";
|
|
936
|
+
};
|
|
937
|
+
const roleNameValidate = (value) => {
|
|
938
|
+
if (typeof value !== "string" || value.trim() === "") return true;
|
|
939
|
+
return isRoleName(value) || "Use letters and spaces only.";
|
|
940
|
+
};
|
|
812
941
|
/**
|
|
813
|
-
*
|
|
814
|
-
*
|
|
942
|
+
* Settings → Roles. Rank is the array order (Payload's drag handle).
|
|
943
|
+
* Ticks are released catalogue rows. Developer is implicit and shown
|
|
944
|
+
* only to a Developer, with every catalogue tick locked on.
|
|
815
945
|
*/
|
|
816
|
-
|
|
817
|
-
{
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
ok: false,
|
|
863
|
-
message: "Roles must be Developer, Admin, Designer, and Author."
|
|
864
|
-
};
|
|
865
|
-
const rows = [];
|
|
866
|
-
const seen = /* @__PURE__ */ new Set();
|
|
867
|
-
for (const item of value) {
|
|
868
|
-
if (!item || typeof item !== "object") continue;
|
|
869
|
-
const role = "role" in item ? item.role : void 0;
|
|
870
|
-
if (!isRole(role) || seen.has(role)) continue;
|
|
871
|
-
seen.add(role);
|
|
872
|
-
rows.push({
|
|
873
|
-
id: role,
|
|
874
|
-
role,
|
|
875
|
-
content: Boolean("content" in item && item.content),
|
|
876
|
-
brand: Boolean("brand" in item && item.brand),
|
|
877
|
-
publish: Boolean("publish" in item && item.publish),
|
|
878
|
-
users: Boolean("users" in item && item.users)
|
|
879
|
-
});
|
|
880
|
-
}
|
|
881
|
-
if (rows.length !== ROLES.length || ROLES.some((role) => !seen.has(role))) return {
|
|
882
|
-
ok: false,
|
|
883
|
-
message: "Roles must be Developer, Admin, Designer, and Author."
|
|
946
|
+
function createRoles({ extras = [] } = {}) {
|
|
947
|
+
const rolesField = {
|
|
948
|
+
name: "roles",
|
|
949
|
+
type: "array",
|
|
950
|
+
label: "Roles",
|
|
951
|
+
labels: {
|
|
952
|
+
singular: "Role",
|
|
953
|
+
plural: "Roles"
|
|
954
|
+
},
|
|
955
|
+
minRows: 4,
|
|
956
|
+
required: true,
|
|
957
|
+
defaultValue: defaultRolesFieldValue(extras),
|
|
958
|
+
validate: validateRolesMatrix,
|
|
959
|
+
hooks: { beforeChange: [({ value }) => applyRoleSlugsFromNames(value)] },
|
|
960
|
+
admin: {
|
|
961
|
+
components: {
|
|
962
|
+
Field: ROLES_MATRIX_FIELD,
|
|
963
|
+
RowLabel: ROLES_ROW_LABEL
|
|
964
|
+
},
|
|
965
|
+
description: ROLES_FIELD_DESCRIPTION,
|
|
966
|
+
initCollapsed: false
|
|
967
|
+
},
|
|
968
|
+
fields: [
|
|
969
|
+
{
|
|
970
|
+
name: "role",
|
|
971
|
+
type: "text",
|
|
972
|
+
label: "Slug",
|
|
973
|
+
validate: roleSlugValidate,
|
|
974
|
+
admin: { hidden: true }
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
name: "label",
|
|
978
|
+
type: "text",
|
|
979
|
+
label: "Name",
|
|
980
|
+
required: true,
|
|
981
|
+
validate: roleNameValidate,
|
|
982
|
+
admin: { components: { Field: ROLE_NAME_FIELD } }
|
|
983
|
+
},
|
|
984
|
+
{
|
|
985
|
+
name: "grants",
|
|
986
|
+
type: "json",
|
|
987
|
+
label: "Grants",
|
|
988
|
+
defaultValue: [],
|
|
989
|
+
admin: { components: { Field: ROLES_GRANTS_FIELD } }
|
|
990
|
+
}
|
|
991
|
+
]
|
|
884
992
|
};
|
|
885
993
|
return {
|
|
886
|
-
|
|
887
|
-
|
|
994
|
+
slug: ROLES_SLUG,
|
|
995
|
+
label: "Roles",
|
|
996
|
+
admin: {
|
|
997
|
+
group: "Settings",
|
|
998
|
+
hidden: hideUnlessFeature("roles"),
|
|
999
|
+
description: ROLES_GLOBAL_DESCRIPTION
|
|
1000
|
+
},
|
|
1001
|
+
access: {
|
|
1002
|
+
read: (args) => canUseFeature("roles")(args),
|
|
1003
|
+
update: (args) => isAdmin(args)
|
|
1004
|
+
},
|
|
1005
|
+
fields: [rolesField]
|
|
888
1006
|
};
|
|
889
1007
|
}
|
|
890
|
-
function hasPrivilegedUsersTick(rows) {
|
|
891
|
-
return rows.some((row) => (row.role === "admin" || row.role === "developer") && row.users);
|
|
892
|
-
}
|
|
893
|
-
function validateRolesMatrix(value) {
|
|
894
|
-
const parsed = parseRolesMatrix(value);
|
|
895
|
-
if (!parsed.ok) return parsed.message;
|
|
896
|
-
if (!hasPrivilegedUsersTick(parsed.rows)) return LAST_USERS_TICK_MESSAGE;
|
|
897
|
-
return true;
|
|
898
|
-
}
|
|
899
|
-
/**
|
|
900
|
-
* Developer is exclusive. Admin does not swallow Designer: both store.
|
|
901
|
-
*/
|
|
902
|
-
function normalizeStoredRoles(value) {
|
|
903
|
-
if (!Array.isArray(value)) return [];
|
|
904
|
-
const roles = [...new Set(value.filter(isRole))];
|
|
905
|
-
if (roles.includes("developer")) return ["developer"];
|
|
906
|
-
return roles;
|
|
907
|
-
}
|
|
908
|
-
function roleSelectOptions(matrix = DEFAULT_ROLE_MATRIX) {
|
|
909
|
-
return matrix.map((row) => ({
|
|
910
|
-
label: ROLE_LABELS[row.role],
|
|
911
|
-
value: row.role
|
|
912
|
-
}));
|
|
913
|
-
}
|
|
914
|
-
/** Capability copy only. Developer names the API tab; nothing about MCP or seed. */
|
|
915
|
-
function roleDescription(role, matrix = DEFAULT_ROLE_MATRIX) {
|
|
916
|
-
if (role === "developer") return DEVELOPER_DESCRIPTION;
|
|
917
|
-
const row = matrix.find((entry) => entry.role === role);
|
|
918
|
-
if (!row) return "No capabilities";
|
|
919
|
-
return CAPABILITIES.filter((capability) => row[capability]).map((capability) => CAPABILITY_LABELS[capability]).join(", ") || "No capabilities";
|
|
920
|
-
}
|
|
921
1008
|
//#endregion
|
|
922
|
-
//#region src/roles/
|
|
923
|
-
function isAccessArgs(value) {
|
|
924
|
-
return typeof value === "object" && value !== null && "req" in value;
|
|
925
|
-
}
|
|
926
|
-
function storedRoles(user) {
|
|
927
|
-
return Array.isArray(user?.roles) ? user.roles : [];
|
|
928
|
-
}
|
|
929
|
-
function hasRole(user, role) {
|
|
930
|
-
return storedRoles(user).includes(role);
|
|
931
|
-
}
|
|
932
|
-
/** Not a tick. True only when `developer` is stored on the row. */
|
|
933
|
-
function isDeveloper(user) {
|
|
934
|
-
return hasRole(user, "developer");
|
|
935
|
-
}
|
|
936
|
-
function hasCapability(user, capability, matrix = DEFAULT_ROLE_MATRIX) {
|
|
937
|
-
return storedRoles(user).some((role) => {
|
|
938
|
-
return matrix.find((entry) => entry.role === role)?.[capability] === true;
|
|
939
|
-
});
|
|
940
|
-
}
|
|
1009
|
+
//#region src/roles/seed.ts
|
|
941
1010
|
/**
|
|
942
|
-
*
|
|
943
|
-
*
|
|
944
|
-
*
|
|
1011
|
+
* Writes the default matrix (seed four plus any site extras). For a site's
|
|
1012
|
+
* migration `up()`. Never writes a user row — seeding `developer` on a
|
|
1013
|
+
* person stays a site concern.
|
|
945
1014
|
*/
|
|
946
|
-
async function
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
slug: ROLES_SLUG,
|
|
952
|
-
overrideAccess: true,
|
|
953
|
-
req
|
|
954
|
-
});
|
|
955
|
-
const parsed = parseRolesMatrix(doc && typeof doc === "object" && "roles" in doc ? doc.roles : void 0);
|
|
956
|
-
return parsed.ok ? parsed.rows : [...DEFAULT_ROLE_MATRIX];
|
|
957
|
-
} catch {
|
|
958
|
-
return [...DEFAULT_ROLE_MATRIX];
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
function capabilityPredicate(capability) {
|
|
962
|
-
function predicate(userOrArgs, matrix) {
|
|
963
|
-
if (isAccessArgs(userOrArgs)) {
|
|
964
|
-
const user = userOrArgs.req.user;
|
|
965
|
-
if (matrix) return hasCapability(user, capability, matrix);
|
|
966
|
-
return getRolesMatrix(userOrArgs.req).then((rows) => hasCapability(user, capability, rows));
|
|
967
|
-
}
|
|
968
|
-
return hasCapability(userOrArgs, capability, matrix ?? DEFAULT_ROLE_MATRIX);
|
|
969
|
-
}
|
|
970
|
-
return predicate;
|
|
971
|
-
}
|
|
972
|
-
const canManageContent = capabilityPredicate("content");
|
|
973
|
-
const canManageBrand = capabilityPredicate("brand");
|
|
974
|
-
const canPublish = capabilityPredicate("publish");
|
|
975
|
-
/** Users tick on any held role. */
|
|
976
|
-
const isAdmin = capabilityPredicate("users");
|
|
977
|
-
/** This role id currently has the Users tick. */
|
|
978
|
-
function isPrivilegedRole(role, matrix = DEFAULT_ROLE_MATRIX) {
|
|
979
|
-
return isRole(role) && matrix.some((row) => row.role === role && row.users);
|
|
980
|
-
}
|
|
981
|
-
function isAuthenticated(userOrArgs) {
|
|
982
|
-
if (isAccessArgs(userOrArgs)) return Boolean(userOrArgs.req.user);
|
|
983
|
-
return Boolean(userOrArgs);
|
|
984
|
-
}
|
|
985
|
-
const isAdminOrSelf = async ({ req }) => {
|
|
986
|
-
if (!req.user) return false;
|
|
987
|
-
if (await isAdmin({ req })) return true;
|
|
988
|
-
return { id: { equals: req.user.id } };
|
|
989
|
-
};
|
|
990
|
-
const authenticatedOrPublished = ({ req: { user } }) => {
|
|
991
|
-
if (isAuthenticated(user)) return true;
|
|
992
|
-
return { _status: { equals: "published" } };
|
|
993
|
-
};
|
|
994
|
-
/** API tab condition: Developer only, not the Users tick. */
|
|
995
|
-
function isDeveloperTab({ req }) {
|
|
996
|
-
return isDeveloper(req.user);
|
|
1015
|
+
async function seedRoles(payload, extras = []) {
|
|
1016
|
+
return payload.updateGlobal({
|
|
1017
|
+
slug: ROLES_SLUG,
|
|
1018
|
+
data: { roles: defaultRolesFieldValue(extras) }
|
|
1019
|
+
});
|
|
997
1020
|
}
|
|
998
1021
|
//#endregion
|
|
999
|
-
//#region src/
|
|
1000
|
-
const
|
|
1001
|
-
const ROLES_FIELD = "@bison-lab/payload-core/admin#RolesField";
|
|
1022
|
+
//#region src/features/fields.ts
|
|
1023
|
+
const FEATURES_MATRIX_FIELD = "@bison-lab/payload-core/admin#FeaturesMatrixField";
|
|
1002
1024
|
//#endregion
|
|
1003
|
-
//#region src/
|
|
1025
|
+
//#region src/features/global.ts
|
|
1004
1026
|
/**
|
|
1005
|
-
* Settings →
|
|
1006
|
-
*
|
|
1027
|
+
* Settings → Features. One release switch per catalogue row. Off hides
|
|
1028
|
+
* the tick on Roles; Developer still has the feature. This screen is
|
|
1029
|
+
* not itself a row.
|
|
1007
1030
|
*/
|
|
1008
|
-
function
|
|
1031
|
+
function createFeatures({ extras = [] } = {}) {
|
|
1032
|
+
const catalogue = featureCatalogue(extras);
|
|
1009
1033
|
return {
|
|
1010
|
-
slug:
|
|
1011
|
-
label: "
|
|
1034
|
+
slug: FEATURES_SLUG,
|
|
1035
|
+
label: "Features",
|
|
1012
1036
|
admin: {
|
|
1013
1037
|
group: "Settings",
|
|
1014
|
-
hidden: ({ user }) => !
|
|
1015
|
-
description: "
|
|
1038
|
+
hidden: ({ user }) => !isDeveloper(user),
|
|
1039
|
+
description: "Which features other people may be granted on Roles."
|
|
1016
1040
|
},
|
|
1017
1041
|
access: {
|
|
1018
|
-
read: (
|
|
1019
|
-
update: (
|
|
1042
|
+
read: ({ req }) => isDeveloper(req.user),
|
|
1043
|
+
update: ({ req }) => isDeveloper(req.user)
|
|
1020
1044
|
},
|
|
1021
1045
|
fields: [{
|
|
1022
|
-
name: "
|
|
1046
|
+
name: "features",
|
|
1023
1047
|
type: "array",
|
|
1024
|
-
label: "
|
|
1048
|
+
label: "Features",
|
|
1025
1049
|
labels: {
|
|
1026
|
-
singular: "
|
|
1027
|
-
plural: "
|
|
1050
|
+
singular: "Feature",
|
|
1051
|
+
plural: "Features"
|
|
1028
1052
|
},
|
|
1029
|
-
minRows:
|
|
1030
|
-
maxRows:
|
|
1053
|
+
minRows: catalogue.length,
|
|
1054
|
+
maxRows: catalogue.length,
|
|
1031
1055
|
required: true,
|
|
1032
|
-
defaultValue:
|
|
1033
|
-
validate:
|
|
1056
|
+
defaultValue: defaultFeaturesFieldValue(extras),
|
|
1057
|
+
validate: (value) => validateFeaturesMatrix(value, extras),
|
|
1058
|
+
hooks: { beforeChange: [({ value }) => {
|
|
1059
|
+
if (!Array.isArray(value)) return value;
|
|
1060
|
+
return stampFeatureCatalogue(value, extras);
|
|
1061
|
+
}] },
|
|
1034
1062
|
admin: {
|
|
1035
|
-
components: { Field:
|
|
1036
|
-
description: "
|
|
1063
|
+
components: { Field: FEATURES_MATRIX_FIELD },
|
|
1064
|
+
description: "Release a feature so it can be assigned on Roles. Off keeps it Developer-only.",
|
|
1037
1065
|
initCollapsed: false
|
|
1038
1066
|
},
|
|
1039
1067
|
fields: [
|
|
1040
1068
|
{
|
|
1041
|
-
name: "
|
|
1042
|
-
type: "
|
|
1043
|
-
label: "
|
|
1069
|
+
name: "slug",
|
|
1070
|
+
type: "text",
|
|
1071
|
+
label: "Slug",
|
|
1044
1072
|
required: true,
|
|
1045
|
-
options: ROLES.map((value) => ({
|
|
1046
|
-
label: ROLE_LABELS[value],
|
|
1047
|
-
value
|
|
1048
|
-
})),
|
|
1049
1073
|
admin: { readOnly: true }
|
|
1050
1074
|
},
|
|
1051
1075
|
{
|
|
1052
|
-
name: "
|
|
1053
|
-
type: "
|
|
1054
|
-
label: "
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
name: "brand",
|
|
1058
|
-
type: "checkbox",
|
|
1059
|
-
label: "Brand"
|
|
1076
|
+
name: "label",
|
|
1077
|
+
type: "text",
|
|
1078
|
+
label: "Name",
|
|
1079
|
+
required: true,
|
|
1080
|
+
admin: { readOnly: true }
|
|
1060
1081
|
},
|
|
1061
1082
|
{
|
|
1062
|
-
name: "
|
|
1063
|
-
type: "
|
|
1064
|
-
label: "
|
|
1083
|
+
name: "group",
|
|
1084
|
+
type: "text",
|
|
1085
|
+
label: "Group",
|
|
1086
|
+
admin: { hidden: true }
|
|
1065
1087
|
},
|
|
1066
1088
|
{
|
|
1067
|
-
name: "
|
|
1089
|
+
name: "released",
|
|
1068
1090
|
type: "checkbox",
|
|
1069
|
-
label: "
|
|
1091
|
+
label: "Released",
|
|
1092
|
+
admin: { hidden: true }
|
|
1070
1093
|
}
|
|
1071
1094
|
]
|
|
1072
1095
|
}]
|
|
1073
1096
|
};
|
|
1074
1097
|
}
|
|
1075
1098
|
//#endregion
|
|
1076
|
-
//#region src/
|
|
1099
|
+
//#region src/features/seed.ts
|
|
1077
1100
|
/**
|
|
1078
|
-
* Writes the default
|
|
1079
|
-
*
|
|
1101
|
+
* Writes the default switchboard (package rows plus any site extras).
|
|
1102
|
+
* For a site's migration `up()`.
|
|
1080
1103
|
*/
|
|
1081
|
-
async function
|
|
1104
|
+
async function seedFeatures(payload, extras = []) {
|
|
1082
1105
|
return payload.updateGlobal({
|
|
1083
|
-
slug:
|
|
1084
|
-
data: {
|
|
1106
|
+
slug: FEATURES_SLUG,
|
|
1107
|
+
data: { features: defaultFeaturesFieldValue(extras) }
|
|
1085
1108
|
});
|
|
1086
1109
|
}
|
|
1087
1110
|
//#endregion
|
|
@@ -1184,14 +1207,15 @@ function createPages({ heroBlocks, isReservedSlug, layoutBlocks, previewPath, pr
|
|
|
1184
1207
|
"_status",
|
|
1185
1208
|
"updatedAt"
|
|
1186
1209
|
],
|
|
1210
|
+
hidden: hideUnlessFeature("content"),
|
|
1187
1211
|
preview: (doc) => previewPath(typeof doc.slug === "string" ? doc.slug : ""),
|
|
1188
1212
|
...previewButton ? { components: { edit: { PreviewButton: previewButton } } } : {}
|
|
1189
1213
|
},
|
|
1190
1214
|
access: {
|
|
1191
1215
|
read: authenticatedOrPublished,
|
|
1192
1216
|
readVersions: isAuthenticated,
|
|
1193
|
-
create:
|
|
1194
|
-
update:
|
|
1217
|
+
create: canUseFeature("content"),
|
|
1218
|
+
update: canUseFeature("content"),
|
|
1195
1219
|
delete: isAdmin
|
|
1196
1220
|
},
|
|
1197
1221
|
versions: {
|
|
@@ -1262,7 +1286,7 @@ async function lockLastAdminDecision(req) {
|
|
|
1262
1286
|
});
|
|
1263
1287
|
}
|
|
1264
1288
|
function privilegedRoles(matrix) {
|
|
1265
|
-
return matrix.filter((row) => row.
|
|
1289
|
+
return matrix.filter((row) => isPrivilegedRole(row.role, matrix)).map((row) => row.role);
|
|
1266
1290
|
}
|
|
1267
1291
|
function holdsPrivilegedRole(roles, matrix) {
|
|
1268
1292
|
return Array.isArray(roles) && roles.some((role) => isPrivilegedRole(role, matrix));
|
|
@@ -1283,15 +1307,21 @@ async function adminCount(req, excluding) {
|
|
|
1283
1307
|
});
|
|
1284
1308
|
return totalDocs;
|
|
1285
1309
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1310
|
+
function rolesValidate(extras) {
|
|
1311
|
+
return async (value, options) => {
|
|
1312
|
+
const matrix = await getRolesMatrix(options.req, extras);
|
|
1313
|
+
const builtIn = select(value, {
|
|
1314
|
+
...options,
|
|
1315
|
+
options: roleSelectOptions(matrix)
|
|
1316
|
+
});
|
|
1317
|
+
if (builtIn !== true) return builtIn;
|
|
1318
|
+
if (options.operation !== "update" || options.id === void 0) return true;
|
|
1319
|
+
if (holdsPrivilegedRole(value, matrix) || !holdsPrivilegedRole(options.previousValue, matrix)) return true;
|
|
1320
|
+
return await adminCount(options.req, options.id) > 0 ? true : LAST_ADMIN_DEMOTE_MESSAGE;
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
function createUsers({ secureCookies, rolesField, extras = [] }) {
|
|
1324
|
+
const fallback = seedRoleRows(extras);
|
|
1295
1325
|
return {
|
|
1296
1326
|
slug: "users",
|
|
1297
1327
|
auth: {
|
|
@@ -1304,6 +1334,7 @@ function createUsers({ secureCookies, rolesField }) {
|
|
|
1304
1334
|
}
|
|
1305
1335
|
},
|
|
1306
1336
|
admin: {
|
|
1337
|
+
group: "Settings",
|
|
1307
1338
|
useAsTitle: "email",
|
|
1308
1339
|
defaultColumns: [
|
|
1309
1340
|
"email",
|
|
@@ -1311,13 +1342,16 @@ function createUsers({ secureCookies, rolesField }) {
|
|
|
1311
1342
|
"lastName",
|
|
1312
1343
|
"roles"
|
|
1313
1344
|
],
|
|
1314
|
-
hidden: (
|
|
1345
|
+
hidden: hideUnlessFeature("users")
|
|
1315
1346
|
},
|
|
1316
1347
|
access: {
|
|
1317
1348
|
create: isAdmin,
|
|
1318
1349
|
delete: isAdmin,
|
|
1319
1350
|
unlock: isAdmin,
|
|
1320
|
-
read:
|
|
1351
|
+
read: async (args) => {
|
|
1352
|
+
if (await Promise.resolve(canUseFeature("users")(args))) return true;
|
|
1353
|
+
return isAdminOrSelf(args);
|
|
1354
|
+
},
|
|
1321
1355
|
update: isAdminOrSelf
|
|
1322
1356
|
},
|
|
1323
1357
|
hooks: {
|
|
@@ -1329,7 +1363,7 @@ function createUsers({ secureCookies, rolesField }) {
|
|
|
1329
1363
|
disableErrors: true,
|
|
1330
1364
|
overrideAccess: true,
|
|
1331
1365
|
req
|
|
1332
|
-
})) || await adminCount(req, id) > 0) return;
|
|
1366
|
+
}), await getRolesMatrix(req, extras)) || await adminCount(req, id) > 0) return;
|
|
1333
1367
|
throw new APIError(LAST_ADMIN_DELETE_MESSAGE, 400);
|
|
1334
1368
|
}],
|
|
1335
1369
|
afterOperation: [async (arg) => {
|
|
@@ -1349,14 +1383,17 @@ function createUsers({ secureCookies, rolesField }) {
|
|
|
1349
1383
|
hasMany: true,
|
|
1350
1384
|
required: true,
|
|
1351
1385
|
defaultValue: ["author"],
|
|
1352
|
-
options: roleSelectOptions(),
|
|
1386
|
+
options: roleSelectOptions(fallback),
|
|
1353
1387
|
admin: {
|
|
1354
1388
|
components: { Field: rolesField ?? "@bison-lab/payload-core/admin#RolesField" },
|
|
1355
1389
|
description: "One person can hold several, e.g. Author + Designer."
|
|
1356
1390
|
},
|
|
1357
1391
|
access: { update: isAdmin },
|
|
1358
|
-
validate: rolesValidate,
|
|
1359
|
-
hooks: { beforeValidate: [({ value }) =>
|
|
1392
|
+
validate: rolesValidate(extras),
|
|
1393
|
+
hooks: { beforeValidate: [async ({ value, req }) => {
|
|
1394
|
+
if (!Array.isArray(value)) return value;
|
|
1395
|
+
return normalizeStoredRoles(value, await getRolesMatrix(req, extras));
|
|
1396
|
+
}] }
|
|
1360
1397
|
}]
|
|
1361
1398
|
};
|
|
1362
1399
|
}
|
|
@@ -1370,10 +1407,11 @@ function createUsers({ secureCookies, rolesField }) {
|
|
|
1370
1407
|
function createMedia({ staticDir = "media", mimeTypes = ["image/*"], imageSizes } = {}) {
|
|
1371
1408
|
return {
|
|
1372
1409
|
slug: "media",
|
|
1410
|
+
admin: { hidden: hideUnlessFeature("media") },
|
|
1373
1411
|
access: {
|
|
1374
1412
|
read: () => true,
|
|
1375
|
-
create:
|
|
1376
|
-
update:
|
|
1413
|
+
create: canUseFeature("media"),
|
|
1414
|
+
update: canUseFeature("media"),
|
|
1377
1415
|
delete: isAdmin
|
|
1378
1416
|
},
|
|
1379
1417
|
upload: {
|
|
@@ -1432,6 +1470,6 @@ const adminOnlyApiTab = definePlugin({
|
|
|
1432
1470
|
})
|
|
1433
1471
|
});
|
|
1434
1472
|
//#endregion
|
|
1435
|
-
export { BRAND_ASSETS_MIME_TYPES, BRAND_ASSETS_SLUG, CAPABILITIES, DEFAULT_ROLE_MATRIX, DESCRIPTION_LENGTH, DEVELOPER_DESCRIPTION, LAST_ADMIN_DELETE_MESSAGE, LAST_ADMIN_DEMOTE_MESSAGE, LAST_USERS_TICK_MESSAGE, LOOK_FIELD, PAGE_EDITOR_SYSTEM_KEYS, ROLES, ROLES_FIELD, ROLES_MATRIX_FIELD, ROLES_SLUG, ROLE_LABELS, SHARE_IMAGE_SIZE, SYSTEM_COLOR_KEYS, THEME_APPEARANCE_FIELD, THEME_APPEARANCE_SLUG, THEME_COLORS_SLUG, THEME_COLOR_FIELD, THEME_COLOR_SCALE_FIELD, THEME_CONTRAST_REPORT, THEME_DOCUMENT_CONTROLS, THEME_FONT_FIELD, THEME_GREY_SCALE_FIELD, THEME_IDENTITY_FALLBACK, THEME_IDENTITY_SLUG, THEME_LIBRARY_FIELD, THEME_PAIRING_FIELD, THEME_PREVIEW_BREAKPOINTS, THEME_PUBLISH_FIELD, THEME_SAVE_BUTTON, THEME_SECTION_HEADING, THEME_SLUG, THEME_TYPOGRAPHY_SLUG, adminOnlyApiTab, authenticatedOrPublished, canManageBrand, canManageContent, canPublish, colorTokenField, createBrandAssets, createMedia, createPages, createRoles, createTheme, createUsers, defaultRolesFieldValue, deleteLibraryColor, documentTitle, firstImageIn, getRolesMatrix, hasCapability, hasRole, isAdmin, isAdminOrSelf, isAuthenticated, isDeveloper, isDeveloperTab, isPrivilegedRole, isRole, lookField, noIndexField, normalizeSlug, normalizeStoredRoles, pageEditorLooks, pageEditorTokens, parseRolesMatrix, persistThemeChild, publishThemeChild, resolveThemeIdentity, rewriteColorToken, roleDescription, roleSelectOptions, sanitizeSvg, seedRoles, seedTheme, seoPlugin, slugField, storedRoles, themeColorKeys, themeLibraryFromDoc, titleTemplate, truncateAtWord, validateRolesMatrix };
|
|
1473
|
+
export { BRAND_ASSETS_MIME_TYPES, BRAND_ASSETS_SLUG, CAPABILITIES, CAPABILITY_FEATURES, DEFAULT_ROLE_GRANTS, DEFAULT_ROLE_MATRIX, DESCRIPTION_LENGTH, DEVELOPER_DESCRIPTION, DUPLICATE_ROLE_NAME_MESSAGE, DUPLICATE_ROLE_SLUG_MESSAGE, FEATURES_MATRIX_FIELD, FEATURES_SLUG, FEATURE_GROUPS, FEATURE_GROUP_LABELS, INVALID_ROLE_NAME_MESSAGE, LAST_ADMIN_DELETE_MESSAGE, LAST_ADMIN_DEMOTE_MESSAGE, LAST_USERS_TICK_MESSAGE, LOOK_FIELD, MISSING_PACKAGE_FEATURES_MESSAGE, MISSING_SEED_ROLES_MESSAGE, PACKAGE_FEATURES, PACKAGE_FEATURE_SLUGS, PAGE_EDITOR_SYSTEM_KEYS, ROLES, ROLES_FIELD, ROLES_FIELD_DESCRIPTION, ROLES_GLOBAL_DESCRIPTION, ROLES_GRANTS_FIELD, ROLES_MATRIX_FIELD, ROLES_ROW_LABEL, ROLES_SLUG, ROLE_LABELS, ROLE_NAME_FIELD, ROLE_SLUG_FIELD, SHARE_IMAGE_SIZE, SYSTEM_COLOR_KEYS, THEME_APPEARANCE_FIELD, THEME_APPEARANCE_SLUG, THEME_COLORS_SLUG, THEME_COLOR_FIELD, THEME_COLOR_SCALE_FIELD, THEME_CONTRAST_REPORT, THEME_DOCUMENT_CONTROLS, THEME_FEATURE_SLUGS, THEME_FONT_FIELD, THEME_GREY_SCALE_FIELD, THEME_IDENTITY_FALLBACK, THEME_IDENTITY_SLUG, THEME_LIBRARY_FIELD, THEME_PAIRING_FIELD, THEME_PREVIEW_BREAKPOINTS, THEME_PUBLISH_FIELD, THEME_SAVE_BUTTON, THEME_SECTION_HEADING, THEME_SLUG, THEME_TYPOGRAPHY_SLUG, adminOnlyApiTab, applyRoleSlugsFromNames, authenticatedOrPublished, canManageBrand, canManageContent, canPublish, canUseFeature, colorTokenField, createBrandAssets, createFeatures, createMedia, createPages, createRoles, createTheme, createUsers, defaultFeaturesFieldValue, defaultRolesFieldValue, deleteLibraryColor, documentTitle, featureCatalogue, featureGroupLabel, findColorTokens, findColorUsages, firstImageIn, getFeaturesMatrix, getRolesMatrix, hasCapability, hasFeature, hasGrant, hasRole, hideUnlessFeature, isAdmin, isAdminOrSelf, isAuthenticated, isDeveloper, isDeveloperTab, isFeatureGroupId, isFeatureSlug, isLockedFeature, isPackageFeatureSlug, isPrivilegedRole, isRole, isRoleName, isRoleSlug, lookField, noIndexField, normalizeSlug, normalizeStoredRoles, pageEditorLooks, pageEditorTokens, parseFeaturesMatrix, parseRolesMatrix, persistThemeChild, publishThemeChild, resetRolesMatrix, resolveThemeIdentity, rewriteColorToken, rewriteColorTokens, rewriteColorUsages, roleDescription, roleLabel, roleSelectOptions, sanitizeRoleNameInput, sanitizeSvg, seedFeatures, seedRoleRows, seedRoles, seedTheme, seoPlugin, slugField, slugifyRoleName, stampFeatureCatalogue, storedRoles, themeColorKeys, themeLibraryFromDoc, titleTemplate, truncateAtWord, validateFeaturesMatrix, validateRolesMatrix };
|
|
1436
1474
|
|
|
1437
1475
|
//# sourceMappingURL=index.mjs.map
|