UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

255 lines (253 loc) • 9.81 kB
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_theme = require('../utils/theme.cjs'); const require_shared = require('./shared.cjs'); const require_auth_session = require('../auth-session.cjs'); const require_auth_login = require('../auth-login.cjs'); const require_near_cli = require('../near-cli.cjs'); let node_path = require("node:path"); let effect = require("effect"); let node_process = require("node:process"); node_process = require_runtime.__toESM(node_process, 1); let near_kit = require("near-kit"); //#region src/commands/keys.ts const PUBLISH_FUNCTION_NAMES = ["__fastdata_kv"]; function registerKeys(builder) { return { keyPublish: builder.keyPublish.handler(async ({ input, context }) => { const session = effect.Context.get(context["effect/context"], require_shared.BosDepsTag).session; if (!session?.config) return { status: "error", account: "", network: "mainnet", env: input.env, contract: "", allowance: input.allowance, functionNames: PUBLISH_FUNCTION_NAMES, error: require_config.MISSING_CONFIG_MESSAGE }; const account = input.env === "staging" ? session.config.staging?.account ?? session.config.account : session.config.account; const network = require_network.getNetworkIdForAccount(account); const contract = require_fastkv.getRegistryNamespaceForAccount(account, input.registry); try { await effect.Effect.runPromise(require_near_cli.ensureNearCli); const oldKeys = await require_near_cli.listPublishKeys({ account, contract, network }); const keyPair = await require_near_cli.addFunctionCallAccessKey({ account, contract, allowance: input.allowance, functionNames: PUBLISH_FUNCTION_NAMES, network }); if (oldKeys.length > 0) { console.log(); console.log(` Found ${oldKeys.length} existing publish key${oldKeys.length > 1 ? "s" : ""}:`); for (const k of oldKeys) console.log(` ${require_theme.colors.dim(k)}`); if (input.removeOldKeys !== false) try { await require_near_cli.deleteAccessKeys(account, oldKeys, network); console.log(` ${require_theme.colors.green("✓")} Removed ${oldKeys.length} old key${oldKeys.length > 1 ? "s" : ""}`); } catch { console.log(` ${require_theme.colors.yellow("⚠")} Failed to remove old key${oldKeys.length > 1 ? "s" : ""} (new key still active)`); } else console.log(` ${require_theme.colors.dim("Old key(s) retained.")}`); } return { status: "published", account, network, env: input.env, contract, allowance: input.allowance, functionNames: PUBLISH_FUNCTION_NAMES, publicKey: keyPair.publicKey, privateKey: keyPair.privateKey }; } catch (error) { return { status: "error", account, network, env: input.env, contract, allowance: input.allowance, functionNames: PUBLISH_FUNCTION_NAMES, error: error instanceof Error ? error.message : "Unknown error" }; } }), login: builder.login.handler(async ({ input, context }) => { const deps = effect.Context.get(context["effect/context"], require_shared.BosDepsTag); const staging = input.env === "staging"; const account = staging ? deps.session?.config?.staging?.account ?? deps.session?.config?.account ?? "" : deps.session?.config?.account ?? ""; try { const siteUrl = resolveLoginSiteUrl(input.site, deps.session, staging); const login = await require_auth_login.startDeviceLogin({ siteUrl, device: input.device, account: account || void 0, expiresIn: input.expiresIn }); console.log(); console.log(` One-time code: ${require_theme.colors.cyan(login.userCode)}`); await require_auth_login.openInBrowser(login.verificationUrl).catch((error) => { console.log(require_theme.colors.yellow(` ⚠ ${error.message}`)); }); console.log(); console.log(` Waiting for approval at ${require_theme.colors.dim(login.verificationUrl)}…`); const approval = await login.waitForApproval(); if (!approval.apiKey) return { status: "error", siteUrl, loginUrl: login.verificationUrl, error: "Login approved but no CLI credential was created" }; const expiresAt = new Date(Date.now() + input.expiresIn * 1e3).toISOString(); require_auth_session.writeSessionHandle(deps.session?.root ?? node_process.default.cwd(), { version: 1, credential: { kind: "session", apiKey: approval.apiKey.key, apiKeyId: approval.apiKey.id, accountId: approval.accountId, label: input.device ?? siteUrl, siteUrl, createdAt: (/* @__PURE__ */ new Date()).toISOString(), expiresAt }, publishKey: null, delegateKey: null }); let warning = null; if (account && approval.accountId && approval.accountId !== account) warning = `Logged in as ${approval.accountId}, but the authored config account is ${account}. Publishes will use the configured account.`; let publishKey = null; if (input.key) try { publishKey = await exportPublishKey(account, input.registry); } catch (error) { warning = `Session stored, but publish-key export failed: ${error instanceof Error ? error.message : "unknown error"}`; } return { status: "logged-in", siteUrl, accountId: approval.accountId, expiresAt, loginUrl: login.verificationUrl, publishKey, warning }; } catch (error) { return { status: "error", siteUrl: input.site ?? "", error: error instanceof Error ? error.message : "Unknown error" }; } }), logout: builder.logout.handler(async ({ input, context }) => { const deps = effect.Context.get(context["effect/context"], require_shared.BosDepsTag); const configDir = input.configDir ?? deps.session?.root ?? node_process.default.cwd(); try { const session = require_auth_session.readSessionHandle(configDir); let revokedApiKey = false; let removedPublishKey = false; let warning = null; if (session?.credential) { revokedApiKey = await revokeApiKey(session.credential).catch(() => false); if (!revokedApiKey) warning = "Could not revoke the API key remotely — revoke it manually under Settings → API keys."; } if (session?.publishKey) { const account = session.credential?.accountId ?? deps.session?.config?.account ?? ""; require_auth_session.removePublishedKeyFile(session.publishKey.network, account, session.publishKey.publicKey); removedPublishKey = true; warning = warning ? `${warning} Re-run ${require_theme.colors.cyan("bos login --key")} to re-export a publish key.` : "Removed the exported publish key. Re-run bos login --key to re-export one."; } require_auth_session.deleteSessionHandle(configDir); return { status: "logged-out", revokedApiKey, removedPublishKey, warning }; } catch (error) { return { status: "error", revokedApiKey: false, removedPublishKey: false, error: error instanceof Error ? error.message : "Unknown error" }; } }) }; } function resolveLoginSiteUrl(siteInput, session, staging) { if (siteInput) return siteInput.replace(/\/+$/, ""); if (staging) { const stagingDomain = session?.config?.staging?.domain ?? session?.config?.domain; return stagingDomain ? `https://${stagingDomain}` : session?.runtime?.ui?.url ?? ""; } const devUiUrl = session?.runtime?.ui?.url; if (devUiUrl && /^https?:\/\/(localhost|127\.0\.0\.1)/.test(devUiUrl)) return devUiUrl.replace(/\/+$/, ""); const domain = session?.config?.domain; return domain ? `https://${domain}` : ""; } async function exportPublishKey(account, registry) { if (!account) throw new Error("the authored config has no account to export a publish key for"); await effect.Effect.runPromise(require_near_cli.ensureNearCli); const network = require_network.getNetworkIdForAccount(account); const contract = require_fastkv.getRegistryNamespaceForAccount(account, registry); await require_near_cli.listPublishKeys({ account, contract, network }); const keyPair = require_near_cli.generateNearKeyPair(); await require_near_cli.addFunctionCallAccessKey({ account, contract, allowance: "1NEAR", functionNames: PUBLISH_FUNCTION_NAMES, network, keyPair }); const { FileKeyStore } = await import("near-kit/keys/file"); await new FileKeyStore("~/.near-credentials", network).add(account, parseNearPrivateKey(keyPair.privateKey)); try { const { statSync, chmodSync } = await import("node:fs"); const { homedir } = await import("node:os"); const credentialPath = (0, node_path.join)(homedir(), ".near-credentials", network === "mainnet" ? "mainnet" : network, `${account}.json`); if (statSync(credentialPath).mode & 63) chmodSync(credentialPath, 384); } catch {} return { publicKey: keyPair.publicKey, network, contract, exportedTo: require_auth_session.nearCredentialsPath(network, account) }; } function parseNearPrivateKey(privateKey) { return (0, near_kit.parseKey)(privateKey); } async function revokeApiKey(credential) { if (!credential.apiKey || !credential.siteUrl) return false; try { return (await fetch(`${credential.siteUrl}/api/auth/api-key/delete`, { method: "POST", headers: { "x-api-key": credential.apiKey, "content-type": "application/json" }, body: JSON.stringify({ keyId: credential.apiKeyId }), signal: AbortSignal.timeout(1e4) })).ok; } catch { return false; } } //#endregion exports.registerKeys = registerKeys; //# sourceMappingURL=keys.cjs.map