@base44-preview/cli 0.0.41-pr.398.f273a1e → 0.0.42-pr.404.ec1a1ee

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
@@ -16481,7 +16481,7 @@ var require_lodash = __commonJS((exports, module) => {
16481
16481
  function nth(array2, n2) {
16482
16482
  return array2 && array2.length ? baseNth(array2, toInteger(n2)) : undefined2;
16483
16483
  }
16484
- var pull = baseRest(pullAll);
16484
+ var pull2 = baseRest(pullAll);
16485
16485
  function pullAll(array2, values2) {
16486
16486
  return array2 && array2.length && values2 && values2.length ? basePullAll(array2, values2) : array2;
16487
16487
  }
@@ -18246,7 +18246,7 @@ __p += '`;
18246
18246
  lodash.pickBy = pickBy;
18247
18247
  lodash.property = property;
18248
18248
  lodash.propertyOf = propertyOf;
18249
- lodash.pull = pull;
18249
+ lodash.pull = pull2;
18250
18250
  lodash.pullAll = pullAll;
18251
18251
  lodash.pullAllBy = pullAllBy;
18252
18252
  lodash.pullAllWith = pullAllWith;
@@ -161575,7 +161575,7 @@ var require_is_promise = __commonJS((exports, module) => {
161575
161575
  }
161576
161576
  });
161577
161577
 
161578
- // ../../node_modules/router/node_modules/path-to-regexp/dist/index.js
161578
+ // ../../node_modules/path-to-regexp/dist/index.js
161579
161579
  var require_dist = __commonJS((exports) => {
161580
161580
  Object.defineProperty(exports, "__esModule", { value: true });
161581
161581
  exports.PathError = exports.TokenData = undefined;
@@ -237514,6 +237514,10 @@ var GoogleBigQueryConnectorSchema = exports_external.object({
237514
237514
  type: exports_external.literal("googlebigquery"),
237515
237515
  scopes: exports_external.array(exports_external.string()).default([])
237516
237516
  });
237517
+ var StripeConnectorSchema = exports_external.object({
237518
+ type: exports_external.literal("stripe"),
237519
+ scopes: exports_external.array(exports_external.string()).default([])
237520
+ });
237517
237521
  var CustomTypeSchema = exports_external.string().min(1).regex(/^[a-z0-9_-]+$/i);
237518
237522
  var GenericConnectorSchema = exports_external.object({
237519
237523
  type: CustomTypeSchema,
@@ -237533,6 +237537,7 @@ var ConnectorResourceSchema = exports_external.union([
237533
237537
  HubspotConnectorSchema,
237534
237538
  LinkedInConnectorSchema,
237535
237539
  TikTokConnectorSchema,
237540
+ StripeConnectorSchema,
237536
237541
  GenericConnectorSchema
237537
237542
  ]);
237538
237543
  var KnownIntegrationTypes = [
@@ -237548,7 +237553,8 @@ var KnownIntegrationTypes = [
237548
237553
  "salesforce",
237549
237554
  "hubspot",
237550
237555
  "linkedin",
237551
- "tiktok"
237556
+ "tiktok",
237557
+ "stripe"
237552
237558
  ];
237553
237559
  var IntegrationTypeSchema = exports_external.union([
237554
237560
  exports_external.enum(KnownIntegrationTypes),
@@ -237601,6 +237607,24 @@ var RemoveConnectorResponseSchema = exports_external.object({
237601
237607
  status: data.status,
237602
237608
  integrationType: data.integration_type
237603
237609
  }));
237610
+ var STRIPE_CONNECTOR_TYPE = "stripe";
237611
+ var InstallStripeResponseSchema = exports_external.object({
237612
+ already_installed: exports_external.boolean(),
237613
+ claim_url: exports_external.string().nullable()
237614
+ }).transform((data) => ({
237615
+ alreadyInstalled: data.already_installed,
237616
+ claimUrl: data.claim_url
237617
+ }));
237618
+ var StripeStatusResponseSchema = exports_external.object({
237619
+ stripe_mode: exports_external.enum(["sandbox", "live"]).nullable(),
237620
+ sandbox_claim_url: exports_external.string().nullable().optional()
237621
+ }).transform((data) => ({
237622
+ stripeMode: data.stripe_mode,
237623
+ sandboxClaimUrl: data.sandbox_claim_url
237624
+ }));
237625
+ var RemoveStripeResponseSchema = exports_external.object({
237626
+ success: exports_external.boolean()
237627
+ });
237604
237628
  var ConnectionConfigFieldSchema = exports_external.object({
237605
237629
  name: exports_external.string(),
237606
237630
  display_name: exports_external.string(),
@@ -237715,6 +237739,54 @@ async function removeConnector(integrationType) {
237715
237739
  }
237716
237740
  return result.data;
237717
237741
  }
237742
+ async function installStripe() {
237743
+ const appClient = getAppClient();
237744
+ let response;
237745
+ try {
237746
+ response = await appClient.post("payments/stripe/install", {
237747
+ timeout: 60000
237748
+ });
237749
+ } catch (error48) {
237750
+ throw await ApiError.fromHttpError(error48, "installing Stripe");
237751
+ }
237752
+ const result = InstallStripeResponseSchema.safeParse(await response.json());
237753
+ if (!result.success) {
237754
+ throw new SchemaValidationError("Invalid response from server", result.error);
237755
+ }
237756
+ return result.data;
237757
+ }
237758
+ async function getStripeStatus() {
237759
+ const appClient = getAppClient();
237760
+ let response;
237761
+ try {
237762
+ response = await appClient.get("payments/stripe/status", {
237763
+ timeout: 60000
237764
+ });
237765
+ } catch (error48) {
237766
+ throw await ApiError.fromHttpError(error48, "checking Stripe integration status");
237767
+ }
237768
+ const result = StripeStatusResponseSchema.safeParse(await response.json());
237769
+ if (!result.success) {
237770
+ throw new SchemaValidationError("Invalid response from server", result.error);
237771
+ }
237772
+ return result.data;
237773
+ }
237774
+ async function removeStripe() {
237775
+ const appClient = getAppClient();
237776
+ let response;
237777
+ try {
237778
+ response = await appClient.delete("payments/stripe", {
237779
+ timeout: 60000
237780
+ });
237781
+ } catch (error48) {
237782
+ throw await ApiError.fromHttpError(error48, "removing Stripe integration");
237783
+ }
237784
+ const result = RemoveStripeResponseSchema.safeParse(await response.json());
237785
+ if (!result.success) {
237786
+ throw new SchemaValidationError("Invalid response from server", result.error);
237787
+ }
237788
+ return result.data;
237789
+ }
237718
237790
  // src/core/resources/connector/config.ts
237719
237791
  import { join as join4 } from "node:path";
237720
237792
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
@@ -237763,7 +237835,7 @@ async function readAllConnectors(connectorsDir) {
237763
237835
  async function writeConnectors(connectorsDir, remoteConnectors) {
237764
237836
  const entries = await readConnectorFiles(connectorsDir);
237765
237837
  const typeToEntry = buildTypeToEntryMap(entries);
237766
- const newTypes = new Set(remoteConnectors.map((c) => c.integrationType));
237838
+ const newTypes = new Set(remoteConnectors.map((c) => c.type));
237767
237839
  const deleted = [];
237768
237840
  for (const [type, entry] of typeToEntry) {
237769
237841
  if (!newTypes.has(type)) {
@@ -237773,22 +237845,105 @@ async function writeConnectors(connectorsDir, remoteConnectors) {
237773
237845
  }
237774
237846
  const written = [];
237775
237847
  for (const connector of remoteConnectors) {
237776
- const existing = typeToEntry.get(connector.integrationType);
237777
- const localConnector = {
237778
- type: connector.integrationType,
237779
- scopes: connector.scopes
237780
- };
237781
- if (existing && isDeepStrictEqual2(existing.data, localConnector)) {
237848
+ const existing = typeToEntry.get(connector.type);
237849
+ if (existing && isDeepStrictEqual2(existing.data, connector)) {
237782
237850
  continue;
237783
237851
  }
237784
- const filePath = existing?.filePath ?? join4(connectorsDir, `${connector.integrationType}.${CONFIG_FILE_EXTENSION}`);
237785
- await writeJsonFile(filePath, localConnector);
237786
- written.push(connector.integrationType);
237852
+ const filePath = existing?.filePath ?? join4(connectorsDir, `${connector.type}.${CONFIG_FILE_EXTENSION}`);
237853
+ await writeJsonFile(filePath, connector);
237854
+ written.push(connector.type);
237787
237855
  }
237788
237856
  return { written, deleted };
237789
237857
  }
237858
+ // src/core/resources/connector/stripe.ts
237859
+ async function syncStripeConnector(localStripe) {
237860
+ const remoteStatus = await fetchStripeRemoteStatus();
237861
+ if (remoteStatus === "error") {
237862
+ return localStripe ? stripeError("Failed to check Stripe integration status") : null;
237863
+ }
237864
+ const isRemoteInstalled = remoteStatus.stripeMode !== null;
237865
+ const needsInstall = localStripe && !isRemoteInstalled;
237866
+ const alreadySynced = localStripe && isRemoteInstalled;
237867
+ const needsRemoval = !localStripe && isRemoteInstalled;
237868
+ if (needsInstall) {
237869
+ return handleStripeInstall();
237870
+ }
237871
+ if (alreadySynced) {
237872
+ return stripeSynced();
237873
+ }
237874
+ if (needsRemoval) {
237875
+ return handleStripeRemoval();
237876
+ }
237877
+ return null;
237878
+ }
237879
+ async function isStripeInstalled() {
237880
+ const status = await getStripeStatus();
237881
+ return status.stripeMode !== null;
237882
+ }
237883
+ async function fetchStripeRemoteStatus() {
237884
+ try {
237885
+ return await getStripeStatus();
237886
+ } catch {
237887
+ return "error";
237888
+ }
237889
+ }
237890
+ async function handleStripeInstall() {
237891
+ try {
237892
+ const result = await installStripe();
237893
+ return stripeProvisioned(result.claimUrl ?? undefined);
237894
+ } catch (err) {
237895
+ return stripeError(err instanceof Error ? err.message : String(err));
237896
+ }
237897
+ }
237898
+ async function handleStripeRemoval() {
237899
+ try {
237900
+ await removeStripe();
237901
+ return stripeRemoved();
237902
+ } catch (err) {
237903
+ return stripeError(err instanceof Error ? err.message : String(err));
237904
+ }
237905
+ }
237906
+ function stripeSynced() {
237907
+ return { type: STRIPE_CONNECTOR_TYPE, action: "synced" };
237908
+ }
237909
+ function stripeProvisioned(claimUrl) {
237910
+ return { type: STRIPE_CONNECTOR_TYPE, action: "provisioned", claimUrl };
237911
+ }
237912
+ function stripeRemoved() {
237913
+ return { type: STRIPE_CONNECTOR_TYPE, action: "removed" };
237914
+ }
237915
+ function stripeError(error48) {
237916
+ return { type: STRIPE_CONNECTOR_TYPE, action: "error", error: error48 };
237917
+ }
237918
+
237919
+ // src/core/resources/connector/pull.ts
237920
+ async function pullAllConnectors() {
237921
+ const [oauthResponse, stripeInstalled] = await Promise.all([
237922
+ listConnectors(),
237923
+ isStripeInstalled()
237924
+ ]);
237925
+ const connectors = oauthResponse.integrations.map((i) => ({
237926
+ type: i.integrationType,
237927
+ scopes: i.scopes
237928
+ }));
237929
+ if (stripeInstalled) {
237930
+ connectors.push({ type: STRIPE_CONNECTOR_TYPE, scopes: [] });
237931
+ }
237932
+ return connectors;
237933
+ }
237790
237934
  // src/core/resources/connector/push.ts
237791
237935
  async function pushConnectors(connectors) {
237936
+ const stripeConnector = connectors.find((c) => c.type === STRIPE_CONNECTOR_TYPE);
237937
+ const oauthConnectors = connectors.filter((c) => c.type !== STRIPE_CONNECTOR_TYPE);
237938
+ const oauthResults = await syncOAuthConnectors(oauthConnectors);
237939
+ const stripeResult = await syncStripeConnector(stripeConnector);
237940
+ const results = [...oauthResults];
237941
+ if (stripeResult) {
237942
+ results.push(stripeResult);
237943
+ }
237944
+ return { results };
237945
+ }
237946
+ async function syncOAuthConnectors(connectors) {
237792
237947
  const results = [];
237793
237948
  const upstream = await listConnectors();
237794
237949
  const localTypes = new Set(connectors.map((c) => c.type));
@@ -237821,7 +237976,7 @@ async function pushConnectors(connectors) {
237821
237976
  }
237822
237977
  }
237823
237978
  }
237824
- return { results };
237979
+ return results;
237825
237980
  }
237826
237981
  function getConnectorSyncResult(type, response) {
237827
237982
  if (response.error === "different_user") {
@@ -238402,7 +238557,7 @@ import { join as join7 } from "node:path";
238402
238557
  // package.json
238403
238558
  var package_default = {
238404
238559
  name: "base44",
238405
- version: "0.0.41",
238560
+ version: "0.0.42",
238406
238561
  description: "Base44 CLI - Unified interface for managing Base44 applications",
238407
238562
  type: "module",
238408
238563
  bin: {
@@ -238421,6 +238576,8 @@ var package_default = {
238421
238576
  start: "./bin/run.js",
238422
238577
  clean: "rm -rf dist && mkdir -p dist",
238423
238578
  test: "vitest run",
238579
+ "test:npm": "CLI_TEST_RUNNER=npm vitest run",
238580
+ "test:binary": "CLI_TEST_RUNNER=binary vitest run",
238424
238581
  "test:watch": "vitest",
238425
238582
  lint: "cd ../.. && bun run lint",
238426
238583
  "lint:fix": "cd ../.. && bun run lint:fix",
@@ -238469,7 +238626,6 @@ var package_default = {
238469
238626
  json5: "^2.2.3",
238470
238627
  ky: "^1.14.2",
238471
238628
  lodash: "^4.17.23",
238472
- msw: "^2.12.10",
238473
238629
  multer: "^2.0.0",
238474
238630
  nanoid: "^5.1.6",
238475
238631
  open: "^11.0.0",
@@ -246336,6 +246492,10 @@ function getDashboardUrl(projectId) {
246336
246492
  const id = projectId ?? getAppConfig().id;
246337
246493
  return `${getBase44ApiUrl()}/apps/${id}/editor/workspace/overview`;
246338
246494
  }
246495
+ function getConnectorsUrl(projectId) {
246496
+ const id = projectId ?? getAppConfig().id;
246497
+ return `${getBase44ApiUrl()}/apps/${id}/editor/workspace/app-connections`;
246498
+ }
246339
246499
  // src/cli/utils/yaml.ts
246340
246500
  var import_lodash = __toESM(require_lodash(), 1);
246341
246501
 
@@ -246531,13 +246691,13 @@ async function pullConnectorsAction() {
246531
246691
  const configDir = dirname8(project2.configPath);
246532
246692
  const connectorsDir = join11(configDir, project2.connectorsDir);
246533
246693
  const remoteConnectors = await runTask("Fetching connectors from Base44", async () => {
246534
- return await listConnectors();
246694
+ return await pullAllConnectors();
246535
246695
  }, {
246536
246696
  successMessage: "Connectors fetched successfully",
246537
246697
  errorMessage: "Failed to fetch connectors"
246538
246698
  });
246539
246699
  const { written, deleted } = await runTask("Syncing connector files", async () => {
246540
- return await writeConnectors(connectorsDir, remoteConnectors.integrations);
246700
+ return await writeConnectors(connectorsDir, remoteConnectors);
246541
246701
  }, {
246542
246702
  successMessage: "Connector files synced successfully",
246543
246703
  errorMessage: "Failed to sync connector files"
@@ -246552,7 +246712,7 @@ async function pullConnectorsAction() {
246552
246712
  R2.info("All connectors are already up to date");
246553
246713
  }
246554
246714
  return {
246555
- outroMessage: `Pulled ${remoteConnectors.integrations.length} connectors to ${connectorsDir}`
246715
+ outroMessage: `Pulled ${remoteConnectors.length} connectors to ${connectorsDir}`
246556
246716
  };
246557
246717
  }
246558
246718
  function getConnectorsPullCommand(context) {
@@ -247171,7 +247331,7 @@ var open_default = open;
247171
247331
  var POLL_INTERVAL_MS = 2000;
247172
247332
  var POLL_TIMEOUT_MS = 2 * 60 * 1000;
247173
247333
  function filterPendingOAuth(results) {
247174
- return results.filter((r) => r.action === "needs_oauth" && !!r.redirectUrl && !!r.connectionId);
247334
+ return results.filter((r) => r.action === "needs_oauth" && !!r.connectionId);
247175
247335
  }
247176
247336
  async function runOAuthFlowWithSkip(connector2) {
247177
247337
  await open_default(connector2.redirectUrl);
@@ -247189,6 +247349,10 @@ async function runOAuthFlowWithSkip(connector2) {
247189
247349
  finalStatus = "SKIPPED";
247190
247350
  return true;
247191
247351
  }
247352
+ if (!connector2.connectionId) {
247353
+ finalStatus = "FAILED";
247354
+ return true;
247355
+ }
247192
247356
  const response = await getOAuthStatus(connector2.type, connector2.connectionId);
247193
247357
  finalStatus = response.status;
247194
247358
  return response.status !== "PENDING";
@@ -247251,32 +247415,49 @@ async function promptOAuthFlows(pending, options) {
247251
247415
  function printSummary(results, oauthOutcomes) {
247252
247416
  const synced = [];
247253
247417
  const added = [];
247418
+ let provisioned;
247254
247419
  const removed = [];
247255
247420
  const skipped = [];
247256
247421
  const failed = [];
247257
247422
  for (const r of results) {
247258
- const oauthStatus = oauthOutcomes.get(r.type);
247259
- if (r.action === "synced") {
247260
- synced.push(r.type);
247261
- } else if (r.action === "removed") {
247262
- removed.push(r.type);
247263
- } else if (r.action === "error") {
247264
- failed.push({ type: r.type, error: r.error });
247265
- } else if (r.action === "needs_oauth") {
247266
- if (oauthStatus === "ACTIVE") {
247267
- added.push(r.type);
247268
- } else if (oauthStatus === "SKIPPED") {
247269
- skipped.push(r.type);
247270
- } else if (oauthStatus === "PENDING") {
247271
- failed.push({ type: r.type, error: "authorization timed out" });
247272
- } else if (oauthStatus === "FAILED") {
247273
- failed.push({ type: r.type, error: "authorization failed" });
247274
- } else {
247275
- failed.push({ type: r.type, error: "needs authorization" });
247423
+ switch (r.action) {
247424
+ case "provisioned":
247425
+ provisioned = r;
247426
+ break;
247427
+ case "synced":
247428
+ synced.push(r.type);
247429
+ break;
247430
+ case "removed":
247431
+ removed.push(r.type);
247432
+ break;
247433
+ case "error":
247434
+ failed.push({ type: r.type, error: r.error });
247435
+ break;
247436
+ case "needs_oauth": {
247437
+ const oauthStatus = oauthOutcomes.get(r.type);
247438
+ if (oauthStatus === "ACTIVE") {
247439
+ added.push(r.type);
247440
+ } else if (oauthStatus === "SKIPPED") {
247441
+ skipped.push(r.type);
247442
+ } else if (oauthStatus === "PENDING") {
247443
+ failed.push({ type: r.type, error: "authorization timed out" });
247444
+ } else if (oauthStatus === "FAILED") {
247445
+ failed.push({ type: r.type, error: "authorization failed" });
247446
+ } else {
247447
+ failed.push({ type: r.type, error: "needs authorization" });
247448
+ }
247449
+ break;
247276
247450
  }
247277
247451
  }
247278
247452
  }
247279
247453
  R2.info(theme.styles.bold("Summary:"));
247454
+ if (provisioned) {
247455
+ R2.success("Stripe sandbox provisioned");
247456
+ if (provisioned.claimUrl) {
247457
+ R2.info(` Claim your Stripe sandbox: ${theme.colors.links(provisioned.claimUrl)}`);
247458
+ }
247459
+ R2.info(` Connectors dashboard: ${theme.colors.links(getConnectorsUrl())}`);
247460
+ }
247280
247461
  if (synced.length > 0) {
247281
247462
  R2.success(`Synced: ${synced.join(", ")}`);
247282
247463
  }
@@ -247290,7 +247471,7 @@ function printSummary(results, oauthOutcomes) {
247290
247471
  R2.warn(`Skipped: ${skipped.join(", ")}`);
247291
247472
  }
247292
247473
  for (const r of failed) {
247293
- R2.error(`Failed: ${r.type}${r.error ? ` - ${r.error}` : ""}`);
247474
+ R2.error(`Failed: ${r.type} - ${r.error}`);
247294
247475
  }
247295
247476
  }
247296
247477
  async function pushConnectorsAction(isNonInteractive) {
@@ -247638,15 +247819,11 @@ ${summaryLines.join(`
247638
247819
  successMessage: theme.colors.base44Orange("Deployment completed"),
247639
247820
  errorMessage: "Deployment failed"
247640
247821
  });
247641
- const needsOAuth = filterPendingOAuth(result.connectorResults ?? []);
247642
- if (needsOAuth.length > 0) {
247643
- const oauthOutcomes = await promptOAuthFlows(needsOAuth, {
247644
- skipPrompt: options.yes || options.isNonInteractive
247645
- });
247646
- const allAuthorized = oauthOutcomes.size > 0 && [...oauthOutcomes.values()].every((s) => s === "ACTIVE");
247647
- if (!allAuthorized) {
247648
- R2.info("Some connectors still require authorization. Run 'base44 connectors push' or open the links above in your browser.");
247649
- }
247822
+ const connectorResults = result.connectorResults ?? [];
247823
+ await handleOAuthConnectors(connectorResults, options);
247824
+ const stripeResult = connectorResults.find((r) => r.type === "stripe");
247825
+ if (stripeResult?.action === "provisioned") {
247826
+ printStripeResult(stripeResult);
247650
247827
  }
247651
247828
  R2.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl())}`);
247652
247829
  if (result.appUrl) {
@@ -247662,6 +247839,25 @@ function getDeployCommand(context) {
247662
247839
  }), { requireAuth: true }, context);
247663
247840
  });
247664
247841
  }
247842
+ async function handleOAuthConnectors(connectorResults, options) {
247843
+ const needsOAuth = filterPendingOAuth(connectorResults);
247844
+ if (needsOAuth.length === 0)
247845
+ return;
247846
+ const oauthOutcomes = await promptOAuthFlows(needsOAuth, {
247847
+ skipPrompt: options.yes || options.isNonInteractive
247848
+ });
247849
+ const allAuthorized = oauthOutcomes.size > 0 && [...oauthOutcomes.values()].every((s) => s === "ACTIVE");
247850
+ if (!allAuthorized) {
247851
+ R2.info("Some connectors still require authorization. Run 'base44 connectors push' or open the links above in your browser.");
247852
+ }
247853
+ }
247854
+ function printStripeResult(r) {
247855
+ R2.success("Stripe sandbox provisioned");
247856
+ if (r.claimUrl) {
247857
+ R2.info(` Claim your Stripe sandbox: ${theme.colors.links(r.claimUrl)}`);
247858
+ }
247859
+ R2.info(` Connectors dashboard: ${theme.colors.links(getConnectorsUrl())}`);
247860
+ }
247665
247861
 
247666
247862
  // src/cli/commands/project/link.ts
247667
247863
  function validateNonInteractiveFlags2(command) {
@@ -247900,7 +248096,16 @@ async function getAllFunctionNames() {
247900
248096
  const { functions } = await readProjectConfig();
247901
248097
  return functions.map((fn) => fn.name);
247902
248098
  }
248099
+ function validateLimit(limit) {
248100
+ if (limit === undefined)
248101
+ return;
248102
+ const n2 = Number.parseInt(limit, 10);
248103
+ if (Number.isNaN(n2) || n2 < 1 || n2 > 1000) {
248104
+ throw new InvalidInputError(`Invalid limit: "${limit}". Must be a number between 1 and 1000.`);
248105
+ }
248106
+ }
247903
248107
  async function logsAction(options) {
248108
+ validateLimit(options.limit);
247904
248109
  const specifiedFunctions = parseFunctionNames(options.function);
247905
248110
  const allProjectFunctions = await getAllFunctionNames();
247906
248111
  const functionNames = specifiedFunctions.length > 0 ? specifiedFunctions : allProjectFunctions;
@@ -247917,13 +248122,7 @@ async function logsAction(options) {
247917
248122
  return { outroMessage: "Fetched logs", stdout: logsOutput };
247918
248123
  }
247919
248124
  function getLogsCommand(context) {
247920
- return new Command("logs").description("Fetch function logs for this app").option("--function <names>", "Filter by function name(s), comma-separated. If omitted, fetches logs for all project functions").option("--since <datetime>", "Show logs from this time (ISO format)", normalizeDatetime).option("--until <datetime>", "Show logs until this time (ISO format)", normalizeDatetime).addOption(new Option("--level <level>", "Filter by log level").choices([...LogLevelSchema.options]).hideHelp()).option("-n, --limit <n>", "Results per page (1-1000, default: 50)", (v) => {
247921
- const n2 = Number.parseInt(v, 10);
247922
- if (Number.isNaN(n2) || n2 < 1 || n2 > 1000) {
247923
- throw new InvalidInputError(`Invalid limit: "${v}". Must be a number between 1 and 1000.`);
247924
- }
247925
- return v;
247926
- }).addOption(new Option("--order <order>", "Sort order").choices(["asc", "desc"])).action(async (options) => {
248125
+ return new Command("logs").description("Fetch function logs for this app").option("--function <names>", "Filter by function name(s), comma-separated. If omitted, fetches logs for all project functions").option("--since <datetime>", "Show logs from this time (ISO format)", normalizeDatetime).option("--until <datetime>", "Show logs until this time (ISO format)", normalizeDatetime).addOption(new Option("--level <level>", "Filter by log level").choices([...LogLevelSchema.options]).hideHelp()).option("-n, --limit <n>", "Results per page (1-1000, default: 50)").addOption(new Option("--order <order>", "Sort order").choices(["asc", "desc"])).action(async (options) => {
247927
248126
  await runCommand(() => logsAction(options), { requireAuth: true }, context);
247928
248127
  });
247929
248128
  }
@@ -247989,11 +248188,9 @@ function parseEntries(entries) {
247989
248188
  }
247990
248189
  return secrets;
247991
248190
  }
247992
- function validateInput(command) {
247993
- const entries = command.args;
247994
- const { envFile } = command.opts();
248191
+ function validateInput(entries, options) {
247995
248192
  const hasEntries = entries.length > 0;
247996
- const hasEnvFile = Boolean(envFile);
248193
+ const hasEnvFile = Boolean(options.envFile);
247997
248194
  if (!hasEntries && !hasEnvFile) {
247998
248195
  throw new InvalidInputError("Provide KEY=VALUE pairs or use --env-file. Example: base44 secrets set KEY1=VALUE1 KEY2=VALUE2");
247999
248196
  }
@@ -248002,6 +248199,7 @@ function validateInput(command) {
248002
248199
  }
248003
248200
  }
248004
248201
  async function setSecretsAction(entries, options) {
248202
+ validateInput(entries, options);
248005
248203
  let secrets;
248006
248204
  if (options.envFile) {
248007
248205
  secrets = await parseEnvFile(resolve3(options.envFile));
@@ -248024,7 +248222,7 @@ async function setSecretsAction(entries, options) {
248024
248222
  };
248025
248223
  }
248026
248224
  function getSecretsSetCommand(context) {
248027
- return new Command("set").description("Set one or more secrets (KEY=VALUE format)").argument("[entries...]", "KEY=VALUE pairs (e.g. KEY1=VALUE1 KEY2=VALUE2)").option("--env-file <path>", "Path to .env file").hook("preAction", validateInput).action(async (entries, options) => {
248225
+ return new Command("set").description("Set one or more secrets (KEY=VALUE format)").argument("[entries...]", "KEY=VALUE pairs (e.g. KEY1=VALUE1 KEY2=VALUE2)").option("--env-file <path>", "Path to .env file").action(async (entries, options) => {
248028
248226
  await runCommand(() => setSecretsAction(entries, options), { requireAuth: true }, context);
248029
248227
  });
248030
248228
  }
@@ -248885,13 +249083,19 @@ function createEntityRoutes(db2, logger, remoteProxy, broadcast) {
248885
249083
  // src/cli/dev/dev-server/routes/integrations.ts
248886
249084
  var import_express3 = __toESM(require_express(), 1);
248887
249085
  var import_multer = __toESM(require_multer(), 1);
248888
- import { randomUUID as randomUUID4 } from "node:crypto";
249086
+ import { createHash, randomUUID as randomUUID4 } from "node:crypto";
248889
249087
  import fs28 from "node:fs";
248890
249088
  import path18 from "node:path";
249089
+ function createFileToken(fileUri) {
249090
+ return createHash("sha256").update(fileUri).digest("hex");
249091
+ }
248891
249092
  function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
248892
249093
  const router = import_express3.Router({ mergeParams: true });
248893
249094
  const parseBody = import_express3.json();
249095
+ const privateFilesDir = path18.join(mediaFilesDir, "private");
248894
249096
  fs28.mkdirSync(mediaFilesDir, { recursive: true });
249097
+ fs28.mkdirSync(privateFilesDir, { recursive: true });
249098
+ const MAX_FILE_SIZE = 50 * 1024 * 1024;
248895
249099
  const storage = import_multer.default.diskStorage({
248896
249100
  destination: mediaFilesDir,
248897
249101
  filename: (_req, file2, cb2) => {
@@ -248899,8 +249103,18 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
248899
249103
  cb2(null, `${randomUUID4()}${ext}`);
248900
249104
  }
248901
249105
  });
248902
- const MAX_FILE_SIZE = 50 * 1024 * 1024;
249106
+ const privateStorage = import_multer.default.diskStorage({
249107
+ destination: privateFilesDir,
249108
+ filename: (_req, file2, cb2) => {
249109
+ const ext = path18.extname(file2.originalname);
249110
+ cb2(null, `${randomUUID4()}${ext}`);
249111
+ }
249112
+ });
248903
249113
  const upload = import_multer.default({ storage, limits: { fileSize: MAX_FILE_SIZE } });
249114
+ const privateUpload = import_multer.default({
249115
+ storage: privateStorage,
249116
+ limits: { fileSize: MAX_FILE_SIZE }
249117
+ });
248904
249118
  router.post("/Core/UploadFile", upload.single("file"), (req, res) => {
248905
249119
  if (!req.file) {
248906
249120
  res.status(400).json({ error: "No file uploaded" });
@@ -248909,7 +249123,7 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
248909
249123
  const file_url = `${baseUrl}/media/${req.file.filename}`;
248910
249124
  res.json({ file_url });
248911
249125
  });
248912
- router.post("/Core/UploadPrivateFile", upload.single("file"), (req, res) => {
249126
+ router.post("/Core/UploadPrivateFile", privateUpload.single("file"), (req, res) => {
248913
249127
  if (!req.file) {
248914
249128
  res.status(400).json({ error: "No file uploaded" });
248915
249129
  return;
@@ -248923,8 +249137,8 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
248923
249137
  res.status(400).json({ error: "file_uri is required" });
248924
249138
  return;
248925
249139
  }
248926
- const signature = randomUUID4();
248927
- const signed_url = `${baseUrl}/media/${file_uri}?signature=${signature}`;
249140
+ const token2 = createFileToken(file_uri);
249141
+ const signed_url = `${baseUrl}/media/private/${file_uri}?token=${token2}`;
248928
249142
  res.json({ signed_url });
248929
249143
  });
248930
249144
  router.post("/Core/:endpointName", (req, res, next) => {
@@ -250693,6 +250907,24 @@ async function createDevServer(options8) {
250693
250907
  const entityRoutes = createEntityRoutes(db2, devLogger, remoteProxy, (...args) => emitEntityEvent(...args));
250694
250908
  app.use("/api/apps/:appId/entities", entityRoutes);
250695
250909
  const { path: mediaFilesDir } = await $dir();
250910
+ app.use("/media/private/:fileUri", (req, res, next) => {
250911
+ const { fileUri } = req.params;
250912
+ const token2 = req.query.token;
250913
+ if (!token2) {
250914
+ res.status(401).json({ error: "Missing token" });
250915
+ return;
250916
+ }
250917
+ const expectedToken = createFileToken(fileUri);
250918
+ if (token2 !== expectedToken) {
250919
+ res.status(400).json({
250920
+ error: "InvalidJWT",
250921
+ message: "signature verification failed",
250922
+ statusCode: "400"
250923
+ });
250924
+ return;
250925
+ }
250926
+ next();
250927
+ });
250696
250928
  app.use("/media", import_express4.default.static(mediaFilesDir));
250697
250929
  const integrationRoutes = createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, devLogger);
250698
250930
  app.use("/api/apps/:appId/integration-endpoints", integrationRoutes);
@@ -255143,4 +255375,4 @@ export {
255143
255375
  CLIExitError
255144
255376
  };
255145
255377
 
255146
- //# debugId=5197AF7DA9482FFF64756E2164756E21
255378
+ //# debugId=384DD458B8CE578E64756E2164756E21