everything-dev 1.45.0 → 1.46.1
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/build.cjs +335 -0
- package/dist/build.cjs.map +1 -0
- package/dist/build.mjs +327 -0
- package/dist/build.mjs.map +1 -0
- package/dist/cli/init.cjs +1 -1
- package/dist/cli/init.mjs +1 -1
- package/dist/cli/sync.cjs +1 -1
- package/dist/cli/sync.mjs +1 -1
- package/dist/cli/upgrade.cjs +2 -2
- package/dist/cli/upgrade.mjs +2 -2
- package/dist/cli.cjs +2 -2
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/code-artifacts.cjs +25 -0
- package/dist/code-artifacts.cjs.map +1 -0
- package/dist/code-artifacts.mjs +24 -0
- package/dist/code-artifacts.mjs.map +1 -0
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +14 -13
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +14 -13
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.mjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/integrity.cjs +18 -55
- package/dist/integrity.cjs.map +1 -1
- package/dist/integrity.d.cts +3 -7
- package/dist/integrity.d.cts.map +1 -1
- package/dist/integrity.d.mts +3 -7
- package/dist/integrity.d.mts.map +1 -1
- package/dist/integrity.mjs +18 -53
- package/dist/integrity.mjs.map +1 -1
- package/dist/plugin.cjs +37 -571
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +7 -14
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +7 -14
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +23 -556
- package/dist/plugin.mjs.map +1 -1
- package/dist/publish.cjs +220 -0
- package/dist/publish.cjs.map +1 -0
- package/dist/publish.mjs +217 -0
- package/dist/publish.mjs.map +1 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- package/dist/utils/run.cjs +21 -3
- package/dist/utils/run.cjs.map +1 -1
- package/dist/utils/run.mjs +21 -3
- package/dist/utils/run.mjs.map +1 -1
- package/dist/utils/string.cjs +9 -0
- package/dist/utils/string.cjs.map +1 -0
- package/dist/utils/string.mjs +8 -0
- package/dist/utils/string.mjs.map +1 -0
- package/package.json +1 -1
package/dist/publish.cjs
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_fastkv = require('./fastkv.cjs');
|
|
3
|
+
const require_network = require('./network.cjs');
|
|
4
|
+
const require_config = require('./config.cjs');
|
|
5
|
+
const require_string = require('./utils/string.cjs');
|
|
6
|
+
const require_theme = require('./utils/theme.cjs');
|
|
7
|
+
const require_build = require('./build.cjs');
|
|
8
|
+
const require_code_artifacts = require('./code-artifacts.cjs');
|
|
9
|
+
const require_near_cli = require('./near-cli.cjs');
|
|
10
|
+
let node_fs = require("node:fs");
|
|
11
|
+
let node_path = require("node:path");
|
|
12
|
+
let effect = require("effect");
|
|
13
|
+
let node_process = require("node:process");
|
|
14
|
+
node_process = require_runtime.__toESM(node_process, 1);
|
|
15
|
+
|
|
16
|
+
//#region src/publish.ts
|
|
17
|
+
function sleep(ms) {
|
|
18
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19
|
+
}
|
|
20
|
+
function extractPublishedUrl(output) {
|
|
21
|
+
const deployMatch = output.match(/🚀.*Deployed:\s*(https?:\S+)/);
|
|
22
|
+
if (deployMatch) return deployMatch[1];
|
|
23
|
+
const match = output.match(/https?:\/\/[^\s"'<>]+/g);
|
|
24
|
+
if (!match || match.length === 0) return null;
|
|
25
|
+
return match[match.length - 1] ?? null;
|
|
26
|
+
}
|
|
27
|
+
async function waitForPublishedConfig(opts) {
|
|
28
|
+
const envTimeoutMs = Number(node_process.default.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);
|
|
29
|
+
const envIntervalMs = Number(node_process.default.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);
|
|
30
|
+
const timeoutMs = opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : void 0) ?? 12e4;
|
|
31
|
+
const intervalMs = opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : void 0) ?? 3e3;
|
|
32
|
+
const startedAt = Date.now();
|
|
33
|
+
let lastError;
|
|
34
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
35
|
+
try {
|
|
36
|
+
const verifiedConfig = await require_fastkv.fetchBosConfigFromFastKv(`bos://${opts.account}/${opts.gateway}`);
|
|
37
|
+
if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) return;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
lastError = error;
|
|
40
|
+
}
|
|
41
|
+
await sleep(intervalMs);
|
|
42
|
+
}
|
|
43
|
+
const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
|
|
44
|
+
throw new Error(`Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`);
|
|
45
|
+
}
|
|
46
|
+
async function publishToFastKv(input) {
|
|
47
|
+
const { env, dryRun, configDir } = input;
|
|
48
|
+
let bosConfig = input.bosConfig;
|
|
49
|
+
const runtimeConfig = input.runtimeConfig;
|
|
50
|
+
const isStaging = env === "staging";
|
|
51
|
+
const account = bosConfig.account;
|
|
52
|
+
const gateway = isStaging ? bosConfig.staging?.domain ?? bosConfig.domain : bosConfig.domain;
|
|
53
|
+
if (!gateway) return {
|
|
54
|
+
status: "error",
|
|
55
|
+
registryUrl: "",
|
|
56
|
+
error: "bos.config.json must define domain to publish"
|
|
57
|
+
};
|
|
58
|
+
const network = input.network ?? require_network.getNetworkIdForAccount(account);
|
|
59
|
+
const registryUrl = require_fastkv.buildRegistryConfigUrlForNetwork(network, account, gateway);
|
|
60
|
+
const targets = require_build.selectWorkspaceTargets(input.packages, bosConfig);
|
|
61
|
+
let built;
|
|
62
|
+
let skipped;
|
|
63
|
+
let deployResults;
|
|
64
|
+
if (dryRun) return {
|
|
65
|
+
status: "dry-run",
|
|
66
|
+
registryUrl,
|
|
67
|
+
built,
|
|
68
|
+
skipped
|
|
69
|
+
};
|
|
70
|
+
const privateKey = input.privateKey || node_process.default.env.NEAR_PRIVATE_KEY || node_process.default.env.BOS_NEAR_PRIVATE_KEY;
|
|
71
|
+
let signingMode;
|
|
72
|
+
try {
|
|
73
|
+
signingMode = require_near_cli.resolveNearSigningMode(privateKey);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
return {
|
|
76
|
+
status: "error",
|
|
77
|
+
registryUrl,
|
|
78
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
if (input.build) {
|
|
82
|
+
console.log(" Ensuring NEAR CLI...");
|
|
83
|
+
await effect.Effect.runPromise(require_near_cli.ensureNearCli);
|
|
84
|
+
console.log(" NEAR CLI ready");
|
|
85
|
+
await require_code_artifacts.generateCodeArtifacts(configDir, bosConfig, {
|
|
86
|
+
env: "production",
|
|
87
|
+
runtimeConfig: runtimeConfig ?? void 0
|
|
88
|
+
});
|
|
89
|
+
const result = await require_build.buildWorkspaceTargets({
|
|
90
|
+
configDir,
|
|
91
|
+
bosConfig,
|
|
92
|
+
runtimeConfig,
|
|
93
|
+
targets,
|
|
94
|
+
deploy: true,
|
|
95
|
+
verbose: input.verbose
|
|
96
|
+
});
|
|
97
|
+
built = result.built;
|
|
98
|
+
skipped = result.skipped;
|
|
99
|
+
deployResults = result.deployResults;
|
|
100
|
+
if (deployResults) {
|
|
101
|
+
const failures = deployResults.filter((r) => !r.success);
|
|
102
|
+
if (failures.length > 0) {
|
|
103
|
+
const total = deployResults.length;
|
|
104
|
+
console.log();
|
|
105
|
+
console.log(require_theme.colors.error(` ${require_theme.icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? "s" : ""} failed`));
|
|
106
|
+
console.log();
|
|
107
|
+
for (const f of failures) {
|
|
108
|
+
const errorLine = (f.error ?? "Failed").split("\n")[0];
|
|
109
|
+
console.log(` ${require_theme.colors.error(require_theme.icons.err)} ${require_string.padRight(f.key, 28)} ${errorLine}`);
|
|
110
|
+
}
|
|
111
|
+
console.log();
|
|
112
|
+
if (!input.verbose) {
|
|
113
|
+
console.log(require_theme.colors.dim(" Run with --verbose for full build output."));
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
status: "error",
|
|
118
|
+
registryUrl,
|
|
119
|
+
built,
|
|
120
|
+
skipped,
|
|
121
|
+
deployResults,
|
|
122
|
+
error: `${failures.length} of ${total} workspaces failed to deploy`
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const refreshed = await require_config.loadResolvedConfig({ cwd: configDir });
|
|
127
|
+
if (!refreshed?.config) return {
|
|
128
|
+
status: "error",
|
|
129
|
+
registryUrl,
|
|
130
|
+
built,
|
|
131
|
+
skipped,
|
|
132
|
+
deployResults,
|
|
133
|
+
error: "Failed to reload bos.config.json after build"
|
|
134
|
+
};
|
|
135
|
+
bosConfig = refreshed.config;
|
|
136
|
+
}
|
|
137
|
+
const rawConfigPath = (0, node_path.join)(configDir, "bos.config.json");
|
|
138
|
+
const rawConfig = JSON.parse((0, node_fs.readFileSync)(rawConfigPath, "utf-8"));
|
|
139
|
+
const publishPayload = isStaging ? {
|
|
140
|
+
...rawConfig,
|
|
141
|
+
domain: gateway
|
|
142
|
+
} : rawConfig;
|
|
143
|
+
const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload) };
|
|
144
|
+
const payload = JSON.stringify(registryEntries);
|
|
145
|
+
const argsBase64 = Buffer.from(payload).toString("base64");
|
|
146
|
+
console.log();
|
|
147
|
+
console.log(" Publishing to:");
|
|
148
|
+
console.log(` ${require_theme.colors.cyan(registryUrl)}`);
|
|
149
|
+
try {
|
|
150
|
+
let txHash;
|
|
151
|
+
console.log(` Submitting transaction on ${network}...`);
|
|
152
|
+
try {
|
|
153
|
+
const tx = await effect.Effect.runPromise(require_near_cli.executeTransaction({
|
|
154
|
+
account,
|
|
155
|
+
contract: require_fastkv.getRegistryNamespaceForNetwork(network),
|
|
156
|
+
method: "__fastdata_kv",
|
|
157
|
+
argsBase64,
|
|
158
|
+
network,
|
|
159
|
+
privateKey: signingMode._tag === "privateKey" ? signingMode.privateKey : void 0,
|
|
160
|
+
gas: "300Tgas",
|
|
161
|
+
deposit: "0NEAR",
|
|
162
|
+
verbose: input.verbose
|
|
163
|
+
}, signingMode));
|
|
164
|
+
txHash = tx.txHash;
|
|
165
|
+
if (txHash && !tx.output?.includes("CodeDoesNotExist")) console.log(` Transaction submitted: ${require_theme.colors.dim(txHash)}`);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.log(require_theme.colors.dim(" Transaction reported an error — verifying publish..."));
|
|
168
|
+
try {
|
|
169
|
+
await waitForPublishedConfig({
|
|
170
|
+
account,
|
|
171
|
+
gateway,
|
|
172
|
+
publishConfig: publishPayload,
|
|
173
|
+
timeoutMs: 3e4,
|
|
174
|
+
intervalMs: 2e3
|
|
175
|
+
});
|
|
176
|
+
txHash = extractTransactionHash(error);
|
|
177
|
+
} catch {
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
console.log(" Waiting for publish confirmation...");
|
|
182
|
+
await waitForPublishedConfig({
|
|
183
|
+
account,
|
|
184
|
+
gateway,
|
|
185
|
+
publishConfig: publishPayload
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
status: "published",
|
|
189
|
+
registryUrl,
|
|
190
|
+
txHash,
|
|
191
|
+
built,
|
|
192
|
+
skipped,
|
|
193
|
+
deployResults,
|
|
194
|
+
publishConfig: publishPayload
|
|
195
|
+
};
|
|
196
|
+
} catch (error) {
|
|
197
|
+
return {
|
|
198
|
+
status: "error",
|
|
199
|
+
registryUrl,
|
|
200
|
+
error: formatNearError(error),
|
|
201
|
+
built,
|
|
202
|
+
skipped,
|
|
203
|
+
deployResults
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function formatNearError(error) {
|
|
208
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
209
|
+
if (message.includes("exceeded gas") || message.includes("GasLimitExceeded")) return `Transaction exceeded gas limit.\n Original: ${message}`;
|
|
210
|
+
if (message.includes("timeout") || message.includes("Timeout")) return `Transaction timed out. Check NEAR network status.\n Original: ${message}`;
|
|
211
|
+
return message;
|
|
212
|
+
}
|
|
213
|
+
function extractTransactionHash(error) {
|
|
214
|
+
return (error instanceof Error ? error.message : String(error)).match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
//#endregion
|
|
218
|
+
exports.extractPublishedUrl = extractPublishedUrl;
|
|
219
|
+
exports.publishToFastKv = publishToFastKv;
|
|
220
|
+
//# sourceMappingURL=publish.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.cjs","names":["process","fetchBosConfigFromFastKv","getNetworkIdForAccount","buildRegistryConfigUrlForNetwork","selectWorkspaceTargets","resolveNearSigningMode","Effect","ensureNearCli","generateCodeArtifacts","buildWorkspaceTargets","colors","icons","padRight","loadResolvedConfig","executeTransaction","getRegistryNamespaceForNetwork"],"sources":["../src/publish.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { buildWorkspaceTargets, selectWorkspaceTargets } from \"./build\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { loadResolvedConfig } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n} from \"./fastkv\";\nimport { ensureNearCli, executeTransaction, resolveNearSigningMode } from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type { BosConfig, BosConfigInput, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function extractPublishedUrl(output: string): string | null {\n const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n if (deployMatch) return deployMatch[1];\n const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n if (!match || match.length === 0) return null;\n return match[match.length - 1] ?? null;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n}\n\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const { env, dryRun, configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n\n const isStaging = env === \"staging\";\n const account = bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n status: \"error\",\n registryUrl: \"\",\n error: \"bos.config.json must define domain to publish\",\n };\n }\n\n const network = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);\n const targets = selectWorkspaceTargets(input.packages, bosConfig);\n\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n\n if (dryRun) {\n return { status: \"dry-run\", registryUrl, built, skipped };\n }\n\n const privateKey =\n input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;\n let signingMode: ReturnType<typeof resolveNearSigningMode>;\n try {\n signingMode = resolveNearSigningMode(privateKey);\n } catch (error) {\n return {\n status: \"error\" as const,\n registryUrl,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n\n if (input.build) {\n console.log(\" Ensuring NEAR CLI...\");\n await Effect.runPromise(ensureNearCli);\n console.log(\" NEAR CLI ready\");\n\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await loadResolvedConfig({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload bos.config.json after build\",\n };\n }\n\n bosConfig = refreshed.config;\n }\n\n const rawConfigPath = join(configDir, \"bos.config.json\");\n const rawConfig = JSON.parse(readFileSync(rawConfigPath, \"utf-8\")) as BosConfigInput;\n const publishPayload: BosConfigInput = isStaging ? { ...rawConfig, domain: gateway } : rawConfig;\n\n const registryEntries: Record<string, string> = {\n [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload),\n };\n\n const payload = JSON.stringify(registryEntries);\n const argsBase64 = Buffer.from(payload).toString(\"base64\");\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n\n try {\n let txHash: string | undefined;\n\n console.log(` Submitting transaction on ${network}...`);\n\n try {\n const tx = await Effect.runPromise(\n executeTransaction(\n {\n account,\n contract: getRegistryNamespaceForNetwork(network),\n method: \"__fastdata_kv\",\n argsBase64,\n network,\n privateKey: signingMode._tag === \"privateKey\" ? signingMode.privateKey : undefined,\n gas: \"300Tgas\",\n deposit: \"0NEAR\",\n verbose: input.verbose,\n },\n signingMode,\n ),\n );\n txHash = tx.txHash;\n if (txHash && !tx.output?.includes(\"CodeDoesNotExist\")) {\n console.log(` Transaction submitted: ${colors.dim(txHash)}`);\n }\n } catch (error) {\n console.log(colors.dim(\" Transaction reported an error — verifying publish...\"));\n try {\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n timeoutMs: 30_000,\n intervalMs: 2_000,\n });\n txHash = extractTransactionHash(error);\n } catch {\n throw error;\n }\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n });\n\n return {\n status: \"published\",\n registryUrl,\n txHash,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n\nfunction extractTransactionHash(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n const match = message.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n"],"mappings":"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"}
|
package/dist/publish.mjs
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { buildRegistryConfigUrlForNetwork, fetchBosConfigFromFastKv, getRegistryNamespaceForNetwork } from "./fastkv.mjs";
|
|
2
|
+
import { getNetworkIdForAccount } from "./network.mjs";
|
|
3
|
+
import { loadResolvedConfig } from "./config.mjs";
|
|
4
|
+
import { padRight } from "./utils/string.mjs";
|
|
5
|
+
import { colors, icons } from "./utils/theme.mjs";
|
|
6
|
+
import { buildWorkspaceTargets, selectWorkspaceTargets } from "./build.mjs";
|
|
7
|
+
import { generateCodeArtifacts } from "./code-artifacts.mjs";
|
|
8
|
+
import { ensureNearCli, executeTransaction, resolveNearSigningMode } from "./near-cli.mjs";
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { Effect } from "effect";
|
|
12
|
+
import process from "node:process";
|
|
13
|
+
|
|
14
|
+
//#region src/publish.ts
|
|
15
|
+
function sleep(ms) {
|
|
16
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
+
}
|
|
18
|
+
function extractPublishedUrl(output) {
|
|
19
|
+
const deployMatch = output.match(/🚀.*Deployed:\s*(https?:\S+)/);
|
|
20
|
+
if (deployMatch) return deployMatch[1];
|
|
21
|
+
const match = output.match(/https?:\/\/[^\s"'<>]+/g);
|
|
22
|
+
if (!match || match.length === 0) return null;
|
|
23
|
+
return match[match.length - 1] ?? null;
|
|
24
|
+
}
|
|
25
|
+
async function waitForPublishedConfig(opts) {
|
|
26
|
+
const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);
|
|
27
|
+
const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);
|
|
28
|
+
const timeoutMs = opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : void 0) ?? 12e4;
|
|
29
|
+
const intervalMs = opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : void 0) ?? 3e3;
|
|
30
|
+
const startedAt = Date.now();
|
|
31
|
+
let lastError;
|
|
32
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
33
|
+
try {
|
|
34
|
+
const verifiedConfig = await fetchBosConfigFromFastKv(`bos://${opts.account}/${opts.gateway}`);
|
|
35
|
+
if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) return;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
lastError = error;
|
|
38
|
+
}
|
|
39
|
+
await sleep(intervalMs);
|
|
40
|
+
}
|
|
41
|
+
const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
|
|
42
|
+
throw new Error(`Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`);
|
|
43
|
+
}
|
|
44
|
+
async function publishToFastKv(input) {
|
|
45
|
+
const { env, dryRun, configDir } = input;
|
|
46
|
+
let bosConfig = input.bosConfig;
|
|
47
|
+
const runtimeConfig = input.runtimeConfig;
|
|
48
|
+
const isStaging = env === "staging";
|
|
49
|
+
const account = bosConfig.account;
|
|
50
|
+
const gateway = isStaging ? bosConfig.staging?.domain ?? bosConfig.domain : bosConfig.domain;
|
|
51
|
+
if (!gateway) return {
|
|
52
|
+
status: "error",
|
|
53
|
+
registryUrl: "",
|
|
54
|
+
error: "bos.config.json must define domain to publish"
|
|
55
|
+
};
|
|
56
|
+
const network = input.network ?? getNetworkIdForAccount(account);
|
|
57
|
+
const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);
|
|
58
|
+
const targets = selectWorkspaceTargets(input.packages, bosConfig);
|
|
59
|
+
let built;
|
|
60
|
+
let skipped;
|
|
61
|
+
let deployResults;
|
|
62
|
+
if (dryRun) return {
|
|
63
|
+
status: "dry-run",
|
|
64
|
+
registryUrl,
|
|
65
|
+
built,
|
|
66
|
+
skipped
|
|
67
|
+
};
|
|
68
|
+
const privateKey = input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;
|
|
69
|
+
let signingMode;
|
|
70
|
+
try {
|
|
71
|
+
signingMode = resolveNearSigningMode(privateKey);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
return {
|
|
74
|
+
status: "error",
|
|
75
|
+
registryUrl,
|
|
76
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (input.build) {
|
|
80
|
+
console.log(" Ensuring NEAR CLI...");
|
|
81
|
+
await Effect.runPromise(ensureNearCli);
|
|
82
|
+
console.log(" NEAR CLI ready");
|
|
83
|
+
await generateCodeArtifacts(configDir, bosConfig, {
|
|
84
|
+
env: "production",
|
|
85
|
+
runtimeConfig: runtimeConfig ?? void 0
|
|
86
|
+
});
|
|
87
|
+
const result = await buildWorkspaceTargets({
|
|
88
|
+
configDir,
|
|
89
|
+
bosConfig,
|
|
90
|
+
runtimeConfig,
|
|
91
|
+
targets,
|
|
92
|
+
deploy: true,
|
|
93
|
+
verbose: input.verbose
|
|
94
|
+
});
|
|
95
|
+
built = result.built;
|
|
96
|
+
skipped = result.skipped;
|
|
97
|
+
deployResults = result.deployResults;
|
|
98
|
+
if (deployResults) {
|
|
99
|
+
const failures = deployResults.filter((r) => !r.success);
|
|
100
|
+
if (failures.length > 0) {
|
|
101
|
+
const total = deployResults.length;
|
|
102
|
+
console.log();
|
|
103
|
+
console.log(colors.error(` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? "s" : ""} failed`));
|
|
104
|
+
console.log();
|
|
105
|
+
for (const f of failures) {
|
|
106
|
+
const errorLine = (f.error ?? "Failed").split("\n")[0];
|
|
107
|
+
console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);
|
|
108
|
+
}
|
|
109
|
+
console.log();
|
|
110
|
+
if (!input.verbose) {
|
|
111
|
+
console.log(colors.dim(" Run with --verbose for full build output."));
|
|
112
|
+
console.log();
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
status: "error",
|
|
116
|
+
registryUrl,
|
|
117
|
+
built,
|
|
118
|
+
skipped,
|
|
119
|
+
deployResults,
|
|
120
|
+
error: `${failures.length} of ${total} workspaces failed to deploy`
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const refreshed = await loadResolvedConfig({ cwd: configDir });
|
|
125
|
+
if (!refreshed?.config) return {
|
|
126
|
+
status: "error",
|
|
127
|
+
registryUrl,
|
|
128
|
+
built,
|
|
129
|
+
skipped,
|
|
130
|
+
deployResults,
|
|
131
|
+
error: "Failed to reload bos.config.json after build"
|
|
132
|
+
};
|
|
133
|
+
bosConfig = refreshed.config;
|
|
134
|
+
}
|
|
135
|
+
const rawConfigPath = join(configDir, "bos.config.json");
|
|
136
|
+
const rawConfig = JSON.parse(readFileSync(rawConfigPath, "utf-8"));
|
|
137
|
+
const publishPayload = isStaging ? {
|
|
138
|
+
...rawConfig,
|
|
139
|
+
domain: gateway
|
|
140
|
+
} : rawConfig;
|
|
141
|
+
const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload) };
|
|
142
|
+
const payload = JSON.stringify(registryEntries);
|
|
143
|
+
const argsBase64 = Buffer.from(payload).toString("base64");
|
|
144
|
+
console.log();
|
|
145
|
+
console.log(" Publishing to:");
|
|
146
|
+
console.log(` ${colors.cyan(registryUrl)}`);
|
|
147
|
+
try {
|
|
148
|
+
let txHash;
|
|
149
|
+
console.log(` Submitting transaction on ${network}...`);
|
|
150
|
+
try {
|
|
151
|
+
const tx = await Effect.runPromise(executeTransaction({
|
|
152
|
+
account,
|
|
153
|
+
contract: getRegistryNamespaceForNetwork(network),
|
|
154
|
+
method: "__fastdata_kv",
|
|
155
|
+
argsBase64,
|
|
156
|
+
network,
|
|
157
|
+
privateKey: signingMode._tag === "privateKey" ? signingMode.privateKey : void 0,
|
|
158
|
+
gas: "300Tgas",
|
|
159
|
+
deposit: "0NEAR",
|
|
160
|
+
verbose: input.verbose
|
|
161
|
+
}, signingMode));
|
|
162
|
+
txHash = tx.txHash;
|
|
163
|
+
if (txHash && !tx.output?.includes("CodeDoesNotExist")) console.log(` Transaction submitted: ${colors.dim(txHash)}`);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.log(colors.dim(" Transaction reported an error — verifying publish..."));
|
|
166
|
+
try {
|
|
167
|
+
await waitForPublishedConfig({
|
|
168
|
+
account,
|
|
169
|
+
gateway,
|
|
170
|
+
publishConfig: publishPayload,
|
|
171
|
+
timeoutMs: 3e4,
|
|
172
|
+
intervalMs: 2e3
|
|
173
|
+
});
|
|
174
|
+
txHash = extractTransactionHash(error);
|
|
175
|
+
} catch {
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
console.log(" Waiting for publish confirmation...");
|
|
180
|
+
await waitForPublishedConfig({
|
|
181
|
+
account,
|
|
182
|
+
gateway,
|
|
183
|
+
publishConfig: publishPayload
|
|
184
|
+
});
|
|
185
|
+
return {
|
|
186
|
+
status: "published",
|
|
187
|
+
registryUrl,
|
|
188
|
+
txHash,
|
|
189
|
+
built,
|
|
190
|
+
skipped,
|
|
191
|
+
deployResults,
|
|
192
|
+
publishConfig: publishPayload
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
return {
|
|
196
|
+
status: "error",
|
|
197
|
+
registryUrl,
|
|
198
|
+
error: formatNearError(error),
|
|
199
|
+
built,
|
|
200
|
+
skipped,
|
|
201
|
+
deployResults
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function formatNearError(error) {
|
|
206
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
207
|
+
if (message.includes("exceeded gas") || message.includes("GasLimitExceeded")) return `Transaction exceeded gas limit.\n Original: ${message}`;
|
|
208
|
+
if (message.includes("timeout") || message.includes("Timeout")) return `Transaction timed out. Check NEAR network status.\n Original: ${message}`;
|
|
209
|
+
return message;
|
|
210
|
+
}
|
|
211
|
+
function extractTransactionHash(error) {
|
|
212
|
+
return (error instanceof Error ? error.message : String(error)).match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
//#endregion
|
|
216
|
+
export { extractPublishedUrl, publishToFastKv };
|
|
217
|
+
//# sourceMappingURL=publish.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.mjs","names":[],"sources":["../src/publish.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { buildWorkspaceTargets, selectWorkspaceTargets } from \"./build\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { loadResolvedConfig } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport {\n buildRegistryConfigUrlForNetwork,\n fetchBosConfigFromFastKv,\n getRegistryNamespaceForNetwork,\n} from \"./fastkv\";\nimport { ensureNearCli, executeTransaction, resolveNearSigningMode } from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type { BosConfig, BosConfigInput, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function extractPublishedUrl(output: string): string | null {\n const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n if (deployMatch) return deployMatch[1];\n const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n if (!match || match.length === 0) return null;\n return match[match.length - 1] ?? null;\n}\n\nexport async function waitForPublishedConfig(opts: {\n account: string;\n gateway: string;\n publishConfig: BosConfigInput;\n timeoutMs?: number;\n intervalMs?: number;\n}): Promise<void> {\n const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n const timeoutMs =\n opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n const intervalMs =\n opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n const startedAt = Date.now();\n let lastError: unknown;\n\n while (Date.now() - startedAt < timeoutMs) {\n try {\n const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n `bos://${opts.account}/${opts.gateway}`,\n );\n\n if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n return;\n }\n } catch (error) {\n lastError = error;\n }\n\n await sleep(intervalMs);\n }\n\n const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n throw new Error(\n `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n );\n}\n\ninterface PublishToFastKvInput {\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig | null;\n configDir: string;\n env: \"production\" | \"staging\";\n build: boolean;\n dryRun: boolean;\n verbose: boolean;\n packages: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n}\n\ninterface PublishToFastKvResult {\n status: \"published\" | \"error\" | \"dry-run\";\n registryUrl: string;\n txHash?: string;\n built?: string[];\n skipped?: string[];\n error?: string;\n publishConfig?: BosConfigInput;\n deployResults?: WorkspaceDeployResult[];\n}\n\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n const { env, dryRun, configDir } = input;\n let bosConfig = input.bosConfig;\n const runtimeConfig = input.runtimeConfig;\n\n const isStaging = env === \"staging\";\n const account = bosConfig.account;\n const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n if (!gateway) {\n return {\n status: \"error\",\n registryUrl: \"\",\n error: \"bos.config.json must define domain to publish\",\n };\n }\n\n const network = input.network ?? getNetworkIdForAccount(account);\n const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);\n const targets = selectWorkspaceTargets(input.packages, bosConfig);\n\n let built: string[] | undefined;\n let skipped: string[] | undefined;\n let deployResults: WorkspaceDeployResult[] | undefined;\n\n if (dryRun) {\n return { status: \"dry-run\", registryUrl, built, skipped };\n }\n\n const privateKey =\n input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;\n let signingMode: ReturnType<typeof resolveNearSigningMode>;\n try {\n signingMode = resolveNearSigningMode(privateKey);\n } catch (error) {\n return {\n status: \"error\" as const,\n registryUrl,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n\n if (input.build) {\n console.log(\" Ensuring NEAR CLI...\");\n await Effect.runPromise(ensureNearCli);\n console.log(\" NEAR CLI ready\");\n\n await generateCodeArtifacts(configDir, bosConfig, {\n env: \"production\",\n runtimeConfig: runtimeConfig ?? undefined,\n });\n\n const result = await buildWorkspaceTargets({\n configDir,\n bosConfig,\n runtimeConfig,\n targets,\n deploy: true,\n verbose: input.verbose,\n });\n built = result.built;\n skipped = result.skipped;\n deployResults = result.deployResults;\n\n if (deployResults) {\n const failures = deployResults.filter((r) => !r.success);\n if (failures.length > 0) {\n const total = deployResults.length;\n console.log();\n console.log(\n colors.error(\n ` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n ),\n );\n console.log();\n for (const f of failures) {\n const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n }\n console.log();\n if (!input.verbose) {\n console.log(colors.dim(\" Run with --verbose for full build output.\"));\n console.log();\n }\n return {\n status: \"error\" as const,\n registryUrl,\n built,\n skipped,\n deployResults,\n error: `${failures.length} of ${total} workspaces failed to deploy`,\n };\n }\n }\n\n const refreshed = await loadResolvedConfig({ cwd: configDir });\n if (!refreshed?.config) {\n return {\n status: \"error\",\n registryUrl,\n built,\n skipped,\n deployResults,\n error: \"Failed to reload bos.config.json after build\",\n };\n }\n\n bosConfig = refreshed.config;\n }\n\n const rawConfigPath = join(configDir, \"bos.config.json\");\n const rawConfig = JSON.parse(readFileSync(rawConfigPath, \"utf-8\")) as BosConfigInput;\n const publishPayload: BosConfigInput = isStaging ? { ...rawConfig, domain: gateway } : rawConfig;\n\n const registryEntries: Record<string, string> = {\n [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload),\n };\n\n const payload = JSON.stringify(registryEntries);\n const argsBase64 = Buffer.from(payload).toString(\"base64\");\n\n console.log();\n console.log(\" Publishing to:\");\n console.log(` ${colors.cyan(registryUrl)}`);\n\n try {\n let txHash: string | undefined;\n\n console.log(` Submitting transaction on ${network}...`);\n\n try {\n const tx = await Effect.runPromise(\n executeTransaction(\n {\n account,\n contract: getRegistryNamespaceForNetwork(network),\n method: \"__fastdata_kv\",\n argsBase64,\n network,\n privateKey: signingMode._tag === \"privateKey\" ? signingMode.privateKey : undefined,\n gas: \"300Tgas\",\n deposit: \"0NEAR\",\n verbose: input.verbose,\n },\n signingMode,\n ),\n );\n txHash = tx.txHash;\n if (txHash && !tx.output?.includes(\"CodeDoesNotExist\")) {\n console.log(` Transaction submitted: ${colors.dim(txHash)}`);\n }\n } catch (error) {\n console.log(colors.dim(\" Transaction reported an error — verifying publish...\"));\n try {\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n timeoutMs: 30_000,\n intervalMs: 2_000,\n });\n txHash = extractTransactionHash(error);\n } catch {\n throw error;\n }\n }\n\n console.log(\" Waiting for publish confirmation...\");\n await waitForPublishedConfig({\n account,\n gateway,\n publishConfig: publishPayload,\n });\n\n return {\n status: \"published\",\n registryUrl,\n txHash,\n built,\n skipped,\n deployResults,\n publishConfig: publishPayload,\n };\n } catch (error) {\n return {\n status: \"error\",\n registryUrl,\n error: formatNearError(error),\n built,\n skipped,\n deployResults,\n };\n }\n}\n\nfunction formatNearError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n return `Transaction exceeded gas limit.\\n Original: ${message}`;\n }\n\n if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n return `Transaction timed out. Check NEAR network status.\\n Original: ${message}`;\n }\n\n return message;\n}\n\nfunction extractTransactionHash(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n const match = message.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n"],"mappings":"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"}
|
package/dist/types.d.cts
CHANGED
|
@@ -386,8 +386,8 @@ declare const RuntimeConfigSchema: z.ZodObject<{
|
|
|
386
386
|
account: z.ZodString;
|
|
387
387
|
domain: z.ZodOptional<z.ZodString>;
|
|
388
388
|
networkId: z.ZodEnum<{
|
|
389
|
-
testnet: "testnet";
|
|
390
389
|
mainnet: "mainnet";
|
|
390
|
+
testnet: "testnet";
|
|
391
391
|
}>;
|
|
392
392
|
title: z.ZodOptional<z.ZodString>;
|
|
393
393
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -514,8 +514,8 @@ declare const ClientRuntimeConfigSchema: z.ZodObject<{
|
|
|
514
514
|
}>;
|
|
515
515
|
account: z.ZodString;
|
|
516
516
|
networkId: z.ZodEnum<{
|
|
517
|
-
testnet: "testnet";
|
|
518
517
|
mainnet: "mainnet";
|
|
518
|
+
testnet: "testnet";
|
|
519
519
|
}>;
|
|
520
520
|
hostUrl: z.ZodOptional<z.ZodString>;
|
|
521
521
|
assetsUrl: z.ZodString;
|
package/dist/types.d.mts
CHANGED
|
@@ -386,8 +386,8 @@ declare const RuntimeConfigSchema: z.ZodObject<{
|
|
|
386
386
|
account: z.ZodString;
|
|
387
387
|
domain: z.ZodOptional<z.ZodString>;
|
|
388
388
|
networkId: z.ZodEnum<{
|
|
389
|
-
testnet: "testnet";
|
|
390
389
|
mainnet: "mainnet";
|
|
390
|
+
testnet: "testnet";
|
|
391
391
|
}>;
|
|
392
392
|
title: z.ZodOptional<z.ZodString>;
|
|
393
393
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -514,8 +514,8 @@ declare const ClientRuntimeConfigSchema: z.ZodObject<{
|
|
|
514
514
|
}>;
|
|
515
515
|
account: z.ZodString;
|
|
516
516
|
networkId: z.ZodEnum<{
|
|
517
|
-
testnet: "testnet";
|
|
518
517
|
mainnet: "mainnet";
|
|
518
|
+
testnet: "testnet";
|
|
519
519
|
}>;
|
|
520
520
|
hostUrl: z.ZodOptional<z.ZodString>;
|
|
521
521
|
assetsUrl: z.ZodString;
|
package/dist/utils/run.cjs
CHANGED
|
@@ -3,7 +3,7 @@ let execa = require("execa");
|
|
|
3
3
|
|
|
4
4
|
//#region src/utils/run.ts
|
|
5
5
|
async function run(cmd, args, options = {}) {
|
|
6
|
-
const proc =
|
|
6
|
+
const proc = (0, execa.execa)(cmd, args, {
|
|
7
7
|
cwd: options.cwd,
|
|
8
8
|
env: options.env ? {
|
|
9
9
|
...process.env,
|
|
@@ -12,14 +12,32 @@ async function run(cmd, args, options = {}) {
|
|
|
12
12
|
stdio: options.capture ? "pipe" : "inherit",
|
|
13
13
|
reject: false
|
|
14
14
|
});
|
|
15
|
+
let capturedStdout = "";
|
|
16
|
+
let capturedStderr = "";
|
|
17
|
+
if (options.capture && options.onChunk) {
|
|
18
|
+
proc.stdout?.on("data", (chunk) => {
|
|
19
|
+
capturedStdout += chunk.toString("utf-8");
|
|
20
|
+
options.onChunk("stdout", chunk);
|
|
21
|
+
});
|
|
22
|
+
proc.stderr?.on("data", (chunk) => {
|
|
23
|
+
capturedStderr += chunk.toString("utf-8");
|
|
24
|
+
options.onChunk("stderr", chunk);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
await proc;
|
|
15
28
|
if (!options.capture) {
|
|
16
29
|
const exitCode = proc.exitCode ?? 0;
|
|
17
30
|
if (exitCode !== 0) throw new Error(`${cmd} ${args.join(" ")} failed with exit code ${exitCode}`);
|
|
18
31
|
return;
|
|
19
32
|
}
|
|
33
|
+
if (options.onChunk) return {
|
|
34
|
+
stdout: capturedStdout,
|
|
35
|
+
stderr: capturedStderr,
|
|
36
|
+
exitCode: proc.exitCode ?? 0
|
|
37
|
+
};
|
|
20
38
|
return {
|
|
21
|
-
stdout: proc.stdout
|
|
22
|
-
stderr: proc.stderr
|
|
39
|
+
stdout: typeof proc.stdout === "string" ? proc.stdout : "",
|
|
40
|
+
stderr: typeof proc.stderr === "string" ? proc.stderr : "",
|
|
23
41
|
exitCode: proc.exitCode ?? 0
|
|
24
42
|
};
|
|
25
43
|
}
|
package/dist/utils/run.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.cjs","names":[],"sources":["../../src/utils/run.ts"],"sourcesContent":["import { execa } from \"execa\";\n\ntype RunResult = { stdout: string; stderr: string; exitCode: number };\n\nexport async function run(\n cmd: string,\n args: string[],\n options: {
|
|
1
|
+
{"version":3,"file":"run.cjs","names":[],"sources":["../../src/utils/run.ts"],"sourcesContent":["import { execa } from \"execa\";\n\ntype RunResult = { stdout: string; stderr: string; exitCode: number };\n\nexport async function run(\n cmd: string,\n args: string[],\n options: {\n cwd?: string;\n env?: Record<string, string>;\n capture?: boolean;\n onChunk?: (stream: \"stdout\" | \"stderr\", chunk: Buffer) => void;\n } = {},\n): Promise<RunResult | undefined> {\n const proc = execa(cmd, args, {\n cwd: options.cwd,\n env: options.env ? { ...(process.env as Record<string, string>), ...options.env } : process.env,\n stdio: options.capture ? \"pipe\" : \"inherit\",\n reject: false,\n });\n\n let capturedStdout = \"\";\n let capturedStderr = \"\";\n\n if (options.capture && options.onChunk) {\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n capturedStdout += chunk.toString(\"utf-8\");\n options.onChunk!(\"stdout\", chunk);\n });\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n capturedStderr += chunk.toString(\"utf-8\");\n options.onChunk!(\"stderr\", chunk);\n });\n }\n\n await proc;\n\n if (!options.capture) {\n const exitCode = proc.exitCode ?? 0;\n if (exitCode !== 0) {\n throw new Error(`${cmd} ${args.join(\" \")} failed with exit code ${exitCode}`);\n }\n return;\n }\n\n if (options.onChunk) {\n return {\n stdout: capturedStdout,\n stderr: capturedStderr,\n exitCode: proc.exitCode ?? 0,\n };\n }\n\n const result: RunResult = {\n stdout: typeof proc.stdout === \"string\" ? proc.stdout : \"\",\n stderr: typeof proc.stderr === \"string\" ? proc.stderr : \"\",\n exitCode: proc.exitCode ?? 0,\n };\n return result;\n}\n"],"mappings":";;;;AAIA,eAAsB,IACpB,KACA,MACA,UAKI,EAAE,EAC0B;CAChC,MAAM,wBAAa,KAAK,MAAM;EAC5B,KAAK,QAAQ;EACb,KAAK,QAAQ,MAAM;GAAE,GAAI,QAAQ;GAAgC,GAAG,QAAQ;GAAK,GAAG,QAAQ;EAC5F,OAAO,QAAQ,UAAU,SAAS;EAClC,QAAQ;EACT,CAAC;CAEF,IAAI,iBAAiB;CACrB,IAAI,iBAAiB;AAErB,KAAI,QAAQ,WAAW,QAAQ,SAAS;AACtC,OAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,qBAAkB,MAAM,SAAS,QAAQ;AACzC,WAAQ,QAAS,UAAU,MAAM;IACjC;AACF,OAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,qBAAkB,MAAM,SAAS,QAAQ;AACzC,WAAQ,QAAS,UAAU,MAAM;IACjC;;AAGJ,OAAM;AAEN,KAAI,CAAC,QAAQ,SAAS;EACpB,MAAM,WAAW,KAAK,YAAY;AAClC,MAAI,aAAa,EACf,OAAM,IAAI,MAAM,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,yBAAyB,WAAW;AAE/E;;AAGF,KAAI,QAAQ,QACV,QAAO;EACL,QAAQ;EACR,QAAQ;EACR,UAAU,KAAK,YAAY;EAC5B;AAQH,QAAO;EAJL,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;EACxD,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;EACxD,UAAU,KAAK,YAAY;EAEhB"}
|
package/dist/utils/run.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { execa } from "execa";
|
|
|
2
2
|
|
|
3
3
|
//#region src/utils/run.ts
|
|
4
4
|
async function run(cmd, args, options = {}) {
|
|
5
|
-
const proc =
|
|
5
|
+
const proc = execa(cmd, args, {
|
|
6
6
|
cwd: options.cwd,
|
|
7
7
|
env: options.env ? {
|
|
8
8
|
...process.env,
|
|
@@ -11,14 +11,32 @@ async function run(cmd, args, options = {}) {
|
|
|
11
11
|
stdio: options.capture ? "pipe" : "inherit",
|
|
12
12
|
reject: false
|
|
13
13
|
});
|
|
14
|
+
let capturedStdout = "";
|
|
15
|
+
let capturedStderr = "";
|
|
16
|
+
if (options.capture && options.onChunk) {
|
|
17
|
+
proc.stdout?.on("data", (chunk) => {
|
|
18
|
+
capturedStdout += chunk.toString("utf-8");
|
|
19
|
+
options.onChunk("stdout", chunk);
|
|
20
|
+
});
|
|
21
|
+
proc.stderr?.on("data", (chunk) => {
|
|
22
|
+
capturedStderr += chunk.toString("utf-8");
|
|
23
|
+
options.onChunk("stderr", chunk);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
await proc;
|
|
14
27
|
if (!options.capture) {
|
|
15
28
|
const exitCode = proc.exitCode ?? 0;
|
|
16
29
|
if (exitCode !== 0) throw new Error(`${cmd} ${args.join(" ")} failed with exit code ${exitCode}`);
|
|
17
30
|
return;
|
|
18
31
|
}
|
|
32
|
+
if (options.onChunk) return {
|
|
33
|
+
stdout: capturedStdout,
|
|
34
|
+
stderr: capturedStderr,
|
|
35
|
+
exitCode: proc.exitCode ?? 0
|
|
36
|
+
};
|
|
19
37
|
return {
|
|
20
|
-
stdout: proc.stdout
|
|
21
|
-
stderr: proc.stderr
|
|
38
|
+
stdout: typeof proc.stdout === "string" ? proc.stdout : "",
|
|
39
|
+
stderr: typeof proc.stderr === "string" ? proc.stderr : "",
|
|
22
40
|
exitCode: proc.exitCode ?? 0
|
|
23
41
|
};
|
|
24
42
|
}
|
package/dist/utils/run.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.mjs","names":[],"sources":["../../src/utils/run.ts"],"sourcesContent":["import { execa } from \"execa\";\n\ntype RunResult = { stdout: string; stderr: string; exitCode: number };\n\nexport async function run(\n cmd: string,\n args: string[],\n options: {
|
|
1
|
+
{"version":3,"file":"run.mjs","names":[],"sources":["../../src/utils/run.ts"],"sourcesContent":["import { execa } from \"execa\";\n\ntype RunResult = { stdout: string; stderr: string; exitCode: number };\n\nexport async function run(\n cmd: string,\n args: string[],\n options: {\n cwd?: string;\n env?: Record<string, string>;\n capture?: boolean;\n onChunk?: (stream: \"stdout\" | \"stderr\", chunk: Buffer) => void;\n } = {},\n): Promise<RunResult | undefined> {\n const proc = execa(cmd, args, {\n cwd: options.cwd,\n env: options.env ? { ...(process.env as Record<string, string>), ...options.env } : process.env,\n stdio: options.capture ? \"pipe\" : \"inherit\",\n reject: false,\n });\n\n let capturedStdout = \"\";\n let capturedStderr = \"\";\n\n if (options.capture && options.onChunk) {\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n capturedStdout += chunk.toString(\"utf-8\");\n options.onChunk!(\"stdout\", chunk);\n });\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n capturedStderr += chunk.toString(\"utf-8\");\n options.onChunk!(\"stderr\", chunk);\n });\n }\n\n await proc;\n\n if (!options.capture) {\n const exitCode = proc.exitCode ?? 0;\n if (exitCode !== 0) {\n throw new Error(`${cmd} ${args.join(\" \")} failed with exit code ${exitCode}`);\n }\n return;\n }\n\n if (options.onChunk) {\n return {\n stdout: capturedStdout,\n stderr: capturedStderr,\n exitCode: proc.exitCode ?? 0,\n };\n }\n\n const result: RunResult = {\n stdout: typeof proc.stdout === \"string\" ? proc.stdout : \"\",\n stderr: typeof proc.stderr === \"string\" ? proc.stderr : \"\",\n exitCode: proc.exitCode ?? 0,\n };\n return result;\n}\n"],"mappings":";;;AAIA,eAAsB,IACpB,KACA,MACA,UAKI,EAAE,EAC0B;CAChC,MAAM,OAAO,MAAM,KAAK,MAAM;EAC5B,KAAK,QAAQ;EACb,KAAK,QAAQ,MAAM;GAAE,GAAI,QAAQ;GAAgC,GAAG,QAAQ;GAAK,GAAG,QAAQ;EAC5F,OAAO,QAAQ,UAAU,SAAS;EAClC,QAAQ;EACT,CAAC;CAEF,IAAI,iBAAiB;CACrB,IAAI,iBAAiB;AAErB,KAAI,QAAQ,WAAW,QAAQ,SAAS;AACtC,OAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,qBAAkB,MAAM,SAAS,QAAQ;AACzC,WAAQ,QAAS,UAAU,MAAM;IACjC;AACF,OAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,qBAAkB,MAAM,SAAS,QAAQ;AACzC,WAAQ,QAAS,UAAU,MAAM;IACjC;;AAGJ,OAAM;AAEN,KAAI,CAAC,QAAQ,SAAS;EACpB,MAAM,WAAW,KAAK,YAAY;AAClC,MAAI,aAAa,EACf,OAAM,IAAI,MAAM,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,yBAAyB,WAAW;AAE/E;;AAGF,KAAI,QAAQ,QACV,QAAO;EACL,QAAQ;EACR,QAAQ;EACR,UAAU,KAAK,YAAY;EAC5B;AAQH,QAAO;EAJL,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;EACxD,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;EACxD,UAAU,KAAK,YAAY;EAEhB"}
|