@oneentry/mcp-platform-server 0.1.0 → 0.1.1
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 +113 -71
- package/data/permissions.json +411 -0
- package/dist/api/build-catalog.d.ts +24 -0
- package/dist/api/build-catalog.d.ts.map +1 -0
- package/dist/api/build-catalog.js +257 -0
- package/dist/api/build-catalog.js.map +1 -0
- package/dist/api/catalog.d.ts +22 -3
- package/dist/api/catalog.d.ts.map +1 -1
- package/dist/api/catalog.js +69 -4
- package/dist/api/catalog.js.map +1 -1
- package/dist/api/normalize-schema.d.ts +14 -0
- package/dist/api/normalize-schema.d.ts.map +1 -0
- package/dist/api/normalize-schema.js +151 -0
- package/dist/api/normalize-schema.js.map +1 -0
- package/dist/api/swagger-source.d.ts +22 -0
- package/dist/api/swagger-source.d.ts.map +1 -0
- package/dist/api/swagger-source.js +76 -0
- package/dist/api/swagger-source.js.map +1 -0
- package/dist/api/types.d.ts +1 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/bin/cli.js +11 -3
- package/dist/bin/cli.js.map +1 -1
- package/dist/config/config.d.ts +84 -10
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +69 -6
- package/dist/config/config.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/knowledge/github.d.ts +46 -0
- package/dist/knowledge/github.d.ts.map +1 -0
- package/dist/knowledge/github.js +214 -0
- package/dist/knowledge/github.js.map +1 -0
- package/dist/knowledge/loader.d.ts +46 -19
- package/dist/knowledge/loader.d.ts.map +1 -1
- package/dist/knowledge/loader.js +92 -105
- package/dist/knowledge/loader.js.map +1 -1
- package/dist/knowledge/search.d.ts +11 -0
- package/dist/knowledge/search.d.ts.map +1 -1
- package/dist/knowledge/search.js +36 -3
- package/dist/knowledge/search.js.map +1 -1
- package/dist/knowledge/tar.d.ts +22 -0
- package/dist/knowledge/tar.d.ts.map +1 -0
- package/dist/knowledge/tar.js +120 -0
- package/dist/knowledge/tar.js.map +1 -0
- package/dist/knowledge/types.d.ts +31 -10
- package/dist/knowledge/types.d.ts.map +1 -1
- package/dist/server.d.ts +3 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -6
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts +6 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +8 -0
- package/dist/session.js.map +1 -1
- package/dist/tools/guide.d.ts.map +1 -1
- package/dist/tools/guide.js +9 -2
- package/dist/tools/guide.js.map +1 -1
- package/dist/tools/whoami.d.ts.map +1 -1
- package/dist/tools/whoami.js +4 -0
- package/dist/tools/whoami.js.map +1 -1
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +26 -1
- package/dist/transports/http.js.map +1 -1
- package/dist/transports/stdio.js +1 -1
- package/dist/transports/stdio.js.map +1 -1
- package/knowledge/operating-rules.md +176 -0
- package/package.json +4 -4
- package/data/catalog.json +0 -1
- package/data/knowledge.json +0 -1
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { capSchema, normalizeSchema } from './normalize-schema.js';
|
|
3
|
+
const API_PREFIX = '/api/admin';
|
|
4
|
+
const METHODS = ['get', 'post', 'put', 'patch', 'delete'];
|
|
5
|
+
/**
|
|
6
|
+
* Операции, которые остаются за подтверждением при любом уровне `--allow`.
|
|
7
|
+
* Список путей, а не прав: право можно выдать админу по недоразумению,
|
|
8
|
+
* а этот барьер снять нельзя.
|
|
9
|
+
*/
|
|
10
|
+
const ALWAYS_CONFIRM = [
|
|
11
|
+
/^\/immutable-settings/,
|
|
12
|
+
/^\/admins/,
|
|
13
|
+
/^\/backups/,
|
|
14
|
+
/^\/modules/,
|
|
15
|
+
/^\/payments\/webhook/,
|
|
16
|
+
/^\/auth\/logout\/all-users/,
|
|
17
|
+
/^\/settings-general/,
|
|
18
|
+
/^\/system\/captcha-keys/,
|
|
19
|
+
];
|
|
20
|
+
/** Какие разделы документации объясняют операции конкретного тега. */
|
|
21
|
+
const TAG_DOCS = {
|
|
22
|
+
Orders: ['back/docs/orders-module', 'back/docs/order-status-axis'],
|
|
23
|
+
Products: [
|
|
24
|
+
'back/docs/postgres-db-with-attribute-index',
|
|
25
|
+
'back/docs/product-relations',
|
|
26
|
+
'back/docs/isPrice-attribute',
|
|
27
|
+
],
|
|
28
|
+
Payments: ['back/docs/payments-module', 'back/docs/isPrice-attribute'],
|
|
29
|
+
Blocks: ['back/docs/blocks-module'],
|
|
30
|
+
Pages: ['back/docs/pages-module'],
|
|
31
|
+
Discounts: ['back/docs/orders-module'],
|
|
32
|
+
Filters: ['back/docs/filters'],
|
|
33
|
+
'Attributes Sets': [
|
|
34
|
+
'back/docs/postgres-db-with-attribute-index',
|
|
35
|
+
'back/docs/attribute-indexing',
|
|
36
|
+
'back/tests/attributes-sets-e2e',
|
|
37
|
+
],
|
|
38
|
+
Menus: ['back/docs/menus-module', 'back/tests/menus-e2e'],
|
|
39
|
+
'Index Attributes': ['back/docs/attribute-indexing'],
|
|
40
|
+
Modules: ['back/docs/user-permissions'],
|
|
41
|
+
Subscriptions: ['back/docs/subscriptions-module'],
|
|
42
|
+
Forms: ['back/docs/forms-and-form-data'],
|
|
43
|
+
FormData: ['back/docs/forms-and-form-data'],
|
|
44
|
+
'User Permissions': ['back/docs/user-permissions', 'front/docs/user-permissions'],
|
|
45
|
+
'User Groups': ['back/docs/user-permissions'],
|
|
46
|
+
Admins: ['back/docs/user-permissions', 'back/tests/admins-e2e'],
|
|
47
|
+
'Global Search': ['back/docs/global-search'],
|
|
48
|
+
'AI Gateway': ['back/docs/ai-gateway'],
|
|
49
|
+
'AI Gateway / settings': ['back/docs/ai-gateway'],
|
|
50
|
+
'File Uploading': ['back/docs/file-upload-dev-mode'],
|
|
51
|
+
System: ['back/docs/captcha-recaptcha'],
|
|
52
|
+
Templates: ['back/tests/templates-e2e'],
|
|
53
|
+
'Template previews': ['back/tests/template-previews-e2e'],
|
|
54
|
+
Import: ['back/tests/import-e2e'],
|
|
55
|
+
};
|
|
56
|
+
const riskOf = (method) => {
|
|
57
|
+
if (method === 'get') {
|
|
58
|
+
return 'read';
|
|
59
|
+
}
|
|
60
|
+
return method === 'delete' ? 'destructive' : 'write';
|
|
61
|
+
};
|
|
62
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
63
|
+
const asString = (value) => typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
|
|
64
|
+
/** Собирает одну человекочитаемую строку описания успешного ответа. */
|
|
65
|
+
const responseSummary = (responses) => {
|
|
66
|
+
if (!isRecord(responses)) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
for (const code of ['200', '201', '202']) {
|
|
70
|
+
const entry = responses[code];
|
|
71
|
+
if (isRecord(entry)) {
|
|
72
|
+
const description = asString(entry['description']);
|
|
73
|
+
if (description) {
|
|
74
|
+
return description.replace(/\s+/g, ' ').slice(0, 300);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
};
|
|
80
|
+
const buildParams = (raw, components) => {
|
|
81
|
+
if (!Array.isArray(raw)) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const params = [];
|
|
85
|
+
for (const item of raw) {
|
|
86
|
+
if (!isRecord(item)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const location = asString(item['in']);
|
|
90
|
+
const name = asString(item['name']);
|
|
91
|
+
if (!name || (location !== 'path' && location !== 'query' && location !== 'header')) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
params.push({
|
|
95
|
+
name,
|
|
96
|
+
location,
|
|
97
|
+
required: item['required'] === true || location === 'path',
|
|
98
|
+
description: asString(item['description']),
|
|
99
|
+
schema: normalizeSchema(item['schema'], components),
|
|
100
|
+
example: item['example'],
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return params;
|
|
104
|
+
};
|
|
105
|
+
const buildBody = (raw, components) => {
|
|
106
|
+
if (!isRecord(raw)) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const content = raw['content'];
|
|
110
|
+
if (!isRecord(content)) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
const contentType = Object.keys(content)[0];
|
|
114
|
+
if (!contentType) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
const media = content[contentType];
|
|
118
|
+
if (!isRecord(media)) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
contentType,
|
|
123
|
+
schema: capSchema(normalizeSchema(media['schema'], components)),
|
|
124
|
+
required: raw['required'] === true,
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Строит каталог операций из swagger стенда и карты прав.
|
|
129
|
+
* Два источника, потому что ни одного не хватает: swagger даёт пути и схемы,
|
|
130
|
+
* а требуемое право объявлено декоратором и в swagger не попадает.
|
|
131
|
+
* Классификация риска и список навсегда подтверждаемых путей вычисляются здесь,
|
|
132
|
+
* то есть в коде пакета, — swagger приходит по сети и не должен на них влиять.
|
|
133
|
+
*/
|
|
134
|
+
export const buildCatalog = (params) => {
|
|
135
|
+
const { rawSwagger } = params;
|
|
136
|
+
const swagger = JSON.parse(rawSwagger);
|
|
137
|
+
if (!isRecord(swagger) || !isRecord(swagger['paths'])) {
|
|
138
|
+
throw new Error('The fetched document does not look like an OpenAPI document');
|
|
139
|
+
}
|
|
140
|
+
const componentsNode = swagger['components'];
|
|
141
|
+
const components = isRecord(componentsNode) && isRecord(componentsNode['schemas'])
|
|
142
|
+
? componentsNode['schemas']
|
|
143
|
+
: {};
|
|
144
|
+
const { byOpId, permissions } = params.permissions;
|
|
145
|
+
const operations = [];
|
|
146
|
+
/** Пути не из Admin API и операции без operationId — оба случая идут в warnings. */
|
|
147
|
+
const foreignPaths = [];
|
|
148
|
+
const withoutOpId = [];
|
|
149
|
+
for (const [fullPath, pathItem] of Object.entries(swagger['paths'])) {
|
|
150
|
+
if (!isRecord(pathItem)) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Путь вне `/api/admin` в каталог не попадает никогда: сервер по замыслу
|
|
155
|
+
* не выпускает наружу Content и Developer API. Документ приходит по сети,
|
|
156
|
+
* поэтому здесь фильтр, а не исключение — одна лишняя запись не должна
|
|
157
|
+
* лишать агента всего каталога.
|
|
158
|
+
*/
|
|
159
|
+
if (!fullPath.startsWith(API_PREFIX)) {
|
|
160
|
+
foreignPaths.push(fullPath);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const path = fullPath.slice(API_PREFIX.length) || '/';
|
|
164
|
+
for (const method of METHODS) {
|
|
165
|
+
const operation = pathItem[method];
|
|
166
|
+
if (!isRecord(operation)) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const opId = asString(operation['operationId']);
|
|
170
|
+
if (!opId) {
|
|
171
|
+
withoutOpId.push(`${method.toUpperCase()} ${fullPath}`);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const tags = operation['tags'];
|
|
175
|
+
const tag = (Array.isArray(tags) ? asString(tags[0]) : undefined) ?? 'Other';
|
|
176
|
+
const summary = asString(operation['summary']) ?? asString(operation['description']) ?? '';
|
|
177
|
+
const risk = riskOf(method);
|
|
178
|
+
const alwaysConfirm = method !== 'get' && ALWAYS_CONFIRM.some((pattern) => pattern.test(path));
|
|
179
|
+
const permission = byOpId[opId];
|
|
180
|
+
const entry = {
|
|
181
|
+
opId,
|
|
182
|
+
method,
|
|
183
|
+
path,
|
|
184
|
+
fullPath,
|
|
185
|
+
tag,
|
|
186
|
+
summary,
|
|
187
|
+
...(permission ? { permission } : {}),
|
|
188
|
+
risk,
|
|
189
|
+
alwaysConfirm,
|
|
190
|
+
params: buildParams(operation['parameters'], components),
|
|
191
|
+
...(buildBody(operation['requestBody'], components)
|
|
192
|
+
? { body: buildBody(operation['requestBody'], components) }
|
|
193
|
+
: {}),
|
|
194
|
+
...(responseSummary(operation['responses'])
|
|
195
|
+
? { responseSummary: responseSummary(operation['responses']) }
|
|
196
|
+
: {}),
|
|
197
|
+
docLinks: [...(TAG_DOCS[tag] ?? []), 'mcp/operating-rules'],
|
|
198
|
+
searchText: '',
|
|
199
|
+
};
|
|
200
|
+
entry.searchText = [opId, method.toUpperCase(), path, tag, summary, permission ?? '']
|
|
201
|
+
.join(' ')
|
|
202
|
+
.toLowerCase();
|
|
203
|
+
operations.push(entry);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
operations.sort((a, b) => a.opId.localeCompare(b.opId));
|
|
207
|
+
const warnings = [];
|
|
208
|
+
if (foreignPaths.length > 0) {
|
|
209
|
+
warnings.push(`${String(foreignPaths.length)} path(s) outside ${API_PREFIX} were dropped from the catalog ` +
|
|
210
|
+
`(e.g. ${foreignPaths.slice(0, 3).join(', ')}). This server exposes the Admin API only.`);
|
|
211
|
+
}
|
|
212
|
+
if (withoutOpId.length > 0) {
|
|
213
|
+
warnings.push(`${String(withoutOpId.length)} operation(s) have no operationId and cannot be called ` +
|
|
214
|
+
`(e.g. ${withoutOpId.slice(0, 3).join(', ')}). Report it against the CMS.`);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Обработчик объявляет право, но живой swagger о нём не знает.
|
|
218
|
+
* Раньше это означало устаревший снимок swagger; теперь документ приходит
|
|
219
|
+
* со стенда, поэтому смысл другой: карта прав собрана с другой версии кода,
|
|
220
|
+
* чем развёрнута на стенде. Агенту это важно так же — иначе он получит 404
|
|
221
|
+
* на существующий, по его данным, эндпоинт.
|
|
222
|
+
*/
|
|
223
|
+
const known = new Set(operations.map((o) => o.opId));
|
|
224
|
+
const missing = Object.keys(byOpId).filter((opId) => !known.has(opId) && !opId.startsWith('Developer') && !opId.startsWith('Content'));
|
|
225
|
+
if (missing.length > 0) {
|
|
226
|
+
warnings.push(`${String(missing.length)} admin handler(s) declare a permission but are absent from the ` +
|
|
227
|
+
`stand's swagger (e.g. ${missing.slice(0, 3).join(', ')}). data/permissions.json was ` +
|
|
228
|
+
'generated from a different revision of dnk-back than the stand runs — re-run ' +
|
|
229
|
+
'npm run sync:permissions if the catalog looks incomplete.');
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Право, объявленное контроллером, но отсутствующее в `AdminPermissionsEnum`,
|
|
233
|
+
* никогда не будет выдано администратору — такой эндпоинт отвечает 403 всегда.
|
|
234
|
+
* Это дефект dnk-back, и о нём должен знать и агент, и человек.
|
|
235
|
+
*/
|
|
236
|
+
const knownPermissions = new Set(permissions);
|
|
237
|
+
const orphanPermissions = [
|
|
238
|
+
...new Set(operations
|
|
239
|
+
.map((operation) => operation.permission)
|
|
240
|
+
.filter((value) => value !== undefined && !knownPermissions.has(value))),
|
|
241
|
+
];
|
|
242
|
+
if (orphanPermissions.length > 0) {
|
|
243
|
+
warnings.push(`${orphanPermissions.length} permission(s) are required by controllers but missing from ` +
|
|
244
|
+
`AdminPermissionsEnum (${orphanPermissions.join(', ')}). No admin can hold them, so those ` +
|
|
245
|
+
'operations always answer 403 — report it rather than retrying.');
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
version: 1,
|
|
249
|
+
builtAt: params.builtAt,
|
|
250
|
+
apiPrefix: API_PREFIX,
|
|
251
|
+
swaggerHash: createHash('sha256').update(rawSwagger).digest('hex').slice(0, 16),
|
|
252
|
+
permissions,
|
|
253
|
+
warnings,
|
|
254
|
+
operations,
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
//# sourceMappingURL=build-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-catalog.js","sourceRoot":"","sources":["../../src/api/build-catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/api/catalog.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Config } from '../config/config.js';
|
|
2
|
+
import { type PermissionMap } from './build-catalog.js';
|
|
1
3
|
import type { Catalog, Operation } from './types.js';
|
|
2
4
|
/** Найденная операция с оценкой релевантности. */
|
|
3
5
|
export interface OperationHit {
|
|
@@ -17,10 +19,27 @@ export interface OperationHit {
|
|
|
17
19
|
* полнотекстовый движок дал бы ту же выдачу при большем весе.
|
|
18
20
|
*/
|
|
19
21
|
export declare class OperationCatalog {
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
+
private byOpId;
|
|
23
|
+
catalog: Catalog;
|
|
22
24
|
constructor(catalog: Catalog);
|
|
23
|
-
|
|
25
|
+
/** Карта прав — единственное, что осталось предсобранным: её нет в swagger. */
|
|
26
|
+
static permissionMap(): PermissionMap;
|
|
27
|
+
/**
|
|
28
|
+
* Строит каталог из swagger подключённого стенда.
|
|
29
|
+
* Недоступный стенд не мешает серверу подняться: каталог получается пустым,
|
|
30
|
+
* а причина уходит в `warnings` и оттуда в `cms_guide` и `cms_whoami`.
|
|
31
|
+
* Пустой каталог безопасен — вызвать по нему нечего, — но молчать о нём нельзя.
|
|
32
|
+
*/
|
|
33
|
+
static resolve(config: Config, bearer?: string): Promise<OperationCatalog>;
|
|
34
|
+
/** Каталог не удалось собрать при старте — стенд был недоступен или закрыт авторизацией. */
|
|
35
|
+
get isEmpty(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Заменяет содержимое каталога, собранного вхолостую.
|
|
38
|
+
* Нужно remote-режиму: процесс поднимается без учётных данных, и если стенд
|
|
39
|
+
* отдаёт swagger только авторизованным, единственный шанс получить каталог —
|
|
40
|
+
* первая сессия с токеном. Каталог общий на процесс, поэтому и подмена одна.
|
|
41
|
+
*/
|
|
42
|
+
adopt(other: OperationCatalog): void;
|
|
24
43
|
get(opId: string): Operation | undefined;
|
|
25
44
|
operations(): readonly Operation[];
|
|
26
45
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/api/catalog.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/api/catalog.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAErD,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,EAAE,OAAO,CAAC;gBAEL,OAAO,EAAE,OAAO;IAS5B,+EAA+E;IAC/E,MAAM,CAAC,aAAa,IAAI,aAAa;IAMrC;;;;;OAKG;WACU,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA2ChF,4FAA4F;IAC5F,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAKpC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxC,UAAU,IAAI,SAAS,SAAS,EAAE;IAIlC;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE;IAU1C,MAAM,CAAC,MAAM,EAAE;QACb,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,YAAY,EAAE;CA+CnB"}
|
package/dist/api/catalog.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { dataDir } from '../knowledge/loader.js';
|
|
4
|
+
import { buildCatalog } from './build-catalog.js';
|
|
5
|
+
import { fetchSwagger } from './swagger-source.js';
|
|
4
6
|
/**
|
|
5
7
|
* Индекс каталога операций.
|
|
6
8
|
* Поиск здесь примитивный — подсчёт совпадений термов по склеенной строке.
|
|
@@ -14,13 +16,76 @@ export class OperationCatalog {
|
|
|
14
16
|
if (catalog.version !== 1) {
|
|
15
17
|
throw new Error(`Unsupported catalog version ${String(catalog.version)}`);
|
|
16
18
|
}
|
|
17
|
-
/**
|
|
19
|
+
/** Каталог собирается из документа, полученного по сети: поля нормализуем на входе. */
|
|
18
20
|
this.catalog = { ...catalog, warnings: catalog.warnings ?? [] };
|
|
19
21
|
this.byOpId = new Map(catalog.operations.map((o) => [o.opId, o]));
|
|
20
22
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
/** Карта прав — единственное, что осталось предсобранным: её нет в swagger. */
|
|
24
|
+
static permissionMap() {
|
|
25
|
+
const file = resolve(dataDir(), 'permissions.json');
|
|
26
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
27
|
+
return { byOpId: parsed.byOpId, permissions: parsed.permissions };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Строит каталог из swagger подключённого стенда.
|
|
31
|
+
* Недоступный стенд не мешает серверу подняться: каталог получается пустым,
|
|
32
|
+
* а причина уходит в `warnings` и оттуда в `cms_guide` и `cms_whoami`.
|
|
33
|
+
* Пустой каталог безопасен — вызвать по нему нечего, — но молчать о нём нельзя.
|
|
34
|
+
*/
|
|
35
|
+
static async resolve(config, bearer) {
|
|
36
|
+
const builtAt = new Date().toISOString();
|
|
37
|
+
try {
|
|
38
|
+
const swagger = await fetchSwagger({
|
|
39
|
+
baseUrl: config.baseUrl,
|
|
40
|
+
cacheDir: config.cacheDir,
|
|
41
|
+
timeoutMs: config.requestTimeoutMs,
|
|
42
|
+
...(bearer ? { bearer } : {}),
|
|
43
|
+
});
|
|
44
|
+
const catalog = buildCatalog({
|
|
45
|
+
rawSwagger: swagger.raw,
|
|
46
|
+
permissions: OperationCatalog.permissionMap(),
|
|
47
|
+
builtAt,
|
|
48
|
+
});
|
|
49
|
+
return new OperationCatalog(swagger.origin === 'cache'
|
|
50
|
+
? {
|
|
51
|
+
...catalog,
|
|
52
|
+
warnings: [
|
|
53
|
+
...catalog.warnings,
|
|
54
|
+
`The stand at ${config.baseUrl} was unreachable; this catalog came from the ` +
|
|
55
|
+
'on-disk cache and may not match the API that is actually running.',
|
|
56
|
+
],
|
|
57
|
+
}
|
|
58
|
+
: catalog);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
return new OperationCatalog({
|
|
62
|
+
version: 1,
|
|
63
|
+
builtAt,
|
|
64
|
+
apiPrefix: '/api/admin',
|
|
65
|
+
swaggerHash: '',
|
|
66
|
+
permissions: [],
|
|
67
|
+
warnings: [
|
|
68
|
+
`The operation catalog is EMPTY: ${config.baseUrl} did not serve its swagger ` +
|
|
69
|
+
`(${error instanceof Error ? error.message : String(error)}). ` +
|
|
70
|
+
'No API operation can be searched or called until the stand is reachable.',
|
|
71
|
+
],
|
|
72
|
+
operations: [],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Каталог не удалось собрать при старте — стенд был недоступен или закрыт авторизацией. */
|
|
77
|
+
get isEmpty() {
|
|
78
|
+
return this.catalog.operations.length === 0;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Заменяет содержимое каталога, собранного вхолостую.
|
|
82
|
+
* Нужно remote-режиму: процесс поднимается без учётных данных, и если стенд
|
|
83
|
+
* отдаёт swagger только авторизованным, единственный шанс получить каталог —
|
|
84
|
+
* первая сессия с токеном. Каталог общий на процесс, поэтому и подмена одна.
|
|
85
|
+
*/
|
|
86
|
+
adopt(other) {
|
|
87
|
+
this.catalog = other.catalog;
|
|
88
|
+
this.byOpId = new Map(other.catalog.operations.map((o) => [o.opId, o]));
|
|
24
89
|
}
|
|
25
90
|
get(opId) {
|
|
26
91
|
return this.byOpId.get(opId);
|
package/dist/api/catalog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/api/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/api/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAsB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAenD;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IACnB,MAAM,CAAyB;IACvC,OAAO,CAAU;IAEjB,YAAY,OAAgB;QAC1B,IAAI,OAAO,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,uFAAuF;QACvF,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QAChE,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,+EAA+E;IAC/E,MAAM,CAAC,aAAa;QAClB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkB,CAAC;QACvE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,MAAe;QAClD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC;gBACjC,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,SAAS,EAAE,MAAM,CAAC,gBAAgB;gBAClC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9B,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC;gBAC3B,UAAU,EAAE,OAAO,CAAC,GAAG;gBACvB,WAAW,EAAE,gBAAgB,CAAC,aAAa,EAAE;gBAC7C,OAAO;aACR,CAAC,CAAC;YACH,OAAO,IAAI,gBAAgB,CACzB,OAAO,CAAC,MAAM,KAAK,OAAO;gBACxB,CAAC,CAAC;oBACE,GAAG,OAAO;oBACV,QAAQ,EAAE;wBACR,GAAG,OAAO,CAAC,QAAQ;wBACnB,gBAAgB,MAAM,CAAC,OAAO,+CAA+C;4BAC3E,mEAAmE;qBACtE;iBACF;gBACH,CAAC,CAAC,OAAO,CACZ,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,gBAAgB,CAAC;gBAC1B,OAAO,EAAE,CAAC;gBACV,OAAO;gBACP,SAAS,EAAE,YAAY;gBACvB,WAAW,EAAE,EAAE;gBACf,WAAW,EAAE,EAAE;gBACf,QAAQ,EAAE;oBACR,mCAAmC,MAAM,CAAC,OAAO,6BAA6B;wBAC5E,IAAI,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK;wBAC/D,0EAA0E;iBAC7E;gBACD,UAAU,EAAE,EAAE;aACf,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,4FAA4F;IAC5F,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAuB;QAC3B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,IAAY,EAAE,KAAK,GAAG,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU;aAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;aAC5E,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;aAClC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;aACjC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;aACf,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,CAAC,MAMN;QACC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK;aACvB,WAAW,EAAE;aACb,KAAK,CAAC,SAAS,CAAC;aAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAmB,EAAE,CAAC;QAEhC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YAChD,IAAI,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC3E,SAAS;YACX,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;gBACtE,SAAS;YACX,CAAC;YACD,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,CAAC;gBACrF,SAAS;YACX,CAAC;YAED,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAChD,KAAK,IAAI,CAAC,CAAC;gBACb,CAAC;gBACD,IAAI,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/C,KAAK,IAAI,CAAC,CAAC;gBACb,CAAC;gBACD,IAAI,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBACxC,KAAK,IAAI,CAAC,CAAC;gBACb,CAAC;YACH,CAAC;YACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,IAAI,CAAC,IAAI,CAAC;oBACR,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE;oBACtC,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,GAAG,EAAE,SAAS,CAAC,GAAG;oBAClB,OAAO,EAAE,SAAS,CAAC,OAAO;oBAC1B,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACrE,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,KAAK;iBACN,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;CACF;AAED,iFAAiF;AACjF,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE;IAC/C,MAAM,KAAK,GAAG,CAAC,KAAa,EAAe,EAAE;QAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;AACpD,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { JsonSchema } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Разворачивает `$ref` и нормализует типы за один проход.
|
|
4
|
+
* Циклы (а они есть: сущности ссылаются друг на друга) обрываются заглушкой,
|
|
5
|
+
* иначе разворачивание не завершится; глубина ограничена, чтобы схема осталась читаемой.
|
|
6
|
+
*/
|
|
7
|
+
export declare const normalizeSchema: (node: unknown, components: Record<string, unknown>, depth?: number, refStack?: readonly string[]) => JsonSchema;
|
|
8
|
+
/**
|
|
9
|
+
* Урезает слишком большую схему до верхнего уровня свойств.
|
|
10
|
+
* Схема тела запроса уходит прямо в контекст модели, и развёрнутый DTO
|
|
11
|
+
* на 40 КБ вытеснит из него саму задачу.
|
|
12
|
+
*/
|
|
13
|
+
export declare const capSchema: (schema: JsonSchema) => JsonSchema;
|
|
14
|
+
//# sourceMappingURL=normalize-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-schema.d.ts","sourceRoot":"","sources":["../../src/api/normalize-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA2C7C;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,OAAO,EACb,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,cAAS,EACT,WAAU,SAAS,MAAM,EAAO,KAC/B,UA8FF,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,QAAQ,UAAU,KAAG,UAmB9C,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/** Валидные типы JSON Schema. Всё остальное в этом swagger — TypeScript-выражения. */
|
|
2
|
+
const VALID_TYPES = new Set(['object', 'array', 'string', 'number', 'integer', 'boolean', 'null']);
|
|
3
|
+
/**
|
|
4
|
+
* Приведение TypeScript-подобных типов из swagger к JSON Schema.
|
|
5
|
+
* Проект генерирует схемы из декораторов NestJS, и `type` часто содержит
|
|
6
|
+
* TS-выражение; таблица покрывает частые случаи, остальное помечается x-loose.
|
|
7
|
+
*/
|
|
8
|
+
const TYPE_MAP = {
|
|
9
|
+
date: { type: 'string', format: 'date-time' },
|
|
10
|
+
Date: { type: 'string', format: 'date-time' },
|
|
11
|
+
'iso-date': { type: 'string', format: 'date-time' },
|
|
12
|
+
float: { type: 'number' },
|
|
13
|
+
int: { type: 'integer' },
|
|
14
|
+
json: { type: 'object' },
|
|
15
|
+
list: { type: 'array' },
|
|
16
|
+
text: { type: 'string' },
|
|
17
|
+
textWithHeader: { type: 'string' },
|
|
18
|
+
image: { type: 'object' },
|
|
19
|
+
file: { type: 'object' },
|
|
20
|
+
'number[]': { type: 'array', items: { type: 'number' } },
|
|
21
|
+
'string[]': { type: 'array', items: { type: 'string' } },
|
|
22
|
+
};
|
|
23
|
+
const MAX_DESCRIPTION = 240;
|
|
24
|
+
const MAX_DEPTH = 6;
|
|
25
|
+
const trimDescription = (value) => {
|
|
26
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const flat = value.replace(/\s+/g, ' ').trim();
|
|
30
|
+
return flat.length > MAX_DESCRIPTION ? `${flat.slice(0, MAX_DESCRIPTION)}…` : flat;
|
|
31
|
+
};
|
|
32
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
33
|
+
/**
|
|
34
|
+
* Разворачивает `$ref` и нормализует типы за один проход.
|
|
35
|
+
* Циклы (а они есть: сущности ссылаются друг на друга) обрываются заглушкой,
|
|
36
|
+
* иначе разворачивание не завершится; глубина ограничена, чтобы схема осталась читаемой.
|
|
37
|
+
*/
|
|
38
|
+
export const normalizeSchema = (node, components, depth = 0, refStack = []) => {
|
|
39
|
+
if (!isRecord(node)) {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
const ref = node['$ref'];
|
|
43
|
+
if (typeof ref === 'string') {
|
|
44
|
+
const name = ref.split('/').pop() ?? '';
|
|
45
|
+
if (refStack.includes(name)) {
|
|
46
|
+
return { type: 'object', description: `(recursive ${name}, omitted)` };
|
|
47
|
+
}
|
|
48
|
+
const target = components[name];
|
|
49
|
+
if (target === undefined) {
|
|
50
|
+
return { type: 'object', description: `(unresolved ${name})` };
|
|
51
|
+
}
|
|
52
|
+
return normalizeSchema(target, components, depth, [...refStack, name]);
|
|
53
|
+
}
|
|
54
|
+
/** allOf/oneOf/anyOf в этом swagger встречаются только как обёртки — берём первый член. */
|
|
55
|
+
for (const key of ['allOf', 'oneOf', 'anyOf']) {
|
|
56
|
+
const variants = node[key];
|
|
57
|
+
if (Array.isArray(variants) && variants.length > 0) {
|
|
58
|
+
const merged = normalizeSchema(variants[0], components, depth, refStack);
|
|
59
|
+
const description = trimDescription(node['description']);
|
|
60
|
+
return description ? { ...merged, description } : merged;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const out = {};
|
|
64
|
+
const rawType = node['type'];
|
|
65
|
+
if (typeof rawType === 'string') {
|
|
66
|
+
if (VALID_TYPES.has(rawType)) {
|
|
67
|
+
out.type = rawType;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const mapped = TYPE_MAP[rawType];
|
|
71
|
+
if (mapped) {
|
|
72
|
+
out.type = mapped.type;
|
|
73
|
+
if (mapped.format) {
|
|
74
|
+
out.format = mapped.format;
|
|
75
|
+
}
|
|
76
|
+
if (mapped.items) {
|
|
77
|
+
out.items = mapped.items;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (rawType.startsWith('Record<')) {
|
|
81
|
+
out.type = 'object';
|
|
82
|
+
}
|
|
83
|
+
out['x-source-type'] = rawType;
|
|
84
|
+
out['x-loose'] = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const format = node['format'];
|
|
88
|
+
if (typeof format === 'string' && !out.format) {
|
|
89
|
+
out.format = format;
|
|
90
|
+
}
|
|
91
|
+
const description = trimDescription(node['description']);
|
|
92
|
+
if (description) {
|
|
93
|
+
out.description = description;
|
|
94
|
+
}
|
|
95
|
+
if (node['example'] !== undefined) {
|
|
96
|
+
out.example = node['example'];
|
|
97
|
+
}
|
|
98
|
+
if (Array.isArray(node['enum'])) {
|
|
99
|
+
out.enum = node['enum'];
|
|
100
|
+
}
|
|
101
|
+
if (depth >= MAX_DEPTH) {
|
|
102
|
+
out['x-truncated'] = true;
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
if (node['items'] !== undefined) {
|
|
106
|
+
out.items = normalizeSchema(node['items'], components, depth + 1, refStack);
|
|
107
|
+
if (!out.type) {
|
|
108
|
+
out.type = 'array';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const properties = node['properties'];
|
|
112
|
+
if (isRecord(properties)) {
|
|
113
|
+
out.type = out.type ?? 'object';
|
|
114
|
+
out.properties = {};
|
|
115
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
116
|
+
out.properties[key] = normalizeSchema(value, components, depth + 1, refStack);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const required = node['required'];
|
|
120
|
+
if (Array.isArray(required) && required.every((r) => typeof r === 'string')) {
|
|
121
|
+
out.required = required;
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
};
|
|
125
|
+
const MAX_SCHEMA_BYTES = 6_144;
|
|
126
|
+
/**
|
|
127
|
+
* Урезает слишком большую схему до верхнего уровня свойств.
|
|
128
|
+
* Схема тела запроса уходит прямо в контекст модели, и развёрнутый DTO
|
|
129
|
+
* на 40 КБ вытеснит из него саму задачу.
|
|
130
|
+
*/
|
|
131
|
+
export const capSchema = (schema) => {
|
|
132
|
+
if (Buffer.byteLength(JSON.stringify(schema), 'utf8') <= MAX_SCHEMA_BYTES) {
|
|
133
|
+
return schema;
|
|
134
|
+
}
|
|
135
|
+
if (!schema.properties) {
|
|
136
|
+
return { ...schema, 'x-truncated': true };
|
|
137
|
+
}
|
|
138
|
+
const shallow = {};
|
|
139
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
140
|
+
shallow[key] = {
|
|
141
|
+
...(value.type ? { type: value.type } : {}),
|
|
142
|
+
...(value.format ? { format: value.format } : {}),
|
|
143
|
+
...(value.description ? { description: value.description } : {}),
|
|
144
|
+
...(value.example !== undefined ? { example: value.example } : {}),
|
|
145
|
+
...(value['x-loose'] ? { 'x-loose': true } : {}),
|
|
146
|
+
...(value.properties || value.items ? { 'x-truncated': true } : {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return { ...schema, properties: shallow, 'x-truncated': true };
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=normalize-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-schema.js","sourceRoot":"","sources":["../../src/api/normalize-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Откуда и как забирать swagger. */
|
|
2
|
+
export interface SwaggerSource {
|
|
3
|
+
/** Базовый URL Admin API, уже нормализованный (с `/api/admin`, без слэша на конце). */
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
cacheDir: string;
|
|
6
|
+
timeoutMs: number;
|
|
7
|
+
/** Bearer-токен: нужен, если стенд закрывает этот эндпоинт авторизацией. */
|
|
8
|
+
bearer?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Полученный документ и то, откуда он взялся. */
|
|
11
|
+
export interface FetchedSwagger {
|
|
12
|
+
raw: string;
|
|
13
|
+
origin: 'stand' | 'cache';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Забирает swagger со стенда, с откатом на кэш.
|
|
17
|
+
* Эндпоинт публичный на большинстве стендов, поэтому первый запрос идёт без
|
|
18
|
+
* авторизации: в remote-режиме на момент старта процесса учётных данных может
|
|
19
|
+
* не быть вовсе. Токен добавляется только если стенд ответил 401/403.
|
|
20
|
+
*/
|
|
21
|
+
export declare const fetchSwagger: (source: SwaggerSource) => Promise<FetchedSwagger>;
|
|
22
|
+
//# sourceMappingURL=swagger-source.d.ts.map
|