strapi-relation-names 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/admin/{SettingsPage-CaBXOirN.js → SettingsPage-BGsuRnwx.js} +17 -6
- package/dist/admin/{SettingsPage-CpTyZSvB.mjs → SettingsPage-Blk-4H_X.mjs} +17 -6
- package/dist/admin/{index-CKaZcnCM.js → index-DFr0KRky.js} +1 -1
- package/dist/admin/{index-DGXo1dxk.mjs → index-DdvdGn6T.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/utils/template.d.ts +2 -0
- package/dist/server/index.js +32 -6
- package/dist/server/index.mjs +32 -6
- package/dist/server/src/services/relation-labels.d.ts +4 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -171,6 +171,7 @@ The default label is also used when:
|
|
|
171
171
|
- [ ] Live label previews while editing templates
|
|
172
172
|
- [ ] Define default relation templates in plugin configuration
|
|
173
173
|
- [x] Support nested field paths in templates
|
|
174
|
+
- [x] Support nested relation fields in templates
|
|
174
175
|
- [ ] Import and export relation-label settings
|
|
175
176
|
- [ ] Conditional labels and configurable fallback rules
|
|
176
177
|
- [ ] Support label transformation functions (e.g., `toUpperCase`, `toLowerCase`, `capitalize`, etc.)
|
|
@@ -5,7 +5,7 @@ const designSystem = require("@strapi/design-system");
|
|
|
5
5
|
const react = require("react");
|
|
6
6
|
const reactIntl = require("react-intl");
|
|
7
7
|
const admin = require("@strapi/strapi/admin");
|
|
8
|
-
const index = require("./index-
|
|
8
|
+
const index = require("./index-DFr0KRky.js");
|
|
9
9
|
const FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
10
10
|
"string",
|
|
11
11
|
"text",
|
|
@@ -31,6 +31,15 @@ const SYSTEM_SCALAR_FIELDS = [
|
|
|
31
31
|
"status"
|
|
32
32
|
];
|
|
33
33
|
const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
34
|
+
const getNestedSchemaUid = (attribute) => {
|
|
35
|
+
if (attribute.type === "component") {
|
|
36
|
+
return attribute.component;
|
|
37
|
+
}
|
|
38
|
+
if (attribute.type === "relation") {
|
|
39
|
+
return attribute.targetModel ?? attribute.target;
|
|
40
|
+
}
|
|
41
|
+
return void 0;
|
|
42
|
+
};
|
|
34
43
|
const getPlaceholders = (template) => {
|
|
35
44
|
if (!template.trim()) {
|
|
36
45
|
return null;
|
|
@@ -74,10 +83,11 @@ const validateTemplate = (template, attributes, schemas) => {
|
|
|
74
83
|
if (isLastSegment) {
|
|
75
84
|
return !FIELD_TYPES.has(attribute.type ?? "");
|
|
76
85
|
}
|
|
77
|
-
|
|
86
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
87
|
+
if (!nestedSchemaUid) {
|
|
78
88
|
return true;
|
|
79
89
|
}
|
|
80
|
-
currentAttributes = schemas?.get(
|
|
90
|
+
currentAttributes = schemas?.get(nestedSchemaUid)?.attributes;
|
|
81
91
|
}
|
|
82
92
|
return true;
|
|
83
93
|
});
|
|
@@ -95,14 +105,15 @@ const getAvailableFields = (schema, schemas, prefix = "", ancestors = /* @__PURE
|
|
|
95
105
|
if (FIELD_TYPES.has(attribute.type ?? "")) {
|
|
96
106
|
return [path];
|
|
97
107
|
}
|
|
98
|
-
|
|
108
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
109
|
+
if (!nestedSchemaUid || ancestors.has(nestedSchemaUid)) {
|
|
99
110
|
return [];
|
|
100
111
|
}
|
|
101
112
|
return getAvailableFields(
|
|
102
|
-
schemas.get(
|
|
113
|
+
schemas.get(nestedSchemaUid),
|
|
103
114
|
schemas,
|
|
104
115
|
`${path}.`,
|
|
105
|
-
/* @__PURE__ */ new Set([...ancestors,
|
|
116
|
+
/* @__PURE__ */ new Set([...ancestors, nestedSchemaUid])
|
|
106
117
|
);
|
|
107
118
|
});
|
|
108
119
|
const systemFields = prefix === "" ? SYSTEM_SCALAR_FIELDS : [];
|
|
@@ -3,7 +3,7 @@ import { Main, Box, Typography, Field, TextInput, Flex, Button } from "@strapi/d
|
|
|
3
3
|
import { useState, useCallback, useEffect, useMemo } from "react";
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
5
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
6
|
-
import { g as getTranslation } from "./index-
|
|
6
|
+
import { g as getTranslation } from "./index-DdvdGn6T.mjs";
|
|
7
7
|
const FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
8
8
|
"string",
|
|
9
9
|
"text",
|
|
@@ -29,6 +29,15 @@ const SYSTEM_SCALAR_FIELDS = [
|
|
|
29
29
|
"status"
|
|
30
30
|
];
|
|
31
31
|
const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
32
|
+
const getNestedSchemaUid = (attribute) => {
|
|
33
|
+
if (attribute.type === "component") {
|
|
34
|
+
return attribute.component;
|
|
35
|
+
}
|
|
36
|
+
if (attribute.type === "relation") {
|
|
37
|
+
return attribute.targetModel ?? attribute.target;
|
|
38
|
+
}
|
|
39
|
+
return void 0;
|
|
40
|
+
};
|
|
32
41
|
const getPlaceholders = (template) => {
|
|
33
42
|
if (!template.trim()) {
|
|
34
43
|
return null;
|
|
@@ -72,10 +81,11 @@ const validateTemplate = (template, attributes, schemas) => {
|
|
|
72
81
|
if (isLastSegment) {
|
|
73
82
|
return !FIELD_TYPES.has(attribute.type ?? "");
|
|
74
83
|
}
|
|
75
|
-
|
|
84
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
85
|
+
if (!nestedSchemaUid) {
|
|
76
86
|
return true;
|
|
77
87
|
}
|
|
78
|
-
currentAttributes = schemas?.get(
|
|
88
|
+
currentAttributes = schemas?.get(nestedSchemaUid)?.attributes;
|
|
79
89
|
}
|
|
80
90
|
return true;
|
|
81
91
|
});
|
|
@@ -93,14 +103,15 @@ const getAvailableFields = (schema, schemas, prefix = "", ancestors = /* @__PURE
|
|
|
93
103
|
if (FIELD_TYPES.has(attribute.type ?? "")) {
|
|
94
104
|
return [path];
|
|
95
105
|
}
|
|
96
|
-
|
|
106
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
107
|
+
if (!nestedSchemaUid || ancestors.has(nestedSchemaUid)) {
|
|
97
108
|
return [];
|
|
98
109
|
}
|
|
99
110
|
return getAvailableFields(
|
|
100
|
-
schemas.get(
|
|
111
|
+
schemas.get(nestedSchemaUid),
|
|
101
112
|
schemas,
|
|
102
113
|
`${path}.`,
|
|
103
|
-
/* @__PURE__ */ new Set([...ancestors,
|
|
114
|
+
/* @__PURE__ */ new Set([...ancestors, nestedSchemaUid])
|
|
104
115
|
);
|
|
105
116
|
});
|
|
106
117
|
const systemFields = prefix === "" ? SYSTEM_SCALAR_FIELDS : [];
|
|
@@ -89,7 +89,7 @@ const plugin = {
|
|
|
89
89
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
90
90
|
defaultMessage: "Relation Names"
|
|
91
91
|
},
|
|
92
|
-
Component: () => Promise.resolve().then(() => require("./SettingsPage-
|
|
92
|
+
Component: () => Promise.resolve().then(() => require("./SettingsPage-BGsuRnwx.js")).then((module2) => ({ default: module2.SettingsPage })),
|
|
93
93
|
permissions: []
|
|
94
94
|
});
|
|
95
95
|
app.registerPlugin({
|
|
@@ -88,7 +88,7 @@ const plugin = {
|
|
|
88
88
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
89
89
|
defaultMessage: "Relation Names"
|
|
90
90
|
},
|
|
91
|
-
Component: () => import("./SettingsPage-
|
|
91
|
+
Component: () => import("./SettingsPage-Blk-4H_X.mjs").then((module) => ({ default: module.SettingsPage })),
|
|
92
92
|
permissions: []
|
|
93
93
|
});
|
|
94
94
|
app.registerPlugin({
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -164,6 +164,9 @@ const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)
|
|
|
164
164
|
const isRecord$1 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
165
165
|
const getPathValue = (value, path) => {
|
|
166
166
|
return path.split(".").reduce((current, segment) => {
|
|
167
|
+
if (Array.isArray(current)) {
|
|
168
|
+
return current.map((item) => isRecord$1(item) ? item[segment] : void 0).filter((item) => item !== void 0);
|
|
169
|
+
}
|
|
167
170
|
return isRecord$1(current) ? current[segment] : void 0;
|
|
168
171
|
}, value);
|
|
169
172
|
};
|
|
@@ -215,10 +218,11 @@ const compileTemplate = (template, targetSchema, resolveSchema) => {
|
|
|
215
218
|
if (isLastSegment) {
|
|
216
219
|
return SCALAR_TYPES.has(attribute.type ?? "");
|
|
217
220
|
}
|
|
218
|
-
|
|
221
|
+
const nestedSchemaUid = attribute.type === "component" ? attribute.component : attribute.type === "relation" ? attribute.target : void 0;
|
|
222
|
+
if (!nestedSchemaUid || !resolveSchema) {
|
|
219
223
|
return false;
|
|
220
224
|
}
|
|
221
|
-
schema = resolveSchema(
|
|
225
|
+
schema = resolveSchema(nestedSchemaUid);
|
|
222
226
|
if (!schema) {
|
|
223
227
|
return false;
|
|
224
228
|
}
|
|
@@ -329,10 +333,32 @@ const getRuntime = async (strapi, settings2, sourceUid, targetField, userAbility
|
|
|
329
333
|
};
|
|
330
334
|
};
|
|
331
335
|
const buildPopulate = (placeholders) => {
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
+
const populate = {};
|
|
337
|
+
for (const placeholder of placeholders) {
|
|
338
|
+
const segments = placeholder.split(".");
|
|
339
|
+
if (segments.length < 2) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
let current = populate;
|
|
343
|
+
for (const [index2, segment] of segments.slice(0, -1).entries()) {
|
|
344
|
+
const existing = current[segment];
|
|
345
|
+
if (existing === true) {
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
if (index2 === segments.length - 2) {
|
|
349
|
+
current[segment] = existing ?? true;
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
if (!existing) {
|
|
353
|
+
current[segment] = { populate: {} };
|
|
354
|
+
}
|
|
355
|
+
const next = current[segment];
|
|
356
|
+
if (next !== true) {
|
|
357
|
+
current = next.populate;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return Object.keys(populate).length > 0 ? populate : void 0;
|
|
336
362
|
};
|
|
337
363
|
const hydrateValues = async (strapi, ctx, runtime, values) => {
|
|
338
364
|
const targetSchema = strapi.getModel(runtime.targetUid);
|
package/dist/server/index.mjs
CHANGED
|
@@ -162,6 +162,9 @@ const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)
|
|
|
162
162
|
const isRecord$1 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
163
163
|
const getPathValue = (value, path) => {
|
|
164
164
|
return path.split(".").reduce((current, segment) => {
|
|
165
|
+
if (Array.isArray(current)) {
|
|
166
|
+
return current.map((item) => isRecord$1(item) ? item[segment] : void 0).filter((item) => item !== void 0);
|
|
167
|
+
}
|
|
165
168
|
return isRecord$1(current) ? current[segment] : void 0;
|
|
166
169
|
}, value);
|
|
167
170
|
};
|
|
@@ -213,10 +216,11 @@ const compileTemplate = (template, targetSchema, resolveSchema) => {
|
|
|
213
216
|
if (isLastSegment) {
|
|
214
217
|
return SCALAR_TYPES.has(attribute.type ?? "");
|
|
215
218
|
}
|
|
216
|
-
|
|
219
|
+
const nestedSchemaUid = attribute.type === "component" ? attribute.component : attribute.type === "relation" ? attribute.target : void 0;
|
|
220
|
+
if (!nestedSchemaUid || !resolveSchema) {
|
|
217
221
|
return false;
|
|
218
222
|
}
|
|
219
|
-
schema = resolveSchema(
|
|
223
|
+
schema = resolveSchema(nestedSchemaUid);
|
|
220
224
|
if (!schema) {
|
|
221
225
|
return false;
|
|
222
226
|
}
|
|
@@ -327,10 +331,32 @@ const getRuntime = async (strapi, settings2, sourceUid, targetField, userAbility
|
|
|
327
331
|
};
|
|
328
332
|
};
|
|
329
333
|
const buildPopulate = (placeholders) => {
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
+
const populate = {};
|
|
335
|
+
for (const placeholder of placeholders) {
|
|
336
|
+
const segments = placeholder.split(".");
|
|
337
|
+
if (segments.length < 2) {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
let current = populate;
|
|
341
|
+
for (const [index2, segment] of segments.slice(0, -1).entries()) {
|
|
342
|
+
const existing = current[segment];
|
|
343
|
+
if (existing === true) {
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
if (index2 === segments.length - 2) {
|
|
347
|
+
current[segment] = existing ?? true;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
if (!existing) {
|
|
351
|
+
current[segment] = { populate: {} };
|
|
352
|
+
}
|
|
353
|
+
const next = current[segment];
|
|
354
|
+
if (next !== true) {
|
|
355
|
+
current = next.populate;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return Object.keys(populate).length > 0 ? populate : void 0;
|
|
334
360
|
};
|
|
335
361
|
const hydrateValues = async (strapi, ctx, runtime, values) => {
|
|
336
362
|
const targetSchema = strapi.getModel(runtime.targetUid);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Core } from '@strapi/strapi';
|
|
2
2
|
import { SchemaLike } from './utils/relation-labels';
|
|
3
|
-
|
|
3
|
+
type Populate = Record<string, true | {
|
|
4
|
+
populate: Populate;
|
|
5
|
+
}>;
|
|
6
|
+
declare const buildPopulate: (placeholders: string[]) => Populate | undefined;
|
|
4
7
|
declare const relationLabels: ({ strapi }: {
|
|
5
8
|
strapi: Core.Strapi;
|
|
6
9
|
}) => {
|