multi-content-type-relation 0.1.0 → 2.1.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/dist/_chunks/en-Bk9okOMP.js +32 -0
- package/dist/_chunks/en-Cj4T04Z2.mjs +32 -0
- package/dist/_chunks/fr-KHPiQOFP.mjs +32 -0
- package/dist/_chunks/fr-ZS3aTnjj.js +32 -0
- package/dist/_chunks/index-BHcolZ4N.mjs +333 -0
- package/dist/_chunks/index-CktBIBSM.js +332 -0
- package/dist/_chunks/index-CxWt3llJ.js +3566 -0
- package/dist/_chunks/index-D6nv39Fp.mjs +3564 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/index.mjs +4 -0
- package/dist/admin/src/components/Input/InputContentSuggestions.d.ts +13 -0
- package/dist/admin/src/components/Input/MainInput.d.ts +16 -0
- package/dist/admin/src/components/Input/PublicationState.d.ts +6 -0
- package/dist/admin/src/components/Input/TableItem.d.ts +12 -0
- package/dist/admin/src/components/Input/index.d.ts +2 -0
- package/dist/admin/src/components/PluginIcon/index.d.ts +2 -0
- package/dist/admin/src/components/SidePanel/SidePanel.d.ts +7 -0
- package/dist/admin/src/helpers/content.d.ts +5 -0
- package/dist/admin/src/helpers/storage.d.ts +15 -0
- package/dist/admin/src/hooks/useSearchedEntries.d.ts +6 -0
- package/dist/admin/src/hooks/useTranslate.d.ts +4 -0
- package/dist/admin/src/index.d.ts +9 -0
- package/dist/admin/src/interface.d.ts +33 -0
- package/dist/admin/src/pluginId.d.ts +2 -0
- package/dist/server/index.js +506 -25
- package/dist/server/index.mjs +509 -0
- package/dist/server/src/bootstrap.d.ts +5 -0
- package/dist/server/src/config/index.d.ts +13 -0
- package/dist/server/src/content-types/index.d.ts +35 -0
- package/dist/server/src/content-types/mctr-relation/index.d.ts +33 -0
- package/dist/server/src/content-types/mctr-relation/schema.d.ts +31 -0
- package/dist/server/src/controllers/controller.d.ts +27 -0
- package/dist/server/src/controllers/index.d.ts +28 -0
- package/dist/server/src/destroy.d.ts +5 -0
- package/dist/server/src/helpers/index.d.ts +2 -0
- package/dist/server/src/index.d.ts +113 -0
- package/dist/server/src/interface.d.ts +42 -0
- package/dist/server/src/middlewares/index.d.ts +4 -0
- package/dist/server/src/middlewares/middleware.d.ts +2 -0
- package/dist/server/src/policies/index.d.ts +2 -0
- package/dist/server/src/register.d.ts +5 -0
- package/dist/server/src/routes/index.d.ts +18 -0
- package/dist/server/src/services/index.d.ts +8 -0
- package/dist/server/src/services/service.d.ts +7 -0
- package/dist/server/src/utils.d.ts +3 -0
- package/package.json +55 -27
- package/TODO.md +0 -4
- package/admin/src/components/Input/InputContentSuggestions.tsx +0 -162
- package/admin/src/components/Input/MainInput.tsx +0 -135
- package/admin/src/components/Input/PublicationState.tsx +0 -28
- package/admin/src/components/Input/TableItem.tsx +0 -109
- package/admin/src/components/Input/index.tsx +0 -27
- package/admin/src/components/PluginIcon/index.tsx +0 -12
- package/admin/src/helpers/content.ts +0 -60
- package/admin/src/helpers/storage.ts +0 -32
- package/admin/src/hooks/useSearchedEntries.ts +0 -41
- package/admin/src/index.tsx +0 -140
- package/admin/src/interface.ts +0 -37
- package/admin/src/pluginId.ts +0 -5
- package/admin/src/translations/en.json +0 -1
- package/admin/src/translations/fr.json +0 -1
- package/admin/src/utils/getTrad.ts +0 -5
- package/dist/server/bootstrap.js +0 -5
- package/dist/server/config/index.js +0 -27
- package/dist/server/content-types/index.js +0 -3
- package/dist/server/controllers/controller.js +0 -92
- package/dist/server/controllers/index.js +0 -9
- package/dist/server/destroy.js +0 -5
- package/dist/server/interface.js +0 -2
- package/dist/server/middlewares/index.js +0 -9
- package/dist/server/middlewares/middleware.js +0 -163
- package/dist/server/policies/index.js +0 -3
- package/dist/server/register.js +0 -15
- package/dist/server/routes/index.js +0 -29
- package/dist/server/services/index.js +0 -9
- package/dist/server/services/service.js +0 -8
- package/dist/server/utils.js +0 -15
- package/dist/tsconfig.server.tsbuildinfo +0 -1
- package/server/bootstrap.ts +0 -5
- package/server/config/index.ts +0 -28
- package/server/content-types/index.ts +0 -1
- package/server/controllers/controller.ts +0 -107
- package/server/controllers/index.ts +0 -5
- package/server/destroy.ts +0 -5
- package/server/index.ts +0 -23
- package/server/interface.ts +0 -50
- package/server/middlewares/index.ts +0 -5
- package/server/middlewares/middleware.ts +0 -197
- package/server/policies/index.ts +0 -1
- package/server/register.ts +0 -14
- package/server/routes/index.ts +0 -27
- package/server/services/index.ts +0 -5
- package/server/services/service.ts +0 -11
- package/server/utils.ts +0 -14
- package/strapi-admin.js +0 -3
- package/strapi-server.js +0 -3
- package/tsconfig.json +0 -20
- package/tsconfig.server.json +0 -25
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { Strapi } from "@strapi/strapi"
|
|
2
|
-
import type { Common } from "@strapi/strapi"
|
|
3
|
-
import { FormattedStrapiEntry } from "../interface"
|
|
4
|
-
|
|
5
|
-
export default ({ strapi }: { strapi: Strapi }) => ({
|
|
6
|
-
getMatchingContent(ctx) {
|
|
7
|
-
const contentTypes = strapi.contentTypes
|
|
8
|
-
const body = ctx.request.body
|
|
9
|
-
|
|
10
|
-
const requestedContentTypes = body.contentTypes as string[]
|
|
11
|
-
const keyword = body.keyword as string
|
|
12
|
-
const locale = body.locale as string
|
|
13
|
-
|
|
14
|
-
const mapping = requestedContentTypes.reduce((accumulator, contentType) => {
|
|
15
|
-
Object.keys(contentTypes).forEach((model) => {
|
|
16
|
-
const strapiContentType = contentTypes[model]
|
|
17
|
-
if (strapiContentType.info.singularName === contentType || strapiContentType.info.pluralName === contentType) {
|
|
18
|
-
accumulator[contentType] = {
|
|
19
|
-
uid: model,
|
|
20
|
-
displayName: contentTypes[model].info.displayName,
|
|
21
|
-
searchableField: strapi
|
|
22
|
-
.plugin("multi-content-type-relation")
|
|
23
|
-
.service("service")
|
|
24
|
-
.getFirstStringFieldInContentType(contentTypes[model])
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
return accumulator
|
|
30
|
-
}, {} as Record<string, { uid: string; displayName: string; searchableField: string }>)
|
|
31
|
-
|
|
32
|
-
const promises = Object.keys(mapping).map((contentType) => {
|
|
33
|
-
const uid = mapping[contentType].uid
|
|
34
|
-
|
|
35
|
-
return strapi
|
|
36
|
-
.entityService!.findMany(uid as Common.UID.ContentType, {
|
|
37
|
-
filters: {
|
|
38
|
-
[mapping[contentType].searchableField]: {
|
|
39
|
-
$containsi: keyword
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
locale
|
|
43
|
-
})
|
|
44
|
-
.then((results) => {
|
|
45
|
-
let contents = Array.isArray(results) ? results : typeof results === "object" && results ? [results] : []
|
|
46
|
-
|
|
47
|
-
const contentTypeDefinition = strapi.contentType(uid as Common.UID.ContentType)
|
|
48
|
-
if (contentTypeDefinition?.options?.draftAndPublish) {
|
|
49
|
-
contents = contents.filter((content) => content.publishedAt !== null)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
uid,
|
|
54
|
-
displayName: mapping[contentType].displayName,
|
|
55
|
-
searchableField: mapping[contentType].searchableField,
|
|
56
|
-
results: contents
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
return Promise.all(promises)
|
|
62
|
-
},
|
|
63
|
-
validateRelations: async function (ctx) {
|
|
64
|
-
const contentTypes = strapi.contentTypes
|
|
65
|
-
const body = ctx.request.body
|
|
66
|
-
|
|
67
|
-
const entries = body.entries as FormattedStrapiEntry[]
|
|
68
|
-
|
|
69
|
-
const promises = entries.map((entry) => {
|
|
70
|
-
return strapi
|
|
71
|
-
.entityService!.findOne(entry.uid as Common.UID.ContentType, entry.id, { populate: "deep" })
|
|
72
|
-
.then((result) => {
|
|
73
|
-
return {
|
|
74
|
-
uid: entry.uid,
|
|
75
|
-
result
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
const responses = await Promise.all(promises)
|
|
81
|
-
|
|
82
|
-
return responses
|
|
83
|
-
.map((response) => {
|
|
84
|
-
return {
|
|
85
|
-
displayName: contentTypes[response.uid].info.displayName,
|
|
86
|
-
uid: response.uid,
|
|
87
|
-
searchableField: strapi
|
|
88
|
-
.plugin("multi-content-type-relation")
|
|
89
|
-
.service("service")
|
|
90
|
-
.getFirstStringFieldInContentType(contentTypes[response.uid]),
|
|
91
|
-
item: response.result
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
.filter((entry) => entry.item)
|
|
95
|
-
},
|
|
96
|
-
listContentTypes: async function (ctx) {
|
|
97
|
-
const contentTypes: Record<string, unknown>[] = []
|
|
98
|
-
|
|
99
|
-
for (const contentType of Object.values(strapi.contentTypes) as { kind: string; plugin: boolean }[]) {
|
|
100
|
-
if ((contentType.kind === "collectionType" || contentType.kind === "singleType") && !contentType.plugin) {
|
|
101
|
-
contentTypes.push(contentType as Record<string, unknown>)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return contentTypes
|
|
106
|
-
}
|
|
107
|
-
})
|
package/server/destroy.ts
DELETED
package/server/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import register from './register';
|
|
2
|
-
import bootstrap from './bootstrap';
|
|
3
|
-
import destroy from './destroy';
|
|
4
|
-
import config from './config';
|
|
5
|
-
import contentTypes from './content-types';
|
|
6
|
-
import controllers from './controllers';
|
|
7
|
-
import routes from './routes';
|
|
8
|
-
import middlewares from './middlewares';
|
|
9
|
-
import policies from './policies';
|
|
10
|
-
import services from './services';
|
|
11
|
-
|
|
12
|
-
export default {
|
|
13
|
-
register,
|
|
14
|
-
bootstrap,
|
|
15
|
-
destroy,
|
|
16
|
-
config,
|
|
17
|
-
controllers,
|
|
18
|
-
routes,
|
|
19
|
-
services,
|
|
20
|
-
contentTypes,
|
|
21
|
-
policies,
|
|
22
|
-
middlewares,
|
|
23
|
-
};
|
package/server/interface.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
export type StrapiContentTypeDefinition = {
|
|
2
|
-
collectionName: string
|
|
3
|
-
info: {
|
|
4
|
-
name: string
|
|
5
|
-
description: string
|
|
6
|
-
singularName: string
|
|
7
|
-
pluralName: string
|
|
8
|
-
displayName: string
|
|
9
|
-
}
|
|
10
|
-
attributes: Record<string, unknown>
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type SelectedEntry = {
|
|
14
|
-
displayName: string
|
|
15
|
-
searchableField: string
|
|
16
|
-
uid: string
|
|
17
|
-
item: {
|
|
18
|
-
id: string
|
|
19
|
-
[key: string]: any
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type FormattedStrapiEntry = {
|
|
24
|
-
uid: string
|
|
25
|
-
id: string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type Configuration = {
|
|
29
|
-
recursive: {
|
|
30
|
-
enabled: boolean
|
|
31
|
-
maxDepth: number
|
|
32
|
-
}
|
|
33
|
-
debug: boolean
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export type AnyEntity = {
|
|
37
|
-
id: number | string
|
|
38
|
-
attributes: {
|
|
39
|
-
[key: string]: any
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export type StrapiResponse = {
|
|
44
|
-
data: AnyEntity | AnyEntity[]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type Context = {
|
|
48
|
-
configuration: Configuration
|
|
49
|
-
publicationState: "live" | "preview"
|
|
50
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import type { Common } from "@strapi/strapi"
|
|
2
|
-
import { getPluginConfiguration, log } from "../utils"
|
|
3
|
-
import type { Context, StrapiResponse, AnyEntity } from "../interface"
|
|
4
|
-
|
|
5
|
-
export default async (ctx, next) => {
|
|
6
|
-
await next()
|
|
7
|
-
|
|
8
|
-
if (!ctx?.request?.url?.startsWith("/api")) return
|
|
9
|
-
if (ctx.request.method !== "GET") return
|
|
10
|
-
if (!ctx.body) return
|
|
11
|
-
|
|
12
|
-
const configuration = getPluginConfiguration()
|
|
13
|
-
|
|
14
|
-
const handler = ctx.state.route.handler
|
|
15
|
-
const contentTypes = Object.keys(strapi.contentTypes)
|
|
16
|
-
|
|
17
|
-
log(`URL: ${ctx.request.url} (${ctx.request.method})`)
|
|
18
|
-
log(`Strapi Route: ${JSON.stringify(ctx.state.route, null, 2)}`)
|
|
19
|
-
|
|
20
|
-
const validHandler = contentTypes
|
|
21
|
-
.filter((contentType) => contentType.startsWith("api::"))
|
|
22
|
-
.some(
|
|
23
|
-
(contentType) =>
|
|
24
|
-
handler.includes(`${contentType}.findOne`) ||
|
|
25
|
-
handler.includes(`${contentType}.findMany`) ||
|
|
26
|
-
handler.includes(`${contentType}.find`)
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
log(`Is valid handler: ${validHandler}`)
|
|
30
|
-
|
|
31
|
-
// Allow only findOne/findMany for native contentypes that have api::
|
|
32
|
-
if (!validHandler) return
|
|
33
|
-
|
|
34
|
-
const context = {
|
|
35
|
-
configuration,
|
|
36
|
-
publicationState: ctx.request.query?.["publicationState"] ?? "live"
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
log(" ----- ")
|
|
40
|
-
log(`Context Body: ${JSON.stringify(ctx.body, null, 2)}`)
|
|
41
|
-
if (ctx.body.error || !ctx.body?.data.attributes) return
|
|
42
|
-
|
|
43
|
-
const hydratedData = await augmentMRCT(ctx.body, 1, context)
|
|
44
|
-
|
|
45
|
-
ctx.body.data = hydratedData
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const augmentMRCT = async (
|
|
49
|
-
strapiResponse: StrapiResponse,
|
|
50
|
-
currentDepth: number,
|
|
51
|
-
context: Context
|
|
52
|
-
): Promise<AnyEntity | AnyEntity[]> => {
|
|
53
|
-
if (Array.isArray(strapiResponse.data)) {
|
|
54
|
-
const promises = strapiResponse.data.map((item) => hydrateMRCT(item, currentDepth, context))
|
|
55
|
-
|
|
56
|
-
return await Promise.all(promises)
|
|
57
|
-
} else {
|
|
58
|
-
return await hydrateMRCT(strapiResponse.data, currentDepth, context)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const hydrateMRCT = async (content: AnyEntity, currentDepth: number, context: Context) => {
|
|
63
|
-
const eligibleProperties: Set<string> = new Set()
|
|
64
|
-
const contentsToFetch: Set<string> = new Set()
|
|
65
|
-
|
|
66
|
-
const { configuration } = context
|
|
67
|
-
|
|
68
|
-
const flattenedProperties = flattenObj(content.attributes, null)
|
|
69
|
-
|
|
70
|
-
for (const [key, value] of Object.entries(flattenedProperties)) {
|
|
71
|
-
if (typeof value !== "string" || !value.includes("MRCT")) continue
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const field = JSON.parse(value)
|
|
75
|
-
|
|
76
|
-
if (!Array.isArray(field)) continue
|
|
77
|
-
|
|
78
|
-
for (const item of field) {
|
|
79
|
-
if (Object.keys(item).length !== 3 || (!item.uid && typeof item.uid !== "string") || !item.id) continue
|
|
80
|
-
|
|
81
|
-
const compositeID = `${item.uid}####${item.id}`
|
|
82
|
-
|
|
83
|
-
eligibleProperties.add(key)
|
|
84
|
-
|
|
85
|
-
if (contentsToFetch.has(compositeID)) continue
|
|
86
|
-
else contentsToFetch.add(compositeID)
|
|
87
|
-
}
|
|
88
|
-
} catch (e) {
|
|
89
|
-
continue
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (!contentsToFetch.size) return content
|
|
94
|
-
|
|
95
|
-
log(`Depth: ${currentDepth}, Hydrating MCTR for ID ${content.id}`)
|
|
96
|
-
|
|
97
|
-
const promises: Promise<any>[] = []
|
|
98
|
-
for (const item of Array.from(contentsToFetch)) {
|
|
99
|
-
const [uid, id] = item.split("####")
|
|
100
|
-
const promise = strapi.entityService
|
|
101
|
-
.findOne(uid as Common.UID.ContentType, id, { populate: "deep" })
|
|
102
|
-
.then(async (response) => {
|
|
103
|
-
if (!response) return { uid, response }
|
|
104
|
-
|
|
105
|
-
if (configuration.recursive.enabled && currentDepth < configuration.recursive.maxDepth) {
|
|
106
|
-
// Entity service serve the content flattened, so we need to rebuild the API format for the hydrate recursion
|
|
107
|
-
const hydratedResponse = await hydrateMRCT(
|
|
108
|
-
{
|
|
109
|
-
id: response.id,
|
|
110
|
-
attributes: response
|
|
111
|
-
},
|
|
112
|
-
currentDepth + 1,
|
|
113
|
-
context
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
uid,
|
|
118
|
-
response: {
|
|
119
|
-
id: response.id,
|
|
120
|
-
attributes: hydratedResponse.attributes
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
124
|
-
return {
|
|
125
|
-
uid,
|
|
126
|
-
response: {
|
|
127
|
-
id: response.id,
|
|
128
|
-
attributes: response
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
promises.push(promise)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const linkedEntries: any[] = await Promise.all(promises)
|
|
138
|
-
|
|
139
|
-
const filteredLinkedEntries: { uid: string; response: AnyEntity }[] = linkedEntries
|
|
140
|
-
.filter((linkedEntry) => Boolean(linkedEntry.response))
|
|
141
|
-
.filter((linkedEntry) => {
|
|
142
|
-
const contentTypeConfiguration = strapi.contentTypes[linkedEntry.uid]
|
|
143
|
-
|
|
144
|
-
if (!contentTypeConfiguration) return true
|
|
145
|
-
if (!contentTypeConfiguration.options?.draftAndPublish) return true
|
|
146
|
-
if (context.publicationState === "preview") return true
|
|
147
|
-
|
|
148
|
-
return typeof linkedEntry.response?.attributes.publishedAt === "string"
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
for (const key of Array.from(eligibleProperties)) {
|
|
152
|
-
const hydratedArray: AnyEntity[] = []
|
|
153
|
-
|
|
154
|
-
const unhydratedField = JSON.parse(flattenedProperties[key]) as { uid: string; id: string }[]
|
|
155
|
-
|
|
156
|
-
for (const item of unhydratedField) {
|
|
157
|
-
const matchingContent = filteredLinkedEntries.find(
|
|
158
|
-
(linkedEntry) => item.uid === linkedEntry.uid && item.id === linkedEntry.response.id
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
if (matchingContent) {
|
|
162
|
-
hydratedArray.push(matchingContent.response)
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
flattenedProperties[key] = hydratedArray
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const newContent = unflatten(flattenedProperties)
|
|
170
|
-
return {
|
|
171
|
-
...content,
|
|
172
|
-
attributes: newContent
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const flattenObj = (obj: any, parent: any, res: Record<string, any> = {}) => {
|
|
177
|
-
for (let key in obj) {
|
|
178
|
-
let propName = parent ? parent + "." + key : key
|
|
179
|
-
if (typeof obj[key] == "object") {
|
|
180
|
-
flattenObj(obj[key], propName, res)
|
|
181
|
-
} else {
|
|
182
|
-
res[propName] = obj[key]
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return res
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const unflatten = (data: any) => {
|
|
189
|
-
var result = {}
|
|
190
|
-
for (var i in data) {
|
|
191
|
-
var keys = i.split(".")
|
|
192
|
-
keys.reduce(function (r: any, e, j) {
|
|
193
|
-
return r[e] || (r[e] = isNaN(Number(keys[j + 1])) ? (keys.length - 1 == j ? data[i] : {}) : [])
|
|
194
|
-
}, result)
|
|
195
|
-
}
|
|
196
|
-
return result
|
|
197
|
-
}
|
package/server/policies/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default {};
|
package/server/register.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Strapi } from "@strapi/strapi"
|
|
2
|
-
|
|
3
|
-
import middlewares from "./middlewares"
|
|
4
|
-
|
|
5
|
-
export default ({ strapi }: { strapi: Strapi }) => {
|
|
6
|
-
// register phase
|
|
7
|
-
strapi.customFields.register({
|
|
8
|
-
name: "multi-content-type-relation",
|
|
9
|
-
plugin: "multi-content-type-relation",
|
|
10
|
-
type: "richtext"
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
strapi.server.use(middlewares.middleware)
|
|
14
|
-
}
|
package/server/routes/index.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export default [
|
|
2
|
-
{
|
|
3
|
-
method: "GET",
|
|
4
|
-
path: "/list-content-types",
|
|
5
|
-
handler: "controller.listContentTypes",
|
|
6
|
-
config: {
|
|
7
|
-
policies: [],
|
|
8
|
-
auth: false
|
|
9
|
-
}
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
method: "POST",
|
|
13
|
-
path: "/get-content",
|
|
14
|
-
handler: "controller.getMatchingContent",
|
|
15
|
-
config: {
|
|
16
|
-
policies: []
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
method: "POST",
|
|
21
|
-
path: "/validate-relations",
|
|
22
|
-
handler: "controller.validateRelations",
|
|
23
|
-
config: {
|
|
24
|
-
policies: []
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
]
|
package/server/services/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Strapi } from "@strapi/strapi"
|
|
2
|
-
|
|
3
|
-
export default ({ strapi }: { strapi: Strapi }) => ({
|
|
4
|
-
getFirstStringFieldInContentType(contentType) {
|
|
5
|
-
const result = Object.keys(contentType.attributes).find(
|
|
6
|
-
(attribute) => contentType.attributes[attribute].type === "string"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
return result
|
|
10
|
-
}
|
|
11
|
-
})
|
package/server/utils.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Configuration } from "./interface"
|
|
2
|
-
|
|
3
|
-
export const getPluginConfiguration = (): Configuration => {
|
|
4
|
-
const pluginConfiguration = strapi.config.get("plugin.multi-content-type-relation") as Configuration
|
|
5
|
-
|
|
6
|
-
return pluginConfiguration
|
|
7
|
-
}
|
|
8
|
-
export const log = (message: string) => {
|
|
9
|
-
const { debug } = getPluginConfiguration()
|
|
10
|
-
|
|
11
|
-
if (debug) {
|
|
12
|
-
console.log(`[MCTR DEBUG] ${message}`)
|
|
13
|
-
}
|
|
14
|
-
}
|
package/strapi-admin.js
DELETED
package/strapi-server.js
DELETED
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "@strapi/typescript-utils/tsconfigs/admin",
|
|
3
|
-
|
|
4
|
-
"compilerOptions": {
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"strict": true
|
|
7
|
-
},
|
|
8
|
-
|
|
9
|
-
"include": ["admin", "custom.d.ts"],
|
|
10
|
-
|
|
11
|
-
"exclude": [
|
|
12
|
-
"node_modules/",
|
|
13
|
-
"dist/",
|
|
14
|
-
|
|
15
|
-
// Do not include server files in the server compilation
|
|
16
|
-
"server/",
|
|
17
|
-
// Do not include test files
|
|
18
|
-
"**/*.test.ts"
|
|
19
|
-
]
|
|
20
|
-
}
|
package/tsconfig.server.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "@strapi/typescript-utils/tsconfigs/server",
|
|
3
|
-
|
|
4
|
-
"compilerOptions": {
|
|
5
|
-
"outDir": "dist",
|
|
6
|
-
"rootDir": "."
|
|
7
|
-
},
|
|
8
|
-
|
|
9
|
-
"include": [
|
|
10
|
-
// Include the root directory
|
|
11
|
-
"server",
|
|
12
|
-
// Force the JSON files in the src folder to be included
|
|
13
|
-
"server/**/*.json"
|
|
14
|
-
],
|
|
15
|
-
|
|
16
|
-
"exclude": [
|
|
17
|
-
"node_modules/",
|
|
18
|
-
"dist/",
|
|
19
|
-
|
|
20
|
-
// Do not include admin files in the server compilation
|
|
21
|
-
"admin/",
|
|
22
|
-
// Do not include test files
|
|
23
|
-
"**/*.test.ts"
|
|
24
|
-
]
|
|
25
|
-
}
|