@base44-preview/cli 0.1.7-pr.585.44bc526 → 0.1.7-pr.585.63c3afc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +698 -639
- package/dist/cli/index.js.map +14 -15
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -23352,15 +23352,15 @@ var require_windows = __commonJS((exports, module) => {
|
|
|
23352
23352
|
}
|
|
23353
23353
|
return false;
|
|
23354
23354
|
}
|
|
23355
|
-
function checkStat(
|
|
23356
|
-
if (!
|
|
23355
|
+
function checkStat(stat2, path11, options) {
|
|
23356
|
+
if (!stat2.isSymbolicLink() && !stat2.isFile()) {
|
|
23357
23357
|
return false;
|
|
23358
23358
|
}
|
|
23359
23359
|
return checkPathExt(path11, options);
|
|
23360
23360
|
}
|
|
23361
23361
|
function isexe(path11, options, cb) {
|
|
23362
|
-
fs14.stat(path11, function(er,
|
|
23363
|
-
cb(er, er ? false : checkStat(
|
|
23362
|
+
fs14.stat(path11, function(er, stat2) {
|
|
23363
|
+
cb(er, er ? false : checkStat(stat2, path11, options));
|
|
23364
23364
|
});
|
|
23365
23365
|
}
|
|
23366
23366
|
function sync(path11, options) {
|
|
@@ -23374,20 +23374,20 @@ var require_mode = __commonJS((exports, module) => {
|
|
|
23374
23374
|
isexe.sync = sync;
|
|
23375
23375
|
var fs14 = __require("fs");
|
|
23376
23376
|
function isexe(path11, options, cb) {
|
|
23377
|
-
fs14.stat(path11, function(er,
|
|
23378
|
-
cb(er, er ? false : checkStat(
|
|
23377
|
+
fs14.stat(path11, function(er, stat2) {
|
|
23378
|
+
cb(er, er ? false : checkStat(stat2, options));
|
|
23379
23379
|
});
|
|
23380
23380
|
}
|
|
23381
23381
|
function sync(path11, options) {
|
|
23382
23382
|
return checkStat(fs14.statSync(path11), options);
|
|
23383
23383
|
}
|
|
23384
|
-
function checkStat(
|
|
23385
|
-
return
|
|
23384
|
+
function checkStat(stat2, options) {
|
|
23385
|
+
return stat2.isFile() && checkMode(stat2, options);
|
|
23386
23386
|
}
|
|
23387
|
-
function checkMode(
|
|
23388
|
-
var mod =
|
|
23389
|
-
var uid =
|
|
23390
|
-
var gid =
|
|
23387
|
+
function checkMode(stat2, options) {
|
|
23388
|
+
var mod = stat2.mode;
|
|
23389
|
+
var uid = stat2.uid;
|
|
23390
|
+
var gid = stat2.gid;
|
|
23391
23391
|
var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
|
|
23392
23392
|
var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
|
|
23393
23393
|
var u = parseInt("100", 8);
|
|
@@ -23419,12 +23419,12 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
23419
23419
|
if (typeof Promise !== "function") {
|
|
23420
23420
|
throw new TypeError("callback not provided");
|
|
23421
23421
|
}
|
|
23422
|
-
return new Promise(function(
|
|
23422
|
+
return new Promise(function(resolve4, reject) {
|
|
23423
23423
|
isexe(path11, options || {}, function(er, is) {
|
|
23424
23424
|
if (er) {
|
|
23425
23425
|
reject(er);
|
|
23426
23426
|
} else {
|
|
23427
|
-
|
|
23427
|
+
resolve4(is);
|
|
23428
23428
|
}
|
|
23429
23429
|
});
|
|
23430
23430
|
});
|
|
@@ -23486,27 +23486,27 @@ var require_which = __commonJS((exports, module) => {
|
|
|
23486
23486
|
opt = {};
|
|
23487
23487
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
23488
23488
|
const found = [];
|
|
23489
|
-
const step = (i) => new Promise((
|
|
23489
|
+
const step = (i) => new Promise((resolve4, reject) => {
|
|
23490
23490
|
if (i === pathEnv.length)
|
|
23491
|
-
return opt.all && found.length ?
|
|
23491
|
+
return opt.all && found.length ? resolve4(found) : reject(getNotFoundError(cmd));
|
|
23492
23492
|
const ppRaw = pathEnv[i];
|
|
23493
23493
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
23494
23494
|
const pCmd = path11.join(pathPart, cmd);
|
|
23495
23495
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
23496
|
-
|
|
23496
|
+
resolve4(subStep(p, i, 0));
|
|
23497
23497
|
});
|
|
23498
|
-
const subStep = (p, i, ii) => new Promise((
|
|
23498
|
+
const subStep = (p, i, ii) => new Promise((resolve4, reject) => {
|
|
23499
23499
|
if (ii === pathExt.length)
|
|
23500
|
-
return
|
|
23500
|
+
return resolve4(step(i + 1));
|
|
23501
23501
|
const ext = pathExt[ii];
|
|
23502
23502
|
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
23503
23503
|
if (!er && is) {
|
|
23504
23504
|
if (opt.all)
|
|
23505
23505
|
found.push(p + ext);
|
|
23506
23506
|
else
|
|
23507
|
-
return
|
|
23507
|
+
return resolve4(p + ext);
|
|
23508
23508
|
}
|
|
23509
|
-
return
|
|
23509
|
+
return resolve4(subStep(p, i, ii + 1));
|
|
23510
23510
|
});
|
|
23511
23511
|
});
|
|
23512
23512
|
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
@@ -221220,7 +221220,7 @@ var require_dist5 = __commonJS((exports, module) => {
|
|
|
221220
221220
|
determineAgent: () => determineAgent
|
|
221221
221221
|
});
|
|
221222
221222
|
module.exports = __toCommonJS2(src_exports);
|
|
221223
|
-
var
|
|
221223
|
+
var import_promises26 = __require("node:fs/promises");
|
|
221224
221224
|
var import_node_fs24 = __require("node:fs");
|
|
221225
221225
|
var DEVIN_LOCAL_PATH = "/opt/.devin";
|
|
221226
221226
|
var CURSOR2 = "cursor";
|
|
@@ -221278,7 +221278,7 @@ var require_dist5 = __commonJS((exports, module) => {
|
|
|
221278
221278
|
return { isAgent: true, agent: { name: REPLIT } };
|
|
221279
221279
|
}
|
|
221280
221280
|
try {
|
|
221281
|
-
await (0,
|
|
221281
|
+
await (0, import_promises26.access)(DEVIN_LOCAL_PATH, import_node_fs24.constants.F_OK);
|
|
221282
221282
|
return { isAgent: true, agent: { name: DEVIN } };
|
|
221283
221283
|
} catch (error48) {}
|
|
221284
221284
|
return { isAgent: false, agent: undefined };
|
|
@@ -248113,6 +248113,7 @@ var package_default = {
|
|
|
248113
248113
|
nanoid: "^5.1.6",
|
|
248114
248114
|
open: "^11.0.0",
|
|
248115
248115
|
outdent: "^0.8.0",
|
|
248116
|
+
"p-map": "^7.0.6",
|
|
248116
248117
|
"p-wait-for": "^6.0.0",
|
|
248117
248118
|
"posthog-node": "5.21.2",
|
|
248118
248119
|
qs: "^6.12.3",
|
|
@@ -248258,7 +248259,7 @@ async function createProjectFilesForExistingProject(options) {
|
|
|
248258
248259
|
};
|
|
248259
248260
|
}
|
|
248260
248261
|
// src/core/project/deploy.ts
|
|
248261
|
-
import { resolve as
|
|
248262
|
+
import { resolve as resolve3 } from "node:path";
|
|
248262
248263
|
|
|
248263
248264
|
// src/core/site/api.ts
|
|
248264
248265
|
async function uploadSite(archivePath) {
|
|
@@ -248361,13 +248362,588 @@ async function createArchive(pathToArchive, targetArchivePath) {
|
|
|
248361
248362
|
cwd: pathToArchive
|
|
248362
248363
|
}, ["."]);
|
|
248363
248364
|
}
|
|
248364
|
-
// src/core/site/
|
|
248365
|
-
|
|
248366
|
-
|
|
248365
|
+
// src/core/site/gate.ts
|
|
248366
|
+
var STATIC_DEPLOYMENTS_ENV = "BASE44_STATIC_DEPLOYMENTS";
|
|
248367
|
+
function staticDeploymentsEnabled(env2 = process.env) {
|
|
248368
|
+
const value = env2[STATIC_DEPLOYMENTS_ENV];
|
|
248369
|
+
return value === "1" || value === "true";
|
|
248370
|
+
}
|
|
248371
|
+
// src/core/site/manifest.ts
|
|
248372
|
+
import { createHash } from "node:crypto";
|
|
248373
|
+
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
248374
|
+
import { basename as basename4, join as join15 } from "node:path";
|
|
248375
|
+
var MAX_ASSET_SIZE_BYTES = 25 * 1024 * 1024;
|
|
248376
|
+
var MAX_ASSET_COUNT = 1e5;
|
|
248377
|
+
var ASSETS_IGNORE_FILE = ".assetsignore";
|
|
248378
|
+
var ALWAYS_IGNORED = new Set([
|
|
248379
|
+
ASSETS_IGNORE_FILE,
|
|
248380
|
+
"wrangler.json",
|
|
248381
|
+
".dev.vars"
|
|
248382
|
+
]);
|
|
248383
|
+
function hashAsset(appId, content) {
|
|
248384
|
+
return createHash("sha256").update(Buffer.from(appId, "utf8")).update(content).digest("hex").slice(0, 32);
|
|
248385
|
+
}
|
|
248386
|
+
async function buildAssetManifest(assetsDir, appId) {
|
|
248387
|
+
const manifest = {};
|
|
248388
|
+
const filesByHash = new Map;
|
|
248389
|
+
const found = await globby("**/*", {
|
|
248390
|
+
cwd: assetsDir,
|
|
248391
|
+
dot: true,
|
|
248392
|
+
onlyFiles: true,
|
|
248393
|
+
followSymbolicLinks: false,
|
|
248394
|
+
ignoreFiles: [ASSETS_IGNORE_FILE]
|
|
248395
|
+
});
|
|
248396
|
+
const relativeFilePaths = found.filter((path11) => !ALWAYS_IGNORED.has(basename4(path11)));
|
|
248397
|
+
if (relativeFilePaths.length > MAX_ASSET_COUNT) {
|
|
248398
|
+
throw new InvalidInputError(`Too many static assets: found ${relativeFilePaths.length}, the limit is ${MAX_ASSET_COUNT} files.`);
|
|
248399
|
+
}
|
|
248400
|
+
for (const relativePath of relativeFilePaths.sort()) {
|
|
248401
|
+
const absolutePath = join15(assetsDir, ...relativePath.split("/"));
|
|
248402
|
+
const { size } = await stat(absolutePath);
|
|
248403
|
+
if (size > MAX_ASSET_SIZE_BYTES) {
|
|
248404
|
+
throw new InvalidInputError(`Static asset "${relativePath}" is ${size} bytes, which exceeds the 25 MiB per-file limit.`);
|
|
248405
|
+
}
|
|
248406
|
+
const content = await readFile2(absolutePath);
|
|
248407
|
+
const hash2 = hashAsset(appId, content);
|
|
248408
|
+
manifest[`/${relativePath}`] = { hash: hash2, size };
|
|
248409
|
+
if (!filesByHash.has(hash2)) {
|
|
248410
|
+
filesByHash.set(hash2, { absolutePath, hash: hash2, size });
|
|
248411
|
+
}
|
|
248412
|
+
}
|
|
248413
|
+
return { manifest, filesByHash };
|
|
248414
|
+
}
|
|
248367
248415
|
// src/core/site/static-site.ts
|
|
248368
248416
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
248369
248417
|
import { join as join16 } from "node:path";
|
|
248370
248418
|
|
|
248419
|
+
// src/core/site/upload.ts
|
|
248420
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
248421
|
+
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
248422
|
+
|
|
248423
|
+
// ../../node_modules/p-map/index.js
|
|
248424
|
+
async function pMap(iterable, mapper, {
|
|
248425
|
+
concurrency = Number.POSITIVE_INFINITY,
|
|
248426
|
+
stopOnError = true,
|
|
248427
|
+
signal
|
|
248428
|
+
} = {}) {
|
|
248429
|
+
return new Promise((resolve_, reject_) => {
|
|
248430
|
+
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
|
|
248431
|
+
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
|
|
248432
|
+
}
|
|
248433
|
+
if (typeof mapper !== "function") {
|
|
248434
|
+
throw new TypeError("Mapper function is required");
|
|
248435
|
+
}
|
|
248436
|
+
if (!(Number.isSafeInteger(concurrency) && concurrency >= 1 || concurrency === Number.POSITIVE_INFINITY)) {
|
|
248437
|
+
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
|
|
248438
|
+
}
|
|
248439
|
+
const result = [];
|
|
248440
|
+
const errors4 = [];
|
|
248441
|
+
const skippedIndexesMap = new Map;
|
|
248442
|
+
let isRejected = false;
|
|
248443
|
+
let isResolved = false;
|
|
248444
|
+
let isIterableDone = false;
|
|
248445
|
+
let resolvingCount = 0;
|
|
248446
|
+
let currentIndex = 0;
|
|
248447
|
+
const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
|
|
248448
|
+
const signalListener = () => {
|
|
248449
|
+
reject(signal.reason);
|
|
248450
|
+
};
|
|
248451
|
+
const cleanup = () => {
|
|
248452
|
+
signal?.removeEventListener("abort", signalListener);
|
|
248453
|
+
};
|
|
248454
|
+
const resolve3 = (value) => {
|
|
248455
|
+
resolve_(value);
|
|
248456
|
+
cleanup();
|
|
248457
|
+
};
|
|
248458
|
+
const reject = (reason) => {
|
|
248459
|
+
isRejected = true;
|
|
248460
|
+
isResolved = true;
|
|
248461
|
+
reject_(reason);
|
|
248462
|
+
cleanup();
|
|
248463
|
+
};
|
|
248464
|
+
if (signal) {
|
|
248465
|
+
if (signal.aborted) {
|
|
248466
|
+
reject(signal.reason);
|
|
248467
|
+
return;
|
|
248468
|
+
}
|
|
248469
|
+
signal.addEventListener("abort", signalListener, { once: true });
|
|
248470
|
+
}
|
|
248471
|
+
const next = async () => {
|
|
248472
|
+
if (isResolved) {
|
|
248473
|
+
return;
|
|
248474
|
+
}
|
|
248475
|
+
const nextItem = await iterator.next();
|
|
248476
|
+
const index = currentIndex;
|
|
248477
|
+
currentIndex++;
|
|
248478
|
+
if (nextItem.done) {
|
|
248479
|
+
isIterableDone = true;
|
|
248480
|
+
if (resolvingCount === 0 && !isResolved) {
|
|
248481
|
+
if (!stopOnError && errors4.length > 0) {
|
|
248482
|
+
reject(new AggregateError(errors4));
|
|
248483
|
+
return;
|
|
248484
|
+
}
|
|
248485
|
+
isResolved = true;
|
|
248486
|
+
if (skippedIndexesMap.size === 0) {
|
|
248487
|
+
resolve3(result);
|
|
248488
|
+
return;
|
|
248489
|
+
}
|
|
248490
|
+
const pureResult = [];
|
|
248491
|
+
for (const [index2, value] of result.entries()) {
|
|
248492
|
+
if (skippedIndexesMap.get(index2) === pMapSkip) {
|
|
248493
|
+
continue;
|
|
248494
|
+
}
|
|
248495
|
+
pureResult.push(value);
|
|
248496
|
+
}
|
|
248497
|
+
resolve3(pureResult);
|
|
248498
|
+
}
|
|
248499
|
+
return;
|
|
248500
|
+
}
|
|
248501
|
+
resolvingCount++;
|
|
248502
|
+
(async () => {
|
|
248503
|
+
try {
|
|
248504
|
+
const element = await nextItem.value;
|
|
248505
|
+
if (isResolved) {
|
|
248506
|
+
return;
|
|
248507
|
+
}
|
|
248508
|
+
const value = await mapper(element, index);
|
|
248509
|
+
if (value === pMapSkip) {
|
|
248510
|
+
skippedIndexesMap.set(index, value);
|
|
248511
|
+
}
|
|
248512
|
+
result[index] = value;
|
|
248513
|
+
resolvingCount--;
|
|
248514
|
+
await next();
|
|
248515
|
+
} catch (error48) {
|
|
248516
|
+
if (stopOnError) {
|
|
248517
|
+
reject(error48);
|
|
248518
|
+
} else {
|
|
248519
|
+
errors4.push(error48);
|
|
248520
|
+
resolvingCount--;
|
|
248521
|
+
try {
|
|
248522
|
+
await next();
|
|
248523
|
+
} catch (error49) {
|
|
248524
|
+
reject(error49);
|
|
248525
|
+
}
|
|
248526
|
+
}
|
|
248527
|
+
}
|
|
248528
|
+
})();
|
|
248529
|
+
};
|
|
248530
|
+
(async () => {
|
|
248531
|
+
for (let index = 0;index < concurrency; index++) {
|
|
248532
|
+
try {
|
|
248533
|
+
await next();
|
|
248534
|
+
} catch (error48) {
|
|
248535
|
+
reject(error48);
|
|
248536
|
+
break;
|
|
248537
|
+
}
|
|
248538
|
+
if (isIterableDone || isRejected) {
|
|
248539
|
+
break;
|
|
248540
|
+
}
|
|
248541
|
+
}
|
|
248542
|
+
})();
|
|
248543
|
+
});
|
|
248544
|
+
}
|
|
248545
|
+
var pMapSkip = Symbol("skip");
|
|
248546
|
+
|
|
248547
|
+
// src/core/site/upload.ts
|
|
248548
|
+
var DEFAULT_UPLOAD_CONCURRENCY = 3;
|
|
248549
|
+
var MAX_UPLOAD_CONCURRENCY = 50;
|
|
248550
|
+
var MAX_ATTEMPTS_PER_UPLOAD = 3;
|
|
248551
|
+
var RETRY_BASE_DELAY_MS = 500;
|
|
248552
|
+
async function uploadPresignedAssets(uploads, assets, options = {}) {
|
|
248553
|
+
const { concurrency = DEFAULT_UPLOAD_CONCURRENCY, onProgress } = options;
|
|
248554
|
+
let uploadedFiles = 0;
|
|
248555
|
+
await pMap(uploads, async (upload) => {
|
|
248556
|
+
await uploadPresignedAssetWithRetry(upload, assets);
|
|
248557
|
+
uploadedFiles++;
|
|
248558
|
+
onProgress?.({ uploadedFiles, totalFiles: uploads.length });
|
|
248559
|
+
}, { concurrency });
|
|
248560
|
+
}
|
|
248561
|
+
async function uploadPresignedAssetWithRetry(upload, assets) {
|
|
248562
|
+
const entry = assets.manifest[upload.path];
|
|
248563
|
+
const file2 = entry && assets.filesByHash.get(entry.hash);
|
|
248564
|
+
if (!file2) {
|
|
248565
|
+
throw new InternalError(`Server requested upload of unknown asset path: ${upload.path}`);
|
|
248566
|
+
}
|
|
248567
|
+
const content = await readFile3(file2.absolutePath);
|
|
248568
|
+
let lastError;
|
|
248569
|
+
for (let attempt = 0;attempt < MAX_ATTEMPTS_PER_UPLOAD; attempt++) {
|
|
248570
|
+
if (attempt > 0) {
|
|
248571
|
+
await sleep3(RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
|
|
248572
|
+
}
|
|
248573
|
+
try {
|
|
248574
|
+
await distribution_default.put(upload.url, {
|
|
248575
|
+
body: new Uint8Array(content),
|
|
248576
|
+
headers: { "Content-Type": upload.contentType },
|
|
248577
|
+
timeout: 120000,
|
|
248578
|
+
retry: 0
|
|
248579
|
+
});
|
|
248580
|
+
return;
|
|
248581
|
+
} catch (error48) {
|
|
248582
|
+
lastError = error48;
|
|
248583
|
+
}
|
|
248584
|
+
}
|
|
248585
|
+
throw await ApiError.fromHttpError(lastError, "uploading static assets");
|
|
248586
|
+
}
|
|
248587
|
+
|
|
248588
|
+
// src/core/site/static-site.ts
|
|
248589
|
+
async function deployStaticSite(options) {
|
|
248590
|
+
const { outputDir, gitHash, concurrency, progress } = options;
|
|
248591
|
+
const assets = await buildAssetManifest(outputDir, getAppContext().id);
|
|
248592
|
+
if (!assets.manifest["/index.html"]) {
|
|
248593
|
+
throw new InvalidInputError(`No index.html found in "${outputDir}" — a static site needs one at the output directory root.`);
|
|
248594
|
+
}
|
|
248595
|
+
const created = await createDeployment({
|
|
248596
|
+
git_hash: gitHash,
|
|
248597
|
+
asset_manifest: assets.manifest
|
|
248598
|
+
});
|
|
248599
|
+
progress?.onAssets?.({
|
|
248600
|
+
totalAssets: Object.keys(assets.manifest).length,
|
|
248601
|
+
newAssets: created.assetUploads?.uploads.length ?? 0
|
|
248602
|
+
});
|
|
248603
|
+
if (created.assetUploads) {
|
|
248604
|
+
await uploadPresignedAssets(created.assetUploads.uploads, assets, {
|
|
248605
|
+
concurrency,
|
|
248606
|
+
onProgress: progress?.onAssetUpload
|
|
248607
|
+
});
|
|
248608
|
+
}
|
|
248609
|
+
const indexHtml = await readFile4(join16(outputDir, "index.html"));
|
|
248610
|
+
const finalized = await finalizeStaticDeployment(created.deploymentId, new Uint8Array(indexHtml));
|
|
248611
|
+
return { deploymentId: finalized.deploymentId };
|
|
248612
|
+
}
|
|
248613
|
+
// src/core/project/deploy.ts
|
|
248614
|
+
function hasResourcesToDeploy(projectData) {
|
|
248615
|
+
const {
|
|
248616
|
+
project,
|
|
248617
|
+
entities,
|
|
248618
|
+
functions,
|
|
248619
|
+
agents,
|
|
248620
|
+
agentSkills,
|
|
248621
|
+
connectors,
|
|
248622
|
+
authConfig
|
|
248623
|
+
} = projectData;
|
|
248624
|
+
const hasSite = Boolean(project.site?.outputDirectory);
|
|
248625
|
+
const hasEntities = entities.length > 0;
|
|
248626
|
+
const hasFunctions = functions.length > 0;
|
|
248627
|
+
const hasAgents = agents.length > 0;
|
|
248628
|
+
const hasAgentSkills = agentSkills.length > 0;
|
|
248629
|
+
const hasConnectors = connectors.length > 0;
|
|
248630
|
+
const hasAuthConfig = authConfig.length > 0;
|
|
248631
|
+
const hasVisibility = Boolean(project.visibility);
|
|
248632
|
+
return hasEntities || hasFunctions || hasAgents || hasAgentSkills || hasConnectors || hasAuthConfig || hasVisibility || hasSite;
|
|
248633
|
+
}
|
|
248634
|
+
async function deployAll(projectData, options) {
|
|
248635
|
+
const {
|
|
248636
|
+
project,
|
|
248637
|
+
entities,
|
|
248638
|
+
functions,
|
|
248639
|
+
agents,
|
|
248640
|
+
agentSkills,
|
|
248641
|
+
connectors,
|
|
248642
|
+
authConfig
|
|
248643
|
+
} = projectData;
|
|
248644
|
+
await setAppVisibility(project.visibility);
|
|
248645
|
+
if (project.visibility) {
|
|
248646
|
+
options?.onVisibilitySet?.(project.visibility);
|
|
248647
|
+
}
|
|
248648
|
+
await entityResource.push(entities);
|
|
248649
|
+
await deployFunctionsSequentially(functions, {
|
|
248650
|
+
onStart: options?.onFunctionStart,
|
|
248651
|
+
onResult: options?.onFunctionResult
|
|
248652
|
+
});
|
|
248653
|
+
await agentSkillResource.push(agentSkills);
|
|
248654
|
+
await agentResource.push(agents);
|
|
248655
|
+
await authConfigResource.push(authConfig);
|
|
248656
|
+
const skipConnectorSync = connectors.length === 0 && hasWorkspaceApiKeyAuth();
|
|
248657
|
+
const connectorResults = skipConnectorSync ? [] : (await pushConnectors(connectors)).results;
|
|
248658
|
+
if (project.site?.outputDirectory) {
|
|
248659
|
+
const outputDir = resolve3(project.root, project.site.outputDirectory);
|
|
248660
|
+
const { appUrl } = await deploySite(outputDir);
|
|
248661
|
+
return { appUrl, connectorResults };
|
|
248662
|
+
}
|
|
248663
|
+
return { connectorResults };
|
|
248664
|
+
}
|
|
248665
|
+
// src/core/clients/base44-client.ts
|
|
248666
|
+
var retriedRequests = new WeakSet;
|
|
248667
|
+
async function captureRequestBody(request, options) {
|
|
248668
|
+
if (request.body == null) {
|
|
248669
|
+
return;
|
|
248670
|
+
}
|
|
248671
|
+
try {
|
|
248672
|
+
const cloned = request.clone();
|
|
248673
|
+
const text = await cloned.text();
|
|
248674
|
+
options.context.__requestBody = text;
|
|
248675
|
+
} catch {}
|
|
248676
|
+
}
|
|
248677
|
+
async function handleUnauthorized(request, _options, response) {
|
|
248678
|
+
if (response.status !== 401) {
|
|
248679
|
+
return;
|
|
248680
|
+
}
|
|
248681
|
+
if (hasWorkspaceApiKeyAuth()) {
|
|
248682
|
+
return;
|
|
248683
|
+
}
|
|
248684
|
+
if (retriedRequests.has(request)) {
|
|
248685
|
+
return;
|
|
248686
|
+
}
|
|
248687
|
+
const newAccessToken = await refreshAndSaveTokens();
|
|
248688
|
+
if (!newAccessToken) {
|
|
248689
|
+
return;
|
|
248690
|
+
}
|
|
248691
|
+
retriedRequests.add(request);
|
|
248692
|
+
const requestId = request.headers.get("X-Request-ID");
|
|
248693
|
+
return distribution_default(request.clone(), {
|
|
248694
|
+
headers: {
|
|
248695
|
+
...requestId && { "X-Request-ID": requestId },
|
|
248696
|
+
Authorization: `Bearer ${newAccessToken}`
|
|
248697
|
+
}
|
|
248698
|
+
});
|
|
248699
|
+
}
|
|
248700
|
+
var base44Client = distribution_default.create({
|
|
248701
|
+
prefixUrl: getBase44ApiUrl(),
|
|
248702
|
+
headers: {
|
|
248703
|
+
"User-Agent": "Base44 CLI"
|
|
248704
|
+
},
|
|
248705
|
+
hooks: {
|
|
248706
|
+
beforeRequest: [
|
|
248707
|
+
(request) => {
|
|
248708
|
+
request.headers.set("X-Request-ID", randomUUID2());
|
|
248709
|
+
},
|
|
248710
|
+
captureRequestBody,
|
|
248711
|
+
async (request) => {
|
|
248712
|
+
const workspaceApiKey = getWorkspaceApiKeyFromEnv();
|
|
248713
|
+
if (workspaceApiKey && isWorkspaceApiKey(workspaceApiKey)) {
|
|
248714
|
+
request.headers.set("api_key", workspaceApiKey);
|
|
248715
|
+
return;
|
|
248716
|
+
}
|
|
248717
|
+
try {
|
|
248718
|
+
const auth = await readAuth();
|
|
248719
|
+
if (isTokenExpired(auth)) {
|
|
248720
|
+
const newAccessToken = await refreshAndSaveTokens();
|
|
248721
|
+
if (newAccessToken) {
|
|
248722
|
+
request.headers.set("Authorization", `Bearer ${newAccessToken}`);
|
|
248723
|
+
return;
|
|
248724
|
+
}
|
|
248725
|
+
}
|
|
248726
|
+
request.headers.set("Authorization", `Bearer ${auth.accessToken}`);
|
|
248727
|
+
} catch {}
|
|
248728
|
+
}
|
|
248729
|
+
],
|
|
248730
|
+
afterResponse: [handleUnauthorized]
|
|
248731
|
+
}
|
|
248732
|
+
});
|
|
248733
|
+
function getAppClient() {
|
|
248734
|
+
const { id } = getAppContext();
|
|
248735
|
+
return base44Client.extend({
|
|
248736
|
+
prefixUrl: new URL(`/api/apps/${id}/`, getBase44ApiUrl()).href
|
|
248737
|
+
});
|
|
248738
|
+
}
|
|
248739
|
+
function getSandboxClient(appId) {
|
|
248740
|
+
return base44Client.extend({
|
|
248741
|
+
prefixUrl: new URL(`/api/apps/${appId}/sandbox-bridge/`, getBase44ApiUrl()).href
|
|
248742
|
+
});
|
|
248743
|
+
}
|
|
248744
|
+
// src/core/clients/oauth-client.ts
|
|
248745
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
248746
|
+
var oauthClient = distribution_default.create({
|
|
248747
|
+
prefixUrl: getBase44ApiUrl(),
|
|
248748
|
+
headers: {
|
|
248749
|
+
"User-Agent": "Base44 CLI"
|
|
248750
|
+
},
|
|
248751
|
+
hooks: {
|
|
248752
|
+
beforeRequest: [
|
|
248753
|
+
(request) => {
|
|
248754
|
+
request.headers.set("X-Request-ID", randomUUID3());
|
|
248755
|
+
}
|
|
248756
|
+
]
|
|
248757
|
+
}
|
|
248758
|
+
});
|
|
248759
|
+
// src/core/auth/api.ts
|
|
248760
|
+
async function generateDeviceCode() {
|
|
248761
|
+
const response = await oauthClient.post("oauth/device/code", {
|
|
248762
|
+
json: {
|
|
248763
|
+
client_id: AUTH_CLIENT_ID,
|
|
248764
|
+
scope: "apps:read apps:write sandbox:write"
|
|
248765
|
+
},
|
|
248766
|
+
throwHttpErrors: false
|
|
248767
|
+
});
|
|
248768
|
+
if (!response.ok) {
|
|
248769
|
+
throw new ApiError(`Failed to generate device code: ${response.status} ${response.statusText}`, { statusCode: response.status });
|
|
248770
|
+
}
|
|
248771
|
+
const result = DeviceCodeResponseSchema.safeParse(await response.json());
|
|
248772
|
+
if (!result.success) {
|
|
248773
|
+
throw new SchemaValidationError("Invalid device code response from server", result.error);
|
|
248774
|
+
}
|
|
248775
|
+
return result.data;
|
|
248776
|
+
}
|
|
248777
|
+
async function getTokenFromDeviceCode(deviceCode) {
|
|
248778
|
+
const searchParams = new URLSearchParams;
|
|
248779
|
+
searchParams.set("grant_type", "urn:ietf:params:oauth:grant-type:device_code");
|
|
248780
|
+
searchParams.set("device_code", deviceCode);
|
|
248781
|
+
searchParams.set("client_id", AUTH_CLIENT_ID);
|
|
248782
|
+
const response = await oauthClient.post("oauth/token", {
|
|
248783
|
+
body: searchParams.toString(),
|
|
248784
|
+
headers: {
|
|
248785
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
248786
|
+
},
|
|
248787
|
+
throwHttpErrors: false
|
|
248788
|
+
});
|
|
248789
|
+
const json2 = await response.json();
|
|
248790
|
+
if (!response.ok) {
|
|
248791
|
+
const errorResult = OAuthErrorSchema.safeParse(json2);
|
|
248792
|
+
if (!errorResult.success) {
|
|
248793
|
+
throw new SchemaValidationError("Token request failed", errorResult.error);
|
|
248794
|
+
}
|
|
248795
|
+
const { error: error48, error_description } = errorResult.data;
|
|
248796
|
+
if (error48 === "authorization_pending" || error48 === "slow_down") {
|
|
248797
|
+
return null;
|
|
248798
|
+
}
|
|
248799
|
+
throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
|
|
248800
|
+
statusCode: response.status
|
|
248801
|
+
});
|
|
248802
|
+
}
|
|
248803
|
+
const result = TokenResponseSchema.safeParse(json2);
|
|
248804
|
+
if (!result.success) {
|
|
248805
|
+
throw new SchemaValidationError("Invalid token response from server", result.error);
|
|
248806
|
+
}
|
|
248807
|
+
return result.data;
|
|
248808
|
+
}
|
|
248809
|
+
async function renewAccessToken(refreshToken) {
|
|
248810
|
+
const searchParams = new URLSearchParams;
|
|
248811
|
+
searchParams.set("grant_type", "refresh_token");
|
|
248812
|
+
searchParams.set("refresh_token", refreshToken);
|
|
248813
|
+
searchParams.set("client_id", AUTH_CLIENT_ID);
|
|
248814
|
+
const response = await oauthClient.post("oauth/token", {
|
|
248815
|
+
body: searchParams.toString(),
|
|
248816
|
+
headers: {
|
|
248817
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
248818
|
+
},
|
|
248819
|
+
throwHttpErrors: false
|
|
248820
|
+
});
|
|
248821
|
+
const json2 = await response.json();
|
|
248822
|
+
if (!response.ok) {
|
|
248823
|
+
const errorResult = OAuthErrorSchema.safeParse(json2);
|
|
248824
|
+
if (!errorResult.success) {
|
|
248825
|
+
throw new ApiError(`Token refresh failed: ${response.statusText}`, {
|
|
248826
|
+
statusCode: response.status
|
|
248827
|
+
});
|
|
248828
|
+
}
|
|
248829
|
+
const { error: error48, error_description } = errorResult.data;
|
|
248830
|
+
throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
|
|
248831
|
+
statusCode: response.status
|
|
248832
|
+
});
|
|
248833
|
+
}
|
|
248834
|
+
const result = TokenResponseSchema.safeParse(json2);
|
|
248835
|
+
if (!result.success) {
|
|
248836
|
+
throw new SchemaValidationError("Invalid token response from server", result.error);
|
|
248837
|
+
}
|
|
248838
|
+
return result.data;
|
|
248839
|
+
}
|
|
248840
|
+
async function getUserInfo(accessToken) {
|
|
248841
|
+
const response = await oauthClient.get("oauth/userinfo", {
|
|
248842
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
248843
|
+
});
|
|
248844
|
+
if (!response.ok) {
|
|
248845
|
+
throw new ApiError(`Failed to fetch user info: ${response.status}`, {
|
|
248846
|
+
statusCode: response.status
|
|
248847
|
+
});
|
|
248848
|
+
}
|
|
248849
|
+
const result = UserInfoSchema.safeParse(await response.json());
|
|
248850
|
+
if (!result.success) {
|
|
248851
|
+
throw new SchemaValidationError("Invalid UserInfo response from server", result.error);
|
|
248852
|
+
}
|
|
248853
|
+
return result.data;
|
|
248854
|
+
}
|
|
248855
|
+
// src/cli/commands/auth/login-flow.ts
|
|
248856
|
+
async function generateAndDisplayDeviceCode(log, runTask) {
|
|
248857
|
+
const deviceCodeResponse = await runTask("Generating device code...", async () => {
|
|
248858
|
+
return await generateDeviceCode();
|
|
248859
|
+
}, {
|
|
248860
|
+
successMessage: "Device code generated",
|
|
248861
|
+
errorMessage: "Failed to generate device code"
|
|
248862
|
+
});
|
|
248863
|
+
log.info(`Verification code: ${theme.styles.bold(deviceCodeResponse.userCode)}` + `
|
|
248864
|
+
Please confirm this code at: ${deviceCodeResponse.verificationUri}`);
|
|
248865
|
+
return deviceCodeResponse;
|
|
248866
|
+
}
|
|
248867
|
+
async function waitForAuthentication(deviceCode, expiresIn, interval, runTask) {
|
|
248868
|
+
let tokenResponse;
|
|
248869
|
+
try {
|
|
248870
|
+
await runTask("Waiting for authentication...", async () => {
|
|
248871
|
+
await pWaitFor(async () => {
|
|
248872
|
+
const result = await getTokenFromDeviceCode(deviceCode);
|
|
248873
|
+
if (result !== null) {
|
|
248874
|
+
tokenResponse = result;
|
|
248875
|
+
return true;
|
|
248876
|
+
}
|
|
248877
|
+
return false;
|
|
248878
|
+
}, {
|
|
248879
|
+
interval: interval * 1000,
|
|
248880
|
+
timeout: expiresIn * 1000
|
|
248881
|
+
});
|
|
248882
|
+
}, {
|
|
248883
|
+
successMessage: "Authentication completed!",
|
|
248884
|
+
errorMessage: "Authentication failed"
|
|
248885
|
+
});
|
|
248886
|
+
} catch (error48) {
|
|
248887
|
+
if (error48 instanceof Error && error48.message.includes("timed out")) {
|
|
248888
|
+
throw new AuthExpiredError("Authentication timed out. Please try again.");
|
|
248889
|
+
}
|
|
248890
|
+
throw error48;
|
|
248891
|
+
}
|
|
248892
|
+
if (tokenResponse === undefined) {
|
|
248893
|
+
throw new InternalError("Failed to retrieve authentication token.");
|
|
248894
|
+
}
|
|
248895
|
+
return tokenResponse;
|
|
248896
|
+
}
|
|
248897
|
+
async function saveAuthData(response, userInfo) {
|
|
248898
|
+
const expiresAt = Date.now() + response.expiresIn * 1000;
|
|
248899
|
+
await writeAuth({
|
|
248900
|
+
accessToken: response.accessToken,
|
|
248901
|
+
refreshToken: response.refreshToken,
|
|
248902
|
+
expiresAt,
|
|
248903
|
+
email: userInfo.email,
|
|
248904
|
+
name: userInfo.name
|
|
248905
|
+
});
|
|
248906
|
+
}
|
|
248907
|
+
async function login({
|
|
248908
|
+
log,
|
|
248909
|
+
runTask
|
|
248910
|
+
}) {
|
|
248911
|
+
const deviceCodeResponse = await generateAndDisplayDeviceCode(log, runTask);
|
|
248912
|
+
const token = await waitForAuthentication(deviceCodeResponse.deviceCode, deviceCodeResponse.expiresIn, deviceCodeResponse.interval, runTask);
|
|
248913
|
+
const userInfo = await getUserInfo(token.accessToken);
|
|
248914
|
+
await saveAuthData(token, userInfo);
|
|
248915
|
+
return {
|
|
248916
|
+
outroMessage: `Successfully logged in as ${theme.styles.bold(userInfo.email)}`
|
|
248917
|
+
};
|
|
248918
|
+
}
|
|
248919
|
+
|
|
248920
|
+
// src/cli/utils/command/middleware.ts
|
|
248921
|
+
async function ensureAuth(ctx) {
|
|
248922
|
+
if (hasWorkspaceApiKeyAuth()) {
|
|
248923
|
+
ctx.errorReporter.setContext({
|
|
248924
|
+
user: { email: "workspace-api-key", name: "Workspace API key" }
|
|
248925
|
+
});
|
|
248926
|
+
return;
|
|
248927
|
+
}
|
|
248928
|
+
await seedAuthFromEnv();
|
|
248929
|
+
const loggedIn = await isLoggedIn();
|
|
248930
|
+
if (!loggedIn) {
|
|
248931
|
+
ctx.log.info("You need to login first to continue.");
|
|
248932
|
+
await login(ctx);
|
|
248933
|
+
}
|
|
248934
|
+
try {
|
|
248935
|
+
const userInfo = await readAuth();
|
|
248936
|
+
ctx.errorReporter.setContext({
|
|
248937
|
+
user: { email: userInfo.email, name: userInfo.name }
|
|
248938
|
+
});
|
|
248939
|
+
} catch {}
|
|
248940
|
+
}
|
|
248941
|
+
async function ensureAppContext(ctx, options = {}) {
|
|
248942
|
+
const appContext = await initAppContext(options);
|
|
248943
|
+
ctx.app = appContext;
|
|
248944
|
+
ctx.errorReporter.setContext({ appId: appContext.id });
|
|
248945
|
+
}
|
|
248946
|
+
|
|
248371
248947
|
// ../../node_modules/is-plain-obj/index.js
|
|
248372
248948
|
function isPlainObject2(value) {
|
|
248373
248949
|
if (typeof value !== "object" || value === null) {
|
|
@@ -248465,13 +249041,13 @@ var getJoinLength = (uint8Arrays) => {
|
|
|
248465
249041
|
var isTemplateString = (templates) => Array.isArray(templates) && Array.isArray(templates.raw);
|
|
248466
249042
|
var parseTemplates = (templates, expressions) => {
|
|
248467
249043
|
let tokens = [];
|
|
248468
|
-
for (const [index,
|
|
249044
|
+
for (const [index, template2] of templates.entries()) {
|
|
248469
249045
|
tokens = parseTemplate({
|
|
248470
249046
|
templates,
|
|
248471
249047
|
expressions,
|
|
248472
249048
|
tokens,
|
|
248473
249049
|
index,
|
|
248474
|
-
template
|
|
249050
|
+
template: template2
|
|
248475
249051
|
});
|
|
248476
249052
|
}
|
|
248477
249053
|
if (tokens.length === 0) {
|
|
@@ -248480,11 +249056,11 @@ var parseTemplates = (templates, expressions) => {
|
|
|
248480
249056
|
const [file2, ...commandArguments] = tokens;
|
|
248481
249057
|
return [file2, commandArguments, {}];
|
|
248482
249058
|
};
|
|
248483
|
-
var parseTemplate = ({ templates, expressions, tokens, index, template }) => {
|
|
248484
|
-
if (
|
|
249059
|
+
var parseTemplate = ({ templates, expressions, tokens, index, template: template2 }) => {
|
|
249060
|
+
if (template2 === undefined) {
|
|
248485
249061
|
throw new TypeError(`Invalid backslash sequence: ${templates.raw[index]}`);
|
|
248486
249062
|
}
|
|
248487
|
-
const { nextTokens, leadingWhitespaces, trailingWhitespaces } = splitByWhitespaces(
|
|
249063
|
+
const { nextTokens, leadingWhitespaces, trailingWhitespaces } = splitByWhitespaces(template2, templates.raw[index]);
|
|
248488
249064
|
const newTokens = concatTokens(tokens, nextTokens, leadingWhitespaces);
|
|
248489
249065
|
if (index === expressions.length) {
|
|
248490
249066
|
return newTokens;
|
|
@@ -248493,18 +249069,18 @@ var parseTemplate = ({ templates, expressions, tokens, index, template }) => {
|
|
|
248493
249069
|
const expressionTokens = Array.isArray(expression) ? expression.map((expression2) => parseExpression(expression2)) : [parseExpression(expression)];
|
|
248494
249070
|
return concatTokens(newTokens, expressionTokens, trailingWhitespaces);
|
|
248495
249071
|
};
|
|
248496
|
-
var splitByWhitespaces = (
|
|
249072
|
+
var splitByWhitespaces = (template2, rawTemplate) => {
|
|
248497
249073
|
if (rawTemplate.length === 0) {
|
|
248498
249074
|
return { nextTokens: [], leadingWhitespaces: false, trailingWhitespaces: false };
|
|
248499
249075
|
}
|
|
248500
249076
|
const nextTokens = [];
|
|
248501
249077
|
let templateStart = 0;
|
|
248502
249078
|
const leadingWhitespaces = DELIMITERS.has(rawTemplate[0]);
|
|
248503
|
-
for (let templateIndex = 0, rawIndex = 0;templateIndex <
|
|
249079
|
+
for (let templateIndex = 0, rawIndex = 0;templateIndex < template2.length; templateIndex += 1, rawIndex += 1) {
|
|
248504
249080
|
const rawCharacter = rawTemplate[rawIndex];
|
|
248505
249081
|
if (DELIMITERS.has(rawCharacter)) {
|
|
248506
249082
|
if (templateStart !== templateIndex) {
|
|
248507
|
-
nextTokens.push(
|
|
249083
|
+
nextTokens.push(template2.slice(templateStart, templateIndex));
|
|
248508
249084
|
}
|
|
248509
249085
|
templateStart = templateIndex + 1;
|
|
248510
249086
|
} else if (rawCharacter === "\\") {
|
|
@@ -248520,9 +249096,9 @@ var splitByWhitespaces = (template, rawTemplate) => {
|
|
|
248520
249096
|
}
|
|
248521
249097
|
}
|
|
248522
249098
|
}
|
|
248523
|
-
const trailingWhitespaces = templateStart ===
|
|
249099
|
+
const trailingWhitespaces = templateStart === template2.length;
|
|
248524
249100
|
if (!trailingWhitespaces) {
|
|
248525
|
-
nextTokens.push(
|
|
249101
|
+
nextTokens.push(template2.slice(templateStart));
|
|
248526
249102
|
}
|
|
248527
249103
|
return { nextTokens, leadingWhitespaces, trailingWhitespaces };
|
|
248528
249104
|
};
|
|
@@ -249916,8 +250492,8 @@ var disconnect = (anyProcess) => {
|
|
|
249916
250492
|
// ../../node_modules/execa/lib/utils/deferred.js
|
|
249917
250493
|
var createDeferred = () => {
|
|
249918
250494
|
const methods = {};
|
|
249919
|
-
const promise2 = new Promise((
|
|
249920
|
-
Object.assign(methods, { resolve:
|
|
250495
|
+
const promise2 = new Promise((resolve4, reject) => {
|
|
250496
|
+
Object.assign(methods, { resolve: resolve4, reject });
|
|
249921
250497
|
});
|
|
249922
250498
|
return Object.assign(promise2, methods);
|
|
249923
250499
|
};
|
|
@@ -254281,11 +254857,11 @@ var addConcurrentStream = (concurrentStreams, stream, waitName) => {
|
|
|
254281
254857
|
const promises = weakMap.get(stream);
|
|
254282
254858
|
const promise2 = createDeferred();
|
|
254283
254859
|
promises.push(promise2);
|
|
254284
|
-
const
|
|
254285
|
-
return { resolve:
|
|
254860
|
+
const resolve4 = promise2.resolve.bind(promise2);
|
|
254861
|
+
return { resolve: resolve4, promises };
|
|
254286
254862
|
};
|
|
254287
|
-
var waitForConcurrentStreams = async ({ resolve:
|
|
254288
|
-
|
|
254863
|
+
var waitForConcurrentStreams = async ({ resolve: resolve4, promises }, subprocess) => {
|
|
254864
|
+
resolve4();
|
|
254289
254865
|
const [isSubprocessExit] = await Promise.race([
|
|
254290
254866
|
Promise.allSettled([true, subprocess]),
|
|
254291
254867
|
Promise.all([false, ...promises])
|
|
@@ -254864,522 +255440,6 @@ var {
|
|
|
254864
255440
|
getCancelSignal: getCancelSignal2
|
|
254865
255441
|
} = getIpcExport();
|
|
254866
255442
|
|
|
254867
|
-
// src/core/utils/git.ts
|
|
254868
|
-
var GIT_HASH_PATTERN = /^[a-fA-F0-9]{7,64}$/;
|
|
254869
|
-
function isGitCommitHash(value) {
|
|
254870
|
-
return GIT_HASH_PATTERN.test(value);
|
|
254871
|
-
}
|
|
254872
|
-
async function getGitHead(cwd) {
|
|
254873
|
-
try {
|
|
254874
|
-
const { stdout } = await execa("git", ["rev-parse", "HEAD"], { cwd });
|
|
254875
|
-
return stdout.trim();
|
|
254876
|
-
} catch {
|
|
254877
|
-
return null;
|
|
254878
|
-
}
|
|
254879
|
-
}
|
|
254880
|
-
|
|
254881
|
-
// src/core/site/manifest.ts
|
|
254882
|
-
import { createHash } from "node:crypto";
|
|
254883
|
-
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
254884
|
-
import { basename as basename4, join as join15 } from "node:path";
|
|
254885
|
-
var MAX_ASSET_SIZE_BYTES = 25 * 1024 * 1024;
|
|
254886
|
-
var MAX_ASSET_COUNT = 1e5;
|
|
254887
|
-
var ASSETS_IGNORE_FILE = ".assetsignore";
|
|
254888
|
-
var ALWAYS_IGNORED = new Set([
|
|
254889
|
-
ASSETS_IGNORE_FILE,
|
|
254890
|
-
"wrangler.json",
|
|
254891
|
-
".dev.vars"
|
|
254892
|
-
]);
|
|
254893
|
-
function hashAsset(appId, content) {
|
|
254894
|
-
return createHash("sha256").update(Buffer.from(appId, "utf8")).update(content).digest("hex").slice(0, 32);
|
|
254895
|
-
}
|
|
254896
|
-
async function buildAssetManifest(assetsDir, appId) {
|
|
254897
|
-
const manifest = {};
|
|
254898
|
-
const filesByHash = new Map;
|
|
254899
|
-
const found = await globby("**/*", {
|
|
254900
|
-
cwd: assetsDir,
|
|
254901
|
-
dot: true,
|
|
254902
|
-
onlyFiles: true,
|
|
254903
|
-
followSymbolicLinks: false,
|
|
254904
|
-
ignoreFiles: [ASSETS_IGNORE_FILE]
|
|
254905
|
-
});
|
|
254906
|
-
const relativeFilePaths = found.filter((path16) => !ALWAYS_IGNORED.has(basename4(path16)));
|
|
254907
|
-
if (relativeFilePaths.length > MAX_ASSET_COUNT) {
|
|
254908
|
-
throw new InvalidInputError(`Too many static assets: found ${relativeFilePaths.length}, the limit is ${MAX_ASSET_COUNT} files.`);
|
|
254909
|
-
}
|
|
254910
|
-
for (const relativePath of relativeFilePaths.sort()) {
|
|
254911
|
-
const absolutePath = join15(assetsDir, ...relativePath.split("/"));
|
|
254912
|
-
const { size } = await stat(absolutePath);
|
|
254913
|
-
if (size > MAX_ASSET_SIZE_BYTES) {
|
|
254914
|
-
throw new InvalidInputError(`Static asset "${relativePath}" is ${size} bytes, which exceeds the 25 MiB per-file limit.`);
|
|
254915
|
-
}
|
|
254916
|
-
const content = await readFile2(absolutePath);
|
|
254917
|
-
const hash2 = hashAsset(appId, content);
|
|
254918
|
-
manifest[`/${relativePath}`] = { hash: hash2, size };
|
|
254919
|
-
if (!filesByHash.has(hash2)) {
|
|
254920
|
-
filesByHash.set(hash2, { absolutePath, hash: hash2, size });
|
|
254921
|
-
}
|
|
254922
|
-
}
|
|
254923
|
-
return { manifest, filesByHash };
|
|
254924
|
-
}
|
|
254925
|
-
|
|
254926
|
-
// src/core/site/upload.ts
|
|
254927
|
-
import { readFile as readFile3 } from "node:fs/promises";
|
|
254928
|
-
var UPLOAD_CONCURRENCY = 3;
|
|
254929
|
-
var MAX_ATTEMPTS_PER_UPLOAD = 3;
|
|
254930
|
-
var RETRY_BASE_DELAY_MS = 500;
|
|
254931
|
-
async function uploadPresignedAssets(uploads, assets, onProgress) {
|
|
254932
|
-
let uploadedFiles = 0;
|
|
254933
|
-
let nextUpload = 0;
|
|
254934
|
-
const worker = async () => {
|
|
254935
|
-
while (nextUpload < uploads.length) {
|
|
254936
|
-
const upload = uploads[nextUpload++];
|
|
254937
|
-
await uploadPresignedAssetWithRetry(upload, assets);
|
|
254938
|
-
uploadedFiles++;
|
|
254939
|
-
onProgress?.({ uploadedFiles, totalFiles: uploads.length });
|
|
254940
|
-
}
|
|
254941
|
-
};
|
|
254942
|
-
await Promise.all(Array.from({ length: Math.min(UPLOAD_CONCURRENCY, uploads.length) }, worker));
|
|
254943
|
-
}
|
|
254944
|
-
async function uploadPresignedAssetWithRetry(upload, assets) {
|
|
254945
|
-
const entry = assets.manifest[upload.path];
|
|
254946
|
-
const file2 = entry && assets.filesByHash.get(entry.hash);
|
|
254947
|
-
if (!file2) {
|
|
254948
|
-
throw new InternalError(`Server requested upload of unknown asset path: ${upload.path}`);
|
|
254949
|
-
}
|
|
254950
|
-
const content = await readFile3(file2.absolutePath);
|
|
254951
|
-
let lastError;
|
|
254952
|
-
for (let attempt = 0;attempt < MAX_ATTEMPTS_PER_UPLOAD; attempt++) {
|
|
254953
|
-
if (attempt > 0) {
|
|
254954
|
-
await sleep3(RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
|
|
254955
|
-
}
|
|
254956
|
-
try {
|
|
254957
|
-
await distribution_default.put(upload.url, {
|
|
254958
|
-
body: new Uint8Array(content),
|
|
254959
|
-
headers: { "Content-Type": upload.contentType },
|
|
254960
|
-
timeout: 120000,
|
|
254961
|
-
retry: 0
|
|
254962
|
-
});
|
|
254963
|
-
return;
|
|
254964
|
-
} catch (error48) {
|
|
254965
|
-
lastError = error48;
|
|
254966
|
-
}
|
|
254967
|
-
}
|
|
254968
|
-
throw await ApiError.fromHttpError(lastError, "uploading static assets");
|
|
254969
|
-
}
|
|
254970
|
-
function sleep3(ms) {
|
|
254971
|
-
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
254972
|
-
}
|
|
254973
|
-
|
|
254974
|
-
// src/core/site/static-site.ts
|
|
254975
|
-
async function deployStaticSite(options) {
|
|
254976
|
-
const { outputDir, projectRoot, progress } = options;
|
|
254977
|
-
const gitHash = await resolveGitHash(projectRoot, options.gitHash);
|
|
254978
|
-
const assets = await buildAssetManifest(outputDir, getAppContext().id);
|
|
254979
|
-
if (!assets.manifest["/index.html"]) {
|
|
254980
|
-
throw new InvalidInputError(`No index.html found in "${outputDir}" — a static site needs one at the output directory root.`);
|
|
254981
|
-
}
|
|
254982
|
-
const created = await createDeployment({
|
|
254983
|
-
git_hash: gitHash,
|
|
254984
|
-
asset_manifest: assets.manifest
|
|
254985
|
-
});
|
|
254986
|
-
progress?.onAssets?.({
|
|
254987
|
-
totalAssets: Object.keys(assets.manifest).length,
|
|
254988
|
-
newAssets: created.assetUploads?.uploads.length ?? 0
|
|
254989
|
-
});
|
|
254990
|
-
if (created.assetUploads) {
|
|
254991
|
-
await uploadPresignedAssets(created.assetUploads.uploads, assets, progress?.onAssetUpload);
|
|
254992
|
-
}
|
|
254993
|
-
const indexHtml = await readFile4(join16(outputDir, "index.html"));
|
|
254994
|
-
const finalized = await finalizeStaticDeployment(created.deploymentId, new Uint8Array(indexHtml));
|
|
254995
|
-
return { deploymentId: finalized.deploymentId, gitHash };
|
|
254996
|
-
}
|
|
254997
|
-
async function resolveGitHash(projectRoot, explicit) {
|
|
254998
|
-
const hash2 = explicit ?? await getGitHead(projectRoot);
|
|
254999
|
-
if (!hash2 || !isGitCommitHash(hash2)) {
|
|
255000
|
-
throw new InvalidInputError(explicit ? `'${explicit}' is not a git commit hash.` : "Deployments are addressed by the commit that produced the build, and no git commit was found.", {
|
|
255001
|
-
hints: [
|
|
255002
|
-
{
|
|
255003
|
-
message: "Run the deploy from a git checkout, or pass the commit explicitly: base44 site deploy --git-hash <commit>."
|
|
255004
|
-
}
|
|
255005
|
-
]
|
|
255006
|
-
});
|
|
255007
|
-
}
|
|
255008
|
-
return hash2;
|
|
255009
|
-
}
|
|
255010
|
-
|
|
255011
|
-
// src/core/site/deploy-app.ts
|
|
255012
|
-
function planAppDeploy(target, staticDeployments) {
|
|
255013
|
-
const outputDirectory = target.site?.outputDirectory;
|
|
255014
|
-
if (!outputDirectory) {
|
|
255015
|
-
return { kind: "none" };
|
|
255016
|
-
}
|
|
255017
|
-
const outputDir = resolve3(target.root, outputDirectory);
|
|
255018
|
-
return staticDeployments ? { kind: "static-deployment", outputDir } : { kind: "static", outputDir };
|
|
255019
|
-
}
|
|
255020
|
-
function detectAppDeployKind(target, options = {}) {
|
|
255021
|
-
return planAppDeploy(target, options.staticDeployments ?? false).kind;
|
|
255022
|
-
}
|
|
255023
|
-
async function deployAppSite(target, options = {}) {
|
|
255024
|
-
const plan = planAppDeploy(target, options.staticDeployments ?? false);
|
|
255025
|
-
switch (plan.kind) {
|
|
255026
|
-
case "static-deployment": {
|
|
255027
|
-
const { deploymentId, gitHash } = await deployStaticSite({
|
|
255028
|
-
outputDir: plan.outputDir,
|
|
255029
|
-
projectRoot: target.root,
|
|
255030
|
-
gitHash: options.gitHash,
|
|
255031
|
-
progress: options.progress
|
|
255032
|
-
});
|
|
255033
|
-
return { kind: "static-deployment", deploymentId, gitHash };
|
|
255034
|
-
}
|
|
255035
|
-
case "static": {
|
|
255036
|
-
const { appUrl } = await deploySite(plan.outputDir);
|
|
255037
|
-
return { kind: "static", appUrl };
|
|
255038
|
-
}
|
|
255039
|
-
case "none":
|
|
255040
|
-
return { kind: "none" };
|
|
255041
|
-
}
|
|
255042
|
-
}
|
|
255043
|
-
// src/core/site/gate.ts
|
|
255044
|
-
var STATIC_DEPLOYMENTS_ENV = "BASE44_STATIC_DEPLOYMENTS";
|
|
255045
|
-
function staticDeploymentsEnabled(env2 = process.env) {
|
|
255046
|
-
const value = env2[STATIC_DEPLOYMENTS_ENV];
|
|
255047
|
-
return value === "1" || value === "true";
|
|
255048
|
-
}
|
|
255049
|
-
// src/core/project/deploy.ts
|
|
255050
|
-
function hasResourcesToDeploy(projectData) {
|
|
255051
|
-
const {
|
|
255052
|
-
project,
|
|
255053
|
-
entities,
|
|
255054
|
-
functions,
|
|
255055
|
-
agents,
|
|
255056
|
-
agentSkills,
|
|
255057
|
-
connectors,
|
|
255058
|
-
authConfig
|
|
255059
|
-
} = projectData;
|
|
255060
|
-
const hasSite = Boolean(project.site?.outputDirectory);
|
|
255061
|
-
const hasEntities = entities.length > 0;
|
|
255062
|
-
const hasFunctions = functions.length > 0;
|
|
255063
|
-
const hasAgents = agents.length > 0;
|
|
255064
|
-
const hasAgentSkills = agentSkills.length > 0;
|
|
255065
|
-
const hasConnectors = connectors.length > 0;
|
|
255066
|
-
const hasAuthConfig = authConfig.length > 0;
|
|
255067
|
-
const hasVisibility = Boolean(project.visibility);
|
|
255068
|
-
return hasEntities || hasFunctions || hasAgents || hasAgentSkills || hasConnectors || hasAuthConfig || hasVisibility || hasSite;
|
|
255069
|
-
}
|
|
255070
|
-
async function deployAll(projectData, options) {
|
|
255071
|
-
const {
|
|
255072
|
-
project,
|
|
255073
|
-
entities,
|
|
255074
|
-
functions,
|
|
255075
|
-
agents,
|
|
255076
|
-
agentSkills,
|
|
255077
|
-
connectors,
|
|
255078
|
-
authConfig
|
|
255079
|
-
} = projectData;
|
|
255080
|
-
await setAppVisibility(project.visibility);
|
|
255081
|
-
if (project.visibility) {
|
|
255082
|
-
options?.onVisibilitySet?.(project.visibility);
|
|
255083
|
-
}
|
|
255084
|
-
await entityResource.push(entities);
|
|
255085
|
-
await deployFunctionsSequentially(functions, {
|
|
255086
|
-
onStart: options?.onFunctionStart,
|
|
255087
|
-
onResult: options?.onFunctionResult
|
|
255088
|
-
});
|
|
255089
|
-
await agentSkillResource.push(agentSkills);
|
|
255090
|
-
await agentResource.push(agents);
|
|
255091
|
-
await authConfigResource.push(authConfig);
|
|
255092
|
-
const skipConnectorSync = connectors.length === 0 && hasWorkspaceApiKeyAuth();
|
|
255093
|
-
const connectorResults = skipConnectorSync ? [] : (await pushConnectors(connectors)).results;
|
|
255094
|
-
if (project.site?.outputDirectory) {
|
|
255095
|
-
const outputDir = resolve4(project.root, project.site.outputDirectory);
|
|
255096
|
-
const { appUrl } = await deploySite(outputDir);
|
|
255097
|
-
return { appUrl, connectorResults };
|
|
255098
|
-
}
|
|
255099
|
-
return { connectorResults };
|
|
255100
|
-
}
|
|
255101
|
-
// src/core/clients/base44-client.ts
|
|
255102
|
-
var retriedRequests = new WeakSet;
|
|
255103
|
-
async function captureRequestBody(request, options) {
|
|
255104
|
-
if (request.body == null) {
|
|
255105
|
-
return;
|
|
255106
|
-
}
|
|
255107
|
-
try {
|
|
255108
|
-
const cloned = request.clone();
|
|
255109
|
-
const text = await cloned.text();
|
|
255110
|
-
options.context.__requestBody = text;
|
|
255111
|
-
} catch {}
|
|
255112
|
-
}
|
|
255113
|
-
async function handleUnauthorized(request, _options, response) {
|
|
255114
|
-
if (response.status !== 401) {
|
|
255115
|
-
return;
|
|
255116
|
-
}
|
|
255117
|
-
if (hasWorkspaceApiKeyAuth()) {
|
|
255118
|
-
return;
|
|
255119
|
-
}
|
|
255120
|
-
if (retriedRequests.has(request)) {
|
|
255121
|
-
return;
|
|
255122
|
-
}
|
|
255123
|
-
const newAccessToken = await refreshAndSaveTokens();
|
|
255124
|
-
if (!newAccessToken) {
|
|
255125
|
-
return;
|
|
255126
|
-
}
|
|
255127
|
-
retriedRequests.add(request);
|
|
255128
|
-
const requestId = request.headers.get("X-Request-ID");
|
|
255129
|
-
return distribution_default(request.clone(), {
|
|
255130
|
-
headers: {
|
|
255131
|
-
...requestId && { "X-Request-ID": requestId },
|
|
255132
|
-
Authorization: `Bearer ${newAccessToken}`
|
|
255133
|
-
}
|
|
255134
|
-
});
|
|
255135
|
-
}
|
|
255136
|
-
var base44Client = distribution_default.create({
|
|
255137
|
-
prefixUrl: getBase44ApiUrl(),
|
|
255138
|
-
headers: {
|
|
255139
|
-
"User-Agent": "Base44 CLI"
|
|
255140
|
-
},
|
|
255141
|
-
hooks: {
|
|
255142
|
-
beforeRequest: [
|
|
255143
|
-
(request) => {
|
|
255144
|
-
request.headers.set("X-Request-ID", randomUUID2());
|
|
255145
|
-
},
|
|
255146
|
-
captureRequestBody,
|
|
255147
|
-
async (request) => {
|
|
255148
|
-
const workspaceApiKey = getWorkspaceApiKeyFromEnv();
|
|
255149
|
-
if (workspaceApiKey && isWorkspaceApiKey(workspaceApiKey)) {
|
|
255150
|
-
request.headers.set("api_key", workspaceApiKey);
|
|
255151
|
-
return;
|
|
255152
|
-
}
|
|
255153
|
-
try {
|
|
255154
|
-
const auth = await readAuth();
|
|
255155
|
-
if (isTokenExpired(auth)) {
|
|
255156
|
-
const newAccessToken = await refreshAndSaveTokens();
|
|
255157
|
-
if (newAccessToken) {
|
|
255158
|
-
request.headers.set("Authorization", `Bearer ${newAccessToken}`);
|
|
255159
|
-
return;
|
|
255160
|
-
}
|
|
255161
|
-
}
|
|
255162
|
-
request.headers.set("Authorization", `Bearer ${auth.accessToken}`);
|
|
255163
|
-
} catch {}
|
|
255164
|
-
}
|
|
255165
|
-
],
|
|
255166
|
-
afterResponse: [handleUnauthorized]
|
|
255167
|
-
}
|
|
255168
|
-
});
|
|
255169
|
-
function getAppClient() {
|
|
255170
|
-
const { id } = getAppContext();
|
|
255171
|
-
return base44Client.extend({
|
|
255172
|
-
prefixUrl: new URL(`/api/apps/${id}/`, getBase44ApiUrl()).href
|
|
255173
|
-
});
|
|
255174
|
-
}
|
|
255175
|
-
function getSandboxClient(appId) {
|
|
255176
|
-
return base44Client.extend({
|
|
255177
|
-
prefixUrl: new URL(`/api/apps/${appId}/sandbox-bridge/`, getBase44ApiUrl()).href
|
|
255178
|
-
});
|
|
255179
|
-
}
|
|
255180
|
-
// src/core/clients/oauth-client.ts
|
|
255181
|
-
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
255182
|
-
var oauthClient = distribution_default.create({
|
|
255183
|
-
prefixUrl: getBase44ApiUrl(),
|
|
255184
|
-
headers: {
|
|
255185
|
-
"User-Agent": "Base44 CLI"
|
|
255186
|
-
},
|
|
255187
|
-
hooks: {
|
|
255188
|
-
beforeRequest: [
|
|
255189
|
-
(request) => {
|
|
255190
|
-
request.headers.set("X-Request-ID", randomUUID3());
|
|
255191
|
-
}
|
|
255192
|
-
]
|
|
255193
|
-
}
|
|
255194
|
-
});
|
|
255195
|
-
// src/core/auth/api.ts
|
|
255196
|
-
async function generateDeviceCode() {
|
|
255197
|
-
const response = await oauthClient.post("oauth/device/code", {
|
|
255198
|
-
json: {
|
|
255199
|
-
client_id: AUTH_CLIENT_ID,
|
|
255200
|
-
scope: "apps:read apps:write sandbox:write"
|
|
255201
|
-
},
|
|
255202
|
-
throwHttpErrors: false
|
|
255203
|
-
});
|
|
255204
|
-
if (!response.ok) {
|
|
255205
|
-
throw new ApiError(`Failed to generate device code: ${response.status} ${response.statusText}`, { statusCode: response.status });
|
|
255206
|
-
}
|
|
255207
|
-
const result = DeviceCodeResponseSchema.safeParse(await response.json());
|
|
255208
|
-
if (!result.success) {
|
|
255209
|
-
throw new SchemaValidationError("Invalid device code response from server", result.error);
|
|
255210
|
-
}
|
|
255211
|
-
return result.data;
|
|
255212
|
-
}
|
|
255213
|
-
async function getTokenFromDeviceCode(deviceCode) {
|
|
255214
|
-
const searchParams = new URLSearchParams;
|
|
255215
|
-
searchParams.set("grant_type", "urn:ietf:params:oauth:grant-type:device_code");
|
|
255216
|
-
searchParams.set("device_code", deviceCode);
|
|
255217
|
-
searchParams.set("client_id", AUTH_CLIENT_ID);
|
|
255218
|
-
const response = await oauthClient.post("oauth/token", {
|
|
255219
|
-
body: searchParams.toString(),
|
|
255220
|
-
headers: {
|
|
255221
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
255222
|
-
},
|
|
255223
|
-
throwHttpErrors: false
|
|
255224
|
-
});
|
|
255225
|
-
const json2 = await response.json();
|
|
255226
|
-
if (!response.ok) {
|
|
255227
|
-
const errorResult = OAuthErrorSchema.safeParse(json2);
|
|
255228
|
-
if (!errorResult.success) {
|
|
255229
|
-
throw new SchemaValidationError("Token request failed", errorResult.error);
|
|
255230
|
-
}
|
|
255231
|
-
const { error: error48, error_description } = errorResult.data;
|
|
255232
|
-
if (error48 === "authorization_pending" || error48 === "slow_down") {
|
|
255233
|
-
return null;
|
|
255234
|
-
}
|
|
255235
|
-
throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
|
|
255236
|
-
statusCode: response.status
|
|
255237
|
-
});
|
|
255238
|
-
}
|
|
255239
|
-
const result = TokenResponseSchema.safeParse(json2);
|
|
255240
|
-
if (!result.success) {
|
|
255241
|
-
throw new SchemaValidationError("Invalid token response from server", result.error);
|
|
255242
|
-
}
|
|
255243
|
-
return result.data;
|
|
255244
|
-
}
|
|
255245
|
-
async function renewAccessToken(refreshToken) {
|
|
255246
|
-
const searchParams = new URLSearchParams;
|
|
255247
|
-
searchParams.set("grant_type", "refresh_token");
|
|
255248
|
-
searchParams.set("refresh_token", refreshToken);
|
|
255249
|
-
searchParams.set("client_id", AUTH_CLIENT_ID);
|
|
255250
|
-
const response = await oauthClient.post("oauth/token", {
|
|
255251
|
-
body: searchParams.toString(),
|
|
255252
|
-
headers: {
|
|
255253
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
255254
|
-
},
|
|
255255
|
-
throwHttpErrors: false
|
|
255256
|
-
});
|
|
255257
|
-
const json2 = await response.json();
|
|
255258
|
-
if (!response.ok) {
|
|
255259
|
-
const errorResult = OAuthErrorSchema.safeParse(json2);
|
|
255260
|
-
if (!errorResult.success) {
|
|
255261
|
-
throw new ApiError(`Token refresh failed: ${response.statusText}`, {
|
|
255262
|
-
statusCode: response.status
|
|
255263
|
-
});
|
|
255264
|
-
}
|
|
255265
|
-
const { error: error48, error_description } = errorResult.data;
|
|
255266
|
-
throw new ApiError(error_description ?? `OAuth error: ${error48}`, {
|
|
255267
|
-
statusCode: response.status
|
|
255268
|
-
});
|
|
255269
|
-
}
|
|
255270
|
-
const result = TokenResponseSchema.safeParse(json2);
|
|
255271
|
-
if (!result.success) {
|
|
255272
|
-
throw new SchemaValidationError("Invalid token response from server", result.error);
|
|
255273
|
-
}
|
|
255274
|
-
return result.data;
|
|
255275
|
-
}
|
|
255276
|
-
async function getUserInfo(accessToken) {
|
|
255277
|
-
const response = await oauthClient.get("oauth/userinfo", {
|
|
255278
|
-
headers: { Authorization: `Bearer ${accessToken}` }
|
|
255279
|
-
});
|
|
255280
|
-
if (!response.ok) {
|
|
255281
|
-
throw new ApiError(`Failed to fetch user info: ${response.status}`, {
|
|
255282
|
-
statusCode: response.status
|
|
255283
|
-
});
|
|
255284
|
-
}
|
|
255285
|
-
const result = UserInfoSchema.safeParse(await response.json());
|
|
255286
|
-
if (!result.success) {
|
|
255287
|
-
throw new SchemaValidationError("Invalid UserInfo response from server", result.error);
|
|
255288
|
-
}
|
|
255289
|
-
return result.data;
|
|
255290
|
-
}
|
|
255291
|
-
// src/cli/commands/auth/login-flow.ts
|
|
255292
|
-
async function generateAndDisplayDeviceCode(log, runTask) {
|
|
255293
|
-
const deviceCodeResponse = await runTask("Generating device code...", async () => {
|
|
255294
|
-
return await generateDeviceCode();
|
|
255295
|
-
}, {
|
|
255296
|
-
successMessage: "Device code generated",
|
|
255297
|
-
errorMessage: "Failed to generate device code"
|
|
255298
|
-
});
|
|
255299
|
-
log.info(`Verification code: ${theme.styles.bold(deviceCodeResponse.userCode)}` + `
|
|
255300
|
-
Please confirm this code at: ${deviceCodeResponse.verificationUri}`);
|
|
255301
|
-
return deviceCodeResponse;
|
|
255302
|
-
}
|
|
255303
|
-
async function waitForAuthentication(deviceCode, expiresIn, interval, runTask) {
|
|
255304
|
-
let tokenResponse;
|
|
255305
|
-
try {
|
|
255306
|
-
await runTask("Waiting for authentication...", async () => {
|
|
255307
|
-
await pWaitFor(async () => {
|
|
255308
|
-
const result = await getTokenFromDeviceCode(deviceCode);
|
|
255309
|
-
if (result !== null) {
|
|
255310
|
-
tokenResponse = result;
|
|
255311
|
-
return true;
|
|
255312
|
-
}
|
|
255313
|
-
return false;
|
|
255314
|
-
}, {
|
|
255315
|
-
interval: interval * 1000,
|
|
255316
|
-
timeout: expiresIn * 1000
|
|
255317
|
-
});
|
|
255318
|
-
}, {
|
|
255319
|
-
successMessage: "Authentication completed!",
|
|
255320
|
-
errorMessage: "Authentication failed"
|
|
255321
|
-
});
|
|
255322
|
-
} catch (error48) {
|
|
255323
|
-
if (error48 instanceof Error && error48.message.includes("timed out")) {
|
|
255324
|
-
throw new AuthExpiredError("Authentication timed out. Please try again.");
|
|
255325
|
-
}
|
|
255326
|
-
throw error48;
|
|
255327
|
-
}
|
|
255328
|
-
if (tokenResponse === undefined) {
|
|
255329
|
-
throw new InternalError("Failed to retrieve authentication token.");
|
|
255330
|
-
}
|
|
255331
|
-
return tokenResponse;
|
|
255332
|
-
}
|
|
255333
|
-
async function saveAuthData(response, userInfo) {
|
|
255334
|
-
const expiresAt = Date.now() + response.expiresIn * 1000;
|
|
255335
|
-
await writeAuth({
|
|
255336
|
-
accessToken: response.accessToken,
|
|
255337
|
-
refreshToken: response.refreshToken,
|
|
255338
|
-
expiresAt,
|
|
255339
|
-
email: userInfo.email,
|
|
255340
|
-
name: userInfo.name
|
|
255341
|
-
});
|
|
255342
|
-
}
|
|
255343
|
-
async function login({
|
|
255344
|
-
log,
|
|
255345
|
-
runTask
|
|
255346
|
-
}) {
|
|
255347
|
-
const deviceCodeResponse = await generateAndDisplayDeviceCode(log, runTask);
|
|
255348
|
-
const token = await waitForAuthentication(deviceCodeResponse.deviceCode, deviceCodeResponse.expiresIn, deviceCodeResponse.interval, runTask);
|
|
255349
|
-
const userInfo = await getUserInfo(token.accessToken);
|
|
255350
|
-
await saveAuthData(token, userInfo);
|
|
255351
|
-
return {
|
|
255352
|
-
outroMessage: `Successfully logged in as ${theme.styles.bold(userInfo.email)}`
|
|
255353
|
-
};
|
|
255354
|
-
}
|
|
255355
|
-
|
|
255356
|
-
// src/cli/utils/command/middleware.ts
|
|
255357
|
-
async function ensureAuth(ctx) {
|
|
255358
|
-
if (hasWorkspaceApiKeyAuth()) {
|
|
255359
|
-
ctx.errorReporter.setContext({
|
|
255360
|
-
user: { email: "workspace-api-key", name: "Workspace API key" }
|
|
255361
|
-
});
|
|
255362
|
-
return;
|
|
255363
|
-
}
|
|
255364
|
-
await seedAuthFromEnv();
|
|
255365
|
-
const loggedIn = await isLoggedIn();
|
|
255366
|
-
if (!loggedIn) {
|
|
255367
|
-
ctx.log.info("You need to login first to continue.");
|
|
255368
|
-
await login(ctx);
|
|
255369
|
-
}
|
|
255370
|
-
try {
|
|
255371
|
-
const userInfo = await readAuth();
|
|
255372
|
-
ctx.errorReporter.setContext({
|
|
255373
|
-
user: { email: userInfo.email, name: userInfo.name }
|
|
255374
|
-
});
|
|
255375
|
-
} catch {}
|
|
255376
|
-
}
|
|
255377
|
-
async function ensureAppContext(ctx, options = {}) {
|
|
255378
|
-
const appContext = await initAppContext(options);
|
|
255379
|
-
ctx.app = appContext;
|
|
255380
|
-
ctx.errorReporter.setContext({ appId: appContext.id });
|
|
255381
|
-
}
|
|
255382
|
-
|
|
255383
255443
|
// src/cli/utils/version-check.ts
|
|
255384
255444
|
async function checkForUpgrade() {
|
|
255385
255445
|
const testLatestVersion = getTestOverrides()?.latestVersion;
|
|
@@ -255772,6 +255832,11 @@ function verifyDenoInstalled(context) {
|
|
|
255772
255832
|
});
|
|
255773
255833
|
}
|
|
255774
255834
|
}
|
|
255835
|
+
// src/core/utils/git.ts
|
|
255836
|
+
var GIT_HASH_PATTERN = /^[a-fA-F0-9]{7,64}$/;
|
|
255837
|
+
function isGitCommitHash(value) {
|
|
255838
|
+
return GIT_HASH_PATTERN.test(value);
|
|
255839
|
+
}
|
|
255775
255840
|
// src/core/workspace/schema.ts
|
|
255776
255841
|
var WorkspaceSchema = exports_external.object({
|
|
255777
255842
|
id: exports_external.string(),
|
|
@@ -256075,7 +256140,7 @@ function getAuthPushCommand() {
|
|
|
256075
256140
|
}
|
|
256076
256141
|
|
|
256077
256142
|
// src/cli/commands/auth/social-login.ts
|
|
256078
|
-
import { dirname as dirname14, join as join21, resolve as
|
|
256143
|
+
import { dirname as dirname14, join as join21, resolve as resolve4 } from "node:path";
|
|
256079
256144
|
var PROVIDER_LABELS = {
|
|
256080
256145
|
google: "Google",
|
|
256081
256146
|
microsoft: "Microsoft",
|
|
@@ -256115,7 +256180,7 @@ async function socialLoginAction({ log, isNonInteractive, runTask: runTask2 }, p
|
|
|
256115
256180
|
let clientSecret;
|
|
256116
256181
|
if (useCustomOAuth && oauth && oauthCli && hasSecretOptions(options)) {
|
|
256117
256182
|
if (options.envFile) {
|
|
256118
|
-
const secrets = await parseEnvFile(
|
|
256183
|
+
const secrets = await parseEnvFile(resolve4(options.envFile));
|
|
256119
256184
|
const value = secrets[oauthCli.envVar];
|
|
256120
256185
|
if (!value) {
|
|
256121
256186
|
throw new InvalidInputError(`Key "${oauthCli.envVar}" not found in ${options.envFile}.`);
|
|
@@ -256171,7 +256236,7 @@ function getSocialLoginCommand() {
|
|
|
256171
256236
|
}
|
|
256172
256237
|
|
|
256173
256238
|
// src/cli/commands/auth/sso.ts
|
|
256174
|
-
import { dirname as dirname15, join as join22, resolve as
|
|
256239
|
+
import { dirname as dirname15, join as join22, resolve as resolve5 } from "node:path";
|
|
256175
256240
|
var SSOConfigFileSchema = exports_external.object({
|
|
256176
256241
|
provider: exports_external.enum(Object.values(KNOWN_SSO_PROVIDERS)),
|
|
256177
256242
|
clientId: exports_external.string(),
|
|
@@ -256187,7 +256252,7 @@ var SSOConfigFileSchema = exports_external.object({
|
|
|
256187
256252
|
ssoName: exports_external.string().optional()
|
|
256188
256253
|
});
|
|
256189
256254
|
async function loadSSOConfigFile(filePath) {
|
|
256190
|
-
const resolved =
|
|
256255
|
+
const resolved = resolve5(filePath);
|
|
256191
256256
|
const raw2 = await readJsonFile(resolved);
|
|
256192
256257
|
const result = SSOConfigFileSchema.safeParse(raw2);
|
|
256193
256258
|
if (!result.success) {
|
|
@@ -256275,7 +256340,7 @@ async function ssoEnableAction({ isNonInteractive, runTask: runTask2 }, options)
|
|
|
256275
256340
|
}
|
|
256276
256341
|
let clientSecret;
|
|
256277
256342
|
if (merged.envFile && !merged.clientSecret) {
|
|
256278
|
-
const secrets2 = await parseEnvFile(
|
|
256343
|
+
const secrets2 = await parseEnvFile(resolve5(merged.envFile));
|
|
256279
256344
|
const value = secrets2.sso_client_secret;
|
|
256280
256345
|
if (!value) {
|
|
256281
256346
|
throw new InvalidInputError(`Key "sso_client_secret" not found in ${merged.envFile}.`);
|
|
@@ -256913,19 +256978,19 @@ var baseOpen = async (options) => {
|
|
|
256913
256978
|
}
|
|
256914
256979
|
const subprocess = childProcess3.spawn(command2, cliArguments, childProcessOptions);
|
|
256915
256980
|
if (options.wait) {
|
|
256916
|
-
return new Promise((
|
|
256981
|
+
return new Promise((resolve6, reject) => {
|
|
256917
256982
|
subprocess.once("error", reject);
|
|
256918
256983
|
subprocess.once("close", (exitCode) => {
|
|
256919
256984
|
if (!options.allowNonzeroExitCode && exitCode !== 0) {
|
|
256920
256985
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
256921
256986
|
return;
|
|
256922
256987
|
}
|
|
256923
|
-
|
|
256988
|
+
resolve6(subprocess);
|
|
256924
256989
|
});
|
|
256925
256990
|
});
|
|
256926
256991
|
}
|
|
256927
256992
|
if (isFallbackAttempt) {
|
|
256928
|
-
return new Promise((
|
|
256993
|
+
return new Promise((resolve6, reject) => {
|
|
256929
256994
|
subprocess.once("error", reject);
|
|
256930
256995
|
subprocess.once("spawn", () => {
|
|
256931
256996
|
subprocess.once("close", (exitCode) => {
|
|
@@ -256935,17 +257000,17 @@ var baseOpen = async (options) => {
|
|
|
256935
257000
|
return;
|
|
256936
257001
|
}
|
|
256937
257002
|
subprocess.unref();
|
|
256938
|
-
|
|
257003
|
+
resolve6(subprocess);
|
|
256939
257004
|
});
|
|
256940
257005
|
});
|
|
256941
257006
|
});
|
|
256942
257007
|
}
|
|
256943
257008
|
subprocess.unref();
|
|
256944
|
-
return new Promise((
|
|
257009
|
+
return new Promise((resolve6, reject) => {
|
|
256945
257010
|
subprocess.once("error", reject);
|
|
256946
257011
|
subprocess.once("spawn", () => {
|
|
256947
257012
|
subprocess.off("error", reject);
|
|
256948
|
-
|
|
257013
|
+
resolve6(subprocess);
|
|
256949
257014
|
});
|
|
256950
257015
|
});
|
|
256951
257016
|
};
|
|
@@ -257208,10 +257273,10 @@ function getConnectorsListAvailableCommand() {
|
|
|
257208
257273
|
}
|
|
257209
257274
|
|
|
257210
257275
|
// src/cli/commands/connectors/pull.ts
|
|
257211
|
-
import { dirname as dirname16, join as join23, resolve as
|
|
257276
|
+
import { dirname as dirname16, join as join23, resolve as resolve6 } from "node:path";
|
|
257212
257277
|
async function resolveConnectorsDir(options) {
|
|
257213
257278
|
if (!getAppContext().projectRoot) {
|
|
257214
|
-
return
|
|
257279
|
+
return resolve6(options.dir ?? "connectors");
|
|
257215
257280
|
}
|
|
257216
257281
|
const { project: project2 } = await readProjectConfig();
|
|
257217
257282
|
return join23(dirname16(project2.configPath), project2.connectorsDir);
|
|
@@ -257255,10 +257320,10 @@ function getConnectorsPullCommand() {
|
|
|
257255
257320
|
}
|
|
257256
257321
|
|
|
257257
257322
|
// src/cli/commands/connectors/push.ts
|
|
257258
|
-
import { resolve as
|
|
257323
|
+
import { resolve as resolve7 } from "node:path";
|
|
257259
257324
|
async function readConnectorsToPush(options) {
|
|
257260
257325
|
if (!getAppContext().projectRoot) {
|
|
257261
|
-
return readAllConnectors(
|
|
257326
|
+
return readAllConnectors(resolve7(options.dir ?? "connectors"));
|
|
257262
257327
|
}
|
|
257263
257328
|
const { connectors } = await readProjectConfig();
|
|
257264
257329
|
return connectors;
|
|
@@ -257759,7 +257824,7 @@ function getBuildCommand() {
|
|
|
257759
257824
|
}
|
|
257760
257825
|
|
|
257761
257826
|
// src/cli/commands/project/create.ts
|
|
257762
|
-
import { basename as basename5, resolve as
|
|
257827
|
+
import { basename as basename5, resolve as resolve8 } from "node:path";
|
|
257763
257828
|
var import_kebabCase = __toESM(require_kebabCase(), 1);
|
|
257764
257829
|
|
|
257765
257830
|
// src/cli/commands/project/scaffold-shared.ts
|
|
@@ -257951,7 +258016,7 @@ async function createInteractive(options, ctx) {
|
|
|
257951
258016
|
}, ctx);
|
|
257952
258017
|
}
|
|
257953
258018
|
async function createNonInteractive(options, ctx) {
|
|
257954
|
-
ctx.log.info(`Creating a new project at ${
|
|
258019
|
+
ctx.log.info(`Creating a new project at ${resolve8(options.path)}`);
|
|
257955
258020
|
const template2 = await getTemplateById(options.template ?? DEFAULT_TEMPLATE_ID);
|
|
257956
258021
|
return await executeCreate({
|
|
257957
258022
|
template: template2,
|
|
@@ -257975,7 +258040,7 @@ async function executeCreate({
|
|
|
257975
258040
|
}, ctx) {
|
|
257976
258041
|
const { log, runTask: runTask2 } = ctx;
|
|
257977
258042
|
const name2 = rawName.trim();
|
|
257978
|
-
const resolvedPath =
|
|
258043
|
+
const resolvedPath = resolve8(projectPath);
|
|
257979
258044
|
const organizationId = await resolveWorkspaceId(ctx, flagWorkspaceId, isInteractive);
|
|
257980
258045
|
const { projectId } = await runTask2("Setting up your project...", async () => {
|
|
257981
258046
|
return await createProjectFiles({
|
|
@@ -258382,7 +258447,7 @@ async function followLogs(functionNames, options, availableFunctionNames, jsonMo
|
|
|
258382
258447
|
for (const entry of fresh)
|
|
258383
258448
|
writeFollowLine(entry, jsonMode);
|
|
258384
258449
|
first = false;
|
|
258385
|
-
await new Promise((
|
|
258450
|
+
await new Promise((resolve9) => setTimeout(resolve9, 2000));
|
|
258386
258451
|
}
|
|
258387
258452
|
}
|
|
258388
258453
|
function formatLogs(entries, env3) {
|
|
@@ -258496,7 +258561,7 @@ function getLogsCommand() {
|
|
|
258496
258561
|
}
|
|
258497
258562
|
|
|
258498
258563
|
// src/cli/commands/project/scaffold.ts
|
|
258499
|
-
import { basename as basename6, resolve as
|
|
258564
|
+
import { basename as basename6, resolve as resolve9 } from "node:path";
|
|
258500
258565
|
function resolveAppId(options) {
|
|
258501
258566
|
const appId = options.appId;
|
|
258502
258567
|
if (!appId) {
|
|
@@ -258512,7 +258577,7 @@ function resolveAppId(options) {
|
|
|
258512
258577
|
async function scaffoldAction(ctx, name2, options, command2) {
|
|
258513
258578
|
const { log, runTask: runTask2 } = ctx;
|
|
258514
258579
|
const appId = resolveAppId(command2.optsWithGlobals());
|
|
258515
|
-
const resolvedPath =
|
|
258580
|
+
const resolvedPath = resolve9("./");
|
|
258516
258581
|
const projectName = (name2 ?? basename6(resolvedPath)).trim();
|
|
258517
258582
|
const template2 = await getTemplateById("backend-only");
|
|
258518
258583
|
log.info(`Scaffolding project at ${resolvedPath}`);
|
|
@@ -258909,7 +258974,7 @@ function getSecretsListCommand() {
|
|
|
258909
258974
|
}
|
|
258910
258975
|
|
|
258911
258976
|
// src/cli/commands/secrets/set.ts
|
|
258912
|
-
import { resolve as
|
|
258977
|
+
import { resolve as resolve10 } from "node:path";
|
|
258913
258978
|
function parseEntries(entries) {
|
|
258914
258979
|
const secrets = {};
|
|
258915
258980
|
for (const entry of entries) {
|
|
@@ -258940,7 +259005,7 @@ async function setSecretsAction({ log, runTask: runTask2 }, entries, options) {
|
|
|
258940
259005
|
validateInput(entries, options);
|
|
258941
259006
|
let secrets;
|
|
258942
259007
|
if (options.envFile) {
|
|
258943
|
-
secrets = await parseEnvFile(
|
|
259008
|
+
secrets = await parseEnvFile(resolve10(options.envFile));
|
|
258944
259009
|
if (Object.keys(secrets).length === 0) {
|
|
258945
259010
|
throw new InvalidInputError("The env file contains no valid KEY=VALUE entries.");
|
|
258946
259011
|
}
|
|
@@ -258968,49 +259033,8 @@ function getSecretsCommand() {
|
|
|
258968
259033
|
return new Command("secrets").description("Manage project secrets (environment variables)").addCommand(getSecretsListCommand()).addCommand(getSecretsSetCommand()).addCommand(getSecretsDeleteCommand());
|
|
258969
259034
|
}
|
|
258970
259035
|
|
|
258971
|
-
// src/cli/commands/site/run-app-deploy.ts
|
|
258972
|
-
var TASK_LABELS = {
|
|
258973
|
-
"static-deployment": {
|
|
258974
|
-
start: "Deploying site...",
|
|
258975
|
-
success: "Site deployed",
|
|
258976
|
-
error: "Site deploy failed"
|
|
258977
|
-
},
|
|
258978
|
-
static: {
|
|
258979
|
-
start: "Creating archive and deploying site...",
|
|
258980
|
-
success: "Site deployed successfully",
|
|
258981
|
-
error: "Deployment failed"
|
|
258982
|
-
}
|
|
258983
|
-
};
|
|
258984
|
-
async function runAppSiteDeploy({ runTask: runTask2, log, staticDeployments }, target, options = {}) {
|
|
258985
|
-
const kind = detectAppDeployKind(target, { staticDeployments });
|
|
258986
|
-
if (kind === "none")
|
|
258987
|
-
return { kind: "none" };
|
|
258988
|
-
const labels = TASK_LABELS[kind];
|
|
258989
|
-
const progressLines = [];
|
|
258990
|
-
const result = await runTask2(labels.start, async (updateMessage) => await deployAppSite(target, {
|
|
258991
|
-
staticDeployments,
|
|
258992
|
-
gitHash: options.gitHash,
|
|
258993
|
-
progress: {
|
|
258994
|
-
onAssets: ({ totalAssets, newAssets }) => {
|
|
258995
|
-
const line = `Found ${totalAssets} static assets (${newAssets} new)`;
|
|
258996
|
-
progressLines.push(line);
|
|
258997
|
-
updateMessage(line);
|
|
258998
|
-
},
|
|
258999
|
-
onAssetUpload: ({ uploadedFiles, totalFiles }) => {
|
|
259000
|
-
updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} assets`);
|
|
259001
|
-
}
|
|
259002
|
-
}
|
|
259003
|
-
}), {
|
|
259004
|
-
successMessage: labels.success,
|
|
259005
|
-
errorMessage: labels.error
|
|
259006
|
-
});
|
|
259007
|
-
for (const line of progressLines) {
|
|
259008
|
-
log.message(theme.styles.dim(line));
|
|
259009
|
-
}
|
|
259010
|
-
return result;
|
|
259011
|
-
}
|
|
259012
|
-
|
|
259013
259036
|
// src/cli/commands/site/deploy.ts
|
|
259037
|
+
import { resolve as resolve11 } from "node:path";
|
|
259014
259038
|
async function deployAction2(ctx, options) {
|
|
259015
259039
|
const { isNonInteractive } = ctx;
|
|
259016
259040
|
if (isNonInteractive && !options.yes) {
|
|
@@ -259036,28 +259060,63 @@ async function deployAction2(ctx, options) {
|
|
|
259036
259060
|
}
|
|
259037
259061
|
}
|
|
259038
259062
|
await maybeBuildBeforeDeploy(ctx, project2, options.build);
|
|
259039
|
-
const
|
|
259040
|
-
|
|
259041
|
-
|
|
259042
|
-
|
|
259043
|
-
|
|
259044
|
-
|
|
259045
|
-
|
|
259046
|
-
|
|
259047
|
-
|
|
259048
|
-
|
|
259049
|
-
|
|
259050
|
-
|
|
259063
|
+
const outputDir = resolve11(project2.root, outputDirectory);
|
|
259064
|
+
const { gitHash, concurrency } = options;
|
|
259065
|
+
return gitHash ? await deployToDeploymentsApi(ctx, outputDir, gitHash, concurrency) : await deployTarball(ctx, outputDir);
|
|
259066
|
+
}
|
|
259067
|
+
async function deployToDeploymentsApi({ runTask: runTask2, log, jsonMode }, outputDir, gitHash, concurrency) {
|
|
259068
|
+
const progressLines = [];
|
|
259069
|
+
const { deploymentId } = await runTask2("Deploying site...", async (updateMessage) => await deployStaticSite({
|
|
259070
|
+
outputDir,
|
|
259071
|
+
gitHash,
|
|
259072
|
+
concurrency,
|
|
259073
|
+
progress: {
|
|
259074
|
+
onAssets: ({ totalAssets, newAssets }) => {
|
|
259075
|
+
const line = `Found ${totalAssets} static assets (${newAssets} new)`;
|
|
259076
|
+
progressLines.push(line);
|
|
259077
|
+
updateMessage(line);
|
|
259078
|
+
},
|
|
259079
|
+
onAssetUpload: ({ uploadedFiles, totalFiles }) => {
|
|
259080
|
+
updateMessage(`Uploaded ${uploadedFiles} of ${totalFiles} assets`);
|
|
259081
|
+
}
|
|
259082
|
+
}
|
|
259083
|
+
}), { successMessage: "Site deployed", errorMessage: "Site deploy failed" });
|
|
259084
|
+
for (const line of progressLines) {
|
|
259085
|
+
log.message(theme.styles.dim(line));
|
|
259051
259086
|
}
|
|
259052
|
-
return {
|
|
259087
|
+
return {
|
|
259088
|
+
outroMessage: `Deployment ${deploymentId} (commit ${gitHash.slice(0, 12)})`,
|
|
259089
|
+
stdout: jsonMode ? `${JSON.stringify({ deploymentId, gitHash }, null, 2)}
|
|
259090
|
+
` : undefined
|
|
259091
|
+
};
|
|
259092
|
+
}
|
|
259093
|
+
async function deployTarball({ runTask: runTask2 }, outputDir) {
|
|
259094
|
+
const { appUrl } = await runTask2("Creating archive and deploying site...", async () => await deploySite(outputDir), {
|
|
259095
|
+
successMessage: "Site deployed successfully",
|
|
259096
|
+
errorMessage: "Deployment failed"
|
|
259097
|
+
});
|
|
259098
|
+
return { outroMessage: `Visit your site at: ${appUrl}` };
|
|
259053
259099
|
}
|
|
259054
259100
|
function getSiteDeployCommand() {
|
|
259055
259101
|
const command2 = new Base44Command("deploy").description("Deploy built site files to Base44 hosting").option("-y, --yes", "Skip confirmation prompt").option("--build", "Build the site before deploying (skips the prompt)").option("--no-build", "Deploy without building (skips the prompt)");
|
|
259056
259102
|
if (staticDeploymentsEnabled()) {
|
|
259057
|
-
command2.addOption(new Option("--git-hash <hash>", "Commit the build came from
|
|
259103
|
+
command2.addOption(new Option("--git-hash <hash>", "Commit the build came from — deploys through the deployments API").argParser((value) => {
|
|
259104
|
+
if (!isGitCommitHash(value)) {
|
|
259105
|
+
throw new InvalidArgumentError("Expected a git commit hash (7-64 hex chars).");
|
|
259106
|
+
}
|
|
259107
|
+
return value;
|
|
259108
|
+
}));
|
|
259109
|
+
command2.addOption(new Option("--concurrency <n>", "Parallel asset uploads").default(DEFAULT_UPLOAD_CONCURRENCY).argParser(parseConcurrency));
|
|
259058
259110
|
}
|
|
259059
259111
|
return command2.action(deployAction2);
|
|
259060
259112
|
}
|
|
259113
|
+
function parseConcurrency(value) {
|
|
259114
|
+
const parsed = Number(value);
|
|
259115
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_UPLOAD_CONCURRENCY) {
|
|
259116
|
+
throw new InvalidArgumentError(`Expected a whole number between 1 and ${MAX_UPLOAD_CONCURRENCY}.`);
|
|
259117
|
+
}
|
|
259118
|
+
return parsed;
|
|
259119
|
+
}
|
|
259061
259120
|
|
|
259062
259121
|
// src/cli/commands/site/open.ts
|
|
259063
259122
|
async function openAction({
|
|
@@ -267850,4 +267909,4 @@ export {
|
|
|
267850
267909
|
CLIExitError
|
|
267851
267910
|
};
|
|
267852
267911
|
|
|
267853
|
-
//# debugId=
|
|
267912
|
+
//# debugId=8D3A45157A4E22AA64756E2164756E21
|