@base44-preview/cli 0.0.16-pr.95.3b2ce0c → 0.0.17-pr.104.ad47aa8
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 +56 -2
- package/dist/cli/index.js +936 -148
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { EventEmitter, addAbortListener, on, once, setMaxListeners } from "node:
|
|
|
4
4
|
import childProcess, { ChildProcess, execFile, spawn, spawnSync } from "node:child_process";
|
|
5
5
|
import path, { basename, dirname, join, posix, resolve, win32 } from "node:path";
|
|
6
6
|
import fs, { appendFileSync, createReadStream, createWriteStream, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
7
|
-
import
|
|
7
|
+
import process$1, { execArgv, execPath, hrtime, platform, stdin, stdout } from "node:process";
|
|
8
8
|
import { aborted, callbackify, debuglog, inspect, promisify, stripVTControlCharacters } from "node:util";
|
|
9
9
|
import * as g from "node:readline";
|
|
10
10
|
import O from "node:readline";
|
|
@@ -894,7 +894,7 @@ var require_command = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
894
894
|
const childProcess$1 = __require("node:child_process");
|
|
895
895
|
const path$15 = __require("node:path");
|
|
896
896
|
const fs$10 = __require("node:fs");
|
|
897
|
-
const process$
|
|
897
|
+
const process$4 = __require("node:process");
|
|
898
898
|
const { Argument, humanReadableArgName } = require_argument();
|
|
899
899
|
const { CommanderError } = require_error$1();
|
|
900
900
|
const { Help } = require_help();
|
|
@@ -945,10 +945,10 @@ var require_command = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
945
945
|
this._showHelpAfterError = false;
|
|
946
946
|
this._showSuggestionAfterError = true;
|
|
947
947
|
this._outputConfiguration = {
|
|
948
|
-
writeOut: (str) => process$
|
|
949
|
-
writeErr: (str) => process$
|
|
950
|
-
getOutHelpWidth: () => process$
|
|
951
|
-
getErrHelpWidth: () => process$
|
|
948
|
+
writeOut: (str) => process$4.stdout.write(str),
|
|
949
|
+
writeErr: (str) => process$4.stderr.write(str),
|
|
950
|
+
getOutHelpWidth: () => process$4.stdout.isTTY ? process$4.stdout.columns : void 0,
|
|
951
|
+
getErrHelpWidth: () => process$4.stderr.isTTY ? process$4.stderr.columns : void 0,
|
|
952
952
|
outputError: (str, write) => write(str)
|
|
953
953
|
};
|
|
954
954
|
this._hidden = false;
|
|
@@ -1302,7 +1302,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1302
1302
|
*/
|
|
1303
1303
|
_exit(exitCode, code$1, message) {
|
|
1304
1304
|
if (this._exitCallback) this._exitCallback(new CommanderError(exitCode, code$1, message));
|
|
1305
|
-
process$
|
|
1305
|
+
process$4.exit(exitCode);
|
|
1306
1306
|
}
|
|
1307
1307
|
/**
|
|
1308
1308
|
* Register callback `fn` for the command.
|
|
@@ -1641,11 +1641,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1641
1641
|
if (argv !== void 0 && !Array.isArray(argv)) throw new Error("first parameter to parse must be array or undefined");
|
|
1642
1642
|
parseOptions = parseOptions || {};
|
|
1643
1643
|
if (argv === void 0 && parseOptions.from === void 0) {
|
|
1644
|
-
if (process$
|
|
1645
|
-
const execArgv$1 = process$
|
|
1644
|
+
if (process$4.versions?.electron) parseOptions.from = "electron";
|
|
1645
|
+
const execArgv$1 = process$4.execArgv ?? [];
|
|
1646
1646
|
if (execArgv$1.includes("-e") || execArgv$1.includes("--eval") || execArgv$1.includes("-p") || execArgv$1.includes("--print")) parseOptions.from = "eval";
|
|
1647
1647
|
}
|
|
1648
|
-
if (argv === void 0) argv = process$
|
|
1648
|
+
if (argv === void 0) argv = process$4.argv;
|
|
1649
1649
|
this.rawArgs = argv.slice();
|
|
1650
1650
|
let userArgs;
|
|
1651
1651
|
switch (parseOptions.from) {
|
|
@@ -1655,7 +1655,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1655
1655
|
userArgs = argv.slice(2);
|
|
1656
1656
|
break;
|
|
1657
1657
|
case "electron":
|
|
1658
|
-
if (process$
|
|
1658
|
+
if (process$4.defaultApp) {
|
|
1659
1659
|
this._scriptPath = argv[1];
|
|
1660
1660
|
userArgs = argv.slice(2);
|
|
1661
1661
|
} else userArgs = argv.slice(1);
|
|
@@ -1769,15 +1769,15 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1769
1769
|
}
|
|
1770
1770
|
launchWithNode = sourceExt.includes(path$15.extname(executableFile));
|
|
1771
1771
|
let proc$1;
|
|
1772
|
-
if (process$
|
|
1772
|
+
if (process$4.platform !== "win32") if (launchWithNode) {
|
|
1773
1773
|
args.unshift(executableFile);
|
|
1774
|
-
args = incrementNodeInspectorPort(process$
|
|
1775
|
-
proc$1 = childProcess$1.spawn(process$
|
|
1774
|
+
args = incrementNodeInspectorPort(process$4.execArgv).concat(args);
|
|
1775
|
+
proc$1 = childProcess$1.spawn(process$4.argv[0], args, { stdio: "inherit" });
|
|
1776
1776
|
} else proc$1 = childProcess$1.spawn(executableFile, args, { stdio: "inherit" });
|
|
1777
1777
|
else {
|
|
1778
1778
|
args.unshift(executableFile);
|
|
1779
|
-
args = incrementNodeInspectorPort(process$
|
|
1780
|
-
proc$1 = childProcess$1.spawn(process$
|
|
1779
|
+
args = incrementNodeInspectorPort(process$4.execArgv).concat(args);
|
|
1780
|
+
proc$1 = childProcess$1.spawn(process$4.execPath, args, { stdio: "inherit" });
|
|
1781
1781
|
}
|
|
1782
1782
|
if (!proc$1.killed) [
|
|
1783
1783
|
"SIGUSR1",
|
|
@@ -1786,14 +1786,14 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1786
1786
|
"SIGINT",
|
|
1787
1787
|
"SIGHUP"
|
|
1788
1788
|
].forEach((signal) => {
|
|
1789
|
-
process$
|
|
1789
|
+
process$4.on(signal, () => {
|
|
1790
1790
|
if (proc$1.killed === false && proc$1.exitCode === null) proc$1.kill(signal);
|
|
1791
1791
|
});
|
|
1792
1792
|
});
|
|
1793
1793
|
const exitCallback = this._exitCallback;
|
|
1794
1794
|
proc$1.on("close", (code$1) => {
|
|
1795
1795
|
code$1 = code$1 ?? 1;
|
|
1796
|
-
if (!exitCallback) process$
|
|
1796
|
+
if (!exitCallback) process$4.exit(code$1);
|
|
1797
1797
|
else exitCallback(new CommanderError(code$1, "commander.executeSubCommandAsync", "(close)"));
|
|
1798
1798
|
});
|
|
1799
1799
|
proc$1.on("error", (err) => {
|
|
@@ -1805,7 +1805,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1805
1805
|
- ${executableDirMessage}`;
|
|
1806
1806
|
throw new Error(executableMissing);
|
|
1807
1807
|
} else if (err.code === "EACCES") throw new Error(`'${executableFile}' not executable`);
|
|
1808
|
-
if (!exitCallback) process$
|
|
1808
|
+
if (!exitCallback) process$4.exit(1);
|
|
1809
1809
|
else {
|
|
1810
1810
|
const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
|
|
1811
1811
|
wrappedError.nestedError = err;
|
|
@@ -2211,13 +2211,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2211
2211
|
*/
|
|
2212
2212
|
_parseOptionsEnv() {
|
|
2213
2213
|
this.options.forEach((option) => {
|
|
2214
|
-
if (option.envVar && option.envVar in process$
|
|
2214
|
+
if (option.envVar && option.envVar in process$4.env) {
|
|
2215
2215
|
const optionKey = option.attributeName();
|
|
2216
2216
|
if (this.getOptionValue(optionKey) === void 0 || [
|
|
2217
2217
|
"default",
|
|
2218
2218
|
"config",
|
|
2219
2219
|
"env"
|
|
2220
|
-
].includes(this.getOptionValueSource(optionKey))) if (option.required || option.optional) this.emit(`optionEnv:${option.name()}`, process$
|
|
2220
|
+
].includes(this.getOptionValueSource(optionKey))) if (option.required || option.optional) this.emit(`optionEnv:${option.name()}`, process$4.env[option.envVar]);
|
|
2221
2221
|
else this.emit(`optionEnv:${option.name()}`);
|
|
2222
2222
|
}
|
|
2223
2223
|
});
|
|
@@ -2596,7 +2596,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2596
2596
|
*/
|
|
2597
2597
|
help(contextOptions) {
|
|
2598
2598
|
this.outputHelp(contextOptions);
|
|
2599
|
-
let exitCode = process$
|
|
2599
|
+
let exitCode = process$4.exitCode || 0;
|
|
2600
2600
|
if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) exitCode = 1;
|
|
2601
2601
|
this._exit(exitCode, "commander.help", "(outputHelp)");
|
|
2602
2602
|
}
|
|
@@ -2712,16 +2712,16 @@ var require_src = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
2712
2712
|
const CSI = `${ESC}[`;
|
|
2713
2713
|
const beep = "\x07";
|
|
2714
2714
|
const cursor = {
|
|
2715
|
-
to(x$2, y$
|
|
2716
|
-
if (!y$
|
|
2717
|
-
return `${CSI}${y$
|
|
2715
|
+
to(x$2, y$1) {
|
|
2716
|
+
if (!y$1) return `${CSI}${x$2 + 1}G`;
|
|
2717
|
+
return `${CSI}${y$1 + 1};${x$2 + 1}H`;
|
|
2718
2718
|
},
|
|
2719
|
-
move(x$2, y$
|
|
2719
|
+
move(x$2, y$1) {
|
|
2720
2720
|
let ret = "";
|
|
2721
2721
|
if (x$2 < 0) ret += `${CSI}${-x$2}D`;
|
|
2722
2722
|
else if (x$2 > 0) ret += `${CSI}${x$2}C`;
|
|
2723
|
-
if (y$
|
|
2724
|
-
else if (y$
|
|
2723
|
+
if (y$1 < 0) ret += `${CSI}${-y$1}A`;
|
|
2724
|
+
else if (y$1 > 0) ret += `${CSI}${y$1}B`;
|
|
2725
2725
|
return ret;
|
|
2726
2726
|
},
|
|
2727
2727
|
up: (count$1 = 1) => `${CSI}${count$1}A`,
|
|
@@ -3031,13 +3031,13 @@ function rD() {
|
|
|
3031
3031
|
}
|
|
3032
3032
|
}), r;
|
|
3033
3033
|
}
|
|
3034
|
-
const ED = rD(), d$1 = new Set(["\x1B", ""]), oD = 39, y
|
|
3034
|
+
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
3035
|
const F$1 = [...u$2];
|
|
3036
3036
|
let s = !1, i$1 = !1, D$1 = p(P$1(e$1[e$1.length - 1]));
|
|
3037
3037
|
for (const [C$1, n$1] of F$1.entries()) {
|
|
3038
3038
|
const E = p(n$1);
|
|
3039
3039
|
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
|
|
3040
|
+
i$1 ? n$1 === y && (s = !1, i$1 = !1) : n$1 === G$1 && (s = !1);
|
|
3041
3041
|
continue;
|
|
3042
3042
|
}
|
|
3043
3043
|
D$1 += E, D$1 === t && C$1 < F$1.length - 1 && (e$1.push(""), D$1 = 0);
|
|
@@ -3079,7 +3079,7 @@ const ED = rD(), d$1 = new Set(["\x1B", ""]), oD = 39, y$1 = "\x07", V$1 = "["
|
|
|
3079
3079
|
`)];
|
|
3080
3080
|
for (const [E, a$1] of n$1.entries()) {
|
|
3081
3081
|
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
|
|
3082
|
+
const { groups: c$1 } = (/* @__PURE__ */ new RegExp(`(?:\\${V$1}(?<code>\\d+)m|\\${_$1}(?<uri>.*)${y})`)).exec(n$1.slice(E).join("")) || { groups: {} };
|
|
3083
3083
|
if (c$1.code !== void 0) {
|
|
3084
3084
|
const f = Number.parseFloat(c$1.code);
|
|
3085
3085
|
s = f === oD ? void 0 : f;
|
|
@@ -3480,7 +3480,7 @@ var RD = class extends x$1 {
|
|
|
3480
3480
|
//#endregion
|
|
3481
3481
|
//#region node_modules/@clack/prompts/dist/index.mjs
|
|
3482
3482
|
function ce() {
|
|
3483
|
-
return
|
|
3483
|
+
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
3484
|
}
|
|
3485
3485
|
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
3486
|
switch (t) {
|
|
@@ -5819,6 +5819,97 @@ function handleTupleResult(result, final, index) {
|
|
|
5819
5819
|
if (result.issues.length) final.issues.push(...prefixIssues(index, result.issues));
|
|
5820
5820
|
final.value[index] = result.value;
|
|
5821
5821
|
}
|
|
5822
|
+
const $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
5823
|
+
$ZodType.init(inst, def);
|
|
5824
|
+
inst._zod.parse = (payload, ctx) => {
|
|
5825
|
+
const input = payload.value;
|
|
5826
|
+
if (!isPlainObject$1(input)) {
|
|
5827
|
+
payload.issues.push({
|
|
5828
|
+
expected: "record",
|
|
5829
|
+
code: "invalid_type",
|
|
5830
|
+
input,
|
|
5831
|
+
inst
|
|
5832
|
+
});
|
|
5833
|
+
return payload;
|
|
5834
|
+
}
|
|
5835
|
+
const proms = [];
|
|
5836
|
+
const values = def.keyType._zod.values;
|
|
5837
|
+
if (values) {
|
|
5838
|
+
payload.value = {};
|
|
5839
|
+
const recordKeys = /* @__PURE__ */ new Set();
|
|
5840
|
+
for (const key of values) if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
5841
|
+
recordKeys.add(typeof key === "number" ? key.toString() : key);
|
|
5842
|
+
const result = def.valueType._zod.run({
|
|
5843
|
+
value: input[key],
|
|
5844
|
+
issues: []
|
|
5845
|
+
}, ctx);
|
|
5846
|
+
if (result instanceof Promise) proms.push(result.then((result$1) => {
|
|
5847
|
+
if (result$1.issues.length) payload.issues.push(...prefixIssues(key, result$1.issues));
|
|
5848
|
+
payload.value[key] = result$1.value;
|
|
5849
|
+
}));
|
|
5850
|
+
else {
|
|
5851
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
5852
|
+
payload.value[key] = result.value;
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
let unrecognized;
|
|
5856
|
+
for (const key in input) if (!recordKeys.has(key)) {
|
|
5857
|
+
unrecognized = unrecognized ?? [];
|
|
5858
|
+
unrecognized.push(key);
|
|
5859
|
+
}
|
|
5860
|
+
if (unrecognized && unrecognized.length > 0) payload.issues.push({
|
|
5861
|
+
code: "unrecognized_keys",
|
|
5862
|
+
input,
|
|
5863
|
+
inst,
|
|
5864
|
+
keys: unrecognized
|
|
5865
|
+
});
|
|
5866
|
+
} else {
|
|
5867
|
+
payload.value = {};
|
|
5868
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
5869
|
+
if (key === "__proto__") continue;
|
|
5870
|
+
let keyResult = def.keyType._zod.run({
|
|
5871
|
+
value: key,
|
|
5872
|
+
issues: []
|
|
5873
|
+
}, ctx);
|
|
5874
|
+
if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
5875
|
+
if (typeof key === "string" && number$1.test(key) && keyResult.issues.length && keyResult.issues.some((iss) => iss.code === "invalid_type" && iss.expected === "number")) {
|
|
5876
|
+
const retryResult = def.keyType._zod.run({
|
|
5877
|
+
value: Number(key),
|
|
5878
|
+
issues: []
|
|
5879
|
+
}, ctx);
|
|
5880
|
+
if (retryResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
5881
|
+
if (retryResult.issues.length === 0) keyResult = retryResult;
|
|
5882
|
+
}
|
|
5883
|
+
if (keyResult.issues.length) {
|
|
5884
|
+
if (def.mode === "loose") payload.value[key] = input[key];
|
|
5885
|
+
else payload.issues.push({
|
|
5886
|
+
code: "invalid_key",
|
|
5887
|
+
origin: "record",
|
|
5888
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
5889
|
+
input: key,
|
|
5890
|
+
path: [key],
|
|
5891
|
+
inst
|
|
5892
|
+
});
|
|
5893
|
+
continue;
|
|
5894
|
+
}
|
|
5895
|
+
const result = def.valueType._zod.run({
|
|
5896
|
+
value: input[key],
|
|
5897
|
+
issues: []
|
|
5898
|
+
}, ctx);
|
|
5899
|
+
if (result instanceof Promise) proms.push(result.then((result$1) => {
|
|
5900
|
+
if (result$1.issues.length) payload.issues.push(...prefixIssues(key, result$1.issues));
|
|
5901
|
+
payload.value[keyResult.value] = result$1.value;
|
|
5902
|
+
}));
|
|
5903
|
+
else {
|
|
5904
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
5905
|
+
payload.value[keyResult.value] = result.value;
|
|
5906
|
+
}
|
|
5907
|
+
}
|
|
5908
|
+
}
|
|
5909
|
+
if (proms.length) return Promise.all(proms).then(() => payload);
|
|
5910
|
+
return payload;
|
|
5911
|
+
};
|
|
5912
|
+
});
|
|
5822
5913
|
const $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
5823
5914
|
$ZodType.init(inst, def);
|
|
5824
5915
|
const values = getEnumValues(def.entries);
|
|
@@ -6654,7 +6745,7 @@ function initializeContext(params) {
|
|
|
6654
6745
|
external: params?.external ?? void 0
|
|
6655
6746
|
};
|
|
6656
6747
|
}
|
|
6657
|
-
function process$
|
|
6748
|
+
function process$3(schema, ctx, _params = {
|
|
6658
6749
|
path: [],
|
|
6659
6750
|
schemaPath: []
|
|
6660
6751
|
}) {
|
|
@@ -6691,7 +6782,7 @@ function process$2(schema, ctx, _params = {
|
|
|
6691
6782
|
const parent = schema._zod.parent;
|
|
6692
6783
|
if (parent) {
|
|
6693
6784
|
if (!result.ref) result.ref = parent;
|
|
6694
|
-
process$
|
|
6785
|
+
process$3(parent, ctx, params);
|
|
6695
6786
|
ctx.seen.get(parent).isParent = true;
|
|
6696
6787
|
}
|
|
6697
6788
|
}
|
|
@@ -6903,7 +6994,7 @@ const createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
|
|
6903
6994
|
...params,
|
|
6904
6995
|
processors
|
|
6905
6996
|
});
|
|
6906
|
-
process$
|
|
6997
|
+
process$3(schema, ctx);
|
|
6907
6998
|
extractDefs(ctx, schema);
|
|
6908
6999
|
return finalize(ctx, schema);
|
|
6909
7000
|
};
|
|
@@ -6915,7 +7006,7 @@ const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params)
|
|
|
6915
7006
|
io,
|
|
6916
7007
|
processors
|
|
6917
7008
|
});
|
|
6918
|
-
process$
|
|
7009
|
+
process$3(schema, ctx);
|
|
6919
7010
|
extractDefs(ctx, schema);
|
|
6920
7011
|
return finalize(ctx, schema);
|
|
6921
7012
|
};
|
|
@@ -7002,7 +7093,7 @@ const arrayProcessor = (schema, ctx, _json, params) => {
|
|
|
7002
7093
|
if (typeof minimum === "number") json.minItems = minimum;
|
|
7003
7094
|
if (typeof maximum === "number") json.maxItems = maximum;
|
|
7004
7095
|
json.type = "array";
|
|
7005
|
-
json.items = process$
|
|
7096
|
+
json.items = process$3(def.element, ctx, {
|
|
7006
7097
|
...params,
|
|
7007
7098
|
path: [...params.path, "items"]
|
|
7008
7099
|
});
|
|
@@ -7013,7 +7104,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
7013
7104
|
json.type = "object";
|
|
7014
7105
|
json.properties = {};
|
|
7015
7106
|
const shape = def.shape;
|
|
7016
|
-
for (const key in shape) json.properties[key] = process$
|
|
7107
|
+
for (const key in shape) json.properties[key] = process$3(shape[key], ctx, {
|
|
7017
7108
|
...params,
|
|
7018
7109
|
path: [
|
|
7019
7110
|
...params.path,
|
|
@@ -7031,7 +7122,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
7031
7122
|
if (def.catchall?._zod.def.type === "never") json.additionalProperties = false;
|
|
7032
7123
|
else if (!def.catchall) {
|
|
7033
7124
|
if (ctx.io === "output") json.additionalProperties = false;
|
|
7034
|
-
} else if (def.catchall) json.additionalProperties = process$
|
|
7125
|
+
} else if (def.catchall) json.additionalProperties = process$3(def.catchall, ctx, {
|
|
7035
7126
|
...params,
|
|
7036
7127
|
path: [...params.path, "additionalProperties"]
|
|
7037
7128
|
});
|
|
@@ -7039,7 +7130,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
7039
7130
|
const unionProcessor = (schema, ctx, json, params) => {
|
|
7040
7131
|
const def = schema._zod.def;
|
|
7041
7132
|
const isExclusive = def.inclusive === false;
|
|
7042
|
-
const options = def.options.map((x$2, i$1) => process$
|
|
7133
|
+
const options = def.options.map((x$2, i$1) => process$3(x$2, ctx, {
|
|
7043
7134
|
...params,
|
|
7044
7135
|
path: [
|
|
7045
7136
|
...params.path,
|
|
@@ -7052,7 +7143,7 @@ const unionProcessor = (schema, ctx, json, params) => {
|
|
|
7052
7143
|
};
|
|
7053
7144
|
const intersectionProcessor = (schema, ctx, json, params) => {
|
|
7054
7145
|
const def = schema._zod.def;
|
|
7055
|
-
const a$1 = process$
|
|
7146
|
+
const a$1 = process$3(def.left, ctx, {
|
|
7056
7147
|
...params,
|
|
7057
7148
|
path: [
|
|
7058
7149
|
...params.path,
|
|
@@ -7060,7 +7151,7 @@ const intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
7060
7151
|
0
|
|
7061
7152
|
]
|
|
7062
7153
|
});
|
|
7063
|
-
const b$2 = process$
|
|
7154
|
+
const b$2 = process$3(def.right, ctx, {
|
|
7064
7155
|
...params,
|
|
7065
7156
|
path: [
|
|
7066
7157
|
...params.path,
|
|
@@ -7077,7 +7168,7 @@ const tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
7077
7168
|
json.type = "array";
|
|
7078
7169
|
const prefixPath$1 = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
|
|
7079
7170
|
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$
|
|
7171
|
+
const prefixItems = def.items.map((x$2, i$1) => process$3(x$2, ctx, {
|
|
7081
7172
|
...params,
|
|
7082
7173
|
path: [
|
|
7083
7174
|
...params.path,
|
|
@@ -7085,7 +7176,7 @@ const tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
7085
7176
|
i$1
|
|
7086
7177
|
]
|
|
7087
7178
|
}));
|
|
7088
|
-
const rest = def.rest ? process$
|
|
7179
|
+
const rest = def.rest ? process$3(def.rest, ctx, {
|
|
7089
7180
|
...params,
|
|
7090
7181
|
path: [
|
|
7091
7182
|
...params.path,
|
|
@@ -7109,9 +7200,42 @@ const tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
7109
7200
|
if (typeof minimum === "number") json.minItems = minimum;
|
|
7110
7201
|
if (typeof maximum === "number") json.maxItems = maximum;
|
|
7111
7202
|
};
|
|
7203
|
+
const recordProcessor = (schema, ctx, _json, params) => {
|
|
7204
|
+
const json = _json;
|
|
7205
|
+
const def = schema._zod.def;
|
|
7206
|
+
json.type = "object";
|
|
7207
|
+
const keyType = def.keyType;
|
|
7208
|
+
const patterns = keyType._zod.bag?.patterns;
|
|
7209
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
7210
|
+
const valueSchema = process$3(def.valueType, ctx, {
|
|
7211
|
+
...params,
|
|
7212
|
+
path: [
|
|
7213
|
+
...params.path,
|
|
7214
|
+
"patternProperties",
|
|
7215
|
+
"*"
|
|
7216
|
+
]
|
|
7217
|
+
});
|
|
7218
|
+
json.patternProperties = {};
|
|
7219
|
+
for (const pattern of patterns) json.patternProperties[pattern.source] = valueSchema;
|
|
7220
|
+
} else {
|
|
7221
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") json.propertyNames = process$3(def.keyType, ctx, {
|
|
7222
|
+
...params,
|
|
7223
|
+
path: [...params.path, "propertyNames"]
|
|
7224
|
+
});
|
|
7225
|
+
json.additionalProperties = process$3(def.valueType, ctx, {
|
|
7226
|
+
...params,
|
|
7227
|
+
path: [...params.path, "additionalProperties"]
|
|
7228
|
+
});
|
|
7229
|
+
}
|
|
7230
|
+
const keyValues = keyType._zod.values;
|
|
7231
|
+
if (keyValues) {
|
|
7232
|
+
const validKeyValues = [...keyValues].filter((v$1) => typeof v$1 === "string" || typeof v$1 === "number");
|
|
7233
|
+
if (validKeyValues.length > 0) json.required = validKeyValues;
|
|
7234
|
+
}
|
|
7235
|
+
};
|
|
7112
7236
|
const nullableProcessor = (schema, ctx, json, params) => {
|
|
7113
7237
|
const def = schema._zod.def;
|
|
7114
|
-
const inner = process$
|
|
7238
|
+
const inner = process$3(def.innerType, ctx, params);
|
|
7115
7239
|
const seen = ctx.seen.get(schema);
|
|
7116
7240
|
if (ctx.target === "openapi-3.0") {
|
|
7117
7241
|
seen.ref = def.innerType;
|
|
@@ -7120,27 +7244,27 @@ const nullableProcessor = (schema, ctx, json, params) => {
|
|
|
7120
7244
|
};
|
|
7121
7245
|
const nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
7122
7246
|
const def = schema._zod.def;
|
|
7123
|
-
process$
|
|
7247
|
+
process$3(def.innerType, ctx, params);
|
|
7124
7248
|
const seen = ctx.seen.get(schema);
|
|
7125
7249
|
seen.ref = def.innerType;
|
|
7126
7250
|
};
|
|
7127
7251
|
const defaultProcessor = (schema, ctx, json, params) => {
|
|
7128
7252
|
const def = schema._zod.def;
|
|
7129
|
-
process$
|
|
7253
|
+
process$3(def.innerType, ctx, params);
|
|
7130
7254
|
const seen = ctx.seen.get(schema);
|
|
7131
7255
|
seen.ref = def.innerType;
|
|
7132
7256
|
json.default = JSON.parse(JSON.stringify(def.defaultValue));
|
|
7133
7257
|
};
|
|
7134
7258
|
const prefaultProcessor = (schema, ctx, json, params) => {
|
|
7135
7259
|
const def = schema._zod.def;
|
|
7136
|
-
process$
|
|
7260
|
+
process$3(def.innerType, ctx, params);
|
|
7137
7261
|
const seen = ctx.seen.get(schema);
|
|
7138
7262
|
seen.ref = def.innerType;
|
|
7139
7263
|
if (ctx.io === "input") json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
|
|
7140
7264
|
};
|
|
7141
7265
|
const catchProcessor = (schema, ctx, json, params) => {
|
|
7142
7266
|
const def = schema._zod.def;
|
|
7143
|
-
process$
|
|
7267
|
+
process$3(def.innerType, ctx, params);
|
|
7144
7268
|
const seen = ctx.seen.get(schema);
|
|
7145
7269
|
seen.ref = def.innerType;
|
|
7146
7270
|
let catchValue;
|
|
@@ -7154,20 +7278,20 @@ const catchProcessor = (schema, ctx, json, params) => {
|
|
|
7154
7278
|
const pipeProcessor = (schema, ctx, _json, params) => {
|
|
7155
7279
|
const def = schema._zod.def;
|
|
7156
7280
|
const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
|
|
7157
|
-
process$
|
|
7281
|
+
process$3(innerType, ctx, params);
|
|
7158
7282
|
const seen = ctx.seen.get(schema);
|
|
7159
7283
|
seen.ref = innerType;
|
|
7160
7284
|
};
|
|
7161
7285
|
const readonlyProcessor = (schema, ctx, json, params) => {
|
|
7162
7286
|
const def = schema._zod.def;
|
|
7163
|
-
process$
|
|
7287
|
+
process$3(def.innerType, ctx, params);
|
|
7164
7288
|
const seen = ctx.seen.get(schema);
|
|
7165
7289
|
seen.ref = def.innerType;
|
|
7166
7290
|
json.readOnly = true;
|
|
7167
7291
|
};
|
|
7168
7292
|
const optionalProcessor = (schema, ctx, _json, params) => {
|
|
7169
7293
|
const def = schema._zod.def;
|
|
7170
|
-
process$
|
|
7294
|
+
process$3(def.innerType, ctx, params);
|
|
7171
7295
|
const seen = ctx.seen.get(schema);
|
|
7172
7296
|
seen.ref = def.innerType;
|
|
7173
7297
|
};
|
|
@@ -7638,6 +7762,21 @@ function tuple(items, _paramsOrRest, _params) {
|
|
|
7638
7762
|
...normalizeParams(params)
|
|
7639
7763
|
});
|
|
7640
7764
|
}
|
|
7765
|
+
const ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
7766
|
+
$ZodRecord.init(inst, def);
|
|
7767
|
+
ZodType.init(inst, def);
|
|
7768
|
+
inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
|
|
7769
|
+
inst.keyType = def.keyType;
|
|
7770
|
+
inst.valueType = def.valueType;
|
|
7771
|
+
});
|
|
7772
|
+
function record(keyType, valueType, params) {
|
|
7773
|
+
return new ZodRecord({
|
|
7774
|
+
type: "record",
|
|
7775
|
+
keyType,
|
|
7776
|
+
valueType,
|
|
7777
|
+
...normalizeParams(params)
|
|
7778
|
+
});
|
|
7779
|
+
}
|
|
7641
7780
|
const ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
7642
7781
|
$ZodEnum.init(inst, def);
|
|
7643
7782
|
ZodType.init(inst, def);
|
|
@@ -7900,6 +8039,19 @@ var AuthValidationError = class extends Error {
|
|
|
7900
8039
|
this.name = "AuthValidationError";
|
|
7901
8040
|
}
|
|
7902
8041
|
};
|
|
8042
|
+
var ConnectorApiError = class extends Error {
|
|
8043
|
+
constructor(message, cause) {
|
|
8044
|
+
super(message);
|
|
8045
|
+
this.cause = cause;
|
|
8046
|
+
this.name = "ConnectorApiError";
|
|
8047
|
+
}
|
|
8048
|
+
};
|
|
8049
|
+
var ConnectorValidationError = class extends Error {
|
|
8050
|
+
constructor(message) {
|
|
8051
|
+
super(message);
|
|
8052
|
+
this.name = "ConnectorValidationError";
|
|
8053
|
+
}
|
|
8054
|
+
};
|
|
7903
8055
|
|
|
7904
8056
|
//#endregion
|
|
7905
8057
|
//#region src/core/consts.ts
|
|
@@ -16193,7 +16345,7 @@ const createIgnorePredicate = (patterns, cwd, baseDir) => {
|
|
|
16193
16345
|
};
|
|
16194
16346
|
const normalizeOptions$2 = (options = {}) => {
|
|
16195
16347
|
const ignoreOption = options.ignore ? Array.isArray(options.ignore) ? options.ignore : [options.ignore] : [];
|
|
16196
|
-
const cwd = toPath$1(options.cwd) ??
|
|
16348
|
+
const cwd = toPath$1(options.cwd) ?? process$1.cwd();
|
|
16197
16349
|
const deep = typeof options.deep === "number" ? Math.max(0, options.deep) + 1 : Number.POSITIVE_INFINITY;
|
|
16198
16350
|
return {
|
|
16199
16351
|
cwd,
|
|
@@ -16290,7 +16442,7 @@ const getDirectoryGlob = ({ directoryPath, files, extensions }) => {
|
|
|
16290
16442
|
const extensionGlob = extensions?.length > 0 ? `.${extensions.length > 1 ? `{${extensions.join(",")}}` : extensions[0]}` : "";
|
|
16291
16443
|
return files ? files.map((file) => path.posix.join(directoryPath, `**/${path.extname(file) ? file : `${file}${extensionGlob}`}`)) : [path.posix.join(directoryPath, `**${extensionGlob ? `/*${extensionGlob}` : ""}`)];
|
|
16292
16444
|
};
|
|
16293
|
-
const directoryToGlob = async (directoryPaths, { cwd =
|
|
16445
|
+
const directoryToGlob = async (directoryPaths, { cwd = process$1.cwd(), files, extensions, fs: fsImplementation } = {}) => {
|
|
16294
16446
|
return (await Promise.all(directoryPaths.map(async (directoryPath) => {
|
|
16295
16447
|
if (shouldExpandGlobstarDirectory(isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath)) return getDirectoryGlob({
|
|
16296
16448
|
directoryPath,
|
|
@@ -16304,7 +16456,7 @@ const directoryToGlob = async (directoryPaths, { cwd = y.cwd(), files, extension
|
|
|
16304
16456
|
}) : directoryPath;
|
|
16305
16457
|
}))).flat();
|
|
16306
16458
|
};
|
|
16307
|
-
const directoryToGlobSync = (directoryPaths, { cwd =
|
|
16459
|
+
const directoryToGlobSync = (directoryPaths, { cwd = process$1.cwd(), files, extensions, fs: fsImplementation } = {}) => directoryPaths.flatMap((directoryPath) => {
|
|
16308
16460
|
if (shouldExpandGlobstarDirectory(isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath)) return getDirectoryGlob({
|
|
16309
16461
|
directoryPath,
|
|
16310
16462
|
files,
|
|
@@ -16400,7 +16552,7 @@ const applyIgnoreFilesAndGetFilterSync = (options) => {
|
|
|
16400
16552
|
};
|
|
16401
16553
|
const createFilterFunction = (isIgnored, cwd) => {
|
|
16402
16554
|
const seen = /* @__PURE__ */ new Set();
|
|
16403
|
-
const basePath = cwd ||
|
|
16555
|
+
const basePath = cwd || process$1.cwd();
|
|
16404
16556
|
const pathCache = /* @__PURE__ */ new Map();
|
|
16405
16557
|
return (fastGlobResult) => {
|
|
16406
16558
|
const pathKey$1 = path.normalize(fastGlobResult.path ?? fastGlobResult);
|
|
@@ -16697,10 +16849,13 @@ const SiteConfigSchema = object({
|
|
|
16697
16849
|
outputDirectory: string().optional(),
|
|
16698
16850
|
installCommand: string().optional()
|
|
16699
16851
|
});
|
|
16852
|
+
const ConnectorConfigSchema = object({ scopes: array(string()).optional() });
|
|
16853
|
+
const ConnectorsConfigSchema = record(string(), ConnectorConfigSchema);
|
|
16700
16854
|
const ProjectConfigSchema = object({
|
|
16701
16855
|
name: string().min(1, "App name cannot be empty"),
|
|
16702
16856
|
description: string().optional(),
|
|
16703
16857
|
site: SiteConfigSchema.optional(),
|
|
16858
|
+
connectors: ConnectorsConfigSchema.optional(),
|
|
16704
16859
|
entitiesDir: string().optional().default("entities"),
|
|
16705
16860
|
functionsDir: string().optional().default("functions")
|
|
16706
16861
|
});
|
|
@@ -16798,7 +16953,10 @@ async function createProject(projectName, description) {
|
|
|
16798
16953
|
return { projectId: CreateProjectResponseSchema.parse(await response.json()).id };
|
|
16799
16954
|
}
|
|
16800
16955
|
async function listProjects() {
|
|
16801
|
-
const response = await base44Client.get(`api/apps
|
|
16956
|
+
const response = await base44Client.get(`api/apps`, { searchParams: {
|
|
16957
|
+
"sort": "-updated_date",
|
|
16958
|
+
"fields": "id,name,user_description,is_managed_source_code"
|
|
16959
|
+
} });
|
|
16802
16960
|
return ProjectsResponseSchema.parse(await response.json());
|
|
16803
16961
|
}
|
|
16804
16962
|
|
|
@@ -30751,13 +30909,13 @@ var ansi_styles_default = ansiStyles;
|
|
|
30751
30909
|
|
|
30752
30910
|
//#endregion
|
|
30753
30911
|
//#region node_modules/chalk/source/vendor/supports-color/index.js
|
|
30754
|
-
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args :
|
|
30912
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process$1.argv) {
|
|
30755
30913
|
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
30756
30914
|
const position = argv.indexOf(prefix + flag);
|
|
30757
30915
|
const terminatorPosition = argv.indexOf("--");
|
|
30758
30916
|
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
30759
30917
|
}
|
|
30760
|
-
const { env } =
|
|
30918
|
+
const { env } = process$1;
|
|
30761
30919
|
let flagForceColor;
|
|
30762
30920
|
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) flagForceColor = 0;
|
|
30763
30921
|
else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) flagForceColor = 1;
|
|
@@ -30790,7 +30948,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
30790
30948
|
if (haveStream && !streamIsTTY && forceColor === void 0) return 0;
|
|
30791
30949
|
const min = forceColor || 0;
|
|
30792
30950
|
if (env.TERM === "dumb") return min;
|
|
30793
|
-
if (
|
|
30951
|
+
if (process$1.platform === "win32") {
|
|
30794
30952
|
const osRelease = os.release().split(".");
|
|
30795
30953
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
30796
30954
|
return 1;
|
|
@@ -31003,7 +31161,10 @@ const theme = {
|
|
|
31003
31161
|
base44OrangeBackground: source_default.bgHex("#E86B3C"),
|
|
31004
31162
|
shinyOrange: source_default.hex("#FFD700"),
|
|
31005
31163
|
links: source_default.hex("#00D4FF"),
|
|
31006
|
-
white: source_default.white
|
|
31164
|
+
white: source_default.white,
|
|
31165
|
+
success: source_default.green,
|
|
31166
|
+
warning: source_default.yellow,
|
|
31167
|
+
error: source_default.red
|
|
31007
31168
|
},
|
|
31008
31169
|
styles: {
|
|
31009
31170
|
header: source_default.dim,
|
|
@@ -31529,9 +31690,9 @@ const getSubprocessResult = ({ stdout: stdout$1 }) => {
|
|
|
31529
31690
|
//#region node_modules/execa/lib/utils/standard-stream.js
|
|
31530
31691
|
const isStandardStream = (stream) => STANDARD_STREAMS.includes(stream);
|
|
31531
31692
|
const STANDARD_STREAMS = [
|
|
31532
|
-
|
|
31533
|
-
|
|
31534
|
-
|
|
31693
|
+
process$1.stdin,
|
|
31694
|
+
process$1.stdout,
|
|
31695
|
+
process$1.stderr
|
|
31535
31696
|
];
|
|
31536
31697
|
const STANDARD_STREAMS_ALIASES = [
|
|
31537
31698
|
"stdin",
|
|
@@ -31656,9 +31817,9 @@ const NO_ESCAPE_REGEXP = /^[\w./-]+$/;
|
|
|
31656
31817
|
//#endregion
|
|
31657
31818
|
//#region node_modules/is-unicode-supported/index.js
|
|
31658
31819
|
function isUnicodeSupported() {
|
|
31659
|
-
const { env: env$1 } =
|
|
31820
|
+
const { env: env$1 } = process$1;
|
|
31660
31821
|
const { TERM, TERM_PROGRAM } = env$1;
|
|
31661
|
-
if (
|
|
31822
|
+
if (process$1.platform !== "win32") return TERM !== "linux";
|
|
31662
31823
|
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
31824
|
}
|
|
31664
31825
|
|
|
@@ -32585,7 +32746,7 @@ const TEN_MEGABYTES_IN_BYTES = 10 * 1024 * 1024;
|
|
|
32585
32746
|
|
|
32586
32747
|
//#endregion
|
|
32587
32748
|
//#region node_modules/npm-run-path/index.js
|
|
32588
|
-
const npmRunPath = ({ cwd =
|
|
32749
|
+
const npmRunPath = ({ cwd = process$1.cwd(), path: pathOption = process$1.env[pathKey()], preferLocal = true, execPath: execPath$1 = process$1.execPath, addExecPath = true } = {}) => {
|
|
32589
32750
|
const cwdPath = path.resolve(toPath(cwd));
|
|
32590
32751
|
const result = [];
|
|
32591
32752
|
const pathParts = pathOption.split(path.delimiter);
|
|
@@ -32603,7 +32764,7 @@ const applyExecPath = (result, pathParts, execPath$1, cwdPath) => {
|
|
|
32603
32764
|
const pathPart = path.resolve(cwdPath, toPath(execPath$1), "..");
|
|
32604
32765
|
if (!pathParts.includes(pathPart)) result.push(pathPart);
|
|
32605
32766
|
};
|
|
32606
|
-
const npmRunPathEnv = ({ env: env$1 =
|
|
32767
|
+
const npmRunPathEnv = ({ env: env$1 = process$1.env, ...options } = {}) => {
|
|
32607
32768
|
env$1 = { ...env$1 };
|
|
32608
32769
|
const pathName = pathKey({ env: env$1 });
|
|
32609
32770
|
options.path = env$1[pathName];
|
|
@@ -33738,7 +33899,7 @@ const normalizeCwd = (cwd = getDefaultCwd()) => {
|
|
|
33738
33899
|
};
|
|
33739
33900
|
const getDefaultCwd = () => {
|
|
33740
33901
|
try {
|
|
33741
|
-
return
|
|
33902
|
+
return process$1.cwd();
|
|
33742
33903
|
} catch (error) {
|
|
33743
33904
|
error.message = `The current directory does not exist.\n${error.message}`;
|
|
33744
33905
|
throw error;
|
|
@@ -33773,7 +33934,7 @@ const normalizeOptions = (filePath, rawArguments, rawOptions) => {
|
|
|
33773
33934
|
options.killSignal = normalizeKillSignal(options.killSignal);
|
|
33774
33935
|
options.forceKillAfterDelay = normalizeForceKillAfterDelay(options.forceKillAfterDelay);
|
|
33775
33936
|
options.lines = options.lines.map((lines, fdNumber) => lines && !BINARY_ENCODINGS.has(options.encoding) && options.buffer[fdNumber]);
|
|
33776
|
-
if (
|
|
33937
|
+
if (process$1.platform === "win32" && path.basename(file, ".exe") === "cmd") commandArguments.unshift("/q");
|
|
33777
33938
|
return {
|
|
33778
33939
|
file,
|
|
33779
33940
|
commandArguments,
|
|
@@ -33800,7 +33961,7 @@ const addDefaultOptions = ({ extendEnv = true, preferLocal = false, cwd, localDi
|
|
|
33800
33961
|
});
|
|
33801
33962
|
const getEnv = ({ env: envOption, extendEnv, preferLocal, node, localDirectory, nodePath }) => {
|
|
33802
33963
|
const env$1 = extendEnv ? {
|
|
33803
|
-
...
|
|
33964
|
+
...process$1.env,
|
|
33804
33965
|
...envOption
|
|
33805
33966
|
} : envOption;
|
|
33806
33967
|
if (preferLocal || node) return npmRunPathEnv({
|
|
@@ -34800,12 +34961,12 @@ const guessStreamDirection = {
|
|
|
34800
34961
|
}
|
|
34801
34962
|
};
|
|
34802
34963
|
const getStandardStreamDirection = (value) => {
|
|
34803
|
-
if ([0,
|
|
34964
|
+
if ([0, process$1.stdin].includes(value)) return "input";
|
|
34804
34965
|
if ([
|
|
34805
34966
|
1,
|
|
34806
34967
|
2,
|
|
34807
|
-
|
|
34808
|
-
|
|
34968
|
+
process$1.stdout,
|
|
34969
|
+
process$1.stderr
|
|
34809
34970
|
].includes(value)) return "output";
|
|
34810
34971
|
};
|
|
34811
34972
|
const DEFAULT_DIRECTION = "output";
|
|
@@ -35869,9 +36030,9 @@ const addIpcMethods = (subprocess, { ipc }) => {
|
|
|
35869
36030
|
Object.assign(subprocess, getIpcMethods(subprocess, false, ipc));
|
|
35870
36031
|
};
|
|
35871
36032
|
const getIpcExport = () => {
|
|
35872
|
-
const anyProcess =
|
|
36033
|
+
const anyProcess = process$1;
|
|
35873
36034
|
const isSubprocess = true;
|
|
35874
|
-
const ipc =
|
|
36035
|
+
const ipc = process$1.channel !== void 0;
|
|
35875
36036
|
return {
|
|
35876
36037
|
...getIpcMethods(anyProcess, isSubprocess, ipc),
|
|
35877
36038
|
getCancelSignal: getCancelSignal$1.bind(void 0, {
|
|
@@ -36113,7 +36274,7 @@ if (process.platform === "linux") signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SI
|
|
|
36113
36274
|
|
|
36114
36275
|
//#endregion
|
|
36115
36276
|
//#region node_modules/signal-exit/dist/mjs/index.js
|
|
36116
|
-
const processOk = (process$
|
|
36277
|
+
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
36278
|
const kExitEmitter = Symbol.for("signal-exit emitter");
|
|
36118
36279
|
const global$1 = globalThis;
|
|
36119
36280
|
const ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
@@ -36181,7 +36342,7 @@ var SignalExitFallback = class extends SignalExitBase {
|
|
|
36181
36342
|
};
|
|
36182
36343
|
var SignalExit = class extends SignalExitBase {
|
|
36183
36344
|
/* c8 ignore start */
|
|
36184
|
-
#hupSig = process$
|
|
36345
|
+
#hupSig = process$2.platform === "win32" ? "SIGINT" : "SIGHUP";
|
|
36185
36346
|
/* c8 ignore stop */
|
|
36186
36347
|
#emitter = new Emitter();
|
|
36187
36348
|
#process;
|
|
@@ -36189,15 +36350,15 @@ var SignalExit = class extends SignalExitBase {
|
|
|
36189
36350
|
#originalProcessReallyExit;
|
|
36190
36351
|
#sigListeners = {};
|
|
36191
36352
|
#loaded = false;
|
|
36192
|
-
constructor(process$
|
|
36353
|
+
constructor(process$5) {
|
|
36193
36354
|
super();
|
|
36194
|
-
this.#process = process$
|
|
36355
|
+
this.#process = process$5;
|
|
36195
36356
|
this.#sigListeners = {};
|
|
36196
36357
|
for (const sig of signals) this.#sigListeners[sig] = () => {
|
|
36197
36358
|
const listeners = this.#process.listeners(sig);
|
|
36198
36359
|
let { count: count$1 } = this.#emitter;
|
|
36199
36360
|
/* c8 ignore start */
|
|
36200
|
-
const p$1 = process$
|
|
36361
|
+
const p$1 = process$5;
|
|
36201
36362
|
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
36363
|
/* c8 ignore stop */
|
|
36203
36364
|
if (listeners.length === count$1) {
|
|
@@ -36205,11 +36366,11 @@ var SignalExit = class extends SignalExitBase {
|
|
|
36205
36366
|
const ret = this.#emitter.emit("exit", null, sig);
|
|
36206
36367
|
/* c8 ignore start */
|
|
36207
36368
|
const s = sig === "SIGHUP" ? this.#hupSig : sig;
|
|
36208
|
-
if (!ret) process$
|
|
36369
|
+
if (!ret) process$5.kill(process$5.pid, s);
|
|
36209
36370
|
}
|
|
36210
36371
|
};
|
|
36211
|
-
this.#originalProcessReallyExit = process$
|
|
36212
|
-
this.#originalProcessEmit = process$
|
|
36372
|
+
this.#originalProcessReallyExit = process$5.reallyExit;
|
|
36373
|
+
this.#originalProcessEmit = process$5.emit;
|
|
36213
36374
|
}
|
|
36214
36375
|
onExit(cb, opts) {
|
|
36215
36376
|
/* c8 ignore start */
|
|
@@ -36276,8 +36437,8 @@ var SignalExit = class extends SignalExitBase {
|
|
|
36276
36437
|
} else return og.call(this.#process, ev, ...args);
|
|
36277
36438
|
}
|
|
36278
36439
|
};
|
|
36279
|
-
const process$
|
|
36280
|
-
const { onExit, load, unload } = signalExitWrap(processOk(process$
|
|
36440
|
+
const process$2 = globalThis.process;
|
|
36441
|
+
const { onExit, load, unload } = signalExitWrap(processOk(process$2) ? new SignalExit(process$2) : new SignalExitFallback());
|
|
36281
36442
|
|
|
36282
36443
|
//#endregion
|
|
36283
36444
|
//#region node_modules/execa/lib/terminate/cleanup.js
|
|
@@ -38028,13 +38189,6 @@ var require_lodash = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
38028
38189
|
//#region src/cli/commands/project/create.ts
|
|
38029
38190
|
var import_lodash = /* @__PURE__ */ __toESM(require_lodash(), 1);
|
|
38030
38191
|
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
38192
|
async function getTemplateById(templateId) {
|
|
38039
38193
|
const templates = await listTemplates();
|
|
38040
38194
|
const template = templates.find((t) => t.id === templateId);
|
|
@@ -38097,7 +38251,6 @@ async function createInteractive(options) {
|
|
|
38097
38251
|
description: result.description || void 0,
|
|
38098
38252
|
projectPath: result.projectPath,
|
|
38099
38253
|
deploy: options.deploy,
|
|
38100
|
-
skills: options.skills,
|
|
38101
38254
|
isInteractive: true
|
|
38102
38255
|
});
|
|
38103
38256
|
}
|
|
@@ -38108,11 +38261,10 @@ async function createNonInteractive(options) {
|
|
|
38108
38261
|
description: options.description,
|
|
38109
38262
|
projectPath: options.path,
|
|
38110
38263
|
deploy: options.deploy,
|
|
38111
|
-
skills: options.skills,
|
|
38112
38264
|
isInteractive: false
|
|
38113
38265
|
});
|
|
38114
38266
|
}
|
|
38115
|
-
async function executeCreate({ template, name: rawName, description, projectPath, deploy,
|
|
38267
|
+
async function executeCreate({ template, name: rawName, description, projectPath, deploy, isInteractive }) {
|
|
38116
38268
|
const name$1 = rawName.trim();
|
|
38117
38269
|
const resolvedPath = resolve(projectPath);
|
|
38118
38270
|
const { projectId } = await runTask("Setting up your project...", async () => {
|
|
@@ -38172,45 +38324,12 @@ async function executeCreate({ template, name: rawName, description, projectPath
|
|
|
38172
38324
|
finalAppUrl = appUrl;
|
|
38173
38325
|
}
|
|
38174
38326
|
}
|
|
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
38327
|
M.message(`${theme.styles.header("Project")}: ${theme.colors.base44Orange(name$1)}`);
|
|
38209
38328
|
M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(projectId))}`);
|
|
38210
38329
|
if (finalAppUrl) M.message(`${theme.styles.header("Site")}: ${theme.colors.links(finalAppUrl)}`);
|
|
38211
38330
|
return { outroMessage: "Your project is set up and ready to use" };
|
|
38212
38331
|
}
|
|
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").
|
|
38332
|
+
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
38333
|
await chooseCreate(options);
|
|
38215
38334
|
});
|
|
38216
38335
|
|
|
@@ -38256,7 +38375,7 @@ function isInsideContainer() {
|
|
|
38256
38375
|
//#endregion
|
|
38257
38376
|
//#region node_modules/is-wsl/index.js
|
|
38258
38377
|
const isWsl = () => {
|
|
38259
|
-
if (
|
|
38378
|
+
if (process$1.platform !== "linux") return false;
|
|
38260
38379
|
if (os.release().toLowerCase().includes("microsoft")) {
|
|
38261
38380
|
if (isInsideContainer()) return false;
|
|
38262
38381
|
return true;
|
|
@@ -38267,12 +38386,12 @@ const isWsl = () => {
|
|
|
38267
38386
|
return false;
|
|
38268
38387
|
}
|
|
38269
38388
|
};
|
|
38270
|
-
var is_wsl_default =
|
|
38389
|
+
var is_wsl_default = process$1.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
38271
38390
|
|
|
38272
38391
|
//#endregion
|
|
38273
38392
|
//#region node_modules/powershell-utils/index.js
|
|
38274
38393
|
const execFile$2 = promisify(childProcess.execFile);
|
|
38275
|
-
const powerShellPath$1 = () => `${
|
|
38394
|
+
const powerShellPath$1 = () => `${process$1.env.SYSTEMROOT || process$1.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
38276
38395
|
const executePowerShell = async (command, options = {}) => {
|
|
38277
38396
|
const { powerShellPath: psPath, ...execFileOptions } = options;
|
|
38278
38397
|
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
@@ -38383,7 +38502,7 @@ function defineLazyProperty(object$1, propertyName, valueGetter) {
|
|
|
38383
38502
|
//#region node_modules/default-browser-id/index.js
|
|
38384
38503
|
const execFileAsync$3 = promisify(execFile);
|
|
38385
38504
|
async function defaultBrowserId() {
|
|
38386
|
-
if (
|
|
38505
|
+
if (process$1.platform !== "darwin") throw new Error("macOS only");
|
|
38387
38506
|
const { stdout: stdout$1 } = await execFileAsync$3("defaults", [
|
|
38388
38507
|
"read",
|
|
38389
38508
|
"com.apple.LaunchServices/com.apple.launchservices.secure",
|
|
@@ -38398,7 +38517,7 @@ async function defaultBrowserId() {
|
|
|
38398
38517
|
//#region node_modules/run-applescript/index.js
|
|
38399
38518
|
const execFileAsync$2 = promisify(execFile);
|
|
38400
38519
|
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
38401
|
-
if (
|
|
38520
|
+
if (process$1.platform !== "darwin") throw new Error("macOS only");
|
|
38402
38521
|
const outputArguments = humanReadableOutput ? [] : ["-ss"];
|
|
38403
38522
|
const execOptions = {};
|
|
38404
38523
|
if (signal) execOptions.signal = signal;
|
|
@@ -38507,14 +38626,14 @@ async function defaultBrowser$1(_execFileAsync = execFileAsync$1) {
|
|
|
38507
38626
|
const execFileAsync = promisify(execFile);
|
|
38508
38627
|
const titleize = (string$2) => string$2.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x$2) => x$2.toUpperCase());
|
|
38509
38628
|
async function defaultBrowser() {
|
|
38510
|
-
if (
|
|
38629
|
+
if (process$1.platform === "darwin") {
|
|
38511
38630
|
const id = await defaultBrowserId();
|
|
38512
38631
|
return {
|
|
38513
38632
|
name: await bundleName(id),
|
|
38514
38633
|
id
|
|
38515
38634
|
};
|
|
38516
38635
|
}
|
|
38517
|
-
if (
|
|
38636
|
+
if (process$1.platform === "linux") {
|
|
38518
38637
|
const { stdout: stdout$1 } = await execFileAsync("xdg-mime", [
|
|
38519
38638
|
"query",
|
|
38520
38639
|
"default",
|
|
@@ -38526,13 +38645,13 @@ async function defaultBrowser() {
|
|
|
38526
38645
|
id
|
|
38527
38646
|
};
|
|
38528
38647
|
}
|
|
38529
|
-
if (
|
|
38648
|
+
if (process$1.platform === "win32") return defaultBrowser$1();
|
|
38530
38649
|
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
38531
38650
|
}
|
|
38532
38651
|
|
|
38533
38652
|
//#endregion
|
|
38534
38653
|
//#region node_modules/is-in-ssh/index.js
|
|
38535
|
-
const isInSsh = Boolean(
|
|
38654
|
+
const isInSsh = Boolean(process$1.env.SSH_CONNECTION || process$1.env.SSH_CLIENT || process$1.env.SSH_TTY);
|
|
38536
38655
|
var is_in_ssh_default = isInSsh;
|
|
38537
38656
|
|
|
38538
38657
|
//#endregion
|
|
@@ -38540,7 +38659,7 @@ var is_in_ssh_default = isInSsh;
|
|
|
38540
38659
|
const fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
38541
38660
|
const __dirname = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : "";
|
|
38542
38661
|
const localXdgOpenPath = path.join(__dirname, "xdg-open");
|
|
38543
|
-
const { platform: platform$1, arch } =
|
|
38662
|
+
const { platform: platform$1, arch } = process$1;
|
|
38544
38663
|
const tryEachApp = async (apps$1, opener) => {
|
|
38545
38664
|
if (apps$1.length === 0) return;
|
|
38546
38665
|
const errors = [];
|
|
@@ -38653,7 +38772,7 @@ const baseOpen = async (options) => {
|
|
|
38653
38772
|
await fs$1.access(localXdgOpenPath, constants$1.X_OK);
|
|
38654
38773
|
exeLocalXdgOpen = true;
|
|
38655
38774
|
} catch {}
|
|
38656
|
-
command =
|
|
38775
|
+
command = process$1.versions.electron ?? (platform$1 === "android" || isBundled || !exeLocalXdgOpen) ? "xdg-open" : localXdgOpenPath;
|
|
38657
38776
|
}
|
|
38658
38777
|
if (appArguments.length > 0) cliArguments.push(...appArguments);
|
|
38659
38778
|
if (!options.wait) {
|
|
@@ -38796,9 +38915,8 @@ const deployCommand = new Command("deploy").description("Deploy all project reso
|
|
|
38796
38915
|
//#endregion
|
|
38797
38916
|
//#region src/cli/commands/project/link.ts
|
|
38798
38917
|
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");
|
|
38918
|
+
const { create: create$1, name: name$1, projectId } = command.opts();
|
|
38919
|
+
if (create$1 && projectId) command.error("--create and --projectId cannot be used together");
|
|
38802
38920
|
if (create$1 && !name$1) command.error("--name is required when using --create");
|
|
38803
38921
|
}
|
|
38804
38922
|
async function promptForLinkAction() {
|
|
@@ -38862,14 +38980,18 @@ async function link(options) {
|
|
|
38862
38980
|
if (!projectRoot) throw new Error("No Base44 project found. Run this command from a project directory with a config.jsonc file.");
|
|
38863
38981
|
if (await appConfigExists(projectRoot.root)) throw new Error("Project is already linked. An .app.jsonc file with the appId already exists.");
|
|
38864
38982
|
let finalProjectId;
|
|
38865
|
-
const action = options.
|
|
38983
|
+
const action = options.projectId ? "choose" : options.create ? "create" : await promptForLinkAction();
|
|
38866
38984
|
if (action === "choose") {
|
|
38867
38985
|
const linkableProjects = (await runTask("Fetching projects...", async () => listProjects(), {
|
|
38868
38986
|
successMessage: "Projects fetched",
|
|
38869
38987
|
errorMessage: "Failed to fetch projects"
|
|
38870
38988
|
})).filter((p$1) => p$1.isManagedSourceCode !== true);
|
|
38871
38989
|
if (!linkableProjects.length) return { outroMessage: "No projects available for linking" };
|
|
38872
|
-
|
|
38990
|
+
let projectId;
|
|
38991
|
+
if (options.projectId) {
|
|
38992
|
+
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.`);
|
|
38993
|
+
projectId = options.projectId;
|
|
38994
|
+
} else projectId = (await promptForExistingProject(linkableProjects)).id;
|
|
38873
38995
|
await runTask("Linking project...", async () => {
|
|
38874
38996
|
await writeAppConfig(projectRoot.root, projectId);
|
|
38875
38997
|
setAppConfig({
|
|
@@ -38903,7 +39025,7 @@ async function link(options) {
|
|
|
38903
39025
|
M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(finalProjectId))}`);
|
|
38904
39026
|
return { outroMessage: "Project linked" };
|
|
38905
39027
|
}
|
|
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("-
|
|
39028
|
+
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
39029
|
await runCommand(() => link(options), {
|
|
38908
39030
|
requireAuth: true,
|
|
38909
39031
|
requireAppConfig: false
|
|
@@ -38931,9 +39053,674 @@ const siteDeployCommand = new Command("site").description("Manage site deploymen
|
|
|
38931
39053
|
await runCommand(() => deployAction(options), { requireAuth: true });
|
|
38932
39054
|
}));
|
|
38933
39055
|
|
|
39056
|
+
//#endregion
|
|
39057
|
+
//#region src/core/connectors/schema.ts
|
|
39058
|
+
/**
|
|
39059
|
+
* Response from POST /api/apps/{app_id}/external-auth/initiate
|
|
39060
|
+
*/
|
|
39061
|
+
const InitiateResponseSchema = object({
|
|
39062
|
+
redirect_url: string().nullish(),
|
|
39063
|
+
connection_id: string().nullish(),
|
|
39064
|
+
already_authorized: boolean().nullish(),
|
|
39065
|
+
other_user_email: string().nullish(),
|
|
39066
|
+
error: string().nullish()
|
|
39067
|
+
});
|
|
39068
|
+
/**
|
|
39069
|
+
* Response from GET /api/apps/{app_id}/external-auth/status
|
|
39070
|
+
*/
|
|
39071
|
+
const StatusResponseSchema = object({
|
|
39072
|
+
status: _enum([
|
|
39073
|
+
"ACTIVE",
|
|
39074
|
+
"PENDING",
|
|
39075
|
+
"FAILED"
|
|
39076
|
+
]),
|
|
39077
|
+
account_email: string().nullish(),
|
|
39078
|
+
error: string().nullish()
|
|
39079
|
+
}).transform((data) => ({
|
|
39080
|
+
status: data.status,
|
|
39081
|
+
accountEmail: data.account_email,
|
|
39082
|
+
error: data.error
|
|
39083
|
+
}));
|
|
39084
|
+
/**
|
|
39085
|
+
* A connected integration from the list endpoint
|
|
39086
|
+
*/
|
|
39087
|
+
const ConnectorSchema = object({
|
|
39088
|
+
integration_type: string(),
|
|
39089
|
+
status: string(),
|
|
39090
|
+
connected_at: string().nullish(),
|
|
39091
|
+
account_info: object({
|
|
39092
|
+
email: string().nullish(),
|
|
39093
|
+
name: string().nullish()
|
|
39094
|
+
}).nullish()
|
|
39095
|
+
}).transform((data) => ({
|
|
39096
|
+
integrationType: data.integration_type,
|
|
39097
|
+
status: data.status,
|
|
39098
|
+
connectedAt: data.connected_at,
|
|
39099
|
+
accountInfo: data.account_info
|
|
39100
|
+
}));
|
|
39101
|
+
/**
|
|
39102
|
+
* Response from GET /api/apps/{app_id}/external-auth/list
|
|
39103
|
+
*/
|
|
39104
|
+
const ListResponseSchema = object({ integrations: array(ConnectorSchema) });
|
|
39105
|
+
/**
|
|
39106
|
+
* Generic API error response
|
|
39107
|
+
*/
|
|
39108
|
+
const ApiErrorSchema = object({
|
|
39109
|
+
error: string(),
|
|
39110
|
+
detail: string().nullish()
|
|
39111
|
+
});
|
|
39112
|
+
|
|
39113
|
+
//#endregion
|
|
39114
|
+
//#region src/core/connectors/api.ts
|
|
39115
|
+
/**
|
|
39116
|
+
* Initiates OAuth flow for a connector integration.
|
|
39117
|
+
* Returns a redirect URL to open in the browser.
|
|
39118
|
+
*/
|
|
39119
|
+
async function initiateOAuth(integrationType, scopes = null) {
|
|
39120
|
+
const response = await getAppClient().post("external-auth/initiate", {
|
|
39121
|
+
json: {
|
|
39122
|
+
integration_type: integrationType,
|
|
39123
|
+
scopes
|
|
39124
|
+
},
|
|
39125
|
+
throwHttpErrors: false
|
|
39126
|
+
});
|
|
39127
|
+
const json = await response.json();
|
|
39128
|
+
if (!response.ok) {
|
|
39129
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39130
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39131
|
+
throw new ConnectorApiError(`Failed to initiate OAuth: ${response.status} ${response.statusText}`);
|
|
39132
|
+
}
|
|
39133
|
+
const result = InitiateResponseSchema.safeParse(json);
|
|
39134
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid initiate response from server: ${result.error.message}`);
|
|
39135
|
+
return result.data;
|
|
39136
|
+
}
|
|
39137
|
+
/**
|
|
39138
|
+
* Checks the status of an OAuth connection attempt.
|
|
39139
|
+
*/
|
|
39140
|
+
async function checkOAuthStatus(integrationType, connectionId) {
|
|
39141
|
+
const response = await getAppClient().get("external-auth/status", {
|
|
39142
|
+
searchParams: {
|
|
39143
|
+
integration_type: integrationType,
|
|
39144
|
+
connection_id: connectionId
|
|
39145
|
+
},
|
|
39146
|
+
throwHttpErrors: false
|
|
39147
|
+
});
|
|
39148
|
+
const json = await response.json();
|
|
39149
|
+
if (!response.ok) {
|
|
39150
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39151
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39152
|
+
throw new ConnectorApiError(`Failed to check OAuth status: ${response.status} ${response.statusText}`);
|
|
39153
|
+
}
|
|
39154
|
+
const result = StatusResponseSchema.safeParse(json);
|
|
39155
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid status response from server: ${result.error.message}`);
|
|
39156
|
+
return result.data;
|
|
39157
|
+
}
|
|
39158
|
+
/**
|
|
39159
|
+
* Lists all connected integrations for the current app.
|
|
39160
|
+
*/
|
|
39161
|
+
async function listConnectors() {
|
|
39162
|
+
const response = await getAppClient().get("external-auth/list", { throwHttpErrors: false });
|
|
39163
|
+
const json = await response.json();
|
|
39164
|
+
if (!response.ok) {
|
|
39165
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39166
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39167
|
+
throw new ConnectorApiError(`Failed to list connectors: ${response.status} ${response.statusText}`);
|
|
39168
|
+
}
|
|
39169
|
+
const result = ListResponseSchema.safeParse(json);
|
|
39170
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid list response from server: ${result.error.message}`);
|
|
39171
|
+
return result.data.integrations;
|
|
39172
|
+
}
|
|
39173
|
+
/**
|
|
39174
|
+
* Disconnects (soft delete) a connector integration.
|
|
39175
|
+
*/
|
|
39176
|
+
async function disconnectConnector(integrationType) {
|
|
39177
|
+
const response = await getAppClient().delete(`external-auth/integrations/${integrationType}`, { throwHttpErrors: false });
|
|
39178
|
+
if (!response.ok) {
|
|
39179
|
+
const json = await response.json();
|
|
39180
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39181
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39182
|
+
throw new ConnectorApiError(`Failed to disconnect connector: ${response.status} ${response.statusText}`);
|
|
39183
|
+
}
|
|
39184
|
+
}
|
|
39185
|
+
/**
|
|
39186
|
+
* Removes (hard delete) a connector integration.
|
|
39187
|
+
* This permanently removes the connector and cannot be undone.
|
|
39188
|
+
*/
|
|
39189
|
+
async function removeConnector(integrationType) {
|
|
39190
|
+
const response = await getAppClient().delete(`external-auth/integrations/${integrationType}/remove`, { throwHttpErrors: false });
|
|
39191
|
+
if (!response.ok) {
|
|
39192
|
+
const json = await response.json();
|
|
39193
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
39194
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
39195
|
+
throw new ConnectorApiError(`Failed to remove connector: ${response.status} ${response.statusText}`);
|
|
39196
|
+
}
|
|
39197
|
+
}
|
|
39198
|
+
|
|
39199
|
+
//#endregion
|
|
39200
|
+
//#region src/core/connectors/constants.ts
|
|
39201
|
+
/**
|
|
39202
|
+
* OAuth polling configuration
|
|
39203
|
+
*/
|
|
39204
|
+
const OAUTH_POLL_INTERVAL_MS = 2e3;
|
|
39205
|
+
const OAUTH_POLL_TIMEOUT_MS = 300 * 1e3;
|
|
39206
|
+
/**
|
|
39207
|
+
* Supported OAuth connector integrations.
|
|
39208
|
+
* Based on apper/backend/app/external_auth/models/constants.py
|
|
39209
|
+
*/
|
|
39210
|
+
const SUPPORTED_INTEGRATIONS = [
|
|
39211
|
+
"googlecalendar",
|
|
39212
|
+
"googledrive",
|
|
39213
|
+
"gmail",
|
|
39214
|
+
"googlesheets",
|
|
39215
|
+
"googledocs",
|
|
39216
|
+
"googleslides",
|
|
39217
|
+
"slack",
|
|
39218
|
+
"notion",
|
|
39219
|
+
"salesforce",
|
|
39220
|
+
"hubspot",
|
|
39221
|
+
"linkedin",
|
|
39222
|
+
"tiktok"
|
|
39223
|
+
];
|
|
39224
|
+
/**
|
|
39225
|
+
* Display names for integrations (for CLI output)
|
|
39226
|
+
*/
|
|
39227
|
+
const INTEGRATION_DISPLAY_NAMES = {
|
|
39228
|
+
googlecalendar: "Google Calendar",
|
|
39229
|
+
googledrive: "Google Drive",
|
|
39230
|
+
gmail: "Gmail",
|
|
39231
|
+
googlesheets: "Google Sheets",
|
|
39232
|
+
googledocs: "Google Docs",
|
|
39233
|
+
googleslides: "Google Slides",
|
|
39234
|
+
slack: "Slack",
|
|
39235
|
+
notion: "Notion",
|
|
39236
|
+
salesforce: "Salesforce",
|
|
39237
|
+
hubspot: "HubSpot",
|
|
39238
|
+
linkedin: "LinkedIn",
|
|
39239
|
+
tiktok: "TikTok"
|
|
39240
|
+
};
|
|
39241
|
+
function isValidIntegration(type) {
|
|
39242
|
+
return SUPPORTED_INTEGRATIONS.includes(type);
|
|
39243
|
+
}
|
|
39244
|
+
function getIntegrationDisplayName(type) {
|
|
39245
|
+
if (isValidIntegration(type)) return INTEGRATION_DISPLAY_NAMES[type];
|
|
39246
|
+
return type;
|
|
39247
|
+
}
|
|
39248
|
+
|
|
39249
|
+
//#endregion
|
|
39250
|
+
//#region src/core/connectors/config.ts
|
|
39251
|
+
/**
|
|
39252
|
+
* Read all connectors from the project config file
|
|
39253
|
+
*/
|
|
39254
|
+
async function readLocalConnectors(projectRoot) {
|
|
39255
|
+
const found = await findProjectRoot(projectRoot);
|
|
39256
|
+
if (!found) return [];
|
|
39257
|
+
const connectorsData = (await readJsonFile(found.configPath)).connectors;
|
|
39258
|
+
if (!connectorsData) return [];
|
|
39259
|
+
const connectors = [];
|
|
39260
|
+
for (const [type, config$1] of Object.entries(connectorsData)) {
|
|
39261
|
+
if (!isValidIntegration(type)) throw new Error(`Unknown connector type: ${type}`);
|
|
39262
|
+
connectors.push({
|
|
39263
|
+
type,
|
|
39264
|
+
scopes: config$1.scopes
|
|
39265
|
+
});
|
|
39266
|
+
}
|
|
39267
|
+
return connectors;
|
|
39268
|
+
}
|
|
39269
|
+
/**
|
|
39270
|
+
* Write connectors to the project config file
|
|
39271
|
+
*/
|
|
39272
|
+
async function writeLocalConnectors(connectors, projectRoot) {
|
|
39273
|
+
const found = await findProjectRoot(projectRoot);
|
|
39274
|
+
if (!found) throw new Error("Project config not found. Run this command from a Base44 project directory.");
|
|
39275
|
+
const existingConfig = await readJsonFile(found.configPath);
|
|
39276
|
+
const connectorsData = {};
|
|
39277
|
+
for (const connector of connectors) connectorsData[connector.type] = { ...connector.scopes && { scopes: connector.scopes } };
|
|
39278
|
+
const updatedConfig = {
|
|
39279
|
+
...existingConfig,
|
|
39280
|
+
connectors: Object.keys(connectorsData).length > 0 ? connectorsData : void 0
|
|
39281
|
+
};
|
|
39282
|
+
if (!updatedConfig.connectors) delete updatedConfig.connectors;
|
|
39283
|
+
await writeJsonFile(found.configPath, updatedConfig);
|
|
39284
|
+
return found.configPath;
|
|
39285
|
+
}
|
|
39286
|
+
/**
|
|
39287
|
+
* Add a connector to the project config file
|
|
39288
|
+
*/
|
|
39289
|
+
async function addLocalConnector(type, scopes, projectRoot) {
|
|
39290
|
+
const connectors = await readLocalConnectors(projectRoot);
|
|
39291
|
+
const existing = connectors.find((c$1) => c$1.type === type);
|
|
39292
|
+
if (existing) {
|
|
39293
|
+
if (scopes) existing.scopes = scopes;
|
|
39294
|
+
} else connectors.push({
|
|
39295
|
+
type,
|
|
39296
|
+
scopes
|
|
39297
|
+
});
|
|
39298
|
+
return await writeLocalConnectors(connectors, projectRoot);
|
|
39299
|
+
}
|
|
39300
|
+
/**
|
|
39301
|
+
* Remove a connector from the project config file
|
|
39302
|
+
*/
|
|
39303
|
+
async function removeLocalConnector(type, projectRoot) {
|
|
39304
|
+
const connectors = await readLocalConnectors(projectRoot);
|
|
39305
|
+
const filtered = connectors.filter((c$1) => c$1.type !== type);
|
|
39306
|
+
if (filtered.length === connectors.length) return null;
|
|
39307
|
+
return await writeLocalConnectors(filtered, projectRoot);
|
|
39308
|
+
}
|
|
39309
|
+
|
|
39310
|
+
//#endregion
|
|
39311
|
+
//#region src/cli/commands/connectors/add.ts
|
|
39312
|
+
function validateIntegrationType(type) {
|
|
39313
|
+
if (!isValidIntegration(type)) {
|
|
39314
|
+
const supportedList = SUPPORTED_INTEGRATIONS.join(", ");
|
|
39315
|
+
throw new Error(`Unsupported connector: ${type}\nSupported connectors: ${supportedList}`);
|
|
39316
|
+
}
|
|
39317
|
+
return type;
|
|
39318
|
+
}
|
|
39319
|
+
async function promptForIntegrationType() {
|
|
39320
|
+
const selected = await ve({
|
|
39321
|
+
message: "Select an integration to connect:",
|
|
39322
|
+
options: SUPPORTED_INTEGRATIONS.map((type) => ({
|
|
39323
|
+
value: type,
|
|
39324
|
+
label: getIntegrationDisplayName(type)
|
|
39325
|
+
}))
|
|
39326
|
+
});
|
|
39327
|
+
if (pD(selected)) {
|
|
39328
|
+
xe("Operation cancelled.");
|
|
39329
|
+
process.exit(0);
|
|
39330
|
+
}
|
|
39331
|
+
return selected;
|
|
39332
|
+
}
|
|
39333
|
+
async function waitForOAuthCompletion(integrationType, connectionId) {
|
|
39334
|
+
let accountEmail;
|
|
39335
|
+
let error;
|
|
39336
|
+
try {
|
|
39337
|
+
await runTask("Waiting for authorization...", async (updateMessage) => {
|
|
39338
|
+
await pWaitFor(async () => {
|
|
39339
|
+
const status = await checkOAuthStatus(integrationType, connectionId);
|
|
39340
|
+
if (status.status === "ACTIVE") {
|
|
39341
|
+
accountEmail = status.accountEmail ?? void 0;
|
|
39342
|
+
return true;
|
|
39343
|
+
}
|
|
39344
|
+
if (status.status === "FAILED") {
|
|
39345
|
+
error = status.error || "Authorization failed";
|
|
39346
|
+
throw new Error(error);
|
|
39347
|
+
}
|
|
39348
|
+
updateMessage("Waiting for authorization in browser...");
|
|
39349
|
+
return false;
|
|
39350
|
+
}, {
|
|
39351
|
+
interval: OAUTH_POLL_INTERVAL_MS,
|
|
39352
|
+
timeout: OAUTH_POLL_TIMEOUT_MS
|
|
39353
|
+
});
|
|
39354
|
+
}, {
|
|
39355
|
+
successMessage: "Authorization completed!",
|
|
39356
|
+
errorMessage: "Authorization failed"
|
|
39357
|
+
});
|
|
39358
|
+
return {
|
|
39359
|
+
success: true,
|
|
39360
|
+
accountEmail
|
|
39361
|
+
};
|
|
39362
|
+
} catch (err) {
|
|
39363
|
+
if (err instanceof Error && err.message.includes("timed out")) return {
|
|
39364
|
+
success: false,
|
|
39365
|
+
error: "Authorization timed out. Please try again."
|
|
39366
|
+
};
|
|
39367
|
+
return {
|
|
39368
|
+
success: false,
|
|
39369
|
+
error: error || (err instanceof Error ? err.message : "Unknown error")
|
|
39370
|
+
};
|
|
39371
|
+
}
|
|
39372
|
+
}
|
|
39373
|
+
async function addConnector(integrationType) {
|
|
39374
|
+
const selectedType = integrationType ? validateIntegrationType(integrationType) : await promptForIntegrationType();
|
|
39375
|
+
const displayName = getIntegrationDisplayName(selectedType);
|
|
39376
|
+
const initiateResponse = await runTask(`Initiating ${displayName} connection...`, async () => {
|
|
39377
|
+
return await initiateOAuth(selectedType);
|
|
39378
|
+
}, {
|
|
39379
|
+
successMessage: `${displayName} OAuth initiated`,
|
|
39380
|
+
errorMessage: `Failed to initiate ${displayName} connection`
|
|
39381
|
+
});
|
|
39382
|
+
if (initiateResponse.already_authorized) {
|
|
39383
|
+
await addLocalConnector(selectedType);
|
|
39384
|
+
return { outroMessage: `Already connected to ${theme.styles.bold(displayName)} (added to config)` };
|
|
39385
|
+
}
|
|
39386
|
+
if (initiateResponse.error === "different_user" && initiateResponse.other_user_email) throw new Error(`This app is already connected to ${displayName} by ${initiateResponse.other_user_email}`);
|
|
39387
|
+
if (!initiateResponse.redirect_url || !initiateResponse.connection_id) throw new Error("Invalid response from server: missing redirect URL or connection ID");
|
|
39388
|
+
M.info(`Please authorize ${displayName} at:\n${theme.colors.links(initiateResponse.redirect_url)}`);
|
|
39389
|
+
const result = await waitForOAuthCompletion(selectedType, initiateResponse.connection_id);
|
|
39390
|
+
if (!result.success) throw new Error(result.error || "Authorization failed");
|
|
39391
|
+
await addLocalConnector(selectedType);
|
|
39392
|
+
const accountInfo = result.accountEmail ? ` as ${theme.styles.bold(result.accountEmail)}` : "";
|
|
39393
|
+
return { outroMessage: `Successfully connected to ${theme.styles.bold(displayName)}${accountInfo}` };
|
|
39394
|
+
}
|
|
39395
|
+
const connectorsAddCommand = new Command("add").argument("[type]", "Integration type (e.g., slack, notion, googlecalendar)").description("Connect an OAuth integration").action(async (type) => {
|
|
39396
|
+
await runCommand(() => addConnector(type), {
|
|
39397
|
+
requireAuth: true,
|
|
39398
|
+
requireAppConfig: true
|
|
39399
|
+
});
|
|
39400
|
+
});
|
|
39401
|
+
|
|
39402
|
+
//#endregion
|
|
39403
|
+
//#region src/cli/commands/connectors/list.ts
|
|
39404
|
+
function mergeConnectors(local, backend) {
|
|
39405
|
+
const merged = /* @__PURE__ */ new Map();
|
|
39406
|
+
for (const connector of local) merged.set(connector.type, {
|
|
39407
|
+
type: connector.type,
|
|
39408
|
+
displayName: getIntegrationDisplayName(connector.type),
|
|
39409
|
+
inLocal: true,
|
|
39410
|
+
inBackend: false
|
|
39411
|
+
});
|
|
39412
|
+
for (const connector of backend) {
|
|
39413
|
+
const existing = merged.get(connector.integrationType);
|
|
39414
|
+
const accountEmail = (connector.accountInfo?.email || connector.accountInfo?.name) ?? void 0;
|
|
39415
|
+
if (existing) {
|
|
39416
|
+
existing.inBackend = true;
|
|
39417
|
+
existing.status = connector.status;
|
|
39418
|
+
existing.accountEmail = accountEmail;
|
|
39419
|
+
} else merged.set(connector.integrationType, {
|
|
39420
|
+
type: connector.integrationType,
|
|
39421
|
+
displayName: getIntegrationDisplayName(connector.integrationType),
|
|
39422
|
+
inLocal: false,
|
|
39423
|
+
inBackend: true,
|
|
39424
|
+
status: connector.status,
|
|
39425
|
+
accountEmail
|
|
39426
|
+
});
|
|
39427
|
+
}
|
|
39428
|
+
return Array.from(merged.values());
|
|
39429
|
+
}
|
|
39430
|
+
function formatConnectorLine(connector) {
|
|
39431
|
+
const { displayName, inLocal, inBackend, status, accountEmail } = connector;
|
|
39432
|
+
const isConnected$1 = inBackend && status?.toLowerCase() === "active";
|
|
39433
|
+
const isPending = inLocal && !inBackend;
|
|
39434
|
+
const isOrphaned = inBackend && !inLocal;
|
|
39435
|
+
let bullet;
|
|
39436
|
+
let statusText = "";
|
|
39437
|
+
if (isConnected$1) {
|
|
39438
|
+
bullet = theme.colors.success("●");
|
|
39439
|
+
if (accountEmail) statusText = ` - ${accountEmail}`;
|
|
39440
|
+
} else if (isPending) {
|
|
39441
|
+
bullet = theme.colors.warning("○");
|
|
39442
|
+
statusText = theme.styles.dim(" (not connected)");
|
|
39443
|
+
} else if (isOrphaned) {
|
|
39444
|
+
bullet = theme.colors.error("○");
|
|
39445
|
+
statusText = theme.styles.dim(" (not in local config)");
|
|
39446
|
+
} else {
|
|
39447
|
+
bullet = theme.colors.error("○");
|
|
39448
|
+
statusText = theme.styles.dim(` (${status || "disconnected"})`);
|
|
39449
|
+
}
|
|
39450
|
+
return `${bullet} ${displayName}${statusText}`;
|
|
39451
|
+
}
|
|
39452
|
+
async function listConnectorsCommand() {
|
|
39453
|
+
const [localConnectors, backendConnectors] = await runTask("Fetching connectors...", async () => {
|
|
39454
|
+
const [local, backend] = await Promise.all([readLocalConnectors().catch(() => []), listConnectors().catch(() => [])]);
|
|
39455
|
+
return [local, backend];
|
|
39456
|
+
}, {
|
|
39457
|
+
successMessage: "Connectors loaded",
|
|
39458
|
+
errorMessage: "Failed to fetch connectors"
|
|
39459
|
+
});
|
|
39460
|
+
const merged = mergeConnectors(localConnectors, backendConnectors);
|
|
39461
|
+
if (merged.length === 0) {
|
|
39462
|
+
M.info("No connectors configured for this app.");
|
|
39463
|
+
M.info(`Run ${theme.styles.bold("base44 connectors add")} to connect an integration.`);
|
|
39464
|
+
return { outroMessage: "" };
|
|
39465
|
+
}
|
|
39466
|
+
console.log();
|
|
39467
|
+
for (const connector of merged) console.log(formatConnectorLine(connector));
|
|
39468
|
+
console.log();
|
|
39469
|
+
const connected = merged.filter((c$1) => c$1.inBackend && c$1.status?.toLowerCase() === "active").length;
|
|
39470
|
+
const pending = merged.filter((c$1) => c$1.inLocal && !c$1.inBackend).length;
|
|
39471
|
+
let summary = `${connected} connected`;
|
|
39472
|
+
if (pending > 0) {
|
|
39473
|
+
summary += `, ${pending} pending`;
|
|
39474
|
+
M.info(`Run ${theme.styles.bold("base44 connectors push")} to connect pending integrations.`);
|
|
39475
|
+
}
|
|
39476
|
+
return { outroMessage: summary };
|
|
39477
|
+
}
|
|
39478
|
+
const connectorsListCommand = new Command("list").description("List all connected OAuth integrations").action(async () => {
|
|
39479
|
+
await runCommand(listConnectorsCommand, {
|
|
39480
|
+
requireAuth: true,
|
|
39481
|
+
requireAppConfig: true
|
|
39482
|
+
});
|
|
39483
|
+
});
|
|
39484
|
+
|
|
39485
|
+
//#endregion
|
|
39486
|
+
//#region src/cli/commands/connectors/push.ts
|
|
39487
|
+
function findPendingConnectors(local, backend) {
|
|
39488
|
+
const connectedTypes = new Set(backend.filter((c$1) => c$1.status.toLowerCase() === "active").map((c$1) => c$1.integrationType));
|
|
39489
|
+
return local.filter((c$1) => !connectedTypes.has(c$1.type)).map((c$1) => ({
|
|
39490
|
+
type: c$1.type,
|
|
39491
|
+
displayName: getIntegrationDisplayName(c$1.type),
|
|
39492
|
+
scopes: c$1.scopes
|
|
39493
|
+
}));
|
|
39494
|
+
}
|
|
39495
|
+
function findOrphanedConnectors(local, backend) {
|
|
39496
|
+
const localTypes = new Set(local.map((c$1) => c$1.type));
|
|
39497
|
+
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) => ({
|
|
39498
|
+
type: c$1.integrationType,
|
|
39499
|
+
displayName: getIntegrationDisplayName(c$1.integrationType),
|
|
39500
|
+
accountEmail: (c$1.accountInfo?.email || c$1.accountInfo?.name) ?? void 0
|
|
39501
|
+
}));
|
|
39502
|
+
}
|
|
39503
|
+
async function connectSingleConnector(connector) {
|
|
39504
|
+
const { type, displayName, scopes } = connector;
|
|
39505
|
+
const initiateResponse = await initiateOAuth(type, scopes || null);
|
|
39506
|
+
if (initiateResponse.already_authorized) return { success: true };
|
|
39507
|
+
if (initiateResponse.error === "different_user") return {
|
|
39508
|
+
success: false,
|
|
39509
|
+
error: `Already connected by ${initiateResponse.other_user_email}`
|
|
39510
|
+
};
|
|
39511
|
+
if (!initiateResponse.redirect_url || !initiateResponse.connection_id) return {
|
|
39512
|
+
success: false,
|
|
39513
|
+
error: "Invalid response from server"
|
|
39514
|
+
};
|
|
39515
|
+
M.info(`Please authorize ${displayName} at:\n${theme.colors.links(initiateResponse.redirect_url)}`);
|
|
39516
|
+
let accountEmail;
|
|
39517
|
+
try {
|
|
39518
|
+
await runTask("Waiting for authorization...", async () => {
|
|
39519
|
+
await pWaitFor(async () => {
|
|
39520
|
+
const status = await checkOAuthStatus(type, initiateResponse.connection_id);
|
|
39521
|
+
if (status.status === "ACTIVE") {
|
|
39522
|
+
accountEmail = status.accountEmail ?? void 0;
|
|
39523
|
+
return true;
|
|
39524
|
+
}
|
|
39525
|
+
if (status.status === "FAILED") throw new Error(status.error || "Authorization failed");
|
|
39526
|
+
return false;
|
|
39527
|
+
}, {
|
|
39528
|
+
interval: OAUTH_POLL_INTERVAL_MS,
|
|
39529
|
+
timeout: OAUTH_POLL_TIMEOUT_MS
|
|
39530
|
+
});
|
|
39531
|
+
}, {
|
|
39532
|
+
successMessage: "Authorization completed!",
|
|
39533
|
+
errorMessage: "Authorization failed"
|
|
39534
|
+
});
|
|
39535
|
+
return {
|
|
39536
|
+
success: true,
|
|
39537
|
+
accountEmail
|
|
39538
|
+
};
|
|
39539
|
+
} catch (err) {
|
|
39540
|
+
if (err instanceof Error && err.message.includes("timed out")) return {
|
|
39541
|
+
success: false,
|
|
39542
|
+
error: "Authorization timed out. Please try again."
|
|
39543
|
+
};
|
|
39544
|
+
return {
|
|
39545
|
+
success: false,
|
|
39546
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
39547
|
+
};
|
|
39548
|
+
}
|
|
39549
|
+
}
|
|
39550
|
+
async function pushConnectorsCommand() {
|
|
39551
|
+
const [localConnectors, backendConnectors] = await runTask("Checking connector status...", async () => {
|
|
39552
|
+
const [local, backend] = await Promise.all([readLocalConnectors(), listConnectors().catch(() => [])]);
|
|
39553
|
+
return [local, backend];
|
|
39554
|
+
}, {
|
|
39555
|
+
successMessage: "Status checked",
|
|
39556
|
+
errorMessage: "Failed to check status"
|
|
39557
|
+
});
|
|
39558
|
+
const pending = findPendingConnectors(localConnectors, backendConnectors);
|
|
39559
|
+
const orphaned = findOrphanedConnectors(localConnectors, backendConnectors);
|
|
39560
|
+
if (pending.length === 0 && orphaned.length === 0) return { outroMessage: "All connectors are in sync" };
|
|
39561
|
+
console.log();
|
|
39562
|
+
if (pending.length > 0) {
|
|
39563
|
+
M.info(`${pending.length} connector${pending.length === 1 ? "" : "s"} to connect:`);
|
|
39564
|
+
for (const c$1 of pending) console.log(` ${theme.colors.success("+")} ${c$1.displayName}`);
|
|
39565
|
+
}
|
|
39566
|
+
if (orphaned.length > 0) {
|
|
39567
|
+
M.info(`${orphaned.length} connector${orphaned.length === 1 ? "" : "s"} to remove:`);
|
|
39568
|
+
for (const c$1 of orphaned) {
|
|
39569
|
+
const accountInfo = c$1.accountEmail ? ` (${c$1.accountEmail})` : "";
|
|
39570
|
+
console.log(` ${theme.colors.error("-")} ${c$1.displayName}${accountInfo}`);
|
|
39571
|
+
}
|
|
39572
|
+
}
|
|
39573
|
+
console.log();
|
|
39574
|
+
const totalChanges = pending.length + orphaned.length;
|
|
39575
|
+
const shouldProceed = await ye({
|
|
39576
|
+
message: `Apply ${totalChanges} change${totalChanges === 1 ? "" : "s"}?`,
|
|
39577
|
+
initialValue: true
|
|
39578
|
+
});
|
|
39579
|
+
if (pD(shouldProceed) || !shouldProceed) return { outroMessage: "Cancelled" };
|
|
39580
|
+
let connected = 0;
|
|
39581
|
+
let removed = 0;
|
|
39582
|
+
let failed = 0;
|
|
39583
|
+
for (const connector of orphaned) try {
|
|
39584
|
+
await disconnectConnector(connector.type);
|
|
39585
|
+
M.success(`Removed ${connector.displayName}`);
|
|
39586
|
+
removed++;
|
|
39587
|
+
} catch (err) {
|
|
39588
|
+
M.error(`Failed to remove ${connector.displayName}: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
39589
|
+
failed++;
|
|
39590
|
+
}
|
|
39591
|
+
for (const connector of pending) {
|
|
39592
|
+
console.log();
|
|
39593
|
+
M.info(`Connecting ${theme.styles.bold(connector.displayName)}...`);
|
|
39594
|
+
const result = await connectSingleConnector(connector);
|
|
39595
|
+
if (result.success) {
|
|
39596
|
+
const accountInfo = result.accountEmail ? ` as ${result.accountEmail}` : "";
|
|
39597
|
+
M.success(`${connector.displayName} connected${accountInfo}`);
|
|
39598
|
+
connected++;
|
|
39599
|
+
} else {
|
|
39600
|
+
M.error(`${connector.displayName} failed: ${result.error}`);
|
|
39601
|
+
failed++;
|
|
39602
|
+
}
|
|
39603
|
+
}
|
|
39604
|
+
console.log();
|
|
39605
|
+
const parts = [];
|
|
39606
|
+
if (connected > 0) parts.push(`${connected} connected`);
|
|
39607
|
+
if (removed > 0) parts.push(`${removed} removed`);
|
|
39608
|
+
if (failed > 0) parts.push(`${failed} failed`);
|
|
39609
|
+
return { outroMessage: parts.join(", ") };
|
|
39610
|
+
}
|
|
39611
|
+
const connectorsPushCommand = new Command("push").description("Sync connectors with backend (connect new, remove missing)").action(async () => {
|
|
39612
|
+
await runCommand(pushConnectorsCommand, {
|
|
39613
|
+
requireAuth: true,
|
|
39614
|
+
requireAppConfig: true
|
|
39615
|
+
});
|
|
39616
|
+
});
|
|
39617
|
+
|
|
39618
|
+
//#endregion
|
|
39619
|
+
//#region src/cli/commands/connectors/remove.ts
|
|
39620
|
+
function mergeConnectorsForRemoval(local, backend) {
|
|
39621
|
+
const merged = /* @__PURE__ */ new Map();
|
|
39622
|
+
for (const connector of local) merged.set(connector.type, {
|
|
39623
|
+
type: connector.type,
|
|
39624
|
+
displayName: getIntegrationDisplayName(connector.type),
|
|
39625
|
+
inLocal: true,
|
|
39626
|
+
inBackend: false
|
|
39627
|
+
});
|
|
39628
|
+
for (const connector of backend) {
|
|
39629
|
+
if (!isValidIntegration(connector.integrationType)) continue;
|
|
39630
|
+
const existing = merged.get(connector.integrationType);
|
|
39631
|
+
const accountEmail = (connector.accountInfo?.email || connector.accountInfo?.name) ?? void 0;
|
|
39632
|
+
if (existing) {
|
|
39633
|
+
existing.inBackend = true;
|
|
39634
|
+
existing.accountEmail = accountEmail;
|
|
39635
|
+
} else merged.set(connector.integrationType, {
|
|
39636
|
+
type: connector.integrationType,
|
|
39637
|
+
displayName: getIntegrationDisplayName(connector.integrationType),
|
|
39638
|
+
inLocal: false,
|
|
39639
|
+
inBackend: true,
|
|
39640
|
+
accountEmail
|
|
39641
|
+
});
|
|
39642
|
+
}
|
|
39643
|
+
return Array.from(merged.values());
|
|
39644
|
+
}
|
|
39645
|
+
function validateConnectorType(type, merged) {
|
|
39646
|
+
if (!isValidIntegration(type)) throw new Error(`Invalid connector type: ${type}`);
|
|
39647
|
+
const connector = merged.find((c$1) => c$1.type === type);
|
|
39648
|
+
if (!connector) throw new Error(`No ${getIntegrationDisplayName(type)} connector found`);
|
|
39649
|
+
return {
|
|
39650
|
+
type,
|
|
39651
|
+
connector
|
|
39652
|
+
};
|
|
39653
|
+
}
|
|
39654
|
+
async function promptForConnectorToRemove(connectors) {
|
|
39655
|
+
const selected = await ve({
|
|
39656
|
+
message: "Select a connector to remove:",
|
|
39657
|
+
options: connectors.map((c$1) => {
|
|
39658
|
+
let label = c$1.displayName;
|
|
39659
|
+
if (c$1.accountEmail) label += ` (${c$1.accountEmail})`;
|
|
39660
|
+
else if (c$1.inLocal && !c$1.inBackend) label += " (not connected)";
|
|
39661
|
+
return {
|
|
39662
|
+
value: c$1.type,
|
|
39663
|
+
label
|
|
39664
|
+
};
|
|
39665
|
+
})
|
|
39666
|
+
});
|
|
39667
|
+
if (pD(selected)) {
|
|
39668
|
+
xe("Operation cancelled.");
|
|
39669
|
+
process.exit(0);
|
|
39670
|
+
}
|
|
39671
|
+
return {
|
|
39672
|
+
type: selected,
|
|
39673
|
+
connector: connectors.find((c$1) => c$1.type === selected)
|
|
39674
|
+
};
|
|
39675
|
+
}
|
|
39676
|
+
async function removeConnectorCommand(integrationType, options = {}) {
|
|
39677
|
+
const isHardDelete = options.hard === true;
|
|
39678
|
+
const [localConnectors, backendConnectors] = await runTask("Fetching connectors...", async () => {
|
|
39679
|
+
const [local, backend] = await Promise.all([readLocalConnectors().catch(() => []), listConnectors().catch(() => [])]);
|
|
39680
|
+
return [local, backend];
|
|
39681
|
+
}, {
|
|
39682
|
+
successMessage: "Connectors loaded",
|
|
39683
|
+
errorMessage: "Failed to fetch connectors"
|
|
39684
|
+
});
|
|
39685
|
+
const merged = mergeConnectorsForRemoval(localConnectors, backendConnectors);
|
|
39686
|
+
if (merged.length === 0) return { outroMessage: "No connectors to remove" };
|
|
39687
|
+
const { type: selectedType, connector: selectedConnector } = integrationType ? validateConnectorType(integrationType, merged) : await promptForConnectorToRemove(merged);
|
|
39688
|
+
const displayName = getIntegrationDisplayName(selectedType);
|
|
39689
|
+
const accountInfo = selectedConnector.accountEmail ? ` (${selectedConnector.accountEmail})` : "";
|
|
39690
|
+
if (!options.yes) {
|
|
39691
|
+
const shouldRemove = await ye({
|
|
39692
|
+
message: `${isHardDelete ? "Permanently remove" : "Remove"} ${displayName}${accountInfo}?`,
|
|
39693
|
+
initialValue: false
|
|
39694
|
+
});
|
|
39695
|
+
if (pD(shouldRemove) || !shouldRemove) {
|
|
39696
|
+
xe("Operation cancelled.");
|
|
39697
|
+
process.exit(0);
|
|
39698
|
+
}
|
|
39699
|
+
}
|
|
39700
|
+
await runTask(`Removing ${displayName}...`, async () => {
|
|
39701
|
+
if (selectedConnector.inBackend) if (isHardDelete) await removeConnector(selectedType);
|
|
39702
|
+
else await disconnectConnector(selectedType);
|
|
39703
|
+
await removeLocalConnector(selectedType);
|
|
39704
|
+
}, {
|
|
39705
|
+
successMessage: `${displayName} removed`,
|
|
39706
|
+
errorMessage: `Failed to remove ${displayName}`
|
|
39707
|
+
});
|
|
39708
|
+
return { outroMessage: `Successfully removed ${theme.styles.bold(displayName)}` };
|
|
39709
|
+
}
|
|
39710
|
+
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) => {
|
|
39711
|
+
await runCommand(() => removeConnectorCommand(type, options), {
|
|
39712
|
+
requireAuth: true,
|
|
39713
|
+
requireAppConfig: true
|
|
39714
|
+
});
|
|
39715
|
+
});
|
|
39716
|
+
|
|
39717
|
+
//#endregion
|
|
39718
|
+
//#region src/cli/commands/connectors/index.ts
|
|
39719
|
+
const connectorsCommand = new Command("connectors").description("Manage OAuth connectors").addCommand(connectorsAddCommand).addCommand(connectorsListCommand).addCommand(connectorsPushCommand).addCommand(connectorsRemoveCommand);
|
|
39720
|
+
|
|
38934
39721
|
//#endregion
|
|
38935
39722
|
//#region package.json
|
|
38936
|
-
var version = "0.0.
|
|
39723
|
+
var version = "0.0.17";
|
|
38937
39724
|
|
|
38938
39725
|
//#endregion
|
|
38939
39726
|
//#region src/cli/index.ts
|
|
@@ -38950,6 +39737,7 @@ program.addCommand(linkCommand);
|
|
|
38950
39737
|
program.addCommand(entitiesPushCommand);
|
|
38951
39738
|
program.addCommand(functionsDeployCommand);
|
|
38952
39739
|
program.addCommand(siteDeployCommand);
|
|
39740
|
+
program.addCommand(connectorsCommand);
|
|
38953
39741
|
program.parse();
|
|
38954
39742
|
|
|
38955
39743
|
//#endregion
|