@base44-preview/cli 0.0.31-pr.243.ce802aa → 0.0.31-pr.244.d6ebd8d

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
@@ -17446,7 +17446,7 @@ var require_lodash2 = __commonJS((exports, module) => {
17446
17446
  }
17447
17447
  return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined2, comparator) : [];
17448
17448
  });
17449
- function join10(array2, separator) {
17449
+ function join12(array2, separator) {
17450
17450
  return array2 == null ? "" : nativeJoin.call(array2, separator);
17451
17451
  }
17452
17452
  function last(array2) {
@@ -19378,7 +19378,7 @@ __p += '`;
19378
19378
  lodash.isUndefined = isUndefined;
19379
19379
  lodash.isWeakMap = isWeakMap;
19380
19380
  lodash.isWeakSet = isWeakSet;
19381
- lodash.join = join10;
19381
+ lodash.join = join12;
19382
19382
  lodash.kebabCase = kebabCase2;
19383
19383
  lodash.last = last;
19384
19384
  lodash.lastIndexOf = lastIndexOf;
@@ -20007,7 +20007,7 @@ function cleanDoc(doc2) {
20007
20007
  return mapDoc(doc2, (currentDoc) => cleanDocFn(currentDoc));
20008
20008
  }
20009
20009
  function replaceEndOfLine(doc2, replacement = literalline) {
20010
- return mapDoc(doc2, (currentDoc) => typeof currentDoc === "string" ? join10(replacement, currentDoc.split(`
20010
+ return mapDoc(doc2, (currentDoc) => typeof currentDoc === "string" ? join12(replacement, currentDoc.split(`
20011
20011
  `)) : currentDoc);
20012
20012
  }
20013
20013
  function canBreakFn(doc2) {
@@ -20087,7 +20087,7 @@ function indentIfBreak(contents, options) {
20087
20087
  negate: options.negate
20088
20088
  };
20089
20089
  }
20090
- function join10(separator, docs) {
20090
+ function join12(separator, docs) {
20091
20091
  assertDoc(separator);
20092
20092
  assertDocArray(docs);
20093
20093
  const parts = [];
@@ -20798,7 +20798,7 @@ var init_doc = __esm(() => {
20798
20798
  MODE_FLAT = Symbol("MODE_FLAT");
20799
20799
  DOC_FILL_PRINTED_LENGTH = Symbol("DOC_FILL_PRINTED_LENGTH");
20800
20800
  builders = {
20801
- join: join10,
20801
+ join: join12,
20802
20802
  line,
20803
20803
  softline,
20804
20804
  hardline,
@@ -125712,7 +125712,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
125712
125712
  return mapDoc2(doc2, (currentDoc) => cleanDocFn2(currentDoc));
125713
125713
  }
125714
125714
  function replaceEndOfLine2(doc2, replacement = literalline2) {
125715
- return mapDoc2(doc2, (currentDoc) => typeof currentDoc === "string" ? join12(replacement, currentDoc.split(`
125715
+ return mapDoc2(doc2, (currentDoc) => typeof currentDoc === "string" ? join14(replacement, currentDoc.split(`
125716
125716
  `)) : currentDoc);
125717
125717
  }
125718
125718
  function canBreakFn2(doc2) {
@@ -125798,7 +125798,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
125798
125798
  negate: options8.negate
125799
125799
  };
125800
125800
  }
125801
- function join12(separator, docs) {
125801
+ function join14(separator, docs) {
125802
125802
  assertDoc2(separator);
125803
125803
  assertDocArray2(docs);
125804
125804
  const parts = [];
@@ -126463,7 +126463,7 @@ Expected it to be ${EXPECTED_TYPE_VALUES}.`;
126463
126463
  }
126464
126464
  }
126465
126465
  var builders2 = {
126466
- join: join12,
126466
+ join: join14,
126467
126467
  line: line3,
126468
126468
  softline: softline2,
126469
126469
  hardline: hardline4,
@@ -155678,10 +155678,10 @@ var require_view = __commonJS((exports, module) => {
155678
155678
  var debug = require_src4()("express:view");
155679
155679
  var path18 = __require("node:path");
155680
155680
  var fs28 = __require("node:fs");
155681
- var dirname10 = path18.dirname;
155681
+ var dirname11 = path18.dirname;
155682
155682
  var basename4 = path18.basename;
155683
155683
  var extname2 = path18.extname;
155684
- var join13 = path18.join;
155684
+ var join15 = path18.join;
155685
155685
  var resolve5 = path18.resolve;
155686
155686
  module.exports = View;
155687
155687
  function View(name2, options8) {
@@ -155717,7 +155717,7 @@ var require_view = __commonJS((exports, module) => {
155717
155717
  for (var i5 = 0;i5 < roots.length && !path19; i5++) {
155718
155718
  var root2 = roots[i5];
155719
155719
  var loc = resolve5(root2, name2);
155720
- var dir = dirname10(loc);
155720
+ var dir = dirname11(loc);
155721
155721
  var file2 = basename4(loc);
155722
155722
  path19 = this.resolve(dir, file2);
155723
155723
  }
@@ -155743,12 +155743,12 @@ var require_view = __commonJS((exports, module) => {
155743
155743
  };
155744
155744
  View.prototype.resolve = function resolve6(dir, file2) {
155745
155745
  var ext = this.ext;
155746
- var path19 = join13(dir, file2);
155746
+ var path19 = join15(dir, file2);
155747
155747
  var stat2 = tryStat(path19);
155748
155748
  if (stat2 && stat2.isFile()) {
155749
155749
  return path19;
155750
155750
  }
155751
- path19 = join13(dir, basename4(file2, ext), "index" + ext);
155751
+ path19 = join15(dir, basename4(file2, ext), "index" + ext);
155752
155752
  stat2 = tryStat(path19);
155753
155753
  if (stat2 && stat2.isFile()) {
155754
155754
  return path19;
@@ -159443,7 +159443,7 @@ var require_send = __commonJS((exports, module) => {
159443
159443
  var Stream2 = __require("stream");
159444
159444
  var util2 = __require("util");
159445
159445
  var extname2 = path18.extname;
159446
- var join13 = path18.join;
159446
+ var join15 = path18.join;
159447
159447
  var normalize = path18.normalize;
159448
159448
  var resolve5 = path18.resolve;
159449
159449
  var sep = path18.sep;
@@ -159615,7 +159615,7 @@ var require_send = __commonJS((exports, module) => {
159615
159615
  return res;
159616
159616
  }
159617
159617
  parts = path19.split(sep);
159618
- path19 = normalize(join13(root2, path19));
159618
+ path19 = normalize(join15(root2, path19));
159619
159619
  } else {
159620
159620
  if (UP_PATH_REGEXP.test(path19)) {
159621
159621
  debug('malicious path "%s"', path19);
@@ -159755,7 +159755,7 @@ var require_send = __commonJS((exports, module) => {
159755
159755
  return self2.onStatError(err);
159756
159756
  return self2.error(404);
159757
159757
  }
159758
- var p4 = join13(path19, self2._index[i5]);
159758
+ var p4 = join15(path19, self2._index[i5]);
159759
159759
  debug('stat "%s"', p4);
159760
159760
  fs28.stat(p4, function(err2, stat2) {
159761
159761
  if (err2)
@@ -162834,7 +162834,7 @@ var {
162834
162834
  } = import__.default;
162835
162835
 
162836
162836
  // src/cli/commands/agents/pull.ts
162837
- import { dirname as dirname7, join as join8 } from "node:path";
162837
+ import { dirname as dirname7, join as join9 } from "node:path";
162838
162838
 
162839
162839
  // node_modules/@clack/core/dist/index.mjs
162840
162840
  var import_sisteransi = __toESM(require_src(), 1);
@@ -184871,7 +184871,7 @@ var generateGlobTasks = normalizeArguments(generateTasks);
184871
184871
  var generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync);
184872
184872
 
184873
184873
  // src/core/project/config.ts
184874
- import { dirname as dirname5, join as join5 } from "node:path";
184874
+ import { dirname as dirname5, join as join6 } from "node:path";
184875
184875
 
184876
184876
  // src/core/resources/agent/schema.ts
184877
184877
  var EntityOperationSchema = exports_external.enum(["create", "update", "delete", "read"]);
@@ -184888,7 +184888,7 @@ var ToolConfigSchema = exports_external.union([
184888
184888
  BackendFunctionToolConfigSchema
184889
184889
  ]);
184890
184890
  var AgentConfigSchema = exports_external.looseObject({
184891
- name: exports_external.string().regex(/^[a-z0-9_]+$/, "Agent name must be lowercase alphanumeric with underscores").min(1).max(100),
184891
+ name: exports_external.string().trim().min(1).max(100),
184892
184892
  description: exports_external.string().trim().min(1, "Description is required"),
184893
184893
  instructions: exports_external.string().trim().min(1, "Instructions are required"),
184894
184894
  tool_configs: exports_external.array(ToolConfigSchema).optional().default([]),
@@ -184944,6 +184944,9 @@ async function fetchAgents() {
184944
184944
  }
184945
184945
  // src/core/resources/agent/config.ts
184946
184946
  import { join as join3 } from "node:path";
184947
+ function toFileSlug(name2) {
184948
+ return name2.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
184949
+ }
184947
184950
  async function readAgentFile(agentPath) {
184948
184951
  const parsed = await readJsonFile(agentPath);
184949
184952
  const result = AgentConfigSchema.safeParse(parsed);
@@ -184975,7 +184978,8 @@ async function writeAgents(agentsDir, remoteAgents) {
184975
184978
  const newNames = new Set(remoteAgents.map((a) => a.name));
184976
184979
  const toDelete = existingAgents.filter((a) => !newNames.has(a.name));
184977
184980
  for (const agent of toDelete) {
184978
- const files = await globby(`${agent.name}.${CONFIG_FILE_EXTENSION_GLOB}`, {
184981
+ const slug = toFileSlug(agent.name);
184982
+ const files = await globby(`${slug}.${CONFIG_FILE_EXTENSION_GLOB}`, {
184979
184983
  cwd: agentsDir,
184980
184984
  absolute: true
184981
184985
  });
@@ -184984,7 +184988,8 @@ async function writeAgents(agentsDir, remoteAgents) {
184984
184988
  }
184985
184989
  }
184986
184990
  for (const agent of remoteAgents) {
184987
- const filePath = join3(agentsDir, `${agent.name}.${CONFIG_FILE_EXTENSION}`);
184991
+ const slug = toFileSlug(agent.name);
184992
+ const filePath = join3(agentsDir, `${slug}.${CONFIG_FILE_EXTENSION}`);
184988
184993
  await writeJsonFile(filePath, agent);
184989
184994
  }
184990
184995
  const written = remoteAgents.map((a) => a.name);
@@ -185198,6 +185203,8 @@ async function removeConnector(integrationType) {
185198
185203
  return result.data;
185199
185204
  }
185200
185205
  // src/core/resources/connector/config.ts
185206
+ import { join as join4 } from "node:path";
185207
+ import { isDeepStrictEqual } from "node:util";
185201
185208
  async function readConnectorFile(connectorPath) {
185202
185209
  const parsed = await readJsonFile(connectorPath);
185203
185210
  const result = ConnectorResourceSchema.safeParse(parsed);
@@ -185206,7 +185213,7 @@ async function readConnectorFile(connectorPath) {
185206
185213
  }
185207
185214
  return result.data;
185208
185215
  }
185209
- async function readAllConnectors(connectorsDir) {
185216
+ async function readConnectorFiles(connectorsDir) {
185210
185217
  if (!await pathExists(connectorsDir)) {
185211
185218
  return [];
185212
185219
  }
@@ -185214,24 +185221,58 @@ async function readAllConnectors(connectorsDir) {
185214
185221
  cwd: connectorsDir,
185215
185222
  absolute: true
185216
185223
  });
185217
- const connectors = await Promise.all(files.map((filePath) => readConnectorFile(filePath)));
185218
- assertNoDuplicateConnectors(connectors);
185219
- return connectors;
185224
+ return await Promise.all(files.map(async (filePath) => ({
185225
+ data: await readConnectorFile(filePath),
185226
+ filePath
185227
+ })));
185220
185228
  }
185221
- function assertNoDuplicateConnectors(connectors) {
185222
- const types = new Set;
185223
- for (const connector of connectors) {
185224
- if (types.has(connector.type)) {
185225
- throw new InvalidInputError(`Duplicate connector type "${connector.type}"`, {
185229
+ function buildTypeToEntryMap(entries) {
185230
+ const typeToEntry = new Map;
185231
+ for (const entry of entries) {
185232
+ if (typeToEntry.has(entry.data.type)) {
185233
+ throw new InvalidInputError(`Duplicate connector type "${entry.data.type}"`, {
185226
185234
  hints: [
185227
185235
  {
185228
- message: `Remove duplicate connectors with type "${connector.type}" - only one connector per type is allowed`
185236
+ message: `Remove duplicate connectors with type "${entry.data.type}" - only one connector per type is allowed`
185229
185237
  }
185230
185238
  ]
185231
185239
  });
185232
185240
  }
185233
- types.add(connector.type);
185241
+ typeToEntry.set(entry.data.type, entry);
185242
+ }
185243
+ return typeToEntry;
185244
+ }
185245
+ async function readAllConnectors(connectorsDir) {
185246
+ const entries = await readConnectorFiles(connectorsDir);
185247
+ const typeToEntry = buildTypeToEntryMap(entries);
185248
+ return [...typeToEntry.values()].map((e2) => e2.data);
185249
+ }
185250
+ async function writeConnectors(connectorsDir, remoteConnectors) {
185251
+ const entries = await readConnectorFiles(connectorsDir);
185252
+ const typeToEntry = buildTypeToEntryMap(entries);
185253
+ const newTypes = new Set(remoteConnectors.map((c) => c.integrationType));
185254
+ const deleted = [];
185255
+ for (const [type, entry] of typeToEntry) {
185256
+ if (!newTypes.has(type)) {
185257
+ await deleteFile(entry.filePath);
185258
+ deleted.push(type);
185259
+ }
185260
+ }
185261
+ const written = [];
185262
+ for (const connector of remoteConnectors) {
185263
+ const existing = typeToEntry.get(connector.integrationType);
185264
+ const localConnector = {
185265
+ type: connector.integrationType,
185266
+ scopes: connector.scopes
185267
+ };
185268
+ if (existing && isDeepStrictEqual(existing.data, localConnector)) {
185269
+ continue;
185270
+ }
185271
+ const filePath = existing?.filePath ?? join4(connectorsDir, `${connector.integrationType}.${CONFIG_FILE_EXTENSION}`);
185272
+ await writeJsonFile(filePath, localConnector);
185273
+ written.push(connector.integrationType);
185234
185274
  }
185275
+ return { written, deleted };
185235
185276
  }
185236
185277
  // src/core/resources/connector/push.ts
185237
185278
  async function pushConnectors(connectors) {
@@ -185573,7 +185614,7 @@ async function deployFunctions(functions) {
185573
185614
  return result.data;
185574
185615
  }
185575
185616
  // src/core/resources/function/config.ts
185576
- import { dirname as dirname4, join as join4 } from "node:path";
185617
+ import { dirname as dirname4, join as join5 } from "node:path";
185577
185618
  async function readFunctionConfig(configPath) {
185578
185619
  const parsed = await readJsonFile(configPath);
185579
185620
  const result = FunctionConfigSchema.safeParse(parsed);
@@ -185585,7 +185626,7 @@ async function readFunctionConfig(configPath) {
185585
185626
  async function readFunction(configPath) {
185586
185627
  const config5 = await readFunctionConfig(configPath);
185587
185628
  const functionDir = dirname4(configPath);
185588
- const entryPath = join4(functionDir, config5.entry);
185629
+ const entryPath = join5(functionDir, config5.entry);
185589
185630
  if (!await pathExists(entryPath)) {
185590
185631
  throw new FileNotFoundError(`Function entry file not found: ${entryPath} (referenced in ${configPath})`);
185591
185632
  }
@@ -185674,10 +185715,10 @@ async function readProjectConfig(projectRoot) {
185674
185715
  const project = result.data;
185675
185716
  const configDir = dirname5(configPath);
185676
185717
  const [entities, functions, agents, connectors] = await Promise.all([
185677
- entityResource.readAll(join5(configDir, project.entitiesDir)),
185678
- functionResource.readAll(join5(configDir, project.functionsDir)),
185679
- agentResource.readAll(join5(configDir, project.agentsDir)),
185680
- connectorResource.readAll(join5(configDir, project.connectorsDir))
185718
+ entityResource.readAll(join6(configDir, project.entitiesDir)),
185719
+ functionResource.readAll(join6(configDir, project.functionsDir)),
185720
+ agentResource.readAll(join6(configDir, project.agentsDir)),
185721
+ connectorResource.readAll(join6(configDir, project.connectorsDir))
185681
185722
  ]);
185682
185723
  return {
185683
185724
  project: { ...project, root, configPath },
@@ -185774,7 +185815,7 @@ async function readAppConfig(projectRoot) {
185774
185815
  // src/core/project/template.ts
185775
185816
  var import_ejs = __toESM(require_ejs(), 1);
185776
185817
  var import_front_matter = __toESM(require_front_matter(), 1);
185777
- import { dirname as dirname6, join as join6 } from "node:path";
185818
+ import { dirname as dirname6, join as join7 } from "node:path";
185778
185819
  async function listTemplates() {
185779
185820
  const parsed = await readJsonFile(getTemplatesIndexPath());
185780
185821
  const result = TemplatesConfigSchema.safeParse(parsed);
@@ -185784,23 +185825,23 @@ async function listTemplates() {
185784
185825
  return result.data.templates;
185785
185826
  }
185786
185827
  async function renderTemplate(template, destPath, data) {
185787
- const templateDir = join6(getTemplatesDir(), template.path);
185828
+ const templateDir = join7(getTemplatesDir(), template.path);
185788
185829
  const files = await globby("**/*", {
185789
185830
  cwd: templateDir,
185790
185831
  dot: true,
185791
185832
  onlyFiles: true
185792
185833
  });
185793
185834
  for (const file2 of files) {
185794
- const srcPath = join6(templateDir, file2);
185835
+ const srcPath = join7(templateDir, file2);
185795
185836
  try {
185796
185837
  if (file2.endsWith(".ejs")) {
185797
185838
  const rendered = await import_ejs.default.renderFile(srcPath, data);
185798
185839
  const { attributes, body } = import_front_matter.default(rendered);
185799
- const destFile = attributes.outputFileName ? join6(dirname6(file2), attributes.outputFileName) : file2.replace(/\.ejs$/, "");
185800
- const destFilePath = join6(destPath, destFile);
185840
+ const destFile = attributes.outputFileName ? join7(dirname6(file2), attributes.outputFileName) : file2.replace(/\.ejs$/, "");
185841
+ const destFilePath = join7(destPath, destFile);
185801
185842
  await writeFile(destFilePath, body);
185802
185843
  } else {
185803
- const destFilePath = join6(destPath, file2);
185844
+ const destFilePath = join7(destPath, file2);
185804
185845
  await copyFile(srcPath, destFilePath);
185805
185846
  }
185806
185847
  } catch (error48) {
@@ -185903,7 +185944,7 @@ async function getSiteFilePaths(outputDir) {
185903
185944
  // src/core/site/deploy.ts
185904
185945
  import { randomUUID } from "node:crypto";
185905
185946
  import { tmpdir } from "node:os";
185906
- import { join as join7 } from "node:path";
185947
+ import { join as join8 } from "node:path";
185907
185948
  async function deploySite(siteOutputDir) {
185908
185949
  if (!await pathExists(siteOutputDir)) {
185909
185950
  throw new FileNotFoundError(`Output directory does not exist: ${siteOutputDir}. Make sure to build your project first.`, {
@@ -185920,7 +185961,7 @@ async function deploySite(siteOutputDir) {
185920
185961
  ]
185921
185962
  });
185922
185963
  }
185923
- const archivePath = join7(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
185964
+ const archivePath = join8(tmpdir(), `base44-site-${randomUUID()}.tar.gz`);
185924
185965
  try {
185925
185966
  await createArchive(siteOutputDir, archivePath);
185926
185967
  return await uploadSite(archivePath);
@@ -185937,24 +185978,26 @@ async function createArchive(pathToArchive, targetArchivePath) {
185937
185978
  }
185938
185979
  // src/core/project/deploy.ts
185939
185980
  function hasResourcesToDeploy(projectData) {
185940
- const { project, entities, functions, agents } = projectData;
185981
+ const { project, entities, functions, agents, connectors } = projectData;
185941
185982
  const hasSite = Boolean(project.site?.outputDirectory);
185942
185983
  const hasEntities = entities.length > 0;
185943
185984
  const hasFunctions = functions.length > 0;
185944
185985
  const hasAgents = agents.length > 0;
185945
- return hasEntities || hasFunctions || hasAgents || hasSite;
185986
+ const hasConnectors = connectors.length > 0;
185987
+ return hasEntities || hasFunctions || hasAgents || hasConnectors || hasSite;
185946
185988
  }
185947
185989
  async function deployAll(projectData) {
185948
- const { project, entities, functions, agents } = projectData;
185990
+ const { project, entities, functions, agents, connectors } = projectData;
185949
185991
  await entityResource.push(entities);
185950
185992
  await functionResource.push(functions);
185951
185993
  await agentResource.push(agents);
185994
+ const { results: connectorResults } = await pushConnectors(connectors);
185952
185995
  if (project.site?.outputDirectory) {
185953
185996
  const outputDir = resolve(project.root, project.site.outputDirectory);
185954
185997
  const { appUrl } = await deploySite(outputDir);
185955
- return { appUrl };
185998
+ return { appUrl, connectorResults };
185956
185999
  }
185957
- return {};
186000
+ return { connectorResults };
185958
186001
  }
185959
186002
  // src/core/clients/base44-client.ts
185960
186003
  var retriedRequests = new WeakSet;
@@ -193596,7 +193639,7 @@ function getDashboardUrl(projectId) {
193596
193639
  async function pullAgentsAction() {
193597
193640
  const { project: project2 } = await readProjectConfig();
193598
193641
  const configDir = dirname7(project2.configPath);
193599
- const agentsDir = join8(configDir, project2.agentsDir);
193642
+ const agentsDir = join9(configDir, project2.agentsDir);
193600
193643
  const remoteAgents = await runTask("Fetching agents from Base44", async () => {
193601
193644
  return await fetchAgents();
193602
193645
  }, {
@@ -193689,6 +193732,43 @@ function getWhoamiCommand(context) {
193689
193732
  });
193690
193733
  }
193691
193734
 
193735
+ // src/cli/commands/connectors/pull.ts
193736
+ import { dirname as dirname8, join as join10 } from "node:path";
193737
+ async function pullConnectorsAction() {
193738
+ const { project: project2 } = await readProjectConfig();
193739
+ const configDir = dirname8(project2.configPath);
193740
+ const connectorsDir = join10(configDir, project2.connectorsDir);
193741
+ const remoteConnectors = await runTask("Fetching connectors from Base44", async () => {
193742
+ return await listConnectors();
193743
+ }, {
193744
+ successMessage: "Connectors fetched successfully",
193745
+ errorMessage: "Failed to fetch connectors"
193746
+ });
193747
+ const { written, deleted } = await runTask("Syncing connector files", async () => {
193748
+ return await writeConnectors(connectorsDir, remoteConnectors.integrations);
193749
+ }, {
193750
+ successMessage: "Connector files synced successfully",
193751
+ errorMessage: "Failed to sync connector files"
193752
+ });
193753
+ if (written.length > 0) {
193754
+ M2.success(`Written: ${written.join(", ")}`);
193755
+ }
193756
+ if (deleted.length > 0) {
193757
+ M2.warn(`Deleted: ${deleted.join(", ")}`);
193758
+ }
193759
+ if (written.length === 0 && deleted.length === 0) {
193760
+ M2.info("All connectors are already up to date");
193761
+ }
193762
+ return {
193763
+ outroMessage: `Pulled ${remoteConnectors.integrations.length} connectors to ${connectorsDir}`
193764
+ };
193765
+ }
193766
+ function getConnectorsPullCommand(context) {
193767
+ return new Command("pull").description("Pull connectors from Base44 to local files (replaces all local connector configs)").action(async () => {
193768
+ await runCommand(pullConnectorsAction, { requireAuth: true }, context);
193769
+ });
193770
+ }
193771
+
193692
193772
  // node_modules/open/index.js
193693
193773
  import process20 from "node:process";
193694
193774
  import path16 from "node:path";
@@ -194295,14 +194375,94 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
194295
194375
  }));
194296
194376
  var open_default = open;
194297
194377
 
194298
- // src/cli/commands/connectors/push.ts
194299
- function isPendingOAuth(r2) {
194300
- return r2.action === "needs_oauth" && !!r2.redirectUrl && !!r2.connectionId;
194378
+ // src/cli/commands/connectors/oauth-prompt.ts
194379
+ var POLL_INTERVAL_MS = 2000;
194380
+ var POLL_TIMEOUT_MS = 2 * 60 * 1000;
194381
+ function filterPendingOAuth(results) {
194382
+ return results.filter((r2) => r2.action === "needs_oauth" && !!r2.redirectUrl && !!r2.connectionId);
194383
+ }
194384
+ async function runOAuthFlowWithSkip(connector2) {
194385
+ await open_default(connector2.redirectUrl);
194386
+ let finalStatus = "PENDING";
194387
+ let skipped = false;
194388
+ const s = Y2();
194389
+ const originalExit = process.exit;
194390
+ process.exit = () => {
194391
+ skipped = true;
194392
+ s.stop(`${connector2.type} skipped`);
194393
+ };
194394
+ s.start(`Waiting for ${connector2.type} authorization... (Esc to skip)`);
194395
+ try {
194396
+ await pWaitFor(async () => {
194397
+ if (skipped) {
194398
+ finalStatus = "SKIPPED";
194399
+ return true;
194400
+ }
194401
+ const response = await getOAuthStatus(connector2.type, connector2.connectionId);
194402
+ finalStatus = response.status;
194403
+ return response.status !== "PENDING";
194404
+ }, {
194405
+ interval: POLL_INTERVAL_MS,
194406
+ timeout: POLL_TIMEOUT_MS
194407
+ });
194408
+ } catch (err) {
194409
+ if (err instanceof TimeoutError2) {
194410
+ finalStatus = "PENDING";
194411
+ } else {
194412
+ throw err;
194413
+ }
194414
+ } finally {
194415
+ process.exit = originalExit;
194416
+ if (!skipped) {
194417
+ if (finalStatus === "ACTIVE") {
194418
+ s.stop(`${connector2.type} authorization complete`);
194419
+ } else if (finalStatus === "FAILED") {
194420
+ s.stop(`${connector2.type} authorization failed`);
194421
+ } else {
194422
+ s.stop(`${connector2.type} authorization timed out`);
194423
+ }
194424
+ }
194425
+ }
194426
+ return finalStatus;
194427
+ }
194428
+ async function promptOAuthFlows(pending, options) {
194429
+ const outcomes = new Map;
194430
+ if (pending.length === 0) {
194431
+ return outcomes;
194432
+ }
194433
+ M2.warn(`${pending.length} connector(s) require authorization in your browser:`);
194434
+ for (const connector2 of pending) {
194435
+ M2.info(` ${connector2.type}: ${theme.styles.dim(connector2.redirectUrl)}`);
194436
+ }
194437
+ if (options?.skipPrompt) {
194438
+ return outcomes;
194439
+ }
194440
+ const shouldAuth = await ye({
194441
+ message: "Open browser to authorize now?"
194442
+ });
194443
+ if (pD(shouldAuth) || !shouldAuth) {
194444
+ return outcomes;
194445
+ }
194446
+ for (const connector2 of pending) {
194447
+ try {
194448
+ M2.info(`
194449
+ Opening browser for ${connector2.type}...`);
194450
+ const status = await runOAuthFlowWithSkip(connector2);
194451
+ outcomes.set(connector2.type, status);
194452
+ } catch (err) {
194453
+ M2.error(`Failed to authorize ${connector2.type}: ${err instanceof Error ? err.message : String(err)}`);
194454
+ outcomes.set(connector2.type, "FAILED");
194455
+ }
194456
+ }
194457
+ return outcomes;
194301
194458
  }
194459
+
194460
+ // src/cli/commands/connectors/push.ts
194302
194461
  function printSummary(results, oauthOutcomes) {
194303
194462
  const synced = [];
194304
194463
  const added = [];
194305
194464
  const removed = [];
194465
+ const skipped = [];
194306
194466
  const failed = [];
194307
194467
  for (const r2 of results) {
194308
194468
  const oauthStatus = oauthOutcomes.get(r2.type);
@@ -194315,6 +194475,8 @@ function printSummary(results, oauthOutcomes) {
194315
194475
  } else if (r2.action === "needs_oauth") {
194316
194476
  if (oauthStatus === "ACTIVE") {
194317
194477
  added.push(r2.type);
194478
+ } else if (oauthStatus === "SKIPPED") {
194479
+ skipped.push(r2.type);
194318
194480
  } else if (oauthStatus === "PENDING") {
194319
194481
  failed.push({ type: r2.type, error: "authorization timed out" });
194320
194482
  } else if (oauthStatus === "FAILED") {
@@ -194324,7 +194486,6 @@ function printSummary(results, oauthOutcomes) {
194324
194486
  }
194325
194487
  }
194326
194488
  }
194327
- M2.info("");
194328
194489
  M2.info(theme.styles.bold("Summary:"));
194329
194490
  if (synced.length > 0) {
194330
194491
  M2.success(`Synced: ${synced.join(", ")}`);
@@ -194335,6 +194496,9 @@ function printSummary(results, oauthOutcomes) {
194335
194496
  if (removed.length > 0) {
194336
194497
  M2.info(theme.styles.dim(`Removed: ${removed.join(", ")}`));
194337
194498
  }
194499
+ if (skipped.length > 0) {
194500
+ M2.warn(`Skipped: ${skipped.join(", ")}`);
194501
+ }
194338
194502
  for (const r2 of failed) {
194339
194503
  M2.error(`Failed: ${r2.type}${r2.error ? ` - ${r2.error}` : ""}`);
194340
194504
  }
@@ -194350,59 +194514,14 @@ async function pushConnectorsAction() {
194350
194514
  const { results } = await runTask("Pushing connectors to Base44", async () => {
194351
194515
  return await pushConnectors(connectors);
194352
194516
  });
194353
- const oauthOutcomes = new Map;
194354
- const needsOAuth = results.filter(isPendingOAuth);
194517
+ const needsOAuth = filterPendingOAuth(results);
194355
194518
  let outroMessage = "Connectors pushed to Base44";
194356
- if (needsOAuth.length === 0) {
194357
- printSummary(results, oauthOutcomes);
194358
- return { outroMessage };
194359
- }
194360
- M2.warn(`${needsOAuth.length} connector(s) require authorization in your browser:`);
194361
- for (const connector2 of needsOAuth) {
194362
- M2.info(` '${connector2.type}': ${theme.styles.dim(connector2.redirectUrl)}`);
194363
- }
194364
- const pending = needsOAuth.map((c3) => c3.type).join(", ");
194365
- if (process.env.CI) {
194366
- outroMessage = `Skipped OAuth in CI. Pending: ${pending}. Run 'base44 connectors push' locally to authorize.`;
194367
- } else {
194368
- const shouldAuth = await ye({
194369
- message: "Open browser to authorize now?"
194370
- });
194371
- if (pD(shouldAuth) || !shouldAuth) {
194372
- outroMessage = `Authorization skipped. Pending: ${pending}. Run 'base44 connectors push' again to complete.`;
194373
- } else {
194374
- for (const connector2 of needsOAuth) {
194375
- try {
194376
- M2.info(`
194377
- Opening browser for '${connector2.type}'...`);
194378
- await open_default(connector2.redirectUrl);
194379
- let finalStatus = "PENDING";
194380
- await runTask(`Waiting for '${connector2.type}' authorization...`, async () => {
194381
- await pWaitFor(async () => {
194382
- const response = await getOAuthStatus(connector2.type, connector2.connectionId);
194383
- finalStatus = response.status;
194384
- return response.status !== "PENDING";
194385
- }, {
194386
- interval: 2000,
194387
- timeout: 2 * 60 * 1000
194388
- });
194389
- }, {
194390
- successMessage: `'${connector2.type}' authorization complete`,
194391
- errorMessage: `'${connector2.type}' authorization failed`
194392
- }).catch((err) => {
194393
- if (err instanceof TimeoutError2) {
194394
- finalStatus = "PENDING";
194395
- } else {
194396
- throw err;
194397
- }
194398
- });
194399
- oauthOutcomes.set(connector2.type, finalStatus);
194400
- } catch (err) {
194401
- M2.error(`Failed to authorize '${connector2.type}': ${err instanceof Error ? err.message : String(err)}`);
194402
- oauthOutcomes.set(connector2.type, "FAILED");
194403
- }
194404
- }
194405
- }
194519
+ const oauthOutcomes = await promptOAuthFlows(needsOAuth, {
194520
+ skipPrompt: !!process.env.CI
194521
+ });
194522
+ const allAuthorized = oauthOutcomes.size > 0 && [...oauthOutcomes.values()].every((s) => s === "ACTIVE");
194523
+ if (needsOAuth.length > 0 && !allAuthorized) {
194524
+ outroMessage = process.env.CI ? "Skipped OAuth in CI. Run 'base44 connectors push' locally or open the links above to authorize." : "Some connectors still require authorization. Run 'base44 connectors push' or open the links above to authorize.";
194406
194525
  }
194407
194526
  printSummary(results, oauthOutcomes);
194408
194527
  return { outroMessage };
@@ -194415,7 +194534,7 @@ function getConnectorsPushCommand(context) {
194415
194534
 
194416
194535
  // src/cli/commands/connectors/index.ts
194417
194536
  function getConnectorsCommand(context) {
194418
- return new Command("connectors").description("Manage project connectors (OAuth integrations)").addCommand(getConnectorsPushCommand(context));
194537
+ return new Command("connectors").description("Manage project connectors (OAuth integrations)").addCommand(getConnectorsPullCommand(context)).addCommand(getConnectorsPushCommand(context));
194419
194538
  }
194420
194539
 
194421
194540
  // src/cli/commands/dashboard/open.ts
@@ -194509,7 +194628,7 @@ function getFunctionsDeployCommand(context) {
194509
194628
  }
194510
194629
 
194511
194630
  // src/cli/commands/project/create.ts
194512
- import { basename as basename3, join as join9, resolve as resolve2 } from "node:path";
194631
+ import { basename as basename3, join as join11, resolve as resolve2 } from "node:path";
194513
194632
  var import_lodash = __toESM(require_lodash(), 1);
194514
194633
  var DEFAULT_TEMPLATE_ID = "backend-only";
194515
194634
  async function getTemplateById(templateId) {
@@ -194645,7 +194764,7 @@ async function executeCreate({
194645
194764
  updateMessage("Building project...");
194646
194765
  await execa({ cwd: resolvedPath, shell: true })`${buildCommand}`;
194647
194766
  updateMessage("Deploying site...");
194648
- return await deploySite(join9(resolvedPath, outputDirectory));
194767
+ return await deploySite(join11(resolvedPath, outputDirectory));
194649
194768
  }, {
194650
194769
  successMessage: theme.colors.base44Orange("Site deployed successfully"),
194651
194770
  errorMessage: "Failed to deploy site"
@@ -194693,7 +194812,7 @@ async function deployAction(options) {
194693
194812
  outroMessage: "No resources found to deploy"
194694
194813
  };
194695
194814
  }
194696
- const { project: project2, entities, functions, agents } = projectData;
194815
+ const { project: project2, entities, functions, agents, connectors } = projectData;
194697
194816
  const summaryLines = [];
194698
194817
  if (entities.length > 0) {
194699
194818
  summaryLines.push(` - ${entities.length} ${entities.length === 1 ? "entity" : "entities"}`);
@@ -194704,6 +194823,9 @@ async function deployAction(options) {
194704
194823
  if (agents.length > 0) {
194705
194824
  summaryLines.push(` - ${agents.length} ${agents.length === 1 ? "agent" : "agents"}`);
194706
194825
  }
194826
+ if (connectors.length > 0) {
194827
+ summaryLines.push(` - ${connectors.length} ${connectors.length === 1 ? "connector" : "connectors"}`);
194828
+ }
194707
194829
  if (project2.site?.outputDirectory) {
194708
194830
  summaryLines.push(` - Site from ${project2.site.outputDirectory}`);
194709
194831
  }
@@ -194728,6 +194850,16 @@ ${summaryLines.join(`
194728
194850
  successMessage: theme.colors.base44Orange("Deployment completed"),
194729
194851
  errorMessage: "Deployment failed"
194730
194852
  });
194853
+ const needsOAuth = filterPendingOAuth(result.connectorResults ?? []);
194854
+ if (needsOAuth.length > 0) {
194855
+ const oauthOutcomes = await promptOAuthFlows(needsOAuth, {
194856
+ skipPrompt: options.yes || !!process.env.CI
194857
+ });
194858
+ const allAuthorized = oauthOutcomes.size > 0 && [...oauthOutcomes.values()].every((s) => s === "ACTIVE");
194859
+ if (!allAuthorized) {
194860
+ M2.info("Some connectors still require authorization. Run 'base44 connectors push' or open the links above in your browser.");
194861
+ }
194862
+ }
194731
194863
  M2.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl())}`);
194732
194864
  if (result.appUrl) {
194733
194865
  M2.message(`${theme.styles.header("App URL")}: ${theme.colors.links(result.appUrl)}`);
@@ -194735,7 +194867,7 @@ ${summaryLines.join(`
194735
194867
  return { outroMessage: "App deployed successfully" };
194736
194868
  }
194737
194869
  function getDeployCommand(context) {
194738
- return new Command("deploy").description("Deploy all project resources (entities, functions, agents, and site)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
194870
+ return new Command("deploy").description("Deploy all project resources (entities, functions, agents, connectors, and site)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
194739
194871
  await runCommand(() => deployAction(options), { requireAuth: true }, context);
194740
194872
  });
194741
194873
  }
@@ -195026,10 +195158,10 @@ function toPascalCase(name2) {
195026
195158
  return name2.split(/[-_\s]+/).map((w9) => w9.charAt(0).toUpperCase() + w9.slice(1)).join("");
195027
195159
  }
195028
195160
  // src/core/types/update-project.ts
195029
- import { join as join12 } from "node:path";
195161
+ import { join as join14 } from "node:path";
195030
195162
  var TYPES_INCLUDE_PATH = `${PROJECT_SUBDIR}/${TYPES_OUTPUT_SUBDIR}/*.d.ts`;
195031
195163
  async function updateProjectConfig(projectRoot) {
195032
- const tsconfigPath = join12(projectRoot, "tsconfig.json");
195164
+ const tsconfigPath = join14(projectRoot, "tsconfig.json");
195033
195165
  if (!await pathExists(tsconfigPath)) {
195034
195166
  return false;
195035
195167
  }
@@ -195358,7 +195490,7 @@ function createProgram(context) {
195358
195490
  program2.addCommand(getConnectorsCommand(context));
195359
195491
  program2.addCommand(getFunctionsDeployCommand(context));
195360
195492
  program2.addCommand(getSiteCommand(context));
195361
- program2.addCommand(getTypesCommand(context), { hidden: true });
195493
+ program2.addCommand(getTypesCommand(context));
195362
195494
  program2.addCommand(getDevCommand(context), { hidden: true });
195363
195495
  return program2;
195364
195496
  }
@@ -195398,7 +195530,7 @@ function nanoid3(size = 21) {
195398
195530
  }
195399
195531
 
195400
195532
  // node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
195401
- import { dirname as dirname10, posix, sep } from "path";
195533
+ import { dirname as dirname11, posix, sep } from "path";
195402
195534
  function createModulerModifier() {
195403
195535
  const getModuleFromFileName = createGetModuleFromFilename();
195404
195536
  return async (frames) => {
@@ -195407,7 +195539,7 @@ function createModulerModifier() {
195407
195539
  return frames;
195408
195540
  };
195409
195541
  }
195410
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname10(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
195542
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname11(process.argv[1]) : process.cwd(), isWindows4 = sep === "\\") {
195411
195543
  const normalizedBase = isWindows4 ? normalizeWindowsPath2(basePath) : basePath;
195412
195544
  return (filename) => {
195413
195545
  if (!filename)
@@ -199626,4 +199758,4 @@ export {
199626
199758
  CLIExitError
199627
199759
  };
199628
199760
 
199629
- //# debugId=6A2560FE978C00DF64756E2164756E21
199761
+ //# debugId=475C7FF08980E31A64756E2164756E21