@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 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")), ...rm2(n, t, s)], { shouldBreak: i });
39573
+ return l(["<", r("name"), r("typeArguments"), m(e.map(() => [o, r()], "attributes")), ...rm3(n, t, s)], { shouldBreak: i });
39574
39574
  }
39575
- function rm2(e, t, r) {
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 rm3(e, t, a) {
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: rm3, 194: rm3, 195: function(t, a, _) {
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 RequestBodySchema = looseObject({
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(), PathItemSchema),
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/operations.ts
249306
- var PERSONAL_ACCESS_TOKEN_SCHEME = "PersonalAccessTokenAuth";
249307
- var READ_ONLY_SCOPE = "read_only";
249308
- function isReadOnly(operation, spec) {
249309
- const security = operation.security ?? spec.security ?? [];
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 jsonSchemaOf(value) {
249415
- const parsed = RequestBodySchema.safeParse(value);
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
- found.set(value, schema);
249434
- leftoverRefs(schema, schemas, found);
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]) => jsonSchemaOf(response)).find(Boolean);
249450
- const errors = responses.filter(([status, response]) => !status.startsWith("2") && response.description !== FRAMEWORK_VALIDATION_ERROR);
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 ? { refs: Object.fromEntries(refs) } : {}
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 === undefined ? {} : { "Content-Type": "application/json" },
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 raw = error instanceof HTTPError ? await readBody(error.response) : undefined;
249513
- throw new ApiError(apiError.message, {
249514
- statusCode: apiError.statusCode,
249515
- requestUrl: apiError.requestUrl,
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
- await writeFile(partial, text);
249580
- await rename(partial, path);
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
- return { stdout: formatJson(getOperationContract(spec, op)) };
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
- ctx.errorReporter.setContext({
249739
- command: {
249740
- name: "api fetch",
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 narrowed = options.area !== undefined || options.readOnly === true;
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 or schemas to return (default 20)").option("--read-only", READ_ONLY_FILTER_HELP).option("--refresh", REFRESH_OPTION_HELP).action(grepAction);
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 basename6, resolve as resolve11 } from "node:path";
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: basename6(process.cwd()),
251746
- initialValue: basename6(process.cwd()),
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 basename7, resolve as resolve12 } from "node:path";
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 ?? basename7(resolvedPath)).trim();
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 nullableType = ZodNullable2.create;
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 rm(dir, { recursive: true, force: true });
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=47D4434C61AEF7C764756E2164756E21
273409
+ //# debugId=FFC47D2E535D22E664756E2164756E21