@plasmicpkgs/strapi 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +56 -4
- package/dist/index.esm.js +178 -45
- package/dist/index.esm.js.map +3 -3
- package/dist/index.js +178 -43
- package/dist/index.js.map +3 -3
- package/package.json +5 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { RulesLogic } from 'json-logic-js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Extracts fields whose types can be displayed in Plasmic.
|
|
3
5
|
* @internal
|
|
@@ -55,15 +57,59 @@ export declare const _queryParameters: {
|
|
|
55
57
|
label: string;
|
|
56
58
|
}[];
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Query a Strapi collection with optional filtering.
|
|
62
|
+
*
|
|
63
|
+
* @param opts - Query options including host, token, collection, and filter logic
|
|
64
|
+
* @returns Promise resolving to the Strapi query response or null if required params are missing
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* // Fetch all entries
|
|
69
|
+
* const result = await queryStrapi({
|
|
70
|
+
* host: 'https://api.example.com',
|
|
71
|
+
* token: 'your-api-token',
|
|
72
|
+
* collection: 'articles'
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
* // Fetch with filter
|
|
76
|
+
* const filtered = await queryStrapi({
|
|
77
|
+
* host: 'https://api.example.com',
|
|
78
|
+
* token: 'your-api-token',
|
|
79
|
+
* collection: 'articles',
|
|
80
|
+
* filterLogic: { "==": [{ var: "status" }, "published"] }
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function queryStrapi({ host, token, collection, filterLogic, }: QueryStrapiOpts): Promise<StrapiQueryResponse | null>;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Query Strapi with simplified filter props.
|
|
88
|
+
*
|
|
89
|
+
* @deprecated Use {@link queryStrapi} with `filterLogic` parameter instead.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* // Old way (deprecated)
|
|
94
|
+
* _queryStrapi({ filterField: 'name', filterValue: 'John' })
|
|
95
|
+
*
|
|
96
|
+
* // New way
|
|
97
|
+
* queryStrapi({
|
|
98
|
+
* filterLogic: {"==": [{ var: "name" }, "John"]}
|
|
99
|
+
* })
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function _queryStrapi({ host, token, collection, filterLogic, filterField, filterValue, filterParameter, }: QueryStrapiOpts & StrapiQueryOldFilterProps): Promise<StrapiQueryResponse | null>;
|
|
59
103
|
|
|
60
104
|
declare interface QueryStrapiOpts {
|
|
61
105
|
host?: string;
|
|
62
106
|
token?: string;
|
|
63
107
|
collection?: string;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Filter logic using JSON Logic format to filter Strapi entries.
|
|
110
|
+
* See {@link https://www.npmjs.com/package/@types/json-logic-js?activeTab=readme}
|
|
111
|
+
*/
|
|
112
|
+
filterLogic?: RulesLogic;
|
|
67
113
|
}
|
|
68
114
|
|
|
69
115
|
export declare function registerStrapi(loader?: {
|
|
@@ -104,6 +150,12 @@ declare interface StrapiMediaAttributes {
|
|
|
104
150
|
absoluteUrl?: string;
|
|
105
151
|
}
|
|
106
152
|
|
|
153
|
+
declare interface StrapiQueryOldFilterProps {
|
|
154
|
+
filterField?: string;
|
|
155
|
+
filterValue?: string;
|
|
156
|
+
filterParameter?: string;
|
|
157
|
+
}
|
|
158
|
+
|
|
107
159
|
declare interface StrapiQueryResponse {
|
|
108
160
|
data: StrapiItem[];
|
|
109
161
|
meta: {
|
package/dist/index.esm.js
CHANGED
|
@@ -1,22 +1,3 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defProps = Object.defineProperties;
|
|
3
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
-
var __spreadValues = (a, b) => {
|
|
9
|
-
for (var prop in b || (b = {}))
|
|
10
|
-
if (__hasOwnProp.call(b, prop))
|
|
11
|
-
__defNormalProp(a, prop, b[prop]);
|
|
12
|
-
if (__getOwnPropSymbols)
|
|
13
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
-
if (__propIsEnum.call(b, prop))
|
|
15
|
-
__defNormalProp(a, prop, b[prop]);
|
|
16
|
-
}
|
|
17
|
-
return a;
|
|
18
|
-
};
|
|
19
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
1
|
var __async = (__this, __arguments, generator) => {
|
|
21
2
|
return new Promise((resolve, reject) => {
|
|
22
3
|
var fulfilled = (value) => {
|
|
@@ -239,6 +220,131 @@ function transformMediaUrls(data, host) {
|
|
|
239
220
|
return transformValue(data);
|
|
240
221
|
}
|
|
241
222
|
|
|
223
|
+
// src/where.ts
|
|
224
|
+
function strapiFieldsToQueryBuilderConfig(fields, sampleData) {
|
|
225
|
+
const qbFields = {};
|
|
226
|
+
for (const field of fields) {
|
|
227
|
+
const sampleValue = sampleData == null ? void 0 : sampleData[field];
|
|
228
|
+
const qbField = strapiFieldToQueryBuilderField(field, sampleValue);
|
|
229
|
+
if (qbField) {
|
|
230
|
+
qbFields[field] = qbField;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
fields: qbFields
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function strapiFieldToQueryBuilderField(fieldName, sampleValue) {
|
|
238
|
+
const label = fieldName;
|
|
239
|
+
if (typeof sampleValue === "number") {
|
|
240
|
+
return {
|
|
241
|
+
type: "number",
|
|
242
|
+
label,
|
|
243
|
+
operators: [
|
|
244
|
+
"equal",
|
|
245
|
+
"not_equal",
|
|
246
|
+
"less",
|
|
247
|
+
"less_or_equal",
|
|
248
|
+
"greater",
|
|
249
|
+
"greater_or_equal",
|
|
250
|
+
"is_null",
|
|
251
|
+
"is_not_null"
|
|
252
|
+
]
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
if (typeof sampleValue === "boolean") {
|
|
256
|
+
return {
|
|
257
|
+
type: "boolean",
|
|
258
|
+
label
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
if (typeof sampleValue === "string") {
|
|
262
|
+
if (!isNaN(new Date(sampleValue).getTime())) {
|
|
263
|
+
return {
|
|
264
|
+
type: "datetime",
|
|
265
|
+
label,
|
|
266
|
+
operators: [
|
|
267
|
+
"equal",
|
|
268
|
+
"not_equal",
|
|
269
|
+
"less",
|
|
270
|
+
"less_or_equal",
|
|
271
|
+
"greater",
|
|
272
|
+
"greater_or_equal",
|
|
273
|
+
"is_null",
|
|
274
|
+
"is_not_null"
|
|
275
|
+
]
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
type: "text",
|
|
280
|
+
label,
|
|
281
|
+
operators: [
|
|
282
|
+
"equal",
|
|
283
|
+
"not_equal",
|
|
284
|
+
"like",
|
|
285
|
+
"not_like",
|
|
286
|
+
"is_null",
|
|
287
|
+
"is_not_null"
|
|
288
|
+
]
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
return void 0;
|
|
292
|
+
}
|
|
293
|
+
function rulesLogicToStrapiFilters(logic) {
|
|
294
|
+
if (logic === null || logic === void 0) {
|
|
295
|
+
return void 0;
|
|
296
|
+
} else if (typeof logic !== "object") {
|
|
297
|
+
throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);
|
|
298
|
+
} else if ("and" in logic) {
|
|
299
|
+
return {
|
|
300
|
+
$and: logic["and"].map(rulesLogicToStrapiFilters)
|
|
301
|
+
};
|
|
302
|
+
} else if ("or" in logic) {
|
|
303
|
+
return {
|
|
304
|
+
$or: logic["or"].map(rulesLogicToStrapiFilters)
|
|
305
|
+
};
|
|
306
|
+
} else if ("!" in logic) {
|
|
307
|
+
return {
|
|
308
|
+
$not: rulesLogicToStrapiFilters(logic["!"])
|
|
309
|
+
};
|
|
310
|
+
} else if ("==" in logic) {
|
|
311
|
+
const [{ var: field }, operand] = logic["=="];
|
|
312
|
+
if (operand === null) {
|
|
313
|
+
return { [field]: { $null: true } };
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
[field]: { $eq: operand }
|
|
317
|
+
};
|
|
318
|
+
} else if ("!=" in logic) {
|
|
319
|
+
const [{ var: field }, operand] = logic["!="];
|
|
320
|
+
if (operand === null) {
|
|
321
|
+
return { [field]: { $notNull: true } };
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
[field]: { $ne: operand }
|
|
325
|
+
};
|
|
326
|
+
} else if ("in" in logic) {
|
|
327
|
+
const [operand, { var: field }] = logic["in"];
|
|
328
|
+
return {
|
|
329
|
+
[field]: { $contains: operand }
|
|
330
|
+
};
|
|
331
|
+
} else {
|
|
332
|
+
const [key, value] = Object.entries(logic)[0];
|
|
333
|
+
const apiOp = operatorMapping[key];
|
|
334
|
+
if (apiOp) {
|
|
335
|
+
const [{ var: field }, operand] = value;
|
|
336
|
+
return { [field]: { [apiOp]: operand } };
|
|
337
|
+
}
|
|
338
|
+
throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
var operatorMapping = {
|
|
342
|
+
"<": "$lt",
|
|
343
|
+
"<=": "$lte",
|
|
344
|
+
">": "$gt",
|
|
345
|
+
">=": "$gte"
|
|
346
|
+
};
|
|
347
|
+
|
|
242
348
|
// src/query-strapi.tsx
|
|
243
349
|
var queryStrapiMeta = {
|
|
244
350
|
name: "queryStrapi",
|
|
@@ -263,24 +369,12 @@ var queryStrapiMeta = {
|
|
|
263
369
|
type: "string",
|
|
264
370
|
description: "The name of the Strapi collection to query"
|
|
265
371
|
},
|
|
266
|
-
|
|
267
|
-
type: "
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
filterValue: {
|
|
273
|
-
type: "string",
|
|
274
|
-
description: "The value to filter by (optional, if you want to filter results)"
|
|
275
|
-
},
|
|
276
|
-
filterParameter: {
|
|
277
|
-
type: "choice",
|
|
278
|
-
description: "The parameter for filtering (e.g., 'eq', 'contains', etc.) (optional)",
|
|
279
|
-
options: () => {
|
|
280
|
-
return queryParameters.map((item) => ({
|
|
281
|
-
label: item == null ? void 0 : item.label,
|
|
282
|
-
value: item == null ? void 0 : item.value
|
|
283
|
-
}));
|
|
372
|
+
filterLogic: {
|
|
373
|
+
type: "queryBuilder",
|
|
374
|
+
description: "Filter fetched entries. Defaults to fetch all entries.",
|
|
375
|
+
config: (_, ctx) => {
|
|
376
|
+
const fields = (ctx == null ? void 0 : ctx.strapiFields) || [];
|
|
377
|
+
return strapiFieldsToQueryBuilderConfig(fields, ctx == null ? void 0 : ctx.sampleData);
|
|
284
378
|
}
|
|
285
379
|
}
|
|
286
380
|
}
|
|
@@ -295,15 +389,37 @@ var queryStrapiMeta = {
|
|
|
295
389
|
})
|
|
296
390
|
};
|
|
297
391
|
}
|
|
392
|
+
const fetchOpts = {
|
|
393
|
+
host: strapiOpts.host,
|
|
394
|
+
token: strapiOpts.token,
|
|
395
|
+
collection: strapiOpts.collection
|
|
396
|
+
};
|
|
298
397
|
return {
|
|
299
|
-
dataKey: JSON.stringify(
|
|
398
|
+
dataKey: JSON.stringify(fetchOpts),
|
|
300
399
|
fetcher: () => __async(void 0, null, function* () {
|
|
301
|
-
const resp = yield queryStrapi(
|
|
400
|
+
const resp = yield queryStrapi(fetchOpts);
|
|
302
401
|
const collectionData = resp == null ? void 0 : resp.data;
|
|
303
402
|
if (!collectionData) {
|
|
304
403
|
return { strapiFields: [] };
|
|
305
404
|
}
|
|
306
|
-
|
|
405
|
+
const sampleData = {};
|
|
406
|
+
const fields = extractFilterableFields(collectionData);
|
|
407
|
+
const itemsToCheck = collectionData.slice(0, 10);
|
|
408
|
+
for (const field of fields) {
|
|
409
|
+
for (const item of itemsToCheck) {
|
|
410
|
+
if (item) {
|
|
411
|
+
const value = getFieldValue(item, field);
|
|
412
|
+
if (value !== null && value !== void 0) {
|
|
413
|
+
sampleData[field] = value;
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
strapiFields: fields,
|
|
421
|
+
sampleData
|
|
422
|
+
};
|
|
307
423
|
})
|
|
308
424
|
};
|
|
309
425
|
}
|
|
@@ -313,6 +429,17 @@ function queryStrapi(_0) {
|
|
|
313
429
|
host,
|
|
314
430
|
token,
|
|
315
431
|
collection,
|
|
432
|
+
filterLogic
|
|
433
|
+
}) {
|
|
434
|
+
return _queryStrapi({ host, token, collection, filterLogic });
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
function _queryStrapi(_0) {
|
|
438
|
+
return __async(this, arguments, function* ({
|
|
439
|
+
host,
|
|
440
|
+
token,
|
|
441
|
+
collection,
|
|
442
|
+
filterLogic,
|
|
316
443
|
filterField,
|
|
317
444
|
filterValue,
|
|
318
445
|
filterParameter
|
|
@@ -325,15 +452,20 @@ function queryStrapi(_0) {
|
|
|
325
452
|
if (token) {
|
|
326
453
|
requestInit.headers = { Authorization: "Bearer " + token };
|
|
327
454
|
}
|
|
328
|
-
|
|
329
|
-
|
|
455
|
+
let filters = {};
|
|
456
|
+
if (filterLogic) {
|
|
457
|
+
filters = rulesLogicToStrapiFilters(filterLogic);
|
|
458
|
+
} else if (filterField && filterParameter && filterValue) {
|
|
459
|
+
filters = {
|
|
330
460
|
[filterField]: {
|
|
331
461
|
[filterParameter]: filterValue
|
|
332
462
|
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
const queryParams = qs.stringify({
|
|
466
|
+
filters,
|
|
335
467
|
populate: "*"
|
|
336
|
-
})
|
|
468
|
+
});
|
|
337
469
|
const resp = yield fetch(`${query}?${queryParams}`, requestInit);
|
|
338
470
|
const data = yield resp.json();
|
|
339
471
|
return transformMediaUrls(data, host);
|
|
@@ -363,6 +495,7 @@ export {
|
|
|
363
495
|
isStrapiItemArray as _isStrapiItemArray,
|
|
364
496
|
isStrapiPrimitive as _isStrapiPrimitive,
|
|
365
497
|
queryParameters as _queryParameters,
|
|
498
|
+
_queryStrapi,
|
|
366
499
|
queryStrapi,
|
|
367
500
|
registerStrapi
|
|
368
501
|
};
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../src/query-strapi.tsx", "../src/strapi-compat.ts", "../src/utils.ts"],
|
|
4
|
-
"sourcesContent": ["import registerFunction, {\n CustomFunctionMeta,\n} from \"@plasmicapp/host/registerFunction\";\nimport { queryStrapi, queryStrapiMeta } from \"./query-strapi\";\n\nexport function registerStrapi(loader?: { registerFunction: any }) {\n function _registerFunction<T extends (...args: any[]) => any>(\n fn: T,\n meta: CustomFunctionMeta<T>\n ) {\n if (loader) {\n loader.registerFunction(fn, meta);\n } else {\n registerFunction(fn, meta);\n }\n }\n\n _registerFunction(queryStrapi, queryStrapiMeta);\n}\n\nexport { queryStrapi };\n\n// used by @plasmicpkgs/plasmic-strapi\nexport {\n getItemKeys as _getFieldKeys,\n getFieldValue as _getFieldValue,\n getId as _getId,\n getMediaAttributes as _getMediaAttributes,\n isStrapiItem as _isStrapiItem,\n isStrapiItemArray as _isStrapiItemArray,\n isStrapiPrimitive as _isStrapiPrimitive,\n} from \"./strapi-compat\";\nexport {\n extractDisplayableFields as _extractDisplayableFields,\n extractFilterableFields as _extractFilterableFields,\n isImage as _isImage,\n queryParameters as _queryParameters,\n} from \"./utils\";\n", "import { CustomFunctionMeta } from \"@plasmicapp/host/registerFunction\";\nimport qs from \"qs\";\nimport { StrapiQueryResponse } from \"./strapi-compat\";\nimport {\n extractFilterableFields,\n normalizeUrl,\n queryParameters,\n transformMediaUrls,\n} from \"./utils\";\n\nexport const queryStrapiMeta: CustomFunctionMeta<typeof queryStrapi> = {\n name: \"queryStrapi\",\n displayName: \"Query Strapi\",\n description: \"Query a Strapi collection\",\n importPath: \"@plasmicpkgs/strapi\",\n params: [\n {\n name: \"opts\",\n type: \"object\",\n display: \"flatten\",\n fields: {\n host: {\n type: \"string\",\n description: \"The Strapi host URL (e.g., https://example.com)\",\n },\n token: {\n type: \"string\",\n description:\n \"The Strapi API token (optional, for authenticated requests)\",\n },\n collection: {\n type: \"string\",\n description: \"The name of the Strapi collection to query\",\n },\n filterField: {\n type: \"choice\",\n options: (_, ctx) => {\n return ctx?.strapiFields;\n },\n },\n filterValue: {\n type: \"string\",\n description:\n \"The value to filter by (optional, if you want to filter results)\",\n },\n filterParameter: {\n type: \"choice\",\n description:\n \"The parameter for filtering (e.g., 'eq', 'contains', etc.) (optional)\",\n options: () => {\n return queryParameters.map((item: any) => ({\n label: item?.label,\n value: item?.value,\n }));\n },\n },\n },\n },\n ],\n fnContext: (strapiOpts?: QueryStrapiOpts) => {\n if (!strapiOpts?.host) {\n return {\n dataKey: \"\",\n fetcher: async () => {\n return {};\n },\n };\n }\n return {\n dataKey: JSON.stringify(strapiOpts),\n fetcher: async () => {\n const resp = await queryStrapi(strapiOpts);\n const collectionData = resp?.data;\n if (!collectionData) {\n return { strapiFields: [] };\n }\n\n return { strapiFields: extractFilterableFields(collectionData) };\n },\n };\n },\n};\n\nexport interface QueryStrapiOpts {\n host?: string;\n token?: string;\n collection?: string;\n filterField?: string;\n filterValue?: string;\n filterParameter?: string;\n}\n\nexport async function queryStrapi({\n host,\n token,\n collection,\n filterField,\n filterValue,\n filterParameter,\n}: QueryStrapiOpts): Promise<StrapiQueryResponse | null> {\n if (!host || !collection) {\n return null;\n }\n\n const query = normalizeUrl(host) + \"/api/\" + collection.trim();\n\n const requestInit: RequestInit = { method: \"GET\" };\n if (token) {\n requestInit.headers = { Authorization: \"Bearer \" + token };\n }\n\n const queryParams = qs.stringify({\n ...(filterField && filterParameter && filterValue\n ? {\n filters: {\n [filterField]: {\n [filterParameter]: filterValue,\n },\n },\n }\n : {}),\n populate: \"*\",\n });\n\n const resp = await fetch(`${query}?${queryParams}`, requestInit);\n const data = await resp.json();\n\n // Transform all relative media URLs to absolute URLs\n return transformMediaUrls(data, host);\n}\n", "// This file contains Strapi code for handling v4/v5 compatibility.\n// https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/new-response-format\n\nexport interface StrapiQueryResponse {\n data: StrapiItem[];\n meta: {\n pagination: {\n page: number;\n pageSize: number;\n pageCount: number;\n total: number;\n };\n };\n}\n\n/** A primitive, item, item array, or null (for optional fields). */\nexport type StrapiValue =\n | boolean\n | number\n | string\n | StrapiItem\n | ReadonlyArray<StrapiItem>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV4 =\n | boolean\n | number\n | string\n | { data: StrapiItemV4 | ReadonlyArray<StrapiItemV4> }\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV5 =\n | boolean\n | number\n | string\n | StrapiItemV5\n | ReadonlyArray<StrapiItemV5>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\n\n/** A content item or media item. */\nexport type StrapiItem = StrapiItemV4 | StrapiItemV5;\nexport interface StrapiItemV4 {\n id: number;\n attributes: {\n [attribute: string]: StrapiValueV4;\n };\n}\nexport interface StrapiItemV5 {\n documentId: string;\n [attribute: string]: StrapiValueV5;\n}\nfunction isV5Item(item: StrapiItem): item is StrapiItemV5 {\n return \"documentId\" in item;\n}\n\nfunction isV4Item(item: StrapiItem): item is StrapiItemV5 {\n return \"id\" in item && \"attributes\" in item;\n}\n\n/** @internal */\nexport function isStrapiPrimitive(\n value: StrapiValue | undefined\n): value is boolean | number | string {\n const type = typeof value;\n return type === \"boolean\" || type === \"number\" || type === \"string\";\n}\n/** @internal */\nexport function isStrapiItem(\n item: StrapiValue | undefined\n): item is StrapiItem {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) {\n return false;\n }\n // The object must be a valid v5 or v4 item\n return isV5Item(item as any) || isV4Item(item as any);\n}\n/** @internal */\nexport function isStrapiItemArray(\n value: StrapiValue | undefined\n): value is ReadonlyArray<StrapiItem> {\n return typeof value === \"object\" && value !== null && Array.isArray(value);\n}\n\n/** @internal */\nexport function getId(item: StrapiItem): string {\n if (isV5Item(item)) {\n return item.documentId;\n } else {\n // v4\n return item.id.toString();\n }\n}\n\n/** @internal */\nexport function getItemKeys(item: StrapiItem) {\n if (isV5Item(item)) {\n return Object.keys(item).filter((key) => key !== \"documentId\");\n } else {\n // v4\n return Object.keys(item.attributes);\n }\n}\n\n/**\n * Gets the value, or undefined if the field key does not exist.\n * @internal\n */\nexport function getFieldValue(\n item: StrapiItem,\n key: string\n): StrapiValue | undefined {\n if (isV5Item(item)) {\n return item[key];\n } else {\n // v4\n const value = item.attributes[key];\n if (value === null || value === undefined) {\n return value;\n }\n switch (typeof value) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n return value;\n case \"object\":\n if (value && \"data\" in value) {\n return value.data;\n } else {\n return undefined;\n }\n default:\n return undefined;\n }\n }\n}\n\n/** This includes any asset such as image, video, audio, file */\nexport interface StrapiMediaAttributes {\n url: string;\n mime: string;\n ext: string;\n size: number;\n // width and height are null for non-image media (e.g. audio files)\n width: number | null;\n height: number | null;\n formats?: { [key: string]: Omit<StrapiMediaAttributes, \"formats\"> };\n // Added by transformMediaUrls - absolute URL with host prepended\n absoluteUrl?: string;\n}\n\nexport interface StrapiImageAttribute extends StrapiMediaAttributes {\n width: number;\n height: number;\n}\n/**\n * Gets media attributes if it's a media item.\n *\n * This is the small subset of the fields that we care about.\n *\n * @internal\n */\nexport function getMediaAttributes(\n value: StrapiItem\n): StrapiMediaAttributes | undefined {\n const attributes = isV5Item(value) ? value : value.attributes;\n if (\n \"url\" in attributes &&\n \"mime\" in attributes &&\n \"ext\" in attributes &&\n \"size\" in attributes\n ) {\n return attributes as { [attribute: string]: any } as StrapiMediaAttributes;\n } else {\n return undefined;\n }\n}\n", "import {\n StrapiImageAttribute,\n StrapiItem,\n StrapiMediaAttributes,\n StrapiQueryResponse,\n getFieldValue,\n getItemKeys,\n getMediaAttributes,\n isStrapiItem,\n isStrapiPrimitive,\n} from \"./strapi-compat\";\n\n/**\n * https://docs-v4.strapi.io/dev-docs/api/entity-service/filter\n * @internal\n */\nexport const queryParameters = [\n {\n value: \"$eq\",\n label: \"Equal\",\n },\n {\n value: \"$ne\",\n label: \"Not equal\",\n },\n {\n value: \"$lt\",\n label: \"Less than\",\n },\n {\n value: \"$lte\",\n label: \"Less than or equal to\",\n },\n {\n value: \"$gt\",\n label: \"Greater than\",\n },\n {\n value: \"$gte\",\n label: \"Greater than or equal to\",\n },\n {\n value: \"$in\",\n label: \"Included in an array\",\n },\n {\n value: \"$notIn\",\n label: \"Not included in an array\",\n },\n {\n value: \"$contains\",\n label: \"Contains\",\n },\n {\n value: \"$notContains\",\n label: \"Does not contain\",\n },\n];\n\n/**\n * Checks if the media attribute contains an image media\n * @internal\n */\nexport function isImage(\n mediaAttr: StrapiMediaAttributes\n): mediaAttr is StrapiImageAttribute {\n return mediaAttr?.mime.startsWith(\"image\");\n}\n\n/**\n * Removes leading and trailing slash and whitespace characters from a URL\n * @internal\n */\nexport function normalizeUrl(url: string): string {\n return (\n url\n .trim()\n // remove leading slash\n .replace(/^\\/+/, \"\")\n // remove leading trailing\n .replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Extracts fields whose types can be filtered in Plasmic.\n * @internal\n */\nexport function extractFilterableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(filterableFields)));\n } else {\n return filterableFields(items);\n }\n}\n\nfunction filterableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return isStrapiPrimitive(value);\n });\n}\n\n/**\n * Extracts fields whose types can be displayed in Plasmic.\n * @internal\n */\nexport function extractDisplayableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(displayableFields)));\n } else {\n return displayableFields(items);\n }\n}\n\nfunction displayableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return (\n isStrapiPrimitive(value) ||\n (isStrapiItem(value) && getMediaAttributes(value))\n );\n });\n}\n\n/**\n * Traverses @param data and adds an absoluteUrl field to all media items by prepending the @param host to the url\n * @internal\n */\nexport function transformMediaUrls(\n data: StrapiQueryResponse,\n host: string\n): StrapiQueryResponse {\n if (data === null || data === undefined) {\n return data;\n }\n\n const normalizedHost = normalizeUrl(host);\n\n /**\n * Converts a relative URL to absolute by prepending the host.\n * If URL is already absolute, returns it unchanged.\n */\n function makeAbsoluteUrl(url: string): string {\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n return url;\n }\n return normalizedHost + \"/\" + normalizeUrl(url);\n }\n\n /**\n * Adds absoluteUrl to a media item and its format variations\n */\n function transformMediaItem(mediaAttrs: StrapiMediaAttributes): void {\n mediaAttrs.absoluteUrl = makeAbsoluteUrl(mediaAttrs.url);\n\n // Transform format variations (thumbnail, small, medium, large, etc.)\n if (mediaAttrs.formats && typeof mediaAttrs.formats === \"object\") {\n for (const formatKey of Object.keys(mediaAttrs.formats)) {\n transformMediaItem(mediaAttrs.formats[formatKey]);\n }\n }\n }\n\n /**\n * Recursively traverses a Strapi item and transforms all nested media\n */\n function transformStrapiItem(item: StrapiItem): void {\n const mediaAttrs = getMediaAttributes(item);\n\n if (mediaAttrs) {\n // This item is itself a media item\n transformMediaItem(mediaAttrs);\n } else {\n // This item contains other fields that might be media\n for (const key of getItemKeys(item)) {\n const fieldValue = getFieldValue(item, key);\n transformValue(fieldValue);\n }\n }\n }\n\n /**\n * Recursively traverses and transforms media URLs in any value\n */\n function transformValue(value: any): any {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (isStrapiPrimitive(value)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n value.forEach(transformValue);\n return value;\n }\n\n if (isStrapiItem(value)) {\n transformStrapiItem(value);\n } else if (typeof value === \"object\") {\n // Plain object - traverse its properties\n for (const key of Object.keys(value)) {\n transformValue(value[key]);\n }\n }\n\n return value;\n }\n\n return transformValue(data);\n}\n"],
|
|
5
|
-
"mappings": "
|
|
3
|
+
"sources": ["../src/index.ts", "../src/query-strapi.tsx", "../src/strapi-compat.ts", "../src/utils.ts", "../src/where.ts"],
|
|
4
|
+
"sourcesContent": ["import registerFunction, {\n CustomFunctionMeta,\n} from \"@plasmicapp/host/registerFunction\";\nimport { _queryStrapi, queryStrapi, queryStrapiMeta } from \"./query-strapi\";\n\nexport function registerStrapi(loader?: { registerFunction: any }) {\n function _registerFunction<T extends (...args: any[]) => any>(\n fn: T,\n meta: CustomFunctionMeta<T>\n ) {\n if (loader) {\n loader.registerFunction(fn, meta);\n } else {\n registerFunction(fn, meta);\n }\n }\n\n _registerFunction(queryStrapi, queryStrapiMeta);\n}\n\nexport {\n // used by @plasmicpkgs/plasmic-strapi\n _queryStrapi,\n queryStrapi,\n};\n\n// used by @plasmicpkgs/plasmic-strapi\nexport {\n getItemKeys as _getFieldKeys,\n getFieldValue as _getFieldValue,\n getId as _getId,\n getMediaAttributes as _getMediaAttributes,\n isStrapiItem as _isStrapiItem,\n isStrapiItemArray as _isStrapiItemArray,\n isStrapiPrimitive as _isStrapiPrimitive,\n} from \"./strapi-compat\";\nexport {\n extractDisplayableFields as _extractDisplayableFields,\n extractFilterableFields as _extractFilterableFields,\n isImage as _isImage,\n queryParameters as _queryParameters,\n} from \"./utils\";\n", "import { CustomFunctionMeta } from \"@plasmicapp/host/registerFunction\";\nimport type { RulesLogic } from \"json-logic-js\";\nimport qs from \"qs\";\nimport { getFieldValue, StrapiQueryResponse } from \"./strapi-compat\";\nimport {\n extractFilterableFields,\n normalizeUrl,\n transformMediaUrls,\n} from \"./utils\";\nimport {\n rulesLogicToStrapiFilters,\n strapiFieldsToQueryBuilderConfig,\n} from \"./where\";\n\nexport const queryStrapiMeta: CustomFunctionMeta<typeof queryStrapi> = {\n name: \"queryStrapi\",\n displayName: \"Query Strapi\",\n description: \"Query a Strapi collection\",\n importPath: \"@plasmicpkgs/strapi\",\n params: [\n {\n name: \"opts\",\n type: \"object\",\n display: \"flatten\",\n fields: {\n host: {\n type: \"string\",\n description: \"The Strapi host URL (e.g., https://example.com)\",\n },\n token: {\n type: \"string\",\n description:\n \"The Strapi API token (optional, for authenticated requests)\",\n },\n collection: {\n type: \"string\",\n description: \"The name of the Strapi collection to query\",\n },\n filterLogic: {\n type: \"queryBuilder\",\n description: \"Filter fetched entries. Defaults to fetch all entries.\",\n config: (_: any, ctx: any) => {\n const fields = ctx?.strapiFields || [];\n return strapiFieldsToQueryBuilderConfig(fields, ctx?.sampleData);\n },\n },\n },\n },\n ],\n fnContext: (strapiOpts?: QueryStrapiOpts) => {\n if (!strapiOpts?.host) {\n return {\n dataKey: \"\",\n fetcher: async () => {\n return {};\n },\n };\n }\n // Exclude filterLogic from dataKey to prevent refetching when user types in query builder\n // The fields and sampleData should only depend on host, token, and collection\n const fetchOpts: QueryStrapiOpts = {\n host: strapiOpts.host,\n token: strapiOpts.token,\n collection: strapiOpts.collection,\n };\n return {\n dataKey: JSON.stringify(fetchOpts),\n fetcher: async () => {\n const resp = await queryStrapi(fetchOpts);\n const collectionData = resp?.data;\n if (!collectionData) {\n return { strapiFields: [] };\n }\n\n // Extract field values from multiple items for type inference\n // Check up to 10 items to find non-null values for each field\n const sampleData: Record<string, any> = {};\n const fields = extractFilterableFields(collectionData);\n const itemsToCheck = collectionData.slice(0, 10);\n // For each field, find the first non-null value across multiple items\n for (const field of fields) {\n for (const item of itemsToCheck) {\n if (item) {\n const value = getFieldValue(item, field);\n if (value !== null && value !== undefined) {\n sampleData[field] = value;\n break;\n }\n }\n }\n }\n\n return {\n strapiFields: fields,\n sampleData,\n };\n },\n };\n },\n};\n\n// Simplified filter props only intended for use by the deprecated StrapiCollection component\nexport interface StrapiQueryOldFilterProps {\n filterField?: string;\n filterValue?: string;\n filterParameter?: string;\n}\n\nexport interface QueryStrapiOpts {\n host?: string;\n token?: string;\n collection?: string;\n /**\n * Filter logic using JSON Logic format to filter Strapi entries.\n * See {@link https://www.npmjs.com/package/@types/json-logic-js?activeTab=readme}\n */\n filterLogic?: RulesLogic;\n}\n\n/**\n * Query a Strapi collection with optional filtering.\n *\n * @param opts - Query options including host, token, collection, and filter logic\n * @returns Promise resolving to the Strapi query response or null if required params are missing\n *\n * @example\n * ```ts\n * // Fetch all entries\n * const result = await queryStrapi({\n * host: 'https://api.example.com',\n * token: 'your-api-token',\n * collection: 'articles'\n * });\n *\n * // Fetch with filter\n * const filtered = await queryStrapi({\n * host: 'https://api.example.com',\n * token: 'your-api-token',\n * collection: 'articles',\n * filterLogic: { \"==\": [{ var: \"status\" }, \"published\"] }\n * });\n * ```\n */\nexport async function queryStrapi({\n host,\n token,\n collection,\n filterLogic,\n}: QueryStrapiOpts): Promise<StrapiQueryResponse | null> {\n return _queryStrapi({ host, token, collection, filterLogic });\n}\n\n/**\n * Query Strapi with simplified filter props.\n *\n * @deprecated Use {@link queryStrapi} with `filterLogic` parameter instead.\n *\n * @example\n * ```ts\n * // Old way (deprecated)\n * _queryStrapi({ filterField: 'name', filterValue: 'John' })\n *\n * // New way\n * queryStrapi({\n * filterLogic: {\"==\": [{ var: \"name\" }, \"John\"]}\n * })\n * ```\n */\nexport async function _queryStrapi({\n host,\n token,\n collection,\n filterLogic,\n filterField,\n filterValue,\n filterParameter,\n}: QueryStrapiOpts &\n StrapiQueryOldFilterProps): Promise<StrapiQueryResponse | null> {\n if (!host || !collection) {\n return null;\n }\n\n const query = normalizeUrl(host) + \"/api/\" + collection.trim();\n\n const requestInit: RequestInit = { method: \"GET\" };\n if (token) {\n requestInit.headers = { Authorization: \"Bearer \" + token };\n }\n\n let filters: Record<string, any> = {};\n if (filterLogic) {\n filters = rulesLogicToStrapiFilters(filterLogic);\n } else if (filterField && filterParameter && filterValue) {\n filters = {\n [filterField]: {\n [filterParameter]: filterValue,\n },\n };\n }\n\n // Build query parameters for Strapi REST API\n // Strapi uses nested query parameters like: filters[$and][0][field][$eq]=value\n const queryParams = qs.stringify({\n filters,\n populate: \"*\",\n });\n\n const resp = await fetch(`${query}?${queryParams}`, requestInit);\n const data = await resp.json();\n\n // Transform all relative media URLs to absolute URLs\n return transformMediaUrls(data, host);\n}\n", "// This file contains Strapi code for handling v4/v5 compatibility.\n// https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/new-response-format\n\nexport interface StrapiQueryResponse {\n data: StrapiItem[];\n meta: {\n pagination: {\n page: number;\n pageSize: number;\n pageCount: number;\n total: number;\n };\n };\n}\n\n/** A primitive, item, item array, or null (for optional fields). */\nexport type StrapiValue =\n | boolean\n | number\n | string\n | StrapiItem\n | ReadonlyArray<StrapiItem>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV4 =\n | boolean\n | number\n | string\n | { data: StrapiItemV4 | ReadonlyArray<StrapiItemV4> }\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV5 =\n | boolean\n | number\n | string\n | StrapiItemV5\n | ReadonlyArray<StrapiItemV5>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\n\n/** A content item or media item. */\nexport type StrapiItem = StrapiItemV4 | StrapiItemV5;\nexport interface StrapiItemV4 {\n id: number;\n attributes: {\n [attribute: string]: StrapiValueV4;\n };\n}\nexport interface StrapiItemV5 {\n documentId: string;\n [attribute: string]: StrapiValueV5;\n}\nfunction isV5Item(item: StrapiItem): item is StrapiItemV5 {\n return \"documentId\" in item;\n}\n\nfunction isV4Item(item: StrapiItem): item is StrapiItemV5 {\n return \"id\" in item && \"attributes\" in item;\n}\n\n/** @internal */\nexport function isStrapiPrimitive(\n value: StrapiValue | undefined\n): value is boolean | number | string {\n const type = typeof value;\n return type === \"boolean\" || type === \"number\" || type === \"string\";\n}\n/** @internal */\nexport function isStrapiItem(\n item: StrapiValue | undefined\n): item is StrapiItem {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) {\n return false;\n }\n // The object must be a valid v5 or v4 item\n return isV5Item(item as any) || isV4Item(item as any);\n}\n/** @internal */\nexport function isStrapiItemArray(\n value: StrapiValue | undefined\n): value is ReadonlyArray<StrapiItem> {\n return typeof value === \"object\" && value !== null && Array.isArray(value);\n}\n\n/** @internal */\nexport function getId(item: StrapiItem): string {\n if (isV5Item(item)) {\n return item.documentId;\n } else {\n // v4\n return item.id.toString();\n }\n}\n\n/** @internal */\nexport function getItemKeys(item: StrapiItem) {\n if (isV5Item(item)) {\n return Object.keys(item).filter((key) => key !== \"documentId\");\n } else {\n // v4\n return Object.keys(item.attributes);\n }\n}\n\n/**\n * Gets the value, or undefined if the field key does not exist.\n * @internal\n */\nexport function getFieldValue(\n item: StrapiItem,\n key: string\n): StrapiValue | undefined {\n if (isV5Item(item)) {\n return item[key];\n } else {\n // v4\n const value = item.attributes[key];\n if (value === null || value === undefined) {\n return value;\n }\n switch (typeof value) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n return value;\n case \"object\":\n if (value && \"data\" in value) {\n return value.data;\n } else {\n return undefined;\n }\n default:\n return undefined;\n }\n }\n}\n\n/** This includes any asset such as image, video, audio, file */\nexport interface StrapiMediaAttributes {\n url: string;\n mime: string;\n ext: string;\n size: number;\n // width and height are null for non-image media (e.g. audio files)\n width: number | null;\n height: number | null;\n formats?: { [key: string]: Omit<StrapiMediaAttributes, \"formats\"> };\n // Added by transformMediaUrls - absolute URL with host prepended\n absoluteUrl?: string;\n}\n\nexport interface StrapiImageAttribute extends StrapiMediaAttributes {\n width: number;\n height: number;\n}\n/**\n * Gets media attributes if it's a media item.\n *\n * This is the small subset of the fields that we care about.\n *\n * @internal\n */\nexport function getMediaAttributes(\n value: StrapiItem\n): StrapiMediaAttributes | undefined {\n const attributes = isV5Item(value) ? value : value.attributes;\n if (\n \"url\" in attributes &&\n \"mime\" in attributes &&\n \"ext\" in attributes &&\n \"size\" in attributes\n ) {\n return attributes as { [attribute: string]: any } as StrapiMediaAttributes;\n } else {\n return undefined;\n }\n}\n", "import {\n StrapiImageAttribute,\n StrapiItem,\n StrapiMediaAttributes,\n StrapiQueryResponse,\n getFieldValue,\n getItemKeys,\n getMediaAttributes,\n isStrapiItem,\n isStrapiPrimitive,\n} from \"./strapi-compat\";\n\n/**\n * https://docs-v4.strapi.io/dev-docs/api/entity-service/filter\n * @internal\n */\nexport const queryParameters = [\n {\n value: \"$eq\",\n label: \"Equal\",\n },\n {\n value: \"$ne\",\n label: \"Not equal\",\n },\n {\n value: \"$lt\",\n label: \"Less than\",\n },\n {\n value: \"$lte\",\n label: \"Less than or equal to\",\n },\n {\n value: \"$gt\",\n label: \"Greater than\",\n },\n {\n value: \"$gte\",\n label: \"Greater than or equal to\",\n },\n {\n value: \"$in\",\n label: \"Included in an array\",\n },\n {\n value: \"$notIn\",\n label: \"Not included in an array\",\n },\n {\n value: \"$contains\",\n label: \"Contains\",\n },\n {\n value: \"$notContains\",\n label: \"Does not contain\",\n },\n];\n\n/**\n * Checks if the media attribute contains an image media\n * @internal\n */\nexport function isImage(\n mediaAttr: StrapiMediaAttributes\n): mediaAttr is StrapiImageAttribute {\n return mediaAttr?.mime.startsWith(\"image\");\n}\n\n/**\n * Removes leading and trailing slash and whitespace characters from a URL\n * @internal\n */\nexport function normalizeUrl(url: string): string {\n return (\n url\n .trim()\n // remove leading slash\n .replace(/^\\/+/, \"\")\n // remove leading trailing\n .replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Extracts fields whose types can be filtered in Plasmic.\n * @internal\n */\nexport function extractFilterableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(filterableFields)));\n } else {\n return filterableFields(items);\n }\n}\n\nfunction filterableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return isStrapiPrimitive(value);\n });\n}\n\n/**\n * Extracts fields whose types can be displayed in Plasmic.\n * @internal\n */\nexport function extractDisplayableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(displayableFields)));\n } else {\n return displayableFields(items);\n }\n}\n\nfunction displayableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return (\n isStrapiPrimitive(value) ||\n (isStrapiItem(value) && getMediaAttributes(value))\n );\n });\n}\n\n/**\n * Traverses @param data and adds an absoluteUrl field to all media items by prepending the @param host to the url\n * @internal\n */\nexport function transformMediaUrls(\n data: StrapiQueryResponse,\n host: string\n): StrapiQueryResponse {\n if (data === null || data === undefined) {\n return data;\n }\n\n const normalizedHost = normalizeUrl(host);\n\n /**\n * Converts a relative URL to absolute by prepending the host.\n * If URL is already absolute, returns it unchanged.\n */\n function makeAbsoluteUrl(url: string): string {\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n return url;\n }\n return normalizedHost + \"/\" + normalizeUrl(url);\n }\n\n /**\n * Adds absoluteUrl to a media item and its format variations\n */\n function transformMediaItem(mediaAttrs: StrapiMediaAttributes): void {\n mediaAttrs.absoluteUrl = makeAbsoluteUrl(mediaAttrs.url);\n\n // Transform format variations (thumbnail, small, medium, large, etc.)\n if (mediaAttrs.formats && typeof mediaAttrs.formats === \"object\") {\n for (const formatKey of Object.keys(mediaAttrs.formats)) {\n transformMediaItem(mediaAttrs.formats[formatKey]);\n }\n }\n }\n\n /**\n * Recursively traverses a Strapi item and transforms all nested media\n */\n function transformStrapiItem(item: StrapiItem): void {\n const mediaAttrs = getMediaAttributes(item);\n\n if (mediaAttrs) {\n // This item is itself a media item\n transformMediaItem(mediaAttrs);\n } else {\n // This item contains other fields that might be media\n for (const key of getItemKeys(item)) {\n const fieldValue = getFieldValue(item, key);\n transformValue(fieldValue);\n }\n }\n }\n\n /**\n * Recursively traverses and transforms media URLs in any value\n */\n function transformValue(value: any): any {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (isStrapiPrimitive(value)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n value.forEach(transformValue);\n return value;\n }\n\n if (isStrapiItem(value)) {\n transformStrapiItem(value);\n } else if (typeof value === \"object\") {\n // Plain object - traverse its properties\n for (const key of Object.keys(value)) {\n transformValue(value[key]);\n }\n }\n\n return value;\n }\n\n return transformValue(data);\n}\n", "import type {\n Config,\n Field,\n FieldOrGroup,\n} from \"@react-awesome-query-builder/core\";\nimport type { RulesLogic } from \"json-logic-js\";\n\n/**\n * Maps Strapi collection fields to react-awesome-query-builder config.\n *\n * The result will be handled by {@link rulesLogicToStrapiFilters}.\n * Make sure it supports all operators defined here.\n */\nexport function strapiFieldsToQueryBuilderConfig(\n fields: string[],\n sampleData?: any\n): Pick<Config, \"fields\"> {\n const qbFields: { [key: string]: FieldOrGroup } = {};\n for (const field of fields) {\n // Try to get sample value from sampleData to infer type\n const sampleValue = sampleData?.[field];\n const qbField = strapiFieldToQueryBuilderField(field, sampleValue);\n if (qbField) {\n qbFields[field] = qbField;\n }\n }\n return {\n fields: qbFields,\n };\n}\n\n/**\n * Maps a Strapi field name to a query builder field configuration.\n *\n * Infers field type from field name patterns and sample values if provided.\n */\nfunction strapiFieldToQueryBuilderField(\n fieldName: string,\n sampleValue?: unknown\n): Field | undefined {\n const label = fieldName;\n\n // Infer type from sample value if provided\n if (typeof sampleValue === \"number\") {\n return {\n type: \"number\",\n label,\n operators: [\n \"equal\",\n \"not_equal\",\n \"less\",\n \"less_or_equal\",\n \"greater\",\n \"greater_or_equal\",\n \"is_null\",\n \"is_not_null\",\n ],\n };\n }\n if (typeof sampleValue === \"boolean\") {\n return {\n type: \"boolean\",\n label,\n };\n }\n if (typeof sampleValue === \"string\") {\n if (!isNaN(new Date(sampleValue).getTime())) {\n return {\n type: \"datetime\",\n label,\n operators: [\n \"equal\",\n \"not_equal\",\n \"less\",\n \"less_or_equal\",\n \"greater\",\n \"greater_or_equal\",\n \"is_null\",\n \"is_not_null\",\n ],\n };\n }\n\n return {\n type: \"text\",\n label,\n operators: [\n \"equal\",\n \"not_equal\",\n \"like\",\n \"not_like\",\n \"is_null\",\n \"is_not_null\",\n ],\n };\n }\n\n return undefined;\n}\n\n/**\n * Maps JsonLogic to Strapi API filters format.\n *\n * See also:\n * - https://docs.strapi.io/cms/api/rest/filters\n */\nexport function rulesLogicToStrapiFilters(logic: RulesLogic | undefined): any {\n if (logic === null || logic === undefined) {\n return undefined;\n } else if (typeof logic !== \"object\") {\n throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);\n } else if (\"and\" in logic) {\n return {\n $and: logic[\"and\"].map(rulesLogicToStrapiFilters),\n };\n } else if (\"or\" in logic) {\n return {\n $or: logic[\"or\"].map(rulesLogicToStrapiFilters),\n };\n } else if (\"!\" in logic) {\n return {\n $not: rulesLogicToStrapiFilters(logic[\"!\"]),\n };\n } else if (\"==\" in logic) {\n const [{ var: field }, operand] = logic[\"==\"] as [{ var: string }, unknown];\n if (operand === null) {\n return { [field]: { $null: true } };\n }\n return {\n [field]: { $eq: operand },\n };\n } else if (\"!=\" in logic) {\n const [{ var: field }, operand] = logic[\"!=\"] as [{ var: string }, unknown];\n if (operand === null) {\n return { [field]: { $notNull: true } };\n }\n return {\n [field]: { $ne: operand },\n };\n // Map in operator to Strapi filters format:\n // JsonLogic: { \"in\": [\"Mairi\", { \"var\": \"name\" }] }\n // Strapi filters: { \"name\": { $contains: \"Mairi\" } }\n } else if (\"in\" in logic) {\n const [operand, { var: field }] = logic[\"in\"] as [string, { var: string }];\n return {\n [field]: { $contains: operand },\n };\n } else {\n // Map JsonLogic to Strapi filters format:\n // JsonLogic: { \"<=\": [{ \"var\": \"age\" }, 18] }\n // Strapi filters: { \"age\": { \"$lte\": 18 } }\n const [key, value] = Object.entries(logic)[0];\n const apiOp: string | undefined = operatorMapping[key];\n if (apiOp) {\n const [{ var: field }, operand] = value as [{ var: string }, unknown];\n return { [field]: { [apiOp]: operand } };\n }\n\n throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);\n }\n}\n\n/** Maps JsonLogic operator to Strapi filter operator. */\nconst operatorMapping: Record<string, string> = {\n \"<\": \"$lt\",\n \"<=\": \"$lte\",\n \">\": \"$gt\",\n \">=\": \"$gte\",\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __create = Object.create;
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
-
var __defProps = Object.defineProperties;
|
|
5
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
10
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
-
var __spreadValues = (a, b) => {
|
|
14
|
-
for (var prop in b || (b = {}))
|
|
15
|
-
if (__hasOwnProp.call(b, prop))
|
|
16
|
-
__defNormalProp(a, prop, b[prop]);
|
|
17
|
-
if (__getOwnPropSymbols)
|
|
18
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
19
|
-
if (__propIsEnum.call(b, prop))
|
|
20
|
-
__defNormalProp(a, prop, b[prop]);
|
|
21
|
-
}
|
|
22
|
-
return a;
|
|
23
|
-
};
|
|
24
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
8
|
var __export = (target, all) => {
|
|
26
9
|
for (var name in all)
|
|
27
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -78,6 +61,7 @@ __export(src_exports, {
|
|
|
78
61
|
_isStrapiItemArray: () => isStrapiItemArray,
|
|
79
62
|
_isStrapiPrimitive: () => isStrapiPrimitive,
|
|
80
63
|
_queryParameters: () => queryParameters,
|
|
64
|
+
_queryStrapi: () => _queryStrapi,
|
|
81
65
|
queryStrapi: () => queryStrapi,
|
|
82
66
|
registerStrapi: () => registerStrapi
|
|
83
67
|
});
|
|
@@ -282,6 +266,131 @@ function transformMediaUrls(data, host) {
|
|
|
282
266
|
return transformValue(data);
|
|
283
267
|
}
|
|
284
268
|
|
|
269
|
+
// src/where.ts
|
|
270
|
+
function strapiFieldsToQueryBuilderConfig(fields, sampleData) {
|
|
271
|
+
const qbFields = {};
|
|
272
|
+
for (const field of fields) {
|
|
273
|
+
const sampleValue = sampleData == null ? void 0 : sampleData[field];
|
|
274
|
+
const qbField = strapiFieldToQueryBuilderField(field, sampleValue);
|
|
275
|
+
if (qbField) {
|
|
276
|
+
qbFields[field] = qbField;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
fields: qbFields
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function strapiFieldToQueryBuilderField(fieldName, sampleValue) {
|
|
284
|
+
const label = fieldName;
|
|
285
|
+
if (typeof sampleValue === "number") {
|
|
286
|
+
return {
|
|
287
|
+
type: "number",
|
|
288
|
+
label,
|
|
289
|
+
operators: [
|
|
290
|
+
"equal",
|
|
291
|
+
"not_equal",
|
|
292
|
+
"less",
|
|
293
|
+
"less_or_equal",
|
|
294
|
+
"greater",
|
|
295
|
+
"greater_or_equal",
|
|
296
|
+
"is_null",
|
|
297
|
+
"is_not_null"
|
|
298
|
+
]
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (typeof sampleValue === "boolean") {
|
|
302
|
+
return {
|
|
303
|
+
type: "boolean",
|
|
304
|
+
label
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
if (typeof sampleValue === "string") {
|
|
308
|
+
if (!isNaN(new Date(sampleValue).getTime())) {
|
|
309
|
+
return {
|
|
310
|
+
type: "datetime",
|
|
311
|
+
label,
|
|
312
|
+
operators: [
|
|
313
|
+
"equal",
|
|
314
|
+
"not_equal",
|
|
315
|
+
"less",
|
|
316
|
+
"less_or_equal",
|
|
317
|
+
"greater",
|
|
318
|
+
"greater_or_equal",
|
|
319
|
+
"is_null",
|
|
320
|
+
"is_not_null"
|
|
321
|
+
]
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
return {
|
|
325
|
+
type: "text",
|
|
326
|
+
label,
|
|
327
|
+
operators: [
|
|
328
|
+
"equal",
|
|
329
|
+
"not_equal",
|
|
330
|
+
"like",
|
|
331
|
+
"not_like",
|
|
332
|
+
"is_null",
|
|
333
|
+
"is_not_null"
|
|
334
|
+
]
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
return void 0;
|
|
338
|
+
}
|
|
339
|
+
function rulesLogicToStrapiFilters(logic) {
|
|
340
|
+
if (logic === null || logic === void 0) {
|
|
341
|
+
return void 0;
|
|
342
|
+
} else if (typeof logic !== "object") {
|
|
343
|
+
throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);
|
|
344
|
+
} else if ("and" in logic) {
|
|
345
|
+
return {
|
|
346
|
+
$and: logic["and"].map(rulesLogicToStrapiFilters)
|
|
347
|
+
};
|
|
348
|
+
} else if ("or" in logic) {
|
|
349
|
+
return {
|
|
350
|
+
$or: logic["or"].map(rulesLogicToStrapiFilters)
|
|
351
|
+
};
|
|
352
|
+
} else if ("!" in logic) {
|
|
353
|
+
return {
|
|
354
|
+
$not: rulesLogicToStrapiFilters(logic["!"])
|
|
355
|
+
};
|
|
356
|
+
} else if ("==" in logic) {
|
|
357
|
+
const [{ var: field }, operand] = logic["=="];
|
|
358
|
+
if (operand === null) {
|
|
359
|
+
return { [field]: { $null: true } };
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
[field]: { $eq: operand }
|
|
363
|
+
};
|
|
364
|
+
} else if ("!=" in logic) {
|
|
365
|
+
const [{ var: field }, operand] = logic["!="];
|
|
366
|
+
if (operand === null) {
|
|
367
|
+
return { [field]: { $notNull: true } };
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
[field]: { $ne: operand }
|
|
371
|
+
};
|
|
372
|
+
} else if ("in" in logic) {
|
|
373
|
+
const [operand, { var: field }] = logic["in"];
|
|
374
|
+
return {
|
|
375
|
+
[field]: { $contains: operand }
|
|
376
|
+
};
|
|
377
|
+
} else {
|
|
378
|
+
const [key, value] = Object.entries(logic)[0];
|
|
379
|
+
const apiOp = operatorMapping[key];
|
|
380
|
+
if (apiOp) {
|
|
381
|
+
const [{ var: field }, operand] = value;
|
|
382
|
+
return { [field]: { [apiOp]: operand } };
|
|
383
|
+
}
|
|
384
|
+
throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
var operatorMapping = {
|
|
388
|
+
"<": "$lt",
|
|
389
|
+
"<=": "$lte",
|
|
390
|
+
">": "$gt",
|
|
391
|
+
">=": "$gte"
|
|
392
|
+
};
|
|
393
|
+
|
|
285
394
|
// src/query-strapi.tsx
|
|
286
395
|
var queryStrapiMeta = {
|
|
287
396
|
name: "queryStrapi",
|
|
@@ -306,24 +415,12 @@ var queryStrapiMeta = {
|
|
|
306
415
|
type: "string",
|
|
307
416
|
description: "The name of the Strapi collection to query"
|
|
308
417
|
},
|
|
309
|
-
|
|
310
|
-
type: "
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
filterValue: {
|
|
316
|
-
type: "string",
|
|
317
|
-
description: "The value to filter by (optional, if you want to filter results)"
|
|
318
|
-
},
|
|
319
|
-
filterParameter: {
|
|
320
|
-
type: "choice",
|
|
321
|
-
description: "The parameter for filtering (e.g., 'eq', 'contains', etc.) (optional)",
|
|
322
|
-
options: () => {
|
|
323
|
-
return queryParameters.map((item) => ({
|
|
324
|
-
label: item == null ? void 0 : item.label,
|
|
325
|
-
value: item == null ? void 0 : item.value
|
|
326
|
-
}));
|
|
418
|
+
filterLogic: {
|
|
419
|
+
type: "queryBuilder",
|
|
420
|
+
description: "Filter fetched entries. Defaults to fetch all entries.",
|
|
421
|
+
config: (_, ctx) => {
|
|
422
|
+
const fields = (ctx == null ? void 0 : ctx.strapiFields) || [];
|
|
423
|
+
return strapiFieldsToQueryBuilderConfig(fields, ctx == null ? void 0 : ctx.sampleData);
|
|
327
424
|
}
|
|
328
425
|
}
|
|
329
426
|
}
|
|
@@ -338,15 +435,37 @@ var queryStrapiMeta = {
|
|
|
338
435
|
})
|
|
339
436
|
};
|
|
340
437
|
}
|
|
438
|
+
const fetchOpts = {
|
|
439
|
+
host: strapiOpts.host,
|
|
440
|
+
token: strapiOpts.token,
|
|
441
|
+
collection: strapiOpts.collection
|
|
442
|
+
};
|
|
341
443
|
return {
|
|
342
|
-
dataKey: JSON.stringify(
|
|
444
|
+
dataKey: JSON.stringify(fetchOpts),
|
|
343
445
|
fetcher: () => __async(void 0, null, function* () {
|
|
344
|
-
const resp = yield queryStrapi(
|
|
446
|
+
const resp = yield queryStrapi(fetchOpts);
|
|
345
447
|
const collectionData = resp == null ? void 0 : resp.data;
|
|
346
448
|
if (!collectionData) {
|
|
347
449
|
return { strapiFields: [] };
|
|
348
450
|
}
|
|
349
|
-
|
|
451
|
+
const sampleData = {};
|
|
452
|
+
const fields = extractFilterableFields(collectionData);
|
|
453
|
+
const itemsToCheck = collectionData.slice(0, 10);
|
|
454
|
+
for (const field of fields) {
|
|
455
|
+
for (const item of itemsToCheck) {
|
|
456
|
+
if (item) {
|
|
457
|
+
const value = getFieldValue(item, field);
|
|
458
|
+
if (value !== null && value !== void 0) {
|
|
459
|
+
sampleData[field] = value;
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
strapiFields: fields,
|
|
467
|
+
sampleData
|
|
468
|
+
};
|
|
350
469
|
})
|
|
351
470
|
};
|
|
352
471
|
}
|
|
@@ -356,6 +475,17 @@ function queryStrapi(_0) {
|
|
|
356
475
|
host,
|
|
357
476
|
token,
|
|
358
477
|
collection,
|
|
478
|
+
filterLogic
|
|
479
|
+
}) {
|
|
480
|
+
return _queryStrapi({ host, token, collection, filterLogic });
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
function _queryStrapi(_0) {
|
|
484
|
+
return __async(this, arguments, function* ({
|
|
485
|
+
host,
|
|
486
|
+
token,
|
|
487
|
+
collection,
|
|
488
|
+
filterLogic,
|
|
359
489
|
filterField,
|
|
360
490
|
filterValue,
|
|
361
491
|
filterParameter
|
|
@@ -368,15 +498,20 @@ function queryStrapi(_0) {
|
|
|
368
498
|
if (token) {
|
|
369
499
|
requestInit.headers = { Authorization: "Bearer " + token };
|
|
370
500
|
}
|
|
371
|
-
|
|
372
|
-
|
|
501
|
+
let filters = {};
|
|
502
|
+
if (filterLogic) {
|
|
503
|
+
filters = rulesLogicToStrapiFilters(filterLogic);
|
|
504
|
+
} else if (filterField && filterParameter && filterValue) {
|
|
505
|
+
filters = {
|
|
373
506
|
[filterField]: {
|
|
374
507
|
[filterParameter]: filterValue
|
|
375
508
|
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
const queryParams = import_qs.default.stringify({
|
|
512
|
+
filters,
|
|
378
513
|
populate: "*"
|
|
379
|
-
})
|
|
514
|
+
});
|
|
380
515
|
const resp = yield fetch(`${query}?${queryParams}`, requestInit);
|
|
381
516
|
const data = yield resp.json();
|
|
382
517
|
return transformMediaUrls(data, host);
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../src/query-strapi.tsx", "../src/strapi-compat.ts", "../src/utils.ts"],
|
|
4
|
-
"sourcesContent": ["import registerFunction, {\n CustomFunctionMeta,\n} from \"@plasmicapp/host/registerFunction\";\nimport { queryStrapi, queryStrapiMeta } from \"./query-strapi\";\n\nexport function registerStrapi(loader?: { registerFunction: any }) {\n function _registerFunction<T extends (...args: any[]) => any>(\n fn: T,\n meta: CustomFunctionMeta<T>\n ) {\n if (loader) {\n loader.registerFunction(fn, meta);\n } else {\n registerFunction(fn, meta);\n }\n }\n\n _registerFunction(queryStrapi, queryStrapiMeta);\n}\n\nexport { queryStrapi };\n\n// used by @plasmicpkgs/plasmic-strapi\nexport {\n getItemKeys as _getFieldKeys,\n getFieldValue as _getFieldValue,\n getId as _getId,\n getMediaAttributes as _getMediaAttributes,\n isStrapiItem as _isStrapiItem,\n isStrapiItemArray as _isStrapiItemArray,\n isStrapiPrimitive as _isStrapiPrimitive,\n} from \"./strapi-compat\";\nexport {\n extractDisplayableFields as _extractDisplayableFields,\n extractFilterableFields as _extractFilterableFields,\n isImage as _isImage,\n queryParameters as _queryParameters,\n} from \"./utils\";\n", "import { CustomFunctionMeta } from \"@plasmicapp/host/registerFunction\";\nimport qs from \"qs\";\nimport { StrapiQueryResponse } from \"./strapi-compat\";\nimport {\n extractFilterableFields,\n normalizeUrl,\n queryParameters,\n transformMediaUrls,\n} from \"./utils\";\n\nexport const queryStrapiMeta: CustomFunctionMeta<typeof queryStrapi> = {\n name: \"queryStrapi\",\n displayName: \"Query Strapi\",\n description: \"Query a Strapi collection\",\n importPath: \"@plasmicpkgs/strapi\",\n params: [\n {\n name: \"opts\",\n type: \"object\",\n display: \"flatten\",\n fields: {\n host: {\n type: \"string\",\n description: \"The Strapi host URL (e.g., https://example.com)\",\n },\n token: {\n type: \"string\",\n description:\n \"The Strapi API token (optional, for authenticated requests)\",\n },\n collection: {\n type: \"string\",\n description: \"The name of the Strapi collection to query\",\n },\n filterField: {\n type: \"choice\",\n options: (_, ctx) => {\n return ctx?.strapiFields;\n },\n },\n filterValue: {\n type: \"string\",\n description:\n \"The value to filter by (optional, if you want to filter results)\",\n },\n filterParameter: {\n type: \"choice\",\n description:\n \"The parameter for filtering (e.g., 'eq', 'contains', etc.) (optional)\",\n options: () => {\n return queryParameters.map((item: any) => ({\n label: item?.label,\n value: item?.value,\n }));\n },\n },\n },\n },\n ],\n fnContext: (strapiOpts?: QueryStrapiOpts) => {\n if (!strapiOpts?.host) {\n return {\n dataKey: \"\",\n fetcher: async () => {\n return {};\n },\n };\n }\n return {\n dataKey: JSON.stringify(strapiOpts),\n fetcher: async () => {\n const resp = await queryStrapi(strapiOpts);\n const collectionData = resp?.data;\n if (!collectionData) {\n return { strapiFields: [] };\n }\n\n return { strapiFields: extractFilterableFields(collectionData) };\n },\n };\n },\n};\n\nexport interface QueryStrapiOpts {\n host?: string;\n token?: string;\n collection?: string;\n filterField?: string;\n filterValue?: string;\n filterParameter?: string;\n}\n\nexport async function queryStrapi({\n host,\n token,\n collection,\n filterField,\n filterValue,\n filterParameter,\n}: QueryStrapiOpts): Promise<StrapiQueryResponse | null> {\n if (!host || !collection) {\n return null;\n }\n\n const query = normalizeUrl(host) + \"/api/\" + collection.trim();\n\n const requestInit: RequestInit = { method: \"GET\" };\n if (token) {\n requestInit.headers = { Authorization: \"Bearer \" + token };\n }\n\n const queryParams = qs.stringify({\n ...(filterField && filterParameter && filterValue\n ? {\n filters: {\n [filterField]: {\n [filterParameter]: filterValue,\n },\n },\n }\n : {}),\n populate: \"*\",\n });\n\n const resp = await fetch(`${query}?${queryParams}`, requestInit);\n const data = await resp.json();\n\n // Transform all relative media URLs to absolute URLs\n return transformMediaUrls(data, host);\n}\n", "// This file contains Strapi code for handling v4/v5 compatibility.\n// https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/new-response-format\n\nexport interface StrapiQueryResponse {\n data: StrapiItem[];\n meta: {\n pagination: {\n page: number;\n pageSize: number;\n pageCount: number;\n total: number;\n };\n };\n}\n\n/** A primitive, item, item array, or null (for optional fields). */\nexport type StrapiValue =\n | boolean\n | number\n | string\n | StrapiItem\n | ReadonlyArray<StrapiItem>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV4 =\n | boolean\n | number\n | string\n | { data: StrapiItemV4 | ReadonlyArray<StrapiItemV4> }\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV5 =\n | boolean\n | number\n | string\n | StrapiItemV5\n | ReadonlyArray<StrapiItemV5>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\n\n/** A content item or media item. */\nexport type StrapiItem = StrapiItemV4 | StrapiItemV5;\nexport interface StrapiItemV4 {\n id: number;\n attributes: {\n [attribute: string]: StrapiValueV4;\n };\n}\nexport interface StrapiItemV5 {\n documentId: string;\n [attribute: string]: StrapiValueV5;\n}\nfunction isV5Item(item: StrapiItem): item is StrapiItemV5 {\n return \"documentId\" in item;\n}\n\nfunction isV4Item(item: StrapiItem): item is StrapiItemV5 {\n return \"id\" in item && \"attributes\" in item;\n}\n\n/** @internal */\nexport function isStrapiPrimitive(\n value: StrapiValue | undefined\n): value is boolean | number | string {\n const type = typeof value;\n return type === \"boolean\" || type === \"number\" || type === \"string\";\n}\n/** @internal */\nexport function isStrapiItem(\n item: StrapiValue | undefined\n): item is StrapiItem {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) {\n return false;\n }\n // The object must be a valid v5 or v4 item\n return isV5Item(item as any) || isV4Item(item as any);\n}\n/** @internal */\nexport function isStrapiItemArray(\n value: StrapiValue | undefined\n): value is ReadonlyArray<StrapiItem> {\n return typeof value === \"object\" && value !== null && Array.isArray(value);\n}\n\n/** @internal */\nexport function getId(item: StrapiItem): string {\n if (isV5Item(item)) {\n return item.documentId;\n } else {\n // v4\n return item.id.toString();\n }\n}\n\n/** @internal */\nexport function getItemKeys(item: StrapiItem) {\n if (isV5Item(item)) {\n return Object.keys(item).filter((key) => key !== \"documentId\");\n } else {\n // v4\n return Object.keys(item.attributes);\n }\n}\n\n/**\n * Gets the value, or undefined if the field key does not exist.\n * @internal\n */\nexport function getFieldValue(\n item: StrapiItem,\n key: string\n): StrapiValue | undefined {\n if (isV5Item(item)) {\n return item[key];\n } else {\n // v4\n const value = item.attributes[key];\n if (value === null || value === undefined) {\n return value;\n }\n switch (typeof value) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n return value;\n case \"object\":\n if (value && \"data\" in value) {\n return value.data;\n } else {\n return undefined;\n }\n default:\n return undefined;\n }\n }\n}\n\n/** This includes any asset such as image, video, audio, file */\nexport interface StrapiMediaAttributes {\n url: string;\n mime: string;\n ext: string;\n size: number;\n // width and height are null for non-image media (e.g. audio files)\n width: number | null;\n height: number | null;\n formats?: { [key: string]: Omit<StrapiMediaAttributes, \"formats\"> };\n // Added by transformMediaUrls - absolute URL with host prepended\n absoluteUrl?: string;\n}\n\nexport interface StrapiImageAttribute extends StrapiMediaAttributes {\n width: number;\n height: number;\n}\n/**\n * Gets media attributes if it's a media item.\n *\n * This is the small subset of the fields that we care about.\n *\n * @internal\n */\nexport function getMediaAttributes(\n value: StrapiItem\n): StrapiMediaAttributes | undefined {\n const attributes = isV5Item(value) ? value : value.attributes;\n if (\n \"url\" in attributes &&\n \"mime\" in attributes &&\n \"ext\" in attributes &&\n \"size\" in attributes\n ) {\n return attributes as { [attribute: string]: any } as StrapiMediaAttributes;\n } else {\n return undefined;\n }\n}\n", "import {\n StrapiImageAttribute,\n StrapiItem,\n StrapiMediaAttributes,\n StrapiQueryResponse,\n getFieldValue,\n getItemKeys,\n getMediaAttributes,\n isStrapiItem,\n isStrapiPrimitive,\n} from \"./strapi-compat\";\n\n/**\n * https://docs-v4.strapi.io/dev-docs/api/entity-service/filter\n * @internal\n */\nexport const queryParameters = [\n {\n value: \"$eq\",\n label: \"Equal\",\n },\n {\n value: \"$ne\",\n label: \"Not equal\",\n },\n {\n value: \"$lt\",\n label: \"Less than\",\n },\n {\n value: \"$lte\",\n label: \"Less than or equal to\",\n },\n {\n value: \"$gt\",\n label: \"Greater than\",\n },\n {\n value: \"$gte\",\n label: \"Greater than or equal to\",\n },\n {\n value: \"$in\",\n label: \"Included in an array\",\n },\n {\n value: \"$notIn\",\n label: \"Not included in an array\",\n },\n {\n value: \"$contains\",\n label: \"Contains\",\n },\n {\n value: \"$notContains\",\n label: \"Does not contain\",\n },\n];\n\n/**\n * Checks if the media attribute contains an image media\n * @internal\n */\nexport function isImage(\n mediaAttr: StrapiMediaAttributes\n): mediaAttr is StrapiImageAttribute {\n return mediaAttr?.mime.startsWith(\"image\");\n}\n\n/**\n * Removes leading and trailing slash and whitespace characters from a URL\n * @internal\n */\nexport function normalizeUrl(url: string): string {\n return (\n url\n .trim()\n // remove leading slash\n .replace(/^\\/+/, \"\")\n // remove leading trailing\n .replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Extracts fields whose types can be filtered in Plasmic.\n * @internal\n */\nexport function extractFilterableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(filterableFields)));\n } else {\n return filterableFields(items);\n }\n}\n\nfunction filterableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return isStrapiPrimitive(value);\n });\n}\n\n/**\n * Extracts fields whose types can be displayed in Plasmic.\n * @internal\n */\nexport function extractDisplayableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(displayableFields)));\n } else {\n return displayableFields(items);\n }\n}\n\nfunction displayableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return (\n isStrapiPrimitive(value) ||\n (isStrapiItem(value) && getMediaAttributes(value))\n );\n });\n}\n\n/**\n * Traverses @param data and adds an absoluteUrl field to all media items by prepending the @param host to the url\n * @internal\n */\nexport function transformMediaUrls(\n data: StrapiQueryResponse,\n host: string\n): StrapiQueryResponse {\n if (data === null || data === undefined) {\n return data;\n }\n\n const normalizedHost = normalizeUrl(host);\n\n /**\n * Converts a relative URL to absolute by prepending the host.\n * If URL is already absolute, returns it unchanged.\n */\n function makeAbsoluteUrl(url: string): string {\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n return url;\n }\n return normalizedHost + \"/\" + normalizeUrl(url);\n }\n\n /**\n * Adds absoluteUrl to a media item and its format variations\n */\n function transformMediaItem(mediaAttrs: StrapiMediaAttributes): void {\n mediaAttrs.absoluteUrl = makeAbsoluteUrl(mediaAttrs.url);\n\n // Transform format variations (thumbnail, small, medium, large, etc.)\n if (mediaAttrs.formats && typeof mediaAttrs.formats === \"object\") {\n for (const formatKey of Object.keys(mediaAttrs.formats)) {\n transformMediaItem(mediaAttrs.formats[formatKey]);\n }\n }\n }\n\n /**\n * Recursively traverses a Strapi item and transforms all nested media\n */\n function transformStrapiItem(item: StrapiItem): void {\n const mediaAttrs = getMediaAttributes(item);\n\n if (mediaAttrs) {\n // This item is itself a media item\n transformMediaItem(mediaAttrs);\n } else {\n // This item contains other fields that might be media\n for (const key of getItemKeys(item)) {\n const fieldValue = getFieldValue(item, key);\n transformValue(fieldValue);\n }\n }\n }\n\n /**\n * Recursively traverses and transforms media URLs in any value\n */\n function transformValue(value: any): any {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (isStrapiPrimitive(value)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n value.forEach(transformValue);\n return value;\n }\n\n if (isStrapiItem(value)) {\n transformStrapiItem(value);\n } else if (typeof value === \"object\") {\n // Plain object - traverse its properties\n for (const key of Object.keys(value)) {\n transformValue(value[key]);\n }\n }\n\n return value;\n }\n\n return transformValue(data);\n}\n"],
|
|
5
|
-
"mappings": "
|
|
3
|
+
"sources": ["../src/index.ts", "../src/query-strapi.tsx", "../src/strapi-compat.ts", "../src/utils.ts", "../src/where.ts"],
|
|
4
|
+
"sourcesContent": ["import registerFunction, {\n CustomFunctionMeta,\n} from \"@plasmicapp/host/registerFunction\";\nimport { _queryStrapi, queryStrapi, queryStrapiMeta } from \"./query-strapi\";\n\nexport function registerStrapi(loader?: { registerFunction: any }) {\n function _registerFunction<T extends (...args: any[]) => any>(\n fn: T,\n meta: CustomFunctionMeta<T>\n ) {\n if (loader) {\n loader.registerFunction(fn, meta);\n } else {\n registerFunction(fn, meta);\n }\n }\n\n _registerFunction(queryStrapi, queryStrapiMeta);\n}\n\nexport {\n // used by @plasmicpkgs/plasmic-strapi\n _queryStrapi,\n queryStrapi,\n};\n\n// used by @plasmicpkgs/plasmic-strapi\nexport {\n getItemKeys as _getFieldKeys,\n getFieldValue as _getFieldValue,\n getId as _getId,\n getMediaAttributes as _getMediaAttributes,\n isStrapiItem as _isStrapiItem,\n isStrapiItemArray as _isStrapiItemArray,\n isStrapiPrimitive as _isStrapiPrimitive,\n} from \"./strapi-compat\";\nexport {\n extractDisplayableFields as _extractDisplayableFields,\n extractFilterableFields as _extractFilterableFields,\n isImage as _isImage,\n queryParameters as _queryParameters,\n} from \"./utils\";\n", "import { CustomFunctionMeta } from \"@plasmicapp/host/registerFunction\";\nimport type { RulesLogic } from \"json-logic-js\";\nimport qs from \"qs\";\nimport { getFieldValue, StrapiQueryResponse } from \"./strapi-compat\";\nimport {\n extractFilterableFields,\n normalizeUrl,\n transformMediaUrls,\n} from \"./utils\";\nimport {\n rulesLogicToStrapiFilters,\n strapiFieldsToQueryBuilderConfig,\n} from \"./where\";\n\nexport const queryStrapiMeta: CustomFunctionMeta<typeof queryStrapi> = {\n name: \"queryStrapi\",\n displayName: \"Query Strapi\",\n description: \"Query a Strapi collection\",\n importPath: \"@plasmicpkgs/strapi\",\n params: [\n {\n name: \"opts\",\n type: \"object\",\n display: \"flatten\",\n fields: {\n host: {\n type: \"string\",\n description: \"The Strapi host URL (e.g., https://example.com)\",\n },\n token: {\n type: \"string\",\n description:\n \"The Strapi API token (optional, for authenticated requests)\",\n },\n collection: {\n type: \"string\",\n description: \"The name of the Strapi collection to query\",\n },\n filterLogic: {\n type: \"queryBuilder\",\n description: \"Filter fetched entries. Defaults to fetch all entries.\",\n config: (_: any, ctx: any) => {\n const fields = ctx?.strapiFields || [];\n return strapiFieldsToQueryBuilderConfig(fields, ctx?.sampleData);\n },\n },\n },\n },\n ],\n fnContext: (strapiOpts?: QueryStrapiOpts) => {\n if (!strapiOpts?.host) {\n return {\n dataKey: \"\",\n fetcher: async () => {\n return {};\n },\n };\n }\n // Exclude filterLogic from dataKey to prevent refetching when user types in query builder\n // The fields and sampleData should only depend on host, token, and collection\n const fetchOpts: QueryStrapiOpts = {\n host: strapiOpts.host,\n token: strapiOpts.token,\n collection: strapiOpts.collection,\n };\n return {\n dataKey: JSON.stringify(fetchOpts),\n fetcher: async () => {\n const resp = await queryStrapi(fetchOpts);\n const collectionData = resp?.data;\n if (!collectionData) {\n return { strapiFields: [] };\n }\n\n // Extract field values from multiple items for type inference\n // Check up to 10 items to find non-null values for each field\n const sampleData: Record<string, any> = {};\n const fields = extractFilterableFields(collectionData);\n const itemsToCheck = collectionData.slice(0, 10);\n // For each field, find the first non-null value across multiple items\n for (const field of fields) {\n for (const item of itemsToCheck) {\n if (item) {\n const value = getFieldValue(item, field);\n if (value !== null && value !== undefined) {\n sampleData[field] = value;\n break;\n }\n }\n }\n }\n\n return {\n strapiFields: fields,\n sampleData,\n };\n },\n };\n },\n};\n\n// Simplified filter props only intended for use by the deprecated StrapiCollection component\nexport interface StrapiQueryOldFilterProps {\n filterField?: string;\n filterValue?: string;\n filterParameter?: string;\n}\n\nexport interface QueryStrapiOpts {\n host?: string;\n token?: string;\n collection?: string;\n /**\n * Filter logic using JSON Logic format to filter Strapi entries.\n * See {@link https://www.npmjs.com/package/@types/json-logic-js?activeTab=readme}\n */\n filterLogic?: RulesLogic;\n}\n\n/**\n * Query a Strapi collection with optional filtering.\n *\n * @param opts - Query options including host, token, collection, and filter logic\n * @returns Promise resolving to the Strapi query response or null if required params are missing\n *\n * @example\n * ```ts\n * // Fetch all entries\n * const result = await queryStrapi({\n * host: 'https://api.example.com',\n * token: 'your-api-token',\n * collection: 'articles'\n * });\n *\n * // Fetch with filter\n * const filtered = await queryStrapi({\n * host: 'https://api.example.com',\n * token: 'your-api-token',\n * collection: 'articles',\n * filterLogic: { \"==\": [{ var: \"status\" }, \"published\"] }\n * });\n * ```\n */\nexport async function queryStrapi({\n host,\n token,\n collection,\n filterLogic,\n}: QueryStrapiOpts): Promise<StrapiQueryResponse | null> {\n return _queryStrapi({ host, token, collection, filterLogic });\n}\n\n/**\n * Query Strapi with simplified filter props.\n *\n * @deprecated Use {@link queryStrapi} with `filterLogic` parameter instead.\n *\n * @example\n * ```ts\n * // Old way (deprecated)\n * _queryStrapi({ filterField: 'name', filterValue: 'John' })\n *\n * // New way\n * queryStrapi({\n * filterLogic: {\"==\": [{ var: \"name\" }, \"John\"]}\n * })\n * ```\n */\nexport async function _queryStrapi({\n host,\n token,\n collection,\n filterLogic,\n filterField,\n filterValue,\n filterParameter,\n}: QueryStrapiOpts &\n StrapiQueryOldFilterProps): Promise<StrapiQueryResponse | null> {\n if (!host || !collection) {\n return null;\n }\n\n const query = normalizeUrl(host) + \"/api/\" + collection.trim();\n\n const requestInit: RequestInit = { method: \"GET\" };\n if (token) {\n requestInit.headers = { Authorization: \"Bearer \" + token };\n }\n\n let filters: Record<string, any> = {};\n if (filterLogic) {\n filters = rulesLogicToStrapiFilters(filterLogic);\n } else if (filterField && filterParameter && filterValue) {\n filters = {\n [filterField]: {\n [filterParameter]: filterValue,\n },\n };\n }\n\n // Build query parameters for Strapi REST API\n // Strapi uses nested query parameters like: filters[$and][0][field][$eq]=value\n const queryParams = qs.stringify({\n filters,\n populate: \"*\",\n });\n\n const resp = await fetch(`${query}?${queryParams}`, requestInit);\n const data = await resp.json();\n\n // Transform all relative media URLs to absolute URLs\n return transformMediaUrls(data, host);\n}\n", "// This file contains Strapi code for handling v4/v5 compatibility.\n// https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/new-response-format\n\nexport interface StrapiQueryResponse {\n data: StrapiItem[];\n meta: {\n pagination: {\n page: number;\n pageSize: number;\n pageCount: number;\n total: number;\n };\n };\n}\n\n/** A primitive, item, item array, or null (for optional fields). */\nexport type StrapiValue =\n | boolean\n | number\n | string\n | StrapiItem\n | ReadonlyArray<StrapiItem>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV4 =\n | boolean\n | number\n | string\n | { data: StrapiItemV4 | ReadonlyArray<StrapiItemV4> }\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\ntype StrapiValueV5 =\n | boolean\n | number\n | string\n | StrapiItemV5\n | ReadonlyArray<StrapiItemV5>\n | ReadonlyArray<any> // For rich text content, JSON fields, etc.\n | Record<string, any> // For JSON fields, metadata objects, etc.\n | null;\n\n/** A content item or media item. */\nexport type StrapiItem = StrapiItemV4 | StrapiItemV5;\nexport interface StrapiItemV4 {\n id: number;\n attributes: {\n [attribute: string]: StrapiValueV4;\n };\n}\nexport interface StrapiItemV5 {\n documentId: string;\n [attribute: string]: StrapiValueV5;\n}\nfunction isV5Item(item: StrapiItem): item is StrapiItemV5 {\n return \"documentId\" in item;\n}\n\nfunction isV4Item(item: StrapiItem): item is StrapiItemV5 {\n return \"id\" in item && \"attributes\" in item;\n}\n\n/** @internal */\nexport function isStrapiPrimitive(\n value: StrapiValue | undefined\n): value is boolean | number | string {\n const type = typeof value;\n return type === \"boolean\" || type === \"number\" || type === \"string\";\n}\n/** @internal */\nexport function isStrapiItem(\n item: StrapiValue | undefined\n): item is StrapiItem {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) {\n return false;\n }\n // The object must be a valid v5 or v4 item\n return isV5Item(item as any) || isV4Item(item as any);\n}\n/** @internal */\nexport function isStrapiItemArray(\n value: StrapiValue | undefined\n): value is ReadonlyArray<StrapiItem> {\n return typeof value === \"object\" && value !== null && Array.isArray(value);\n}\n\n/** @internal */\nexport function getId(item: StrapiItem): string {\n if (isV5Item(item)) {\n return item.documentId;\n } else {\n // v4\n return item.id.toString();\n }\n}\n\n/** @internal */\nexport function getItemKeys(item: StrapiItem) {\n if (isV5Item(item)) {\n return Object.keys(item).filter((key) => key !== \"documentId\");\n } else {\n // v4\n return Object.keys(item.attributes);\n }\n}\n\n/**\n * Gets the value, or undefined if the field key does not exist.\n * @internal\n */\nexport function getFieldValue(\n item: StrapiItem,\n key: string\n): StrapiValue | undefined {\n if (isV5Item(item)) {\n return item[key];\n } else {\n // v4\n const value = item.attributes[key];\n if (value === null || value === undefined) {\n return value;\n }\n switch (typeof value) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n return value;\n case \"object\":\n if (value && \"data\" in value) {\n return value.data;\n } else {\n return undefined;\n }\n default:\n return undefined;\n }\n }\n}\n\n/** This includes any asset such as image, video, audio, file */\nexport interface StrapiMediaAttributes {\n url: string;\n mime: string;\n ext: string;\n size: number;\n // width and height are null for non-image media (e.g. audio files)\n width: number | null;\n height: number | null;\n formats?: { [key: string]: Omit<StrapiMediaAttributes, \"formats\"> };\n // Added by transformMediaUrls - absolute URL with host prepended\n absoluteUrl?: string;\n}\n\nexport interface StrapiImageAttribute extends StrapiMediaAttributes {\n width: number;\n height: number;\n}\n/**\n * Gets media attributes if it's a media item.\n *\n * This is the small subset of the fields that we care about.\n *\n * @internal\n */\nexport function getMediaAttributes(\n value: StrapiItem\n): StrapiMediaAttributes | undefined {\n const attributes = isV5Item(value) ? value : value.attributes;\n if (\n \"url\" in attributes &&\n \"mime\" in attributes &&\n \"ext\" in attributes &&\n \"size\" in attributes\n ) {\n return attributes as { [attribute: string]: any } as StrapiMediaAttributes;\n } else {\n return undefined;\n }\n}\n", "import {\n StrapiImageAttribute,\n StrapiItem,\n StrapiMediaAttributes,\n StrapiQueryResponse,\n getFieldValue,\n getItemKeys,\n getMediaAttributes,\n isStrapiItem,\n isStrapiPrimitive,\n} from \"./strapi-compat\";\n\n/**\n * https://docs-v4.strapi.io/dev-docs/api/entity-service/filter\n * @internal\n */\nexport const queryParameters = [\n {\n value: \"$eq\",\n label: \"Equal\",\n },\n {\n value: \"$ne\",\n label: \"Not equal\",\n },\n {\n value: \"$lt\",\n label: \"Less than\",\n },\n {\n value: \"$lte\",\n label: \"Less than or equal to\",\n },\n {\n value: \"$gt\",\n label: \"Greater than\",\n },\n {\n value: \"$gte\",\n label: \"Greater than or equal to\",\n },\n {\n value: \"$in\",\n label: \"Included in an array\",\n },\n {\n value: \"$notIn\",\n label: \"Not included in an array\",\n },\n {\n value: \"$contains\",\n label: \"Contains\",\n },\n {\n value: \"$notContains\",\n label: \"Does not contain\",\n },\n];\n\n/**\n * Checks if the media attribute contains an image media\n * @internal\n */\nexport function isImage(\n mediaAttr: StrapiMediaAttributes\n): mediaAttr is StrapiImageAttribute {\n return mediaAttr?.mime.startsWith(\"image\");\n}\n\n/**\n * Removes leading and trailing slash and whitespace characters from a URL\n * @internal\n */\nexport function normalizeUrl(url: string): string {\n return (\n url\n .trim()\n // remove leading slash\n .replace(/^\\/+/, \"\")\n // remove leading trailing\n .replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Extracts fields whose types can be filtered in Plasmic.\n * @internal\n */\nexport function extractFilterableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(filterableFields)));\n } else {\n return filterableFields(items);\n }\n}\n\nfunction filterableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return isStrapiPrimitive(value);\n });\n}\n\n/**\n * Extracts fields whose types can be displayed in Plasmic.\n * @internal\n */\nexport function extractDisplayableFields(\n items: StrapiItem | StrapiItem[]\n): string[] {\n if (Array.isArray(items)) {\n return Array.from(new Set(items.flatMap(displayableFields)));\n } else {\n return displayableFields(items);\n }\n}\n\nfunction displayableFields(item: StrapiItem): string[] {\n return getItemKeys(item).filter((key) => {\n const value = getFieldValue(item, key);\n return (\n isStrapiPrimitive(value) ||\n (isStrapiItem(value) && getMediaAttributes(value))\n );\n });\n}\n\n/**\n * Traverses @param data and adds an absoluteUrl field to all media items by prepending the @param host to the url\n * @internal\n */\nexport function transformMediaUrls(\n data: StrapiQueryResponse,\n host: string\n): StrapiQueryResponse {\n if (data === null || data === undefined) {\n return data;\n }\n\n const normalizedHost = normalizeUrl(host);\n\n /**\n * Converts a relative URL to absolute by prepending the host.\n * If URL is already absolute, returns it unchanged.\n */\n function makeAbsoluteUrl(url: string): string {\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n return url;\n }\n return normalizedHost + \"/\" + normalizeUrl(url);\n }\n\n /**\n * Adds absoluteUrl to a media item and its format variations\n */\n function transformMediaItem(mediaAttrs: StrapiMediaAttributes): void {\n mediaAttrs.absoluteUrl = makeAbsoluteUrl(mediaAttrs.url);\n\n // Transform format variations (thumbnail, small, medium, large, etc.)\n if (mediaAttrs.formats && typeof mediaAttrs.formats === \"object\") {\n for (const formatKey of Object.keys(mediaAttrs.formats)) {\n transformMediaItem(mediaAttrs.formats[formatKey]);\n }\n }\n }\n\n /**\n * Recursively traverses a Strapi item and transforms all nested media\n */\n function transformStrapiItem(item: StrapiItem): void {\n const mediaAttrs = getMediaAttributes(item);\n\n if (mediaAttrs) {\n // This item is itself a media item\n transformMediaItem(mediaAttrs);\n } else {\n // This item contains other fields that might be media\n for (const key of getItemKeys(item)) {\n const fieldValue = getFieldValue(item, key);\n transformValue(fieldValue);\n }\n }\n }\n\n /**\n * Recursively traverses and transforms media URLs in any value\n */\n function transformValue(value: any): any {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (isStrapiPrimitive(value)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n value.forEach(transformValue);\n return value;\n }\n\n if (isStrapiItem(value)) {\n transformStrapiItem(value);\n } else if (typeof value === \"object\") {\n // Plain object - traverse its properties\n for (const key of Object.keys(value)) {\n transformValue(value[key]);\n }\n }\n\n return value;\n }\n\n return transformValue(data);\n}\n", "import type {\n Config,\n Field,\n FieldOrGroup,\n} from \"@react-awesome-query-builder/core\";\nimport type { RulesLogic } from \"json-logic-js\";\n\n/**\n * Maps Strapi collection fields to react-awesome-query-builder config.\n *\n * The result will be handled by {@link rulesLogicToStrapiFilters}.\n * Make sure it supports all operators defined here.\n */\nexport function strapiFieldsToQueryBuilderConfig(\n fields: string[],\n sampleData?: any\n): Pick<Config, \"fields\"> {\n const qbFields: { [key: string]: FieldOrGroup } = {};\n for (const field of fields) {\n // Try to get sample value from sampleData to infer type\n const sampleValue = sampleData?.[field];\n const qbField = strapiFieldToQueryBuilderField(field, sampleValue);\n if (qbField) {\n qbFields[field] = qbField;\n }\n }\n return {\n fields: qbFields,\n };\n}\n\n/**\n * Maps a Strapi field name to a query builder field configuration.\n *\n * Infers field type from field name patterns and sample values if provided.\n */\nfunction strapiFieldToQueryBuilderField(\n fieldName: string,\n sampleValue?: unknown\n): Field | undefined {\n const label = fieldName;\n\n // Infer type from sample value if provided\n if (typeof sampleValue === \"number\") {\n return {\n type: \"number\",\n label,\n operators: [\n \"equal\",\n \"not_equal\",\n \"less\",\n \"less_or_equal\",\n \"greater\",\n \"greater_or_equal\",\n \"is_null\",\n \"is_not_null\",\n ],\n };\n }\n if (typeof sampleValue === \"boolean\") {\n return {\n type: \"boolean\",\n label,\n };\n }\n if (typeof sampleValue === \"string\") {\n if (!isNaN(new Date(sampleValue).getTime())) {\n return {\n type: \"datetime\",\n label,\n operators: [\n \"equal\",\n \"not_equal\",\n \"less\",\n \"less_or_equal\",\n \"greater\",\n \"greater_or_equal\",\n \"is_null\",\n \"is_not_null\",\n ],\n };\n }\n\n return {\n type: \"text\",\n label,\n operators: [\n \"equal\",\n \"not_equal\",\n \"like\",\n \"not_like\",\n \"is_null\",\n \"is_not_null\",\n ],\n };\n }\n\n return undefined;\n}\n\n/**\n * Maps JsonLogic to Strapi API filters format.\n *\n * See also:\n * - https://docs.strapi.io/cms/api/rest/filters\n */\nexport function rulesLogicToStrapiFilters(logic: RulesLogic | undefined): any {\n if (logic === null || logic === undefined) {\n return undefined;\n } else if (typeof logic !== \"object\") {\n throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);\n } else if (\"and\" in logic) {\n return {\n $and: logic[\"and\"].map(rulesLogicToStrapiFilters),\n };\n } else if (\"or\" in logic) {\n return {\n $or: logic[\"or\"].map(rulesLogicToStrapiFilters),\n };\n } else if (\"!\" in logic) {\n return {\n $not: rulesLogicToStrapiFilters(logic[\"!\"]),\n };\n } else if (\"==\" in logic) {\n const [{ var: field }, operand] = logic[\"==\"] as [{ var: string }, unknown];\n if (operand === null) {\n return { [field]: { $null: true } };\n }\n return {\n [field]: { $eq: operand },\n };\n } else if (\"!=\" in logic) {\n const [{ var: field }, operand] = logic[\"!=\"] as [{ var: string }, unknown];\n if (operand === null) {\n return { [field]: { $notNull: true } };\n }\n return {\n [field]: { $ne: operand },\n };\n // Map in operator to Strapi filters format:\n // JsonLogic: { \"in\": [\"Mairi\", { \"var\": \"name\" }] }\n // Strapi filters: { \"name\": { $contains: \"Mairi\" } }\n } else if (\"in\" in logic) {\n const [operand, { var: field }] = logic[\"in\"] as [string, { var: string }];\n return {\n [field]: { $contains: operand },\n };\n } else {\n // Map JsonLogic to Strapi filters format:\n // JsonLogic: { \"<=\": [{ \"var\": \"age\" }, 18] }\n // Strapi filters: { \"age\": { \"$lte\": 18 } }\n const [key, value] = Object.entries(logic)[0];\n const apiOp: string | undefined = operatorMapping[key];\n if (apiOp) {\n const [{ var: field }, operand] = value as [{ var: string }, unknown];\n return { [field]: { [apiOp]: operand } };\n }\n\n throw new Error(`unexpected logic: ${JSON.stringify(logic)}`);\n }\n}\n\n/** Maps JsonLogic operator to Strapi filter operator. */\nconst operatorMapping: Record<string, string> = {\n \"<\": \"$lt\",\n \"<=\": \"$lte\",\n \">\": \"$gt\",\n \">=\": \"$gte\",\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAEO;;;ACAP,gBAAe;;;ACqDf,SAAS,SAAS,MAAwC;AACxD,SAAO,gBAAgB;AACzB;AAEA,SAAS,SAAS,MAAwC;AACxD,SAAO,QAAQ,QAAQ,gBAAgB;AACzC;AAGO,SAAS,kBACd,OACoC;AACpC,QAAM,OAAO,OAAO;AACpB,SAAO,SAAS,aAAa,SAAS,YAAY,SAAS;AAC7D;AAEO,SAAS,aACd,MACoB;AACpB,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,MAAM,QAAQ,IAAI,GAAG;AACpE,WAAO;AAAA,EACT;AAEA,SAAO,SAAS,IAAW,KAAK,SAAS,IAAW;AACtD;AAEO,SAAS,kBACd,OACoC;AACpC,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK;AAC3E;AAGO,SAAS,MAAM,MAA0B;AAC9C,MAAI,SAAS,IAAI,GAAG;AAClB,WAAO,KAAK;AAAA,EACd,OAAO;AAEL,WAAO,KAAK,GAAG,SAAS;AAAA,EAC1B;AACF;AAGO,SAAS,YAAY,MAAkB;AAC5C,MAAI,SAAS,IAAI,GAAG;AAClB,WAAO,OAAO,KAAK,IAAI,EAAE,OAAO,CAAC,QAAQ,QAAQ,YAAY;AAAA,EAC/D,OAAO;AAEL,WAAO,OAAO,KAAK,KAAK,UAAU;AAAA,EACpC;AACF;AAMO,SAAS,cACd,MACA,KACyB;AACzB,MAAI,SAAS,IAAI,GAAG;AAClB,WAAO,KAAK,GAAG;AAAA,EACjB,OAAO;AAEL,UAAM,QAAQ,KAAK,WAAW,GAAG;AACjC,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,aAAO;AAAA,IACT;AACA,YAAQ,OAAO,OAAO;AAAA,MACpB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,YAAI,SAAS,UAAU,OAAO;AAC5B,iBAAO,MAAM;AAAA,QACf,OAAO;AACL,iBAAO;AAAA,QACT;AAAA,MACF;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACF;AA2BO,SAAS,mBACd,OACmC;AACnC,QAAM,aAAa,SAAS,KAAK,IAAI,QAAQ,MAAM;AACnD,MACE,SAAS,cACT,UAAU,cACV,SAAS,cACT,UAAU,YACV;AACA,WAAO;AAAA,EACT,OAAO;AACL,WAAO;AAAA,EACT;AACF;;;ACnKO,IAAM,kBAAkB;AAAA,EAC7B;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AACF;AAMO,SAAS,QACd,WACmC;AACnC,SAAO,uCAAW,KAAK,WAAW;AACpC;AAMO,SAAS,aAAa,KAAqB;AAChD,SACE,IACG,KAAK,EAEL,QAAQ,QAAQ,EAAE,EAElB,QAAQ,QAAQ,EAAE;AAEzB;AAMO,SAAS,wBACd,OACU;AACV,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,gBAAgB,CAAC,CAAC;AAAA,EAC5D,OAAO;AACL,WAAO,iBAAiB,KAAK;AAAA,EAC/B;AACF;AAEA,SAAS,iBAAiB,MAA4B;AACpD,SAAO,YAAY,IAAI,EAAE,OAAO,CAAC,QAAQ;AACvC,UAAM,QAAQ,cAAc,MAAM,GAAG;AACrC,WAAO,kBAAkB,KAAK;AAAA,EAChC,CAAC;AACH;AAMO,SAAS,yBACd,OACU;AACV,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,iBAAiB,CAAC,CAAC;AAAA,EAC7D,OAAO;AACL,WAAO,kBAAkB,KAAK;AAAA,EAChC;AACF;AAEA,SAAS,kBAAkB,MAA4B;AACrD,SAAO,YAAY,IAAI,EAAE,OAAO,CAAC,QAAQ;AACvC,UAAM,QAAQ,cAAc,MAAM,GAAG;AACrC,WACE,kBAAkB,KAAK,KACtB,aAAa,KAAK,KAAK,mBAAmB,KAAK;AAAA,EAEpD,CAAC;AACH;AAMO,SAAS,mBACd,MACA,MACqB;AACrB,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,aAAa,IAAI;AAMxC,WAAS,gBAAgB,KAAqB;AAC5C,QAAI,IAAI,WAAW,SAAS,KAAK,IAAI,WAAW,UAAU,GAAG;AAC3D,aAAO;AAAA,IACT;AACA,WAAO,iBAAiB,MAAM,aAAa,GAAG;AAAA,EAChD;AAKA,WAAS,mBAAmB,YAAyC;AACnE,eAAW,cAAc,gBAAgB,WAAW,GAAG;AAGvD,QAAI,WAAW,WAAW,OAAO,WAAW,YAAY,UAAU;AAChE,iBAAW,aAAa,OAAO,KAAK,WAAW,OAAO,GAAG;AACvD,2BAAmB,WAAW,QAAQ,SAAS,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAKA,WAAS,oBAAoB,MAAwB;AACnD,UAAM,aAAa,mBAAmB,IAAI;AAE1C,QAAI,YAAY;AAEd,yBAAmB,UAAU;AAAA,IAC/B,OAAO;AAEL,iBAAW,OAAO,YAAY,IAAI,GAAG;AACnC,cAAM,aAAa,cAAc,MAAM,GAAG;AAC1C,uBAAe,UAAU;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAKA,WAAS,eAAe,OAAiB;AACvC,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,aAAO;AAAA,IACT;AAEA,QAAI,kBAAkB,KAAK,GAAG;AAC5B,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,cAAc;AAC5B,aAAO;AAAA,IACT;AAEA,QAAI,aAAa,KAAK,GAAG;AACvB,0BAAoB,KAAK;AAAA,IAC3B,WAAW,OAAO,UAAU,UAAU;AAEpC,iBAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,uBAAe,MAAM,GAAG,CAAC;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,eAAe,IAAI;AAC5B;;;AC3MO,SAAS,iCACd,QACA,YACwB;AACxB,QAAM,WAA4C,CAAC;AACnD,aAAW,SAAS,QAAQ;AAE1B,UAAM,cAAc,yCAAa;AACjC,UAAM,UAAU,+BAA+B,OAAO,WAAW;AACjE,QAAI,SAAS;AACX,eAAS,KAAK,IAAI;AAAA,IACpB;AAAA,EACF;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,EACV;AACF;AAOA,SAAS,+BACP,WACA,aACmB;AACnB,QAAM,QAAQ;AAGd,MAAI,OAAO,gBAAgB,UAAU;AACnC,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,gBAAgB,WAAW;AACpC,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,gBAAgB,UAAU;AACnC,QAAI,CAAC,MAAM,IAAI,KAAK,WAAW,EAAE,QAAQ,CAAC,GAAG;AAC3C,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAQO,SAAS,0BAA0B,OAAoC;AAC5E,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT,WAAW,OAAO,UAAU,UAAU;AACpC,UAAM,IAAI,MAAM,qBAAqB,KAAK,UAAU,KAAK,GAAG;AAAA,EAC9D,WAAW,SAAS,OAAO;AACzB,WAAO;AAAA,MACL,MAAM,MAAM,KAAK,EAAE,IAAI,yBAAyB;AAAA,IAClD;AAAA,EACF,WAAW,QAAQ,OAAO;AACxB,WAAO;AAAA,MACL,KAAK,MAAM,IAAI,EAAE,IAAI,yBAAyB;AAAA,IAChD;AAAA,EACF,WAAW,OAAO,OAAO;AACvB,WAAO;AAAA,MACL,MAAM,0BAA0B,MAAM,GAAG,CAAC;AAAA,IAC5C;AAAA,EACF,WAAW,QAAQ,OAAO;AACxB,UAAM,CAAC,EAAE,KAAK,MAAM,GAAG,OAAO,IAAI,MAAM,IAAI;AAC5C,QAAI,YAAY,MAAM;AACpB,aAAO,EAAE,CAAC,KAAK,GAAG,EAAE,OAAO,KAAK,EAAE;AAAA,IACpC;AACA,WAAO;AAAA,MACL,CAAC,KAAK,GAAG,EAAE,KAAK,QAAQ;AAAA,IAC1B;AAAA,EACF,WAAW,QAAQ,OAAO;AACxB,UAAM,CAAC,EAAE,KAAK,MAAM,GAAG,OAAO,IAAI,MAAM,IAAI;AAC5C,QAAI,YAAY,MAAM;AACpB,aAAO,EAAE,CAAC,KAAK,GAAG,EAAE,UAAU,KAAK,EAAE;AAAA,IACvC;AACA,WAAO;AAAA,MACL,CAAC,KAAK,GAAG,EAAE,KAAK,QAAQ;AAAA,IAC1B;AAAA,EAIF,WAAW,QAAQ,OAAO;AACxB,UAAM,CAAC,SAAS,EAAE,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI;AAC5C,WAAO;AAAA,MACL,CAAC,KAAK,GAAG,EAAE,WAAW,QAAQ;AAAA,IAChC;AAAA,EACF,OAAO;AAIL,UAAM,CAAC,KAAK,KAAK,IAAI,OAAO,QAAQ,KAAK,EAAE,CAAC;AAC5C,UAAM,QAA4B,gBAAgB,GAAG;AACrD,QAAI,OAAO;AACT,YAAM,CAAC,EAAE,KAAK,MAAM,GAAG,OAAO,IAAI;AAClC,aAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,GAAG,QAAQ,EAAE;AAAA,IACzC;AAEA,UAAM,IAAI,MAAM,qBAAqB,KAAK,UAAU,KAAK,GAAG;AAAA,EAC9D;AACF;AAGA,IAAM,kBAA0C;AAAA,EAC9C,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AACR;;;AH1JO,IAAM,kBAA0D;AAAA,EACrE,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,QAAQ;AAAA,IACN;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,OAAO;AAAA,UACL,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,QACA,YAAY;AAAA,UACV,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,aAAa;AAAA,UACX,MAAM;AAAA,UACN,aAAa;AAAA,UACb,QAAQ,CAAC,GAAQ,QAAa;AAC5B,kBAAM,UAAS,2BAAK,iBAAgB,CAAC;AACrC,mBAAO,iCAAiC,QAAQ,2BAAK,UAAU;AAAA,UACjE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,WAAW,CAAC,eAAiC;AAC3C,QAAI,EAAC,yCAAY,OAAM;AACrB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,MAAY;AACnB,iBAAO,CAAC;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAGA,UAAM,YAA6B;AAAA,MACjC,MAAM,WAAW;AAAA,MACjB,OAAO,WAAW;AAAA,MAClB,YAAY,WAAW;AAAA,IACzB;AACA,WAAO;AAAA,MACL,SAAS,KAAK,UAAU,SAAS;AAAA,MACjC,SAAS,MAAY;AACnB,cAAM,OAAO,MAAM,YAAY,SAAS;AACxC,cAAM,iBAAiB,6BAAM;AAC7B,YAAI,CAAC,gBAAgB;AACnB,iBAAO,EAAE,cAAc,CAAC,EAAE;AAAA,QAC5B;AAIA,cAAM,aAAkC,CAAC;AACzC,cAAM,SAAS,wBAAwB,cAAc;AACrD,cAAM,eAAe,eAAe,MAAM,GAAG,EAAE;AAE/C,mBAAW,SAAS,QAAQ;AAC1B,qBAAW,QAAQ,cAAc;AAC/B,gBAAI,MAAM;AACR,oBAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,kBAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,2BAAW,KAAK,IAAI;AACpB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,UACL,cAAc;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AA4CA,SAAsB,YAAY,IAKuB;AAAA,6CALvB;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAyD;AACvD,WAAO,aAAa,EAAE,MAAM,OAAO,YAAY,YAAY,CAAC;AAAA,EAC9D;AAAA;AAkBA,SAAsB,aAAa,IAS+B;AAAA,6CAT/B;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACkE;AAChE,QAAI,CAAC,QAAQ,CAAC,YAAY;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,aAAa,IAAI,IAAI,UAAU,WAAW,KAAK;AAE7D,UAAM,cAA2B,EAAE,QAAQ,MAAM;AACjD,QAAI,OAAO;AACT,kBAAY,UAAU,EAAE,eAAe,YAAY,MAAM;AAAA,IAC3D;AAEA,QAAI,UAA+B,CAAC;AACpC,QAAI,aAAa;AACf,gBAAU,0BAA0B,WAAW;AAAA,IACjD,WAAW,eAAe,mBAAmB,aAAa;AACxD,gBAAU;AAAA,QACR,CAAC,WAAW,GAAG;AAAA,UACb,CAAC,eAAe,GAAG;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAIA,UAAM,cAAc,UAAAA,QAAG,UAAU;AAAA,MAC/B;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAED,UAAM,OAAO,MAAM,MAAM,GAAG,SAAS,eAAe,WAAW;AAC/D,UAAM,OAAO,MAAM,KAAK,KAAK;AAG7B,WAAO,mBAAmB,MAAM,IAAI;AAAA,EACtC;AAAA;;;AD/MO,SAAS,eAAe,QAAoC;AACjE,WAAS,kBACP,IACA,MACA;AACA,QAAI,QAAQ;AACV,aAAO,iBAAiB,IAAI,IAAI;AAAA,IAClC,OAAO;AACL,kCAAAC,SAAiB,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,oBAAkB,aAAa,eAAe;AAChD;",
|
|
6
6
|
"names": ["qs", "registerFunction"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plasmicpkgs/strapi",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Plasmic registration for Strapi",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,12 +35,14 @@
|
|
|
35
35
|
"qs": "^6.11.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@plasmicapp/host": "1.0.
|
|
38
|
+
"@plasmicapp/host": "1.0.233",
|
|
39
|
+
"@react-awesome-query-builder/core": "^6.6.15",
|
|
40
|
+
"@types/json-logic-js": "^2.0.8",
|
|
39
41
|
"@types/qs": "^6.9.7",
|
|
40
42
|
"typescript": "^5.7.3"
|
|
41
43
|
},
|
|
42
44
|
"peerDependencies": {
|
|
43
45
|
"@plasmicapp/host": "^1.0.211"
|
|
44
46
|
},
|
|
45
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "9b689542d648f282e4bb8e3e392389e44e8bcfe8"
|
|
46
48
|
}
|