@micelio/strapi-plugin-core 0.1.0 → 0.2.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 +5 -3
- package/dist/admin/MicelioLayout-Bmu5xCw9.js +1023 -0
- package/dist/admin/MicelioLayout-DMMsKnMo.mjs +1021 -0
- package/dist/admin/PreviewHeaderAction-BaduMvYy.mjs +61 -0
- package/dist/admin/PreviewHeaderAction-CGHycv4I.js +61 -0
- package/dist/admin/{en-D-T8z3qh.js → en-BDVuq0fN.js} +37 -1
- package/dist/admin/{en-C2O-S2ym.mjs → en-Bahc6y6N.mjs} +37 -1
- package/dist/admin/{es-RV0vkOHh.js → es-DStBGkm7.js} +37 -1
- package/dist/admin/{es-CQ2tv9N8.mjs → es-nUHBIoZG.mjs} +37 -1
- package/dist/admin/{index-D3TGbaQ7.js → index-D_Dbvo2F.js} +8 -2
- package/dist/admin/{index-CiSujTES.mjs → index-Dwr15ZsB.mjs} +8 -2
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/permissions-BAI0qDr9.js +24 -0
- package/dist/admin/permissions-CYirM30e.mjs +25 -0
- package/dist/admin/src/components/EyeIcon.d.ts +8 -0
- package/dist/admin/src/components/PreviewFrame.d.ts +47 -0
- package/dist/admin/src/components/PreviewHeaderAction.d.ts +28 -0
- package/dist/admin/src/hooks/useEntry.d.ts +31 -0
- package/dist/admin/src/hooks/usePreviewSource.d.ts +31 -0
- package/dist/admin/src/pages/MicelioLayout.d.ts +2 -1
- package/dist/admin/src/pages/PreviewPage.d.ts +2 -0
- package/dist/admin/src/permissions.d.ts +5 -0
- package/dist/admin/src/translations/en.json.d.ts +37 -1
- package/dist/admin/src/utils/fetchError.d.ts +2 -0
- package/dist/admin/src/utils/previewAction.d.ts +22 -0
- package/dist/admin/src/utils/previewPane.d.ts +59 -0
- package/dist/server/index.js +796 -105
- package/dist/server/index.mjs +796 -105
- package/dist/server/src/constants/preview.d.ts +2 -0
- package/dist/server/src/constants/taxonomy.d.ts +13 -0
- package/dist/server/src/content-types/category/schema.json.d.ts +78 -0
- package/dist/server/src/content-types/index.d.ts +125 -2
- package/dist/server/src/content-types/preview-credential/schema.json.d.ts +7 -6
- package/dist/server/src/content-types/tag/schema.json.d.ts +46 -0
- package/dist/server/src/controllers/index.d.ts +6 -0
- package/dist/server/src/editorial/transitions.d.ts +5 -2
- package/dist/server/src/index.d.ts +140 -2
- package/dist/server/src/migrations/rename-legacy-uids.d.ts +26 -0
- package/dist/server/src/migrations/site-backfill.d.ts +13 -0
- package/dist/server/src/preview/credentials.d.ts +7 -5
- package/dist/server/src/preview/draft-query.d.ts +62 -0
- package/dist/server/src/preview/revocation.d.ts +9 -1
- package/dist/server/src/preview/shortcut.d.ts +24 -0
- package/dist/server/src/routes/index.d.ts +2 -0
- package/dist/server/src/routes/taxonomy.d.ts +12 -0
- package/dist/server/src/services/index.d.ts +6 -0
- package/dist/server/src/services/preview.d.ts +25 -6
- package/dist/server/src/site-scope/documents.d.ts +13 -3
- package/dist/server/src/types/hooks.d.ts +5 -4
- package/dist/server/src/types/preview.d.ts +35 -10
- package/package.json +4 -3
- package/dist/admin/MicelioLayout-3sKGPS_0.mjs +0 -443
- package/dist/admin/MicelioLayout-DXzRS4l3.js +0 -443
package/dist/server/index.mjs
CHANGED
|
@@ -2,9 +2,9 @@ import { z } from "zod";
|
|
|
2
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { factories } from "@strapi/strapi";
|
|
5
|
+
import { errors } from "@strapi/utils";
|
|
5
6
|
import { createRequire } from "node:module";
|
|
6
7
|
import path from "node:path";
|
|
7
|
-
import { errors } from "@strapi/utils";
|
|
8
8
|
import { Readable } from "node:stream";
|
|
9
9
|
import { pipeline } from "node:stream/promises";
|
|
10
10
|
import { createGzip, createGunzip } from "node:zlib";
|
|
@@ -12,7 +12,7 @@ import { createReadStream, createWriteStream, statSync } from "node:fs";
|
|
|
12
12
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
13
13
|
import os from "node:os";
|
|
14
14
|
import { once } from "node:events";
|
|
15
|
-
const SITE_UID = "plugin::micelio.site";
|
|
15
|
+
const SITE_UID$1 = "plugin::micelio.site";
|
|
16
16
|
const SITE_COMPONENT_CATEGORY = "micelio-site";
|
|
17
17
|
const DEFAULT_SITE_SLUG = "default";
|
|
18
18
|
const LOCALISED_LOCALES = ["en", "es"];
|
|
@@ -113,7 +113,7 @@ function parseExportSection(value) {
|
|
|
113
113
|
function missingLocales(value) {
|
|
114
114
|
return LOCALISED_LOCALES.filter((locale) => !value[locale]?.trim());
|
|
115
115
|
}
|
|
116
|
-
const attributeOf = (id2) => `${SITE_SECTION_ATTRIBUTE_PREFIX}${id2.replace(/-/g, "_")}`;
|
|
116
|
+
const attributeOf$1 = (id2) => `${SITE_SECTION_ATTRIBUTE_PREFIX}${id2.replace(/-/g, "_")}`;
|
|
117
117
|
function createExtensionRegistry(strapi) {
|
|
118
118
|
const pages = [];
|
|
119
119
|
const sections = [];
|
|
@@ -150,8 +150,8 @@ function createExtensionRegistry(strapi) {
|
|
|
150
150
|
"micelio: registerSiteSection: call it in `register`, before the models are built"
|
|
151
151
|
);
|
|
152
152
|
}
|
|
153
|
-
const attribute = attributeOf(section.id);
|
|
154
|
-
strapi.get("content-types").extend(SITE_UID, (contentType) => {
|
|
153
|
+
const attribute = attributeOf$1(section.id);
|
|
154
|
+
strapi.get("content-types").extend(SITE_UID$1, (contentType) => {
|
|
155
155
|
Object.assign(contentType.attributes, {
|
|
156
156
|
[attribute]: {
|
|
157
157
|
type: "component",
|
|
@@ -180,7 +180,7 @@ function createExtensionRegistry(strapi) {
|
|
|
180
180
|
siteSections: () => [...sections],
|
|
181
181
|
statusChecks: () => [...checks],
|
|
182
182
|
exportSections: () => [...exports],
|
|
183
|
-
siteSectionAttribute: attributeOf,
|
|
183
|
+
siteSectionAttribute: attributeOf$1,
|
|
184
184
|
async runStatusChecks(sites) {
|
|
185
185
|
for (const registration of checks) {
|
|
186
186
|
const found = [];
|
|
@@ -204,12 +204,12 @@ function createExtensionRegistry(strapi) {
|
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
206
|
function hasDatabaseModels(strapi) {
|
|
207
|
-
return strapi.db.metadata.has(SITE_UID);
|
|
207
|
+
return strapi.db.metadata.has(SITE_UID$1);
|
|
208
208
|
}
|
|
209
209
|
function extensionsOf(strapi) {
|
|
210
210
|
return strapi.plugin("micelio").service("extensions");
|
|
211
211
|
}
|
|
212
|
-
const SITE$1 = SITE_UID;
|
|
212
|
+
const SITE$1 = SITE_UID$1;
|
|
213
213
|
function siteSectionInstances(strapi) {
|
|
214
214
|
return async (context, next) => {
|
|
215
215
|
if (context.uid === SITE$1 && context.action === "create") {
|
|
@@ -342,7 +342,7 @@ function deepFreeze(value) {
|
|
|
342
342
|
}
|
|
343
343
|
return value;
|
|
344
344
|
}
|
|
345
|
-
const SITE_ATTRIBUTE = "site";
|
|
345
|
+
const SITE_ATTRIBUTE$1 = "site";
|
|
346
346
|
const SITE_SCOPE_MIDDLEWARE = "plugin::micelio.site-scope";
|
|
347
347
|
function withSiteScope(schema) {
|
|
348
348
|
return {
|
|
@@ -353,10 +353,10 @@ function withSiteScope(schema) {
|
|
|
353
353
|
},
|
|
354
354
|
attributes: {
|
|
355
355
|
...schema.attributes,
|
|
356
|
-
[SITE_ATTRIBUTE]: {
|
|
356
|
+
[SITE_ATTRIBUTE$1]: {
|
|
357
357
|
type: "relation",
|
|
358
358
|
relation: "manyToOne",
|
|
359
|
-
target: SITE_UID,
|
|
359
|
+
target: SITE_UID$1,
|
|
360
360
|
required: true,
|
|
361
361
|
pluginOptions: { i18n: { localized: false } }
|
|
362
362
|
}
|
|
@@ -381,7 +381,8 @@ const TRANSITIONS = [
|
|
|
381
381
|
{ from: "draft", to: "scheduled" },
|
|
382
382
|
{ from: "scheduled", to: "draft" },
|
|
383
383
|
{ from: "scheduled", to: "published" },
|
|
384
|
-
{ from: "published", to: "draft" }
|
|
384
|
+
{ from: "published", to: "draft" },
|
|
385
|
+
{ from: "published", to: "published" }
|
|
385
386
|
];
|
|
386
387
|
const SYSTEM_TRANSITIONS = /* @__PURE__ */ new Set(["scheduled->published"]);
|
|
387
388
|
const SUPER_ADMIN = "strapi-super-admin";
|
|
@@ -393,7 +394,8 @@ const DEFAULT_EDITORIAL_POLICY = {
|
|
|
393
394
|
"in_review->published": [EDITOR, SUPER_ADMIN],
|
|
394
395
|
"draft->scheduled": [EDITOR, SUPER_ADMIN],
|
|
395
396
|
"scheduled->draft": [EDITOR, SUPER_ADMIN],
|
|
396
|
-
"published->draft": [EDITOR, SUPER_ADMIN]
|
|
397
|
+
"published->draft": [EDITOR, SUPER_ADMIN],
|
|
398
|
+
"published->published": [EDITOR, SUPER_ADMIN]
|
|
397
399
|
};
|
|
398
400
|
function transitionKey({ from, to }) {
|
|
399
401
|
return `${from}->${to}`;
|
|
@@ -449,7 +451,7 @@ async function performTransition(strapi, request) {
|
|
|
449
451
|
status: "draft",
|
|
450
452
|
populate: {
|
|
451
453
|
[EDITORIAL_ATTRIBUTE]: { populate: ["reviewedBy", "publishedBy"] },
|
|
452
|
-
[SITE_ATTRIBUTE]: { fields: ["documentId", "editorialPolicy"] },
|
|
454
|
+
[SITE_ATTRIBUTE$1]: { fields: ["documentId", "editorialPolicy"] },
|
|
453
455
|
createdBy: true
|
|
454
456
|
}
|
|
455
457
|
});
|
|
@@ -508,7 +510,9 @@ async function performTransition(strapi, request) {
|
|
|
508
510
|
throw new TransitionError(409, "editorialTransitionRefused", refusalMessage(error));
|
|
509
511
|
}
|
|
510
512
|
await runAsTransition(async () => {
|
|
511
|
-
if (transition.from === "published"
|
|
513
|
+
if (transition.from === "published" && transition.to !== "published") {
|
|
514
|
+
await documents.unpublish(target);
|
|
515
|
+
}
|
|
512
516
|
await documents.update({ ...target, data: { [EDITORIAL_ATTRIBUTE]: editorial2 } });
|
|
513
517
|
if (transition.to === "published") await documents.publish(target);
|
|
514
518
|
});
|
|
@@ -1035,10 +1039,10 @@ async function storedFingerprint(strapi) {
|
|
|
1035
1039
|
}
|
|
1036
1040
|
const SITE_LOCALES = ["en", "es"];
|
|
1037
1041
|
async function ensureDefaultSite(strapi) {
|
|
1038
|
-
if (await strapi.db.query(SITE_UID).count() > 0) return false;
|
|
1042
|
+
if (await strapi.db.query(SITE_UID$1).count() > 0) return false;
|
|
1039
1043
|
const locales = strapi.plugin("i18n").service("locales");
|
|
1040
1044
|
const locale = await locales.getDefaultLocale();
|
|
1041
|
-
await strapi.documents(SITE_UID).create({
|
|
1045
|
+
await strapi.documents(SITE_UID$1).create({
|
|
1042
1046
|
locale,
|
|
1043
1047
|
data: {
|
|
1044
1048
|
name: "Micelio",
|
|
@@ -1052,6 +1056,28 @@ async function ensureDefaultSite(strapi) {
|
|
|
1052
1056
|
});
|
|
1053
1057
|
return true;
|
|
1054
1058
|
}
|
|
1059
|
+
const SITE_UID = "plugin::micelio.site";
|
|
1060
|
+
const SITE_ATTRIBUTE = "site";
|
|
1061
|
+
const BACKFILLED = ["plugin::micelio.category", "plugin::micelio.tag"];
|
|
1062
|
+
async function backfillSite(strapi) {
|
|
1063
|
+
const site2 = await strapi.db.query(SITE_UID).findOne({
|
|
1064
|
+
where: { isDefault: true },
|
|
1065
|
+
select: ["id"]
|
|
1066
|
+
});
|
|
1067
|
+
if (!site2) return 0;
|
|
1068
|
+
let linked = 0;
|
|
1069
|
+
for (const uid of BACKFILLED) {
|
|
1070
|
+
const rows = await strapi.db.query(uid).findMany({
|
|
1071
|
+
where: { [SITE_ATTRIBUTE]: null },
|
|
1072
|
+
select: ["id"]
|
|
1073
|
+
});
|
|
1074
|
+
for (const row of rows) {
|
|
1075
|
+
await strapi.db.query(uid).update({ where: { id: row.id }, data: { [SITE_ATTRIBUTE]: site2.id } });
|
|
1076
|
+
}
|
|
1077
|
+
linked += rows.length;
|
|
1078
|
+
}
|
|
1079
|
+
return linked;
|
|
1080
|
+
}
|
|
1055
1081
|
async function registerPreviewPermission(strapi) {
|
|
1056
1082
|
await strapi.service("admin::permission").actionProvider.registerMany([
|
|
1057
1083
|
{
|
|
@@ -1062,9 +1088,13 @@ async function registerPreviewPermission(strapi) {
|
|
|
1062
1088
|
}
|
|
1063
1089
|
]);
|
|
1064
1090
|
}
|
|
1091
|
+
const ADMIN_LOGOUT_HANDLER = "authentication.logout";
|
|
1065
1092
|
function registerPreviewRevocation(strapi) {
|
|
1066
|
-
strapi.
|
|
1067
|
-
|
|
1093
|
+
strapi.server.use(async (ctx, next) => {
|
|
1094
|
+
await next();
|
|
1095
|
+
const route = ctx.state.route;
|
|
1096
|
+
if (route?.info?.pluginName !== "admin" || route.handler !== ADMIN_LOGOUT_HANDLER) return;
|
|
1097
|
+
const id2 = ctx.state.user?.id;
|
|
1068
1098
|
if (typeof id2 !== "number") return;
|
|
1069
1099
|
try {
|
|
1070
1100
|
await strapi.plugin("micelio").service("preview").revoke(id2);
|
|
@@ -1087,6 +1117,9 @@ async function registerStatusPermission(strapi) {
|
|
|
1087
1117
|
}
|
|
1088
1118
|
const bootstrap = async ({ strapi }) => {
|
|
1089
1119
|
await ensureDefaultSite(strapi);
|
|
1120
|
+
const backfilled = await backfillSite(strapi);
|
|
1121
|
+
if (backfilled > 0)
|
|
1122
|
+
strapi.log.info(`[micelio] gave the default site to ${backfilled} categories and tags`);
|
|
1090
1123
|
await ensureSiteSections(strapi);
|
|
1091
1124
|
await strapi.plugin("micelio").service("hostCheck").enforce();
|
|
1092
1125
|
registerScheduler(strapi);
|
|
@@ -1100,7 +1133,7 @@ const DEFAULT_CONFIG = {
|
|
|
1100
1133
|
scheduledPublishRule: "* * * * *",
|
|
1101
1134
|
statusRefreshRule: "0 4 * * *"
|
|
1102
1135
|
};
|
|
1103
|
-
const config = {
|
|
1136
|
+
const config$1 = {
|
|
1104
1137
|
default: DEFAULT_CONFIG,
|
|
1105
1138
|
validator(config2) {
|
|
1106
1139
|
for (const key of ["scheduledPublishRule", "statusRefreshRule"]) {
|
|
@@ -1111,13 +1144,41 @@ const config = {
|
|
|
1111
1144
|
}
|
|
1112
1145
|
}
|
|
1113
1146
|
};
|
|
1147
|
+
const kind$3 = "collectionType";
|
|
1148
|
+
const collectionName$a = "categories";
|
|
1149
|
+
const info$a = { "singularName": "category", "pluralName": "categories", "displayName": "Category", "description": "Organize your content into categories" };
|
|
1150
|
+
const options$a = { "draftAndPublish": false };
|
|
1151
|
+
const pluginOptions$3 = { "content-manager": { "visible": true }, "i18n": { "localized": true } };
|
|
1152
|
+
const attributes$a = { "name": { "type": "string", "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "uid", "regex": "^(?!\\.{1,2}$)[A-Za-z0-9-_.~]*$", "pluginOptions": { "i18n": { "localized": false } } }, "description": { "type": "text", "pluginOptions": { "i18n": { "localized": true } } }, "order": { "type": "integer", "pluginOptions": { "i18n": { "localized": false } } }, "featured": { "type": "boolean", "default": false, "pluginOptions": { "i18n": { "localized": false } } }, "color": { "type": "integer", "min": 1, "max": 5, "pluginOptions": { "i18n": { "localized": false } } } };
|
|
1153
|
+
const category = {
|
|
1154
|
+
kind: kind$3,
|
|
1155
|
+
collectionName: collectionName$a,
|
|
1156
|
+
info: info$a,
|
|
1157
|
+
options: options$a,
|
|
1158
|
+
pluginOptions: pluginOptions$3,
|
|
1159
|
+
attributes: attributes$a
|
|
1160
|
+
};
|
|
1161
|
+
const kind$2 = "collectionType";
|
|
1162
|
+
const collectionName$9 = "micelio_preview_credentials";
|
|
1163
|
+
const info$9 = { "singularName": "preview-credential", "pluralName": "preview-credentials", "displayName": "Preview credential", "description": "A preview token, grant or system grant of ADR-0019, stored as the hash of its value and bound to one draft (and, but for a system grant, to one admin user)" };
|
|
1164
|
+
const options$9 = { "draftAndPublish": false };
|
|
1165
|
+
const pluginOptions$2 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false }, "i18n": { "localized": false }, "micelio": { "export": "never" } };
|
|
1166
|
+
const attributes$9 = { "kind": { "type": "enumeration", "enum": ["token", "grant", "system"], "required": true }, "hash": { "type": "string", "required": true, "unique": true, "private": true }, "adminUser": { "type": "integer" }, "adminOrigin": { "type": "string" }, "entryVersion": { "type": "string" }, "siteDocumentId": { "type": "string", "required": true }, "contentType": { "type": "string", "required": true }, "entryDocumentId": { "type": "string", "required": true }, "entryLocale": { "type": "string" }, "expiresAt": { "type": "datetime", "required": true }, "usedAt": { "type": "datetime" }, "revokedAt": { "type": "datetime" } };
|
|
1167
|
+
const previewCredential = {
|
|
1168
|
+
kind: kind$2,
|
|
1169
|
+
collectionName: collectionName$9,
|
|
1170
|
+
info: info$9,
|
|
1171
|
+
options: options$9,
|
|
1172
|
+
pluginOptions: pluginOptions$2,
|
|
1173
|
+
attributes: attributes$9
|
|
1174
|
+
};
|
|
1114
1175
|
const kind$1 = "collectionType";
|
|
1115
|
-
const collectionName$8 = "
|
|
1116
|
-
const info$8 = { "singularName": "
|
|
1176
|
+
const collectionName$8 = "micelio_sites";
|
|
1177
|
+
const info$8 = { "singularName": "site", "pluralName": "sites", "displayName": "Site", "description": "One site the CMS serves: its identity, its host names and the modules the frontend turns on" };
|
|
1117
1178
|
const options$8 = { "draftAndPublish": false };
|
|
1118
|
-
const pluginOptions$1 = { "content-manager": { "visible":
|
|
1119
|
-
const attributes$8 = { "
|
|
1120
|
-
const
|
|
1179
|
+
const pluginOptions$1 = { "content-manager": { "visible": true }, "content-type-builder": { "visible": false }, "i18n": { "localized": true } };
|
|
1180
|
+
const attributes$8 = { "name": { "type": "string", "required": true, "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "string", "regex": "^[a-z0-9]+(?:-[a-z0-9]+)*$", "maxLength": 64, "required": true, "unique": true, "pluginOptions": { "i18n": { "localized": false } } }, "hosts": { "type": "json", "pluginOptions": { "i18n": { "localized": false } } }, "isDefault": { "type": "boolean", "default": false, "required": true, "pluginOptions": { "i18n": { "localized": false } } }, "editorialPolicy": { "type": "json", "pluginOptions": { "i18n": { "localized": false } } }, "description": { "type": "text", "pluginOptions": { "i18n": { "localized": true } } }, "tagline": { "type": "string", "pluginOptions": { "i18n": { "localized": true } } }, "url": { "type": "string", "regex": "^https?://\\S+$", "pluginOptions": { "i18n": { "localized": false } } }, "defaultLocale": { "type": "enumeration", "enum": ["en", "es"], "default": "en", "required": true, "pluginOptions": { "i18n": { "localized": false } } }, "author": { "type": "component", "repeatable": false, "component": "micelio-site.author", "pluginOptions": { "i18n": { "localized": false } } }, "logo": { "type": "media", "multiple": false, "allowedTypes": ["images"], "pluginOptions": { "i18n": { "localized": false } } }, "favicon": { "type": "media", "multiple": false, "allowedTypes": ["images"], "pluginOptions": { "i18n": { "localized": false } } }, "defaultOgImage": { "type": "media", "multiple": false, "allowedTypes": ["images"], "pluginOptions": { "i18n": { "localized": false } } }, "socialLinks": { "type": "component", "repeatable": true, "component": "micelio-site.social-link", "pluginOptions": { "i18n": { "localized": false } } }, "contactEmail": { "type": "email", "pluginOptions": { "i18n": { "localized": false } } }, "privacyContactEmail": { "type": "email", "pluginOptions": { "i18n": { "localized": false } } }, "securityContact": { "type": "string", "maxLength": 512, "pluginOptions": { "i18n": { "localized": false } } }, "privacyJurisdiction": { "type": "enumeration", "enum": ["colombia"], "pluginOptions": { "i18n": { "localized": false } } }, "privacyUpdatedAt": { "type": "datetime", "pluginOptions": { "i18n": { "localized": false } } }, "supportHandle": { "type": "string", "regex": "^[A-Za-z0-9_-]+$", "pluginOptions": { "i18n": { "localized": false } } }, "timezone": { "type": "string", "regex": "^[A-Za-z][A-Za-z0-9]*(?:[/_+-][A-Za-z0-9]+)*$", "pluginOptions": { "i18n": { "localized": false } } }, "addressLocality": { "type": "string", "pluginOptions": { "i18n": { "localized": true } } }, "modules": { "type": "component", "repeatable": false, "component": "micelio-site.modules", "required": true, "pluginOptions": { "i18n": { "localized": false } } }, "theme": { "type": "component", "repeatable": false, "component": "micelio-site.theme", "pluginOptions": { "i18n": { "localized": false } } }, "fediverse": { "type": "component", "repeatable": false, "component": "micelio-site.fediverse", "pluginOptions": { "i18n": { "localized": false } } } };
|
|
1181
|
+
const site = {
|
|
1121
1182
|
kind: kind$1,
|
|
1122
1183
|
collectionName: collectionName$8,
|
|
1123
1184
|
info: info$8,
|
|
@@ -1126,12 +1187,12 @@ const previewCredential = {
|
|
|
1126
1187
|
attributes: attributes$8
|
|
1127
1188
|
};
|
|
1128
1189
|
const kind = "collectionType";
|
|
1129
|
-
const collectionName$7 = "
|
|
1130
|
-
const info$7 = { "singularName": "
|
|
1190
|
+
const collectionName$7 = "tags";
|
|
1191
|
+
const info$7 = { "singularName": "tag", "pluralName": "tags", "displayName": "Tag", "description": "Topics an article covers, used to filter the blog" };
|
|
1131
1192
|
const options$7 = { "draftAndPublish": false };
|
|
1132
|
-
const pluginOptions = { "content-manager": { "visible": true }, "
|
|
1133
|
-
const attributes$7 = { "name": { "type": "string", "required": true, "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "
|
|
1134
|
-
const
|
|
1193
|
+
const pluginOptions = { "content-manager": { "visible": true }, "i18n": { "localized": true } };
|
|
1194
|
+
const attributes$7 = { "name": { "type": "string", "required": true, "pluginOptions": { "i18n": { "localized": true } } }, "slug": { "type": "uid", "regex": "^(?!\\.{1,2}$)[A-Za-z0-9-_.~]*$", "targetField": "name", "required": true, "pluginOptions": { "i18n": { "localized": false } } } };
|
|
1195
|
+
const tag = {
|
|
1135
1196
|
kind,
|
|
1136
1197
|
collectionName: collectionName$7,
|
|
1137
1198
|
info: info$7,
|
|
@@ -1141,8 +1202,13 @@ const site = {
|
|
|
1141
1202
|
};
|
|
1142
1203
|
const contentTypes = {
|
|
1143
1204
|
site: { schema: site },
|
|
1205
|
+
category: { schema: withSiteScope(category) },
|
|
1206
|
+
tag: { schema: withSiteScope(tag) },
|
|
1144
1207
|
"preview-credential": { schema: withSiteScope(previewCredential) }
|
|
1145
1208
|
};
|
|
1209
|
+
const CATEGORY_UID = "plugin::micelio.category";
|
|
1210
|
+
const TAG_UID = "plugin::micelio.tag";
|
|
1211
|
+
const READ_ACTIONS$1 = [`${CATEGORY_UID}.find`, `${TAG_UID}.find`];
|
|
1146
1212
|
const blocks = () => ({
|
|
1147
1213
|
find(ctx) {
|
|
1148
1214
|
ctx.body = {
|
|
@@ -1160,18 +1226,19 @@ const PREVIEW_PATH = "/_preview";
|
|
|
1160
1226
|
const PREVIEW_GRANT_HEADER = "x-micelio-preview-grant";
|
|
1161
1227
|
const PREVIEW_TOKEN_TTL_SECONDS = 60;
|
|
1162
1228
|
const PREVIEW_GRANT_TTL_SECONDS = 15 * 60;
|
|
1229
|
+
const PREVIEW_SYSTEM_GRANT_TTL_SECONDS = 60;
|
|
1163
1230
|
const PREVIEW_CREDENTIAL_RETENTION_SECONDS = 60 * 60;
|
|
1164
1231
|
const PREVIEW_RATE_WINDOW_SECONDS = 60;
|
|
1165
1232
|
const PREVIEW_TOKEN_RATE_LIMIT = 20;
|
|
1166
1233
|
const PREVIEW_EXCHANGE_RATE_LIMIT = 60;
|
|
1167
1234
|
async function readableDraft(strapi, userAbility, contentType, documentId, locale) {
|
|
1168
1235
|
const uid = contentType;
|
|
1169
|
-
if (!strapi.contentType(uid)?.attributes?.[SITE_ATTRIBUTE]) return { status: "not-site-scoped" };
|
|
1236
|
+
if (!strapi.contentType(uid)?.attributes?.[SITE_ATTRIBUTE$1]) return { status: "not-site-scoped" };
|
|
1170
1237
|
const entry = await strapi.documents(uid).findOne({
|
|
1171
1238
|
documentId,
|
|
1172
1239
|
locale: locale ?? void 0,
|
|
1173
1240
|
status: "draft",
|
|
1174
|
-
populate: { [SITE_ATTRIBUTE]: { fields: ["documentId"] }, createdBy: true }
|
|
1241
|
+
populate: { [SITE_ATTRIBUTE$1]: { fields: ["documentId"] }, createdBy: true }
|
|
1175
1242
|
});
|
|
1176
1243
|
if (!entry?.site) return { status: "missing" };
|
|
1177
1244
|
const checker = strapi.plugin("content-manager").service("permission-checker").create({ userAbility, model: contentType });
|
|
@@ -1186,9 +1253,338 @@ async function abilityOf(strapi, adminUser) {
|
|
|
1186
1253
|
if (!user || user.isActive === false) return null;
|
|
1187
1254
|
return strapi.service("admin::permission").engine.generateUserAbility(user);
|
|
1188
1255
|
}
|
|
1256
|
+
const FILE_UID = "plugin::upload.file";
|
|
1257
|
+
const QUERY_KEYS = /* @__PURE__ */ new Set(["populate", "site"]);
|
|
1258
|
+
const ALWAYS_FIELDS = /* @__PURE__ */ new Set(["id", "documentId", "createdAt", "updatedAt"]);
|
|
1259
|
+
const NOT_SCALAR = /* @__PURE__ */ new Set(["relation", "component", "dynamiczone", "media"]);
|
|
1260
|
+
const NO_POPULATE = { all: false, children: /* @__PURE__ */ new Map() };
|
|
1261
|
+
class QueryProblem extends Error {
|
|
1262
|
+
}
|
|
1263
|
+
function readDraftQuery(strapi, query, schema) {
|
|
1264
|
+
try {
|
|
1265
|
+
for (const key of Object.keys(query)) {
|
|
1266
|
+
if (!QUERY_KEYS.has(key)) {
|
|
1267
|
+
throw new QueryProblem(
|
|
1268
|
+
`The draft read takes only documentId, locale and populate, not "${key}"`
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
return { populate: parsePopulate(strapi, query.populate, schema, "document", "populate") };
|
|
1273
|
+
} catch (error) {
|
|
1274
|
+
if (error instanceof QueryProblem) return { problem: error.message };
|
|
1275
|
+
throw error;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
async function readDraft(strapi, options2) {
|
|
1279
|
+
const schema = strapi.contentType(options2.uid);
|
|
1280
|
+
const params = await strapi.contentAPI.sanitize.query(
|
|
1281
|
+
{ populate: draftPopulate(strapi, options2.populate, schema) },
|
|
1282
|
+
schema,
|
|
1283
|
+
{ auth: options2.auth }
|
|
1284
|
+
);
|
|
1285
|
+
const entry = await strapi.documents(options2.uid).findOne({
|
|
1286
|
+
...params,
|
|
1287
|
+
documentId: options2.documentId,
|
|
1288
|
+
locale: options2.locale,
|
|
1289
|
+
status: "draft"
|
|
1290
|
+
});
|
|
1291
|
+
if (!entry) return null;
|
|
1292
|
+
await publishedRelations(strapi, entry, schema, options2.populate);
|
|
1293
|
+
await keepToSite(strapi, entry, schema, options2.siteDocumentId);
|
|
1294
|
+
return entry;
|
|
1295
|
+
}
|
|
1296
|
+
function fail(message) {
|
|
1297
|
+
throw new QueryProblem(message);
|
|
1298
|
+
}
|
|
1299
|
+
function attributeOf(schema, name2) {
|
|
1300
|
+
return Object.prototype.hasOwnProperty.call(schema.attributes, name2) ? schema.attributes[name2] : void 0;
|
|
1301
|
+
}
|
|
1302
|
+
function expand(value, path2) {
|
|
1303
|
+
const found = { all: false, pairs: [] };
|
|
1304
|
+
const add2 = (part2) => {
|
|
1305
|
+
if (part2 === void 0 || part2 === null || part2 === false || part2 === "false") return;
|
|
1306
|
+
if (part2 === true || part2 === "true") {
|
|
1307
|
+
found.all = true;
|
|
1308
|
+
} else if (typeof part2 === "string") {
|
|
1309
|
+
for (const name2 of part2.split(",").map((piece) => piece.trim())) {
|
|
1310
|
+
if (name2 === "") continue;
|
|
1311
|
+
if (name2 === "*") found.all = true;
|
|
1312
|
+
else {
|
|
1313
|
+
const [head = "", ...rest] = name2.split(".");
|
|
1314
|
+
found.pairs.push([head, rest.length > 0 ? { populate: rest.join(".") } : true]);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
} else if (Array.isArray(part2)) {
|
|
1318
|
+
for (const item of part2) {
|
|
1319
|
+
if (typeof item !== "string" && (typeof item !== "object" || item === null)) {
|
|
1320
|
+
fail(`${path2} must be a name, a list of names or an object`);
|
|
1321
|
+
}
|
|
1322
|
+
add2(item);
|
|
1323
|
+
}
|
|
1324
|
+
} else if (typeof part2 === "object") {
|
|
1325
|
+
found.pairs.push(...Object.entries(part2));
|
|
1326
|
+
} else {
|
|
1327
|
+
fail(`${path2} must be a name, a list of names or an object`);
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
add2(value);
|
|
1331
|
+
return found;
|
|
1332
|
+
}
|
|
1333
|
+
function parsePopulate(strapi, value, schema, scope, path2) {
|
|
1334
|
+
const { all: all2, pairs } = expand(value, path2);
|
|
1335
|
+
if (all2 && pairs.length > 0) fail(`${path2} cannot mix "*" with names`);
|
|
1336
|
+
if (all2 && scope === "related") fail(`${path2} cannot be "*" under a relation`);
|
|
1337
|
+
const children = /* @__PURE__ */ new Map();
|
|
1338
|
+
for (const [name2, sub] of pairs) {
|
|
1339
|
+
const here = `${path2}[${name2}]`;
|
|
1340
|
+
const attribute = attributeOf(schema, name2);
|
|
1341
|
+
if (!attribute || attribute.private === true) fail(`${here} is not an attribute of the type`);
|
|
1342
|
+
if (scope === "related" && attribute.type !== "media") {
|
|
1343
|
+
fail(`${here}: under a relation only a media attribute may be populated`);
|
|
1344
|
+
}
|
|
1345
|
+
if (children.has(name2)) fail(`${here} is named twice`);
|
|
1346
|
+
const node = parseNode(strapi, sub, attribute, here);
|
|
1347
|
+
if (node) children.set(name2, node);
|
|
1348
|
+
}
|
|
1349
|
+
return { all: all2, children };
|
|
1350
|
+
}
|
|
1351
|
+
function parseNode(strapi, sub, attribute, path2) {
|
|
1352
|
+
if (sub === false || sub === "false") return void 0;
|
|
1353
|
+
const options2 = sub === true || sub === "true" || sub === "" ? {} : sub;
|
|
1354
|
+
if (typeof options2 !== "object" || options2 === null || Array.isArray(options2)) {
|
|
1355
|
+
fail(`${path2} must be true or an object`);
|
|
1356
|
+
}
|
|
1357
|
+
const given = options2;
|
|
1358
|
+
const only = (...keys) => {
|
|
1359
|
+
for (const key of Object.keys(given)) {
|
|
1360
|
+
if (!keys.includes(key)) fail(`${path2} does not take "${key}"`);
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
switch (attribute.type) {
|
|
1364
|
+
case "media":
|
|
1365
|
+
only("fields");
|
|
1366
|
+
return { fields: fieldsOf(given.fields, strapi.contentType(FILE_UID), path2) };
|
|
1367
|
+
case "relation": {
|
|
1368
|
+
only("fields", "populate");
|
|
1369
|
+
const target = relationTarget(strapi, attribute, path2);
|
|
1370
|
+
const schema = strapi.contentType(target);
|
|
1371
|
+
const node = { fields: fieldsOf(given.fields, schema, path2) };
|
|
1372
|
+
if (given.populate !== void 0) {
|
|
1373
|
+
node.populate = parsePopulate(
|
|
1374
|
+
strapi,
|
|
1375
|
+
given.populate,
|
|
1376
|
+
schema,
|
|
1377
|
+
"related",
|
|
1378
|
+
`${path2}[populate]`
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
return node;
|
|
1382
|
+
}
|
|
1383
|
+
case "component":
|
|
1384
|
+
only("fields", "populate");
|
|
1385
|
+
return componentNode(strapi, given, attribute.component, path2);
|
|
1386
|
+
case "dynamiczone": {
|
|
1387
|
+
only("on");
|
|
1388
|
+
if (given.on === void 0) return {};
|
|
1389
|
+
if (typeof given.on !== "object" || given.on === null || Array.isArray(given.on)) {
|
|
1390
|
+
fail(`${path2}[on] must be an object`);
|
|
1391
|
+
}
|
|
1392
|
+
const on = /* @__PURE__ */ new Map();
|
|
1393
|
+
for (const [uid, fragment] of Object.entries(given.on)) {
|
|
1394
|
+
if (!attribute.components?.includes(uid))
|
|
1395
|
+
fail(`${path2}[on][${uid}] is not a component of the zone`);
|
|
1396
|
+
const node = parseNode(
|
|
1397
|
+
strapi,
|
|
1398
|
+
fragment,
|
|
1399
|
+
{ type: "component", component: uid },
|
|
1400
|
+
`${path2}[on][${uid}]`
|
|
1401
|
+
);
|
|
1402
|
+
if (node) on.set(uid, node);
|
|
1403
|
+
}
|
|
1404
|
+
return { on };
|
|
1405
|
+
}
|
|
1406
|
+
default:
|
|
1407
|
+
return fail(`${path2} is not a relation, a component, a dynamic zone or a media attribute`);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
function componentNode(strapi, given, uid, path2) {
|
|
1411
|
+
const component2 = strapi.components[uid];
|
|
1412
|
+
const node = { fields: fieldsOf(given.fields, component2, path2) };
|
|
1413
|
+
if (given.populate !== void 0) {
|
|
1414
|
+
node.populate = parsePopulate(
|
|
1415
|
+
strapi,
|
|
1416
|
+
given.populate,
|
|
1417
|
+
component2,
|
|
1418
|
+
"document",
|
|
1419
|
+
`${path2}[populate]`
|
|
1420
|
+
);
|
|
1421
|
+
}
|
|
1422
|
+
return node;
|
|
1423
|
+
}
|
|
1424
|
+
function relationTarget(strapi, attribute, path2) {
|
|
1425
|
+
const target = attribute.target;
|
|
1426
|
+
if (typeof target !== "string" || target.startsWith("admin::") || !(target in strapi.contentTypes)) {
|
|
1427
|
+
return fail(`${path2} is a relation the draft read does not follow`);
|
|
1428
|
+
}
|
|
1429
|
+
return target;
|
|
1430
|
+
}
|
|
1431
|
+
function fieldsOf(value, schema, path2) {
|
|
1432
|
+
if (value === void 0) return void 0;
|
|
1433
|
+
const names = (Array.isArray(value) ? value : [value]).flatMap((item) => {
|
|
1434
|
+
if (typeof item !== "string") return fail(`${path2}[fields] must be names of fields`);
|
|
1435
|
+
return item.split(",").map((piece) => piece.trim());
|
|
1436
|
+
});
|
|
1437
|
+
for (const name2 of names) {
|
|
1438
|
+
const attribute = attributeOf(schema, name2);
|
|
1439
|
+
const known = ALWAYS_FIELDS.has(name2) || attribute !== void 0 && attribute.private !== true;
|
|
1440
|
+
if (!known || attribute !== void 0 && NOT_SCALAR.has(attribute.type)) {
|
|
1441
|
+
fail(`${path2}[fields]: "${name2}" is not a field of the type`);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
return names.filter((name2) => name2 !== "");
|
|
1445
|
+
}
|
|
1446
|
+
function draftPopulate(strapi, spec, schema) {
|
|
1447
|
+
if (spec.all) return "*";
|
|
1448
|
+
const populate = {};
|
|
1449
|
+
for (const [name2, node] of spec.children) {
|
|
1450
|
+
const attribute = attributeOf(schema, name2);
|
|
1451
|
+
if (attribute?.type === "media") {
|
|
1452
|
+
populate[name2] = node.fields ? { fields: node.fields } : true;
|
|
1453
|
+
} else if (attribute?.type === "component") {
|
|
1454
|
+
populate[name2] = componentPopulate(strapi, node, attribute.component);
|
|
1455
|
+
} else if (attribute?.type === "dynamiczone") {
|
|
1456
|
+
populate[name2] = node.on ? {
|
|
1457
|
+
on: Object.fromEntries(
|
|
1458
|
+
[...node.on].map(([uid, fragment]) => [
|
|
1459
|
+
uid,
|
|
1460
|
+
componentPopulate(strapi, fragment, uid)
|
|
1461
|
+
])
|
|
1462
|
+
)
|
|
1463
|
+
} : true;
|
|
1464
|
+
} else {
|
|
1465
|
+
populate[name2] = true;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
return populate;
|
|
1469
|
+
}
|
|
1470
|
+
function componentPopulate(strapi, node, uid) {
|
|
1471
|
+
const options2 = {};
|
|
1472
|
+
if (node.fields) options2.fields = node.fields;
|
|
1473
|
+
if (node.populate) options2.populate = draftPopulate(strapi, node.populate, strapi.components[uid]);
|
|
1474
|
+
return Object.keys(options2).length > 0 ? options2 : true;
|
|
1475
|
+
}
|
|
1476
|
+
async function publishedRelations(strapi, entry, schema, spec) {
|
|
1477
|
+
for (const [name2, attribute] of Object.entries(schema.attributes)) {
|
|
1478
|
+
const value = entry[name2];
|
|
1479
|
+
if (value === void 0 || value === null) continue;
|
|
1480
|
+
const node = spec.children.get(name2) ?? (spec.all ? {} : void 0);
|
|
1481
|
+
if (attribute.type === "relation") {
|
|
1482
|
+
if (typeof attribute.target !== "string") {
|
|
1483
|
+
delete entry[name2];
|
|
1484
|
+
continue;
|
|
1485
|
+
}
|
|
1486
|
+
const target = attribute.target;
|
|
1487
|
+
const published = [];
|
|
1488
|
+
for (const related of Array.isArray(value) ? value : [value]) {
|
|
1489
|
+
const read = await publishedOf(strapi, target, related, node ?? {});
|
|
1490
|
+
if (read) published.push(read);
|
|
1491
|
+
}
|
|
1492
|
+
entry[name2] = Array.isArray(value) ? published : published[0] ?? null;
|
|
1493
|
+
} else if (attribute.type === "component") {
|
|
1494
|
+
const component2 = strapi.components[attribute.component];
|
|
1495
|
+
for (const child of Array.isArray(value) ? value : [value]) {
|
|
1496
|
+
await publishedRelations(strapi, child, component2, node?.populate ?? NO_POPULATE);
|
|
1497
|
+
}
|
|
1498
|
+
} else if (attribute.type === "dynamiczone") {
|
|
1499
|
+
for (const child of value) {
|
|
1500
|
+
const uid = child.__component;
|
|
1501
|
+
if (!(uid in strapi.components)) continue;
|
|
1502
|
+
await publishedRelations(
|
|
1503
|
+
strapi,
|
|
1504
|
+
child,
|
|
1505
|
+
strapi.components[uid],
|
|
1506
|
+
node?.on?.get(uid)?.populate ?? NO_POPULATE
|
|
1507
|
+
);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
async function publishedOf(strapi, target, related, node) {
|
|
1513
|
+
if (typeof related.documentId !== "string") return null;
|
|
1514
|
+
const media2 = {};
|
|
1515
|
+
for (const [name2, child] of node.populate?.children ?? []) {
|
|
1516
|
+
media2[name2] = child.fields ? { fields: child.fields } : true;
|
|
1517
|
+
}
|
|
1518
|
+
return await strapi.documents(target).findOne({
|
|
1519
|
+
documentId: related.documentId,
|
|
1520
|
+
locale: typeof related.locale === "string" ? related.locale : void 0,
|
|
1521
|
+
status: "published",
|
|
1522
|
+
fields: node.fields,
|
|
1523
|
+
populate: Object.keys(media2).length > 0 ? media2 : void 0
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
async function keepToSite(strapi, entry, schema, siteDocumentId) {
|
|
1527
|
+
const found = /* @__PURE__ */ new Map();
|
|
1528
|
+
await walk(strapi, entry, schema, async (target, entries) => {
|
|
1529
|
+
if (!isSiteScoped(strapi.contentType(target))) return entries;
|
|
1530
|
+
const ids = found.get(target) ?? /* @__PURE__ */ new Set();
|
|
1531
|
+
for (const { documentId } of entries) if (typeof documentId === "string") ids.add(documentId);
|
|
1532
|
+
found.set(target, ids);
|
|
1533
|
+
return entries;
|
|
1534
|
+
});
|
|
1535
|
+
if (found.size === 0) return;
|
|
1536
|
+
const owned = /* @__PURE__ */ new Map();
|
|
1537
|
+
for (const [target, ids] of found) {
|
|
1538
|
+
const published = strapi.contentType(target).options?.draftAndPublish === true;
|
|
1539
|
+
const rows = await strapi.db.query(target).findMany({
|
|
1540
|
+
select: ["documentId"],
|
|
1541
|
+
where: {
|
|
1542
|
+
documentId: { $in: [...ids] },
|
|
1543
|
+
[SITE_ATTRIBUTE$1]: { documentId: siteDocumentId },
|
|
1544
|
+
...published ? { publishedAt: { $notNull: true } } : {}
|
|
1545
|
+
}
|
|
1546
|
+
});
|
|
1547
|
+
owned.set(target, new Set(rows.map((row) => row.documentId)));
|
|
1548
|
+
}
|
|
1549
|
+
await walk(strapi, entry, schema, async (target, entries) => {
|
|
1550
|
+
const ids = owned.get(target);
|
|
1551
|
+
if (!isSiteScoped(strapi.contentType(target))) return entries;
|
|
1552
|
+
return entries.filter(
|
|
1553
|
+
({ documentId }) => typeof documentId === "string" && ids?.has(documentId) === true
|
|
1554
|
+
);
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
async function walk(strapi, entry, schema, visit) {
|
|
1558
|
+
for (const [name2, attribute] of Object.entries(schema.attributes)) {
|
|
1559
|
+
const value = entry[name2];
|
|
1560
|
+
if (value === void 0 || value === null) continue;
|
|
1561
|
+
if (attribute.type === "relation") {
|
|
1562
|
+
if (!("target" in attribute) || typeof attribute.target !== "string") {
|
|
1563
|
+
delete entry[name2];
|
|
1564
|
+
continue;
|
|
1565
|
+
}
|
|
1566
|
+
const target = attribute.target;
|
|
1567
|
+
const many = Array.isArray(value);
|
|
1568
|
+
const kept = await visit(target, many ? value : [value]);
|
|
1569
|
+
for (const child of kept) await walk(strapi, child, strapi.contentType(target), visit);
|
|
1570
|
+
entry[name2] = many ? kept : kept[0] ?? null;
|
|
1571
|
+
} else if (attribute.type === "component") {
|
|
1572
|
+
const component2 = strapi.components[attribute.component];
|
|
1573
|
+
for (const child of Array.isArray(value) ? value : [value]) {
|
|
1574
|
+
await walk(strapi, child, component2, visit);
|
|
1575
|
+
}
|
|
1576
|
+
} else if (attribute.type === "dynamiczone") {
|
|
1577
|
+
for (const child of value) {
|
|
1578
|
+
const component2 = strapi.components[child.__component];
|
|
1579
|
+
if (component2) await walk(strapi, child, component2, visit);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1189
1584
|
const LIFETIME_SECONDS = {
|
|
1190
1585
|
token: PREVIEW_TOKEN_TTL_SECONDS,
|
|
1191
|
-
grant: PREVIEW_GRANT_TTL_SECONDS
|
|
1586
|
+
grant: PREVIEW_GRANT_TTL_SECONDS,
|
|
1587
|
+
system: PREVIEW_SYSTEM_GRANT_TTL_SECONDS
|
|
1192
1588
|
};
|
|
1193
1589
|
function hashCredential(value) {
|
|
1194
1590
|
return createHash("sha256").update(value).digest("hex");
|
|
@@ -1196,6 +1592,9 @@ function hashCredential(value) {
|
|
|
1196
1592
|
function issueCredential(kind2, binding, now = /* @__PURE__ */ new Date()) {
|
|
1197
1593
|
const value = randomBytes(32).toString("base64url");
|
|
1198
1594
|
const record = {
|
|
1595
|
+
adminUser: null,
|
|
1596
|
+
adminOrigin: null,
|
|
1597
|
+
entryVersion: null,
|
|
1199
1598
|
...binding,
|
|
1200
1599
|
kind: kind2,
|
|
1201
1600
|
hash: hashCredential(value),
|
|
@@ -1224,15 +1623,22 @@ class PreviewUnavailableError extends Error {
|
|
|
1224
1623
|
const preview$1 = ({ strapi }) => {
|
|
1225
1624
|
const store2 = () => strapi.db.query(PREVIEW_CREDENTIAL_UID);
|
|
1226
1625
|
async function save(record) {
|
|
1227
|
-
const site2 = await strapi.db.query(SITE_UID).findOne({ where: { documentId: record.siteDocumentId }, select: ["id"] });
|
|
1626
|
+
const site2 = await strapi.db.query(SITE_UID$1).findOne({ where: { documentId: record.siteDocumentId }, select: ["id"] });
|
|
1228
1627
|
await store2().create({ data: { ...record, site: site2?.id } });
|
|
1229
1628
|
}
|
|
1230
|
-
async function find(
|
|
1629
|
+
async function find(kinds, value) {
|
|
1231
1630
|
const row = await store2().findOne({
|
|
1232
|
-
where: { hash: hashCredential(value), kind:
|
|
1631
|
+
where: { hash: hashCredential(value), kind: { $in: kinds } }
|
|
1233
1632
|
});
|
|
1234
1633
|
return row;
|
|
1235
1634
|
}
|
|
1635
|
+
async function removeExpired() {
|
|
1636
|
+
await store2().deleteMany({
|
|
1637
|
+
where: {
|
|
1638
|
+
expiresAt: { $lt: new Date(Date.now() - PREVIEW_CREDENTIAL_RETENTION_SECONDS * 1e3) }
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1236
1642
|
async function revoke(adminUser, entryDocumentId) {
|
|
1237
1643
|
await store2().updateMany({
|
|
1238
1644
|
where: {
|
|
@@ -1253,43 +1659,56 @@ const preview$1 = ({ strapi }) => {
|
|
|
1253
1659
|
}
|
|
1254
1660
|
return {
|
|
1255
1661
|
async issueToken(binding) {
|
|
1256
|
-
const site2 = await strapi.db.query(SITE_UID).findOne({ where: { documentId: binding.siteDocumentId }, select: ["url"] });
|
|
1662
|
+
const site2 = await strapi.db.query(SITE_UID$1).findOne({ where: { documentId: binding.siteDocumentId }, select: ["url"] });
|
|
1257
1663
|
const url = previewUrlOf(site2?.url);
|
|
1258
1664
|
if (!url) throw new PreviewUnavailableError(binding.siteDocumentId);
|
|
1259
|
-
await
|
|
1260
|
-
where: {
|
|
1261
|
-
expiresAt: { $lt: new Date(Date.now() - PREVIEW_CREDENTIAL_RETENTION_SECONDS * 1e3) }
|
|
1262
|
-
}
|
|
1263
|
-
});
|
|
1665
|
+
await removeExpired();
|
|
1264
1666
|
const { value, record } = issueCredential("token", binding);
|
|
1265
1667
|
await save(record);
|
|
1266
1668
|
url.searchParams.set("token", value);
|
|
1267
1669
|
return { url: url.toString(), expiresAt: record.expiresAt.toISOString() };
|
|
1268
1670
|
},
|
|
1269
1671
|
async exchange(token, siteDocumentId) {
|
|
1270
|
-
const row = await find("token", token);
|
|
1672
|
+
const row = await find(["token"], token);
|
|
1271
1673
|
if (!row || !mayUseCredential(toRecord(row), "token", { siteDocumentId })) return null;
|
|
1272
1674
|
const claimed = await store2().updateMany({
|
|
1273
1675
|
where: { id: row.id, usedAt: null, revokedAt: null },
|
|
1274
1676
|
data: { usedAt: /* @__PURE__ */ new Date() }
|
|
1275
1677
|
});
|
|
1276
1678
|
if (claimed.count !== 1) return null;
|
|
1277
|
-
|
|
1278
|
-
|
|
1679
|
+
const binding = adminBindingOf(row);
|
|
1680
|
+
if (!binding || !await stillReadable(binding)) return null;
|
|
1681
|
+
const { value, record } = issueCredential("grant", binding);
|
|
1279
1682
|
await save(record);
|
|
1280
1683
|
return {
|
|
1281
1684
|
grant: value,
|
|
1282
1685
|
expiresAt: record.expiresAt.toISOString(),
|
|
1283
|
-
adminOrigin:
|
|
1686
|
+
adminOrigin: binding.adminOrigin,
|
|
1284
1687
|
contentType: row.contentType,
|
|
1285
1688
|
documentId: row.entryDocumentId,
|
|
1286
1689
|
locale: row.entryLocale
|
|
1287
1690
|
};
|
|
1288
1691
|
},
|
|
1692
|
+
async issueSystemGrant(binding) {
|
|
1693
|
+
await removeExpired();
|
|
1694
|
+
const { value, record } = issueCredential("system", binding);
|
|
1695
|
+
await save(record);
|
|
1696
|
+
return value;
|
|
1697
|
+
},
|
|
1289
1698
|
async resolveGrant(grant, expected) {
|
|
1290
|
-
const row = await find("grant", grant);
|
|
1291
|
-
if (!row || !mayUseCredential(toRecord(row),
|
|
1292
|
-
|
|
1699
|
+
const row = await find(["grant", "system"], grant);
|
|
1700
|
+
if (!row || !mayUseCredential(toRecord(row), row.kind, expected)) return null;
|
|
1701
|
+
if (row.kind === "system") {
|
|
1702
|
+
const claimed = await store2().updateMany({
|
|
1703
|
+
where: { id: row.id, usedAt: null, revokedAt: null },
|
|
1704
|
+
data: { usedAt: /* @__PURE__ */ new Date() }
|
|
1705
|
+
});
|
|
1706
|
+
if (claimed.count !== 1) return null;
|
|
1707
|
+
return { ...targetOf(row), actor: "system", entryVersion: row.entryVersion };
|
|
1708
|
+
}
|
|
1709
|
+
const binding = adminBindingOf(row);
|
|
1710
|
+
if (!binding || !await stillReadable(binding)) return null;
|
|
1711
|
+
return { ...targetOf(row), actor: "admin", entryVersion: null };
|
|
1293
1712
|
},
|
|
1294
1713
|
revoke
|
|
1295
1714
|
};
|
|
@@ -1306,21 +1725,26 @@ function previewUrlOf(url) {
|
|
|
1306
1725
|
return void 0;
|
|
1307
1726
|
}
|
|
1308
1727
|
}
|
|
1309
|
-
function
|
|
1728
|
+
function targetOf(row) {
|
|
1310
1729
|
return {
|
|
1311
|
-
adminUser: row.adminUser,
|
|
1312
|
-
adminOrigin: row.adminOrigin,
|
|
1313
1730
|
siteDocumentId: row.siteDocumentId,
|
|
1314
1731
|
contentType: row.contentType,
|
|
1315
1732
|
entryDocumentId: row.entryDocumentId,
|
|
1316
1733
|
entryLocale: row.entryLocale
|
|
1317
1734
|
};
|
|
1318
1735
|
}
|
|
1736
|
+
function adminBindingOf(row) {
|
|
1737
|
+
if (row.adminUser === null || row.adminOrigin === null) return null;
|
|
1738
|
+
return { ...targetOf(row), adminUser: row.adminUser, adminOrigin: row.adminOrigin };
|
|
1739
|
+
}
|
|
1319
1740
|
function toRecord(row) {
|
|
1320
1741
|
return {
|
|
1321
|
-
...
|
|
1742
|
+
...targetOf(row),
|
|
1322
1743
|
kind: row.kind,
|
|
1323
1744
|
hash: row.hash,
|
|
1745
|
+
adminUser: row.adminUser,
|
|
1746
|
+
adminOrigin: row.adminOrigin,
|
|
1747
|
+
entryVersion: row.entryVersion,
|
|
1324
1748
|
expiresAt: new Date(row.expiresAt),
|
|
1325
1749
|
usedAt: row.usedAt ? new Date(row.usedAt) : null,
|
|
1326
1750
|
revokedAt: row.revokedAt ? new Date(row.revokedAt) : null
|
|
@@ -1358,6 +1782,16 @@ const preview = ({ strapi }) => {
|
|
|
1358
1782
|
const previews = () => strapi.plugin("micelio").service("preview");
|
|
1359
1783
|
const tokenLimit = createRateLimiter(PREVIEW_TOKEN_RATE_LIMIT, PREVIEW_RATE_WINDOW_SECONDS);
|
|
1360
1784
|
const exchangeLimit = createRateLimiter(PREVIEW_EXCHANGE_RATE_LIMIT, PREVIEW_RATE_WINDOW_SECONDS);
|
|
1785
|
+
async function isVersionOf(uid, binding) {
|
|
1786
|
+
const current = await strapi.documents(uid).findOne({
|
|
1787
|
+
documentId: binding.entryDocumentId,
|
|
1788
|
+
locale: binding.entryLocale ?? void 0,
|
|
1789
|
+
status: "draft",
|
|
1790
|
+
fields: ["updatedAt"]
|
|
1791
|
+
});
|
|
1792
|
+
if (!current?.updatedAt || !binding.entryVersion) return false;
|
|
1793
|
+
return new Date(current.updatedAt).getTime() === new Date(binding.entryVersion).getTime();
|
|
1794
|
+
}
|
|
1361
1795
|
return {
|
|
1362
1796
|
async token(ctx) {
|
|
1363
1797
|
const ability = ctx.state.userAbility;
|
|
@@ -1461,22 +1895,37 @@ const preview = ({ strapi }) => {
|
|
|
1461
1895
|
}
|
|
1462
1896
|
const uid = binding.contentType;
|
|
1463
1897
|
const schema = strapi.contentType(uid);
|
|
1898
|
+
const read = readDraftQuery(strapi, query, schema);
|
|
1899
|
+
if ("problem" in read) {
|
|
1900
|
+
refuse(ctx, 400, "previewRequestInvalid", read.problem);
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1464
1903
|
const auth = ctx.state.auth;
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1904
|
+
let entry;
|
|
1905
|
+
try {
|
|
1906
|
+
entry = await readDraft(strapi, {
|
|
1907
|
+
uid,
|
|
1908
|
+
documentId: binding.entryDocumentId,
|
|
1909
|
+
locale: binding.entryLocale ?? void 0,
|
|
1910
|
+
populate: read.populate,
|
|
1911
|
+
siteDocumentId: siteOf(ctx),
|
|
1912
|
+
auth
|
|
1913
|
+
});
|
|
1914
|
+
} catch (error) {
|
|
1915
|
+
if (!(error instanceof errors.ValidationError || error instanceof errors.PaginationError)) {
|
|
1916
|
+
throw error;
|
|
1917
|
+
}
|
|
1918
|
+
refuse(ctx, 400, "previewRequestInvalid", error.message);
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1921
|
+
if (!entry || binding.actor === "system" && !await isVersionOf(uid, binding)) {
|
|
1473
1922
|
refuse(ctx, 404, "previewRefused", REFUSED);
|
|
1474
1923
|
return;
|
|
1475
1924
|
}
|
|
1476
1925
|
ctx.set("Cache-Control", "private, no-store");
|
|
1477
1926
|
ctx.body = {
|
|
1478
1927
|
data: await strapi.contentAPI.sanitize.output(entry, schema, { auth }),
|
|
1479
|
-
meta: {}
|
|
1928
|
+
meta: { actor: binding.actor }
|
|
1480
1929
|
};
|
|
1481
1930
|
}
|
|
1482
1931
|
};
|
|
@@ -1509,8 +1958,8 @@ function readTokenBody(body) {
|
|
|
1509
1958
|
return { uid, documentId, locale };
|
|
1510
1959
|
}
|
|
1511
1960
|
const name = "@micelio/strapi-plugin-core";
|
|
1512
|
-
const version$1 = "0.
|
|
1513
|
-
const engines = { "node": ">=22.
|
|
1961
|
+
const version$1 = "0.2.0";
|
|
1962
|
+
const engines = { "node": ">=22.19.0" };
|
|
1514
1963
|
const micelio = "0.6";
|
|
1515
1964
|
const packageJson = {
|
|
1516
1965
|
name,
|
|
@@ -1755,7 +2204,7 @@ function runSanitiser(loaded, html) {
|
|
|
1755
2204
|
return void 0;
|
|
1756
2205
|
}
|
|
1757
2206
|
async function readSiteOrigins(strapi) {
|
|
1758
|
-
const sites = await strapi.db.query(SITE_UID).findMany({ select: ["url"] });
|
|
2207
|
+
const sites = await strapi.db.query(SITE_UID$1).findMany({ select: ["url"] });
|
|
1759
2208
|
const origins = /* @__PURE__ */ new Set();
|
|
1760
2209
|
for (const { url } of sites) {
|
|
1761
2210
|
if (!url) continue;
|
|
@@ -1813,7 +2262,7 @@ async function readSitesWithSections(strapi, sections) {
|
|
|
1813
2262
|
async function readSiteRows(strapi, populate) {
|
|
1814
2263
|
const locales = strapi.plugin("i18n").service("locales");
|
|
1815
2264
|
const defaultLocale = await locales.getDefaultLocale();
|
|
1816
|
-
const rows = await strapi.db.query(SITE_UID).findMany({
|
|
2265
|
+
const rows = await strapi.db.query(SITE_UID$1).findMany({
|
|
1817
2266
|
select: ["documentId", "locale", "name", "slug", "hosts", "isDefault", "url"],
|
|
1818
2267
|
populate,
|
|
1819
2268
|
orderBy: { slug: "asc" }
|
|
@@ -1876,7 +2325,7 @@ const extensions$1 = ({ strapi }) => {
|
|
|
1876
2325
|
},
|
|
1877
2326
|
async sites(ctx) {
|
|
1878
2327
|
const ability = abilityOf2(ctx);
|
|
1879
|
-
if (ability?.can(READ_SITES, SITE_UID) !== true) {
|
|
2328
|
+
if (ability?.can(READ_SITES, SITE_UID$1) !== true) {
|
|
1880
2329
|
sendProblem(ctx, {
|
|
1881
2330
|
type: "about:blank",
|
|
1882
2331
|
title: "Forbidden",
|
|
@@ -1975,7 +2424,9 @@ function readBody(body) {
|
|
|
1975
2424
|
return { uid, documentId, to, locale, publishAt };
|
|
1976
2425
|
}
|
|
1977
2426
|
const controllers = {
|
|
1978
|
-
site: factories.createCoreController(SITE_UID),
|
|
2427
|
+
site: factories.createCoreController(SITE_UID$1),
|
|
2428
|
+
category: factories.createCoreController(CATEGORY_UID),
|
|
2429
|
+
tag: factories.createCoreController(TAG_UID),
|
|
1979
2430
|
blocks,
|
|
1980
2431
|
transitions: transitions$1,
|
|
1981
2432
|
status: status$1,
|
|
@@ -2015,7 +2466,7 @@ const siteScope = (_config, { strapi }) => {
|
|
|
2015
2466
|
};
|
|
2016
2467
|
};
|
|
2017
2468
|
async function loadSites(strapi) {
|
|
2018
|
-
const rows = await strapi.db.query(SITE_UID).findMany({
|
|
2469
|
+
const rows = await strapi.db.query(SITE_UID$1).findMany({
|
|
2019
2470
|
select: ["documentId", "slug", "hosts", "isDefault"]
|
|
2020
2471
|
});
|
|
2021
2472
|
const sites = /* @__PURE__ */ new Map();
|
|
@@ -2117,16 +2568,16 @@ const COMPONENTS = {
|
|
|
2117
2568
|
function registerComponents(strapi) {
|
|
2118
2569
|
const components = Object.fromEntries(
|
|
2119
2570
|
Object.entries(COMPONENTS).flatMap(
|
|
2120
|
-
([
|
|
2121
|
-
const uid = `${
|
|
2571
|
+
([category2, schemas]) => Object.entries(schemas).map(([name2, schema]) => {
|
|
2572
|
+
const uid = `${category2}.${name2}`;
|
|
2122
2573
|
const component2 = {
|
|
2123
2574
|
...structuredClone(schema),
|
|
2124
2575
|
__schema__: structuredClone(schema),
|
|
2125
2576
|
uid,
|
|
2126
|
-
category,
|
|
2577
|
+
category: category2,
|
|
2127
2578
|
modelType: "component",
|
|
2128
2579
|
modelName: name2,
|
|
2129
|
-
globalId: `Component${pascalCase(
|
|
2580
|
+
globalId: `Component${pascalCase(category2)}${pascalCase(name2)}`
|
|
2130
2581
|
};
|
|
2131
2582
|
return [uid, component2];
|
|
2132
2583
|
})
|
|
@@ -2174,10 +2625,120 @@ async function storedState(strapi, uid, params) {
|
|
|
2174
2625
|
});
|
|
2175
2626
|
return entry?.editorial?.state ?? "draft";
|
|
2176
2627
|
}
|
|
2628
|
+
const LEGACY_TO_PLUGIN = {
|
|
2629
|
+
"api::category.category": "plugin::micelio.category",
|
|
2630
|
+
"api::tag.tag": "plugin::micelio.tag"
|
|
2631
|
+
};
|
|
2632
|
+
const CONFIGURATION_KEY_PREFIX = "plugin_content_manager_configuration_content_types::";
|
|
2633
|
+
const ACTION_TABLES = [
|
|
2634
|
+
{ uid: "plugin::users-permissions.permission", owner: "role" },
|
|
2635
|
+
{ uid: "admin::api-token-permission", owner: "token" }
|
|
2636
|
+
];
|
|
2637
|
+
async function renameLegacyUids(strapi) {
|
|
2638
|
+
const report = { actions: 0, subjects: 0, layouts: 0 };
|
|
2639
|
+
for (const [legacy, current] of Object.entries(LEGACY_TO_PLUGIN)) {
|
|
2640
|
+
if (strapi.contentTypes[legacy]) {
|
|
2641
|
+
strapi.log.info(
|
|
2642
|
+
`micelio: kept the grants and layouts of ${legacy}: the host still registers that type`
|
|
2643
|
+
);
|
|
2644
|
+
continue;
|
|
2645
|
+
}
|
|
2646
|
+
for (const { uid, owner } of ACTION_TABLES) {
|
|
2647
|
+
report.actions += await renameActions(strapi, uid, owner, legacy, current);
|
|
2648
|
+
}
|
|
2649
|
+
report.subjects += await renameSubjects(strapi, legacy, current);
|
|
2650
|
+
report.layouts += await renameLayouts(strapi, legacy, current);
|
|
2651
|
+
}
|
|
2652
|
+
return report;
|
|
2653
|
+
}
|
|
2654
|
+
async function hasTable(strapi, uid) {
|
|
2655
|
+
if (!strapi.db.metadata.has(uid)) return false;
|
|
2656
|
+
const tableName = strapi.db.metadata.get(uid).tableName;
|
|
2657
|
+
return Boolean(tableName) && await strapi.db.getSchemaConnection().hasTable(tableName);
|
|
2658
|
+
}
|
|
2659
|
+
async function renameActions(strapi, uid, owner, legacy, current) {
|
|
2660
|
+
if (!await hasTable(strapi, uid)) return 0;
|
|
2661
|
+
const rows = await strapi.db.query(uid).findMany({
|
|
2662
|
+
where: { action: { $startsWith: `${legacy}.` } },
|
|
2663
|
+
populate: { [owner]: { select: ["id"] } }
|
|
2664
|
+
});
|
|
2665
|
+
for (const row of rows) {
|
|
2666
|
+
const action = `${current}${row.action.slice(legacy.length)}`;
|
|
2667
|
+
const ownerRow = row[owner];
|
|
2668
|
+
const twin = ownerRow ? await strapi.db.query(uid).findOne({ where: { action, [owner]: ownerRow.id } }) : null;
|
|
2669
|
+
if (twin) {
|
|
2670
|
+
await strapi.db.query(uid).delete({ where: { id: row.id } });
|
|
2671
|
+
} else {
|
|
2672
|
+
await strapi.db.query(uid).update({ where: { id: row.id }, data: { action } });
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
return rows.length;
|
|
2676
|
+
}
|
|
2677
|
+
async function renameSubjects(strapi, legacy, current) {
|
|
2678
|
+
const uid = "admin::permission";
|
|
2679
|
+
if (!await hasTable(strapi, uid)) return 0;
|
|
2680
|
+
const rows = await strapi.db.query(uid).findMany({
|
|
2681
|
+
where: { subject: legacy },
|
|
2682
|
+
populate: { role: { select: ["id"] } }
|
|
2683
|
+
});
|
|
2684
|
+
for (const row of rows) {
|
|
2685
|
+
const twin = row.role ? await strapi.db.query(uid).findOne({ where: { action: row.action, subject: current, role: row.role.id } }) : null;
|
|
2686
|
+
if (twin) {
|
|
2687
|
+
await strapi.db.query(uid).delete({ where: { id: row.id } });
|
|
2688
|
+
} else {
|
|
2689
|
+
await strapi.db.query(uid).update({ where: { id: row.id }, data: { subject: current } });
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
return rows.length;
|
|
2693
|
+
}
|
|
2694
|
+
function replaceWholeUid(text2, legacy, current) {
|
|
2695
|
+
const escaped = legacy.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2696
|
+
return text2.replace(new RegExp(`${escaped}(?![A-Za-z0-9_-])`, "g"), () => current);
|
|
2697
|
+
}
|
|
2698
|
+
async function renameLayouts(strapi, legacy, current) {
|
|
2699
|
+
const uid = "strapi::core-store";
|
|
2700
|
+
if (!await hasTable(strapi, uid)) return 0;
|
|
2701
|
+
const rows = await strapi.db.query(uid).findMany({
|
|
2702
|
+
where: { key: { $startsWith: CONFIGURATION_KEY_PREFIX } }
|
|
2703
|
+
});
|
|
2704
|
+
let changed = 0;
|
|
2705
|
+
for (const row of rows) {
|
|
2706
|
+
const key = replaceWholeUid(row.key, legacy, current);
|
|
2707
|
+
const value = row.value ? replaceWholeUid(row.value, legacy, current) : row.value;
|
|
2708
|
+
if (key === row.key && value === row.value) continue;
|
|
2709
|
+
changed += 1;
|
|
2710
|
+
if (key !== row.key && await strapi.db.query(uid).findOne({ where: { key } })) {
|
|
2711
|
+
await strapi.db.query(uid).delete({ where: { id: row.id } });
|
|
2712
|
+
} else {
|
|
2713
|
+
await strapi.db.query(uid).update({ where: { id: row.id }, data: { key, value } });
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
return changed;
|
|
2717
|
+
}
|
|
2718
|
+
function previewPageUrl(strapi, uid, { documentId, locale }) {
|
|
2719
|
+
const schema = strapi.contentType(uid);
|
|
2720
|
+
const hasDynamicZone = Object.values(schema?.attributes ?? {}).some(
|
|
2721
|
+
({ type }) => type === "dynamiczone"
|
|
2722
|
+
);
|
|
2723
|
+
if (!documentId || schema?.kind !== "collectionType") return void 0;
|
|
2724
|
+
if (!isSiteScoped(schema) || !hasDynamicZone) return void 0;
|
|
2725
|
+
const base = strapi.config.get("admin.url", "/admin");
|
|
2726
|
+
const page = `${base.replace(/\/$/, "")}/plugins/micelio/preview/${encodeURIComponent(uid)}/${encodeURIComponent(documentId)}`;
|
|
2727
|
+
return locale ? `${page}?locale=${encodeURIComponent(locale)}` : page;
|
|
2728
|
+
}
|
|
2729
|
+
function registerPreviewShortcut(strapi) {
|
|
2730
|
+
if (strapi.config.get("admin.preview") !== void 0) return;
|
|
2731
|
+
strapi.config.set("admin.preview", {
|
|
2732
|
+
enabled: true,
|
|
2733
|
+
config: {
|
|
2734
|
+
handler: (uid, params) => previewPageUrl(strapi, uid, params)
|
|
2735
|
+
}
|
|
2736
|
+
});
|
|
2737
|
+
}
|
|
2177
2738
|
function siteCreatedHook(strapi) {
|
|
2178
2739
|
return async (context, next) => {
|
|
2179
2740
|
const result = await next();
|
|
2180
|
-
if (context.uid !== SITE_UID || context.action !== "create") return result;
|
|
2741
|
+
if (context.uid !== SITE_UID$1 || context.action !== "create") return result;
|
|
2181
2742
|
const site2 = result;
|
|
2182
2743
|
await hooksOf(strapi).runAfter("siteCreated", {
|
|
2183
2744
|
site: site2.documentId,
|
|
@@ -2196,14 +2757,16 @@ function siteScopeDocuments(strapi) {
|
|
|
2196
2757
|
const site2 = currentSite(strapi);
|
|
2197
2758
|
if (context.action === "create") {
|
|
2198
2759
|
params.data = params.data ?? {};
|
|
2199
|
-
if (
|
|
2200
|
-
|
|
2201
|
-
|
|
2760
|
+
if (site2) params.data[SITE_ATTRIBUTE$1] = site2.documentId;
|
|
2761
|
+
else if (isMissing(params.data[SITE_ATTRIBUTE$1])) {
|
|
2762
|
+
throw new errors.ValidationError(`${SITE_ATTRIBUTE$1} is required`);
|
|
2202
2763
|
}
|
|
2203
2764
|
}
|
|
2204
|
-
if (context.action === "update" && params.data && SITE_ATTRIBUTE in params.data) {
|
|
2205
|
-
if (
|
|
2206
|
-
|
|
2765
|
+
if (context.action === "update" && params.data && SITE_ATTRIBUTE$1 in params.data) {
|
|
2766
|
+
if (site2) delete params.data[SITE_ATTRIBUTE$1];
|
|
2767
|
+
else if (isUnchanged(params.data[SITE_ATTRIBUTE$1])) delete params.data[SITE_ATTRIBUTE$1];
|
|
2768
|
+
else if (isMissing(params.data[SITE_ATTRIBUTE$1])) {
|
|
2769
|
+
throw new errors.ValidationError(`${SITE_ATTRIBUTE$1} is required`);
|
|
2207
2770
|
}
|
|
2208
2771
|
}
|
|
2209
2772
|
if (site2 && READ_ACTIONS.has(context.action)) {
|
|
@@ -2215,21 +2778,119 @@ function siteScopeDocuments(strapi) {
|
|
|
2215
2778
|
});
|
|
2216
2779
|
if (owned === 0) throw new errors.NotFoundError("Not Found");
|
|
2217
2780
|
}
|
|
2218
|
-
|
|
2781
|
+
if (context.action === "update" && params.documentId) {
|
|
2782
|
+
await keepSiteOfLocales(strapi, context.uid, params);
|
|
2783
|
+
}
|
|
2784
|
+
const result = await next();
|
|
2785
|
+
if (rebuildsRelations(context.action, params) && params.documentId) {
|
|
2786
|
+
await repairSiteOfLocales(strapi, context.uid, params);
|
|
2787
|
+
}
|
|
2788
|
+
return result;
|
|
2219
2789
|
};
|
|
2220
2790
|
}
|
|
2791
|
+
async function keepSiteOfLocales(strapi, uid, params) {
|
|
2792
|
+
if (!isLocalized(strapi, uid)) return;
|
|
2793
|
+
const locale = typeof params.locale === "string" ? params.locale : await strapi.plugin("i18n").service("locales").getDefaultLocale();
|
|
2794
|
+
const { documentId } = params;
|
|
2795
|
+
const rows = await strapi.db.query(uid).findMany({
|
|
2796
|
+
where: { documentId },
|
|
2797
|
+
populate: { [SITE_ATTRIBUTE$1]: { select: ["id", "documentId"] } }
|
|
2798
|
+
});
|
|
2799
|
+
if (rows.length === 0) return;
|
|
2800
|
+
const named = params.data?.[SITE_ATTRIBUTE$1];
|
|
2801
|
+
if (rows.some((row) => row.locale === locale)) {
|
|
2802
|
+
if (named !== void 0) await refuseMoveAwayFromOtherLocales(strapi, rows, locale, named);
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
const sites = new Map(
|
|
2806
|
+
rows.flatMap((row) => row.site ? [[row.site.documentId, row.site.id]] : [])
|
|
2807
|
+
);
|
|
2808
|
+
const data = params.data = params.data ?? {};
|
|
2809
|
+
if (named !== void 0) {
|
|
2810
|
+
if (sites.size !== 1) return;
|
|
2811
|
+
const [[shared]] = [...sites];
|
|
2812
|
+
for (const documentIdOfNamed of await namedSites(strapi, named)) {
|
|
2813
|
+
if (documentIdOfNamed !== shared) {
|
|
2814
|
+
throw new errors.ValidationError(`${SITE_ATTRIBUTE$1} must be the site of the other locales`);
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
} else if (sites.size !== 1) {
|
|
2818
|
+
throw new errors.ValidationError(`${SITE_ATTRIBUTE$1} is required`);
|
|
2819
|
+
}
|
|
2820
|
+
data[SITE_ATTRIBUTE$1] = { connect: [{ id: [...sites.values()][0] }] };
|
|
2821
|
+
}
|
|
2822
|
+
async function refuseMoveAwayFromOtherLocales(strapi, rows, locale, named) {
|
|
2823
|
+
const target = new Set(await namedSites(strapi, named));
|
|
2824
|
+
const own = rows.filter((row) => row.locale === locale).flatMap((row) => row.site?.documentId ?? []);
|
|
2825
|
+
if (target.size === 0 || [...target].every((site2) => own.includes(site2))) return;
|
|
2826
|
+
const staysElsewhere = rows.some(
|
|
2827
|
+
(row) => row.locale !== locale && row.site && !target.has(row.site.documentId)
|
|
2828
|
+
);
|
|
2829
|
+
if (staysElsewhere) {
|
|
2830
|
+
throw new errors.ValidationError(
|
|
2831
|
+
`${SITE_ATTRIBUTE$1} cannot change while other locales of the document stay on another site`
|
|
2832
|
+
);
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
async function namedSites(strapi, value) {
|
|
2836
|
+
if (typeof value === "string") return [value];
|
|
2837
|
+
if (typeof value === "number") return [await documentIdOfSite(strapi, value)];
|
|
2838
|
+
if (Array.isArray(value))
|
|
2839
|
+
return (await Promise.all(value.map((v) => namedSites(strapi, v)))).flat();
|
|
2840
|
+
if (typeof value !== "object" || value === null) return [];
|
|
2841
|
+
const { documentId, id: id2, connect, set } = value;
|
|
2842
|
+
if (typeof documentId === "string") return [documentId];
|
|
2843
|
+
if (typeof id2 === "number") return [await documentIdOfSite(strapi, id2)];
|
|
2844
|
+
return [...await namedSites(strapi, connect), ...await namedSites(strapi, set)];
|
|
2845
|
+
}
|
|
2846
|
+
async function documentIdOfSite(strapi, id2) {
|
|
2847
|
+
const row = await strapi.db.query(SITE_UID$1).findOne({ where: { id: id2 } });
|
|
2848
|
+
return row?.documentId ?? String(id2);
|
|
2849
|
+
}
|
|
2850
|
+
function isLocalized(strapi, uid) {
|
|
2851
|
+
const model = strapi.contentType(uid);
|
|
2852
|
+
const options2 = model.pluginOptions;
|
|
2853
|
+
return options2?.i18n?.localized === true;
|
|
2854
|
+
}
|
|
2855
|
+
function rebuildsRelations(action, params) {
|
|
2856
|
+
return action === "publish" || action === "discardDraft" || action === "update" && params.status === "published";
|
|
2857
|
+
}
|
|
2858
|
+
async function repairSiteOfLocales(strapi, uid, params) {
|
|
2859
|
+
if (!isLocalized(strapi, uid)) return;
|
|
2860
|
+
const query = strapi.db.query(uid);
|
|
2861
|
+
const rows = await query.findMany({
|
|
2862
|
+
where: {
|
|
2863
|
+
documentId: params.documentId,
|
|
2864
|
+
...typeof params.locale === "string" && params.locale !== "*" ? { locale: params.locale } : {}
|
|
2865
|
+
},
|
|
2866
|
+
populate: { [SITE_ATTRIBUTE$1]: { select: ["id"] } }
|
|
2867
|
+
});
|
|
2868
|
+
for (const row of rows.filter((candidate) => !candidate.site)) {
|
|
2869
|
+
const other = rows.find((candidate) => candidate.locale === row.locale && candidate.site);
|
|
2870
|
+
if (other?.site) {
|
|
2871
|
+
await query.update({ where: { id: row.id }, data: { [SITE_ATTRIBUTE$1]: other.site.id } });
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2221
2875
|
function currentSite(strapi) {
|
|
2222
2876
|
const state = strapi.requestContext.get()?.state;
|
|
2223
2877
|
return state?.micelio?.site;
|
|
2224
2878
|
}
|
|
2225
2879
|
function siteFilter(site2) {
|
|
2226
|
-
return { [SITE_ATTRIBUTE]: { documentId: { $eq: site2.documentId } } };
|
|
2880
|
+
return { [SITE_ATTRIBUTE$1]: { documentId: { $eq: site2.documentId } } };
|
|
2881
|
+
}
|
|
2882
|
+
function isUnchanged(value) {
|
|
2883
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
2884
|
+
const { connect, disconnect, ...rest } = value;
|
|
2885
|
+
const isEmpty = (list2) => list2 === void 0 || Array.isArray(list2) && list2.length === 0;
|
|
2886
|
+
return Object.keys(rest).length === 0 && isEmpty(connect) && isEmpty(disconnect);
|
|
2227
2887
|
}
|
|
2228
2888
|
function isMissing(value) {
|
|
2229
2889
|
if (value === void 0 || value === null || value === "") return true;
|
|
2230
2890
|
if (Array.isArray(value)) return value.length === 0;
|
|
2231
2891
|
if (typeof value === "object") {
|
|
2232
|
-
const { connect, set } = value;
|
|
2892
|
+
const { connect, set, documentId, id: id2 } = value;
|
|
2893
|
+
if (documentId !== void 0 || id2 !== void 0) return !(documentId || id2);
|
|
2233
2894
|
const list2 = set ?? connect;
|
|
2234
2895
|
return Array.isArray(list2) ? list2.length === 0 : list2 === void 0;
|
|
2235
2896
|
}
|
|
@@ -2250,7 +2911,7 @@ function normalizeHosts(value) {
|
|
|
2250
2911
|
}
|
|
2251
2912
|
return hosts;
|
|
2252
2913
|
}
|
|
2253
|
-
const SITE = SITE_UID;
|
|
2914
|
+
const SITE = SITE_UID$1;
|
|
2254
2915
|
function siteRules(strapi) {
|
|
2255
2916
|
return async (context, next) => {
|
|
2256
2917
|
if (context.uid !== SITE) return next();
|
|
@@ -2299,6 +2960,13 @@ async function hostsOfOtherSites(strapi, documentId) {
|
|
|
2299
2960
|
}
|
|
2300
2961
|
const register = ({ strapi }) => {
|
|
2301
2962
|
registerComponents(strapi);
|
|
2963
|
+
registerPreviewShortcut(strapi);
|
|
2964
|
+
strapi.hook("strapi::content-types.beforeSync").register(async () => {
|
|
2965
|
+
const report = await renameLegacyUids(strapi);
|
|
2966
|
+
if (report.actions + report.subjects + report.layouts > 0) {
|
|
2967
|
+
strapi.log.info(`[micelio] moved legacy category and tag UIDs: ${JSON.stringify(report)}`);
|
|
2968
|
+
}
|
|
2969
|
+
});
|
|
2302
2970
|
strapi.documents.use(siteCreatedHook(strapi));
|
|
2303
2971
|
strapi.documents.use(siteRules(strapi));
|
|
2304
2972
|
strapi.documents.use(siteSectionInstances(strapi));
|
|
@@ -2375,14 +3043,32 @@ const contentApiRoutes = () => ({
|
|
|
2375
3043
|
}
|
|
2376
3044
|
]
|
|
2377
3045
|
});
|
|
2378
|
-
const siteRoutes = factories.createCoreRouter(SITE_UID, {
|
|
3046
|
+
const siteRoutes = factories.createCoreRouter(SITE_UID$1, {
|
|
2379
3047
|
prefix: "/micelio",
|
|
2380
3048
|
only: ["find", "findOne"]
|
|
2381
3049
|
});
|
|
3050
|
+
const scoped = () => ({ middlewares: [SITE_SCOPE_MIDDLEWARE] });
|
|
3051
|
+
const config = () => ({
|
|
3052
|
+
find: scoped(),
|
|
3053
|
+
findOne: scoped(),
|
|
3054
|
+
create: scoped(),
|
|
3055
|
+
update: scoped(),
|
|
3056
|
+
delete: scoped()
|
|
3057
|
+
});
|
|
3058
|
+
const categoryRoutes = factories.createCoreRouter(CATEGORY_UID, {
|
|
3059
|
+
prefix: "",
|
|
3060
|
+
config: config()
|
|
3061
|
+
});
|
|
3062
|
+
const tagRoutes = factories.createCoreRouter(TAG_UID, {
|
|
3063
|
+
prefix: "",
|
|
3064
|
+
config: config()
|
|
3065
|
+
});
|
|
2382
3066
|
const routes = {
|
|
2383
3067
|
"content-api": contentApiRoutes,
|
|
2384
3068
|
admin: adminRoutes,
|
|
2385
|
-
site: siteRoutes
|
|
3069
|
+
site: siteRoutes,
|
|
3070
|
+
category: categoryRoutes,
|
|
3071
|
+
tag: tagRoutes
|
|
2386
3072
|
};
|
|
2387
3073
|
const extensions = ({ strapi }) => createExtensionRegistry(strapi);
|
|
2388
3074
|
const hooks = ({ strapi }) => createHookRegistry(strapi.log);
|
|
@@ -2625,7 +3311,7 @@ function asList(value) {
|
|
|
2625
3311
|
function exportedTypes(strapi, personal) {
|
|
2626
3312
|
const types = [];
|
|
2627
3313
|
for (const [uid, schema] of Object.entries(strapi.contentTypes)) {
|
|
2628
|
-
if (uid !== SITE_UID && !isSiteScoped(schema)) continue;
|
|
3314
|
+
if (uid !== SITE_UID$1 && !isSiteScoped(schema)) continue;
|
|
2629
3315
|
if (!isWritten(exportPolicyOf(schema), personal)) continue;
|
|
2630
3316
|
types.push({
|
|
2631
3317
|
uid,
|
|
@@ -2641,20 +3327,20 @@ async function siteRowsOf(strapi, type, site2, context) {
|
|
|
2641
3327
|
const query = strapi.db.query(type.uid);
|
|
2642
3328
|
const owned = await query.findMany({
|
|
2643
3329
|
select: ["documentId"],
|
|
2644
|
-
where: { [SITE_ATTRIBUTE]: { documentId: site2.documentId } }
|
|
3330
|
+
where: { [SITE_ATTRIBUTE$1]: { documentId: site2.documentId } }
|
|
2645
3331
|
});
|
|
2646
3332
|
const documentIds = [...new Set(owned.map((row) => row.documentId))];
|
|
2647
3333
|
if (documentIds.length === 0) return [];
|
|
2648
3334
|
return await query.findMany({
|
|
2649
3335
|
where: { documentId: { $in: documentIds } },
|
|
2650
|
-
populate: populateOf(type.attributes, context, /* @__PURE__ */ new Set([SITE_ATTRIBUTE]))
|
|
3336
|
+
populate: populateOf(type.attributes, context, /* @__PURE__ */ new Set([SITE_ATTRIBUTE$1]))
|
|
2651
3337
|
});
|
|
2652
3338
|
}
|
|
2653
3339
|
function attributesOf(strapi, uid) {
|
|
2654
3340
|
return strapi.contentType(uid).attributes;
|
|
2655
3341
|
}
|
|
2656
3342
|
function documentsOf(type, rows, context) {
|
|
2657
|
-
const skip = new Set(type.uid === SITE_UID ? [] : [SITE_ATTRIBUTE]);
|
|
3343
|
+
const skip = new Set(type.uid === SITE_UID$1 ? [] : [SITE_ATTRIBUTE$1]);
|
|
2658
3344
|
const documents = /* @__PURE__ */ new Map();
|
|
2659
3345
|
for (const row of rows) {
|
|
2660
3346
|
const version2 = {
|
|
@@ -2864,15 +3550,15 @@ async function exportSite(strapi, request, output) {
|
|
|
2864
3550
|
},
|
|
2865
3551
|
personal
|
|
2866
3552
|
};
|
|
2867
|
-
const siteRows = await strapi.db.query(SITE_UID).findMany({
|
|
3553
|
+
const siteRows = await strapi.db.query(SITE_UID$1).findMany({
|
|
2868
3554
|
where: { slug: request.site },
|
|
2869
|
-
populate: populateOf(attributesOf(strapi, SITE_UID), context)
|
|
3555
|
+
populate: populateOf(attributesOf(strapi, SITE_UID$1), context)
|
|
2870
3556
|
});
|
|
2871
3557
|
const site2 = siteRows[0];
|
|
2872
3558
|
if (!site2) throw new ExportError("exportSiteNotFound", `There is no site "${request.site}"`);
|
|
2873
3559
|
const contents = [];
|
|
2874
3560
|
for (const type of types) {
|
|
2875
|
-
const rows = type.uid === SITE_UID ? siteRows : await siteRowsOf(strapi, type, site2, context);
|
|
3561
|
+
const rows = type.uid === SITE_UID$1 ? siteRows : await siteRowsOf(strapi, type, site2, context);
|
|
2876
3562
|
contents.push({ type: type.name, documents: documentsOf(type, rows, context) });
|
|
2877
3563
|
}
|
|
2878
3564
|
const index2 = await mediaIndex(strapi, media2);
|
|
@@ -3408,7 +4094,7 @@ function all(types, strapi) {
|
|
|
3408
4094
|
async function targetSite(strapi, staged, request) {
|
|
3409
4095
|
const archived = staged.contents.get("site").documents[0];
|
|
3410
4096
|
const data = archived.versions[0].data;
|
|
3411
|
-
const rows = await strapi.db.query(SITE_UID).findMany({
|
|
4097
|
+
const rows = await strapi.db.query(SITE_UID$1).findMany({
|
|
3412
4098
|
select: ["documentId", "slug", "hosts", "isDefault"]
|
|
3413
4099
|
});
|
|
3414
4100
|
const sites = [...new Map(rows.map((row) => [row.documentId, row])).values()];
|
|
@@ -3702,7 +4388,7 @@ async function writeContent(strapi, plan2, files, request, report) {
|
|
|
3702
4388
|
const context = deserialiseContext(strapi, plan2, files, written);
|
|
3703
4389
|
const shaOf = new Map([...files.entries()].map(([sha256, id2]) => [id2, sha256]));
|
|
3704
4390
|
const ordered = [...plan2.types].sort(
|
|
3705
|
-
(a, b) => a.uid === SITE_UID ? -1 : b.uid === SITE_UID ? 1 : compare(a.name, b.name)
|
|
4391
|
+
(a, b) => a.uid === SITE_UID$1 ? -1 : b.uid === SITE_UID$1 ? 1 : compare(a.name, b.name)
|
|
3706
4392
|
);
|
|
3707
4393
|
const pending = [];
|
|
3708
4394
|
for (const type of ordered) {
|
|
@@ -3718,7 +4404,7 @@ async function writeContent(strapi, plan2, files, request, report) {
|
|
|
3718
4404
|
}
|
|
3719
4405
|
if (request.mode === "replace") {
|
|
3720
4406
|
for (const type of ordered) {
|
|
3721
|
-
if (type.uid === SITE_UID) continue;
|
|
4407
|
+
if (type.uid === SITE_UID$1) continue;
|
|
3722
4408
|
const kept = new Set(plan2.staged.contents.get(type.name).documents.map((d) => d.documentId));
|
|
3723
4409
|
const rows = await siteRowsOf(strapi, type, plan2.site, serialiseContext(strapi, plan2, shaOf));
|
|
3724
4410
|
for (const documentId of new Set(rows.map((row) => row.documentId))) {
|
|
@@ -3730,9 +4416,9 @@ async function writeContent(strapi, plan2, files, request, report) {
|
|
|
3730
4416
|
}
|
|
3731
4417
|
}
|
|
3732
4418
|
async function writeDocument(strapi, plan2, type, document, context, shaOf) {
|
|
3733
|
-
const isSite = type.uid === SITE_UID;
|
|
4419
|
+
const isSite = type.uid === SITE_UID$1;
|
|
3734
4420
|
const documentId = isSite ? plan2.site.documentId : document.documentId;
|
|
3735
|
-
const skip = new Set(isSite ? [] : [SITE_ATTRIBUTE]);
|
|
4421
|
+
const skip = new Set(isSite ? [] : [SITE_ATTRIBUTE$1]);
|
|
3736
4422
|
const query = strapi.db.query(type.uid);
|
|
3737
4423
|
const rows = await query.findMany({
|
|
3738
4424
|
where: { documentId },
|
|
@@ -3755,7 +4441,7 @@ async function writeDocument(strapi, plan2, type, document, context, shaOf) {
|
|
|
3755
4441
|
pending ||= result.pending > 0;
|
|
3756
4442
|
const data = { ...result.data };
|
|
3757
4443
|
if (!exists) {
|
|
3758
|
-
if (!isSite) data[SITE_ATTRIBUTE] = plan2.site.documentId;
|
|
4444
|
+
if (!isSite) data[SITE_ATTRIBUTE$1] = plan2.site.documentId;
|
|
3759
4445
|
await documents.create({ locale, data: { ...data, documentId } });
|
|
3760
4446
|
exists = true;
|
|
3761
4447
|
} else {
|
|
@@ -3808,7 +4494,7 @@ async function writeDocument(strapi, plan2, type, document, context, shaOf) {
|
|
|
3808
4494
|
}
|
|
3809
4495
|
function desiredData(type, version2, plan2, rows) {
|
|
3810
4496
|
const data = knownData(type.attributes, version2.data);
|
|
3811
|
-
if (type.uid === SITE_UID) {
|
|
4497
|
+
if (type.uid === SITE_UID$1) {
|
|
3812
4498
|
data.isDefault = rows[0]?.isDefault === true;
|
|
3813
4499
|
if (!plan2.site.isNew) data.slug = plan2.site.slug;
|
|
3814
4500
|
}
|
|
@@ -3817,7 +4503,7 @@ function desiredData(type, version2, plan2, rows) {
|
|
|
3817
4503
|
async function checkOwner(strapi, type, documentId, site2) {
|
|
3818
4504
|
const rows = await strapi.db.query(type.uid).findMany({
|
|
3819
4505
|
where: { documentId },
|
|
3820
|
-
populate: { [SITE_ATTRIBUTE]: { select: ["documentId"] } }
|
|
4506
|
+
populate: { [SITE_ATTRIBUTE$1]: { select: ["documentId"] } }
|
|
3821
4507
|
});
|
|
3822
4508
|
if (rows.some((row) => row.site?.documentId && row.site.documentId !== site2)) {
|
|
3823
4509
|
throw new ExportError(
|
|
@@ -3895,7 +4581,9 @@ const transitions = ({ strapi }) => ({
|
|
|
3895
4581
|
}
|
|
3896
4582
|
});
|
|
3897
4583
|
const services = {
|
|
3898
|
-
site: factories.createCoreService(SITE_UID),
|
|
4584
|
+
site: factories.createCoreService(SITE_UID$1),
|
|
4585
|
+
category: factories.createCoreService(CATEGORY_UID),
|
|
4586
|
+
tag: factories.createCoreService(TAG_UID),
|
|
3899
4587
|
transitions,
|
|
3900
4588
|
hostCheck,
|
|
3901
4589
|
hooks,
|
|
@@ -3908,7 +4596,7 @@ const index = {
|
|
|
3908
4596
|
register,
|
|
3909
4597
|
bootstrap,
|
|
3910
4598
|
destroy,
|
|
3911
|
-
config,
|
|
4599
|
+
config: config$1,
|
|
3912
4600
|
controllers,
|
|
3913
4601
|
routes,
|
|
3914
4602
|
services,
|
|
@@ -3917,10 +4605,13 @@ const index = {
|
|
|
3917
4605
|
middlewares
|
|
3918
4606
|
};
|
|
3919
4607
|
export {
|
|
4608
|
+
CATEGORY_UID,
|
|
3920
4609
|
EDITORIAL_STATES,
|
|
3921
|
-
|
|
4610
|
+
READ_ACTIONS$1 as READ_ACTIONS,
|
|
4611
|
+
SITE_ATTRIBUTE$1 as SITE_ATTRIBUTE,
|
|
3922
4612
|
SITE_SCOPE_MIDDLEWARE,
|
|
3923
|
-
SITE_UID,
|
|
4613
|
+
SITE_UID$1 as SITE_UID,
|
|
4614
|
+
TAG_UID,
|
|
3924
4615
|
index as default,
|
|
3925
4616
|
formatHostCheckReport,
|
|
3926
4617
|
missingLocales,
|