@fourlights/strapi-plugin-deep-populate 1.2.4 → 1.3.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 +6 -3
- package/dist/server/index.js +485 -161
- package/dist/server/index.mjs +485 -161
- package/dist/server/src/config/index.d.ts +2 -2
- package/dist/server/src/index.d.ts +2 -2
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const json$1 = require("klona/json");
|
|
3
2
|
const require$$1 = require("crypto");
|
|
4
3
|
const require$$0$1 = require("child_process");
|
|
5
4
|
const require$$0$2 = require("os");
|
|
@@ -12,6 +11,7 @@ const require$$0$6 = require("stream");
|
|
|
12
11
|
const require$$2$1 = require("util");
|
|
13
12
|
const require$$0$8 = require("constants");
|
|
14
13
|
require("node:stream");
|
|
14
|
+
const json$1 = require("klona/json");
|
|
15
15
|
const delve = require("dlv");
|
|
16
16
|
const merge$1 = require("dset/merge");
|
|
17
17
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
@@ -28,13 +28,13 @@ const require$$2__default$1 = /* @__PURE__ */ _interopDefault(require$$2$1);
|
|
|
28
28
|
const require$$0__default$7 = /* @__PURE__ */ _interopDefault(require$$0$8);
|
|
29
29
|
const delve__default = /* @__PURE__ */ _interopDefault(delve);
|
|
30
30
|
const config = {
|
|
31
|
-
default: ({ env: env2 }) => ({
|
|
31
|
+
default: ({ env: env2 }) => ({ useCache: true, replaceWildcard: true }),
|
|
32
32
|
validator: (config2) => {
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
const schema$1 = {
|
|
36
36
|
kind: "collectionType",
|
|
37
|
-
collectionName: "
|
|
37
|
+
collectionName: "populate_cache",
|
|
38
38
|
info: {
|
|
39
39
|
singularName: "cache",
|
|
40
40
|
pluralName: "caches",
|
|
@@ -78,161 +78,6 @@ const schema$1 = {
|
|
|
78
78
|
};
|
|
79
79
|
const cache$1 = { schema: schema$1 };
|
|
80
80
|
const contentTypes$1 = { cache: cache$1 };
|
|
81
|
-
async function hasDeepPopulateCacheFullTextIndex(db, tableName, columnName) {
|
|
82
|
-
const knex = db.connection;
|
|
83
|
-
const client = db.dialect.client;
|
|
84
|
-
if (client === "sqlite") {
|
|
85
|
-
return (await db.dialect.schemaInspector.getTables()).includes(`${tableName}_fts`);
|
|
86
|
-
}
|
|
87
|
-
if (client === "mysql" || client === "mysql2") {
|
|
88
|
-
return (await db.dialect.schemaInspector.getIndexes(tableName)).find(
|
|
89
|
-
({ name }) => name === `${tableName}_${columnName}_fulltext`
|
|
90
|
-
) !== void 0;
|
|
91
|
-
}
|
|
92
|
-
if (client === "pg" || client === "postgres") {
|
|
93
|
-
const result = await knex.raw(
|
|
94
|
-
`SELECT * FROM pg_indexes WHERE tablename = '${tableName}' AND indexname = '${tableName}_${columnName}_gin'`
|
|
95
|
-
);
|
|
96
|
-
return result.rows.length > 0;
|
|
97
|
-
}
|
|
98
|
-
console.log(`Full-text index not supported for this database engine (${client})`);
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
async function addDeepPopulateCacheFullTextIndex(db, tableName, columnName) {
|
|
102
|
-
const knex = db.connection;
|
|
103
|
-
const hasTable = await knex.schema.hasTable(tableName);
|
|
104
|
-
if (!hasTable) return;
|
|
105
|
-
const hasColumn = await knex.schema.hasColumn(tableName, columnName);
|
|
106
|
-
if (!hasColumn) return;
|
|
107
|
-
const client = db.dialect.client;
|
|
108
|
-
if (client === "sqlite") {
|
|
109
|
-
await knex.raw(`CREATE VIRTUAL TABLE ${tableName}_fts USING fts3(${columnName})`);
|
|
110
|
-
await knex.raw(`INSERT INTO ${tableName}_fts (${columnName}) SELECT ${columnName} FROM ${tableName}`);
|
|
111
|
-
} else if (client === "mysql" || client === "mysql2") {
|
|
112
|
-
await knex.raw(`ALTER TABLE ${tableName} ADD FULLTEXT INDEX ${tableName}_${columnName}_fulltext (${columnName})`);
|
|
113
|
-
} else if (client === "pg" || client === "postgres") {
|
|
114
|
-
await knex.raw(
|
|
115
|
-
`CREATE INDEX ${tableName}_${columnName}_gin ON ${tableName} USING GIN (to_tsvector('english', ${columnName}))`
|
|
116
|
-
);
|
|
117
|
-
} else {
|
|
118
|
-
console.log(`Full-text index not supported for this database engine (${client})`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
async function removeDeepPopulateCacheFullTextIndex(db, tableName, columnName) {
|
|
122
|
-
const knex = db.connection;
|
|
123
|
-
const hasTable = await knex.schema.hasTable(tableName);
|
|
124
|
-
if (!hasTable) return;
|
|
125
|
-
const hasColumn = await knex.schema.hasColumn(tableName, columnName);
|
|
126
|
-
if (!hasColumn) return;
|
|
127
|
-
const client = db.dialect.client;
|
|
128
|
-
if (client === "sqlite") {
|
|
129
|
-
await knex.raw(`DROP TABLE ${tableName}_fts`);
|
|
130
|
-
} else if (client === "mysql" || client === "mysql2") {
|
|
131
|
-
await knex.raw(`ALTER TABLE ${tableName} DROP INDEX ${tableName}_${columnName}_fulltext`);
|
|
132
|
-
} else if (client === "pg" || client === "postgres") {
|
|
133
|
-
await knex.raw(`DROP INDEX ${tableName}_${columnName}_gin`);
|
|
134
|
-
} else {
|
|
135
|
-
console.log(`Full-text index not supported for this database engine (${client})`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
const register = async ({ strapi: strapi2 }) => {
|
|
139
|
-
strapi2.hook("strapi::content-types.afterSync").register(async () => {
|
|
140
|
-
const tableName = "caches";
|
|
141
|
-
const columnName = "dependencies";
|
|
142
|
-
const hasIndex = await hasDeepPopulateCacheFullTextIndex(strapi2.db, tableName, columnName);
|
|
143
|
-
const hasTable = await strapi2.db.connection.schema.hasTable(tableName);
|
|
144
|
-
const hasColumn = hasTable && await strapi2.db.connection.schema.hasColumn(tableName, columnName);
|
|
145
|
-
const cacheIsEnabled = strapi2.config.get("plugin::deep-populate").cachePopulate === true;
|
|
146
|
-
const shouldCreateIndex = cacheIsEnabled && hasTable && hasColumn && !hasIndex;
|
|
147
|
-
const shouldRemoveIndex = hasIndex && (!cacheIsEnabled || !hasTable || !hasColumn);
|
|
148
|
-
if (shouldCreateIndex) await addDeepPopulateCacheFullTextIndex(strapi2.db, tableName, columnName);
|
|
149
|
-
if (shouldRemoveIndex) await removeDeepPopulateCacheFullTextIndex(strapi2.db, tableName, columnName);
|
|
150
|
-
});
|
|
151
|
-
strapi2.documents.use(async (context, next) => {
|
|
152
|
-
const { cachePopulate, augmentPopulateStar } = strapi2.config.get("plugin::deep-populate");
|
|
153
|
-
if (
|
|
154
|
-
// do nothing if not configured
|
|
155
|
-
!cachePopulate && !augmentPopulateStar || context.uid === "plugin::deep-populate.cache"
|
|
156
|
-
)
|
|
157
|
-
return await next();
|
|
158
|
-
const populateService = strapi2.plugin("deep-populate").service("populate");
|
|
159
|
-
const cacheService = strapi2.plugin("deep-populate").service("cache");
|
|
160
|
-
const { populate: populate2 } = context.params;
|
|
161
|
-
const returnDeeplyPopulated = augmentPopulateStar && populate2 === "*";
|
|
162
|
-
if (cachePopulate && context.action === "delete")
|
|
163
|
-
await cacheService.clear({ ...context.params, contentType: context.uid });
|
|
164
|
-
const originalFields = json$1.klona(context.fields);
|
|
165
|
-
if (returnDeeplyPopulated && ["findOne", "findFirst", "findMany"].includes(context.action))
|
|
166
|
-
context.fields = ["documentId", "status", "locale"];
|
|
167
|
-
const result = await next();
|
|
168
|
-
if (["create", "update"].includes(context.action)) {
|
|
169
|
-
const { documentId, status: status2, locale: locale2 } = result;
|
|
170
|
-
if (cachePopulate && context.action === "update")
|
|
171
|
-
await cacheService.clear({ ...context.params, contentType: context.uid });
|
|
172
|
-
if (cachePopulate || returnDeeplyPopulated) {
|
|
173
|
-
const deepPopulate = await populateService.get({ contentType: context.uid, documentId, status: status2, locale: locale2 });
|
|
174
|
-
if (returnDeeplyPopulated)
|
|
175
|
-
return await strapi2.documents(context.uid).findOne({ documentId, status: status2, locale: locale2, fields: originalFields, populate: deepPopulate });
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (returnDeeplyPopulated && ["findOne", "findFirst"].includes(context.action)) {
|
|
179
|
-
const { documentId, status: status2, locale: locale2 } = result;
|
|
180
|
-
const deepPopulate = await populateService.get({ contentType: context.uid, documentId, status: status2, locale: locale2 });
|
|
181
|
-
return await strapi2.documents(context.uid).findOne({ documentId, status: status2, locale: locale2, fields: originalFields, populate: deepPopulate });
|
|
182
|
-
}
|
|
183
|
-
if (returnDeeplyPopulated && context.action === "findMany") {
|
|
184
|
-
return await Promise.all(
|
|
185
|
-
result.map(async ({ documentId, status: status2, locale: locale2 }) => {
|
|
186
|
-
const deepPopulate = await populateService.get({ contentType: context.uid, documentId, status: status2, locale: locale2 });
|
|
187
|
-
return await strapi2.documents(context.uid).findOne({ documentId, status: status2, locale: locale2, fields: originalFields, populate: deepPopulate });
|
|
188
|
-
})
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
return result;
|
|
192
|
-
});
|
|
193
|
-
};
|
|
194
|
-
const getHash = (params) => {
|
|
195
|
-
return `${params.contentType}-${params.documentId}-${params.locale}-${params.status}-${params.omitEmpty ? "sparse" : "full"}`;
|
|
196
|
-
};
|
|
197
|
-
const cache = ({ strapi: strapi2 }) => ({
|
|
198
|
-
async get(params) {
|
|
199
|
-
const entry = await strapi2.documents("plugin::deep-populate.cache").findFirst({ filters: { hash: { $eq: getHash(params) } } });
|
|
200
|
-
return entry ? entry.populate : null;
|
|
201
|
-
},
|
|
202
|
-
async set({ populate: populate2, dependencies, ...params }) {
|
|
203
|
-
const documentService = strapi2.documents("plugin::deep-populate.cache");
|
|
204
|
-
const hash = getHash(params);
|
|
205
|
-
const entry = await documentService.findFirst({ filters: { hash: { $eq: hash } } });
|
|
206
|
-
return entry ? await documentService.update({
|
|
207
|
-
documentId: entry.documentId,
|
|
208
|
-
data: { populate: populate2, dependencies: dependencies.join(",") }
|
|
209
|
-
}) : await documentService.create({ data: { hash, params, populate: populate2, dependencies: dependencies.join(",") } });
|
|
210
|
-
},
|
|
211
|
-
async clear(params) {
|
|
212
|
-
const entry = await strapi2.documents("plugin::deep-populate.cache").findFirst({ filters: { hash: { $eq: getHash(params) } } });
|
|
213
|
-
let retval = null;
|
|
214
|
-
if (entry) {
|
|
215
|
-
retval = await strapi2.documents("plugin::deep-populate.cache").delete({ documentId: entry.documentId });
|
|
216
|
-
}
|
|
217
|
-
await this.refreshDependents(params.documentId);
|
|
218
|
-
return retval;
|
|
219
|
-
},
|
|
220
|
-
async refreshDependents(documentId) {
|
|
221
|
-
const entries = await strapi2.documents("plugin::deep-populate.cache").findMany({ filters: { dependencies: { $contains: documentId } }, fields: ["documentId", "params"] });
|
|
222
|
-
const deleted = await strapi2.db.query("plugin::deep-populate.cache").deleteMany({
|
|
223
|
-
where: {
|
|
224
|
-
documentId: { $in: entries.map((x) => x.documentId) }
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
if (deleted.count !== entries.length)
|
|
228
|
-
console.error(`Deleted count ${deleted.count} does not match entries count ${entries.length}`);
|
|
229
|
-
const batchSize = 5;
|
|
230
|
-
for (let i = 0; i < entries.length; i += batchSize) {
|
|
231
|
-
const batch = entries.slice(i, i + batchSize);
|
|
232
|
-
await Promise.all(batch.map((entry) => strapi2.service("plugin::deep-populate.populate").get(entry.params)));
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
81
|
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
237
82
|
function getDefaultExportFromCjs(x) {
|
|
238
83
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
@@ -24350,7 +24195,7 @@ const createVisitorUtils = ({ data }) => ({
|
|
|
24350
24195
|
data[key] = value;
|
|
24351
24196
|
}
|
|
24352
24197
|
});
|
|
24353
|
-
fp.curry(traverseEntity);
|
|
24198
|
+
const traverseEntity$1 = fp.curry(traverseEntity);
|
|
24354
24199
|
const GROUP_OPERATORS = ["$and", "$or"];
|
|
24355
24200
|
const WHERE_OPERATORS = [
|
|
24356
24201
|
"$not",
|
|
@@ -24443,6 +24288,100 @@ const visitor$7 = ({ schema: schema2, key, attribute }, { remove: remove2 }) =>
|
|
|
24443
24288
|
remove2(key);
|
|
24444
24289
|
}
|
|
24445
24290
|
};
|
|
24291
|
+
const VALID_RELATION_ORDERING_KEYS = {
|
|
24292
|
+
strict: fp.isBoolean
|
|
24293
|
+
};
|
|
24294
|
+
const ACTIONS_TO_VERIFY$1 = ["find"];
|
|
24295
|
+
const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
|
|
24296
|
+
const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema: schema2 }, { remove: remove2, set: set2 }) => {
|
|
24297
|
+
if (!attribute) {
|
|
24298
|
+
return;
|
|
24299
|
+
}
|
|
24300
|
+
const isRelation = attribute.type === "relation";
|
|
24301
|
+
if (!isRelation) {
|
|
24302
|
+
return;
|
|
24303
|
+
}
|
|
24304
|
+
const handleMorphRelation = async () => {
|
|
24305
|
+
const elements = data[key];
|
|
24306
|
+
if ("connect" in elements || "set" in elements || "disconnect" in elements) {
|
|
24307
|
+
const newValue = {};
|
|
24308
|
+
const connect = await handleMorphElements(elements.connect || []);
|
|
24309
|
+
const relSet = await handleMorphElements(elements.set || []);
|
|
24310
|
+
const disconnect = await handleMorphElements(elements.disconnect || []);
|
|
24311
|
+
if (connect.length > 0) {
|
|
24312
|
+
newValue.connect = connect;
|
|
24313
|
+
}
|
|
24314
|
+
if (relSet.length > 0) {
|
|
24315
|
+
newValue.set = relSet;
|
|
24316
|
+
}
|
|
24317
|
+
if (disconnect.length > 0) {
|
|
24318
|
+
newValue.disconnect = disconnect;
|
|
24319
|
+
}
|
|
24320
|
+
if ("options" in elements && typeof elements.options === "object" && elements.options !== null) {
|
|
24321
|
+
const filteredOptions = {};
|
|
24322
|
+
Object.keys(elements.options).forEach((key2) => {
|
|
24323
|
+
const validator = VALID_RELATION_ORDERING_KEYS[key2];
|
|
24324
|
+
if (validator && validator(elements.options[key2])) {
|
|
24325
|
+
filteredOptions[key2] = elements.options[key2];
|
|
24326
|
+
}
|
|
24327
|
+
});
|
|
24328
|
+
newValue.options = filteredOptions;
|
|
24329
|
+
} else {
|
|
24330
|
+
newValue.options = {};
|
|
24331
|
+
}
|
|
24332
|
+
set2(key, newValue);
|
|
24333
|
+
} else {
|
|
24334
|
+
const newMorphValue = await handleMorphElements(elements);
|
|
24335
|
+
if (newMorphValue.length) {
|
|
24336
|
+
set2(key, newMorphValue);
|
|
24337
|
+
}
|
|
24338
|
+
}
|
|
24339
|
+
};
|
|
24340
|
+
const handleMorphElements = async (elements) => {
|
|
24341
|
+
const allowedElements = [];
|
|
24342
|
+
if (!fp.isArray(elements)) {
|
|
24343
|
+
return allowedElements;
|
|
24344
|
+
}
|
|
24345
|
+
for (const element of elements) {
|
|
24346
|
+
if (!fp.isObject(element) || !("__type" in element)) {
|
|
24347
|
+
continue;
|
|
24348
|
+
}
|
|
24349
|
+
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
|
|
24350
|
+
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
24351
|
+
if (isAllowed) {
|
|
24352
|
+
allowedElements.push(element);
|
|
24353
|
+
}
|
|
24354
|
+
}
|
|
24355
|
+
return allowedElements;
|
|
24356
|
+
};
|
|
24357
|
+
const handleRegularRelation = async () => {
|
|
24358
|
+
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${attribute.target}.${action}`);
|
|
24359
|
+
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
24360
|
+
if (!isAllowed) {
|
|
24361
|
+
remove2(key);
|
|
24362
|
+
}
|
|
24363
|
+
};
|
|
24364
|
+
const isCreatorRelation = [CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE$1].includes(key);
|
|
24365
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
24366
|
+
await handleMorphRelation();
|
|
24367
|
+
return;
|
|
24368
|
+
}
|
|
24369
|
+
if (isCreatorRelation && schema2.options?.populateCreatorFields) {
|
|
24370
|
+
return;
|
|
24371
|
+
}
|
|
24372
|
+
await handleRegularRelation();
|
|
24373
|
+
};
|
|
24374
|
+
const hasAccessToSomeScopes$1 = async (scopes, auth) => {
|
|
24375
|
+
for (const scope of scopes) {
|
|
24376
|
+
try {
|
|
24377
|
+
await strapi.auth.verify(auth, { scope });
|
|
24378
|
+
return true;
|
|
24379
|
+
} catch {
|
|
24380
|
+
continue;
|
|
24381
|
+
}
|
|
24382
|
+
}
|
|
24383
|
+
return false;
|
|
24384
|
+
};
|
|
24446
24385
|
const visitor$6 = ({ key, attribute }, { remove: remove2 }) => {
|
|
24447
24386
|
if (isMorphToRelationalAttribute(attribute)) {
|
|
24448
24387
|
remove2(key);
|
|
@@ -24453,6 +24392,54 @@ const visitor$5 = ({ key, attribute }, { remove: remove2 }) => {
|
|
|
24453
24392
|
remove2(key);
|
|
24454
24393
|
}
|
|
24455
24394
|
};
|
|
24395
|
+
const removeDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path2 } }, { remove: remove2 }) => {
|
|
24396
|
+
if (allowedFields === null) {
|
|
24397
|
+
return;
|
|
24398
|
+
}
|
|
24399
|
+
if (!(fp.isArray(allowedFields) && allowedFields.every(fp.isString))) {
|
|
24400
|
+
throw new TypeError(
|
|
24401
|
+
`Expected array of strings for allowedFields but got "${typeof allowedFields}"`
|
|
24402
|
+
);
|
|
24403
|
+
}
|
|
24404
|
+
if (fp.isNil(path2)) {
|
|
24405
|
+
return;
|
|
24406
|
+
}
|
|
24407
|
+
const containedPaths = getContainedPaths$1(path2);
|
|
24408
|
+
const isPathAllowed = allowedFields.some(
|
|
24409
|
+
(p) => containedPaths.includes(p) || p.startsWith(`${path2}.`)
|
|
24410
|
+
);
|
|
24411
|
+
if (isPathAllowed) {
|
|
24412
|
+
return;
|
|
24413
|
+
}
|
|
24414
|
+
remove2(key);
|
|
24415
|
+
};
|
|
24416
|
+
const getContainedPaths$1 = (path2) => {
|
|
24417
|
+
const parts = fp.toPath(path2);
|
|
24418
|
+
return parts.reduce((acc, value, index2, list) => {
|
|
24419
|
+
return [...acc, list.slice(0, index2 + 1).join(".")];
|
|
24420
|
+
}, []);
|
|
24421
|
+
};
|
|
24422
|
+
const removeRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path2 } }, { remove: remove2 }) => {
|
|
24423
|
+
if (restrictedFields === null) {
|
|
24424
|
+
remove2(key);
|
|
24425
|
+
return;
|
|
24426
|
+
}
|
|
24427
|
+
if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
|
|
24428
|
+
throw new TypeError(
|
|
24429
|
+
`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`
|
|
24430
|
+
);
|
|
24431
|
+
}
|
|
24432
|
+
if (restrictedFields.includes(path2)) {
|
|
24433
|
+
remove2(key);
|
|
24434
|
+
return;
|
|
24435
|
+
}
|
|
24436
|
+
const isRestrictedNested = restrictedFields.some(
|
|
24437
|
+
(allowedPath) => path2?.toString().startsWith(`${allowedPath}.`)
|
|
24438
|
+
);
|
|
24439
|
+
if (isRestrictedNested) {
|
|
24440
|
+
remove2(key);
|
|
24441
|
+
}
|
|
24442
|
+
};
|
|
24456
24443
|
const visitor$4 = ({ schema: schema2, key, value }, { set: set2 }) => {
|
|
24457
24444
|
if (key === "" && value === "*") {
|
|
24458
24445
|
const { attributes } = schema2;
|
|
@@ -24462,6 +24449,17 @@ const visitor$4 = ({ schema: schema2, key, value }, { set: set2 }) => {
|
|
|
24462
24449
|
set2("", newPopulateQuery);
|
|
24463
24450
|
}
|
|
24464
24451
|
};
|
|
24452
|
+
const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
24453
|
+
__proto__: null,
|
|
24454
|
+
expandWildcardPopulate: visitor$4,
|
|
24455
|
+
removeDisallowedFields,
|
|
24456
|
+
removeDynamicZones: visitor$5,
|
|
24457
|
+
removeMorphToRelations: visitor$6,
|
|
24458
|
+
removePassword: visitor$8,
|
|
24459
|
+
removePrivate: visitor$7,
|
|
24460
|
+
removeRestrictedFields,
|
|
24461
|
+
removeRestrictedRelations
|
|
24462
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
24465
24463
|
const DEFAULT_PATH = { raw: null, attribute: null };
|
|
24466
24464
|
const traverseFactory = () => {
|
|
24467
24465
|
const state = {
|
|
@@ -25017,6 +25015,25 @@ const fields = traverseFactory().intercept(isStringArray, async (visitor2, optio
|
|
|
25017
25015
|
}));
|
|
25018
25016
|
const traverseQueryFields = fp.curry(fields.traverse);
|
|
25019
25017
|
const { ID_ATTRIBUTE: ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$2 } = constants$1;
|
|
25018
|
+
const sanitizePasswords = (ctx) => async (entity) => {
|
|
25019
|
+
if (!ctx.schema) {
|
|
25020
|
+
throw new Error("Missing schema in sanitizePasswords");
|
|
25021
|
+
}
|
|
25022
|
+
return traverseEntity$1(visitor$8, ctx, entity);
|
|
25023
|
+
};
|
|
25024
|
+
const defaultSanitizeOutput = async (ctx, entity) => {
|
|
25025
|
+
if (!ctx.schema) {
|
|
25026
|
+
throw new Error("Missing schema in defaultSanitizeOutput");
|
|
25027
|
+
}
|
|
25028
|
+
return traverseEntity$1(
|
|
25029
|
+
(...args) => {
|
|
25030
|
+
visitor$8(...args);
|
|
25031
|
+
visitor$7(...args);
|
|
25032
|
+
},
|
|
25033
|
+
ctx,
|
|
25034
|
+
entity
|
|
25035
|
+
);
|
|
25036
|
+
};
|
|
25020
25037
|
const defaultSanitizeFilters = fp.curry((ctx, filters2) => {
|
|
25021
25038
|
if (!ctx.schema) {
|
|
25022
25039
|
throw new Error("Missing schema in defaultSanitizeFilters");
|
|
@@ -25131,6 +25148,144 @@ const defaultSanitizePopulate = fp.curry((ctx, populate2) => {
|
|
|
25131
25148
|
traverseQueryPopulate(visitor$7, ctx)
|
|
25132
25149
|
)(populate2);
|
|
25133
25150
|
});
|
|
25151
|
+
const sanitizers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
25152
|
+
__proto__: null,
|
|
25153
|
+
defaultSanitizeFields,
|
|
25154
|
+
defaultSanitizeFilters,
|
|
25155
|
+
defaultSanitizeOutput,
|
|
25156
|
+
defaultSanitizePopulate,
|
|
25157
|
+
defaultSanitizeSort,
|
|
25158
|
+
sanitizePasswords
|
|
25159
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
25160
|
+
const createAPISanitizers = (opts) => {
|
|
25161
|
+
const { getModel } = opts;
|
|
25162
|
+
const sanitizeInput = (data, schema2, { auth } = {}) => {
|
|
25163
|
+
if (!schema2) {
|
|
25164
|
+
throw new Error("Missing schema in sanitizeInput");
|
|
25165
|
+
}
|
|
25166
|
+
if (fp.isArray(data)) {
|
|
25167
|
+
return Promise.all(data.map((entry) => sanitizeInput(entry, schema2, { auth })));
|
|
25168
|
+
}
|
|
25169
|
+
const nonWritableAttributes = getNonWritableAttributes(schema2);
|
|
25170
|
+
const transforms = [
|
|
25171
|
+
// Remove first level ID in inputs
|
|
25172
|
+
fp.omit(constants$1.ID_ATTRIBUTE),
|
|
25173
|
+
fp.omit(constants$1.DOC_ID_ATTRIBUTE),
|
|
25174
|
+
// Remove non-writable attributes
|
|
25175
|
+
traverseEntity$1(removeRestrictedFields(nonWritableAttributes), { schema: schema2, getModel })
|
|
25176
|
+
];
|
|
25177
|
+
if (auth) {
|
|
25178
|
+
transforms.push(
|
|
25179
|
+
traverseEntity$1(removeRestrictedRelations(auth), { schema: schema2, getModel })
|
|
25180
|
+
);
|
|
25181
|
+
}
|
|
25182
|
+
opts?.sanitizers?.input?.forEach((sanitizer) => transforms.push(sanitizer(schema2)));
|
|
25183
|
+
return pipe(...transforms)(data);
|
|
25184
|
+
};
|
|
25185
|
+
const sanitizeOutput = async (data, schema2, { auth } = {}) => {
|
|
25186
|
+
if (!schema2) {
|
|
25187
|
+
throw new Error("Missing schema in sanitizeOutput");
|
|
25188
|
+
}
|
|
25189
|
+
if (fp.isArray(data)) {
|
|
25190
|
+
const res = new Array(data.length);
|
|
25191
|
+
for (let i = 0; i < data.length; i += 1) {
|
|
25192
|
+
res[i] = await sanitizeOutput(data[i], schema2, { auth });
|
|
25193
|
+
}
|
|
25194
|
+
return res;
|
|
25195
|
+
}
|
|
25196
|
+
const transforms = [
|
|
25197
|
+
(data2) => defaultSanitizeOutput({ schema: schema2, getModel }, data2)
|
|
25198
|
+
];
|
|
25199
|
+
if (auth) {
|
|
25200
|
+
transforms.push(
|
|
25201
|
+
traverseEntity$1(removeRestrictedRelations(auth), { schema: schema2, getModel })
|
|
25202
|
+
);
|
|
25203
|
+
}
|
|
25204
|
+
opts?.sanitizers?.output?.forEach((sanitizer) => transforms.push(sanitizer(schema2)));
|
|
25205
|
+
return pipe(...transforms)(data);
|
|
25206
|
+
};
|
|
25207
|
+
const sanitizeQuery = async (query, schema2, { auth } = {}) => {
|
|
25208
|
+
if (!schema2) {
|
|
25209
|
+
throw new Error("Missing schema in sanitizeQuery");
|
|
25210
|
+
}
|
|
25211
|
+
const { filters: filters2, sort: sort2, fields: fields2, populate: populate2 } = query;
|
|
25212
|
+
const sanitizedQuery = fp.cloneDeep(query);
|
|
25213
|
+
if (filters2) {
|
|
25214
|
+
Object.assign(sanitizedQuery, { filters: await sanitizeFilters(filters2, schema2, { auth }) });
|
|
25215
|
+
}
|
|
25216
|
+
if (sort2) {
|
|
25217
|
+
Object.assign(sanitizedQuery, { sort: await sanitizeSort(sort2, schema2, { auth }) });
|
|
25218
|
+
}
|
|
25219
|
+
if (fields2) {
|
|
25220
|
+
Object.assign(sanitizedQuery, { fields: await sanitizeFields(fields2, schema2) });
|
|
25221
|
+
}
|
|
25222
|
+
if (populate2) {
|
|
25223
|
+
Object.assign(sanitizedQuery, { populate: await sanitizePopulate(populate2, schema2) });
|
|
25224
|
+
}
|
|
25225
|
+
return sanitizedQuery;
|
|
25226
|
+
};
|
|
25227
|
+
const sanitizeFilters = (filters2, schema2, { auth } = {}) => {
|
|
25228
|
+
if (!schema2) {
|
|
25229
|
+
throw new Error("Missing schema in sanitizeFilters");
|
|
25230
|
+
}
|
|
25231
|
+
if (fp.isArray(filters2)) {
|
|
25232
|
+
return Promise.all(filters2.map((filter) => sanitizeFilters(filter, schema2, { auth })));
|
|
25233
|
+
}
|
|
25234
|
+
const transforms = [defaultSanitizeFilters({ schema: schema2, getModel })];
|
|
25235
|
+
if (auth) {
|
|
25236
|
+
transforms.push(
|
|
25237
|
+
traverseQueryFilters(removeRestrictedRelations(auth), { schema: schema2, getModel })
|
|
25238
|
+
);
|
|
25239
|
+
}
|
|
25240
|
+
return pipe(...transforms)(filters2);
|
|
25241
|
+
};
|
|
25242
|
+
const sanitizeSort = (sort2, schema2, { auth } = {}) => {
|
|
25243
|
+
if (!schema2) {
|
|
25244
|
+
throw new Error("Missing schema in sanitizeSort");
|
|
25245
|
+
}
|
|
25246
|
+
const transforms = [defaultSanitizeSort({ schema: schema2, getModel })];
|
|
25247
|
+
if (auth) {
|
|
25248
|
+
transforms.push(
|
|
25249
|
+
traverseQuerySort(removeRestrictedRelations(auth), { schema: schema2, getModel })
|
|
25250
|
+
);
|
|
25251
|
+
}
|
|
25252
|
+
return pipe(...transforms)(sort2);
|
|
25253
|
+
};
|
|
25254
|
+
const sanitizeFields = (fields2, schema2) => {
|
|
25255
|
+
if (!schema2) {
|
|
25256
|
+
throw new Error("Missing schema in sanitizeFields");
|
|
25257
|
+
}
|
|
25258
|
+
const transforms = [defaultSanitizeFields({ schema: schema2, getModel })];
|
|
25259
|
+
return pipe(...transforms)(fields2);
|
|
25260
|
+
};
|
|
25261
|
+
const sanitizePopulate = (populate2, schema2, { auth } = {}) => {
|
|
25262
|
+
if (!schema2) {
|
|
25263
|
+
throw new Error("Missing schema in sanitizePopulate");
|
|
25264
|
+
}
|
|
25265
|
+
const transforms = [defaultSanitizePopulate({ schema: schema2, getModel })];
|
|
25266
|
+
if (auth) {
|
|
25267
|
+
transforms.push(
|
|
25268
|
+
traverseQueryPopulate(removeRestrictedRelations(auth), { schema: schema2, getModel })
|
|
25269
|
+
);
|
|
25270
|
+
}
|
|
25271
|
+
return pipe(...transforms)(populate2);
|
|
25272
|
+
};
|
|
25273
|
+
return {
|
|
25274
|
+
input: sanitizeInput,
|
|
25275
|
+
output: sanitizeOutput,
|
|
25276
|
+
query: sanitizeQuery,
|
|
25277
|
+
filters: sanitizeFilters,
|
|
25278
|
+
sort: sanitizeSort,
|
|
25279
|
+
fields: sanitizeFields,
|
|
25280
|
+
populate: sanitizePopulate
|
|
25281
|
+
};
|
|
25282
|
+
};
|
|
25283
|
+
const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
25284
|
+
__proto__: null,
|
|
25285
|
+
createAPISanitizers,
|
|
25286
|
+
sanitizers,
|
|
25287
|
+
visitors: index$4
|
|
25288
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
25134
25289
|
[constants$1.DOC_ID_ATTRIBUTE, constants$1.DOC_ID_ATTRIBUTE];
|
|
25135
25290
|
const isCamelCase = (value) => /^[a-z][a-zA-Z0-9]+$/.test(value);
|
|
25136
25291
|
const isKebabCase = (value) => /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(value);
|
|
@@ -25256,6 +25411,175 @@ setLocale({
|
|
|
25256
25411
|
}
|
|
25257
25412
|
}
|
|
25258
25413
|
});
|
|
25414
|
+
async function hasDeepPopulateCacheFullTextIndex(db, tableName, columnName) {
|
|
25415
|
+
const knex = db.connection;
|
|
25416
|
+
const client = db.dialect.client;
|
|
25417
|
+
if (client === "sqlite") {
|
|
25418
|
+
return (await db.dialect.schemaInspector.getTables()).includes(`${tableName}_fts`);
|
|
25419
|
+
}
|
|
25420
|
+
if (client === "mysql" || client === "mysql2") {
|
|
25421
|
+
return (await db.dialect.schemaInspector.getIndexes(tableName)).find(
|
|
25422
|
+
({ name }) => name === `${tableName}_${columnName}_fulltext`
|
|
25423
|
+
) !== void 0;
|
|
25424
|
+
}
|
|
25425
|
+
if (client === "pg" || client === "postgres") {
|
|
25426
|
+
const result = await knex.raw(
|
|
25427
|
+
`SELECT * FROM pg_indexes WHERE tablename = '${tableName}' AND indexname = '${tableName}_${columnName}_gin'`
|
|
25428
|
+
);
|
|
25429
|
+
return result.rows.length > 0;
|
|
25430
|
+
}
|
|
25431
|
+
console.log(`Full-text index not supported for this database engine (${client})`);
|
|
25432
|
+
return false;
|
|
25433
|
+
}
|
|
25434
|
+
async function addDeepPopulateCacheFullTextIndex(db, tableName, columnName) {
|
|
25435
|
+
const knex = db.connection;
|
|
25436
|
+
const hasTable = await knex.schema.hasTable(tableName);
|
|
25437
|
+
if (!hasTable) return;
|
|
25438
|
+
const hasColumn = await knex.schema.hasColumn(tableName, columnName);
|
|
25439
|
+
if (!hasColumn) return;
|
|
25440
|
+
const client = db.dialect.client;
|
|
25441
|
+
if (client === "sqlite") {
|
|
25442
|
+
await knex.raw(`CREATE VIRTUAL TABLE ${tableName}_fts USING fts3(${columnName})`);
|
|
25443
|
+
await knex.raw(`INSERT INTO ${tableName}_fts (${columnName}) SELECT ${columnName} FROM ${tableName}`);
|
|
25444
|
+
} else if (client === "mysql" || client === "mysql2") {
|
|
25445
|
+
await knex.raw(`ALTER TABLE ${tableName} ADD FULLTEXT INDEX ${tableName}_${columnName}_fulltext (${columnName})`);
|
|
25446
|
+
} else if (client === "pg" || client === "postgres") {
|
|
25447
|
+
await knex.raw(
|
|
25448
|
+
`CREATE INDEX ${tableName}_${columnName}_gin ON ${tableName} USING GIN (to_tsvector('english', ${columnName}))`
|
|
25449
|
+
);
|
|
25450
|
+
} else {
|
|
25451
|
+
console.log(`Full-text index not supported for this database engine (${client})`);
|
|
25452
|
+
}
|
|
25453
|
+
}
|
|
25454
|
+
async function removeDeepPopulateCacheFullTextIndex(db, tableName, columnName) {
|
|
25455
|
+
const knex = db.connection;
|
|
25456
|
+
const hasTable = await knex.schema.hasTable(tableName);
|
|
25457
|
+
if (!hasTable) return;
|
|
25458
|
+
const hasColumn = await knex.schema.hasColumn(tableName, columnName);
|
|
25459
|
+
if (!hasColumn) return;
|
|
25460
|
+
const client = db.dialect.client;
|
|
25461
|
+
if (client === "sqlite") {
|
|
25462
|
+
await knex.raw(`DROP TABLE ${tableName}_fts`);
|
|
25463
|
+
} else if (client === "mysql" || client === "mysql2") {
|
|
25464
|
+
await knex.raw(`ALTER TABLE ${tableName} DROP INDEX ${tableName}_${columnName}_fulltext`);
|
|
25465
|
+
} else if (client === "pg" || client === "postgres") {
|
|
25466
|
+
await knex.raw(`DROP INDEX ${tableName}_${columnName}_gin`);
|
|
25467
|
+
} else {
|
|
25468
|
+
console.log(`Full-text index not supported for this database engine (${client})`);
|
|
25469
|
+
}
|
|
25470
|
+
}
|
|
25471
|
+
const populateIsWildcardEquivalent = async ({
|
|
25472
|
+
strapi: strapi2,
|
|
25473
|
+
schema: schema2,
|
|
25474
|
+
populate: populate2
|
|
25475
|
+
}) => {
|
|
25476
|
+
const expandedWildcardQuery = await index$2.sanitizers.defaultSanitizePopulate(
|
|
25477
|
+
{
|
|
25478
|
+
schema: schema2,
|
|
25479
|
+
getModel: (uid) => strapi2.getModel(uid)
|
|
25480
|
+
},
|
|
25481
|
+
"*"
|
|
25482
|
+
);
|
|
25483
|
+
return populate2 === "*" || populate2 === true || JSON.stringify(expandedWildcardQuery) === JSON.stringify(populate2);
|
|
25484
|
+
};
|
|
25485
|
+
const register = async ({ strapi: strapi2 }) => {
|
|
25486
|
+
strapi2.hook("strapi::content-types.afterSync").register(async () => {
|
|
25487
|
+
const tableName = "populate_cache";
|
|
25488
|
+
const columnName = "dependencies";
|
|
25489
|
+
const hasIndex = await hasDeepPopulateCacheFullTextIndex(strapi2.db, tableName, columnName);
|
|
25490
|
+
const hasTable = await strapi2.db.connection.schema.hasTable(tableName);
|
|
25491
|
+
const hasColumn = hasTable && await strapi2.db.connection.schema.hasColumn(tableName, columnName);
|
|
25492
|
+
const cacheIsEnabled = strapi2.config.get("plugin::deep-populate").useCache === true;
|
|
25493
|
+
const shouldCreateIndex = cacheIsEnabled && hasTable && hasColumn && !hasIndex;
|
|
25494
|
+
const shouldRemoveIndex = hasIndex && (!cacheIsEnabled || !hasTable || !hasColumn);
|
|
25495
|
+
if (shouldCreateIndex) await addDeepPopulateCacheFullTextIndex(strapi2.db, tableName, columnName);
|
|
25496
|
+
if (shouldRemoveIndex) await removeDeepPopulateCacheFullTextIndex(strapi2.db, tableName, columnName);
|
|
25497
|
+
});
|
|
25498
|
+
strapi2.documents.use(async (context, next) => {
|
|
25499
|
+
const { useCache, replaceWildcard } = strapi2.config.get("plugin::deep-populate");
|
|
25500
|
+
if (
|
|
25501
|
+
// do nothing if not configured
|
|
25502
|
+
!useCache && !replaceWildcard || context.uid === "plugin::deep-populate.cache"
|
|
25503
|
+
)
|
|
25504
|
+
return await next();
|
|
25505
|
+
const populateService = strapi2.plugin("deep-populate").service("populate");
|
|
25506
|
+
const cacheService = strapi2.plugin("deep-populate").service("cache");
|
|
25507
|
+
const { populate: populate2 } = context.params;
|
|
25508
|
+
const returnDeeplyPopulated = replaceWildcard && await populateIsWildcardEquivalent({ strapi: strapi2, schema: context.contentType, populate: populate2 });
|
|
25509
|
+
if (useCache && context.action === "delete")
|
|
25510
|
+
await cacheService.clear({ ...context.params, contentType: context.uid });
|
|
25511
|
+
const originalFields = json$1.klona(context.fields);
|
|
25512
|
+
if (returnDeeplyPopulated && ["findOne", "findFirst", "findMany"].includes(context.action))
|
|
25513
|
+
context.fields = ["documentId", "status", "locale"];
|
|
25514
|
+
const result = await next();
|
|
25515
|
+
if (["create", "update"].includes(context.action)) {
|
|
25516
|
+
const { documentId, status: status2, locale: locale2 } = result;
|
|
25517
|
+
if (useCache && context.action === "update")
|
|
25518
|
+
await cacheService.clear({ ...context.params, contentType: context.uid });
|
|
25519
|
+
if (useCache || returnDeeplyPopulated) {
|
|
25520
|
+
const deepPopulate = await populateService.get({ contentType: context.uid, documentId, status: status2, locale: locale2 });
|
|
25521
|
+
if (returnDeeplyPopulated)
|
|
25522
|
+
return await strapi2.documents(context.uid).findOne({ documentId, status: status2, locale: locale2, fields: originalFields, populate: deepPopulate });
|
|
25523
|
+
}
|
|
25524
|
+
}
|
|
25525
|
+
if (returnDeeplyPopulated && ["findOne", "findFirst"].includes(context.action)) {
|
|
25526
|
+
const { documentId, status: status2, locale: locale2 } = result;
|
|
25527
|
+
const deepPopulate = await populateService.get({ contentType: context.uid, documentId, status: status2, locale: locale2 });
|
|
25528
|
+
return await strapi2.documents(context.uid).findOne({ documentId, status: status2, locale: locale2, fields: originalFields, populate: deepPopulate });
|
|
25529
|
+
}
|
|
25530
|
+
if (returnDeeplyPopulated && context.action === "findMany") {
|
|
25531
|
+
return await Promise.all(
|
|
25532
|
+
result.map(async ({ documentId, status: status2, locale: locale2 }) => {
|
|
25533
|
+
const deepPopulate = await populateService.get({ contentType: context.uid, documentId, status: status2, locale: locale2 });
|
|
25534
|
+
return await strapi2.documents(context.uid).findOne({ documentId, status: status2, locale: locale2, fields: originalFields, populate: deepPopulate });
|
|
25535
|
+
})
|
|
25536
|
+
);
|
|
25537
|
+
}
|
|
25538
|
+
return result;
|
|
25539
|
+
});
|
|
25540
|
+
};
|
|
25541
|
+
const getHash = (params) => {
|
|
25542
|
+
return `${params.contentType}-${params.documentId}-${params.locale}-${params.status}-${params.omitEmpty ? "sparse" : "full"}`;
|
|
25543
|
+
};
|
|
25544
|
+
const cache = ({ strapi: strapi2 }) => ({
|
|
25545
|
+
async get(params) {
|
|
25546
|
+
const entry = await strapi2.documents("plugin::deep-populate.cache").findFirst({ filters: { hash: { $eq: getHash(params) } } });
|
|
25547
|
+
return entry ? entry.populate : null;
|
|
25548
|
+
},
|
|
25549
|
+
async set({ populate: populate2, dependencies, ...params }) {
|
|
25550
|
+
const documentService = strapi2.documents("plugin::deep-populate.cache");
|
|
25551
|
+
const hash = getHash(params);
|
|
25552
|
+
const entry = await documentService.findFirst({ filters: { hash: { $eq: hash } } });
|
|
25553
|
+
return entry ? await documentService.update({
|
|
25554
|
+
documentId: entry.documentId,
|
|
25555
|
+
data: { populate: populate2, dependencies: dependencies.join(",") }
|
|
25556
|
+
}) : await documentService.create({ data: { hash, params, populate: populate2, dependencies: dependencies.join(",") } });
|
|
25557
|
+
},
|
|
25558
|
+
async clear(params) {
|
|
25559
|
+
const entry = await strapi2.documents("plugin::deep-populate.cache").findFirst({ filters: { hash: { $eq: getHash(params) } } });
|
|
25560
|
+
let retval = null;
|
|
25561
|
+
if (entry) {
|
|
25562
|
+
retval = await strapi2.documents("plugin::deep-populate.cache").delete({ documentId: entry.documentId });
|
|
25563
|
+
}
|
|
25564
|
+
await this.refreshDependents(params.documentId);
|
|
25565
|
+
return retval;
|
|
25566
|
+
},
|
|
25567
|
+
async refreshDependents(documentId) {
|
|
25568
|
+
const entries = await strapi2.documents("plugin::deep-populate.cache").findMany({ filters: { dependencies: { $contains: documentId } }, fields: ["documentId", "params"] });
|
|
25569
|
+
const deleted = await strapi2.db.query("plugin::deep-populate.cache").deleteMany({
|
|
25570
|
+
where: {
|
|
25571
|
+
documentId: { $in: entries.map((x) => x.documentId) }
|
|
25572
|
+
}
|
|
25573
|
+
});
|
|
25574
|
+
if (deleted.count !== entries.length)
|
|
25575
|
+
console.error(`Deleted count ${deleted.count} does not match entries count ${entries.length}`);
|
|
25576
|
+
const batchSize = 5;
|
|
25577
|
+
for (let i = 0; i < entries.length; i += batchSize) {
|
|
25578
|
+
const batch = entries.slice(i, i + batchSize);
|
|
25579
|
+
await Promise.all(batch.map((entry) => strapi2.service("plugin::deep-populate.populate").get(entry.params)));
|
|
25580
|
+
}
|
|
25581
|
+
}
|
|
25582
|
+
});
|
|
25259
25583
|
const getRelations = (model) => {
|
|
25260
25584
|
const filteredAttributes = /* @__PURE__ */ new Set();
|
|
25261
25585
|
const { populateCreatorFields } = contentTypes.getOptions(model);
|
|
@@ -25466,8 +25790,8 @@ async function populate$1(params) {
|
|
|
25466
25790
|
}
|
|
25467
25791
|
const populate = ({ strapi: strapi2 }) => ({
|
|
25468
25792
|
async get(params) {
|
|
25469
|
-
const {
|
|
25470
|
-
if (!
|
|
25793
|
+
const { useCache } = strapi2.config.get("plugin::deep-populate");
|
|
25794
|
+
if (!useCache) return (await populate$1(params)).populate;
|
|
25471
25795
|
const cachedEntry = await strapi2.service("plugin::deep-populate.cache").get(params);
|
|
25472
25796
|
if (cachedEntry) return cachedEntry;
|
|
25473
25797
|
const resolved = await populate$1(params);
|