@base44-preview/cli 0.1.32-pr.663.a572ec8 → 0.1.32-pr.663.ab2ede0
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/cli/index.js +189 -165
- package/dist/cli/index.js.map +11 -10
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -249102,23 +249102,30 @@ var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
249102
249102
|
var SPACE_OR_PUNCTUATION = /[\n\r\p{Z}\p{P}]+/u;
|
|
249103
249103
|
|
|
249104
249104
|
// src/core/api-spec/search.ts
|
|
249105
|
-
var BOOST = {
|
|
249105
|
+
var BOOST = {
|
|
249106
|
+
method: 1,
|
|
249107
|
+
path: 8,
|
|
249108
|
+
summary: 5,
|
|
249109
|
+
description: 2,
|
|
249110
|
+
parameters: 0.5
|
|
249111
|
+
};
|
|
249106
249112
|
var MIN_RELATIVE_SCORE = 0.2;
|
|
249107
249113
|
var TOKEN_SEPARATOR = /[\n\r\p{Z}\p{P}\p{S}]+/u;
|
|
249108
|
-
var STOPWORDS = new Set("a an and are at be by do does for from how i in is it its me my of on or our that the this to we what who with you your".split(" "));
|
|
249114
|
+
var STOPWORDS = new Set("a an and are at be by do does for from how i id in is it its me my of on or our that the this to we what who with you your".split(" "));
|
|
249109
249115
|
function tokenize(text) {
|
|
249110
|
-
return text.split(TOKEN_SEPARATOR).filter((word) => word && !STOPWORDS.has(word.toLowerCase()));
|
|
249116
|
+
return text.split(TOKEN_SEPARATOR).filter((word) => word.length >= 2 && !STOPWORDS.has(word.toLowerCase()));
|
|
249111
249117
|
}
|
|
249112
249118
|
function toOperationSummary(op) {
|
|
249113
249119
|
return { endpoint: op.endpoint, summary: op.summary };
|
|
249114
249120
|
}
|
|
249115
249121
|
function buildSearchIndex(operations) {
|
|
249116
249122
|
const index = new MiniSearch({
|
|
249117
|
-
fields: ["path", "summary", "description", "parameters"],
|
|
249123
|
+
fields: ["method", "path", "summary", "description", "parameters"],
|
|
249118
249124
|
tokenize
|
|
249119
249125
|
});
|
|
249120
249126
|
index.addAll(operations.map((op, id) => ({
|
|
249121
249127
|
id,
|
|
249128
|
+
method: op.method,
|
|
249122
249129
|
path: op.path.replace(/\{[^}]*\}/g, ""),
|
|
249123
249130
|
summary: op.summary,
|
|
249124
249131
|
description: op.description,
|
|
@@ -249126,27 +249133,37 @@ function buildSearchIndex(operations) {
|
|
|
249126
249133
|
})));
|
|
249127
249134
|
return index;
|
|
249128
249135
|
}
|
|
249129
|
-
function
|
|
249130
|
-
const
|
|
249131
|
-
|
|
249132
|
-
|
|
249133
|
-
|
|
249134
|
-
|
|
249135
|
-
|
|
249136
|
+
function summaryMatch(terms, op) {
|
|
249137
|
+
const words = tokenize(op?.summary.toLowerCase() ?? "");
|
|
249138
|
+
const named = (word) => terms.some((term) => word.startsWith(term));
|
|
249139
|
+
return {
|
|
249140
|
+
coverage: terms.filter((term) => words.some((word) => word.startsWith(term))).length / terms.length,
|
|
249141
|
+
precision: words.length ? words.filter(named).length / words.length : 0
|
|
249142
|
+
};
|
|
249136
249143
|
}
|
|
249144
|
+
var readsFirst = (op) => op?.method === "GET" ? 0 : 1;
|
|
249137
249145
|
function searchOperations(operations, query, options = {}) {
|
|
249146
|
+
const terms = tokenize(query.toLowerCase());
|
|
249147
|
+
if (terms.length === 0) {
|
|
249148
|
+
return [];
|
|
249149
|
+
}
|
|
249138
249150
|
const index = buildSearchIndex(operations);
|
|
249139
249151
|
const hits = index.search(query, {
|
|
249140
249152
|
prefix: (term) => term.length >= 3,
|
|
249141
249153
|
fuzzy: (term) => term.length >= 4 ? 0.2 : false,
|
|
249142
249154
|
boost: BOOST,
|
|
249143
249155
|
filter: options.readOnly ? (hit) => operations[hit.id]?.readOnly === true : undefined
|
|
249144
|
-
}).map((hit) =>
|
|
249145
|
-
|
|
249146
|
-
|
|
249147
|
-
|
|
249148
|
-
|
|
249149
|
-
|
|
249156
|
+
}).map((hit) => {
|
|
249157
|
+
const match = summaryMatch(terms, operations[hit.id]);
|
|
249158
|
+
return {
|
|
249159
|
+
...hit,
|
|
249160
|
+
...match,
|
|
249161
|
+
full: match.coverage === 1,
|
|
249162
|
+
score: hit.score * (1 + match.coverage)
|
|
249163
|
+
};
|
|
249164
|
+
}).sort((a, b) => Number(b.full) - Number(a.full) || (a.full ? b.precision - a.precision || readsFirst(operations[a.id]) - readsFirst(operations[b.id]) : 0) || b.score - a.score);
|
|
249165
|
+
const baseline = Math.max(0, ...hits.map((hit) => hit.score)) * MIN_RELATIVE_SCORE;
|
|
249166
|
+
return hits.filter((hit) => hit.full || hit.score >= baseline).slice(0, options.limit ?? 5).flatMap((hit) => {
|
|
249150
249167
|
const op = operations[hit.id];
|
|
249151
249168
|
return op ? [toOperationSummary(op)] : [];
|
|
249152
249169
|
});
|
|
@@ -249177,7 +249194,7 @@ function groupByArea(operations) {
|
|
|
249177
249194
|
}
|
|
249178
249195
|
return new Map([...areas].sort(([a], [b]) => byCodePoint(a, b)));
|
|
249179
249196
|
}
|
|
249180
|
-
function
|
|
249197
|
+
function readsFirst2(ops) {
|
|
249181
249198
|
const isRead = (op) => op.method === "GET" ? 0 : 1;
|
|
249182
249199
|
return [...ops].sort((a, b) => isRead(a) - isRead(b));
|
|
249183
249200
|
}
|
|
@@ -249185,7 +249202,7 @@ function catalogIndex(operations) {
|
|
|
249185
249202
|
const areas = [...groupByArea(operations)].map(([area, ops]) => ops.length <= INLINE_AREA_MAX ? { area, operations: ops.map(toOperationSummary) } : {
|
|
249186
249203
|
area,
|
|
249187
249204
|
operationCount: ops.length,
|
|
249188
|
-
sample:
|
|
249205
|
+
sample: readsFirst2(ops).slice(0, AREA_SAMPLE_MAX).map((op) => op.summary)
|
|
249189
249206
|
});
|
|
249190
249207
|
return { areas, total: operations.length };
|
|
249191
249208
|
}
|
|
@@ -249197,44 +249214,6 @@ function areaListing(area, operations, max = AREA_OPERATIONS_MAX) {
|
|
|
249197
249214
|
truncated: operations.length > max
|
|
249198
249215
|
};
|
|
249199
249216
|
}
|
|
249200
|
-
// src/core/api-spec/grep.ts
|
|
249201
|
-
var CONTEXT_CHARS = 40;
|
|
249202
|
-
var MAX_SNIPPETS = 3;
|
|
249203
|
-
var MAX_SNIPPET_CHARS = 200;
|
|
249204
|
-
function unescapeJson(snippet) {
|
|
249205
|
-
return snippet.replace(/\\[nrt]/g, " ").replace(/\\"/g, '"');
|
|
249206
|
-
}
|
|
249207
|
-
function snippets(text, pattern) {
|
|
249208
|
-
const found = [];
|
|
249209
|
-
for (const match of text.matchAll(pattern)) {
|
|
249210
|
-
const start = Math.max(0, match.index - CONTEXT_CHARS);
|
|
249211
|
-
const end = match.index + match[0].length + CONTEXT_CHARS;
|
|
249212
|
-
found.push(unescapeJson(text.slice(start, Math.min(end, start + MAX_SNIPPET_CHARS))));
|
|
249213
|
-
if (found.length === MAX_SNIPPETS || match[0].length === 0) {
|
|
249214
|
-
break;
|
|
249215
|
-
}
|
|
249216
|
-
}
|
|
249217
|
-
return found;
|
|
249218
|
-
}
|
|
249219
|
-
function grepSpec(spec, operations, pattern, options = {}) {
|
|
249220
|
-
const regex = new RegExp(pattern, options.ignoreCase ? "gi" : "g");
|
|
249221
|
-
const hits = [];
|
|
249222
|
-
for (const op of operations) {
|
|
249223
|
-
const { summary, description, parameters, requestBody, responses } = op.operation;
|
|
249224
|
-
const matches = snippets(`${op.endpoint} ${JSON.stringify({ summary, description, parameters, requestBody, responses })}`, regex);
|
|
249225
|
-
if (matches.length > 0) {
|
|
249226
|
-
hits.push({ ...toOperationSummary(op), matches });
|
|
249227
|
-
}
|
|
249228
|
-
}
|
|
249229
|
-
const schemas = options.schemas === false ? {} : spec.components?.schemas;
|
|
249230
|
-
for (const [schema, definition] of Object.entries(schemas ?? {})) {
|
|
249231
|
-
const matches = snippets(JSON.stringify(definition), regex);
|
|
249232
|
-
if (matches.length > 0) {
|
|
249233
|
-
hits.push({ schema, matches });
|
|
249234
|
-
}
|
|
249235
|
-
}
|
|
249236
|
-
return hits.slice(0, options.limit ?? 20);
|
|
249237
|
-
}
|
|
249238
249217
|
// src/core/api-spec/schema.ts
|
|
249239
249218
|
var HTTP_METHODS = [
|
|
249240
249219
|
"get",
|
|
@@ -249255,7 +249234,7 @@ var ParameterSchema = looseObject({
|
|
|
249255
249234
|
example: unknown().optional()
|
|
249256
249235
|
});
|
|
249257
249236
|
var MediaTypesSchema = record(string2(), looseObject({ schema: unknown().optional() }));
|
|
249258
|
-
var
|
|
249237
|
+
var MediaContentSchema = looseObject({
|
|
249259
249238
|
content: MediaTypesSchema.optional()
|
|
249260
249239
|
});
|
|
249261
249240
|
var ResponseObjectSchema = looseObject({
|
|
@@ -249285,88 +249264,7 @@ var OpenApiSpecSchema = looseObject({
|
|
|
249285
249264
|
security: array(SecurityRequirementSchema).optional()
|
|
249286
249265
|
});
|
|
249287
249266
|
|
|
249288
|
-
// src/core/api-spec/
|
|
249289
|
-
var PERSONAL_ACCESS_TOKEN_SCHEME = "PersonalAccessTokenAuth";
|
|
249290
|
-
var READ_ONLY_SCOPE = "read_only";
|
|
249291
|
-
function isReadOnly(operation, spec) {
|
|
249292
|
-
const security = operation.security ?? spec.security ?? [];
|
|
249293
|
-
return security.some((requirement) => requirement[PERSONAL_ACCESS_TOKEN_SCHEME]?.includes(READ_ONLY_SCOPE));
|
|
249294
|
-
}
|
|
249295
|
-
function parameterText(operation) {
|
|
249296
|
-
return (operation.parameters ?? []).flatMap((parameter) => {
|
|
249297
|
-
const parsed = ParameterSchema.safeParse(parameter);
|
|
249298
|
-
return parsed.success ? [parsed.data.name, parsed.data.description ?? ""] : [];
|
|
249299
|
-
}).join(" ");
|
|
249300
|
-
}
|
|
249301
|
-
function mergeParameters(shared, own) {
|
|
249302
|
-
if (!shared?.length) {
|
|
249303
|
-
return own;
|
|
249304
|
-
}
|
|
249305
|
-
const key = (parameter) => {
|
|
249306
|
-
const parsed = ParameterSchema.safeParse(parameter);
|
|
249307
|
-
return parsed.success ? `${parsed.data.in}:${parsed.data.name}` : undefined;
|
|
249308
|
-
};
|
|
249309
|
-
const ownKeys = new Set((own ?? []).map(key));
|
|
249310
|
-
return [
|
|
249311
|
-
...shared.filter((parameter) => !ownKeys.has(key(parameter))),
|
|
249312
|
-
...own ?? []
|
|
249313
|
-
];
|
|
249314
|
-
}
|
|
249315
|
-
function listOperations(spec) {
|
|
249316
|
-
return Object.entries(spec.paths).flatMap(([path, item]) => HTTP_METHODS.flatMap((method) => {
|
|
249317
|
-
const declared = item[method];
|
|
249318
|
-
if (!declared) {
|
|
249319
|
-
return [];
|
|
249320
|
-
}
|
|
249321
|
-
const operation = {
|
|
249322
|
-
...declared,
|
|
249323
|
-
parameters: mergeParameters(item.parameters, declared.parameters)
|
|
249324
|
-
};
|
|
249325
|
-
return [
|
|
249326
|
-
{
|
|
249327
|
-
endpoint: `${method.toUpperCase()} ${path}`,
|
|
249328
|
-
method: method.toUpperCase(),
|
|
249329
|
-
path,
|
|
249330
|
-
summary: operation.summary ?? "",
|
|
249331
|
-
description: operation.description ?? "",
|
|
249332
|
-
parameterText: parameterText(operation),
|
|
249333
|
-
readOnly: isReadOnly(operation, spec),
|
|
249334
|
-
operation
|
|
249335
|
-
}
|
|
249336
|
-
];
|
|
249337
|
-
}));
|
|
249338
|
-
}
|
|
249339
|
-
function pathSegments(path) {
|
|
249340
|
-
const pathname = path.split(/[?#]/, 1)[0] ?? "";
|
|
249341
|
-
return pathname.split("/").filter(Boolean);
|
|
249342
|
-
}
|
|
249343
|
-
function segmentPattern(segment) {
|
|
249344
|
-
const source = segment.split(/(\{[^}]+\})/).map((part) => part.startsWith("{") ? "[^/]+" : part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
|
|
249345
|
-
return new RegExp(`^${source}$`);
|
|
249346
|
-
}
|
|
249347
|
-
function specificity(templateSegments) {
|
|
249348
|
-
return templateSegments.map((segment) => segment.includes("{") ? 0 : 1);
|
|
249349
|
-
}
|
|
249350
|
-
function compareSpecificity(a, b) {
|
|
249351
|
-
for (let i = 0;i < a.length; i++) {
|
|
249352
|
-
if (a[i] !== b[i]) {
|
|
249353
|
-
return (b[i] ?? 0) - (a[i] ?? 0);
|
|
249354
|
-
}
|
|
249355
|
-
}
|
|
249356
|
-
return 0;
|
|
249357
|
-
}
|
|
249358
|
-
function matchOperation(operations, method, concretePath) {
|
|
249359
|
-
const upperMethod = method.toUpperCase();
|
|
249360
|
-
const segments = pathSegments(concretePath);
|
|
249361
|
-
const candidates = operations.filter((op) => {
|
|
249362
|
-
if (op.method !== upperMethod) {
|
|
249363
|
-
return false;
|
|
249364
|
-
}
|
|
249365
|
-
const template = pathSegments(op.path);
|
|
249366
|
-
return template.length === segments.length && template.every((part, i) => segmentPattern(part).test(segments[i] ?? ""));
|
|
249367
|
-
});
|
|
249368
|
-
return candidates.sort((a, b) => compareSpecificity(specificity(pathSegments(a.path)), specificity(pathSegments(b.path))))[0];
|
|
249369
|
-
}
|
|
249267
|
+
// src/core/api-spec/contract.ts
|
|
249370
249268
|
var SCHEMA_REF_PREFIX = "#/components/schemas/";
|
|
249371
249269
|
var MAX_REF_DEPTH = 4;
|
|
249372
249270
|
var FRAMEWORK_VALIDATION_ERROR = "Validation Error";
|
|
@@ -249394,12 +249292,8 @@ function inlineRefs(node, schemas, seen = new Set, depth = 0) {
|
|
|
249394
249292
|
inlineRefs(value, schemas, seen, depth)
|
|
249395
249293
|
]));
|
|
249396
249294
|
}
|
|
249397
|
-
function
|
|
249398
|
-
const parsed =
|
|
249399
|
-
return parsed.success ? parsed.data.content?.["application/json"]?.schema : undefined;
|
|
249400
|
-
}
|
|
249401
|
-
function requestBodyOf(value) {
|
|
249402
|
-
const parsed = RequestBodySchema.safeParse(value);
|
|
249295
|
+
function bodyOf(value) {
|
|
249296
|
+
const parsed = MediaContentSchema.safeParse(value);
|
|
249403
249297
|
const content = parsed.success ? parsed.data.content ?? {} : {};
|
|
249404
249298
|
const contentType = "application/json" in content ? "application/json" : Object.keys(content)[0];
|
|
249405
249299
|
return contentType ? { contentType, schema: content[contentType]?.schema } : {};
|
|
@@ -249422,22 +249316,63 @@ function leftoverRefs(node, schemas, found = new Map) {
|
|
|
249422
249316
|
}
|
|
249423
249317
|
return found;
|
|
249424
249318
|
}
|
|
249319
|
+
var SCHEMA_DATA_KEYS = new Set([
|
|
249320
|
+
"example",
|
|
249321
|
+
"examples",
|
|
249322
|
+
"default",
|
|
249323
|
+
"enum",
|
|
249324
|
+
"const"
|
|
249325
|
+
]);
|
|
249326
|
+
var DOCS_CALLOUT = /<(Info|Note|Tip|Check|Warning)>([\s\S]*?)<\/\1>/g;
|
|
249327
|
+
var RELATIVE_LINK = /\[([^\]]+)\]\(\/[^)]*\)/g;
|
|
249328
|
+
function cleanText(text) {
|
|
249329
|
+
return text.replace(DOCS_CALLOUT, (_, kind, body) => kind === "Warning" ? `Warning: ${body}` : body).replace(RELATIVE_LINK, "$1");
|
|
249330
|
+
}
|
|
249331
|
+
function slimSchema(node, isPropertyMap = false) {
|
|
249332
|
+
if (Array.isArray(node)) {
|
|
249333
|
+
return node.map((item) => slimSchema(item));
|
|
249334
|
+
}
|
|
249335
|
+
if (node === null || typeof node !== "object") {
|
|
249336
|
+
return node;
|
|
249337
|
+
}
|
|
249338
|
+
const entries = Object.entries(node);
|
|
249339
|
+
if (isPropertyMap) {
|
|
249340
|
+
return Object.fromEntries(entries.map(([name, value]) => [name, slimSchema(value)]));
|
|
249341
|
+
}
|
|
249342
|
+
const slim = {};
|
|
249343
|
+
for (const [key, value] of entries) {
|
|
249344
|
+
if (key === "title" && typeof value === "string") {
|
|
249345
|
+
continue;
|
|
249346
|
+
}
|
|
249347
|
+
slim[key] = SCHEMA_DATA_KEYS.has(key) ? value : key === "properties" ? slimSchema(value, true) : key === "description" && typeof value === "string" ? cleanText(value) : slimSchema(value);
|
|
249348
|
+
}
|
|
249349
|
+
const { anyOf, ...rest } = slim;
|
|
249350
|
+
const nullable = Array.isArray(anyOf) && anyOf.length === 2 ? nullableType(anyOf) : undefined;
|
|
249351
|
+
return nullable ? { type: [nullable, "null"], ...rest } : slim;
|
|
249352
|
+
}
|
|
249353
|
+
function nullableType(variants) {
|
|
249354
|
+
const types = variants.map((variant) => variant !== null && typeof variant === "object" && Object.keys(variant).length === 1 && typeof variant.type === "string" ? variant.type : undefined);
|
|
249355
|
+
if (types.includes(undefined) || !types.includes("null")) {
|
|
249356
|
+
return;
|
|
249357
|
+
}
|
|
249358
|
+
return types.find((type) => type !== "null");
|
|
249359
|
+
}
|
|
249425
249360
|
function getOperationContract(spec, op) {
|
|
249426
249361
|
const schemas = spec.components?.schemas ?? {};
|
|
249427
|
-
const inline = (node) => node === undefined ? null : inlineRefs(node, schemas);
|
|
249362
|
+
const inline = (node) => node === undefined ? null : slimSchema(inlineRefs(node, schemas));
|
|
249428
249363
|
const responses = Object.entries(op.operation.responses ?? {}).flatMap(([status, response]) => {
|
|
249429
249364
|
const parsed = ResponseObjectSchema.safeParse(response);
|
|
249430
249365
|
return parsed.success ? [[status, parsed.data]] : [];
|
|
249431
249366
|
});
|
|
249432
|
-
const success = responses.filter(([status]) => status.startsWith("2")).sort(([a], [b]) => a.localeCompare(b)).map(([, response]) =>
|
|
249367
|
+
const success = responses.filter(([status]) => status.startsWith("2")).sort(([a], [b]) => a.localeCompare(b)).map(([, response]) => bodyOf(response).schema).find(Boolean);
|
|
249433
249368
|
const errors = responses.filter(([status, response]) => !status.startsWith("2") && response.description !== FRAMEWORK_VALIDATION_ERROR);
|
|
249434
|
-
const requestBody =
|
|
249369
|
+
const requestBody = bodyOf(op.operation.requestBody);
|
|
249435
249370
|
const contract = {
|
|
249436
249371
|
endpoint: op.endpoint,
|
|
249437
249372
|
method: op.method,
|
|
249438
249373
|
path: op.path,
|
|
249439
249374
|
summary: op.summary,
|
|
249440
|
-
description: op.description,
|
|
249375
|
+
description: cleanText(op.description),
|
|
249441
249376
|
parameters: (op.operation.parameters ?? []).flatMap((parameter) => {
|
|
249442
249377
|
const parsed = ParameterSchema.safeParse(parameter);
|
|
249443
249378
|
if (!parsed.success) {
|
|
@@ -249451,7 +249386,7 @@ function getOperationContract(spec, op) {
|
|
|
249451
249386
|
in: location2,
|
|
249452
249387
|
required: required ?? false,
|
|
249453
249388
|
schema: inline(schema ?? {}),
|
|
249454
|
-
...description && !inSchema ? { description } : {},
|
|
249389
|
+
...description && !inSchema ? { description: cleanText(description) } : {},
|
|
249455
249390
|
..."example" in parsed.data ? { example: parsed.data.example } : {}
|
|
249456
249391
|
}
|
|
249457
249392
|
];
|
|
@@ -249459,13 +249394,97 @@ function getOperationContract(spec, op) {
|
|
|
249459
249394
|
...requestBody.contentType && requestBody.contentType !== "application/json" ? { requestBodyContentType: requestBody.contentType } : {},
|
|
249460
249395
|
requestBodySchema: inline(requestBody.schema),
|
|
249461
249396
|
responseSchema: inline(success),
|
|
249462
|
-
errors: Object.fromEntries(errors.map(([status, response]) => [
|
|
249397
|
+
errors: Object.fromEntries(errors.map(([status, response]) => [
|
|
249398
|
+
status,
|
|
249399
|
+
cleanText(response.description ?? "")
|
|
249400
|
+
]))
|
|
249463
249401
|
};
|
|
249464
249402
|
const refs = leftoverRefs(contract, schemas);
|
|
249465
249403
|
return {
|
|
249466
249404
|
...contract,
|
|
249467
|
-
...refs.size > 0 ? {
|
|
249405
|
+
...refs.size > 0 ? {
|
|
249406
|
+
refs: Object.fromEntries([...refs].map(([ref, schema]) => [ref, slimSchema(schema)]))
|
|
249407
|
+
} : {}
|
|
249408
|
+
};
|
|
249409
|
+
}
|
|
249410
|
+
// src/core/api-spec/grep.ts
|
|
249411
|
+
function grepOperations(spec, operations, pattern, options = {}) {
|
|
249412
|
+
const regex = new RegExp(pattern, options.ignoreCase ? "i" : "");
|
|
249413
|
+
return operations.filter((op) => regex.test(JSON.stringify(getOperationContract(spec, op)))).slice(0, options.limit ?? 20).map(toOperationSummary);
|
|
249414
|
+
}
|
|
249415
|
+
// src/core/api-spec/operations.ts
|
|
249416
|
+
var PERSONAL_ACCESS_TOKEN_SCHEME = "PersonalAccessTokenAuth";
|
|
249417
|
+
var READ_ONLY_SCOPE = "read_only";
|
|
249418
|
+
function isReadOnly(operation, spec) {
|
|
249419
|
+
const security = operation.security ?? spec.security ?? [];
|
|
249420
|
+
return security.some((requirement) => requirement[PERSONAL_ACCESS_TOKEN_SCHEME]?.includes(READ_ONLY_SCOPE));
|
|
249421
|
+
}
|
|
249422
|
+
function parameterText(operation) {
|
|
249423
|
+
return (operation.parameters ?? []).flatMap((parameter) => {
|
|
249424
|
+
const parsed = ParameterSchema.safeParse(parameter);
|
|
249425
|
+
return parsed.success ? [parsed.data.name, parsed.data.description ?? ""] : [];
|
|
249426
|
+
}).join(" ");
|
|
249427
|
+
}
|
|
249428
|
+
function mergeParameters(shared, own) {
|
|
249429
|
+
if (!shared?.length) {
|
|
249430
|
+
return own;
|
|
249431
|
+
}
|
|
249432
|
+
const key = (parameter) => {
|
|
249433
|
+
const parsed = ParameterSchema.safeParse(parameter);
|
|
249434
|
+
return parsed.success ? `${parsed.data.in}:${parsed.data.name}` : undefined;
|
|
249468
249435
|
};
|
|
249436
|
+
const ownKeys = new Set((own ?? []).map(key));
|
|
249437
|
+
return [
|
|
249438
|
+
...shared.filter((parameter) => !ownKeys.has(key(parameter))),
|
|
249439
|
+
...own ?? []
|
|
249440
|
+
];
|
|
249441
|
+
}
|
|
249442
|
+
function listOperations(spec) {
|
|
249443
|
+
return Object.entries(spec.paths).flatMap(([path, item]) => HTTP_METHODS.flatMap((method) => {
|
|
249444
|
+
const declared = item[method];
|
|
249445
|
+
if (!declared) {
|
|
249446
|
+
return [];
|
|
249447
|
+
}
|
|
249448
|
+
const operation = {
|
|
249449
|
+
...declared,
|
|
249450
|
+
parameters: mergeParameters(item.parameters, declared.parameters)
|
|
249451
|
+
};
|
|
249452
|
+
return [
|
|
249453
|
+
{
|
|
249454
|
+
endpoint: `${method.toUpperCase()} ${path}`,
|
|
249455
|
+
method: method.toUpperCase(),
|
|
249456
|
+
path,
|
|
249457
|
+
summary: operation.summary ?? "",
|
|
249458
|
+
description: operation.description ?? "",
|
|
249459
|
+
parameterText: parameterText(operation),
|
|
249460
|
+
readOnly: isReadOnly(operation, spec),
|
|
249461
|
+
operation
|
|
249462
|
+
}
|
|
249463
|
+
];
|
|
249464
|
+
}));
|
|
249465
|
+
}
|
|
249466
|
+
function pathSegments(path) {
|
|
249467
|
+
const pathname = path.split(/[?#]/, 1)[0] ?? "";
|
|
249468
|
+
return pathname.split("/").filter(Boolean);
|
|
249469
|
+
}
|
|
249470
|
+
function segmentPattern(segment) {
|
|
249471
|
+
const source = segment.split(/(\{[^}]+\})/).map((part) => part.startsWith("{") ? "[^/]+" : part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
|
|
249472
|
+
return new RegExp(`^${source}$`);
|
|
249473
|
+
}
|
|
249474
|
+
function literalSegments(path) {
|
|
249475
|
+
return pathSegments(path).map((segment) => segment.includes("{") ? "0" : "1").join("");
|
|
249476
|
+
}
|
|
249477
|
+
function matchOperation(operations, method, concretePath) {
|
|
249478
|
+
const upperMethod = method.toUpperCase();
|
|
249479
|
+
const segments = pathSegments(concretePath);
|
|
249480
|
+
const candidates = operations.filter((op) => {
|
|
249481
|
+
if (op.method !== upperMethod) {
|
|
249482
|
+
return false;
|
|
249483
|
+
}
|
|
249484
|
+
const template = pathSegments(op.path);
|
|
249485
|
+
return template.length === segments.length && template.every((part, i) => segmentPattern(part).test(segments[i] ?? ""));
|
|
249486
|
+
});
|
|
249487
|
+
return candidates.sort((a, b) => literalSegments(b.path).localeCompare(literalSegments(a.path)))[0];
|
|
249469
249488
|
}
|
|
249470
249489
|
// src/core/api-spec/request.ts
|
|
249471
249490
|
var MAX_ERROR_BODY_CHARS = 4000;
|
|
@@ -249493,7 +249512,8 @@ async function sendApiRequest(method, path, body) {
|
|
|
249493
249512
|
} catch (error) {
|
|
249494
249513
|
const apiError = await ApiError.fromHttpError(error, `calling ${method} ${path}`);
|
|
249495
249514
|
const raw = error instanceof HTTPError ? await readBody(error.response) : undefined;
|
|
249496
|
-
|
|
249515
|
+
const message = raw && apiError.statusCode !== undefined ? `Error calling ${method} ${path}: HTTP ${apiError.statusCode}` : apiError.message;
|
|
249516
|
+
throw new ApiError(message, {
|
|
249497
249517
|
statusCode: apiError.statusCode,
|
|
249498
249518
|
requestUrl: apiError.requestUrl,
|
|
249499
249519
|
requestMethod: apiError.requestMethod,
|
|
@@ -249636,7 +249656,7 @@ function getApiCatalogCommand() {
|
|
|
249636
249656
|
}
|
|
249637
249657
|
|
|
249638
249658
|
// src/cli/commands/api/fetch.ts
|
|
249639
|
-
async function findOperation(ctx, method, path, refresh) {
|
|
249659
|
+
async function findOperation(ctx, method, path, { refresh, flag }) {
|
|
249640
249660
|
const { spec } = await loadSpecTask(ctx, refresh);
|
|
249641
249661
|
const op = matchOperation(listOperations(spec), method, path);
|
|
249642
249662
|
if (!op) {
|
|
@@ -249644,7 +249664,7 @@ async function findOperation(ctx, method, path, refresh) {
|
|
|
249644
249664
|
hints: [
|
|
249645
249665
|
{
|
|
249646
249666
|
message: "The cached spec may predate this route; fetch it again",
|
|
249647
|
-
command:
|
|
249667
|
+
command: `base44 api fetch ${method} ${path} ${flag} --refresh`
|
|
249648
249668
|
},
|
|
249649
249669
|
{
|
|
249650
249670
|
message: "Find the operation and its path template",
|
|
@@ -249703,11 +249723,17 @@ async function fetchAction(ctx, methodArg, path, options, command) {
|
|
|
249703
249723
|
}
|
|
249704
249724
|
const method = methodArg.toUpperCase();
|
|
249705
249725
|
if (options.help) {
|
|
249706
|
-
const { spec, op } = await findOperation(ctx, method, path,
|
|
249726
|
+
const { spec, op } = await findOperation(ctx, method, path, {
|
|
249727
|
+
refresh: options.refresh,
|
|
249728
|
+
flag: "--help"
|
|
249729
|
+
});
|
|
249707
249730
|
return { stdout: formatJson(getOperationContract(spec, op)) };
|
|
249708
249731
|
}
|
|
249709
249732
|
if (options.readOnly) {
|
|
249710
|
-
const { op } = await findOperation(ctx, method, path,
|
|
249733
|
+
const { op } = await findOperation(ctx, method, path, {
|
|
249734
|
+
refresh: options.refresh,
|
|
249735
|
+
flag: "--read-only"
|
|
249736
|
+
});
|
|
249711
249737
|
if (!op.readOnly) {
|
|
249712
249738
|
throw new InvalidInputError(`Refused under --read-only: ${op.method} ${op.path} is not a read-only operation. Nothing was sent.`);
|
|
249713
249739
|
}
|
|
@@ -249755,11 +249781,9 @@ async function grepAction(ctx, pattern, options) {
|
|
|
249755
249781
|
if (options.readOnly) {
|
|
249756
249782
|
operations = operations.filter((op) => op.readOnly);
|
|
249757
249783
|
}
|
|
249758
|
-
const
|
|
249759
|
-
const hits = grepSpec(spec, operations, pattern, {
|
|
249784
|
+
const hits = grepOperations(spec, operations, pattern, {
|
|
249760
249785
|
ignoreCase: options.ignoreCase,
|
|
249761
|
-
limit
|
|
249762
|
-
schemas: !narrowed
|
|
249786
|
+
limit
|
|
249763
249787
|
});
|
|
249764
249788
|
return { stdout: formatJson(hits) };
|
|
249765
249789
|
}
|
|
@@ -249767,7 +249791,7 @@ function getApiGrepCommand() {
|
|
|
249767
249791
|
return new Base44Command("grep", {
|
|
249768
249792
|
requireAuth: false,
|
|
249769
249793
|
requireAppContext: false
|
|
249770
|
-
}).description("Search the API spec with a regular expression, for when search misses").argument("<pattern>", 'Regular expression, e.g. "runs.*status"').option("--area <area>", "Search only one area's operations (see base44 api catalog)").option("-i, --ignore-case", "Case-insensitive match").option("--limit <n>", "Most operations
|
|
249794
|
+
}).description("Search the API spec with a regular expression, for when search misses").argument("<pattern>", 'Regular expression, e.g. "runs.*status"').option("--area <area>", "Search only one area's operations (see base44 api catalog)").option("-i, --ignore-case", "Case-insensitive match").option("--limit <n>", "Most operations to return (default 20)").option("--read-only", READ_ONLY_FILTER_HELP).option("--refresh", REFRESH_OPTION_HELP).action(grepAction);
|
|
249771
249795
|
}
|
|
249772
249796
|
|
|
249773
249797
|
// src/cli/commands/api/search.ts
|
|
@@ -262327,7 +262351,7 @@ var nativeEnumType = ZodNativeEnum.create;
|
|
|
262327
262351
|
var promiseType = ZodPromise.create;
|
|
262328
262352
|
var effectsType = ZodEffects.create;
|
|
262329
262353
|
var optionalType = ZodOptional2.create;
|
|
262330
|
-
var
|
|
262354
|
+
var nullableType2 = ZodNullable2.create;
|
|
262331
262355
|
var preprocessType = ZodEffects.createWithPreprocess;
|
|
262332
262356
|
var pipelineType = ZodPipeline.create;
|
|
262333
262357
|
// ../functions-compiler/src/contracts.ts
|
|
@@ -273329,4 +273353,4 @@ export {
|
|
|
273329
273353
|
runCLI
|
|
273330
273354
|
};
|
|
273331
273355
|
|
|
273332
|
-
//# debugId=
|
|
273356
|
+
//# debugId=ED51B8A8CDD1B22D64756E2164756E21
|