@base44-preview/cli 0.0.16-pr.95.3b2ce0c → 0.0.17-pr.104.57e16fe
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/README.md +47 -156
- package/bin/dev.js +12 -0
- package/bin/run.js +12 -0
- package/dist/{cli/index.js → index.js} +942 -153
- package/package.json +7 -8
- /package/dist/{cli/templates → templates}/backend-and-client/.nvmrc +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/README.md +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/base44/app.jsonc.ejs +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/base44/config.jsonc.ejs +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/base44/entities/task.jsonc +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/components.json +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/index.html +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/jsconfig.json +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/package.json +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/postcss.config.js +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/App.jsx +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/api/base44Client.js.ejs +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/components/Base44Logo.jsx +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/components/ui/button.jsx +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/components/ui/checkbox.jsx +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/components/ui/input.jsx +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/index.css +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/src/main.jsx +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/tailwind.config.js +0 -0
- /package/dist/{cli/templates → templates}/backend-and-client/vite.config.js +0 -0
- /package/dist/{cli/templates → templates}/backend-only/base44/app.jsonc.ejs +0 -0
- /package/dist/{cli/templates → templates}/backend-only/base44/config.jsonc.ejs +0 -0
- /package/dist/{cli/templates → templates}/templates.json +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { createRequire } from "node:module";
|
|
3
2
|
import { EventEmitter, addAbortListener, on, once, setMaxListeners } from "node:events";
|
|
4
3
|
import childProcess, { ChildProcess, execFile, spawn, spawnSync } from "node:child_process";
|
|
5
4
|
import path, { basename, dirname, join, posix, resolve, win32 } from "node:path";
|
|
6
5
|
import fs, { appendFileSync, createReadStream, createWriteStream, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
7
|
-
import
|
|
6
|
+
import process$1, { execArgv, execPath, hrtime, platform, stdin, stdout } from "node:process";
|
|
8
7
|
import { aborted, callbackify, debuglog, inspect, promisify, stripVTControlCharacters } from "node:util";
|
|
9
8
|
import * as g from "node:readline";
|
|
10
9
|
import O from "node:readline";
|
|
@@ -894,7 +893,7 @@ var require_command = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
894
893
|
const childProcess$1 = __require("node:child_process");
|
|
895
894
|
const path$15 = __require("node:path");
|
|
896
895
|
const fs$10 = __require("node:fs");
|
|
897
|
-
const process$
|
|
896
|
+
const process$4 = __require("node:process");
|
|
898
897
|
const { Argument, humanReadableArgName } = require_argument();
|
|
899
898
|
const { CommanderError } = require_error$1();
|
|
900
899
|
const { Help } = require_help();
|
|
@@ -945,10 +944,10 @@ var require_command = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
945
944
|
this._showHelpAfterError = false;
|
|
946
945
|
this._showSuggestionAfterError = true;
|
|
947
946
|
this._outputConfiguration = {
|
|
948
|
-
writeOut: (str) => process$
|
|
949
|
-
writeErr: (str) => process$
|
|
950
|
-
getOutHelpWidth: () => process$
|
|
951
|
-
getErrHelpWidth: () => process$
|
|
947
|
+
writeOut: (str) => process$4.stdout.write(str),
|
|
948
|
+
writeErr: (str) => process$4.stderr.write(str),
|
|
949
|
+
getOutHelpWidth: () => process$4.stdout.isTTY ? process$4.stdout.columns : void 0,
|
|
950
|
+
getErrHelpWidth: () => process$4.stderr.isTTY ? process$4.stderr.columns : void 0,
|
|
952
951
|
outputError: (str, write) => write(str)
|
|
953
952
|
};
|
|
954
953
|
this._hidden = false;
|
|
@@ -1302,7 +1301,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1302
1301
|
*/
|
|
1303
1302
|
_exit(exitCode, code$1, message) {
|
|
1304
1303
|
if (this._exitCallback) this._exitCallback(new CommanderError(exitCode, code$1, message));
|
|
1305
|
-
process$
|
|
1304
|
+
process$4.exit(exitCode);
|
|
1306
1305
|
}
|
|
1307
1306
|
/**
|
|
1308
1307
|
* Register callback `fn` for the command.
|
|
@@ -1641,11 +1640,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1641
1640
|
if (argv !== void 0 && !Array.isArray(argv)) throw new Error("first parameter to parse must be array or undefined");
|
|
1642
1641
|
parseOptions = parseOptions || {};
|
|
1643
1642
|
if (argv === void 0 && parseOptions.from === void 0) {
|
|
1644
|
-
if (process$
|
|
1645
|
-
const execArgv$1 = process$
|
|
1643
|
+
if (process$4.versions?.electron) parseOptions.from = "electron";
|
|
1644
|
+
const execArgv$1 = process$4.execArgv ?? [];
|
|
1646
1645
|
if (execArgv$1.includes("-e") || execArgv$1.includes("--eval") || execArgv$1.includes("-p") || execArgv$1.includes("--print")) parseOptions.from = "eval";
|
|
1647
1646
|
}
|
|
1648
|
-
if (argv === void 0) argv = process$
|
|
1647
|
+
if (argv === void 0) argv = process$4.argv;
|
|
1649
1648
|
this.rawArgs = argv.slice();
|
|
1650
1649
|
let userArgs;
|
|
1651
1650
|
switch (parseOptions.from) {
|
|
@@ -1655,7 +1654,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1655
1654
|
userArgs = argv.slice(2);
|
|
1656
1655
|
break;
|
|
1657
1656
|
case "electron":
|
|
1658
|
-
if (process$
|
|
1657
|
+
if (process$4.defaultApp) {
|
|
1659
1658
|
this._scriptPath = argv[1];
|
|
1660
1659
|
userArgs = argv.slice(2);
|
|
1661
1660
|
} else userArgs = argv.slice(1);
|
|
@@ -1769,15 +1768,15 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1769
1768
|
}
|
|
1770
1769
|
launchWithNode = sourceExt.includes(path$15.extname(executableFile));
|
|
1771
1770
|
let proc$1;
|
|
1772
|
-
if (process$
|
|
1771
|
+
if (process$4.platform !== "win32") if (launchWithNode) {
|
|
1773
1772
|
args.unshift(executableFile);
|
|
1774
|
-
args = incrementNodeInspectorPort(process$
|
|
1775
|
-
proc$1 = childProcess$1.spawn(process$
|
|
1773
|
+
args = incrementNodeInspectorPort(process$4.execArgv).concat(args);
|
|
1774
|
+
proc$1 = childProcess$1.spawn(process$4.argv[0], args, { stdio: "inherit" });
|
|
1776
1775
|
} else proc$1 = childProcess$1.spawn(executableFile, args, { stdio: "inherit" });
|
|
1777
1776
|
else {
|
|
1778
1777
|
args.unshift(executableFile);
|
|
1779
|
-
args = incrementNodeInspectorPort(process$
|
|
1780
|
-
proc$1 = childProcess$1.spawn(process$
|
|
1778
|
+
args = incrementNodeInspectorPort(process$4.execArgv).concat(args);
|
|
1779
|
+
proc$1 = childProcess$1.spawn(process$4.execPath, args, { stdio: "inherit" });
|
|
1781
1780
|
}
|
|
1782
1781
|
if (!proc$1.killed) [
|
|
1783
1782
|
"SIGUSR1",
|
|
@@ -1786,14 +1785,14 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1786
1785
|
"SIGINT",
|
|
1787
1786
|
"SIGHUP"
|
|
1788
1787
|
].forEach((signal) => {
|
|
1789
|
-
process$
|
|
1788
|
+
process$4.on(signal, () => {
|
|
1790
1789
|
if (proc$1.killed === false && proc$1.exitCode === null) proc$1.kill(signal);
|
|
1791
1790
|
});
|
|
1792
1791
|
});
|
|
1793
1792
|
const exitCallback = this._exitCallback;
|
|
1794
1793
|
proc$1.on("close", (code$1) => {
|
|
1795
1794
|
code$1 = code$1 ?? 1;
|
|
1796
|
-
if (!exitCallback) process$
|
|
1795
|
+
if (!exitCallback) process$4.exit(code$1);
|
|
1797
1796
|
else exitCallback(new CommanderError(code$1, "commander.executeSubCommandAsync", "(close)"));
|
|
1798
1797
|
});
|
|
1799
1798
|
proc$1.on("error", (err) => {
|
|
@@ -1805,7 +1804,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1805
1804
|
- ${executableDirMessage}`;
|
|
1806
1805
|
throw new Error(executableMissing);
|
|
1807
1806
|
} else if (err.code === "EACCES") throw new Error(`'${executableFile}' not executable`);
|
|
1808
|
-
if (!exitCallback) process$
|
|
1807
|
+
if (!exitCallback) process$4.exit(1);
|
|
1809
1808
|
else {
|
|
1810
1809
|
const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
|
|
1811
1810
|
wrappedError.nestedError = err;
|
|
@@ -2211,13 +2210,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2211
2210
|
*/
|
|
2212
2211
|
_parseOptionsEnv() {
|
|
2213
2212
|
this.options.forEach((option) => {
|
|
2214
|
-
if (option.envVar && option.envVar in process$
|
|
2213
|
+
if (option.envVar && option.envVar in process$4.env) {
|
|
2215
2214
|
const optionKey = option.attributeName();
|
|
2216
2215
|
if (this.getOptionValue(optionKey) === void 0 || [
|
|
2217
2216
|
"default",
|
|
2218
2217
|
"config",
|
|
2219
2218
|
"env"
|
|
2220
|
-
].includes(this.getOptionValueSource(optionKey))) if (option.required || option.optional) this.emit(`optionEnv:${option.name()}`, process$
|
|
2219
|
+
].includes(this.getOptionValueSource(optionKey))) if (option.required || option.optional) this.emit(`optionEnv:${option.name()}`, process$4.env[option.envVar]);
|
|
2221
2220
|
else this.emit(`optionEnv:${option.name()}`);
|
|
2222
2221
|
}
|
|
2223
2222
|
});
|
|
@@ -2596,7 +2595,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2596
2595
|
*/
|
|
2597
2596
|
help(contextOptions) {
|
|
2598
2597
|
this.outputHelp(contextOptions);
|
|
2599
|
-
let exitCode = process$
|
|
2598
|
+
let exitCode = process$4.exitCode || 0;
|
|
2600
2599
|
if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) exitCode = 1;
|
|
2601
2600
|
this._exit(exitCode, "commander.help", "(outputHelp)");
|
|
2602
2601
|
}
|
|
@@ -2712,16 +2711,16 @@ var require_src = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2712
2711
|
const CSI = `${ESC}[`;
|
|
2713
2712
|
const beep = "\x07";
|
|
2714
2713
|
const cursor = {
|
|
2715
|
-
to(x$2, y$
|
|
2716
|
-
if (!y$
|
|
2717
|
-
return `${CSI}${y$
|
|
2714
|
+
to(x$2, y$1) {
|
|
2715
|
+
if (!y$1) return `${CSI}${x$2 + 1}G`;
|
|
2716
|
+
return `${CSI}${y$1 + 1};${x$2 + 1}H`;
|
|
2718
2717
|
},
|
|
2719
|
-
move(x$2, y$
|
|
2718
|
+
move(x$2, y$1) {
|
|
2720
2719
|
let ret = "";
|
|
2721
2720
|
if (x$2 < 0) ret += `${CSI}${-x$2}D`;
|
|
2722
2721
|
else if (x$2 > 0) ret += `${CSI}${x$2}C`;
|
|
2723
|
-
if (y$
|
|
2724
|
-
else if (y$
|
|
2722
|
+
if (y$1 < 0) ret += `${CSI}${-y$1}A`;
|
|
2723
|
+
else if (y$1 > 0) ret += `${CSI}${y$1}B`;
|
|
2725
2724
|
return ret;
|
|
2726
2725
|
},
|
|
2727
2726
|
up: (count$1 = 1) => `${CSI}${count$1}A`,
|
|
@@ -3031,13 +3030,13 @@ function rD() {
|
|
|
3031
3030
|
}
|
|
3032
3031
|
}), r;
|
|
3033
3032
|
}
|
|
3034
|
-
const ED = rD(), d$1 = new Set(["\x1B", ""]), oD = 39, y
|
|
3033
|
+
const ED = rD(), d$1 = new Set(["\x1B", ""]), oD = 39, y = "\x07", V$1 = "[", nD = "]", G$1 = "m", _$1 = `${nD}8;;`, z = (e$1) => `${d$1.values().next().value}${V$1}${e$1}${G$1}`, K$1 = (e$1) => `${d$1.values().next().value}${_$1}${e$1}${y}`, aD = (e$1) => e$1.split(" ").map((u$2) => p(u$2)), k$1 = (e$1, u$2, t) => {
|
|
3035
3034
|
const F$1 = [...u$2];
|
|
3036
3035
|
let s = !1, i$1 = !1, D$1 = p(P$1(e$1[e$1.length - 1]));
|
|
3037
3036
|
for (const [C$1, n$1] of F$1.entries()) {
|
|
3038
3037
|
const E = p(n$1);
|
|
3039
3038
|
if (D$1 + E <= t ? e$1[e$1.length - 1] += n$1 : (e$1.push(n$1), D$1 = 0), d$1.has(n$1) && (s = !0, i$1 = F$1.slice(C$1 + 1).join("").startsWith(_$1)), s) {
|
|
3040
|
-
i$1 ? n$1 === y
|
|
3039
|
+
i$1 ? n$1 === y && (s = !1, i$1 = !1) : n$1 === G$1 && (s = !1);
|
|
3041
3040
|
continue;
|
|
3042
3041
|
}
|
|
3043
3042
|
D$1 += E, D$1 === t && C$1 < F$1.length - 1 && (e$1.push(""), D$1 = 0);
|
|
@@ -3079,7 +3078,7 @@ const ED = rD(), d$1 = new Set(["\x1B", ""]), oD = 39, y$1 = "\x07", V$1 = "["
|
|
|
3079
3078
|
`)];
|
|
3080
3079
|
for (const [E, a$1] of n$1.entries()) {
|
|
3081
3080
|
if (F$1 += a$1, d$1.has(a$1)) {
|
|
3082
|
-
const { groups: c$1 } = (/* @__PURE__ */ new RegExp(`(?:\\${V$1}(?<code>\\d+)m|\\${_$1}(?<uri>.*)${y
|
|
3081
|
+
const { groups: c$1 } = (/* @__PURE__ */ new RegExp(`(?:\\${V$1}(?<code>\\d+)m|\\${_$1}(?<uri>.*)${y})`)).exec(n$1.slice(E).join("")) || { groups: {} };
|
|
3083
3082
|
if (c$1.code !== void 0) {
|
|
3084
3083
|
const f = Number.parseFloat(c$1.code);
|
|
3085
3084
|
s = f === oD ? void 0 : f;
|
|
@@ -3480,7 +3479,7 @@ var RD = class extends x$1 {
|
|
|
3480
3479
|
//#endregion
|
|
3481
3480
|
//#region node_modules/@clack/prompts/dist/index.mjs
|
|
3482
3481
|
function ce() {
|
|
3483
|
-
return
|
|
3482
|
+
return process$1.platform !== "win32" ? process$1.env.TERM !== "linux" : !!process$1.env.CI || !!process$1.env.WT_SESSION || !!process$1.env.TERMINUS_SUBLIME || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
3484
3483
|
}
|
|
3485
3484
|
const V = ce(), u$1 = (t, n$1) => V ? t : n$1, le = u$1("◆", "*"), L = u$1("■", "x"), W = u$1("▲", "x"), C = u$1("◇", "o"), ue = u$1("┌", "T"), o$1 = u$1("│", "|"), d = u$1("└", "—"), k = u$1("●", ">"), P = u$1("○", " "), A = u$1("◻", "[•]"), T = u$1("◼", "[+]"), F = u$1("◻", "[ ]"), $e = u$1("▪", "•"), _ = u$1("─", "-"), me = u$1("╮", "+"), de = u$1("├", "+"), pe = u$1("╯", "+"), q = u$1("●", "•"), D = u$1("◆", "*"), U = u$1("▲", "!"), K = u$1("■", "x"), b = (t) => {
|
|
3486
3485
|
switch (t) {
|
|
@@ -5819,6 +5818,97 @@ function handleTupleResult(result, final, index) {
|
|
|
5819
5818
|
if (result.issues.length) final.issues.push(...prefixIssues(index, result.issues));
|
|
5820
5819
|
final.value[index] = result.value;
|
|
5821
5820
|
}
|
|
5821
|
+
const $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
5822
|
+
$ZodType.init(inst, def);
|
|
5823
|
+
inst._zod.parse = (payload, ctx) => {
|
|
5824
|
+
const input = payload.value;
|
|
5825
|
+
if (!isPlainObject$1(input)) {
|
|
5826
|
+
payload.issues.push({
|
|
5827
|
+
expected: "record",
|
|
5828
|
+
code: "invalid_type",
|
|
5829
|
+
input,
|
|
5830
|
+
inst
|
|
5831
|
+
});
|
|
5832
|
+
return payload;
|
|
5833
|
+
}
|
|
5834
|
+
const proms = [];
|
|
5835
|
+
const values = def.keyType._zod.values;
|
|
5836
|
+
if (values) {
|
|
5837
|
+
payload.value = {};
|
|
5838
|
+
const recordKeys = /* @__PURE__ */ new Set();
|
|
5839
|
+
for (const key of values) if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
5840
|
+
recordKeys.add(typeof key === "number" ? key.toString() : key);
|
|
5841
|
+
const result = def.valueType._zod.run({
|
|
5842
|
+
value: input[key],
|
|
5843
|
+
issues: []
|
|
5844
|
+
}, ctx);
|
|
5845
|
+
if (result instanceof Promise) proms.push(result.then((result$1) => {
|
|
5846
|
+
if (result$1.issues.length) payload.issues.push(...prefixIssues(key, result$1.issues));
|
|
5847
|
+
payload.value[key] = result$1.value;
|
|
5848
|
+
}));
|
|
5849
|
+
else {
|
|
5850
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
5851
|
+
payload.value[key] = result.value;
|
|
5852
|
+
}
|
|
5853
|
+
}
|
|
5854
|
+
let unrecognized;
|
|
5855
|
+
for (const key in input) if (!recordKeys.has(key)) {
|
|
5856
|
+
unrecognized = unrecognized ?? [];
|
|
5857
|
+
unrecognized.push(key);
|
|
5858
|
+
}
|
|
5859
|
+
if (unrecognized && unrecognized.length > 0) payload.issues.push({
|
|
5860
|
+
code: "unrecognized_keys",
|
|
5861
|
+
input,
|
|
5862
|
+
inst,
|
|
5863
|
+
keys: unrecognized
|
|
5864
|
+
});
|
|
5865
|
+
} else {
|
|
5866
|
+
payload.value = {};
|
|
5867
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
5868
|
+
if (key === "__proto__") continue;
|
|
5869
|
+
let keyResult = def.keyType._zod.run({
|
|
5870
|
+
value: key,
|
|
5871
|
+
issues: []
|
|
5872
|
+
}, ctx);
|
|
5873
|
+
if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
5874
|
+
if (typeof key === "string" && number$1.test(key) && keyResult.issues.length && keyResult.issues.some((iss) => iss.code === "invalid_type" && iss.expected === "number")) {
|
|
5875
|
+
const retryResult = def.keyType._zod.run({
|
|
5876
|
+
value: Number(key),
|
|
5877
|
+
issues: []
|
|
5878
|
+
}, ctx);
|
|
5879
|
+
if (retryResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
5880
|
+
if (retryResult.issues.length === 0) keyResult = retryResult;
|
|
5881
|
+
}
|
|
5882
|
+
if (keyResult.issues.length) {
|
|
5883
|
+
if (def.mode === "loose") payload.value[key] = input[key];
|
|
5884
|
+
else payload.issues.push({
|
|
5885
|
+
code: "invalid_key",
|
|
5886
|
+
origin: "record",
|
|
5887
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
5888
|
+
input: key,
|
|
5889
|
+
path: [key],
|
|
5890
|
+
inst
|
|
5891
|
+
});
|
|
5892
|
+
continue;
|
|
5893
|
+
}
|
|
5894
|
+
const result = def.valueType._zod.run({
|
|
5895
|
+
value: input[key],
|
|
5896
|
+
issues: []
|
|
5897
|
+
}, ctx);
|
|
5898
|
+
if (result instanceof Promise) proms.push(result.then((result$1) => {
|
|
5899
|
+
if (result$1.issues.length) payload.issues.push(...prefixIssues(key, result$1.issues));
|
|
5900
|
+
payload.value[keyResult.value] = result$1.value;
|
|
5901
|
+
}));
|
|
5902
|
+
else {
|
|
5903
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
5904
|
+
payload.value[keyResult.value] = result.value;
|
|
5905
|
+
}
|
|
5906
|
+
}
|
|
5907
|
+
}
|
|
5908
|
+
if (proms.length) return Promise.all(proms).then(() => payload);
|
|
5909
|
+
return payload;
|
|
5910
|
+
};
|
|
5911
|
+
});
|
|
5822
5912
|
const $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
5823
5913
|
$ZodType.init(inst, def);
|
|
5824
5914
|
const values = getEnumValues(def.entries);
|
|
@@ -6654,7 +6744,7 @@ function initializeContext(params) {
|
|
|
6654
6744
|
external: params?.external ?? void 0
|
|
6655
6745
|
};
|
|
6656
6746
|
}
|
|
6657
|
-
function process$
|
|
6747
|
+
function process$3(schema, ctx, _params = {
|
|
6658
6748
|
path: [],
|
|
6659
6749
|
schemaPath: []
|
|
6660
6750
|
}) {
|
|
@@ -6691,7 +6781,7 @@ function process$2(schema, ctx, _params = {
|
|
|
6691
6781
|
const parent = schema._zod.parent;
|
|
6692
6782
|
if (parent) {
|
|
6693
6783
|
if (!result.ref) result.ref = parent;
|
|
6694
|
-
process$
|
|
6784
|
+
process$3(parent, ctx, params);
|
|
6695
6785
|
ctx.seen.get(parent).isParent = true;
|
|
6696
6786
|
}
|
|
6697
6787
|
}
|
|
@@ -6903,7 +6993,7 @@ const createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
|
|
6903
6993
|
...params,
|
|
6904
6994
|
processors
|
|
6905
6995
|
});
|
|
6906
|
-
process$
|
|
6996
|
+
process$3(schema, ctx);
|
|
6907
6997
|
extractDefs(ctx, schema);
|
|
6908
6998
|
return finalize(ctx, schema);
|
|
6909
6999
|
};
|
|
@@ -6915,7 +7005,7 @@ const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params)
|
|
|
6915
7005
|
io,
|
|
6916
7006
|
processors
|
|
6917
7007
|
});
|
|
6918
|
-
process$
|
|
7008
|
+
process$3(schema, ctx);
|
|
6919
7009
|
extractDefs(ctx, schema);
|
|
6920
7010
|
return finalize(ctx, schema);
|
|
6921
7011
|
};
|
|
@@ -7002,7 +7092,7 @@ const arrayProcessor = (schema, ctx, _json, params) => {
|
|
|
7002
7092
|
if (typeof minimum === "number") json.minItems = minimum;
|
|
7003
7093
|
if (typeof maximum === "number") json.maxItems = maximum;
|
|
7004
7094
|
json.type = "array";
|
|
7005
|
-
json.items = process$
|
|
7095
|
+
json.items = process$3(def.element, ctx, {
|
|
7006
7096
|
...params,
|
|
7007
7097
|
path: [...params.path, "items"]
|
|
7008
7098
|
});
|
|
@@ -7013,7 +7103,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
7013
7103
|
json.type = "object";
|
|
7014
7104
|
json.properties = {};
|
|
7015
7105
|
const shape = def.shape;
|
|
7016
|
-
for (const key in shape) json.properties[key] = process$
|
|
7106
|
+
for (const key in shape) json.properties[key] = process$3(shape[key], ctx, {
|
|
7017
7107
|
...params,
|
|
7018
7108
|
path: [
|
|
7019
7109
|
...params.path,
|
|
@@ -7031,7 +7121,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
7031
7121
|
if (def.catchall?._zod.def.type === "never") json.additionalProperties = false;
|
|
7032
7122
|
else if (!def.catchall) {
|
|
7033
7123
|
if (ctx.io === "output") json.additionalProperties = false;
|
|
7034
|
-
} else if (def.catchall) json.additionalProperties = process$
|
|
7124
|
+
} else if (def.catchall) json.additionalProperties = process$3(def.catchall, ctx, {
|
|
7035
7125
|
...params,
|
|
7036
7126
|
path: [...params.path, "additionalProperties"]
|
|
7037
7127
|
});
|
|
@@ -7039,7 +7129,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
7039
7129
|
const unionProcessor = (schema, ctx, json, params) => {
|
|
7040
7130
|
const def = schema._zod.def;
|
|
7041
7131
|
const isExclusive = def.inclusive === false;
|
|
7042
|
-
const options = def.options.map((x$2, i$1) => process$
|
|
7132
|
+
const options = def.options.map((x$2, i$1) => process$3(x$2, ctx, {
|
|
7043
7133
|
...params,
|
|
7044
7134
|
path: [
|
|
7045
7135
|
...params.path,
|
|
@@ -7052,7 +7142,7 @@ const unionProcessor = (schema, ctx, json, params) => {
|
|
|
7052
7142
|
};
|
|
7053
7143
|
const intersectionProcessor = (schema, ctx, json, params) => {
|
|
7054
7144
|
const def = schema._zod.def;
|
|
7055
|
-
const a$1 = process$
|
|
7145
|
+
const a$1 = process$3(def.left, ctx, {
|
|
7056
7146
|
...params,
|
|
7057
7147
|
path: [
|
|
7058
7148
|
...params.path,
|
|
@@ -7060,7 +7150,7 @@ const intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
7060
7150
|
0
|
|
7061
7151
|
]
|
|
7062
7152
|
});
|
|
7063
|
-
const b$2 = process$
|
|
7153
|
+
const b$2 = process$3(def.right, ctx, {
|
|
7064
7154
|
...params,
|
|
7065
7155
|
path: [
|
|
7066
7156
|
...params.path,
|
|
@@ -7077,7 +7167,7 @@ const tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
7077
7167
|
json.type = "array";
|
|
7078
7168
|
const prefixPath$1 = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
|
|
7079
7169
|
const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
|
|
7080
|
-
const prefixItems = def.items.map((x$2, i$1) => process$
|
|
7170
|
+
const prefixItems = def.items.map((x$2, i$1) => process$3(x$2, ctx, {
|
|
7081
7171
|
...params,
|
|
7082
7172
|
path: [
|
|
7083
7173
|
...params.path,
|
|
@@ -7085,7 +7175,7 @@ const tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
7085
7175
|
i$1
|
|
7086
7176
|
]
|
|
7087
7177
|
}));
|
|
7088
|
-
const rest = def.rest ? process$
|
|
7178
|
+
const rest = def.rest ? process$3(def.rest, ctx, {
|
|
7089
7179
|
...params,
|
|
7090
7180
|
path: [
|
|
7091
7181
|
...params.path,
|
|
@@ -7109,9 +7199,42 @@ const tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
7109
7199
|
if (typeof minimum === "number") json.minItems = minimum;
|
|
7110
7200
|
if (typeof maximum === "number") json.maxItems = maximum;
|
|
7111
7201
|
};
|
|
7202
|
+
const recordProcessor = (schema, ctx, _json, params) => {
|
|
7203
|
+
const json = _json;
|
|
7204
|
+
const def = schema._zod.def;
|
|
7205
|
+
json.type = "object";
|
|
7206
|
+
const keyType = def.keyType;
|
|
7207
|
+
const patterns = keyType._zod.bag?.patterns;
|
|
7208
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
7209
|
+
const valueSchema = process$3(def.valueType, ctx, {
|
|
7210
|
+
...params,
|
|
7211
|
+
path: [
|
|
7212
|
+
...params.path,
|
|
7213
|
+
"patternProperties",
|
|
7214
|
+
"*"
|
|
7215
|
+
]
|
|
7216
|
+
});
|
|
7217
|
+
json.patternProperties = {};
|
|
7218
|
+
for (const pattern of patterns) json.patternProperties[pattern.source] = valueSchema;
|
|
7219
|
+
} else {
|
|
7220
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") json.propertyNames = process$3(def.keyType, ctx, {
|
|
7221
|
+
...params,
|
|
7222
|
+
path: [...params.path, "propertyNames"]
|
|
7223
|
+
});
|
|
7224
|
+
json.additionalProperties = process$3(def.valueType, ctx, {
|
|
7225
|
+
...params,
|
|
7226
|
+
path: [...params.path, "additionalProperties"]
|
|
7227
|
+
});
|
|
7228
|
+
}
|
|
7229
|
+
const keyValues = keyType._zod.values;
|
|
7230
|
+
if (keyValues) {
|
|
7231
|
+
const validKeyValues = [...keyValues].filter((v$1) => typeof v$1 === "string" || typeof v$1 === "number");
|
|
7232
|
+
if (validKeyValues.length > 0) json.required = validKeyValues;
|
|
7233
|
+
}
|
|
7234
|
+
};
|
|
7112
7235
|
const nullableProcessor = (schema, ctx, json, params) => {
|
|
7113
7236
|
const def = schema._zod.def;
|
|
7114
|
-
const inner = process$
|
|
7237
|
+
const inner = process$3(def.innerType, ctx, params);
|
|
7115
7238
|
const seen = ctx.seen.get(schema);
|
|
7116
7239
|
if (ctx.target === "openapi-3.0") {
|
|
7117
7240
|
seen.ref = def.innerType;
|
|
@@ -7120,27 +7243,27 @@ const nullableProcessor = (schema, ctx, json, params) => {
|
|
|
7120
7243
|
};
|
|
7121
7244
|
const nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
7122
7245
|
const def = schema._zod.def;
|
|
7123
|
-
process$
|
|
7246
|
+
process$3(def.innerType, ctx, params);
|
|
7124
7247
|
const seen = ctx.seen.get(schema);
|
|
7125
7248
|
seen.ref = def.innerType;
|
|
7126
7249
|
};
|
|
7127
7250
|
const defaultProcessor = (schema, ctx, json, params) => {
|
|
7128
7251
|
const def = schema._zod.def;
|
|
7129
|
-
process$
|
|
7252
|
+
process$3(def.innerType, ctx, params);
|
|
7130
7253
|
const seen = ctx.seen.get(schema);
|
|
7131
7254
|
seen.ref = def.innerType;
|
|
7132
7255
|
json.default = JSON.parse(JSON.stringify(def.defaultValue));
|
|
7133
7256
|
};
|
|
7134
7257
|
const prefaultProcessor = (schema, ctx, json, params) => {
|
|
7135
7258
|
const def = schema._zod.def;
|
|
7136
|
-
process$
|
|
7259
|
+
process$3(def.innerType, ctx, params);
|
|
7137
7260
|
const seen = ctx.seen.get(schema);
|
|
7138
7261
|
seen.ref = def.innerType;
|
|
7139
7262
|
if (ctx.io === "input") json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
|
|
7140
7263
|
};
|
|
7141
7264
|
const catchProcessor = (schema, ctx, json, params) => {
|
|
7142
7265
|
const def = schema._zod.def;
|
|
7143
|
-
process$
|
|
7266
|
+
process$3(def.innerType, ctx, params);
|
|
7144
7267
|
const seen = ctx.seen.get(schema);
|
|
7145
7268
|
seen.ref = def.innerType;
|
|
7146
7269
|
let catchValue;
|
|
@@ -7154,20 +7277,20 @@ const catchProcessor = (schema, ctx, json, params) => {
|
|
|
7154
7277
|
const pipeProcessor = (schema, ctx, _json, params) => {
|
|
7155
7278
|
const def = schema._zod.def;
|
|
7156
7279
|
const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
|
|
7157
|
-
process$
|
|
7280
|
+
process$3(innerType, ctx, params);
|
|
7158
7281
|
const seen = ctx.seen.get(schema);
|
|
7159
7282
|
seen.ref = innerType;
|
|
7160
7283
|
};
|
|
7161
7284
|
const readonlyProcessor = (schema, ctx, json, params) => {
|
|
7162
7285
|
const def = schema._zod.def;
|
|
7163
|
-
process$
|
|
7286
|
+
process$3(def.innerType, ctx, params);
|
|
7164
7287
|
const seen = ctx.seen.get(schema);
|
|
7165
7288
|
seen.ref = def.innerType;
|
|
7166
7289
|
json.readOnly = true;
|
|
7167
7290
|
};
|
|
7168
7291
|
const optionalProcessor = (schema, ctx, _json, params) => {
|
|
7169
7292
|
const def = schema._zod.def;
|
|
7170
|
-
process$
|
|
7293
|
+
process$3(def.innerType, ctx, params);
|
|
7171
7294
|
const seen = ctx.seen.get(schema);
|
|
7172
7295
|
seen.ref = def.innerType;
|
|
7173
7296
|
};
|
|
@@ -7638,6 +7761,21 @@ function tuple(items, _paramsOrRest, _params) {
|
|
|
7638
7761
|
...normalizeParams(params)
|
|
7639
7762
|
});
|
|
7640
7763
|
}
|
|
7764
|
+
const ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
7765
|
+
$ZodRecord.init(inst, def);
|
|
7766
|
+
ZodType.init(inst, def);
|
|
7767
|
+
inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
|
|
7768
|
+
inst.keyType = def.keyType;
|
|
7769
|
+
inst.valueType = def.valueType;
|
|
7770
|
+
});
|
|
7771
|
+
function record(keyType, valueType, params) {
|
|
7772
|
+
return new ZodRecord({
|
|
7773
|
+
type: "record",
|
|
7774
|
+
keyType,
|
|
7775
|
+
valueType,
|
|
7776
|
+
...normalizeParams(params)
|
|
7777
|
+
});
|
|
7778
|
+
}
|
|
7641
7779
|
const ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
7642
7780
|
$ZodEnum.init(inst, def);
|
|
7643
7781
|
ZodType.init(inst, def);
|
|
@@ -7900,6 +8038,19 @@ var AuthValidationError = class extends Error {
|
|
|
7900
8038
|
this.name = "AuthValidationError";
|
|
7901
8039
|
}
|
|
7902
8040
|
};
|
|
8041
|
+
var ConnectorApiError = class extends Error {
|
|
8042
|
+
constructor(message, cause) {
|
|
8043
|
+
super(message);
|
|
8044
|
+
this.cause = cause;
|
|
8045
|
+
this.name = "ConnectorApiError";
|
|
8046
|
+
}
|
|
8047
|
+
};
|
|
8048
|
+
var ConnectorValidationError = class extends Error {
|
|
8049
|
+
constructor(message) {
|
|
8050
|
+
super(message);
|
|
8051
|
+
this.name = "ConnectorValidationError";
|
|
8052
|
+
}
|
|
8053
|
+
};
|
|
7903
8054
|
|
|
7904
8055
|
//#endregion
|
|
7905
8056
|
//#region src/core/consts.ts
|
|
@@ -16193,7 +16344,7 @@ const createIgnorePredicate = (patterns, cwd, baseDir) => {
|
|
|
16193
16344
|
};
|
|
16194
16345
|
const normalizeOptions$2 = (options = {}) => {
|
|
16195
16346
|
const ignoreOption = options.ignore ? Array.isArray(options.ignore) ? options.ignore : [options.ignore] : [];
|
|
16196
|
-
const cwd = toPath$1(options.cwd) ??
|
|
16347
|
+
const cwd = toPath$1(options.cwd) ?? process$1.cwd();
|
|
16197
16348
|
const deep = typeof options.deep === "number" ? Math.max(0, options.deep) + 1 : Number.POSITIVE_INFINITY;
|
|
16198
16349
|
return {
|
|
16199
16350
|
cwd,
|
|
@@ -16290,7 +16441,7 @@ const getDirectoryGlob = ({ directoryPath, files, extensions }) => {
|
|
|
16290
16441
|
const extensionGlob = extensions?.length > 0 ? `.${extensions.length > 1 ? `{${extensions.join(",")}}` : extensions[0]}` : "";
|
|
16291
16442
|
return files ? files.map((file) => path.posix.join(directoryPath, `**/${path.extname(file) ? file : `${file}${extensionGlob}`}`)) : [path.posix.join(directoryPath, `**${extensionGlob ? `/*${extensionGlob}` : ""}`)];
|
|
16292
16443
|
};
|
|
16293
|
-
const directoryToGlob = async (directoryPaths, { cwd =
|
|
16444
|
+
const directoryToGlob = async (directoryPaths, { cwd = process$1.cwd(), files, extensions, fs: fsImplementation } = {}) => {
|
|
16294
16445
|
return (await Promise.all(directoryPaths.map(async (directoryPath) => {
|
|
16295
16446
|
if (shouldExpandGlobstarDirectory(isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath)) return getDirectoryGlob({
|
|
16296
16447
|
directoryPath,
|
|
@@ -16304,7 +16455,7 @@ const directoryToGlob = async (directoryPaths, { cwd = y.cwd(), files, extension
|
|
|
16304
16455
|
}) : directoryPath;
|
|
16305
16456
|
}))).flat();
|
|
16306
16457
|
};
|
|
16307
|
-
const directoryToGlobSync = (directoryPaths, { cwd =
|
|
16458
|
+
const directoryToGlobSync = (directoryPaths, { cwd = process$1.cwd(), files, extensions, fs: fsImplementation } = {}) => directoryPaths.flatMap((directoryPath) => {
|
|
16308
16459
|
if (shouldExpandGlobstarDirectory(isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath)) return getDirectoryGlob({
|
|
16309
16460
|
directoryPath,
|
|
16310
16461
|
files,
|
|
@@ -16400,7 +16551,7 @@ const applyIgnoreFilesAndGetFilterSync = (options) => {
|
|
|
16400
16551
|
};
|
|
16401
16552
|
const createFilterFunction = (isIgnored, cwd) => {
|
|
16402
16553
|
const seen = /* @__PURE__ */ new Set();
|
|
16403
|
-
const basePath = cwd ||
|
|
16554
|
+
const basePath = cwd || process$1.cwd();
|
|
16404
16555
|
const pathCache = /* @__PURE__ */ new Map();
|
|
16405
16556
|
return (fastGlobResult) => {
|
|
16406
16557
|
const pathKey$1 = path.normalize(fastGlobResult.path ?? fastGlobResult);
|
|
@@ -16697,10 +16848,13 @@ const SiteConfigSchema = object({
|
|
|
16697
16848
|
outputDirectory: string().optional(),
|
|
16698
16849
|
installCommand: string().optional()
|
|
16699
16850
|
});
|
|
16851
|
+
const ConnectorConfigSchema = object({ scopes: array(string()).optional() });
|
|
16852
|
+
const ConnectorsConfigSchema = record(string(), ConnectorConfigSchema);
|
|
16700
16853
|
const ProjectConfigSchema = object({
|
|
16701
16854
|
name: string().min(1, "App name cannot be empty"),
|
|
16702
16855
|
description: string().optional(),
|
|
16703
16856
|
site: SiteConfigSchema.optional(),
|
|
16857
|
+
connectors: ConnectorsConfigSchema.optional(),
|
|
16704
16858
|
entitiesDir: string().optional().default("entities"),
|
|
16705
16859
|
functionsDir: string().optional().default("functions")
|
|
16706
16860
|
});
|
|
@@ -16798,7 +16952,10 @@ async function createProject(projectName, description) {
|
|
|
16798
16952
|
return { projectId: CreateProjectResponseSchema.parse(await response.json()).id };
|
|
16799
16953
|
}
|
|
16800
16954
|
async function listProjects() {
|
|
16801
|
-
const response = await base44Client.get(`api/apps
|
|
16955
|
+
const response = await base44Client.get(`api/apps`, { searchParams: {
|
|
16956
|
+
"sort": "-updated_date",
|
|
16957
|
+
"fields": "id,name,user_description,is_managed_source_code"
|
|
16958
|
+
} });
|
|
16802
16959
|
return ProjectsResponseSchema.parse(await response.json());
|
|
16803
16960
|
}
|
|
16804
16961
|
|
|
@@ -30583,6 +30740,21 @@ async function getUserInfo(accessToken) {
|
|
|
30583
30740
|
return result.data;
|
|
30584
30741
|
}
|
|
30585
30742
|
|
|
30743
|
+
//#endregion
|
|
30744
|
+
//#region src/cli/errors.ts
|
|
30745
|
+
/**
|
|
30746
|
+
* Error thrown to signal a controlled CLI exit with a specific exit code.
|
|
30747
|
+
* This allows proper error propagation without calling process.exit() directly,
|
|
30748
|
+
* making the code more testable and maintaining a single exit point.
|
|
30749
|
+
*/
|
|
30750
|
+
var CLIExitError = class extends Error {
|
|
30751
|
+
constructor(code$1) {
|
|
30752
|
+
super(`CLI exited with code ${code$1}`);
|
|
30753
|
+
this.code = code$1;
|
|
30754
|
+
this.name = "CLIExitError";
|
|
30755
|
+
}
|
|
30756
|
+
};
|
|
30757
|
+
|
|
30586
30758
|
//#endregion
|
|
30587
30759
|
//#region node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
30588
30760
|
const ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -30751,13 +30923,13 @@ var ansi_styles_default = ansiStyles;
|
|
|
30751
30923
|
|
|
30752
30924
|
//#endregion
|
|
30753
30925
|
//#region node_modules/chalk/source/vendor/supports-color/index.js
|
|
30754
|
-
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args :
|
|
30926
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process$1.argv) {
|
|
30755
30927
|
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
30756
30928
|
const position = argv.indexOf(prefix + flag);
|
|
30757
30929
|
const terminatorPosition = argv.indexOf("--");
|
|
30758
30930
|
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
30759
30931
|
}
|
|
30760
|
-
const { env } =
|
|
30932
|
+
const { env } = process$1;
|
|
30761
30933
|
let flagForceColor;
|
|
30762
30934
|
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) flagForceColor = 0;
|
|
30763
30935
|
else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) flagForceColor = 1;
|
|
@@ -30790,7 +30962,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
30790
30962
|
if (haveStream && !streamIsTTY && forceColor === void 0) return 0;
|
|
30791
30963
|
const min = forceColor || 0;
|
|
30792
30964
|
if (env.TERM === "dumb") return min;
|
|
30793
|
-
if (
|
|
30965
|
+
if (process$1.platform === "win32") {
|
|
30794
30966
|
const osRelease = os.release().split(".");
|
|
30795
30967
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
30796
30968
|
return 1;
|
|
@@ -31003,7 +31175,10 @@ const theme = {
|
|
|
31003
31175
|
base44OrangeBackground: source_default.bgHex("#E86B3C"),
|
|
31004
31176
|
shinyOrange: source_default.hex("#FFD700"),
|
|
31005
31177
|
links: source_default.hex("#00D4FF"),
|
|
31006
|
-
white: source_default.white
|
|
31178
|
+
white: source_default.white,
|
|
31179
|
+
success: source_default.green,
|
|
31180
|
+
warning: source_default.yellow,
|
|
31181
|
+
error: source_default.red
|
|
31007
31182
|
},
|
|
31008
31183
|
styles: {
|
|
31009
31184
|
header: source_default.dim,
|
|
@@ -31149,7 +31324,7 @@ async function runCommand(commandFn, options) {
|
|
|
31149
31324
|
} catch (e$1) {
|
|
31150
31325
|
if (e$1 instanceof Error) M.error(e$1.stack ?? e$1.message);
|
|
31151
31326
|
else M.error(String(e$1));
|
|
31152
|
-
|
|
31327
|
+
throw new CLIExitError(1);
|
|
31153
31328
|
}
|
|
31154
31329
|
}
|
|
31155
31330
|
|
|
@@ -31529,9 +31704,9 @@ const getSubprocessResult = ({ stdout: stdout$1 }) => {
|
|
|
31529
31704
|
//#region node_modules/execa/lib/utils/standard-stream.js
|
|
31530
31705
|
const isStandardStream = (stream) => STANDARD_STREAMS.includes(stream);
|
|
31531
31706
|
const STANDARD_STREAMS = [
|
|
31532
|
-
|
|
31533
|
-
|
|
31534
|
-
|
|
31707
|
+
process$1.stdin,
|
|
31708
|
+
process$1.stdout,
|
|
31709
|
+
process$1.stderr
|
|
31535
31710
|
];
|
|
31536
31711
|
const STANDARD_STREAMS_ALIASES = [
|
|
31537
31712
|
"stdin",
|
|
@@ -31656,9 +31831,9 @@ const NO_ESCAPE_REGEXP = /^[\w./-]+$/;
|
|
|
31656
31831
|
//#endregion
|
|
31657
31832
|
//#region node_modules/is-unicode-supported/index.js
|
|
31658
31833
|
function isUnicodeSupported() {
|
|
31659
|
-
const { env: env$1 } =
|
|
31834
|
+
const { env: env$1 } = process$1;
|
|
31660
31835
|
const { TERM, TERM_PROGRAM } = env$1;
|
|
31661
|
-
if (
|
|
31836
|
+
if (process$1.platform !== "win32") return TERM !== "linux";
|
|
31662
31837
|
return Boolean(env$1.WT_SESSION) || Boolean(env$1.TERMINUS_SUBLIME) || env$1.ConEmuTask === "{cmd::Cmder}" || TERM_PROGRAM === "Terminus-Sublime" || TERM_PROGRAM === "vscode" || TERM === "xterm-256color" || TERM === "alacritty" || TERM === "rxvt-unicode" || TERM === "rxvt-unicode-256color" || env$1.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
31663
31838
|
}
|
|
31664
31839
|
|
|
@@ -32585,7 +32760,7 @@ const TEN_MEGABYTES_IN_BYTES = 10 * 1024 * 1024;
|
|
|
32585
32760
|
|
|
32586
32761
|
//#endregion
|
|
32587
32762
|
//#region node_modules/npm-run-path/index.js
|
|
32588
|
-
const npmRunPath = ({ cwd =
|
|
32763
|
+
const npmRunPath = ({ cwd = process$1.cwd(), path: pathOption = process$1.env[pathKey()], preferLocal = true, execPath: execPath$1 = process$1.execPath, addExecPath = true } = {}) => {
|
|
32589
32764
|
const cwdPath = path.resolve(toPath(cwd));
|
|
32590
32765
|
const result = [];
|
|
32591
32766
|
const pathParts = pathOption.split(path.delimiter);
|
|
@@ -32603,7 +32778,7 @@ const applyExecPath = (result, pathParts, execPath$1, cwdPath) => {
|
|
|
32603
32778
|
const pathPart = path.resolve(cwdPath, toPath(execPath$1), "..");
|
|
32604
32779
|
if (!pathParts.includes(pathPart)) result.push(pathPart);
|
|
32605
32780
|
};
|
|
32606
|
-
const npmRunPathEnv = ({ env: env$1 =
|
|
32781
|
+
const npmRunPathEnv = ({ env: env$1 = process$1.env, ...options } = {}) => {
|
|
32607
32782
|
env$1 = { ...env$1 };
|
|
32608
32783
|
const pathName = pathKey({ env: env$1 });
|
|
32609
32784
|
options.path = env$1[pathName];
|
|
@@ -33738,7 +33913,7 @@ const normalizeCwd = (cwd = getDefaultCwd()) => {
|
|
|
33738
33913
|
};
|
|
33739
33914
|
const getDefaultCwd = () => {
|
|
33740
33915
|
try {
|
|
33741
|
-
return
|
|
33916
|
+
return process$1.cwd();
|
|
33742
33917
|
} catch (error) {
|
|
33743
33918
|
error.message = `The current directory does not exist.\n${error.message}`;
|
|
33744
33919
|
throw error;
|
|
@@ -33773,7 +33948,7 @@ const normalizeOptions = (filePath, rawArguments, rawOptions) => {
|
|
|
33773
33948
|
options.killSignal = normalizeKillSignal(options.killSignal);
|
|
33774
33949
|
options.forceKillAfterDelay = normalizeForceKillAfterDelay(options.forceKillAfterDelay);
|
|
33775
33950
|
options.lines = options.lines.map((lines, fdNumber) => lines && !BINARY_ENCODINGS.has(options.encoding) && options.buffer[fdNumber]);
|
|
33776
|
-
if (
|
|
33951
|
+
if (process$1.platform === "win32" && path.basename(file, ".exe") === "cmd") commandArguments.unshift("/q");
|
|
33777
33952
|
return {
|
|
33778
33953
|
file,
|
|
33779
33954
|
commandArguments,
|
|
@@ -33800,7 +33975,7 @@ const addDefaultOptions = ({ extendEnv = true, preferLocal = false, cwd, localDi
|
|
|
33800
33975
|
});
|
|
33801
33976
|
const getEnv = ({ env: envOption, extendEnv, preferLocal, node, localDirectory, nodePath }) => {
|
|
33802
33977
|
const env$1 = extendEnv ? {
|
|
33803
|
-
...
|
|
33978
|
+
...process$1.env,
|
|
33804
33979
|
...envOption
|
|
33805
33980
|
} : envOption;
|
|
33806
33981
|
if (preferLocal || node) return npmRunPathEnv({
|
|
@@ -34800,12 +34975,12 @@ const guessStreamDirection = {
|
|
|
34800
34975
|
}
|
|
34801
34976
|
};
|
|
34802
34977
|
const getStandardStreamDirection = (value) => {
|
|
34803
|
-
if ([0,
|
|
34978
|
+
if ([0, process$1.stdin].includes(value)) return "input";
|
|
34804
34979
|
if ([
|
|
34805
34980
|
1,
|
|
34806
34981
|
2,
|
|
34807
|
-
|
|
34808
|
-
|
|
34982
|
+
process$1.stdout,
|
|
34983
|
+
process$1.stderr
|
|
34809
34984
|
].includes(value)) return "output";
|
|
34810
34985
|
};
|
|
34811
34986
|
const DEFAULT_DIRECTION = "output";
|
|
@@ -35869,9 +36044,9 @@ const addIpcMethods = (subprocess, { ipc }) => {
|
|
|
35869
36044
|
Object.assign(subprocess, getIpcMethods(subprocess, false, ipc));
|
|
35870
36045
|
};
|
|
35871
36046
|
const getIpcExport = () => {
|
|
35872
|
-
const anyProcess =
|
|
36047
|
+
const anyProcess = process$1;
|
|
35873
36048
|
const isSubprocess = true;
|
|
35874
|
-
const ipc =
|
|
36049
|
+
const ipc = process$1.channel !== void 0;
|
|
35875
36050
|
return {
|
|
35876
36051
|
...getIpcMethods(anyProcess, isSubprocess, ipc),
|
|
35877
36052
|
getCancelSignal: getCancelSignal$1.bind(void 0, {
|
|
@@ -36113,7 +36288,7 @@ if (process.platform === "linux") signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SI
|
|
|
36113
36288
|
|
|
36114
36289
|
//#endregion
|
|
36115
36290
|
//#region node_modules/signal-exit/dist/mjs/index.js
|
|
36116
|
-
const processOk = (process$
|
|
36291
|
+
const processOk = (process$5) => !!process$5 && typeof process$5 === "object" && typeof process$5.removeListener === "function" && typeof process$5.emit === "function" && typeof process$5.reallyExit === "function" && typeof process$5.listeners === "function" && typeof process$5.kill === "function" && typeof process$5.pid === "number" && typeof process$5.on === "function";
|
|
36117
36292
|
const kExitEmitter = Symbol.for("signal-exit emitter");
|
|
36118
36293
|
const global$1 = globalThis;
|
|
36119
36294
|
const ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
@@ -36181,7 +36356,7 @@ var SignalExitFallback = class extends SignalExitBase {
|
|
|
36181
36356
|
};
|
|
36182
36357
|
var SignalExit = class extends SignalExitBase {
|
|
36183
36358
|
/* c8 ignore start */
|
|
36184
|
-
#hupSig = process$
|
|
36359
|
+
#hupSig = process$2.platform === "win32" ? "SIGINT" : "SIGHUP";
|
|
36185
36360
|
/* c8 ignore stop */
|
|
36186
36361
|
#emitter = new Emitter();
|
|
36187
36362
|
#process;
|
|
@@ -36189,15 +36364,15 @@ var SignalExit = class extends SignalExitBase {
|
|
|
36189
36364
|
#originalProcessReallyExit;
|
|
36190
36365
|
#sigListeners = {};
|
|
36191
36366
|
#loaded = false;
|
|
36192
|
-
constructor(process$
|
|
36367
|
+
constructor(process$5) {
|
|
36193
36368
|
super();
|
|
36194
|
-
this.#process = process$
|
|
36369
|
+
this.#process = process$5;
|
|
36195
36370
|
this.#sigListeners = {};
|
|
36196
36371
|
for (const sig of signals) this.#sigListeners[sig] = () => {
|
|
36197
36372
|
const listeners = this.#process.listeners(sig);
|
|
36198
36373
|
let { count: count$1 } = this.#emitter;
|
|
36199
36374
|
/* c8 ignore start */
|
|
36200
|
-
const p$1 = process$
|
|
36375
|
+
const p$1 = process$5;
|
|
36201
36376
|
if (typeof p$1.__signal_exit_emitter__ === "object" && typeof p$1.__signal_exit_emitter__.count === "number") count$1 += p$1.__signal_exit_emitter__.count;
|
|
36202
36377
|
/* c8 ignore stop */
|
|
36203
36378
|
if (listeners.length === count$1) {
|
|
@@ -36205,11 +36380,11 @@ var SignalExit = class extends SignalExitBase {
|
|
|
36205
36380
|
const ret = this.#emitter.emit("exit", null, sig);
|
|
36206
36381
|
/* c8 ignore start */
|
|
36207
36382
|
const s = sig === "SIGHUP" ? this.#hupSig : sig;
|
|
36208
|
-
if (!ret) process$
|
|
36383
|
+
if (!ret) process$5.kill(process$5.pid, s);
|
|
36209
36384
|
}
|
|
36210
36385
|
};
|
|
36211
|
-
this.#originalProcessReallyExit = process$
|
|
36212
|
-
this.#originalProcessEmit = process$
|
|
36386
|
+
this.#originalProcessReallyExit = process$5.reallyExit;
|
|
36387
|
+
this.#originalProcessEmit = process$5.emit;
|
|
36213
36388
|
}
|
|
36214
36389
|
onExit(cb, opts) {
|
|
36215
36390
|
/* c8 ignore start */
|
|
@@ -36276,8 +36451,8 @@ var SignalExit = class extends SignalExitBase {
|
|
|
36276
36451
|
} else return og.call(this.#process, ev, ...args);
|
|
36277
36452
|
}
|
|
36278
36453
|
};
|
|
36279
|
-
const process$
|
|
36280
|
-
const { onExit, load, unload } = signalExitWrap(processOk(process$
|
|
36454
|
+
const process$2 = globalThis.process;
|
|
36455
|
+
const { onExit, load, unload } = signalExitWrap(processOk(process$2) ? new SignalExit(process$2) : new SignalExitFallback());
|
|
36281
36456
|
|
|
36282
36457
|
//#endregion
|
|
36283
36458
|
//#region node_modules/execa/lib/terminate/cleanup.js
|
|
@@ -38028,13 +38203,6 @@ var require_lodash = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
38028
38203
|
//#region src/cli/commands/project/create.ts
|
|
38029
38204
|
var import_lodash = /* @__PURE__ */ __toESM(require_lodash(), 1);
|
|
38030
38205
|
const DEFAULT_TEMPLATE_ID = "backend-only";
|
|
38031
|
-
const SUPPORTED_AGENTS = [{
|
|
38032
|
-
value: "cursor",
|
|
38033
|
-
label: "Cursor"
|
|
38034
|
-
}, {
|
|
38035
|
-
value: "claude-code",
|
|
38036
|
-
label: "Claude Code"
|
|
38037
|
-
}];
|
|
38038
38206
|
async function getTemplateById(templateId) {
|
|
38039
38207
|
const templates = await listTemplates();
|
|
38040
38208
|
const template = templates.find((t) => t.id === templateId);
|
|
@@ -38097,7 +38265,6 @@ async function createInteractive(options) {
|
|
|
38097
38265
|
description: result.description || void 0,
|
|
38098
38266
|
projectPath: result.projectPath,
|
|
38099
38267
|
deploy: options.deploy,
|
|
38100
|
-
skills: options.skills,
|
|
38101
38268
|
isInteractive: true
|
|
38102
38269
|
});
|
|
38103
38270
|
}
|
|
@@ -38108,11 +38275,10 @@ async function createNonInteractive(options) {
|
|
|
38108
38275
|
description: options.description,
|
|
38109
38276
|
projectPath: options.path,
|
|
38110
38277
|
deploy: options.deploy,
|
|
38111
|
-
skills: options.skills,
|
|
38112
38278
|
isInteractive: false
|
|
38113
38279
|
});
|
|
38114
38280
|
}
|
|
38115
|
-
async function executeCreate({ template, name: rawName, description, projectPath, deploy,
|
|
38281
|
+
async function executeCreate({ template, name: rawName, description, projectPath, deploy, isInteractive }) {
|
|
38116
38282
|
const name$1 = rawName.trim();
|
|
38117
38283
|
const resolvedPath = resolve(projectPath);
|
|
38118
38284
|
const { projectId } = await runTask("Setting up your project...", async () => {
|
|
@@ -38172,45 +38338,12 @@ async function executeCreate({ template, name: rawName, description, projectPath
|
|
|
38172
38338
|
finalAppUrl = appUrl;
|
|
38173
38339
|
}
|
|
38174
38340
|
}
|
|
38175
|
-
let selectedAgents = [];
|
|
38176
|
-
if (isInteractive) {
|
|
38177
|
-
const result = await fe({
|
|
38178
|
-
message: "Add AI agent skills? (Select agents to configure)",
|
|
38179
|
-
options: SUPPORTED_AGENTS,
|
|
38180
|
-
initialValues: SUPPORTED_AGENTS.map((agent) => agent.value),
|
|
38181
|
-
required: false
|
|
38182
|
-
});
|
|
38183
|
-
if (!pD(result)) selectedAgents = result;
|
|
38184
|
-
} else if (skills) selectedAgents = SUPPORTED_AGENTS.map((agent) => agent.value);
|
|
38185
|
-
if (selectedAgents.length > 0) {
|
|
38186
|
-
const agentArgs = selectedAgents.flatMap((agent) => ["-a", agent]);
|
|
38187
|
-
M.step("Installing skills for: " + selectedAgents.join(", "));
|
|
38188
|
-
await runTask("Installing skills for: " + selectedAgents.join(", "), async () => {
|
|
38189
|
-
await execa("npx", [
|
|
38190
|
-
"-y",
|
|
38191
|
-
"add-skill",
|
|
38192
|
-
"base44/skills",
|
|
38193
|
-
"-y",
|
|
38194
|
-
"-s",
|
|
38195
|
-
"base44-cli",
|
|
38196
|
-
"-s",
|
|
38197
|
-
"base44-sdk",
|
|
38198
|
-
...agentArgs
|
|
38199
|
-
], {
|
|
38200
|
-
cwd: resolvedPath,
|
|
38201
|
-
stdio: "inherit"
|
|
38202
|
-
});
|
|
38203
|
-
}, {
|
|
38204
|
-
successMessage: theme.colors.base44Orange("AI agent skills added successfully"),
|
|
38205
|
-
errorMessage: "Failed to add AI agent skills - you can add them later with: npx add-skill base44/skills"
|
|
38206
|
-
});
|
|
38207
|
-
}
|
|
38208
38341
|
M.message(`${theme.styles.header("Project")}: ${theme.colors.base44Orange(name$1)}`);
|
|
38209
38342
|
M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(projectId))}`);
|
|
38210
38343
|
if (finalAppUrl) M.message(`${theme.styles.header("Site")}: ${theme.colors.links(finalAppUrl)}`);
|
|
38211
38344
|
return { outroMessage: "Your project is set up and ready to use" };
|
|
38212
38345
|
}
|
|
38213
|
-
const createCommand = new Command("create").description("Create a new Base44 project").option("-n, --name <name>", "Project name").option("-d, --description <description>", "Project description").option("-p, --path <path>", "Path where to create the project").option("-t, --template <id>", "Template ID (e.g., backend-only, backend-and-client)").option("--deploy", "Build and deploy the site").
|
|
38346
|
+
const createCommand = new Command("create").description("Create a new Base44 project").option("-n, --name <name>", "Project name").option("-d, --description <description>", "Project description").option("-p, --path <path>", "Path where to create the project").option("-t, --template <id>", "Template ID (e.g., backend-only, backend-and-client)").option("--deploy", "Build and deploy the site").hook("preAction", validateNonInteractiveFlags$1).action(async (options) => {
|
|
38214
38347
|
await chooseCreate(options);
|
|
38215
38348
|
});
|
|
38216
38349
|
|
|
@@ -38256,7 +38389,7 @@ function isInsideContainer() {
|
|
|
38256
38389
|
//#endregion
|
|
38257
38390
|
//#region node_modules/is-wsl/index.js
|
|
38258
38391
|
const isWsl = () => {
|
|
38259
|
-
if (
|
|
38392
|
+
if (process$1.platform !== "linux") return false;
|
|
38260
38393
|
if (os.release().toLowerCase().includes("microsoft")) {
|
|
38261
38394
|
if (isInsideContainer()) return false;
|
|
38262
38395
|
return true;
|
|
@@ -38267,12 +38400,12 @@ const isWsl = () => {
|
|
|
38267
38400
|
return false;
|
|
38268
38401
|
}
|
|
38269
38402
|
};
|
|
38270
|
-
var is_wsl_default =
|
|
38403
|
+
var is_wsl_default = process$1.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
38271
38404
|
|
|
38272
38405
|
//#endregion
|
|
38273
38406
|
//#region node_modules/powershell-utils/index.js
|
|
38274
38407
|
const execFile$2 = promisify(childProcess.execFile);
|
|
38275
|
-
const powerShellPath$1 = () => `${
|
|
38408
|
+
const powerShellPath$1 = () => `${process$1.env.SYSTEMROOT || process$1.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
38276
38409
|
const executePowerShell = async (command, options = {}) => {
|
|
38277
38410
|
const { powerShellPath: psPath, ...execFileOptions } = options;
|
|
38278
38411
|
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
@@ -38383,7 +38516,7 @@ function defineLazyProperty(object$1, propertyName, valueGetter) {
|
|
|
38383
38516
|
//#region node_modules/default-browser-id/index.js
|
|
38384
38517
|
const execFileAsync$3 = promisify(execFile);
|
|
38385
38518
|
async function defaultBrowserId() {
|
|
38386
|
-
if (
|
|
38519
|
+
if (process$1.platform !== "darwin") throw new Error("macOS only");
|
|
38387
38520
|
const { stdout: stdout$1 } = await execFileAsync$3("defaults", [
|
|
38388
38521
|
"read",
|
|
38389
38522
|
"com.apple.LaunchServices/com.apple.launchservices.secure",
|
|
@@ -38398,7 +38531,7 @@ async function defaultBrowserId() {
|
|
|
38398
38531
|
//#region node_modules/run-applescript/index.js
|
|
38399
38532
|
const execFileAsync$2 = promisify(execFile);
|
|
38400
38533
|
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
38401
|
-
if (
|
|
38534
|
+
if (process$1.platform !== "darwin") throw new Error("macOS only");
|
|
38402
38535
|
const outputArguments = humanReadableOutput ? [] : ["-ss"];
|
|
38403
38536
|
const execOptions = {};
|
|
38404
38537
|
if (signal) execOptions.signal = signal;
|
|
@@ -38507,14 +38640,14 @@ async function defaultBrowser$1(_execFileAsync = execFileAsync$1) {
|
|
|
38507
38640
|
const execFileAsync = promisify(execFile);
|
|
38508
38641
|
const titleize = (string$2) => string$2.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x$2) => x$2.toUpperCase());
|
|
38509
38642
|
async function defaultBrowser() {
|
|
38510
|
-
if (
|
|
38643
|
+
if (process$1.platform === "darwin") {
|
|
38511
38644
|
const id = await defaultBrowserId();
|
|
38512
38645
|
return {
|
|
38513
38646
|
name: await bundleName(id),
|
|
38514
38647
|
id
|
|
38515
38648
|
};
|
|
38516
38649
|
}
|
|
38517
|
-
if (
|
|
38650
|
+
if (process$1.platform === "linux") {
|
|
38518
38651
|
const { stdout: stdout$1 } = await execFileAsync("xdg-mime", [
|
|
38519
38652
|
"query",
|
|
38520
38653
|
"default",
|
|
@@ -38526,13 +38659,13 @@ async function defaultBrowser() {
|
|
|
38526
38659
|
id
|
|
38527
38660
|
};
|
|
38528
38661
|
}
|
|
38529
|
-
if (
|
|
38662
|
+
if (process$1.platform === "win32") return defaultBrowser$1();
|
|
38530
38663
|
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
38531
38664
|
}
|
|
38532
38665
|
|
|
38533
38666
|
//#endregion
|
|
38534
38667
|
//#region node_modules/is-in-ssh/index.js
|
|
38535
|
-
const isInSsh = Boolean(
|
|
38668
|
+
const isInSsh = Boolean(process$1.env.SSH_CONNECTION || process$1.env.SSH_CLIENT || process$1.env.SSH_TTY);
|
|
38536
38669
|
var is_in_ssh_default = isInSsh;
|
|
38537
38670
|
|
|
38538
38671
|
//#endregion
|
|
@@ -38540,7 +38673,7 @@ var is_in_ssh_default = isInSsh;
|
|
|
38540
38673
|
const fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
38541
38674
|
const __dirname = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : "";
|
|
38542
38675
|
const localXdgOpenPath = path.join(__dirname, "xdg-open");
|
|
38543
|
-
const { platform: platform$1, arch } =
|
|
38676
|
+
const { platform: platform$1, arch } = process$1;
|
|
38544
38677
|
const tryEachApp = async (apps$1, opener) => {
|
|
38545
38678
|
if (apps$1.length === 0) return;
|
|
38546
38679
|
const errors = [];
|
|
@@ -38653,7 +38786,7 @@ const baseOpen = async (options) => {
|
|
|
38653
38786
|
await fs$1.access(localXdgOpenPath, constants$1.X_OK);
|
|
38654
38787
|
exeLocalXdgOpen = true;
|
|
38655
38788
|
} catch {}
|
|
38656
|
-
command =
|
|
38789
|
+
command = process$1.versions.electron ?? (platform$1 === "android" || isBundled || !exeLocalXdgOpen) ? "xdg-open" : localXdgOpenPath;
|
|
38657
38790
|
}
|
|
38658
38791
|
if (appArguments.length > 0) cliArguments.push(...appArguments);
|
|
38659
38792
|
if (!options.wait) {
|
|
@@ -38796,9 +38929,8 @@ const deployCommand = new Command("deploy").description("Deploy all project reso
|
|
|
38796
38929
|
//#endregion
|
|
38797
38930
|
//#region src/cli/commands/project/link.ts
|
|
38798
38931
|
function validateNonInteractiveFlags(command) {
|
|
38799
|
-
const { create: create$1, name: name$1,
|
|
38800
|
-
if (create$1 &&
|
|
38801
|
-
if (existing && !projectId) command.error("--projectId is required when using --existing");
|
|
38932
|
+
const { create: create$1, name: name$1, projectId } = command.opts();
|
|
38933
|
+
if (create$1 && projectId) command.error("--create and --projectId cannot be used together");
|
|
38802
38934
|
if (create$1 && !name$1) command.error("--name is required when using --create");
|
|
38803
38935
|
}
|
|
38804
38936
|
async function promptForLinkAction() {
|
|
@@ -38862,14 +38994,18 @@ async function link(options) {
|
|
|
38862
38994
|
if (!projectRoot) throw new Error("No Base44 project found. Run this command from a project directory with a config.jsonc file.");
|
|
38863
38995
|
if (await appConfigExists(projectRoot.root)) throw new Error("Project is already linked. An .app.jsonc file with the appId already exists.");
|
|
38864
38996
|
let finalProjectId;
|
|
38865
|
-
const action = options.
|
|
38997
|
+
const action = options.projectId ? "choose" : options.create ? "create" : await promptForLinkAction();
|
|
38866
38998
|
if (action === "choose") {
|
|
38867
38999
|
const linkableProjects = (await runTask("Fetching projects...", async () => listProjects(), {
|
|
38868
39000
|
successMessage: "Projects fetched",
|
|
38869
39001
|
errorMessage: "Failed to fetch projects"
|
|
38870
39002
|
})).filter((p$1) => p$1.isManagedSourceCode !== true);
|
|
38871
39003
|
if (!linkableProjects.length) return { outroMessage: "No projects available for linking" };
|
|
38872
|
-
|
|
39004
|
+
let projectId;
|
|
39005
|
+
if (options.projectId) {
|
|
39006
|
+
if (!linkableProjects.find((p$1) => p$1.id === options.projectId)) throw new Error(`Project with ID "${options.projectId}" not found or not available for linking.`);
|
|
39007
|
+
projectId = options.projectId;
|
|
39008
|
+
} else projectId = (await promptForExistingProject(linkableProjects)).id;
|
|
38873
39009
|
await runTask("Linking project...", async () => {
|
|
38874
39010
|
await writeAppConfig(projectRoot.root, projectId);
|
|
38875
39011
|
setAppConfig({
|
|
@@ -38903,7 +39039,7 @@ async function link(options) {
|
|
|
38903
39039
|
M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(finalProjectId))}`);
|
|
38904
39040
|
return { outroMessage: "Project linked" };
|
|
38905
39041
|
}
|
|
38906
|
-
const linkCommand = new Command("link").description("Link a local project to a Base44 project (create new or link existing)").option("-c, --create", "Create a new project (skip selection prompt)").option("-n, --name <name>", "Project name (required when --create is used)").option("-d, --description <description>", "Project description").option("-
|
|
39042
|
+
const linkCommand = new Command("link").description("Link a local project to a Base44 project (create new or link existing)").option("-c, --create", "Create a new project (skip selection prompt)").option("-n, --name <name>", "Project name (required when --create is used)").option("-d, --description <description>", "Project description").option("-p, --projectId <id>", "Project ID to link to an existing project (skips selection prompt)").hook("preAction", validateNonInteractiveFlags).action(async (options) => {
|
|
38907
39043
|
await runCommand(() => link(options), {
|
|
38908
39044
|
requireAuth: true,
|
|
38909
39045
|
requireAppConfig: false
|
|
@@ -38931,12 +39067,665 @@ const siteDeployCommand = new Command("site").description("Manage site deploymen
|
|
|
38931
39067
|
await runCommand(() => deployAction(options), { requireAuth: true });
|
|
38932
39068
|
}));
|
|
38933
39069
|
|
|
39070
|
+
//#endregion
|
|
39071
|
+
//#region src/core/connectors/schema.ts
|
|
39072
|
+
/**
|
|
39073
|
+
* Response from POST /api/apps/{app_id}/external-auth/initiate
|
|
39074
|
+
*/
|
|
39075
|
+
const InitiateResponseSchema = object({
|
|
39076
|
+
redirect_url: string().nullish(),
|
|
39077
|
+
connection_id: string().nullish(),
|
|
39078
|
+
already_authorized: boolean().nullish(),
|
|
39079
|
+
other_user_email: string().nullish(),
|
|
39080
|
+
error: string().nullish()
|
|
39081
|
+
});
|
|
39082
|
+
/**
|
|
39083
|
+
* Response from GET /api/apps/{app_id}/external-auth/status
|
|
39084
|
+
*/
|
|
39085
|
+
const StatusResponseSchema = object({
|
|
39086
|
+
status: _enum([
|
|
39087
|
+
"ACTIVE",
|
|
39088
|
+
"PENDING",
|
|
39089
|
+
"FAILED"
|
|
39090
|
+
]),
|
|
39091
|
+
account_email: string().nullish(),
|
|
39092
|
+
error: string().nullish()
|
|
39093
|
+
}).transform((data) => ({
|
|
39094
|
+
status: data.status,
|
|
39095
|
+
accountEmail: data.account_email,
|
|
39096
|
+
error: data.error
|
|
39097
|
+
}));
|
|
39098
|
+
/**
|
|
39099
|
+
* A connected integration from the list endpoint
|
|
39100
|
+
*/
|
|
39101
|
+
const ConnectorSchema = object({
|
|
39102
|
+
integration_type: string(),
|
|
39103
|
+
status: string(),
|
|
39104
|
+
connected_at: string().nullish(),
|
|
39105
|
+
account_info: object({
|
|
39106
|
+
email: string().nullish(),
|
|
39107
|
+
name: string().nullish()
|
|
39108
|
+
}).nullish()
|
|
39109
|
+
}).transform((data) => ({
|
|
39110
|
+
integrationType: data.integration_type,
|
|
39111
|
+
status: data.status,
|
|
39112
|
+
connectedAt: data.connected_at,
|
|
39113
|
+
accountInfo: data.account_info
|
|
39114
|
+
}));
|
|
39115
|
+
/**
|
|
39116
|
+
* Response from GET /api/apps/{app_id}/external-auth/list
|
|
39117
|
+
*/
|
|
39118
|
+
const ListResponseSchema = object({ integrations: array(ConnectorSchema) });
|
|
39119
|
+
/**
|
|
39120
|
+
* Generic API error response
|
|
39121
|
+
*/
|
|
39122
|
+
const ApiErrorSchema = object({
|
|
39123
|
+
error: string(),
|
|
39124
|
+
detail: string().nullish()
|
|
39125
|
+
});
|
|
39126
|
+
|
|
39127
|
+
//#endregion
|
|
39128
|
+
//#region src/core/connectors/api.ts
|
|
39129
|
+
/**
|
|
39130
|
+
* Initiates OAuth flow for a connector integration.
|
|
39131
|
+
* Returns a redirect URL to open in the browser.
|
|
39132
|
+
*/
|
|
39133
|
+
async function initiateOAuth(integrationType, scopes = null) {
|
|
39134
|
+
const response = await getAppClient().post("external-auth/initiate", {
|
|
39135
|
+
json: {
|
|
39136
|
+
integration_type: integrationType,
|
|
39137
|
+
scopes
|
|
39138
|
+
},
|
|
39139
|
+
throwHttpErrors: false
|
|
39140
|
+
});
|
|
39141
|
+
const json = await response.json();
|
|
39142
|
+
if (!response.ok) {
|
|
39143
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39144
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39145
|
+
throw new ConnectorApiError(`Failed to initiate OAuth: ${response.status} ${response.statusText}`);
|
|
39146
|
+
}
|
|
39147
|
+
const result = InitiateResponseSchema.safeParse(json);
|
|
39148
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid initiate response from server: ${result.error.message}`);
|
|
39149
|
+
return result.data;
|
|
39150
|
+
}
|
|
39151
|
+
/**
|
|
39152
|
+
* Checks the status of an OAuth connection attempt.
|
|
39153
|
+
*/
|
|
39154
|
+
async function checkOAuthStatus(integrationType, connectionId) {
|
|
39155
|
+
const response = await getAppClient().get("external-auth/status", {
|
|
39156
|
+
searchParams: {
|
|
39157
|
+
integration_type: integrationType,
|
|
39158
|
+
connection_id: connectionId
|
|
39159
|
+
},
|
|
39160
|
+
throwHttpErrors: false
|
|
39161
|
+
});
|
|
39162
|
+
const json = await response.json();
|
|
39163
|
+
if (!response.ok) {
|
|
39164
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39165
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39166
|
+
throw new ConnectorApiError(`Failed to check OAuth status: ${response.status} ${response.statusText}`);
|
|
39167
|
+
}
|
|
39168
|
+
const result = StatusResponseSchema.safeParse(json);
|
|
39169
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid status response from server: ${result.error.message}`);
|
|
39170
|
+
return result.data;
|
|
39171
|
+
}
|
|
39172
|
+
/**
|
|
39173
|
+
* Lists all connected integrations for the current app.
|
|
39174
|
+
*/
|
|
39175
|
+
async function listConnectors() {
|
|
39176
|
+
const response = await getAppClient().get("external-auth/list", { throwHttpErrors: false });
|
|
39177
|
+
const json = await response.json();
|
|
39178
|
+
if (!response.ok) {
|
|
39179
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39180
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39181
|
+
throw new ConnectorApiError(`Failed to list connectors: ${response.status} ${response.statusText}`);
|
|
39182
|
+
}
|
|
39183
|
+
const result = ListResponseSchema.safeParse(json);
|
|
39184
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid list response from server: ${result.error.message}`);
|
|
39185
|
+
return result.data.integrations;
|
|
39186
|
+
}
|
|
39187
|
+
/**
|
|
39188
|
+
* Disconnects (soft delete) a connector integration.
|
|
39189
|
+
*/
|
|
39190
|
+
async function disconnectConnector(integrationType) {
|
|
39191
|
+
const response = await getAppClient().delete(`external-auth/integrations/${integrationType}`, { throwHttpErrors: false });
|
|
39192
|
+
if (!response.ok) {
|
|
39193
|
+
const json = await response.json();
|
|
39194
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39195
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39196
|
+
throw new ConnectorApiError(`Failed to disconnect connector: ${response.status} ${response.statusText}`);
|
|
39197
|
+
}
|
|
39198
|
+
}
|
|
39199
|
+
/**
|
|
39200
|
+
* Removes (hard delete) a connector integration.
|
|
39201
|
+
* This permanently removes the connector and cannot be undone.
|
|
39202
|
+
*/
|
|
39203
|
+
async function removeConnector(integrationType) {
|
|
39204
|
+
const response = await getAppClient().delete(`external-auth/integrations/${integrationType}/remove`, { throwHttpErrors: false });
|
|
39205
|
+
if (!response.ok) {
|
|
39206
|
+
const json = await response.json();
|
|
39207
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39208
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39209
|
+
throw new ConnectorApiError(`Failed to remove connector: ${response.status} ${response.statusText}`);
|
|
39210
|
+
}
|
|
39211
|
+
}
|
|
39212
|
+
|
|
39213
|
+
//#endregion
|
|
39214
|
+
//#region src/core/connectors/constants.ts
|
|
39215
|
+
/**
|
|
39216
|
+
* OAuth polling configuration
|
|
39217
|
+
*/
|
|
39218
|
+
const OAUTH_POLL_INTERVAL_MS = 2e3;
|
|
39219
|
+
const OAUTH_POLL_TIMEOUT_MS = 300 * 1e3;
|
|
39220
|
+
/**
|
|
39221
|
+
* Supported OAuth connector integrations.
|
|
39222
|
+
* Based on apper/backend/app/external_auth/models/constants.py
|
|
39223
|
+
*/
|
|
39224
|
+
const SUPPORTED_INTEGRATIONS = [
|
|
39225
|
+
"googlecalendar",
|
|
39226
|
+
"googledrive",
|
|
39227
|
+
"gmail",
|
|
39228
|
+
"googlesheets",
|
|
39229
|
+
"googledocs",
|
|
39230
|
+
"googleslides",
|
|
39231
|
+
"slack",
|
|
39232
|
+
"notion",
|
|
39233
|
+
"salesforce",
|
|
39234
|
+
"hubspot",
|
|
39235
|
+
"linkedin",
|
|
39236
|
+
"tiktok"
|
|
39237
|
+
];
|
|
39238
|
+
/**
|
|
39239
|
+
* Display names for integrations (for CLI output)
|
|
39240
|
+
*/
|
|
39241
|
+
const INTEGRATION_DISPLAY_NAMES = {
|
|
39242
|
+
googlecalendar: "Google Calendar",
|
|
39243
|
+
googledrive: "Google Drive",
|
|
39244
|
+
gmail: "Gmail",
|
|
39245
|
+
googlesheets: "Google Sheets",
|
|
39246
|
+
googledocs: "Google Docs",
|
|
39247
|
+
googleslides: "Google Slides",
|
|
39248
|
+
slack: "Slack",
|
|
39249
|
+
notion: "Notion",
|
|
39250
|
+
salesforce: "Salesforce",
|
|
39251
|
+
hubspot: "HubSpot",
|
|
39252
|
+
linkedin: "LinkedIn",
|
|
39253
|
+
tiktok: "TikTok"
|
|
39254
|
+
};
|
|
39255
|
+
function isValidIntegration(type) {
|
|
39256
|
+
return SUPPORTED_INTEGRATIONS.includes(type);
|
|
39257
|
+
}
|
|
39258
|
+
function getIntegrationDisplayName(type) {
|
|
39259
|
+
if (isValidIntegration(type)) return INTEGRATION_DISPLAY_NAMES[type];
|
|
39260
|
+
return type;
|
|
39261
|
+
}
|
|
39262
|
+
|
|
39263
|
+
//#endregion
|
|
39264
|
+
//#region src/core/connectors/oauth.ts
|
|
39265
|
+
/**
|
|
39266
|
+
* Polls for OAuth completion status.
|
|
39267
|
+
* Returns when status becomes ACTIVE or FAILED, or times out.
|
|
39268
|
+
*/
|
|
39269
|
+
async function waitForOAuthCompletion(integrationType, connectionId, options) {
|
|
39270
|
+
let accountEmail;
|
|
39271
|
+
let error;
|
|
39272
|
+
try {
|
|
39273
|
+
await pWaitFor(async () => {
|
|
39274
|
+
const status = await checkOAuthStatus(integrationType, connectionId);
|
|
39275
|
+
if (status.status === "ACTIVE") {
|
|
39276
|
+
accountEmail = status.accountEmail ?? void 0;
|
|
39277
|
+
return true;
|
|
39278
|
+
}
|
|
39279
|
+
if (status.status === "FAILED") {
|
|
39280
|
+
error = status.error || "Authorization failed";
|
|
39281
|
+
throw new Error(error);
|
|
39282
|
+
}
|
|
39283
|
+
options?.onPending?.();
|
|
39284
|
+
return false;
|
|
39285
|
+
}, {
|
|
39286
|
+
interval: OAUTH_POLL_INTERVAL_MS,
|
|
39287
|
+
timeout: OAUTH_POLL_TIMEOUT_MS
|
|
39288
|
+
});
|
|
39289
|
+
return {
|
|
39290
|
+
success: true,
|
|
39291
|
+
accountEmail
|
|
39292
|
+
};
|
|
39293
|
+
} catch (err) {
|
|
39294
|
+
if (err instanceof Error && err.message.includes("timed out")) return {
|
|
39295
|
+
success: false,
|
|
39296
|
+
error: "Authorization timed out. Please try again."
|
|
39297
|
+
};
|
|
39298
|
+
return {
|
|
39299
|
+
success: false,
|
|
39300
|
+
error: error || (err instanceof Error ? err.message : "Unknown error")
|
|
39301
|
+
};
|
|
39302
|
+
}
|
|
39303
|
+
}
|
|
39304
|
+
|
|
39305
|
+
//#endregion
|
|
39306
|
+
//#region src/core/connectors/config.ts
|
|
39307
|
+
/**
|
|
39308
|
+
* Read all connectors from the project config file
|
|
39309
|
+
*/
|
|
39310
|
+
async function readLocalConnectors(projectRoot) {
|
|
39311
|
+
const found = await findProjectRoot(projectRoot);
|
|
39312
|
+
if (!found) return [];
|
|
39313
|
+
const connectorsData = (await readJsonFile(found.configPath)).connectors;
|
|
39314
|
+
if (!connectorsData) return [];
|
|
39315
|
+
const connectors = [];
|
|
39316
|
+
for (const [type, config$1] of Object.entries(connectorsData)) {
|
|
39317
|
+
if (!isValidIntegration(type)) throw new Error(`Unknown connector type: ${type}`);
|
|
39318
|
+
connectors.push({
|
|
39319
|
+
type,
|
|
39320
|
+
scopes: config$1.scopes
|
|
39321
|
+
});
|
|
39322
|
+
}
|
|
39323
|
+
return connectors;
|
|
39324
|
+
}
|
|
39325
|
+
/**
|
|
39326
|
+
* Write connectors to the project config file
|
|
39327
|
+
*/
|
|
39328
|
+
async function writeLocalConnectors(connectors, projectRoot) {
|
|
39329
|
+
const found = await findProjectRoot(projectRoot);
|
|
39330
|
+
if (!found) throw new Error("Project config not found. Run this command from a Base44 project directory.");
|
|
39331
|
+
const existingConfig = await readJsonFile(found.configPath);
|
|
39332
|
+
const connectorsData = {};
|
|
39333
|
+
for (const connector of connectors) connectorsData[connector.type] = { ...connector.scopes && { scopes: connector.scopes } };
|
|
39334
|
+
const updatedConfig = {
|
|
39335
|
+
...existingConfig,
|
|
39336
|
+
connectors: Object.keys(connectorsData).length > 0 ? connectorsData : void 0
|
|
39337
|
+
};
|
|
39338
|
+
if (!updatedConfig.connectors) delete updatedConfig.connectors;
|
|
39339
|
+
await writeJsonFile(found.configPath, updatedConfig);
|
|
39340
|
+
return found.configPath;
|
|
39341
|
+
}
|
|
39342
|
+
/**
|
|
39343
|
+
* Add a connector to the project config file
|
|
39344
|
+
*/
|
|
39345
|
+
async function addLocalConnector(type, scopes, projectRoot) {
|
|
39346
|
+
const connectors = await readLocalConnectors(projectRoot);
|
|
39347
|
+
const existing = connectors.find((c$1) => c$1.type === type);
|
|
39348
|
+
if (existing) {
|
|
39349
|
+
if (scopes) existing.scopes = scopes;
|
|
39350
|
+
} else connectors.push({
|
|
39351
|
+
type,
|
|
39352
|
+
scopes
|
|
39353
|
+
});
|
|
39354
|
+
return await writeLocalConnectors(connectors, projectRoot);
|
|
39355
|
+
}
|
|
39356
|
+
/**
|
|
39357
|
+
* Remove a connector from the project config file
|
|
39358
|
+
*/
|
|
39359
|
+
async function removeLocalConnector(type, projectRoot) {
|
|
39360
|
+
const connectors = await readLocalConnectors(projectRoot);
|
|
39361
|
+
const filtered = connectors.filter((c$1) => c$1.type !== type);
|
|
39362
|
+
if (filtered.length === connectors.length) return null;
|
|
39363
|
+
return await writeLocalConnectors(filtered, projectRoot);
|
|
39364
|
+
}
|
|
39365
|
+
|
|
39366
|
+
//#endregion
|
|
39367
|
+
//#region src/core/connectors/state.ts
|
|
39368
|
+
/**
|
|
39369
|
+
* Fetches both local config and backend connectors in parallel.
|
|
39370
|
+
* Gracefully handles failures by returning empty arrays.
|
|
39371
|
+
*/
|
|
39372
|
+
async function fetchConnectorState() {
|
|
39373
|
+
const [local, backend] = await Promise.all([readLocalConnectors().catch(() => []), listConnectors().catch(() => [])]);
|
|
39374
|
+
return {
|
|
39375
|
+
local,
|
|
39376
|
+
backend
|
|
39377
|
+
};
|
|
39378
|
+
}
|
|
39379
|
+
|
|
39380
|
+
//#endregion
|
|
39381
|
+
//#region src/cli/commands/connectors/add.ts
|
|
39382
|
+
function validateIntegrationType(type) {
|
|
39383
|
+
if (!isValidIntegration(type)) {
|
|
39384
|
+
const supportedList = SUPPORTED_INTEGRATIONS.join(", ");
|
|
39385
|
+
throw new Error(`Unsupported connector: ${type}\nSupported connectors: ${supportedList}`);
|
|
39386
|
+
}
|
|
39387
|
+
return type;
|
|
39388
|
+
}
|
|
39389
|
+
async function promptForIntegrationType() {
|
|
39390
|
+
const selected = await ve({
|
|
39391
|
+
message: "Select an integration to connect:",
|
|
39392
|
+
options: SUPPORTED_INTEGRATIONS.map((type) => ({
|
|
39393
|
+
value: type,
|
|
39394
|
+
label: getIntegrationDisplayName(type)
|
|
39395
|
+
}))
|
|
39396
|
+
});
|
|
39397
|
+
if (pD(selected)) {
|
|
39398
|
+
xe("Operation cancelled.");
|
|
39399
|
+
process.exit(0);
|
|
39400
|
+
}
|
|
39401
|
+
return selected;
|
|
39402
|
+
}
|
|
39403
|
+
async function pollForOAuthCompletion(integrationType, connectionId) {
|
|
39404
|
+
return await runTask("Waiting for authorization...", async () => {
|
|
39405
|
+
return await waitForOAuthCompletion(integrationType, connectionId);
|
|
39406
|
+
}, {
|
|
39407
|
+
successMessage: "Authorization completed!",
|
|
39408
|
+
errorMessage: "Authorization failed"
|
|
39409
|
+
});
|
|
39410
|
+
}
|
|
39411
|
+
async function addConnector(integrationType) {
|
|
39412
|
+
const selectedType = integrationType ? validateIntegrationType(integrationType) : await promptForIntegrationType();
|
|
39413
|
+
const displayName = getIntegrationDisplayName(selectedType);
|
|
39414
|
+
const initiateResponse = await runTask(`Initiating ${displayName} connection...`, async () => {
|
|
39415
|
+
return await initiateOAuth(selectedType);
|
|
39416
|
+
}, {
|
|
39417
|
+
successMessage: `${displayName} OAuth initiated`,
|
|
39418
|
+
errorMessage: `Failed to initiate ${displayName} connection`
|
|
39419
|
+
});
|
|
39420
|
+
if (initiateResponse.already_authorized) {
|
|
39421
|
+
await addLocalConnector(selectedType);
|
|
39422
|
+
return { outroMessage: `Already connected to ${theme.styles.bold(displayName)} (added to config)` };
|
|
39423
|
+
}
|
|
39424
|
+
if (initiateResponse.error === "different_user" && initiateResponse.other_user_email) throw new Error(`This app is already connected to ${displayName} by ${initiateResponse.other_user_email}`);
|
|
39425
|
+
if (!initiateResponse.redirect_url || !initiateResponse.connection_id) throw new Error("Invalid response from server: missing redirect URL or connection ID");
|
|
39426
|
+
M.info(`Please authorize ${displayName} at:\n${theme.colors.links(initiateResponse.redirect_url)}`);
|
|
39427
|
+
const result = await pollForOAuthCompletion(selectedType, initiateResponse.connection_id);
|
|
39428
|
+
if (!result.success) throw new Error(result.error || "Authorization failed");
|
|
39429
|
+
await addLocalConnector(selectedType);
|
|
39430
|
+
const accountInfo = result.accountEmail ? ` as ${theme.styles.bold(result.accountEmail)}` : "";
|
|
39431
|
+
return { outroMessage: `Successfully connected to ${theme.styles.bold(displayName)}${accountInfo}` };
|
|
39432
|
+
}
|
|
39433
|
+
const connectorsAddCommand = new Command("add").argument("[type]", "Integration type (e.g., slack, notion, googlecalendar)").description("Connect an OAuth integration").action(async (type) => {
|
|
39434
|
+
await runCommand(() => addConnector(type), {
|
|
39435
|
+
requireAuth: true,
|
|
39436
|
+
requireAppConfig: true
|
|
39437
|
+
});
|
|
39438
|
+
});
|
|
39439
|
+
|
|
39440
|
+
//#endregion
|
|
39441
|
+
//#region src/cli/commands/connectors/list.ts
|
|
39442
|
+
function mergeConnectors(local, backend) {
|
|
39443
|
+
const merged = /* @__PURE__ */ new Map();
|
|
39444
|
+
for (const connector of local) merged.set(connector.type, {
|
|
39445
|
+
type: connector.type,
|
|
39446
|
+
displayName: getIntegrationDisplayName(connector.type),
|
|
39447
|
+
inLocal: true,
|
|
39448
|
+
inBackend: false
|
|
39449
|
+
});
|
|
39450
|
+
for (const connector of backend) {
|
|
39451
|
+
const existing = merged.get(connector.integrationType);
|
|
39452
|
+
const accountEmail = (connector.accountInfo?.email || connector.accountInfo?.name) ?? void 0;
|
|
39453
|
+
if (existing) {
|
|
39454
|
+
existing.inBackend = true;
|
|
39455
|
+
existing.status = connector.status;
|
|
39456
|
+
existing.accountEmail = accountEmail;
|
|
39457
|
+
} else merged.set(connector.integrationType, {
|
|
39458
|
+
type: connector.integrationType,
|
|
39459
|
+
displayName: getIntegrationDisplayName(connector.integrationType),
|
|
39460
|
+
inLocal: false,
|
|
39461
|
+
inBackend: true,
|
|
39462
|
+
status: connector.status,
|
|
39463
|
+
accountEmail
|
|
39464
|
+
});
|
|
39465
|
+
}
|
|
39466
|
+
return Array.from(merged.values());
|
|
39467
|
+
}
|
|
39468
|
+
function formatConnectorLine(connector) {
|
|
39469
|
+
const { displayName, inLocal, inBackend, status, accountEmail } = connector;
|
|
39470
|
+
const isConnected$1 = inBackend && status?.toLowerCase() === "active";
|
|
39471
|
+
const isPending = inLocal && !inBackend;
|
|
39472
|
+
const isOrphaned = inBackend && !inLocal;
|
|
39473
|
+
let bullet;
|
|
39474
|
+
let statusText = "";
|
|
39475
|
+
if (isConnected$1) {
|
|
39476
|
+
bullet = theme.colors.success("●");
|
|
39477
|
+
if (accountEmail) statusText = ` - ${accountEmail}`;
|
|
39478
|
+
} else if (isPending) {
|
|
39479
|
+
bullet = theme.colors.warning("○");
|
|
39480
|
+
statusText = theme.styles.dim(" (not connected)");
|
|
39481
|
+
} else if (isOrphaned) {
|
|
39482
|
+
bullet = theme.colors.error("○");
|
|
39483
|
+
statusText = theme.styles.dim(" (not in local config)");
|
|
39484
|
+
} else {
|
|
39485
|
+
bullet = theme.colors.error("○");
|
|
39486
|
+
statusText = theme.styles.dim(` (${status || "disconnected"})`);
|
|
39487
|
+
}
|
|
39488
|
+
return `${bullet} ${displayName}${statusText}`;
|
|
39489
|
+
}
|
|
39490
|
+
async function listConnectorsCommand() {
|
|
39491
|
+
const { local: localConnectors, backend: backendConnectors } = await runTask("Fetching connectors...", fetchConnectorState, {
|
|
39492
|
+
successMessage: "Connectors loaded",
|
|
39493
|
+
errorMessage: "Failed to fetch connectors"
|
|
39494
|
+
});
|
|
39495
|
+
const merged = mergeConnectors(localConnectors, backendConnectors);
|
|
39496
|
+
if (merged.length === 0) {
|
|
39497
|
+
M.info("No connectors configured for this app.");
|
|
39498
|
+
M.info(`Run ${theme.styles.bold("base44 connectors add")} to connect an integration.`);
|
|
39499
|
+
return { outroMessage: "" };
|
|
39500
|
+
}
|
|
39501
|
+
console.log();
|
|
39502
|
+
for (const connector of merged) console.log(formatConnectorLine(connector));
|
|
39503
|
+
console.log();
|
|
39504
|
+
const connected = merged.filter((c$1) => c$1.inBackend && c$1.status?.toLowerCase() === "active").length;
|
|
39505
|
+
const pending = merged.filter((c$1) => c$1.inLocal && !c$1.inBackend).length;
|
|
39506
|
+
let summary = `${connected} connected`;
|
|
39507
|
+
if (pending > 0) {
|
|
39508
|
+
summary += `, ${pending} pending`;
|
|
39509
|
+
M.info(`Run ${theme.styles.bold("base44 connectors push")} to connect pending integrations.`);
|
|
39510
|
+
}
|
|
39511
|
+
return { outroMessage: summary };
|
|
39512
|
+
}
|
|
39513
|
+
const connectorsListCommand = new Command("list").description("List all connected OAuth integrations").action(async () => {
|
|
39514
|
+
await runCommand(listConnectorsCommand, {
|
|
39515
|
+
requireAuth: true,
|
|
39516
|
+
requireAppConfig: true
|
|
39517
|
+
});
|
|
39518
|
+
});
|
|
39519
|
+
|
|
39520
|
+
//#endregion
|
|
39521
|
+
//#region src/cli/commands/connectors/push.ts
|
|
39522
|
+
function findPendingConnectors(local, backend) {
|
|
39523
|
+
const connectedTypes = new Set(backend.filter((c$1) => c$1.status.toLowerCase() === "active").map((c$1) => c$1.integrationType));
|
|
39524
|
+
return local.filter((c$1) => !connectedTypes.has(c$1.type)).map((c$1) => ({
|
|
39525
|
+
type: c$1.type,
|
|
39526
|
+
displayName: getIntegrationDisplayName(c$1.type),
|
|
39527
|
+
scopes: c$1.scopes
|
|
39528
|
+
}));
|
|
39529
|
+
}
|
|
39530
|
+
function findOrphanedConnectors(local, backend) {
|
|
39531
|
+
const localTypes = new Set(local.map((c$1) => c$1.type));
|
|
39532
|
+
return backend.filter((c$1) => c$1.status.toLowerCase() === "active").filter((c$1) => !localTypes.has(c$1.integrationType)).filter((c$1) => isValidIntegration(c$1.integrationType)).map((c$1) => ({
|
|
39533
|
+
type: c$1.integrationType,
|
|
39534
|
+
displayName: getIntegrationDisplayName(c$1.integrationType),
|
|
39535
|
+
accountEmail: (c$1.accountInfo?.email || c$1.accountInfo?.name) ?? void 0
|
|
39536
|
+
}));
|
|
39537
|
+
}
|
|
39538
|
+
async function connectSingleConnector(connector) {
|
|
39539
|
+
const { type, displayName, scopes } = connector;
|
|
39540
|
+
const initiateResponse = await initiateOAuth(type, scopes || null);
|
|
39541
|
+
if (initiateResponse.already_authorized) return { success: true };
|
|
39542
|
+
if (initiateResponse.error === "different_user") return {
|
|
39543
|
+
success: false,
|
|
39544
|
+
error: `Already connected by ${initiateResponse.other_user_email}`
|
|
39545
|
+
};
|
|
39546
|
+
if (!initiateResponse.redirect_url || !initiateResponse.connection_id) return {
|
|
39547
|
+
success: false,
|
|
39548
|
+
error: "Invalid response from server"
|
|
39549
|
+
};
|
|
39550
|
+
M.info(`Please authorize ${displayName} at:\n${theme.colors.links(initiateResponse.redirect_url)}`);
|
|
39551
|
+
return await runTask("Waiting for authorization...", async () => {
|
|
39552
|
+
return await waitForOAuthCompletion(type, initiateResponse.connection_id);
|
|
39553
|
+
}, {
|
|
39554
|
+
successMessage: "Authorization completed!",
|
|
39555
|
+
errorMessage: "Authorization failed"
|
|
39556
|
+
});
|
|
39557
|
+
}
|
|
39558
|
+
async function pushConnectorsCommand() {
|
|
39559
|
+
const { local: localConnectors, backend: backendConnectors } = await runTask("Checking connector status...", fetchConnectorState, {
|
|
39560
|
+
successMessage: "Status checked",
|
|
39561
|
+
errorMessage: "Failed to check status"
|
|
39562
|
+
});
|
|
39563
|
+
const pending = findPendingConnectors(localConnectors, backendConnectors);
|
|
39564
|
+
const orphaned = findOrphanedConnectors(localConnectors, backendConnectors);
|
|
39565
|
+
if (pending.length === 0 && orphaned.length === 0) return { outroMessage: "All connectors are in sync" };
|
|
39566
|
+
console.log();
|
|
39567
|
+
if (pending.length > 0) {
|
|
39568
|
+
M.info(`${pending.length} connector${pending.length === 1 ? "" : "s"} to connect:`);
|
|
39569
|
+
for (const c$1 of pending) console.log(` ${theme.colors.success("+")} ${c$1.displayName}`);
|
|
39570
|
+
}
|
|
39571
|
+
if (orphaned.length > 0) {
|
|
39572
|
+
M.info(`${orphaned.length} connector${orphaned.length === 1 ? "" : "s"} to remove:`);
|
|
39573
|
+
for (const c$1 of orphaned) {
|
|
39574
|
+
const accountInfo = c$1.accountEmail ? ` (${c$1.accountEmail})` : "";
|
|
39575
|
+
console.log(` ${theme.colors.error("-")} ${c$1.displayName}${accountInfo}`);
|
|
39576
|
+
}
|
|
39577
|
+
}
|
|
39578
|
+
console.log();
|
|
39579
|
+
const totalChanges = pending.length + orphaned.length;
|
|
39580
|
+
const shouldProceed = await ye({
|
|
39581
|
+
message: `Apply ${totalChanges} change${totalChanges === 1 ? "" : "s"}?`,
|
|
39582
|
+
initialValue: true
|
|
39583
|
+
});
|
|
39584
|
+
if (pD(shouldProceed) || !shouldProceed) return { outroMessage: "Cancelled" };
|
|
39585
|
+
let connected = 0;
|
|
39586
|
+
let removed = 0;
|
|
39587
|
+
let failed = 0;
|
|
39588
|
+
for (const connector of orphaned) try {
|
|
39589
|
+
await disconnectConnector(connector.type);
|
|
39590
|
+
M.success(`Removed ${connector.displayName}`);
|
|
39591
|
+
removed++;
|
|
39592
|
+
} catch (err) {
|
|
39593
|
+
M.error(`Failed to remove ${connector.displayName}: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
39594
|
+
failed++;
|
|
39595
|
+
}
|
|
39596
|
+
for (const connector of pending) {
|
|
39597
|
+
console.log();
|
|
39598
|
+
M.info(`Connecting ${theme.styles.bold(connector.displayName)}...`);
|
|
39599
|
+
const result = await connectSingleConnector(connector);
|
|
39600
|
+
if (result.success) {
|
|
39601
|
+
const accountInfo = result.accountEmail ? ` as ${result.accountEmail}` : "";
|
|
39602
|
+
M.success(`${connector.displayName} connected${accountInfo}`);
|
|
39603
|
+
connected++;
|
|
39604
|
+
} else {
|
|
39605
|
+
M.error(`${connector.displayName} failed: ${result.error}`);
|
|
39606
|
+
failed++;
|
|
39607
|
+
}
|
|
39608
|
+
}
|
|
39609
|
+
console.log();
|
|
39610
|
+
const parts = [];
|
|
39611
|
+
if (connected > 0) parts.push(`${connected} connected`);
|
|
39612
|
+
if (removed > 0) parts.push(`${removed} removed`);
|
|
39613
|
+
if (failed > 0) parts.push(`${failed} failed`);
|
|
39614
|
+
return { outroMessage: parts.join(", ") };
|
|
39615
|
+
}
|
|
39616
|
+
const connectorsPushCommand = new Command("push").description("Sync connectors with backend (connect new, remove missing)").action(async () => {
|
|
39617
|
+
await runCommand(pushConnectorsCommand, {
|
|
39618
|
+
requireAuth: true,
|
|
39619
|
+
requireAppConfig: true
|
|
39620
|
+
});
|
|
39621
|
+
});
|
|
39622
|
+
|
|
39623
|
+
//#endregion
|
|
39624
|
+
//#region src/cli/commands/connectors/remove.ts
|
|
39625
|
+
function mergeConnectorsForRemoval(local, backend) {
|
|
39626
|
+
const merged = /* @__PURE__ */ new Map();
|
|
39627
|
+
for (const connector of local) merged.set(connector.type, {
|
|
39628
|
+
type: connector.type,
|
|
39629
|
+
displayName: getIntegrationDisplayName(connector.type),
|
|
39630
|
+
inLocal: true,
|
|
39631
|
+
inBackend: false
|
|
39632
|
+
});
|
|
39633
|
+
for (const connector of backend) {
|
|
39634
|
+
if (!isValidIntegration(connector.integrationType)) continue;
|
|
39635
|
+
const existing = merged.get(connector.integrationType);
|
|
39636
|
+
const accountEmail = (connector.accountInfo?.email || connector.accountInfo?.name) ?? void 0;
|
|
39637
|
+
if (existing) {
|
|
39638
|
+
existing.inBackend = true;
|
|
39639
|
+
existing.accountEmail = accountEmail;
|
|
39640
|
+
} else merged.set(connector.integrationType, {
|
|
39641
|
+
type: connector.integrationType,
|
|
39642
|
+
displayName: getIntegrationDisplayName(connector.integrationType),
|
|
39643
|
+
inLocal: false,
|
|
39644
|
+
inBackend: true,
|
|
39645
|
+
accountEmail
|
|
39646
|
+
});
|
|
39647
|
+
}
|
|
39648
|
+
return Array.from(merged.values());
|
|
39649
|
+
}
|
|
39650
|
+
function validateConnectorType(type, merged) {
|
|
39651
|
+
if (!isValidIntegration(type)) throw new Error(`Invalid connector type: ${type}`);
|
|
39652
|
+
const connector = merged.find((c$1) => c$1.type === type);
|
|
39653
|
+
if (!connector) throw new Error(`No ${getIntegrationDisplayName(type)} connector found`);
|
|
39654
|
+
return {
|
|
39655
|
+
type,
|
|
39656
|
+
connector
|
|
39657
|
+
};
|
|
39658
|
+
}
|
|
39659
|
+
async function promptForConnectorToRemove(connectors) {
|
|
39660
|
+
const selected = await ve({
|
|
39661
|
+
message: "Select a connector to remove:",
|
|
39662
|
+
options: connectors.map((c$1) => {
|
|
39663
|
+
let label = c$1.displayName;
|
|
39664
|
+
if (c$1.accountEmail) label += ` (${c$1.accountEmail})`;
|
|
39665
|
+
else if (c$1.inLocal && !c$1.inBackend) label += " (not connected)";
|
|
39666
|
+
return {
|
|
39667
|
+
value: c$1.type,
|
|
39668
|
+
label
|
|
39669
|
+
};
|
|
39670
|
+
})
|
|
39671
|
+
});
|
|
39672
|
+
if (pD(selected)) {
|
|
39673
|
+
xe("Operation cancelled.");
|
|
39674
|
+
process.exit(0);
|
|
39675
|
+
}
|
|
39676
|
+
return {
|
|
39677
|
+
type: selected,
|
|
39678
|
+
connector: connectors.find((c$1) => c$1.type === selected)
|
|
39679
|
+
};
|
|
39680
|
+
}
|
|
39681
|
+
async function removeConnectorCommand(integrationType, options = {}) {
|
|
39682
|
+
const isHardDelete = options.hard === true;
|
|
39683
|
+
const { local: localConnectors, backend: backendConnectors } = await runTask("Fetching connectors...", fetchConnectorState, {
|
|
39684
|
+
successMessage: "Connectors loaded",
|
|
39685
|
+
errorMessage: "Failed to fetch connectors"
|
|
39686
|
+
});
|
|
39687
|
+
const merged = mergeConnectorsForRemoval(localConnectors, backendConnectors);
|
|
39688
|
+
if (merged.length === 0) return { outroMessage: "No connectors to remove" };
|
|
39689
|
+
const { type: selectedType, connector: selectedConnector } = integrationType ? validateConnectorType(integrationType, merged) : await promptForConnectorToRemove(merged);
|
|
39690
|
+
const displayName = getIntegrationDisplayName(selectedType);
|
|
39691
|
+
const accountInfo = selectedConnector.accountEmail ? ` (${selectedConnector.accountEmail})` : "";
|
|
39692
|
+
if (!options.yes) {
|
|
39693
|
+
const shouldRemove = await ye({
|
|
39694
|
+
message: `${isHardDelete ? "Permanently remove" : "Remove"} ${displayName}${accountInfo}?`,
|
|
39695
|
+
initialValue: false
|
|
39696
|
+
});
|
|
39697
|
+
if (pD(shouldRemove) || !shouldRemove) {
|
|
39698
|
+
xe("Operation cancelled.");
|
|
39699
|
+
process.exit(0);
|
|
39700
|
+
}
|
|
39701
|
+
}
|
|
39702
|
+
await runTask(`Removing ${displayName}...`, async () => {
|
|
39703
|
+
if (selectedConnector.inBackend) if (isHardDelete) await removeConnector(selectedType);
|
|
39704
|
+
else await disconnectConnector(selectedType);
|
|
39705
|
+
await removeLocalConnector(selectedType);
|
|
39706
|
+
}, {
|
|
39707
|
+
successMessage: `${displayName} removed`,
|
|
39708
|
+
errorMessage: `Failed to remove ${displayName}`
|
|
39709
|
+
});
|
|
39710
|
+
return { outroMessage: `Successfully removed ${theme.styles.bold(displayName)}` };
|
|
39711
|
+
}
|
|
39712
|
+
const connectorsRemoveCommand = new Command("remove").argument("[type]", "Integration type to remove (e.g., slack, notion)").option("--hard", "Permanently remove the connector (cannot be undone)").option("-y, --yes", "Skip confirmation prompt").description("Remove an OAuth integration").action(async (type, options) => {
|
|
39713
|
+
await runCommand(() => removeConnectorCommand(type, options), {
|
|
39714
|
+
requireAuth: true,
|
|
39715
|
+
requireAppConfig: true
|
|
39716
|
+
});
|
|
39717
|
+
});
|
|
39718
|
+
|
|
39719
|
+
//#endregion
|
|
39720
|
+
//#region src/cli/commands/connectors/index.ts
|
|
39721
|
+
const connectorsCommand = new Command("connectors").description("Manage OAuth connectors").addCommand(connectorsAddCommand).addCommand(connectorsListCommand).addCommand(connectorsPushCommand).addCommand(connectorsRemoveCommand);
|
|
39722
|
+
|
|
38934
39723
|
//#endregion
|
|
38935
39724
|
//#region package.json
|
|
38936
|
-
var version = "0.0.
|
|
39725
|
+
var version = "0.0.17";
|
|
38937
39726
|
|
|
38938
39727
|
//#endregion
|
|
38939
|
-
//#region src/cli/
|
|
39728
|
+
//#region src/cli/program.ts
|
|
38940
39729
|
const program = new Command();
|
|
38941
39730
|
program.name("base44").description("Base44 CLI - Unified interface for managing Base44 applications").version(version);
|
|
38942
39731
|
program.configureHelp({ sortSubcommands: true });
|
|
@@ -38950,7 +39739,7 @@ program.addCommand(linkCommand);
|
|
|
38950
39739
|
program.addCommand(entitiesPushCommand);
|
|
38951
39740
|
program.addCommand(functionsDeployCommand);
|
|
38952
39741
|
program.addCommand(siteDeployCommand);
|
|
38953
|
-
program.
|
|
39742
|
+
program.addCommand(connectorsCommand);
|
|
38954
39743
|
|
|
38955
39744
|
//#endregion
|
|
38956
|
-
export {
|
|
39745
|
+
export { CLIExitError, program };
|