bdy 1.25.1-stage → 1.25.2-dev

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.25.1-stage",
4
+ "version": "1.25.2-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "homepage": "https://buddy.works/docs/cli",
@@ -50,14 +50,12 @@
50
50
  ],
51
51
  "dependencies": {
52
52
  "@buddy-works/ci-info": "1.1.7",
53
+ "@buddy-works/docs-schema": "0.1.3",
53
54
  "@fastify/accept-negotiator": "2.0.1",
54
55
  "@fastify/cors": "11.2.0",
55
56
  "@inquirer/prompts": "8.5.2",
56
57
  "@modelcontextprotocol/sdk": "1.30.0",
57
58
  "@puppeteer/browsers": "3.2.0",
58
- "@scalar/json-magic": "0.12.16",
59
- "@scalar/openapi-parser": "0.28.7",
60
- "@scalar/openapi-types": "0.9.1",
61
59
  "@xhmikosr/decompress": "11.1.3",
62
60
  "ajv": "8.20.0",
63
61
  "ajv-formats": "3.0.1",
@@ -77,7 +75,6 @@
77
75
  "jsonwebtoken": "9.0.3",
78
76
  "mime-db": "1.54.0",
79
77
  "mime-types": "3.0.2",
80
- "minisearch": "7.2.0",
81
78
  "netmask": "2.1.1",
82
79
  "node-forge": "1.4.0",
83
80
  "open": "11.0.0",
@@ -105,7 +102,6 @@
105
102
  "@rollup/plugin-json": "6.1.0",
106
103
  "@rollup/plugin-node-resolve": "16.0.3",
107
104
  "@rollup/plugin-replace": "6.0.3",
108
- "@scalar/types": "0.13.2",
109
105
  "@stylistic/eslint-plugin": "5.10.0",
110
106
  "@types/basic-auth": "1.1.8",
111
107
  "@types/content-disposition": "0.5.9",
@@ -7,259 +7,255 @@ const utils_1 = require("../../utils");
7
7
  const texts_1 = require("../../texts");
8
8
  const input_1 = __importDefault(require("../../input"));
9
9
  const output_1 = __importDefault(require("../../output"));
10
- const logger_1 = __importDefault(require("../../logger"));
11
- var SCHEMA_TYPE;
12
- (function (SCHEMA_TYPE) {
13
- SCHEMA_TYPE["OBJECT"] = "object";
14
- SCHEMA_TYPE["ARRAY"] = "array";
15
- })(SCHEMA_TYPE || (SCHEMA_TYPE = {}));
16
- const getRequiredScopes = (data) => {
17
- if (data.security && data.security[0] && data.security[0].oauth2) {
18
- return data.security[0].oauth2;
19
- }
20
- return [];
10
+ /** `members` keeps declaration order, which numbers the listing; `values` does not. */
11
+ const orderedMembers = (body) => {
12
+ if (body.kind !== 'union')
13
+ return [];
14
+ const members = body.discriminator?.members;
15
+ return members ? Object.keys(members) : body.variants.map((one) => one.name);
16
+ };
17
+ const memberDef = (body, name) => body.discriminator?.members?.[name] ?? body.variants.find((one) => one.name === name)?.ref?.name;
18
+ const unionsOf = (doc) => {
19
+ const bodies = [];
20
+ for (const content of doc.request?.contents ?? [])
21
+ bodies.push(content.body);
22
+ for (const response of doc.responses)
23
+ for (const content of response.contents)
24
+ bodies.push(content.body);
25
+ return bodies.filter((body) => body.kind === 'union');
21
26
  };
22
- const getParameterType = (p) => {
23
- if (p.schema && p.schema.type) {
24
- return p.schema.type;
27
+ const memberMeta = async (api, doc) => {
28
+ const defs = new Set();
29
+ for (const body of unionsOf(doc)) {
30
+ if (body.kind !== 'union')
31
+ continue;
32
+ for (const name of orderedMembers(body)) {
33
+ const def = memberDef(body, name);
34
+ if (def)
35
+ defs.add(def);
36
+ }
37
+ }
38
+ const meta = new Map();
39
+ for (const def of defs) {
40
+ const type = await api.type(def);
41
+ const shown = type?.extensions?.['x-name'];
42
+ meta.set(def, {
43
+ ...(typeof shown === 'string' ? { shown } : {}),
44
+ deprecated: type?.deprecated === true,
45
+ });
25
46
  }
26
- return 'string';
47
+ return meta;
27
48
  };
28
- const outputParameters = (type, data, workspace, project) => {
29
- const table = [];
30
- (data.parameters || []).forEach((p) => {
31
- if (p.in === type) {
32
- let example = '-';
33
- if (p.name === 'workspace_domain')
34
- example = workspace;
35
- else if (p.name === 'project_name' && project)
36
- example = project;
37
- else if (p.schema && p.schema.example)
38
- example = p.schema.example;
39
- table.push([
40
- p.name || '-',
41
- getParameterType(p),
42
- example.toString(),
43
- p.description || '-',
44
- ]);
49
+ const scopesOf = (security) => {
50
+ const found = new Set();
51
+ for (const alternative of security) {
52
+ for (const requirement of alternative) {
53
+ for (const scope of requirement.scopes)
54
+ found.add(scope);
45
55
  }
46
- });
47
- if (table.length > 0) {
48
- table.unshift([
49
- type === 'path' ? 'URL param' : 'Query param',
50
- 'Type',
51
- 'Example',
52
- 'Description',
56
+ }
57
+ return [...found];
58
+ };
59
+ const exampleOf = (field, workspace, project) => {
60
+ if (field.name === 'workspace_domain')
61
+ return workspace;
62
+ if (field.name === 'project_name' && project)
63
+ return project;
64
+ return field.example === undefined ? '-' : String(field.example);
65
+ };
66
+ const outputParameters = (label, fields, workspace, project) => {
67
+ if (fields.length === 0)
68
+ return;
69
+ const table = [[label, 'Type', 'Example', 'Description']];
70
+ for (const field of fields) {
71
+ table.push([
72
+ field.name || '-',
73
+ field.type || 'string',
74
+ exampleOf(field, workspace, project),
75
+ field.description || '-',
53
76
  ]);
54
- output_1.default.table(table);
55
- output_1.default.normal('');
56
77
  }
78
+ output_1.default.table(table);
79
+ output_1.default.normal('');
57
80
  };
58
81
  const outputTextWithPadding = (text, padding = 1, newLine = true) => {
59
- let t = '';
60
- for (let i = 0; i < padding; i += 1)
61
- t += ' ';
62
- t += text;
63
- output_1.default.normal(t, newLine);
82
+ output_1.default.normal(' '.repeat(padding) + text, newLine);
64
83
  };
65
- const outputSimpleProp = (name, type, description, enu, required, padding) => {
84
+ const outputSimpleProp = (name, type, description, enumValues, required, padding) => {
66
85
  outputTextWithPadding(name, padding, false);
67
86
  output_1.default.gray(`: ${type}`, false);
68
87
  if (required)
69
88
  output_1.default.gray(' (required)', false);
70
89
  if (description)
71
90
  output_1.default.gray(` - ${description}`, false);
72
- if (enu && enu.length)
73
- output_1.default.gray(` - ${enu.join(', ')}`, false);
91
+ if (enumValues && enumValues.length)
92
+ output_1.default.gray(` - ${enumValues.join(', ')}`, false);
74
93
  output_1.default.normal('');
75
94
  };
76
- const outputJsonArrayProp = (data, padding, name, required) => {
77
- if (name) {
78
- outputTextWithPadding(name, padding, false);
79
- output_1.default.gray(`: ${SCHEMA_TYPE.ARRAY}`, false);
80
- if (required)
81
- output_1.default.gray(' (required)', false);
82
- if (data.description)
83
- output_1.default.gray(` - ${data.description}`, false);
84
- output_1.default.normal('');
95
+ const fieldsOf = (field, types) => field.ref?.elsewhere ? (types?.[field.ref.name]?.fields ?? []) : (field.fields ?? []);
96
+ const outputField = (field, padding, ctx, onPath) => {
97
+ if (field.constraints?.format === 'binary') {
98
+ outputSimpleProp(field.name, field.ref?.array ? 'binary array' : 'binary', field.description, undefined, field.required, padding);
99
+ return;
85
100
  }
86
- outputTextWithPadding('[', padding);
87
- if (name === 'trigger_operands') {
88
- outputTextWithPadding(' {...}', padding);
101
+ const named = field.ref?.name;
102
+ const children = named !== undefined && onPath.has(named) ? [] : fieldsOf(field, ctx.types);
103
+ const deeper = named === undefined ? onPath : new Set(onPath).add(named);
104
+ if (children.length === 0) {
105
+ outputSimpleProp(field.name, field.type, field.description, field.enum, field.required, padding);
106
+ return;
89
107
  }
90
- else {
91
- if (data.items.type === SCHEMA_TYPE.OBJECT)
92
- outputJsonObject(data.items, padding + 2);
93
- else if (data.items.type === SCHEMA_TYPE.ARRAY)
94
- outputJsonArrayProp(data.items, padding + 2);
95
- else
96
- outputSimpleProp('item', data.items.type, data.items.description, data.items.enum, false, padding + 2);
108
+ if (field.ref?.array) {
109
+ outputSimpleProp(field.name, 'array', field.description, undefined, field.required, padding);
110
+ outputTextWithPadding('[', padding);
111
+ outputFields(children, padding + 2, ctx, deeper);
112
+ outputTextWithPadding(']', padding);
113
+ return;
97
114
  }
98
- outputTextWithPadding(']', padding);
115
+ outputTextWithPadding(field.name, padding, false);
116
+ output_1.default.gray(' : object', false);
117
+ if (field.required)
118
+ output_1.default.gray(' (required)', false);
119
+ if (field.description)
120
+ output_1.default.gray(` - ${field.description}`, false);
121
+ output_1.default.normal('');
122
+ outputFields(children, padding, ctx, deeper);
99
123
  };
100
- const outputJsonObject = (data, padding = 1, name, required) => {
101
- const propsRequired = data.required || [];
102
- const props = data.properties || {};
103
- if (name) {
104
- outputTextWithPadding(name, padding, false);
105
- output_1.default.gray(` : ${SCHEMA_TYPE.OBJECT}`, false);
106
- if (required)
107
- output_1.default.gray(' (required)', false);
108
- if (data.description)
109
- output_1.default.gray(` - ${data.description}`, false);
110
- output_1.default.normal('');
111
- }
124
+ const outputFields = (fields, padding, ctx, onPath = new Set()) => {
112
125
  outputTextWithPadding('{', padding);
113
- const keys = Object.keys(props);
114
- if (keys.length > 0) {
115
- keys.forEach((name) => {
116
- const prop = props[name];
117
- if (prop.type === SCHEMA_TYPE.ARRAY)
118
- outputJsonArrayProp(prop, padding + 2, name, propsRequired.includes(name));
119
- else if (prop.type === SCHEMA_TYPE.OBJECT)
120
- outputJsonObject(prop, padding + 2, name, propsRequired.includes(name));
121
- else
122
- outputSimpleProp(name, prop.type, prop.description, prop.enum, propsRequired.includes(name), padding + 2);
123
- });
124
- }
125
- else if (data.additionalProperties) {
126
- outputTextWithPadding('key: value', padding + 2, false);
127
- if (data.additionalProperties.description)
128
- output_1.default.gray(` - ${data.additionalProperties.description}`, false);
129
- output_1.default.normal('');
130
- }
126
+ for (const field of fields)
127
+ outputField(field, padding + 2, ctx, onPath);
131
128
  outputTextWithPadding('}', padding);
132
129
  };
133
- const outputMultipartBinary = (name, array, description, required, padding) => {
134
- outputTextWithPadding(name, padding, false);
135
- output_1.default.gray(array ? ': binary array' : ': binary', false);
136
- if (required)
137
- output_1.default.gray(' (required)', false);
138
- if (description)
139
- output_1.default.gray(` - ${description}`, false);
140
- output_1.default.normal('');
141
- };
142
- const outputMultipartFormData = (data, padding = 1) => {
143
- const propsRequired = data.required || [];
144
- const props = data.properties || {};
145
- const keys = Object.keys(props);
146
- if (keys.length > 0) {
147
- keys.forEach((name) => {
148
- const prop = props[name];
149
- if (prop.format === 'binary')
150
- outputMultipartBinary(name, prop.type === 'array', prop.description, propsRequired.includes(name), padding);
151
- else if (prop.type === SCHEMA_TYPE.ARRAY)
152
- output_1.default.exitError(texts_1.ERR_API_MEDIA_TYPE_NOT_IMPLEMENTED);
153
- else if (prop.type === SCHEMA_TYPE.OBJECT)
154
- output_1.default.exitError(texts_1.ERR_API_MEDIA_TYPE_NOT_IMPLEMENTED);
155
- else
156
- outputSimpleProp(name, prop.type, prop.description, prop.enum, propsRequired.includes(name), padding);
157
- });
130
+ const outputUnion = (body, ctx, padding) => {
131
+ const names = orderedMembers(body);
132
+ // One variant means one was asked for; more than one is the listing.
133
+ const shown = body.variants.length === 1 ? body.variants[0] : undefined;
134
+ if (shown) {
135
+ outputFields([...body.shared, ...shown.fields], padding, ctx);
136
+ return;
158
137
  }
138
+ output_1.default.gray(` media type contains ${names.length} schemas:`);
139
+ names.forEach((name, index) => {
140
+ const def = memberDef(body, name);
141
+ const meta = def ? ctx.members.get(def) : undefined;
142
+ outputTextWithPadding(`${index + 1}: ${name}`, padding, false);
143
+ if (meta?.deprecated)
144
+ output_1.default.gray(' (deprecated)', false);
145
+ if (meta?.shown)
146
+ output_1.default.gray(` - ${meta.shown}`, false);
147
+ output_1.default.normal('');
148
+ });
149
+ outputTextWithPadding(`pass ${ctx.flag} with number or type to view it`);
159
150
  };
160
- const outputBodyObject = (mediaType, data) => {
161
- if (mediaType === 'multipart/form-data') {
162
- outputMultipartFormData(data);
163
- }
164
- else if (['application/json', 'application/jsonl'].includes(mediaType)) {
165
- outputJsonObject(data);
151
+ const outputBody = (body, ctx, padding = 1) => {
152
+ switch (body.kind) {
153
+ case 'none':
154
+ return;
155
+ case 'fields':
156
+ outputFields(body.fields, padding, ctx);
157
+ return;
158
+ case 'array':
159
+ outputTextWithPadding('[', padding);
160
+ outputBody(body.items, ctx, padding + 2);
161
+ outputTextWithPadding(']', padding);
162
+ return;
163
+ case 'value': {
164
+ outputTextWithPadding(body.type, padding, false);
165
+ if (body.description)
166
+ output_1.default.gray(` - ${body.description}`, false);
167
+ if (body.enum?.length)
168
+ output_1.default.gray(` - ${body.enum.join(', ')}`, false);
169
+ output_1.default.normal('');
170
+ return;
171
+ }
172
+ case 'union':
173
+ outputUnion(body, ctx, padding);
174
+ return;
166
175
  }
167
- else {
168
- output_1.default.exitError((0, texts_1.ERR_API_MEDIA_TYPE_NOT_IMPLEMENTED)(mediaType));
176
+ };
177
+ const outputContent = (content, ctx, first) => {
178
+ if (!first)
179
+ output_1.default.gray(' ------- or content type -------');
180
+ output_1.default.gray(' content-type: ', false);
181
+ output_1.default.normal(content.contentType ?? '-');
182
+ if (content.contentType === 'multipart/form-data' && content.body.kind === 'fields') {
183
+ for (const field of content.body.fields)
184
+ outputField(field, 1, ctx, new Set());
185
+ return;
169
186
  }
187
+ outputBody(content.body, ctx);
170
188
  };
171
- const outputResponse = (response, schema) => {
172
- const content = response.content || {};
173
- Object.keys(content).forEach((mediaType, index) => {
174
- if (index > 0) {
175
- output_1.default.gray(' ------- or content type -------');
176
- }
177
- outputMediaType(mediaType, content[mediaType], 'response-schema', schema);
189
+ const outputRequestBody = (doc, members) => {
190
+ // Declared with no content is not absent, and the header is all there is to say.
191
+ if (!doc.request)
192
+ return;
193
+ const contents = doc.request.contents;
194
+ const ctx = { types: doc.types, members, flag: '--request-schema' };
195
+ output_1.default.blue(` Request body`);
196
+ contents.forEach((content, index) => outputContent(content, ctx, index === 0));
197
+ output_1.default.normal('');
198
+ };
199
+ const outputResponsesBody = (doc, members) => {
200
+ if (doc.responses.length === 0)
201
+ return;
202
+ const ctx = { types: doc.types, members, flag: '--response-schema' };
203
+ output_1.default.blue(` Response body`);
204
+ doc.responses.forEach((response, index) => {
205
+ if (index > 0)
206
+ output_1.default.gray(' ------------');
207
+ output_1.default.gray(' http status: ', false);
208
+ output_1.default.normal(response.status);
209
+ response.contents.forEach((content, i) => outputContent(content, ctx, i === 0));
178
210
  });
179
211
  };
180
- const outputResponsesBody = (responses, schema) => {
181
- const r = responses || {};
182
- const codes = Object.keys(r);
183
- if (codes.length > 0) {
184
- output_1.default.blue(` Response body`);
185
- codes.forEach((code, index) => {
186
- if (index > 0) {
187
- output_1.default.gray(' ------------');
188
- }
189
- output_1.default.gray(' http status: ', false);
190
- output_1.default.normal(code);
191
- outputResponse(r[code], schema);
192
- });
193
- }
212
+ const chosen = (asked, names) => {
213
+ if (!asked)
214
+ return undefined;
215
+ if (names.includes(asked))
216
+ return asked;
217
+ const position = Number(asked);
218
+ return Number.isInteger(position) && position >= 1 ? names[position - 1] : undefined;
194
219
  };
195
- const outputMediaType = (mediaType, mediaTypeObject, schemaParamName, userSchema) => {
196
- output_1.default.gray(' content-type: ', false);
197
- output_1.default.normal(mediaType);
198
- if (mediaTypeObject.schema) {
199
- if (mediaTypeObject.schema.oneOf) {
200
- const schemas = mediaTypeObject.schema.oneOf;
201
- if (!schemas.length) {
202
- output_1.default.exitError(' media type does not contain any schemas');
203
- }
204
- else if (schemas.length === 1) {
205
- outputBodyObject(mediaType, schemas[0]);
206
- }
207
- else {
208
- const mappings = Object.keys(mediaTypeObject.schema.discriminator?.mapping || {});
209
- for (let i = 1; i <= schemas.length; i += 1) {
210
- if (i.toString() === userSchema) {
211
- outputBodyObject(mediaType, schemas[i]);
212
- return;
213
- }
214
- }
215
- for (let i = 0; i < mappings.length; i += 1) {
216
- if (mappings[i] === userSchema) {
217
- const schema = schemas[i];
218
- if (schema) {
219
- outputBodyObject(mediaType, schema);
220
- return;
221
- }
222
- }
223
- }
224
- output_1.default.gray(` media type contains ${schemas.length} schemas:`);
225
- for (let i = 1; i <= schemas.length; i += 1) {
226
- const mapping = mappings[i - 1];
227
- const name = mapping ? `${i}: ${mapping}` : `${i}`;
228
- outputTextWithPadding(name, 1, false);
229
- const schema = schemas[i - 1];
230
- logger_1.default.info(schema);
231
- if (schema) {
232
- if (schema.deprecated)
233
- output_1.default.gray(` (deprecated)`, false);
234
- const desc = schema['x-name'] || schema.title || schema.description;
235
- if (desc)
236
- output_1.default.gray(` - ${desc}`, false);
237
- }
238
- output_1.default.normal('');
239
- }
240
- outputTextWithPadding(`pass --${schemaParamName} with number or type to view it`);
241
- }
242
- }
243
- else {
244
- outputBodyObject(mediaType, mediaTypeObject.schema);
245
- }
220
+ const commandApiInfo = (0, utils_1.newCommand)('info', texts_1.DESC_COMMAND_API_INFO);
221
+ commandApiInfo.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
222
+ commandApiInfo.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
223
+ commandApiInfo.option('--request-schema <schema>', texts_1.OPT_COMMAND_API_INFO_SCHEMA);
224
+ commandApiInfo.option('--response-schema <schema>', texts_1.OPT_COMMAND_API_INFO_SCHEMA);
225
+ commandApiInfo.argument('<method>', texts_1.OPT_COMMAND_API_INFO_METHOD);
226
+ commandApiInfo.argument('<url>', texts_1.OPT_COMMAND_API_INFO_URL);
227
+ commandApiInfo.action(async (fm, filterUrl, options) => {
228
+ const { apiEndpoints } = require('../../openapi');
229
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
230
+ const project = input_1.default.restApiProject(options.project, true);
231
+ const method = (input_1.default.restApiMethod(fm, false) ?? '').toLowerCase();
232
+ const client = input_1.default.restApiTokenClient(true);
233
+ const api = await apiEndpoints(client.baseUrl);
234
+ const wanted = (await api.operations()).find((operation) => operation.method.toLowerCase() === method &&
235
+ (operation.path === filterUrl ||
236
+ (0, utils_1.openApiPrepareUrl)(operation.path, workspace, project) === filterUrl));
237
+ if (!wanted) {
238
+ output_1.default.exitError(texts_1.ERR_API_ENDPOINT_NOT_FOUND);
239
+ return;
246
240
  }
247
- };
248
- const outputRequestBody = (data, schema) => {
249
- if (data) {
250
- output_1.default.blue(` Request body`);
251
- const content = data.content || {};
252
- Object.keys(content).forEach((mediaType, index) => {
253
- if (index > 0) {
254
- output_1.default.gray(' ------- or content type -------');
255
- }
256
- outputMediaType(mediaType, content[mediaType], 'request-schema', schema);
257
- });
258
- output_1.default.normal('');
241
+ const listed = await api.endpoint(wanted.method, wanted.path);
242
+ if (!listed) {
243
+ output_1.default.exitError(texts_1.ERR_API_ENDPOINT_NOT_FOUND);
244
+ return;
259
245
  }
260
- };
261
- const outputUrl = (url, method, data, workspace, project, requestSchema, responseSchema) => {
262
- const m = (method || 'get').toUpperCase();
246
+ const namesOf = (bodies) => bodies.flatMap((body) => [...orderedMembers(body)]);
247
+ const request = chosen(options.requestSchema, namesOf((listed.request?.contents ?? []).map((content) => content.body)));
248
+ const response = chosen(options.responseSchema, namesOf(listed.responses.flatMap((one) => one.contents.map((content) => content.body))));
249
+ const member = request || response
250
+ ? { ...(request ? { request } : {}), ...(response ? { response } : {}) }
251
+ : undefined;
252
+ const doc = member ? await api.endpoint(wanted.method, wanted.path, member) : listed;
253
+ if (!doc) {
254
+ output_1.default.exitError(texts_1.ERR_API_ENDPOINT_NOT_FOUND);
255
+ return;
256
+ }
257
+ const members = await memberMeta(api, doc);
258
+ const m = doc.method.toUpperCase();
263
259
  if (m === 'GET')
264
260
  output_1.default.cyan(m, false);
265
261
  else if (m === 'POST')
@@ -270,48 +266,21 @@ const outputUrl = (url, method, data, workspace, project, requestSchema, respons
270
266
  output_1.default.yellow(m, false);
271
267
  else if (m === 'DELETE')
272
268
  output_1.default.error(m, false);
273
- output_1.default.normal(` ${url}`);
274
- if (data.summary)
275
- output_1.default.gray(data.summary, false);
276
- const scopes = getRequiredScopes(data);
269
+ output_1.default.normal(` ${(0, utils_1.openApiPrepareUrl)(doc.path, workspace, project)}`);
270
+ if (doc.summary)
271
+ output_1.default.gray(doc.summary, false);
272
+ const scopes = scopesOf(doc.security);
277
273
  if (scopes.length > 0) {
278
- if (data.summary)
274
+ if (doc.summary)
279
275
  output_1.default.gray('. ', false);
280
276
  output_1.default.gray(`${texts_1.TXT_API_ENDPOINT_REQUIRED_SCOPES}: `, false);
281
277
  output_1.default.gray(scopes.join(', '), false);
282
278
  }
283
279
  output_1.default.normal('\n');
284
- outputParameters('path', data, workspace, project);
285
- outputParameters('query', data, workspace, project);
286
- outputRequestBody(data.requestBody, requestSchema);
287
- outputResponsesBody(data.responses, responseSchema);
280
+ outputParameters('URL param', doc.parameters.path ?? [], workspace, project);
281
+ outputParameters('Query param', doc.parameters.query ?? [], workspace, project);
282
+ outputRequestBody(doc, members);
283
+ outputResponsesBody(doc, members);
288
284
  output_1.default.exitNormal();
289
- };
290
- const commandApiInfo = (0, utils_1.newCommand)('info', texts_1.DESC_COMMAND_API_INFO);
291
- commandApiInfo.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
292
- commandApiInfo.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
293
- commandApiInfo.option('--request-schema <schema>', texts_1.OPT_COMMAND_API_INFO_SCHEMA);
294
- commandApiInfo.option('--response-schema <schema>', texts_1.OPT_COMMAND_API_INFO_SCHEMA);
295
- commandApiInfo.argument('<method>', texts_1.OPT_COMMAND_API_INFO_METHOD);
296
- commandApiInfo.argument('<url>', texts_1.OPT_COMMAND_API_INFO_URL);
297
- commandApiInfo.action(async (fm, filterUrl, options) => {
298
- const { fetchOpenApiSchema } = require('../../openapi');
299
- const workspace = input_1.default.restApiWorkspace(options.workspace);
300
- const project = input_1.default.restApiProject(options.project, true);
301
- const filterMethod = input_1.default.restApiMethod(fm, false);
302
- const client = input_1.default.restApiTokenClient(true);
303
- const schema = await fetchOpenApiSchema(client.baseUrl);
304
- const paths = schema.paths || {};
305
- Object.keys(paths).forEach((url) => {
306
- const preparedUrl = (0, utils_1.openApiPrepareUrl)(url, workspace, project);
307
- if (filterUrl === url || filterUrl === preparedUrl) {
308
- const methods = paths[url] || {};
309
- Object.entries(methods).forEach(([method, data]) => {
310
- if (filterMethod === method)
311
- outputUrl(preparedUrl, method, data, workspace, project, options.requestSchema, options.responseSchema);
312
- });
313
- }
314
- });
315
- output_1.default.exitError(texts_1.ERR_API_ENDPOINT_NOT_FOUND);
316
285
  });
317
286
  exports.default = commandApiInfo;
@@ -7,8 +7,8 @@ const utils_1 = require("../../utils");
7
7
  const texts_1 = require("../../texts");
8
8
  const input_1 = __importDefault(require("../../input"));
9
9
  const output_1 = __importDefault(require("../../output"));
10
- const outputUrl = (url, method, data, workspace, project) => {
11
- const m = (method || 'get').toUpperCase();
10
+ const outputUrl = (operation, workspace, project) => {
11
+ const m = operation.method.toUpperCase();
12
12
  if (m === 'GET')
13
13
  output_1.default.cyan(m, false);
14
14
  else if (m === 'POST')
@@ -21,9 +21,9 @@ const outputUrl = (url, method, data, workspace, project) => {
21
21
  output_1.default.error(m, false);
22
22
  else
23
23
  output_1.default.blue(m, false);
24
- output_1.default.normal(` ${(0, utils_1.openApiPrepareUrl)(url, workspace, project)}`);
25
- if (data.summary)
26
- output_1.default.gray(data.summary);
24
+ output_1.default.normal(` ${(0, utils_1.openApiPrepareUrl)(operation.path, workspace, project)}`);
25
+ if (operation.summary)
26
+ output_1.default.gray(operation.summary);
27
27
  };
28
28
  const commandApiList = (0, utils_1.newCommand)('list', texts_1.DESC_COMMAND_API_LIST);
29
29
  commandApiList.alias('ls');
@@ -32,23 +32,20 @@ commandApiList.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
32
32
  commandApiList.option('-m, --method <method>', texts_1.OPT_COMMAND_API_LIST_METHOD);
33
33
  commandApiList.option('-s, --search <phrase>', texts_1.OPT_COMMAND_API_LIST_SEARCH);
34
34
  commandApiList.action(async (options) => {
35
- const { fetchOpenApiSchema } = require('../../openapi');
35
+ const { apiEndpoints } = require('../../openapi');
36
36
  const workspace = input_1.default.restApiWorkspace(options.workspace);
37
37
  const project = input_1.default.restApiProject(options.project, true);
38
38
  const filterMethod = input_1.default.restApiMethod(options.method);
39
39
  const filter = options.search;
40
40
  const client = input_1.default.restApiTokenClient(true);
41
- const schema = await fetchOpenApiSchema(client.baseUrl);
42
- const paths = schema.paths || {};
43
- Object.keys(paths).forEach((url) => {
44
- if (!filter || url.includes(filter)) {
45
- const methods = paths[url] || {};
46
- Object.entries(methods).forEach(([method, data]) => {
47
- if (!filterMethod || filterMethod === method)
48
- outputUrl(url, method, data, workspace, project);
49
- });
50
- }
51
- });
41
+ const api = await apiEndpoints(client.baseUrl);
42
+ for (const operation of await api.operations()) {
43
+ if (filter && !operation.path.includes(filter))
44
+ continue;
45
+ if (filterMethod && filterMethod !== operation.method.toLowerCase())
46
+ continue;
47
+ outputUrl(operation, workspace, project);
48
+ }
52
49
  output_1.default.exitNormal();
53
50
  });
54
51
  exports.default = commandApiList;