@base44-preview/cli 0.1.32-pr.663.ac8cbb8 → 0.1.32-pr.663.b609424
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 +241 -187
- package/dist/cli/index.js.map +13 -11
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -39570,9 +39570,9 @@ function tm(e, t, r) {
|
|
|
39570
39570
|
return l(["<", r("name"), r("typeArguments"), " ", ...e.map(r, "attributes"), n.selfClosing ? " />" : ">"]);
|
|
39571
39571
|
let i = n.attributes?.some((u) => V3(u.value) && u.value.value.includes(`
|
|
39572
39572
|
`)), o = t.singleAttributePerLine && n.attributes.length > 1 ? E : A;
|
|
39573
|
-
return l(["<", r("name"), r("typeArguments"), m(e.map(() => [o, r()], "attributes")), ...
|
|
39573
|
+
return l(["<", r("name"), r("typeArguments"), m(e.map(() => [o, r()], "attributes")), ...rm3(n, t, s)], { shouldBreak: i });
|
|
39574
39574
|
}
|
|
39575
|
-
function
|
|
39575
|
+
function rm3(e, t, r) {
|
|
39576
39576
|
return e.selfClosing ? [A, "/>"] : nm(e, t, r) ? [">"] : [f, ">"];
|
|
39577
39577
|
}
|
|
39578
39578
|
function nm(e, t, r) {
|
|
@@ -111521,7 +111521,7 @@ function N62(e) {
|
|
|
111521
111521
|
function nm2(e, t, a) {
|
|
111522
111522
|
return ie10(t, a, e.typeParameters) || ie10(t, a, e.parameters) || S7(t, e.type);
|
|
111523
111523
|
}
|
|
111524
|
-
function
|
|
111524
|
+
function rm4(e, t, a) {
|
|
111525
111525
|
return ie10(t, a, e.types);
|
|
111526
111526
|
}
|
|
111527
111527
|
function im2(e, t, a) {
|
|
@@ -114489,7 +114489,7 @@ ${Me.join(`
|
|
|
114489
114489
|
return S7(a, t.elementType);
|
|
114490
114490
|
}, 190: function(t, a, _) {
|
|
114491
114491
|
return ie10(a, _, t.elements);
|
|
114492
|
-
}, 193:
|
|
114492
|
+
}, 193: rm4, 194: rm4, 195: function(t, a, _) {
|
|
114493
114493
|
return S7(a, t.checkType) || S7(a, t.extendsType) || S7(a, t.trueType) || S7(a, t.falseType);
|
|
114494
114494
|
}, 196: function(t, a, _) {
|
|
114495
114495
|
return S7(a, t.typeParameter);
|
|
@@ -249214,44 +249214,6 @@ function areaListing(area, operations, max = AREA_OPERATIONS_MAX) {
|
|
|
249214
249214
|
truncated: operations.length > max
|
|
249215
249215
|
};
|
|
249216
249216
|
}
|
|
249217
|
-
// src/core/api-spec/grep.ts
|
|
249218
|
-
var CONTEXT_CHARS = 40;
|
|
249219
|
-
var MAX_SNIPPETS = 3;
|
|
249220
|
-
var MAX_SNIPPET_CHARS = 200;
|
|
249221
|
-
function unescapeJson(snippet) {
|
|
249222
|
-
return snippet.replace(/\\[nrt]/g, " ").replace(/\\"/g, '"');
|
|
249223
|
-
}
|
|
249224
|
-
function snippets(text, pattern) {
|
|
249225
|
-
const found = [];
|
|
249226
|
-
for (const match of text.matchAll(pattern)) {
|
|
249227
|
-
const start = Math.max(0, match.index - CONTEXT_CHARS);
|
|
249228
|
-
const end = match.index + match[0].length + CONTEXT_CHARS;
|
|
249229
|
-
found.push(unescapeJson(text.slice(start, Math.min(end, start + MAX_SNIPPET_CHARS))));
|
|
249230
|
-
if (found.length === MAX_SNIPPETS || match[0].length === 0) {
|
|
249231
|
-
break;
|
|
249232
|
-
}
|
|
249233
|
-
}
|
|
249234
|
-
return found;
|
|
249235
|
-
}
|
|
249236
|
-
function grepSpec(spec, operations, pattern, options = {}) {
|
|
249237
|
-
const regex = new RegExp(pattern, options.ignoreCase ? "gi" : "g");
|
|
249238
|
-
const hits = [];
|
|
249239
|
-
for (const op of operations) {
|
|
249240
|
-
const { summary, description, parameters, requestBody, responses } = op.operation;
|
|
249241
|
-
const matches = snippets(`${op.endpoint} ${JSON.stringify({ summary, description, parameters, requestBody, responses })}`, regex);
|
|
249242
|
-
if (matches.length > 0) {
|
|
249243
|
-
hits.push({ ...toOperationSummary(op), matches });
|
|
249244
|
-
}
|
|
249245
|
-
}
|
|
249246
|
-
const schemas = options.schemas === false ? {} : spec.components?.schemas;
|
|
249247
|
-
for (const [schema, definition] of Object.entries(schemas ?? {})) {
|
|
249248
|
-
const matches = snippets(JSON.stringify(definition), regex);
|
|
249249
|
-
if (matches.length > 0) {
|
|
249250
|
-
hits.push({ schema, matches });
|
|
249251
|
-
}
|
|
249252
|
-
}
|
|
249253
|
-
return hits.slice(0, options.limit ?? 20);
|
|
249254
|
-
}
|
|
249255
249217
|
// src/core/api-spec/schema.ts
|
|
249256
249218
|
var HTTP_METHODS = [
|
|
249257
249219
|
"get",
|
|
@@ -249272,7 +249234,7 @@ var ParameterSchema = looseObject({
|
|
|
249272
249234
|
example: unknown().optional()
|
|
249273
249235
|
});
|
|
249274
249236
|
var MediaTypesSchema = record(string2(), looseObject({ schema: unknown().optional() }));
|
|
249275
|
-
var
|
|
249237
|
+
var MediaContentSchema = looseObject({
|
|
249276
249238
|
content: MediaTypesSchema.optional()
|
|
249277
249239
|
});
|
|
249278
249240
|
var ResponseObjectSchema = looseObject({
|
|
@@ -249289,104 +249251,26 @@ var OperationSchema = looseObject({
|
|
|
249289
249251
|
responses: record(string2(), unknown()).optional(),
|
|
249290
249252
|
security: array(SecurityRequirementSchema).optional()
|
|
249291
249253
|
});
|
|
249292
|
-
var PathItemSchema = looseObject({
|
|
249293
|
-
...Object.fromEntries(HTTP_METHODS.map((method) => [method, OperationSchema.optional()])),
|
|
249294
|
-
parameters: array(unknown()).optional()
|
|
249295
|
-
});
|
|
249296
249254
|
var OpenApiSpecSchema = looseObject({
|
|
249297
249255
|
openapi: string2(),
|
|
249298
|
-
paths: record(string2(),
|
|
249256
|
+
paths: record(string2(), record(string2(), unknown())),
|
|
249299
249257
|
components: looseObject({
|
|
249300
249258
|
schemas: record(string2(), unknown()).optional()
|
|
249301
249259
|
}).optional(),
|
|
249302
|
-
security: array(SecurityRequirementSchema).optional()
|
|
249260
|
+
security: array(SecurityRequirementSchema).optional().catch(undefined)
|
|
249303
249261
|
});
|
|
249262
|
+
var ParameterListSchema = array(unknown());
|
|
249304
249263
|
|
|
249305
|
-
// src/core/api-spec/
|
|
249306
|
-
var
|
|
249307
|
-
var
|
|
249308
|
-
function
|
|
249309
|
-
|
|
249310
|
-
return security.some((requirement) => requirement[PERSONAL_ACCESS_TOKEN_SCHEME]?.includes(READ_ONLY_SCOPE));
|
|
249311
|
-
}
|
|
249312
|
-
function parameterText(operation) {
|
|
249313
|
-
return (operation.parameters ?? []).flatMap((parameter) => {
|
|
249314
|
-
const parsed = ParameterSchema.safeParse(parameter);
|
|
249315
|
-
return parsed.success ? [parsed.data.name, parsed.data.description ?? ""] : [];
|
|
249316
|
-
}).join(" ");
|
|
249317
|
-
}
|
|
249318
|
-
function mergeParameters(shared, own) {
|
|
249319
|
-
if (!shared?.length) {
|
|
249320
|
-
return own;
|
|
249321
|
-
}
|
|
249322
|
-
const key = (parameter) => {
|
|
249323
|
-
const parsed = ParameterSchema.safeParse(parameter);
|
|
249324
|
-
return parsed.success ? `${parsed.data.in}:${parsed.data.name}` : undefined;
|
|
249325
|
-
};
|
|
249326
|
-
const ownKeys = new Set((own ?? []).map(key));
|
|
249327
|
-
return [
|
|
249328
|
-
...shared.filter((parameter) => !ownKeys.has(key(parameter))),
|
|
249329
|
-
...own ?? []
|
|
249330
|
-
];
|
|
249331
|
-
}
|
|
249332
|
-
function listOperations(spec) {
|
|
249333
|
-
return Object.entries(spec.paths).flatMap(([path, item]) => HTTP_METHODS.flatMap((method) => {
|
|
249334
|
-
const declared = item[method];
|
|
249335
|
-
if (!declared) {
|
|
249336
|
-
return [];
|
|
249337
|
-
}
|
|
249338
|
-
const operation = {
|
|
249339
|
-
...declared,
|
|
249340
|
-
parameters: mergeParameters(item.parameters, declared.parameters)
|
|
249341
|
-
};
|
|
249342
|
-
return [
|
|
249343
|
-
{
|
|
249344
|
-
endpoint: `${method.toUpperCase()} ${path}`,
|
|
249345
|
-
method: method.toUpperCase(),
|
|
249346
|
-
path,
|
|
249347
|
-
summary: operation.summary ?? "",
|
|
249348
|
-
description: operation.description ?? "",
|
|
249349
|
-
parameterText: parameterText(operation),
|
|
249350
|
-
readOnly: isReadOnly(operation, spec),
|
|
249351
|
-
operation
|
|
249352
|
-
}
|
|
249353
|
-
];
|
|
249354
|
-
}));
|
|
249355
|
-
}
|
|
249356
|
-
function pathSegments(path) {
|
|
249357
|
-
const pathname = path.split(/[?#]/, 1)[0] ?? "";
|
|
249358
|
-
return pathname.split("/").filter(Boolean);
|
|
249359
|
-
}
|
|
249360
|
-
function segmentPattern(segment) {
|
|
249361
|
-
const source = segment.split(/(\{[^}]+\})/).map((part) => part.startsWith("{") ? "[^/]+" : part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
|
|
249362
|
-
return new RegExp(`^${source}$`);
|
|
249363
|
-
}
|
|
249364
|
-
function specificity(templateSegments) {
|
|
249365
|
-
return templateSegments.map((segment) => segment.includes("{") ? 0 : 1);
|
|
249366
|
-
}
|
|
249367
|
-
function compareSpecificity(a, b) {
|
|
249368
|
-
for (let i = 0;i < a.length; i++) {
|
|
249369
|
-
if (a[i] !== b[i]) {
|
|
249370
|
-
return (b[i] ?? 0) - (a[i] ?? 0);
|
|
249371
|
-
}
|
|
249372
|
-
}
|
|
249373
|
-
return 0;
|
|
249374
|
-
}
|
|
249375
|
-
function matchOperation(operations, method, concretePath) {
|
|
249376
|
-
const upperMethod = method.toUpperCase();
|
|
249377
|
-
const segments = pathSegments(concretePath);
|
|
249378
|
-
const candidates = operations.filter((op) => {
|
|
249379
|
-
if (op.method !== upperMethod) {
|
|
249380
|
-
return false;
|
|
249381
|
-
}
|
|
249382
|
-
const template = pathSegments(op.path);
|
|
249383
|
-
return template.length === segments.length && template.every((part, i) => segmentPattern(part).test(segments[i] ?? ""));
|
|
249384
|
-
});
|
|
249385
|
-
return candidates.sort((a, b) => compareSpecificity(specificity(pathSegments(a.path)), specificity(pathSegments(b.path))))[0];
|
|
249264
|
+
// src/core/api-spec/text.ts
|
|
249265
|
+
var DOCS_CALLOUT = /<(Info|Note|Tip|Check|Warning)>([\s\S]*?)<\/\1>/g;
|
|
249266
|
+
var RELATIVE_LINK = /\[([^\]]+)\]\(\/[^)]*\)/g;
|
|
249267
|
+
function cleanText(text) {
|
|
249268
|
+
return text.replace(DOCS_CALLOUT, (_, kind, body) => kind === "Warning" ? `Warning: ${body}` : body).replace(RELATIVE_LINK, "$1");
|
|
249386
249269
|
}
|
|
249270
|
+
|
|
249271
|
+
// src/core/api-spec/contract.ts
|
|
249387
249272
|
var SCHEMA_REF_PREFIX = "#/components/schemas/";
|
|
249388
249273
|
var MAX_REF_DEPTH = 4;
|
|
249389
|
-
var FRAMEWORK_VALIDATION_ERROR = "Validation Error";
|
|
249390
249274
|
function inlineRefs(node, schemas, seen = new Set, depth = 0) {
|
|
249391
249275
|
if (depth > MAX_REF_DEPTH) {
|
|
249392
249276
|
return node;
|
|
@@ -249411,12 +249295,8 @@ function inlineRefs(node, schemas, seen = new Set, depth = 0) {
|
|
|
249411
249295
|
inlineRefs(value, schemas, seen, depth)
|
|
249412
249296
|
]));
|
|
249413
249297
|
}
|
|
249414
|
-
function
|
|
249415
|
-
const parsed =
|
|
249416
|
-
return parsed.success ? parsed.data.content?.["application/json"]?.schema : undefined;
|
|
249417
|
-
}
|
|
249418
|
-
function requestBodyOf(value) {
|
|
249419
|
-
const parsed = RequestBodySchema.safeParse(value);
|
|
249298
|
+
function bodyOf(value) {
|
|
249299
|
+
const parsed = MediaContentSchema.safeParse(value);
|
|
249420
249300
|
const content = parsed.success ? parsed.data.content ?? {} : {};
|
|
249421
249301
|
const contentType = "application/json" in content ? "application/json" : Object.keys(content)[0];
|
|
249422
249302
|
return contentType ? { contentType, schema: content[contentType]?.schema } : {};
|
|
@@ -249430,8 +249310,10 @@ function leftoverRefs(node, schemas, found = new Map) {
|
|
|
249430
249310
|
for (const [key, value] of Object.entries(node)) {
|
|
249431
249311
|
if (key === "$ref" && typeof value === "string" && value.startsWith(SCHEMA_REF_PREFIX) && !found.has(value)) {
|
|
249432
249312
|
const schema = schemas[value.slice(SCHEMA_REF_PREFIX.length)];
|
|
249433
|
-
|
|
249434
|
-
|
|
249313
|
+
if (schema !== undefined) {
|
|
249314
|
+
found.set(value, schema);
|
|
249315
|
+
leftoverRefs(schema, schemas, found);
|
|
249316
|
+
}
|
|
249435
249317
|
} else {
|
|
249436
249318
|
leftoverRefs(value, schemas, found);
|
|
249437
249319
|
}
|
|
@@ -249439,16 +249321,51 @@ function leftoverRefs(node, schemas, found = new Map) {
|
|
|
249439
249321
|
}
|
|
249440
249322
|
return found;
|
|
249441
249323
|
}
|
|
249324
|
+
var SCHEMA_DATA_KEYS = new Set([
|
|
249325
|
+
"example",
|
|
249326
|
+
"examples",
|
|
249327
|
+
"default",
|
|
249328
|
+
"enum",
|
|
249329
|
+
"const"
|
|
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
|
+
}
|
|
249442
249360
|
function getOperationContract(spec, op) {
|
|
249443
249361
|
const schemas = spec.components?.schemas ?? {};
|
|
249444
|
-
const inline = (node) => node === undefined ? null : inlineRefs(node, schemas);
|
|
249362
|
+
const inline = (node) => node === undefined ? null : slimSchema(inlineRefs(node, schemas));
|
|
249445
249363
|
const responses = Object.entries(op.operation.responses ?? {}).flatMap(([status, response]) => {
|
|
249446
249364
|
const parsed = ResponseObjectSchema.safeParse(response);
|
|
249447
249365
|
return parsed.success ? [[status, parsed.data]] : [];
|
|
249448
249366
|
});
|
|
249449
|
-
const success = responses.filter(([status]) => status.startsWith("2")).sort(([a], [b]) => a.localeCompare(b)).map(([, response]) =>
|
|
249450
|
-
const
|
|
249451
|
-
const requestBody = requestBodyOf(op.operation.requestBody);
|
|
249367
|
+
const success = responses.filter(([status]) => status.startsWith("2")).sort(([a], [b]) => a.localeCompare(b)).map(([, response]) => bodyOf(response).schema).find(Boolean);
|
|
249368
|
+
const requestBody = bodyOf(op.operation.requestBody);
|
|
249452
249369
|
const contract = {
|
|
249453
249370
|
endpoint: op.endpoint,
|
|
249454
249371
|
method: op.method,
|
|
@@ -249468,24 +249385,106 @@ function getOperationContract(spec, op) {
|
|
|
249468
249385
|
in: location2,
|
|
249469
249386
|
required: required ?? false,
|
|
249470
249387
|
schema: inline(schema ?? {}),
|
|
249471
|
-
...description && !inSchema ? { description } : {},
|
|
249388
|
+
...description && !inSchema ? { description: cleanText(description) } : {},
|
|
249472
249389
|
..."example" in parsed.data ? { example: parsed.data.example } : {}
|
|
249473
249390
|
}
|
|
249474
249391
|
];
|
|
249475
249392
|
}),
|
|
249476
249393
|
...requestBody.contentType && requestBody.contentType !== "application/json" ? { requestBodyContentType: requestBody.contentType } : {},
|
|
249477
249394
|
requestBodySchema: inline(requestBody.schema),
|
|
249478
|
-
responseSchema: inline(success)
|
|
249479
|
-
errors: Object.fromEntries(errors.map(([status, response]) => [status, response.description ?? ""]))
|
|
249395
|
+
responseSchema: inline(success)
|
|
249480
249396
|
};
|
|
249481
249397
|
const refs = leftoverRefs(contract, schemas);
|
|
249482
249398
|
return {
|
|
249483
249399
|
...contract,
|
|
249484
|
-
...refs.size > 0 ? {
|
|
249400
|
+
...refs.size > 0 ? {
|
|
249401
|
+
refs: Object.fromEntries([...refs].map(([ref, schema]) => [ref, slimSchema(schema)]))
|
|
249402
|
+
} : {}
|
|
249485
249403
|
};
|
|
249486
249404
|
}
|
|
249405
|
+
// src/core/api-spec/grep.ts
|
|
249406
|
+
function grepOperations(spec, operations, pattern, options = {}) {
|
|
249407
|
+
const regex = new RegExp(pattern, options.ignoreCase ? "i" : "");
|
|
249408
|
+
return operations.filter((op) => regex.test(JSON.stringify(getOperationContract(spec, op)))).slice(0, options.limit ?? 20).map(toOperationSummary);
|
|
249409
|
+
}
|
|
249410
|
+
// src/core/api-spec/operations.ts
|
|
249411
|
+
var PERSONAL_ACCESS_TOKEN_SCHEME = "PersonalAccessTokenAuth";
|
|
249412
|
+
var READ_ONLY_SCOPE = "read_only";
|
|
249413
|
+
function isReadOnly(operation, spec) {
|
|
249414
|
+
const security = operation.security ?? spec.security ?? [];
|
|
249415
|
+
return security.some((requirement) => requirement[PERSONAL_ACCESS_TOKEN_SCHEME]?.includes(READ_ONLY_SCOPE));
|
|
249416
|
+
}
|
|
249417
|
+
function parameterText(operation) {
|
|
249418
|
+
return (operation.parameters ?? []).flatMap((parameter) => {
|
|
249419
|
+
const parsed = ParameterSchema.safeParse(parameter);
|
|
249420
|
+
return parsed.success ? [parsed.data.name, cleanText(parsed.data.description ?? "")] : [];
|
|
249421
|
+
}).join(" ");
|
|
249422
|
+
}
|
|
249423
|
+
function mergeParameters(shared, own) {
|
|
249424
|
+
if (!shared?.length) {
|
|
249425
|
+
return own;
|
|
249426
|
+
}
|
|
249427
|
+
const key = (parameter) => {
|
|
249428
|
+
const parsed = ParameterSchema.safeParse(parameter);
|
|
249429
|
+
return parsed.success ? `${parsed.data.in}:${parsed.data.name}` : undefined;
|
|
249430
|
+
};
|
|
249431
|
+
const ownKeys = new Set((own ?? []).map(key));
|
|
249432
|
+
return [
|
|
249433
|
+
...shared.filter((parameter) => !ownKeys.has(key(parameter))),
|
|
249434
|
+
...own ?? []
|
|
249435
|
+
];
|
|
249436
|
+
}
|
|
249437
|
+
function listOperations(spec) {
|
|
249438
|
+
return Object.entries(spec.paths).flatMap(([path, item]) => HTTP_METHODS.flatMap((method) => {
|
|
249439
|
+
const parsed = OperationSchema.safeParse(item[method]);
|
|
249440
|
+
if (!parsed.success) {
|
|
249441
|
+
return [];
|
|
249442
|
+
}
|
|
249443
|
+
const shared = ParameterListSchema.safeParse(item.parameters);
|
|
249444
|
+
const operation = {
|
|
249445
|
+
...parsed.data,
|
|
249446
|
+
parameters: mergeParameters(shared.success ? shared.data : undefined, parsed.data.parameters)
|
|
249447
|
+
};
|
|
249448
|
+
return [
|
|
249449
|
+
{
|
|
249450
|
+
endpoint: `${method.toUpperCase()} ${path}`,
|
|
249451
|
+
method: method.toUpperCase(),
|
|
249452
|
+
path,
|
|
249453
|
+
summary: operation.summary ?? "",
|
|
249454
|
+
description: cleanText(operation.description ?? ""),
|
|
249455
|
+
parameterText: parameterText(operation),
|
|
249456
|
+
readOnly: isReadOnly(operation, spec),
|
|
249457
|
+
operation
|
|
249458
|
+
}
|
|
249459
|
+
];
|
|
249460
|
+
}));
|
|
249461
|
+
}
|
|
249462
|
+
function pathSegments(path) {
|
|
249463
|
+
const pathname = path.split(/[?#]/, 1)[0] ?? "";
|
|
249464
|
+
return pathname.split("/").filter(Boolean);
|
|
249465
|
+
}
|
|
249466
|
+
function segmentPattern(segment) {
|
|
249467
|
+
const source = segment.split(/(\{[^}]+\})/).map((part) => part.startsWith("{") ? "[^/]+" : part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
|
|
249468
|
+
return new RegExp(`^${source}$`);
|
|
249469
|
+
}
|
|
249470
|
+
function literalSegments(path) {
|
|
249471
|
+
return pathSegments(path).map((segment) => segment.includes("{") ? "0" : "1").join("");
|
|
249472
|
+
}
|
|
249473
|
+
function matchOperation(operations, method, concretePath) {
|
|
249474
|
+
const upperMethod = method.toUpperCase();
|
|
249475
|
+
const segments = pathSegments(concretePath);
|
|
249476
|
+
const candidates = operations.filter((op) => {
|
|
249477
|
+
if (op.method !== upperMethod) {
|
|
249478
|
+
return false;
|
|
249479
|
+
}
|
|
249480
|
+
const template = pathSegments(op.path);
|
|
249481
|
+
return template.length === segments.length && template.every((part, i) => segmentPattern(part).test(segments[i] ?? ""));
|
|
249482
|
+
});
|
|
249483
|
+
return candidates.sort((a, b) => literalSegments(b.path).localeCompare(literalSegments(a.path)))[0];
|
|
249484
|
+
}
|
|
249487
249485
|
// src/core/api-spec/request.ts
|
|
249488
249486
|
var MAX_ERROR_BODY_CHARS = 4000;
|
|
249487
|
+
var QUERY_STRING = /\?\S*/g;
|
|
249489
249488
|
async function readBody(response) {
|
|
249490
249489
|
try {
|
|
249491
249490
|
const text = (await response.clone().text()).trim();
|
|
@@ -249499,8 +249498,9 @@ async function sendApiRequest(method, path, body) {
|
|
|
249499
249498
|
const response = await base44Client(path.replace(/^\/+/, ""), {
|
|
249500
249499
|
method,
|
|
249501
249500
|
body,
|
|
249502
|
-
headers: body ===
|
|
249503
|
-
timeout: false
|
|
249501
|
+
headers: typeof body === "string" ? { "Content-Type": "application/json" } : {},
|
|
249502
|
+
timeout: false,
|
|
249503
|
+
retry: { methods: ["get", "head"] }
|
|
249504
249504
|
});
|
|
249505
249505
|
return {
|
|
249506
249506
|
status: response.status,
|
|
@@ -249509,19 +249509,27 @@ async function sendApiRequest(method, path, body) {
|
|
|
249509
249509
|
};
|
|
249510
249510
|
} catch (error) {
|
|
249511
249511
|
const apiError = await ApiError.fromHttpError(error, `calling ${method} ${path}`);
|
|
249512
|
-
const
|
|
249513
|
-
|
|
249514
|
-
|
|
249515
|
-
|
|
249516
|
-
requestMethod: apiError.requestMethod,
|
|
249517
|
-
requestId: apiError.requestId,
|
|
249518
|
-
hints: apiError.hints,
|
|
249519
|
-
details: raw ? [`Response body: ${raw}`] : apiError.details
|
|
249520
|
-
});
|
|
249512
|
+
const response = error instanceof HTTPError ? error.response : undefined;
|
|
249513
|
+
const raw = response ? await readBody(response) : undefined;
|
|
249514
|
+
const retryAfter = response?.headers.get("retry-after") ?? undefined;
|
|
249515
|
+
throw redactedApiError(apiError, raw, method, path, retryAfter);
|
|
249521
249516
|
}
|
|
249522
249517
|
}
|
|
249518
|
+
function redactedApiError(apiError, raw, method, path, retryAfter) {
|
|
249519
|
+
const wait = retryAfter ? ` (retry after ${/^\d+$/.test(retryAfter) ? `${retryAfter} s` : retryAfter})` : "";
|
|
249520
|
+
const reason = apiError.statusCode !== undefined ? `HTTP ${apiError.statusCode}${wait}` : (apiError.cause?.message ?? "request failed").replace(QUERY_STRING, "");
|
|
249521
|
+
const message = `Error calling ${method} ${path.split("?", 1)[0]}: ${reason}`;
|
|
249522
|
+
return new ApiError(message, {
|
|
249523
|
+
statusCode: apiError.statusCode,
|
|
249524
|
+
requestUrl: apiError.requestUrl?.split("?", 1)[0],
|
|
249525
|
+
requestMethod: apiError.requestMethod,
|
|
249526
|
+
requestId: apiError.requestId,
|
|
249527
|
+
hints: apiError.hints,
|
|
249528
|
+
details: raw ? [`Response body: ${raw}`] : apiError.details
|
|
249529
|
+
});
|
|
249530
|
+
}
|
|
249523
249531
|
// src/core/api-spec/spec.ts
|
|
249524
|
-
import { rename, stat as stat3 } from "node:fs/promises";
|
|
249532
|
+
import { rename, rm, stat as stat3 } from "node:fs/promises";
|
|
249525
249533
|
import { join as join22 } from "node:path";
|
|
249526
249534
|
var SPEC_CACHE_TTL_MS = 60 * 60 * 1000;
|
|
249527
249535
|
function getSpecCachePath(apiUrl = getBase44ApiUrl()) {
|
|
@@ -249576,12 +249584,19 @@ async function loadSpec(options = {}) {
|
|
|
249576
249584
|
const text = await downloadSpec();
|
|
249577
249585
|
const spec = parseSpec(text);
|
|
249578
249586
|
const partial = `${path}.${process.pid}.tmp`;
|
|
249579
|
-
|
|
249580
|
-
|
|
249587
|
+
try {
|
|
249588
|
+
await writeFile(partial, text);
|
|
249589
|
+
await rename(partial, path);
|
|
249590
|
+
} catch {
|
|
249591
|
+
await rm(partial, { force: true }).catch(() => {
|
|
249592
|
+
return;
|
|
249593
|
+
});
|
|
249594
|
+
}
|
|
249581
249595
|
return { text, spec };
|
|
249582
249596
|
}
|
|
249583
249597
|
// src/cli/commands/api/shared.ts
|
|
249584
249598
|
import { fstatSync } from "node:fs";
|
|
249599
|
+
import { basename as basename6 } from "node:path";
|
|
249585
249600
|
function formatJson(value) {
|
|
249586
249601
|
return toJsonStdout(value, { compact: !process.stdout.isTTY });
|
|
249587
249602
|
}
|
|
@@ -249633,6 +249648,41 @@ async function readRequestBody(flag, log) {
|
|
|
249633
249648
|
}
|
|
249634
249649
|
return flag;
|
|
249635
249650
|
}
|
|
249651
|
+
var FORM_FILE = /^@(.+?)(?:;type=([^;]+))?$/;
|
|
249652
|
+
async function readFormBody(fields) {
|
|
249653
|
+
const form = new FormData;
|
|
249654
|
+
for (const field of fields) {
|
|
249655
|
+
const separator = field.indexOf("=");
|
|
249656
|
+
if (separator < 1) {
|
|
249657
|
+
throw new InvalidInputError(`--form takes name=value or name=@file, got "${field}".`);
|
|
249658
|
+
}
|
|
249659
|
+
const name = field.slice(0, separator);
|
|
249660
|
+
const value = field.slice(separator + 1);
|
|
249661
|
+
const file = FORM_FILE.exec(value);
|
|
249662
|
+
if (file?.[1]) {
|
|
249663
|
+
const type = file[2] ?? "application/octet-stream";
|
|
249664
|
+
const blob = new Blob([await readFile(file[1])], { type });
|
|
249665
|
+
form.append(name, blob, basename6(file[1]));
|
|
249666
|
+
} else {
|
|
249667
|
+
form.append(name, value);
|
|
249668
|
+
}
|
|
249669
|
+
}
|
|
249670
|
+
return form;
|
|
249671
|
+
}
|
|
249672
|
+
function withoutQuery(path) {
|
|
249673
|
+
return path.split("?", 1)[0] ?? "";
|
|
249674
|
+
}
|
|
249675
|
+
function reportedFetchCommand(method, path, options) {
|
|
249676
|
+
return {
|
|
249677
|
+
name: "api fetch",
|
|
249678
|
+
args: [method, withoutQuery(path)],
|
|
249679
|
+
options: {
|
|
249680
|
+
...options,
|
|
249681
|
+
...options.body === undefined ? {} : { body: "[not reported]" },
|
|
249682
|
+
...Array.isArray(options.form) && options.form.length > 0 ? { form: "[not reported]" } : {}
|
|
249683
|
+
}
|
|
249684
|
+
};
|
|
249685
|
+
}
|
|
249636
249686
|
|
|
249637
249687
|
// src/cli/commands/api/catalog.ts
|
|
249638
249688
|
async function catalogAction(ctx, area, options) {
|
|
@@ -249657,7 +249707,7 @@ async function findOperation(ctx, method, path, { refresh, flag }) {
|
|
|
249657
249707
|
const { spec } = await loadSpecTask(ctx, refresh);
|
|
249658
249708
|
const op = matchOperation(listOperations(spec), method, path);
|
|
249659
249709
|
if (!op) {
|
|
249660
|
-
throw new InvalidInputError(`No operation in the API spec matches ${method} ${path}.`, {
|
|
249710
|
+
throw new InvalidInputError(`No operation in the API spec matches ${method} ${withoutQuery(path)}.`, {
|
|
249661
249711
|
hints: [
|
|
249662
249712
|
{
|
|
249663
249713
|
message: "The cached spec may predate this route; fetch it again",
|
|
@@ -249672,6 +249722,9 @@ async function findOperation(ctx, method, path, { refresh, flag }) {
|
|
|
249672
249722
|
}
|
|
249673
249723
|
return { spec, op };
|
|
249674
249724
|
}
|
|
249725
|
+
var MULTIPART_HINT = "Send this body with --form name=value, and --form name=@path for files.";
|
|
249726
|
+
var CONTRACT_HELP = `
|
|
249727
|
+
The contract is JSON; cut it down with e.g. | jq '.parameters, .requestBodySchema'`;
|
|
249675
249728
|
var TEXT_CONTENT_TYPES = [
|
|
249676
249729
|
"json",
|
|
249677
249730
|
"text/",
|
|
@@ -249711,9 +249764,13 @@ async function formatResponse({ status, contentType, body }, output, jsonMode) {
|
|
|
249711
249764
|
}
|
|
249712
249765
|
}
|
|
249713
249766
|
async function fetchAction(ctx, methodArg, path, options, command) {
|
|
249767
|
+
ctx.errorReporter.setContext({
|
|
249768
|
+
command: reportedFetchCommand(methodArg ?? "", path ?? "", { ...options })
|
|
249769
|
+
});
|
|
249714
249770
|
if (!methodArg || !path) {
|
|
249715
249771
|
if (options.help) {
|
|
249716
|
-
const usage = command.helpInformation()
|
|
249772
|
+
const usage = `${command.helpInformation()}${CONTRACT_HELP}
|
|
249773
|
+
`;
|
|
249717
249774
|
return { stdout: ctx.jsonMode ? formatJson({ usage }) : usage };
|
|
249718
249775
|
}
|
|
249719
249776
|
throw new InvalidInputError("Provide a method and a path, e.g. GET /api/apps.");
|
|
@@ -249724,7 +249781,10 @@ async function fetchAction(ctx, methodArg, path, options, command) {
|
|
|
249724
249781
|
refresh: options.refresh,
|
|
249725
249782
|
flag: "--help"
|
|
249726
249783
|
});
|
|
249727
|
-
|
|
249784
|
+
const contract = getOperationContract(spec, op);
|
|
249785
|
+
return {
|
|
249786
|
+
stdout: formatJson(contract.requestBodyContentType === "multipart/form-data" ? { ...contract, hint: MULTIPART_HINT } : contract)
|
|
249787
|
+
};
|
|
249728
249788
|
}
|
|
249729
249789
|
if (options.readOnly) {
|
|
249730
249790
|
const { op } = await findOperation(ctx, method, path, {
|
|
@@ -249735,15 +249795,11 @@ async function fetchAction(ctx, methodArg, path, options, command) {
|
|
|
249735
249795
|
throw new InvalidInputError(`Refused under --read-only: ${op.method} ${op.path} is not a read-only operation. Nothing was sent.`);
|
|
249736
249796
|
}
|
|
249737
249797
|
}
|
|
249738
|
-
|
|
249739
|
-
|
|
249740
|
-
|
|
249741
|
-
args: [method, path.split("?", 1)[0] ?? ""],
|
|
249742
|
-
options: { ...options, body: options.body && "[not reported]" }
|
|
249743
|
-
}
|
|
249744
|
-
});
|
|
249798
|
+
if (options.body !== undefined && options.form.length > 0) {
|
|
249799
|
+
throw new InvalidInputError("Use --body or --form, not both.");
|
|
249800
|
+
}
|
|
249745
249801
|
await ensureAuth(ctx);
|
|
249746
|
-
const body = await readRequestBody(options.body, ctx.log);
|
|
249802
|
+
const body = options.form.length > 0 ? await readFormBody(options.form) : await readRequestBody(options.body, ctx.log);
|
|
249747
249803
|
const response = await ctx.runTask(`Calling ${method} ${path}`, () => sendApiRequest(method, path, body), {
|
|
249748
249804
|
successMessage: `Called ${method} ${path}`,
|
|
249749
249805
|
errorMessage: "Request failed"
|
|
@@ -249756,7 +249812,7 @@ function getApiFetchCommand() {
|
|
|
249756
249812
|
return new Base44Command("fetch", {
|
|
249757
249813
|
requireAuth: false,
|
|
249758
249814
|
requireAppContext: false
|
|
249759
|
-
}).description("Call a Base44 API operation; add --help after a path for its contract").helpOption(false).argument("[method]", "HTTP method, e.g. GET or POST").argument("[path]", 'Concrete path with any query string, e.g. "/api/apps/<app-id>/workflows/runs?status=failed"').option("--body <json>", "Request body: JSON, @file.json, or @- to read it from stdin").option("--output <file>", "Save the response body to a file").option("--read-only", "Refuse, before sending, any operation the spec does not mark read-only").option("--refresh", REFRESH_OPTION_HELP).option("-h, --help", "With a method and path, print that operation's contract; otherwise this help").action(fetchAction);
|
|
249815
|
+
}).description("Call a Base44 API operation; add --help after a path for its contract").helpOption(false).argument("[method]", "HTTP method, e.g. GET or POST").argument("[path]", 'Concrete path with any query string, e.g. "/api/apps/<app-id>/workflows/runs?status=failed"').option("--body <json>", "Request body: JSON, @file.json, or @- to read it from stdin").option("--form <field>", "Multipart field: name=value, or name=@file to attach a file (repeatable)", (field, fields) => [...fields, field], []).option("--output <file>", "Save the response body to a file").option("--read-only", "Refuse, before sending, any operation the spec does not mark read-only").option("--refresh", REFRESH_OPTION_HELP).option("-h, --help", "With a method and path, print that operation's contract; otherwise this help").addHelpText("after", CONTRACT_HELP).action(fetchAction);
|
|
249760
249816
|
}
|
|
249761
249817
|
|
|
249762
249818
|
// src/cli/commands/api/grep.ts
|
|
@@ -249778,11 +249834,9 @@ async function grepAction(ctx, pattern, options) {
|
|
|
249778
249834
|
if (options.readOnly) {
|
|
249779
249835
|
operations = operations.filter((op) => op.readOnly);
|
|
249780
249836
|
}
|
|
249781
|
-
const
|
|
249782
|
-
const hits = grepSpec(spec, operations, pattern, {
|
|
249837
|
+
const hits = grepOperations(spec, operations, pattern, {
|
|
249783
249838
|
ignoreCase: options.ignoreCase,
|
|
249784
|
-
limit
|
|
249785
|
-
schemas: !narrowed
|
|
249839
|
+
limit
|
|
249786
249840
|
});
|
|
249787
249841
|
return { stdout: formatJson(hits) };
|
|
249788
249842
|
}
|
|
@@ -249790,7 +249844,7 @@ function getApiGrepCommand() {
|
|
|
249790
249844
|
return new Base44Command("grep", {
|
|
249791
249845
|
requireAuth: false,
|
|
249792
249846
|
requireAppContext: false
|
|
249793
|
-
}).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
|
|
249847
|
+
}).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);
|
|
249794
249848
|
}
|
|
249795
249849
|
|
|
249796
249850
|
// src/cli/commands/api/search.ts
|
|
@@ -251577,7 +251631,7 @@ function getBuildCommand() {
|
|
|
251577
251631
|
}
|
|
251578
251632
|
|
|
251579
251633
|
// src/cli/commands/project/create.ts
|
|
251580
|
-
import { basename as
|
|
251634
|
+
import { basename as basename7, resolve as resolve11 } from "node:path";
|
|
251581
251635
|
var import_kebabCase = __toESM(require_kebabCase(), 1);
|
|
251582
251636
|
|
|
251583
251637
|
// src/cli/commands/project/scaffold-shared.ts
|
|
@@ -251742,8 +251796,8 @@ async function createInteractive(options, ctx) {
|
|
|
251742
251796
|
name: () => {
|
|
251743
251797
|
return options.name ? Promise.resolve(options.name) : Ze({
|
|
251744
251798
|
message: "What is the name of your project?",
|
|
251745
|
-
placeholder:
|
|
251746
|
-
initialValue:
|
|
251799
|
+
placeholder: basename7(process.cwd()),
|
|
251800
|
+
initialValue: basename7(process.cwd()),
|
|
251747
251801
|
validate: (value) => {
|
|
251748
251802
|
if (!value || value.trim().length === 0) {
|
|
251749
251803
|
return "Every project deserves a name";
|
|
@@ -252438,7 +252492,7 @@ function getLogsCommand() {
|
|
|
252438
252492
|
}
|
|
252439
252493
|
|
|
252440
252494
|
// src/cli/commands/project/scaffold.ts
|
|
252441
|
-
import { basename as
|
|
252495
|
+
import { basename as basename8, resolve as resolve12 } from "node:path";
|
|
252442
252496
|
function resolveAppId(options) {
|
|
252443
252497
|
const appId = options.appId;
|
|
252444
252498
|
if (!appId) {
|
|
@@ -252455,7 +252509,7 @@ async function scaffoldAction(ctx, name, options, command) {
|
|
|
252455
252509
|
const { log, runTask } = ctx;
|
|
252456
252510
|
const appId = resolveAppId(command.optsWithGlobals());
|
|
252457
252511
|
const resolvedPath = resolve12("./");
|
|
252458
|
-
const projectName = (name ??
|
|
252512
|
+
const projectName = (name ?? basename8(resolvedPath)).trim();
|
|
252459
252513
|
const template = await getTemplateById("backend-only");
|
|
252460
252514
|
log.info(`Scaffolding project at ${resolvedPath}`);
|
|
252461
252515
|
const { projectId } = await runTask("Setting up your project...", async () => {
|
|
@@ -262350,7 +262404,7 @@ var nativeEnumType = ZodNativeEnum.create;
|
|
|
262350
262404
|
var promiseType = ZodPromise.create;
|
|
262351
262405
|
var effectsType = ZodEffects.create;
|
|
262352
262406
|
var optionalType = ZodOptional2.create;
|
|
262353
|
-
var
|
|
262407
|
+
var nullableType2 = ZodNullable2.create;
|
|
262354
262408
|
var preprocessType = ZodEffects.createWithPreprocess;
|
|
262355
262409
|
var pipelineType = ZodPipeline.create;
|
|
262356
262410
|
// ../functions-compiler/src/contracts.ts
|
|
@@ -262380,7 +262434,7 @@ var bundleAppRequestSchema = objectType({
|
|
|
262380
262434
|
var ACTIVATION_MODE = "pull";
|
|
262381
262435
|
|
|
262382
262436
|
// ../functions-compiler/src/deno-bundle.ts
|
|
262383
|
-
import { mkdtemp, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
262437
|
+
import { mkdtemp, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
|
|
262384
262438
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
262385
262439
|
import path21 from "node:path";
|
|
262386
262440
|
|
|
@@ -262987,7 +263041,7 @@ async function bundleToModule(prepared, nodeModulesDir = "none") {
|
|
|
262987
263041
|
warnings: result.warnings.map((w) => w.text)
|
|
262988
263042
|
};
|
|
262989
263043
|
} finally {
|
|
262990
|
-
await
|
|
263044
|
+
await rm2(dir, { recursive: true, force: true });
|
|
262991
263045
|
}
|
|
262992
263046
|
}
|
|
262993
263047
|
function buildFailureErrors(e, dir) {
|
|
@@ -273352,4 +273406,4 @@ export {
|
|
|
273352
273406
|
runCLI
|
|
273353
273407
|
};
|
|
273354
273408
|
|
|
273355
|
-
//# debugId=
|
|
273409
|
+
//# debugId=FFC47D2E535D22E664756E2164756E21
|