@strapi/core 5.47.0 → 5.48.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/Strapi.d.ts.map +1 -1
- package/dist/Strapi.js +12 -3
- package/dist/Strapi.js.map +1 -1
- package/dist/Strapi.mjs +12 -3
- package/dist/Strapi.mjs.map +1 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +12 -5
- package/dist/compile.js.map +1 -1
- package/dist/compile.mjs +12 -5
- package/dist/compile.mjs.map +1 -1
- package/dist/configuration/index.d.ts +24 -0
- package/dist/configuration/index.d.ts.map +1 -1
- package/dist/configuration/index.js +47 -22
- package/dist/configuration/index.js.map +1 -1
- package/dist/configuration/index.mjs +47 -22
- package/dist/configuration/index.mjs.map +1 -1
- package/dist/middlewares/session.d.ts +2 -2
- package/dist/middlewares/session.d.ts.map +1 -1
- package/dist/middlewares/session.js +1 -1
- package/dist/middlewares/session.js.map +1 -1
- package/dist/middlewares/session.mjs +2 -2
- package/dist/middlewares/session.mjs.map +1 -1
- package/dist/package.json.js +16 -16
- package/dist/package.json.mjs +16 -16
- package/dist/providers/session-manager.d.ts.map +1 -1
- package/dist/providers/session-manager.js +3 -0
- package/dist/providers/session-manager.js.map +1 -1
- package/dist/providers/session-manager.mjs +3 -0
- package/dist/providers/session-manager.mjs.map +1 -1
- package/dist/services/cron.d.ts +1 -1
- package/dist/services/cron.d.ts.map +1 -1
- package/dist/services/cron.js +10 -2
- package/dist/services/cron.js.map +1 -1
- package/dist/services/cron.mjs +10 -2
- package/dist/services/cron.mjs.map +1 -1
- package/dist/services/document-service/draft-and-publish.d.ts +4 -4
- package/dist/services/document-service/internationalization.d.ts +4 -4
- package/dist/services/document-service/utils/unidirectional-relations.d.ts.map +1 -1
- package/dist/services/document-service/utils/unidirectional-relations.js +17 -4
- package/dist/services/document-service/utils/unidirectional-relations.js.map +1 -1
- package/dist/services/document-service/utils/unidirectional-relations.mjs +17 -4
- package/dist/services/document-service/utils/unidirectional-relations.mjs.map +1 -1
- package/dist/services/entity-validator/validators.d.ts.map +1 -1
- package/dist/services/entity-validator/validators.js +51 -2
- package/dist/services/entity-validator/validators.js.map +1 -1
- package/dist/services/entity-validator/validators.mjs +51 -2
- package/dist/services/entity-validator/validators.mjs.map +1 -1
- package/dist/services/mcp/index.d.ts.map +1 -1
- package/dist/services/mcp/index.js +3 -3
- package/dist/services/mcp/index.js.map +1 -1
- package/dist/services/mcp/index.mjs +3 -3
- package/dist/services/mcp/index.mjs.map +1 -1
- package/dist/services/metrics/index.d.ts.map +1 -1
- package/dist/services/metrics/index.js +6 -5
- package/dist/services/metrics/index.js.map +1 -1
- package/dist/services/metrics/index.mjs +6 -5
- package/dist/services/metrics/index.mjs.map +1 -1
- package/dist/services/metrics/sender.d.ts.map +1 -1
- package/dist/services/metrics/sender.js +11 -3
- package/dist/services/metrics/sender.js.map +1 -1
- package/dist/services/metrics/sender.mjs +11 -3
- package/dist/services/metrics/sender.mjs.map +1 -1
- package/dist/services/server/openapi.d.ts +3 -0
- package/dist/services/server/openapi.d.ts.map +1 -0
- package/dist/services/server/openapi.js +209 -0
- package/dist/services/server/openapi.js.map +1 -0
- package/dist/services/server/openapi.mjs +188 -0
- package/dist/services/server/openapi.mjs.map +1 -0
- package/dist/services/server/register-routes.d.ts.map +1 -1
- package/dist/services/server/register-routes.js +2 -0
- package/dist/services/server/register-routes.js.map +1 -1
- package/dist/services/server/register-routes.mjs +2 -0
- package/dist/services/server/register-routes.mjs.map +1 -1
- package/dist/utils/startup-logger.d.ts.map +1 -1
- package/dist/utils/startup-logger.js +18 -6
- package/dist/utils/startup-logger.js.map +1 -1
- package/dist/utils/startup-logger.mjs +18 -6
- package/dist/utils/startup-logger.mjs.map +1 -1
- package/package.json +16 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sender.mjs","sources":["../../../src/services/metrics/sender.ts"],"sourcesContent":["import os from 'os';\nimport path from 'path';\nimport _ from 'lodash';\nimport isDocker from 'is-docker';\nimport ciEnv from 'ci-info';\nimport
|
|
1
|
+
{"version":3,"file":"sender.mjs","sources":["../../../src/services/metrics/sender.ts"],"sourcesContent":["import os from 'os';\nimport path from 'path';\nimport _ from 'lodash';\nimport isDocker from 'is-docker';\nimport ciEnv from 'ci-info';\nimport { env, generateInstallId } from '@strapi/utils';\nimport type { Core } from '@strapi/types';\nimport { generateAdminUserHash } from './admin-user-hash';\n\n// Lazy: only resolved when telemetry is enabled and a sender is constructed\nlet lazyTsUtils: typeof import('@strapi/typescript-utils') | undefined;\nconst tsUtils = (): typeof import('@strapi/typescript-utils') => {\n if (!lazyTsUtils) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n lazyTsUtils = require('@strapi/typescript-utils');\n }\n return lazyTsUtils as typeof import('@strapi/typescript-utils');\n};\n\nexport interface Payload {\n eventProperties?: Record<string, unknown>;\n userProperties?: Record<string, unknown>;\n groupProperties?: Record<string, unknown>;\n}\n\nexport type Sender = (\n event: string,\n payload?: Payload,\n opts?: Record<string, unknown>\n) => Promise<boolean>;\n\nconst defaultQueryOpts = {\n timeout: 1000,\n headers: { 'Content-Type': 'application/json' },\n};\n\n/**\n * Add properties from the package.json strapi key in the metadata\n */\nconst addPackageJsonStrapiMetadata = (metadata: Record<string, unknown>, strapi: Core.Strapi) => {\n const { packageJsonStrapi = {} } = strapi.config;\n\n _.defaults(metadata, packageJsonStrapi);\n};\n\n/**\n * Create a send function for event with all the necessary metadata\n */\nexport default (strapi: Core.Strapi): Sender => {\n const { uuid, installId: installIdFromPackageJson } = strapi.config;\n\n const installId = generateInstallId(uuid, installIdFromPackageJson);\n\n const serverRootPath = strapi.dirs.app.root;\n const adminRootPath = path.join(strapi.dirs.app.root, 'src', 'admin');\n\n const anonymousUserProperties = {\n environment: strapi.config.environment,\n os: os.type(),\n osPlatform: os.platform(),\n osArch: os.arch(),\n osRelease: os.release(),\n nodeVersion: process.versions.node,\n };\n\n const anonymousGroupProperties = {\n docker: process.env.DOCKER || isDocker(),\n isCI: ciEnv.isCI,\n version: strapi.config.get('info.strapi'),\n useTypescriptOnServer: tsUtils().isUsingTypeScriptSync(serverRootPath),\n useTypescriptOnAdmin: tsUtils().isUsingTypeScriptSync(adminRootPath),\n projectId: uuid,\n isHostedOnStrapiCloud: env('STRAPI_HOSTING', null) === 'strapi.cloud',\n };\n\n addPackageJsonStrapiMetadata(anonymousGroupProperties, strapi);\n\n return async (event: string, payload: Payload = {}, opts = {}) => {\n const userId = generateAdminUserHash(strapi);\n\n const eeGroupProps: Record<string, unknown> = {};\n if (strapi.ee?.subscriptionId !== undefined && strapi.ee?.subscriptionId !== null) {\n eeGroupProps.subscriptionId = strapi.ee.subscriptionId;\n }\n if (strapi.ee?.planPriceId !== undefined && strapi.ee?.planPriceId !== null) {\n eeGroupProps.planPriceId = strapi.ee.planPriceId;\n }\n\n const reqParams = {\n method: 'POST',\n body: JSON.stringify({\n event,\n userId,\n installId,\n eventProperties: payload.eventProperties,\n userProperties: userId ? { ...anonymousUserProperties, ...payload.userProperties } : {},\n groupProperties: {\n ...anonymousGroupProperties,\n projectType: strapi.EE ? 'Enterprise' : 'Community',\n ...eeGroupProps,\n ...payload.groupProperties,\n },\n }),\n ..._.merge({ headers: { 'X-Strapi-Event': event } }, defaultQueryOpts, opts),\n };\n\n try {\n const analyticsUrl = env('STRAPI_ANALYTICS_URL', 'https://analytics.strapi.io');\n const res = await strapi.fetch(`${analyticsUrl}/api/v2/track`, reqParams);\n return res.ok;\n } catch (err) {\n return false;\n }\n };\n};\n"],"names":["lazyTsUtils","tsUtils","require","defaultQueryOpts","timeout","headers","addPackageJsonStrapiMetadata","metadata","strapi","packageJsonStrapi","config","_","defaults","uuid","installId","installIdFromPackageJson","generateInstallId","serverRootPath","dirs","app","root","adminRootPath","path","join","anonymousUserProperties","environment","os","type","osPlatform","platform","osArch","arch","osRelease","release","nodeVersion","process","versions","node","anonymousGroupProperties","docker","env","DOCKER","isDocker","isCI","ciEnv","version","get","useTypescriptOnServer","isUsingTypeScriptSync","useTypescriptOnAdmin","projectId","isHostedOnStrapiCloud","event","payload","opts","userId","generateAdminUserHash","eeGroupProps","ee","subscriptionId","undefined","planPriceId","reqParams","method","body","JSON","stringify","eventProperties","userProperties","groupProperties","projectType","EE","merge","analyticsUrl","res","fetch","ok","err"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../../src/services/server/openapi.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AA0K1C,eAAO,MAAM,oBAAoB,WAAY,KAAK,MAAM,SA8DvD,CAAC"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var fse = require('fs-extra');
|
|
5
|
+
var openapi = require('@strapi/openapi');
|
|
6
|
+
|
|
7
|
+
function _interopNamespaceDefault(e) {
|
|
8
|
+
var n = Object.create(null);
|
|
9
|
+
if (e) {
|
|
10
|
+
Object.keys(e).forEach(function (k) {
|
|
11
|
+
if (k !== 'default') {
|
|
12
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () { return e[k]; }
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var openapi__namespace = /*#__PURE__*/_interopNamespaceDefault(openapi);
|
|
25
|
+
|
|
26
|
+
const SUPPORTED_ACCESS = {
|
|
27
|
+
'content-api': [
|
|
28
|
+
'disabled',
|
|
29
|
+
'public'
|
|
30
|
+
],
|
|
31
|
+
admin: [
|
|
32
|
+
'disabled',
|
|
33
|
+
'authenticated'
|
|
34
|
+
]
|
|
35
|
+
};
|
|
36
|
+
const DEFAULTS = {
|
|
37
|
+
routePath: '/openapi.json',
|
|
38
|
+
access: 'disabled',
|
|
39
|
+
cacheEnabled: true,
|
|
40
|
+
cacheMaxAgeMs: 60000,
|
|
41
|
+
cacheRelativeFilePaths: {
|
|
42
|
+
'content-api': '.strapi/openapi/content-api.json',
|
|
43
|
+
admin: '.strapi/openapi/admin.json'
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const normalizePath = (value)=>{
|
|
47
|
+
if (!value) {
|
|
48
|
+
return DEFAULTS.routePath;
|
|
49
|
+
}
|
|
50
|
+
return value.startsWith('/') ? value : `/${value}`;
|
|
51
|
+
};
|
|
52
|
+
const joinPaths = (basePath, routePath)=>{
|
|
53
|
+
const normalizedBasePath = normalizePath(basePath || '/');
|
|
54
|
+
const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);
|
|
55
|
+
const trimmedBasePath = normalizedBasePath === '/' ? '' : normalizedBasePath.replace(/\/+$/, '');
|
|
56
|
+
return `${trimmedBasePath}${normalizedRoutePath}` || '/';
|
|
57
|
+
};
|
|
58
|
+
const stripBasePrefix = (routePath, basePath)=>{
|
|
59
|
+
const normalizedBasePath = normalizePath(basePath || '/');
|
|
60
|
+
const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);
|
|
61
|
+
if (normalizedBasePath === '/') {
|
|
62
|
+
return normalizedRoutePath;
|
|
63
|
+
}
|
|
64
|
+
if (normalizedRoutePath === normalizedBasePath) {
|
|
65
|
+
return '/';
|
|
66
|
+
}
|
|
67
|
+
if (normalizedRoutePath.startsWith(`${normalizedBasePath}/`)) {
|
|
68
|
+
const strippedPath = normalizedRoutePath.slice(normalizedBasePath.length);
|
|
69
|
+
return normalizePath(strippedPath);
|
|
70
|
+
}
|
|
71
|
+
return normalizedRoutePath;
|
|
72
|
+
};
|
|
73
|
+
const resolveEndpointConfig = (strapi, rawConfig, type)=>{
|
|
74
|
+
const apiPrefix = strapi.config.get('api.rest.prefix', '/api');
|
|
75
|
+
const adminPath = strapi.config.get('admin.path', '/admin');
|
|
76
|
+
const basePath = type === 'content-api' ? apiPrefix : adminPath;
|
|
77
|
+
const configuredPath = rawConfig?.route?.path ?? DEFAULTS.routePath;
|
|
78
|
+
const routePath = stripBasePrefix(configuredPath, basePath);
|
|
79
|
+
const routerPrefix = type === 'admin' ? normalizePath(basePath) : undefined;
|
|
80
|
+
const fullPath = type === 'content-api' ? joinPaths(normalizePath(apiPrefix), routePath) : joinPaths(routerPrefix, routePath);
|
|
81
|
+
const access = rawConfig?.access ?? DEFAULTS.access;
|
|
82
|
+
const supportedAccess = SUPPORTED_ACCESS[type];
|
|
83
|
+
if (!supportedAccess.includes(access)) {
|
|
84
|
+
throw new Error(`Invalid OpenAPI access "${access}" for "${type}". Expected one of: ${supportedAccess.join(', ')}`);
|
|
85
|
+
}
|
|
86
|
+
const cacheEnabled = rawConfig?.cache?.enabled ?? DEFAULTS.cacheEnabled;
|
|
87
|
+
const cacheMaxAgeMs = rawConfig?.cache?.maxAgeMs ?? DEFAULTS.cacheMaxAgeMs;
|
|
88
|
+
const configuredCachePath = rawConfig?.cache?.filePath ?? DEFAULTS.cacheRelativeFilePaths[type];
|
|
89
|
+
const absoluteCachePath = path.isAbsolute(configuredCachePath) ? configuredCachePath : path.resolve(strapi.dirs.app.root, configuredCachePath);
|
|
90
|
+
return {
|
|
91
|
+
type,
|
|
92
|
+
access,
|
|
93
|
+
routePath,
|
|
94
|
+
routerPrefix,
|
|
95
|
+
fullPath,
|
|
96
|
+
cacheEnabled,
|
|
97
|
+
cacheMaxAgeMs,
|
|
98
|
+
absoluteCachePath
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Build the route `config` (auth + policies) for an endpoint.
|
|
103
|
+
*
|
|
104
|
+
* - `admin`: requires an authenticated admin via the `admin::isAuthenticatedAdmin`
|
|
105
|
+
* policy.
|
|
106
|
+
* Granular per-permission RBAC is intentionally left for a later iteration.
|
|
107
|
+
* - `content-api`: only supports public access for now, which disables auth so
|
|
108
|
+
* anyone can read the spec.
|
|
109
|
+
*/ const buildRouteConfig = (config)=>{
|
|
110
|
+
if (config.type === 'admin') {
|
|
111
|
+
return {
|
|
112
|
+
policies: [
|
|
113
|
+
'admin::isAuthenticatedAdmin'
|
|
114
|
+
]
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
auth: false
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const resolveOpenAPIConfig = (strapi)=>{
|
|
122
|
+
const rawConfig = strapi.config.get('server.openapi', {});
|
|
123
|
+
return [
|
|
124
|
+
resolveEndpointConfig(strapi, rawConfig['content-api'], 'content-api'),
|
|
125
|
+
resolveEndpointConfig(strapi, rawConfig.admin, 'admin')
|
|
126
|
+
].filter((config)=>config.access !== 'disabled');
|
|
127
|
+
};
|
|
128
|
+
const readCache = async (cachePath, maxAgeMs)=>{
|
|
129
|
+
if (maxAgeMs < 0) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const stat = await fse.stat(cachePath);
|
|
134
|
+
const ageMs = Date.now() - stat.mtimeMs;
|
|
135
|
+
if (ageMs > maxAgeMs) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
return await fse.readJson(cachePath);
|
|
139
|
+
} catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const writeCache = async (cachePath, document)=>{
|
|
144
|
+
await fse.outputJson(cachePath, document, {
|
|
145
|
+
spaces: 2
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
const generateDocument = (strapi, type)=>{
|
|
149
|
+
return openapi__namespace.generate(strapi, {
|
|
150
|
+
type
|
|
151
|
+
}).document;
|
|
152
|
+
};
|
|
153
|
+
const registerOpenAPIRoute = (strapi)=>{
|
|
154
|
+
const configs = resolveOpenAPIConfig(strapi);
|
|
155
|
+
if (!configs.length) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const fullPathSet = new Set();
|
|
159
|
+
for (const config of configs){
|
|
160
|
+
if (fullPathSet.has(config.fullPath)) {
|
|
161
|
+
throw new Error(`Duplicate OpenAPI endpoint path detected: "${config.fullPath}"`);
|
|
162
|
+
}
|
|
163
|
+
fullPathSet.add(config.fullPath);
|
|
164
|
+
}
|
|
165
|
+
const routers = configs.map((config)=>{
|
|
166
|
+
const handler = async (ctx)=>{
|
|
167
|
+
try {
|
|
168
|
+
if (config.cacheEnabled) {
|
|
169
|
+
const cachedDocument = await readCache(config.absoluteCachePath, config.cacheMaxAgeMs);
|
|
170
|
+
if (cachedDocument) {
|
|
171
|
+
ctx.set('Content-Type', 'application/json');
|
|
172
|
+
ctx.body = cachedDocument;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const document = generateDocument(strapi, config.type);
|
|
177
|
+
if (config.cacheEnabled) {
|
|
178
|
+
await writeCache(config.absoluteCachePath, document);
|
|
179
|
+
}
|
|
180
|
+
ctx.set('Content-Type', 'application/json');
|
|
181
|
+
ctx.body = document;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
strapi.log.error(error);
|
|
184
|
+
ctx.internalServerError('Failed to generate OpenAPI document');
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
type: config.type,
|
|
189
|
+
...config.routerPrefix ? {
|
|
190
|
+
prefix: config.routerPrefix
|
|
191
|
+
} : {},
|
|
192
|
+
routes: [
|
|
193
|
+
{
|
|
194
|
+
method: 'GET',
|
|
195
|
+
path: config.routePath,
|
|
196
|
+
handler,
|
|
197
|
+
info: {
|
|
198
|
+
type: config.type
|
|
199
|
+
},
|
|
200
|
+
config: buildRouteConfig(config)
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
routers.forEach((router)=>strapi.server.routes(router));
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
exports.registerOpenAPIRoute = registerOpenAPIRoute;
|
|
209
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.js","sources":["../../../src/services/server/openapi.ts"],"sourcesContent":["import path from 'path';\nimport fs from 'fs-extra';\nimport * as openapi from '@strapi/openapi';\nimport type { Core } from '@strapi/types';\n\ntype OpenAPIConfig = Core.Config.OpenAPI;\ntype OpenAPIRouteType = keyof OpenAPIConfig;\ntype OpenAPIEndpointConfig = NonNullable<OpenAPIConfig[OpenAPIRouteType]>;\ntype OpenAPIAccess =\n | NonNullable<NonNullable<OpenAPIConfig['content-api']>['access']>\n | NonNullable<NonNullable<OpenAPIConfig['admin']>['access']>;\n\nconst SUPPORTED_ACCESS = {\n 'content-api': ['disabled', 'public'],\n admin: ['disabled', 'authenticated'],\n} as const satisfies Record<OpenAPIRouteType, readonly OpenAPIAccess[]>;\n\ninterface ResolvedEndpointConfig {\n type: OpenAPIRouteType;\n access: OpenAPIAccess;\n routePath: string;\n routerPrefix?: string;\n fullPath: string;\n cacheEnabled: boolean;\n cacheMaxAgeMs: number;\n absoluteCachePath: string;\n}\n\nconst DEFAULTS = {\n routePath: '/openapi.json',\n access: 'disabled' as const,\n cacheEnabled: true,\n cacheMaxAgeMs: 60_000,\n cacheRelativeFilePaths: {\n 'content-api': '.strapi/openapi/content-api.json',\n admin: '.strapi/openapi/admin.json',\n } as Record<OpenAPIRouteType, string>,\n};\n\nconst normalizePath = (value: string) => {\n if (!value) {\n return DEFAULTS.routePath;\n }\n\n return value.startsWith('/') ? value : `/${value}`;\n};\n\nconst joinPaths = (basePath: string, routePath: string) => {\n const normalizedBasePath = normalizePath(basePath || '/');\n const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);\n\n const trimmedBasePath = normalizedBasePath === '/' ? '' : normalizedBasePath.replace(/\\/+$/, '');\n\n return `${trimmedBasePath}${normalizedRoutePath}` || '/';\n};\n\nconst stripBasePrefix = (routePath: string, basePath: string) => {\n const normalizedBasePath = normalizePath(basePath || '/');\n const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);\n\n if (normalizedBasePath === '/') {\n return normalizedRoutePath;\n }\n\n if (normalizedRoutePath === normalizedBasePath) {\n return '/';\n }\n\n if (normalizedRoutePath.startsWith(`${normalizedBasePath}/`)) {\n const strippedPath = normalizedRoutePath.slice(normalizedBasePath.length);\n return normalizePath(strippedPath);\n }\n\n return normalizedRoutePath;\n};\n\nconst resolveEndpointConfig = (\n strapi: Core.Strapi,\n rawConfig: OpenAPIEndpointConfig | undefined,\n type: OpenAPIRouteType\n): ResolvedEndpointConfig => {\n const apiPrefix = strapi.config.get('api.rest.prefix', '/api');\n const adminPath = strapi.config.get('admin.path', '/admin');\n const basePath = type === 'content-api' ? apiPrefix : adminPath;\n\n const configuredPath = rawConfig?.route?.path ?? DEFAULTS.routePath;\n const routePath = stripBasePrefix(configuredPath, basePath);\n const routerPrefix = type === 'admin' ? normalizePath(basePath) : undefined;\n const fullPath =\n type === 'content-api'\n ? joinPaths(normalizePath(apiPrefix), routePath)\n : joinPaths(routerPrefix!, routePath);\n const access = rawConfig?.access ?? DEFAULTS.access;\n const supportedAccess = SUPPORTED_ACCESS[type];\n\n if (!(supportedAccess as readonly OpenAPIAccess[]).includes(access)) {\n throw new Error(\n `Invalid OpenAPI access \"${access}\" for \"${type}\". Expected one of: ${supportedAccess.join(', ')}`\n );\n }\n\n const cacheEnabled = rawConfig?.cache?.enabled ?? DEFAULTS.cacheEnabled;\n const cacheMaxAgeMs = rawConfig?.cache?.maxAgeMs ?? DEFAULTS.cacheMaxAgeMs;\n const configuredCachePath = rawConfig?.cache?.filePath ?? DEFAULTS.cacheRelativeFilePaths[type];\n const absoluteCachePath = path.isAbsolute(configuredCachePath)\n ? configuredCachePath\n : path.resolve(strapi.dirs.app.root, configuredCachePath);\n\n return {\n type,\n access,\n routePath,\n routerPrefix,\n fullPath,\n cacheEnabled,\n cacheMaxAgeMs,\n absoluteCachePath,\n };\n};\n\n/**\n * Build the route `config` (auth + policies) for an endpoint.\n *\n * - `admin`: requires an authenticated admin via the `admin::isAuthenticatedAdmin`\n * policy.\n * Granular per-permission RBAC is intentionally left for a later iteration.\n * - `content-api`: only supports public access for now, which disables auth so\n * anyone can read the spec.\n */\nconst buildRouteConfig = (config: ResolvedEndpointConfig): Record<string, unknown> => {\n if (config.type === 'admin') {\n return { policies: ['admin::isAuthenticatedAdmin'] };\n }\n\n return { auth: false };\n};\n\nconst resolveOpenAPIConfig = (strapi: Core.Strapi) => {\n const rawConfig = strapi.config.get('server.openapi', {}) as OpenAPIConfig;\n\n return [\n resolveEndpointConfig(strapi, rawConfig['content-api'], 'content-api'),\n resolveEndpointConfig(strapi, rawConfig.admin, 'admin'),\n ].filter((config) => config.access !== 'disabled');\n};\n\nconst readCache = async (cachePath: string, maxAgeMs: number) => {\n if (maxAgeMs < 0) {\n return null;\n }\n\n try {\n const stat = await fs.stat(cachePath);\n const ageMs = Date.now() - stat.mtimeMs;\n\n if (ageMs > maxAgeMs) {\n return null;\n }\n\n return await fs.readJson(cachePath);\n } catch {\n return null;\n }\n};\n\nconst writeCache = async (cachePath: string, document: unknown) => {\n await fs.outputJson(cachePath, document, { spaces: 2 });\n};\n\nconst generateDocument = (strapi: Core.Strapi, type: OpenAPIRouteType) => {\n return openapi.generate(strapi, { type }).document;\n};\n\nexport const registerOpenAPIRoute = (strapi: Core.Strapi) => {\n const configs = resolveOpenAPIConfig(strapi);\n\n if (!configs.length) {\n return;\n }\n\n const fullPathSet = new Set<string>();\n\n for (const config of configs) {\n if (fullPathSet.has(config.fullPath)) {\n throw new Error(`Duplicate OpenAPI endpoint path detected: \"${config.fullPath}\"`);\n }\n\n fullPathSet.add(config.fullPath);\n }\n\n const routers = configs.map((config) => {\n const handler: Core.MiddlewareHandler = async (ctx) => {\n try {\n if (config.cacheEnabled) {\n const cachedDocument = await readCache(config.absoluteCachePath, config.cacheMaxAgeMs);\n\n if (cachedDocument) {\n ctx.set('Content-Type', 'application/json');\n ctx.body = cachedDocument;\n return;\n }\n }\n\n const document = generateDocument(strapi, config.type);\n\n if (config.cacheEnabled) {\n await writeCache(config.absoluteCachePath, document);\n }\n\n ctx.set('Content-Type', 'application/json');\n ctx.body = document;\n } catch (error) {\n strapi.log.error(error);\n ctx.internalServerError('Failed to generate OpenAPI document');\n }\n };\n\n return {\n type: config.type,\n ...(config.routerPrefix ? { prefix: config.routerPrefix } : {}),\n routes: [\n {\n method: 'GET' as const,\n path: config.routePath,\n handler,\n info: {\n type: config.type,\n },\n config: buildRouteConfig(config),\n },\n ],\n };\n });\n\n routers.forEach((router) => strapi.server.routes(router));\n};\n"],"names":["SUPPORTED_ACCESS","admin","DEFAULTS","routePath","access","cacheEnabled","cacheMaxAgeMs","cacheRelativeFilePaths","normalizePath","value","startsWith","joinPaths","basePath","normalizedBasePath","normalizedRoutePath","trimmedBasePath","replace","stripBasePrefix","strippedPath","slice","length","resolveEndpointConfig","strapi","rawConfig","type","apiPrefix","config","get","adminPath","configuredPath","route","path","routerPrefix","undefined","fullPath","supportedAccess","includes","Error","join","cache","enabled","maxAgeMs","configuredCachePath","filePath","absoluteCachePath","isAbsolute","resolve","dirs","app","root","buildRouteConfig","policies","auth","resolveOpenAPIConfig","filter","readCache","cachePath","stat","fs","ageMs","Date","now","mtimeMs","readJson","writeCache","document","outputJson","spaces","generateDocument","openapi","generate","registerOpenAPIRoute","configs","fullPathSet","Set","has","add","routers","map","handler","ctx","cachedDocument","set","body","error","log","internalServerError","prefix","routes","method","info","forEach","router","server"],"mappings":"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"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fse from 'fs-extra';
|
|
3
|
+
import * as openapi from '@strapi/openapi';
|
|
4
|
+
|
|
5
|
+
const SUPPORTED_ACCESS = {
|
|
6
|
+
'content-api': [
|
|
7
|
+
'disabled',
|
|
8
|
+
'public'
|
|
9
|
+
],
|
|
10
|
+
admin: [
|
|
11
|
+
'disabled',
|
|
12
|
+
'authenticated'
|
|
13
|
+
]
|
|
14
|
+
};
|
|
15
|
+
const DEFAULTS = {
|
|
16
|
+
routePath: '/openapi.json',
|
|
17
|
+
access: 'disabled',
|
|
18
|
+
cacheEnabled: true,
|
|
19
|
+
cacheMaxAgeMs: 60000,
|
|
20
|
+
cacheRelativeFilePaths: {
|
|
21
|
+
'content-api': '.strapi/openapi/content-api.json',
|
|
22
|
+
admin: '.strapi/openapi/admin.json'
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const normalizePath = (value)=>{
|
|
26
|
+
if (!value) {
|
|
27
|
+
return DEFAULTS.routePath;
|
|
28
|
+
}
|
|
29
|
+
return value.startsWith('/') ? value : `/${value}`;
|
|
30
|
+
};
|
|
31
|
+
const joinPaths = (basePath, routePath)=>{
|
|
32
|
+
const normalizedBasePath = normalizePath(basePath || '/');
|
|
33
|
+
const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);
|
|
34
|
+
const trimmedBasePath = normalizedBasePath === '/' ? '' : normalizedBasePath.replace(/\/+$/, '');
|
|
35
|
+
return `${trimmedBasePath}${normalizedRoutePath}` || '/';
|
|
36
|
+
};
|
|
37
|
+
const stripBasePrefix = (routePath, basePath)=>{
|
|
38
|
+
const normalizedBasePath = normalizePath(basePath || '/');
|
|
39
|
+
const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);
|
|
40
|
+
if (normalizedBasePath === '/') {
|
|
41
|
+
return normalizedRoutePath;
|
|
42
|
+
}
|
|
43
|
+
if (normalizedRoutePath === normalizedBasePath) {
|
|
44
|
+
return '/';
|
|
45
|
+
}
|
|
46
|
+
if (normalizedRoutePath.startsWith(`${normalizedBasePath}/`)) {
|
|
47
|
+
const strippedPath = normalizedRoutePath.slice(normalizedBasePath.length);
|
|
48
|
+
return normalizePath(strippedPath);
|
|
49
|
+
}
|
|
50
|
+
return normalizedRoutePath;
|
|
51
|
+
};
|
|
52
|
+
const resolveEndpointConfig = (strapi, rawConfig, type)=>{
|
|
53
|
+
const apiPrefix = strapi.config.get('api.rest.prefix', '/api');
|
|
54
|
+
const adminPath = strapi.config.get('admin.path', '/admin');
|
|
55
|
+
const basePath = type === 'content-api' ? apiPrefix : adminPath;
|
|
56
|
+
const configuredPath = rawConfig?.route?.path ?? DEFAULTS.routePath;
|
|
57
|
+
const routePath = stripBasePrefix(configuredPath, basePath);
|
|
58
|
+
const routerPrefix = type === 'admin' ? normalizePath(basePath) : undefined;
|
|
59
|
+
const fullPath = type === 'content-api' ? joinPaths(normalizePath(apiPrefix), routePath) : joinPaths(routerPrefix, routePath);
|
|
60
|
+
const access = rawConfig?.access ?? DEFAULTS.access;
|
|
61
|
+
const supportedAccess = SUPPORTED_ACCESS[type];
|
|
62
|
+
if (!supportedAccess.includes(access)) {
|
|
63
|
+
throw new Error(`Invalid OpenAPI access "${access}" for "${type}". Expected one of: ${supportedAccess.join(', ')}`);
|
|
64
|
+
}
|
|
65
|
+
const cacheEnabled = rawConfig?.cache?.enabled ?? DEFAULTS.cacheEnabled;
|
|
66
|
+
const cacheMaxAgeMs = rawConfig?.cache?.maxAgeMs ?? DEFAULTS.cacheMaxAgeMs;
|
|
67
|
+
const configuredCachePath = rawConfig?.cache?.filePath ?? DEFAULTS.cacheRelativeFilePaths[type];
|
|
68
|
+
const absoluteCachePath = path.isAbsolute(configuredCachePath) ? configuredCachePath : path.resolve(strapi.dirs.app.root, configuredCachePath);
|
|
69
|
+
return {
|
|
70
|
+
type,
|
|
71
|
+
access,
|
|
72
|
+
routePath,
|
|
73
|
+
routerPrefix,
|
|
74
|
+
fullPath,
|
|
75
|
+
cacheEnabled,
|
|
76
|
+
cacheMaxAgeMs,
|
|
77
|
+
absoluteCachePath
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Build the route `config` (auth + policies) for an endpoint.
|
|
82
|
+
*
|
|
83
|
+
* - `admin`: requires an authenticated admin via the `admin::isAuthenticatedAdmin`
|
|
84
|
+
* policy.
|
|
85
|
+
* Granular per-permission RBAC is intentionally left for a later iteration.
|
|
86
|
+
* - `content-api`: only supports public access for now, which disables auth so
|
|
87
|
+
* anyone can read the spec.
|
|
88
|
+
*/ const buildRouteConfig = (config)=>{
|
|
89
|
+
if (config.type === 'admin') {
|
|
90
|
+
return {
|
|
91
|
+
policies: [
|
|
92
|
+
'admin::isAuthenticatedAdmin'
|
|
93
|
+
]
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
auth: false
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
const resolveOpenAPIConfig = (strapi)=>{
|
|
101
|
+
const rawConfig = strapi.config.get('server.openapi', {});
|
|
102
|
+
return [
|
|
103
|
+
resolveEndpointConfig(strapi, rawConfig['content-api'], 'content-api'),
|
|
104
|
+
resolveEndpointConfig(strapi, rawConfig.admin, 'admin')
|
|
105
|
+
].filter((config)=>config.access !== 'disabled');
|
|
106
|
+
};
|
|
107
|
+
const readCache = async (cachePath, maxAgeMs)=>{
|
|
108
|
+
if (maxAgeMs < 0) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const stat = await fse.stat(cachePath);
|
|
113
|
+
const ageMs = Date.now() - stat.mtimeMs;
|
|
114
|
+
if (ageMs > maxAgeMs) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
return await fse.readJson(cachePath);
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const writeCache = async (cachePath, document)=>{
|
|
123
|
+
await fse.outputJson(cachePath, document, {
|
|
124
|
+
spaces: 2
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
const generateDocument = (strapi, type)=>{
|
|
128
|
+
return openapi.generate(strapi, {
|
|
129
|
+
type
|
|
130
|
+
}).document;
|
|
131
|
+
};
|
|
132
|
+
const registerOpenAPIRoute = (strapi)=>{
|
|
133
|
+
const configs = resolveOpenAPIConfig(strapi);
|
|
134
|
+
if (!configs.length) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const fullPathSet = new Set();
|
|
138
|
+
for (const config of configs){
|
|
139
|
+
if (fullPathSet.has(config.fullPath)) {
|
|
140
|
+
throw new Error(`Duplicate OpenAPI endpoint path detected: "${config.fullPath}"`);
|
|
141
|
+
}
|
|
142
|
+
fullPathSet.add(config.fullPath);
|
|
143
|
+
}
|
|
144
|
+
const routers = configs.map((config)=>{
|
|
145
|
+
const handler = async (ctx)=>{
|
|
146
|
+
try {
|
|
147
|
+
if (config.cacheEnabled) {
|
|
148
|
+
const cachedDocument = await readCache(config.absoluteCachePath, config.cacheMaxAgeMs);
|
|
149
|
+
if (cachedDocument) {
|
|
150
|
+
ctx.set('Content-Type', 'application/json');
|
|
151
|
+
ctx.body = cachedDocument;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const document = generateDocument(strapi, config.type);
|
|
156
|
+
if (config.cacheEnabled) {
|
|
157
|
+
await writeCache(config.absoluteCachePath, document);
|
|
158
|
+
}
|
|
159
|
+
ctx.set('Content-Type', 'application/json');
|
|
160
|
+
ctx.body = document;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
strapi.log.error(error);
|
|
163
|
+
ctx.internalServerError('Failed to generate OpenAPI document');
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
return {
|
|
167
|
+
type: config.type,
|
|
168
|
+
...config.routerPrefix ? {
|
|
169
|
+
prefix: config.routerPrefix
|
|
170
|
+
} : {},
|
|
171
|
+
routes: [
|
|
172
|
+
{
|
|
173
|
+
method: 'GET',
|
|
174
|
+
path: config.routePath,
|
|
175
|
+
handler,
|
|
176
|
+
info: {
|
|
177
|
+
type: config.type
|
|
178
|
+
},
|
|
179
|
+
config: buildRouteConfig(config)
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
routers.forEach((router)=>strapi.server.routes(router));
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export { registerOpenAPIRoute };
|
|
188
|
+
//# sourceMappingURL=openapi.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.mjs","sources":["../../../src/services/server/openapi.ts"],"sourcesContent":["import path from 'path';\nimport fs from 'fs-extra';\nimport * as openapi from '@strapi/openapi';\nimport type { Core } from '@strapi/types';\n\ntype OpenAPIConfig = Core.Config.OpenAPI;\ntype OpenAPIRouteType = keyof OpenAPIConfig;\ntype OpenAPIEndpointConfig = NonNullable<OpenAPIConfig[OpenAPIRouteType]>;\ntype OpenAPIAccess =\n | NonNullable<NonNullable<OpenAPIConfig['content-api']>['access']>\n | NonNullable<NonNullable<OpenAPIConfig['admin']>['access']>;\n\nconst SUPPORTED_ACCESS = {\n 'content-api': ['disabled', 'public'],\n admin: ['disabled', 'authenticated'],\n} as const satisfies Record<OpenAPIRouteType, readonly OpenAPIAccess[]>;\n\ninterface ResolvedEndpointConfig {\n type: OpenAPIRouteType;\n access: OpenAPIAccess;\n routePath: string;\n routerPrefix?: string;\n fullPath: string;\n cacheEnabled: boolean;\n cacheMaxAgeMs: number;\n absoluteCachePath: string;\n}\n\nconst DEFAULTS = {\n routePath: '/openapi.json',\n access: 'disabled' as const,\n cacheEnabled: true,\n cacheMaxAgeMs: 60_000,\n cacheRelativeFilePaths: {\n 'content-api': '.strapi/openapi/content-api.json',\n admin: '.strapi/openapi/admin.json',\n } as Record<OpenAPIRouteType, string>,\n};\n\nconst normalizePath = (value: string) => {\n if (!value) {\n return DEFAULTS.routePath;\n }\n\n return value.startsWith('/') ? value : `/${value}`;\n};\n\nconst joinPaths = (basePath: string, routePath: string) => {\n const normalizedBasePath = normalizePath(basePath || '/');\n const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);\n\n const trimmedBasePath = normalizedBasePath === '/' ? '' : normalizedBasePath.replace(/\\/+$/, '');\n\n return `${trimmedBasePath}${normalizedRoutePath}` || '/';\n};\n\nconst stripBasePrefix = (routePath: string, basePath: string) => {\n const normalizedBasePath = normalizePath(basePath || '/');\n const normalizedRoutePath = normalizePath(routePath || DEFAULTS.routePath);\n\n if (normalizedBasePath === '/') {\n return normalizedRoutePath;\n }\n\n if (normalizedRoutePath === normalizedBasePath) {\n return '/';\n }\n\n if (normalizedRoutePath.startsWith(`${normalizedBasePath}/`)) {\n const strippedPath = normalizedRoutePath.slice(normalizedBasePath.length);\n return normalizePath(strippedPath);\n }\n\n return normalizedRoutePath;\n};\n\nconst resolveEndpointConfig = (\n strapi: Core.Strapi,\n rawConfig: OpenAPIEndpointConfig | undefined,\n type: OpenAPIRouteType\n): ResolvedEndpointConfig => {\n const apiPrefix = strapi.config.get('api.rest.prefix', '/api');\n const adminPath = strapi.config.get('admin.path', '/admin');\n const basePath = type === 'content-api' ? apiPrefix : adminPath;\n\n const configuredPath = rawConfig?.route?.path ?? DEFAULTS.routePath;\n const routePath = stripBasePrefix(configuredPath, basePath);\n const routerPrefix = type === 'admin' ? normalizePath(basePath) : undefined;\n const fullPath =\n type === 'content-api'\n ? joinPaths(normalizePath(apiPrefix), routePath)\n : joinPaths(routerPrefix!, routePath);\n const access = rawConfig?.access ?? DEFAULTS.access;\n const supportedAccess = SUPPORTED_ACCESS[type];\n\n if (!(supportedAccess as readonly OpenAPIAccess[]).includes(access)) {\n throw new Error(\n `Invalid OpenAPI access \"${access}\" for \"${type}\". Expected one of: ${supportedAccess.join(', ')}`\n );\n }\n\n const cacheEnabled = rawConfig?.cache?.enabled ?? DEFAULTS.cacheEnabled;\n const cacheMaxAgeMs = rawConfig?.cache?.maxAgeMs ?? DEFAULTS.cacheMaxAgeMs;\n const configuredCachePath = rawConfig?.cache?.filePath ?? DEFAULTS.cacheRelativeFilePaths[type];\n const absoluteCachePath = path.isAbsolute(configuredCachePath)\n ? configuredCachePath\n : path.resolve(strapi.dirs.app.root, configuredCachePath);\n\n return {\n type,\n access,\n routePath,\n routerPrefix,\n fullPath,\n cacheEnabled,\n cacheMaxAgeMs,\n absoluteCachePath,\n };\n};\n\n/**\n * Build the route `config` (auth + policies) for an endpoint.\n *\n * - `admin`: requires an authenticated admin via the `admin::isAuthenticatedAdmin`\n * policy.\n * Granular per-permission RBAC is intentionally left for a later iteration.\n * - `content-api`: only supports public access for now, which disables auth so\n * anyone can read the spec.\n */\nconst buildRouteConfig = (config: ResolvedEndpointConfig): Record<string, unknown> => {\n if (config.type === 'admin') {\n return { policies: ['admin::isAuthenticatedAdmin'] };\n }\n\n return { auth: false };\n};\n\nconst resolveOpenAPIConfig = (strapi: Core.Strapi) => {\n const rawConfig = strapi.config.get('server.openapi', {}) as OpenAPIConfig;\n\n return [\n resolveEndpointConfig(strapi, rawConfig['content-api'], 'content-api'),\n resolveEndpointConfig(strapi, rawConfig.admin, 'admin'),\n ].filter((config) => config.access !== 'disabled');\n};\n\nconst readCache = async (cachePath: string, maxAgeMs: number) => {\n if (maxAgeMs < 0) {\n return null;\n }\n\n try {\n const stat = await fs.stat(cachePath);\n const ageMs = Date.now() - stat.mtimeMs;\n\n if (ageMs > maxAgeMs) {\n return null;\n }\n\n return await fs.readJson(cachePath);\n } catch {\n return null;\n }\n};\n\nconst writeCache = async (cachePath: string, document: unknown) => {\n await fs.outputJson(cachePath, document, { spaces: 2 });\n};\n\nconst generateDocument = (strapi: Core.Strapi, type: OpenAPIRouteType) => {\n return openapi.generate(strapi, { type }).document;\n};\n\nexport const registerOpenAPIRoute = (strapi: Core.Strapi) => {\n const configs = resolveOpenAPIConfig(strapi);\n\n if (!configs.length) {\n return;\n }\n\n const fullPathSet = new Set<string>();\n\n for (const config of configs) {\n if (fullPathSet.has(config.fullPath)) {\n throw new Error(`Duplicate OpenAPI endpoint path detected: \"${config.fullPath}\"`);\n }\n\n fullPathSet.add(config.fullPath);\n }\n\n const routers = configs.map((config) => {\n const handler: Core.MiddlewareHandler = async (ctx) => {\n try {\n if (config.cacheEnabled) {\n const cachedDocument = await readCache(config.absoluteCachePath, config.cacheMaxAgeMs);\n\n if (cachedDocument) {\n ctx.set('Content-Type', 'application/json');\n ctx.body = cachedDocument;\n return;\n }\n }\n\n const document = generateDocument(strapi, config.type);\n\n if (config.cacheEnabled) {\n await writeCache(config.absoluteCachePath, document);\n }\n\n ctx.set('Content-Type', 'application/json');\n ctx.body = document;\n } catch (error) {\n strapi.log.error(error);\n ctx.internalServerError('Failed to generate OpenAPI document');\n }\n };\n\n return {\n type: config.type,\n ...(config.routerPrefix ? { prefix: config.routerPrefix } : {}),\n routes: [\n {\n method: 'GET' as const,\n path: config.routePath,\n handler,\n info: {\n type: config.type,\n },\n config: buildRouteConfig(config),\n },\n ],\n };\n });\n\n routers.forEach((router) => strapi.server.routes(router));\n};\n"],"names":["SUPPORTED_ACCESS","admin","DEFAULTS","routePath","access","cacheEnabled","cacheMaxAgeMs","cacheRelativeFilePaths","normalizePath","value","startsWith","joinPaths","basePath","normalizedBasePath","normalizedRoutePath","trimmedBasePath","replace","stripBasePrefix","strippedPath","slice","length","resolveEndpointConfig","strapi","rawConfig","type","apiPrefix","config","get","adminPath","configuredPath","route","path","routerPrefix","undefined","fullPath","supportedAccess","includes","Error","join","cache","enabled","maxAgeMs","configuredCachePath","filePath","absoluteCachePath","isAbsolute","resolve","dirs","app","root","buildRouteConfig","policies","auth","resolveOpenAPIConfig","filter","readCache","cachePath","stat","fs","ageMs","Date","now","mtimeMs","readJson","writeCache","document","outputJson","spaces","generateDocument","openapi","generate","registerOpenAPIRoute","configs","fullPathSet","Set","has","add","routers","map","handler","ctx","cachedDocument","set","body","error","log","internalServerError","prefix","routes","method","info","forEach","router","server"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-routes.d.ts","sourceRoot":"","sources":["../../../src/services/server/register-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"register-routes.d.ts","sourceRoot":"","sources":["../../../src/services/server/register-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAiB1C;;GAEG;iCACqB,KAAK,MAAM;AAAnC,wBAKE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var _ = require('lodash');
|
|
4
|
+
var openapi = require('./openapi.js');
|
|
4
5
|
|
|
5
6
|
const createRouteScopeGenerator = (namespace)=>(route)=>{
|
|
6
7
|
const prefix = namespace.endsWith('::') ? namespace : `${namespace}.`;
|
|
@@ -22,6 +23,7 @@ const createRouteScopeGenerator = (namespace)=>(route)=>{
|
|
|
22
23
|
registerAdminRoutes(strapi);
|
|
23
24
|
registerAPIRoutes(strapi);
|
|
24
25
|
registerPluginRoutes(strapi);
|
|
26
|
+
openapi.registerOpenAPIRoute(strapi);
|
|
25
27
|
});
|
|
26
28
|
/**
|
|
27
29
|
* Register admin routes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-routes.js","sources":["../../../src/services/server/register-routes.ts"],"sourcesContent":["import _ from 'lodash';\nimport type { Core } from '@strapi/types';\n\nconst createRouteScopeGenerator = (namespace: string) => (route: Core.RouteInput) => {\n const prefix = namespace.endsWith('::') ? namespace : `${namespace}.`;\n\n if (typeof route.handler === 'string') {\n _.defaultsDeep(route, {\n config: {\n auth: {\n scope: [`${route.handler.startsWith(prefix) ? '' : prefix}${route.handler}`],\n },\n },\n });\n }\n};\n\n/**\n * Register all routes\n */\nexport default (strapi: Core.Strapi) => {\n registerAdminRoutes(strapi);\n registerAPIRoutes(strapi);\n registerPluginRoutes(strapi);\n};\n\n/**\n * Register admin routes\n * @param {import('../../').Strapi} strapi\n */\nconst registerAdminRoutes = (strapi: Core.Strapi) => {\n const generateRouteScope = createRouteScopeGenerator(`admin::`);\n\n // Instantiate function-like routers\n // Mutate admin.routes in-place and make sure router factories are instantiated correctly\n strapi.admin.routes = instantiateRouterInputs(strapi.admin.routes, strapi);\n\n _.forEach(strapi.admin.routes, (router) => {\n router.type = router.type || 'admin';\n router.prefix = router.prefix || `/admin`;\n router.routes.forEach((route) => {\n generateRouteScope(route);\n route.info = { pluginName: 'admin' };\n });\n strapi.server.routes(router);\n });\n};\n\n/**\n * Register plugin routes\n * @param {import('../../').Strapi} strapi\n */\nconst registerPluginRoutes = (strapi: Core.Strapi) => {\n for (const pluginName of Object.keys(strapi.plugins)) {\n const plugin = strapi.plugins[pluginName];\n\n const generateRouteScope = createRouteScopeGenerator(`plugin::${pluginName}`);\n\n if (Array.isArray(plugin.routes)) {\n plugin.routes.forEach((route) => {\n generateRouteScope(route);\n route.info = { pluginName };\n });\n strapi.contentAPI.applyExtraParamsToRoutes(plugin.routes);\n\n strapi.server.routes({\n type: 'admin',\n prefix: `/${pluginName}`,\n routes: plugin.routes,\n });\n } else {\n // Instantiate function-like routers\n // Mutate plugin.routes in-place and make sure router factories are instantiated correctly\n plugin.routes = instantiateRouterInputs(plugin.routes, strapi);\n\n _.forEach(plugin.routes, (router) => {\n router.type = router.type ?? 'admin';\n router.prefix = router.prefix ?? `/${pluginName}`;\n router.routes.forEach((route) => {\n generateRouteScope(route);\n route.info = { pluginName };\n });\n strapi.contentAPI.applyExtraParamsToRoutes(router.routes ?? []);\n\n strapi.server.routes(router);\n });\n }\n }\n};\n\n/**\n * Register api routes\n */\nconst registerAPIRoutes = (strapi: Core.Strapi) => {\n for (const apiName of Object.keys(strapi.apis)) {\n const api = strapi.api(apiName);\n\n const generateRouteScope = createRouteScopeGenerator(`api::${apiName}`);\n\n // Mutate api.routes in-place and make sure router factories are instantiated correctly\n api.routes = instantiateRouterInputs(api.routes, strapi);\n\n _.forEach(api.routes, (router) => {\n // TODO: remove once auth setup\n // pass meta down to compose endpoint\n router.type = 'content-api';\n router.routes?.forEach((route) => {\n generateRouteScope(route);\n route.info = { apiName };\n });\n strapi.contentAPI.applyExtraParamsToRoutes(router.routes ?? []);\n\n return strapi.server.routes(router);\n });\n }\n};\n\nconst instantiateRouterInputs = (\n routers: Record<string, Core.RouterConfig>,\n strapi: Core.Strapi\n): Record<string, Core.Router> => {\n const entries = Object.entries(routers);\n\n return entries.reduce((record, [key, inputOrCallback]) => {\n const isCallback = typeof inputOrCallback === 'function';\n\n return { ...record, [key]: isCallback ? inputOrCallback({ strapi }) : inputOrCallback };\n }, {});\n};\n"],"names":["createRouteScopeGenerator","namespace","route","prefix","endsWith","handler","_","defaultsDeep","config","auth","scope","startsWith","strapi","registerAdminRoutes","registerAPIRoutes","registerPluginRoutes","generateRouteScope","admin","routes","instantiateRouterInputs","forEach","router","type","info","pluginName","server","Object","keys","plugins","plugin","Array","isArray","contentAPI","applyExtraParamsToRoutes","apiName","apis","api","routers","entries","reduce","record","key","inputOrCallback","isCallback"],"mappings":"
|
|
1
|
+
{"version":3,"file":"register-routes.js","sources":["../../../src/services/server/register-routes.ts"],"sourcesContent":["import _ from 'lodash';\nimport type { Core } from '@strapi/types';\nimport { registerOpenAPIRoute } from './openapi';\n\nconst createRouteScopeGenerator = (namespace: string) => (route: Core.RouteInput) => {\n const prefix = namespace.endsWith('::') ? namespace : `${namespace}.`;\n\n if (typeof route.handler === 'string') {\n _.defaultsDeep(route, {\n config: {\n auth: {\n scope: [`${route.handler.startsWith(prefix) ? '' : prefix}${route.handler}`],\n },\n },\n });\n }\n};\n\n/**\n * Register all routes\n */\nexport default (strapi: Core.Strapi) => {\n registerAdminRoutes(strapi);\n registerAPIRoutes(strapi);\n registerPluginRoutes(strapi);\n registerOpenAPIRoute(strapi);\n};\n\n/**\n * Register admin routes\n * @param {import('../../').Strapi} strapi\n */\nconst registerAdminRoutes = (strapi: Core.Strapi) => {\n const generateRouteScope = createRouteScopeGenerator(`admin::`);\n\n // Instantiate function-like routers\n // Mutate admin.routes in-place and make sure router factories are instantiated correctly\n strapi.admin.routes = instantiateRouterInputs(strapi.admin.routes, strapi);\n\n _.forEach(strapi.admin.routes, (router) => {\n router.type = router.type || 'admin';\n router.prefix = router.prefix || `/admin`;\n router.routes.forEach((route) => {\n generateRouteScope(route);\n route.info = { pluginName: 'admin' };\n });\n strapi.server.routes(router);\n });\n};\n\n/**\n * Register plugin routes\n * @param {import('../../').Strapi} strapi\n */\nconst registerPluginRoutes = (strapi: Core.Strapi) => {\n for (const pluginName of Object.keys(strapi.plugins)) {\n const plugin = strapi.plugins[pluginName];\n\n const generateRouteScope = createRouteScopeGenerator(`plugin::${pluginName}`);\n\n if (Array.isArray(plugin.routes)) {\n plugin.routes.forEach((route) => {\n generateRouteScope(route);\n route.info = { pluginName };\n });\n strapi.contentAPI.applyExtraParamsToRoutes(plugin.routes);\n\n strapi.server.routes({\n type: 'admin',\n prefix: `/${pluginName}`,\n routes: plugin.routes,\n });\n } else {\n // Instantiate function-like routers\n // Mutate plugin.routes in-place and make sure router factories are instantiated correctly\n plugin.routes = instantiateRouterInputs(plugin.routes, strapi);\n\n _.forEach(plugin.routes, (router) => {\n router.type = router.type ?? 'admin';\n router.prefix = router.prefix ?? `/${pluginName}`;\n router.routes.forEach((route) => {\n generateRouteScope(route);\n route.info = { pluginName };\n });\n strapi.contentAPI.applyExtraParamsToRoutes(router.routes ?? []);\n\n strapi.server.routes(router);\n });\n }\n }\n};\n\n/**\n * Register api routes\n */\nconst registerAPIRoutes = (strapi: Core.Strapi) => {\n for (const apiName of Object.keys(strapi.apis)) {\n const api = strapi.api(apiName);\n\n const generateRouteScope = createRouteScopeGenerator(`api::${apiName}`);\n\n // Mutate api.routes in-place and make sure router factories are instantiated correctly\n api.routes = instantiateRouterInputs(api.routes, strapi);\n\n _.forEach(api.routes, (router) => {\n // TODO: remove once auth setup\n // pass meta down to compose endpoint\n router.type = 'content-api';\n router.routes?.forEach((route) => {\n generateRouteScope(route);\n route.info = { apiName };\n });\n strapi.contentAPI.applyExtraParamsToRoutes(router.routes ?? []);\n\n return strapi.server.routes(router);\n });\n }\n};\n\nconst instantiateRouterInputs = (\n routers: Record<string, Core.RouterConfig>,\n strapi: Core.Strapi\n): Record<string, Core.Router> => {\n const entries = Object.entries(routers);\n\n return entries.reduce((record, [key, inputOrCallback]) => {\n const isCallback = typeof inputOrCallback === 'function';\n\n return { ...record, [key]: isCallback ? inputOrCallback({ strapi }) : inputOrCallback };\n }, {});\n};\n"],"names":["createRouteScopeGenerator","namespace","route","prefix","endsWith","handler","_","defaultsDeep","config","auth","scope","startsWith","strapi","registerAdminRoutes","registerAPIRoutes","registerPluginRoutes","registerOpenAPIRoute","generateRouteScope","admin","routes","instantiateRouterInputs","forEach","router","type","info","pluginName","server","Object","keys","plugins","plugin","Array","isArray","contentAPI","applyExtraParamsToRoutes","apiName","apis","api","routers","entries","reduce","record","key","inputOrCallback","isCallback"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
+
import { registerOpenAPIRoute } from './openapi.mjs';
|
|
2
3
|
|
|
3
4
|
const createRouteScopeGenerator = (namespace)=>(route)=>{
|
|
4
5
|
const prefix = namespace.endsWith('::') ? namespace : `${namespace}.`;
|
|
@@ -20,6 +21,7 @@ const createRouteScopeGenerator = (namespace)=>(route)=>{
|
|
|
20
21
|
registerAdminRoutes(strapi);
|
|
21
22
|
registerAPIRoutes(strapi);
|
|
22
23
|
registerPluginRoutes(strapi);
|
|
24
|
+
registerOpenAPIRoute(strapi);
|
|
23
25
|
});
|
|
24
26
|
/**
|
|
25
27
|
* Register admin routes
|