everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
220 lines (218 loc) • 7.87 kB
JavaScript
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
const require_fastkv = require('./fastkv.cjs');
const require_network = require('./network.cjs');
const require_config = require('./config.cjs');
const require_string = require('./utils/string.cjs');
const require_theme = require('./utils/theme.cjs');
const require_build = require('./build.cjs');
const require_code_artifacts = require('./code-artifacts.cjs');
const require_near_cli = require('./near-cli.cjs');
let node_fs = require("node:fs");
let node_path = require("node:path");
let effect = require("effect");
let node_process = require("node:process");
node_process = require_runtime.__toESM(node_process, 1);
//#region src/publish.ts
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function extractPublishedUrl(output) {
const deployMatch = output.match(/🚀.*Deployed:\s*(https?:\S+)/);
if (deployMatch) return deployMatch[1];
const match = output.match(/https?:\/\/[^\s"'<>]+/g);
if (!match || match.length === 0) return null;
return match[match.length - 1] ?? null;
}
async function waitForPublishedConfig(opts) {
const envTimeoutMs = Number(node_process.default.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);
const envIntervalMs = Number(node_process.default.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);
const timeoutMs = opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : void 0) ?? 12e4;
const intervalMs = opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : void 0) ?? 3e3;
const startedAt = Date.now();
let lastError;
while (Date.now() - startedAt < timeoutMs) {
try {
const verifiedConfig = await require_fastkv.fetchBosConfigFromFastKv(`bos://${opts.account}/${opts.gateway}`);
if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) return;
} catch (error) {
lastError = error;
}
await sleep(intervalMs);
}
const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
throw new Error(`Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`);
}
async function publishToFastKv(input) {
const { env, dryRun, configDir } = input;
let bosConfig = input.bosConfig;
const runtimeConfig = input.runtimeConfig;
const isStaging = env === "staging";
const account = bosConfig.account;
const gateway = isStaging ? bosConfig.staging?.domain ?? bosConfig.domain : bosConfig.domain;
if (!gateway) return {
status: "error",
registryUrl: "",
error: "bos.config.json must define domain to publish"
};
const network = input.network ?? require_network.getNetworkIdForAccount(account);
const registryUrl = require_fastkv.buildRegistryConfigUrlForNetwork(network, account, gateway);
const targets = require_build.selectWorkspaceTargets(input.packages, bosConfig);
let built;
let skipped;
let deployResults;
if (dryRun) return {
status: "dry-run",
registryUrl,
built,
skipped
};
const privateKey = input.privateKey || node_process.default.env.NEAR_PRIVATE_KEY || node_process.default.env.BOS_NEAR_PRIVATE_KEY;
let signingMode;
try {
signingMode = require_near_cli.resolveNearSigningMode(privateKey);
} catch (error) {
return {
status: "error",
registryUrl,
error: error instanceof Error ? error.message : "Unknown error"
};
}
if (input.build) {
console.log(" Ensuring NEAR CLI...");
await effect.Effect.runPromise(require_near_cli.ensureNearCli);
console.log(" NEAR CLI ready");
await require_code_artifacts.generateCodeArtifacts(configDir, bosConfig, {
env: "production",
runtimeConfig: runtimeConfig ?? void 0
});
const result = await require_build.buildWorkspaceTargets({
configDir,
bosConfig,
runtimeConfig,
targets,
deploy: true,
verbose: input.verbose
});
built = result.built;
skipped = result.skipped;
deployResults = result.deployResults;
if (deployResults) {
const failures = deployResults.filter((r) => !r.success);
if (failures.length > 0) {
const total = deployResults.length;
console.log();
console.log(require_theme.colors.error(` ${require_theme.icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? "s" : ""} failed`));
console.log();
for (const f of failures) {
const errorLine = (f.error ?? "Failed").split("\n")[0];
console.log(` ${require_theme.colors.error(require_theme.icons.err)} ${require_string.padRight(f.key, 28)} ${errorLine}`);
}
console.log();
if (!input.verbose) {
console.log(require_theme.colors.dim(" Run with --verbose for full build output."));
console.log();
}
return {
status: "error",
registryUrl,
built,
skipped,
deployResults,
error: `${failures.length} of ${total} workspaces failed to deploy`
};
}
}
const refreshed = await require_config.loadResolvedConfig({ cwd: configDir });
if (!refreshed?.config) return {
status: "error",
registryUrl,
built,
skipped,
deployResults,
error: "Failed to reload bos.config.json after build"
};
bosConfig = refreshed.config;
}
const rawConfigPath = (0, node_path.join)(configDir, "bos.config.json");
const rawConfig = JSON.parse((0, node_fs.readFileSync)(rawConfigPath, "utf-8"));
const publishPayload = isStaging ? {
...rawConfig,
domain: gateway
} : rawConfig;
const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload) };
const payload = JSON.stringify(registryEntries);
const argsBase64 = Buffer.from(payload).toString("base64");
console.log();
console.log(" Publishing to:");
console.log(` ${require_theme.colors.cyan(registryUrl)}`);
try {
let txHash;
console.log(` Submitting transaction on ${network}...`);
try {
const tx = await effect.Effect.runPromise(require_near_cli.executeTransaction({
account,
contract: require_fastkv.getRegistryNamespaceForNetwork(network),
method: "__fastdata_kv",
argsBase64,
network,
privateKey: signingMode._tag === "privateKey" ? signingMode.privateKey : void 0,
gas: "300Tgas",
deposit: "0NEAR",
verbose: input.verbose
}, signingMode));
txHash = tx.txHash;
if (txHash && !tx.output?.includes("CodeDoesNotExist")) console.log(` Transaction submitted: ${require_theme.colors.dim(txHash)}`);
} catch (error) {
console.log(require_theme.colors.dim(" Transaction reported an error — verifying publish..."));
try {
await waitForPublishedConfig({
account,
gateway,
publishConfig: publishPayload,
timeoutMs: 3e4,
intervalMs: 2e3
});
txHash = extractTransactionHash(error);
} catch {
throw error;
}
}
console.log(" Waiting for publish confirmation...");
await waitForPublishedConfig({
account,
gateway,
publishConfig: publishPayload
});
return {
status: "published",
registryUrl,
txHash,
built,
skipped,
deployResults,
publishConfig: publishPayload
};
} catch (error) {
return {
status: "error",
registryUrl,
error: formatNearError(error),
built,
skipped,
deployResults
};
}
}
function formatNearError(error) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes("exceeded gas") || message.includes("GasLimitExceeded")) return `Transaction exceeded gas limit.\n Original: ${message}`;
if (message.includes("timeout") || message.includes("Timeout")) return `Transaction timed out. Check NEAR network status.\n Original: ${message}`;
return message;
}
function extractTransactionHash(error) {
return (error instanceof Error ? error.message : String(error)).match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
}
//#endregion
exports.extractPublishedUrl = extractPublishedUrl;
exports.publishToFastKv = publishToFastKv;
//# sourceMappingURL=publish.cjs.map