everything-dev 1.30.0 → 1.31.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.
Files changed (77) hide show
  1. package/dist/cli/init.cjs +1 -0
  2. package/dist/cli/init.cjs.map +1 -1
  3. package/dist/cli/init.d.cts +1 -1
  4. package/dist/cli/init.d.cts.map +1 -1
  5. package/dist/cli/init.d.mts +1 -1
  6. package/dist/cli/init.d.mts.map +1 -1
  7. package/dist/cli/init.mjs +1 -0
  8. package/dist/cli/init.mjs.map +1 -1
  9. package/dist/cli/sync.cjs +3 -1
  10. package/dist/cli/sync.cjs.map +1 -1
  11. package/dist/cli/sync.mjs +3 -1
  12. package/dist/cli/sync.mjs.map +1 -1
  13. package/dist/cli/upgrade.cjs +1 -1
  14. package/dist/cli/upgrade.cjs.map +1 -1
  15. package/dist/cli/upgrade.mjs +1 -1
  16. package/dist/cli/upgrade.mjs.map +1 -1
  17. package/dist/cli.cjs +32 -1
  18. package/dist/cli.cjs.map +1 -1
  19. package/dist/cli.mjs +32 -1
  20. package/dist/cli.mjs.map +1 -1
  21. package/dist/contract.cjs +32 -1
  22. package/dist/contract.cjs.map +1 -1
  23. package/dist/contract.d.cts +80 -1
  24. package/dist/contract.d.cts.map +1 -1
  25. package/dist/contract.d.mts +80 -1
  26. package/dist/contract.d.mts.map +1 -1
  27. package/dist/contract.meta.cjs +18 -1
  28. package/dist/contract.meta.cjs.map +1 -1
  29. package/dist/contract.meta.d.cts +33 -0
  30. package/dist/contract.meta.d.mts +33 -0
  31. package/dist/contract.meta.mjs +18 -1
  32. package/dist/contract.meta.mjs.map +1 -1
  33. package/dist/contract.mjs +31 -2
  34. package/dist/contract.mjs.map +1 -1
  35. package/dist/index.cjs +4 -0
  36. package/dist/index.d.cts +3 -3
  37. package/dist/index.d.mts +3 -3
  38. package/dist/index.mjs +3 -3
  39. package/dist/merge.cjs +1 -0
  40. package/dist/merge.cjs.map +1 -1
  41. package/dist/merge.d.cts +1 -1
  42. package/dist/merge.d.cts.map +1 -1
  43. package/dist/merge.d.mts +1 -1
  44. package/dist/merge.d.mts.map +1 -1
  45. package/dist/merge.mjs +1 -0
  46. package/dist/merge.mjs.map +1 -1
  47. package/dist/mf.cjs +1 -0
  48. package/dist/mf.cjs.map +1 -1
  49. package/dist/mf.d.cts.map +1 -1
  50. package/dist/mf.d.mts.map +1 -1
  51. package/dist/mf.mjs +1 -0
  52. package/dist/mf.mjs.map +1 -1
  53. package/dist/near-cli.cjs +20 -4
  54. package/dist/near-cli.cjs.map +1 -1
  55. package/dist/near-cli.mjs +20 -4
  56. package/dist/near-cli.mjs.map +1 -1
  57. package/dist/plugin.cjs +243 -76
  58. package/dist/plugin.cjs.map +1 -1
  59. package/dist/plugin.d.cts +43 -0
  60. package/dist/plugin.d.cts.map +1 -1
  61. package/dist/plugin.d.mts +43 -0
  62. package/dist/plugin.d.mts.map +1 -1
  63. package/dist/plugin.mjs +243 -76
  64. package/dist/plugin.mjs.map +1 -1
  65. package/dist/types.cjs +7 -1
  66. package/dist/types.cjs.map +1 -1
  67. package/dist/types.d.cts +17 -1
  68. package/dist/types.d.cts.map +1 -1
  69. package/dist/types.d.mts +17 -1
  70. package/dist/types.d.mts.map +1 -1
  71. package/dist/types.mjs +6 -2
  72. package/dist/types.mjs.map +1 -1
  73. package/dist/ui/types.d.cts +2 -0
  74. package/dist/ui/types.d.cts.map +1 -1
  75. package/dist/ui/types.d.mts +2 -0
  76. package/dist/ui/types.d.mts.map +1 -1
  77. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"near-cli.cjs","names":["Effect"],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: boolean;\n txHash?: string;\n error?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearCliInstallError extends Error {\n readonly _tag = \"NearCliInstallError\";\n constructor(message: string) {\n super(`Failed to install NEAR CLI: ${message}`);\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nconst installNearCli = Effect.tryPromise({\n try: async () => {\n await execa(\"sh\", [\"-c\", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {\n stdio: \"inherit\",\n });\n },\n catch: (error) => {\n if (error instanceof Error && \"exitCode\" in error) {\n return new NearCliInstallError(\n `Installer exited with code ${(error as { exitCode: number }).exitCode}`,\n );\n }\n return new NearCliInstallError(error instanceof Error ? error.message : String(error));\n },\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n await execa(\"near\", args, { stdio: \"inherit\" });\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n if (process.env.BOS_INSTALL_NEAR_CLI === \"true\") {\n yield* installNearCli;\n return;\n }\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (config.privateKey) {\n args.push(\"sign-with-plaintext-private-key\", config.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const result = await execa(\"near\", args, {\n stdin: \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n });\n\n process.stdout.write(result.stdout);\n const combined = `${result.stdout}\\n${result.stderr}`;\n const txHashMatch = combined.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess =\n Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);\n }\n return combined;\n }\n\n throw new NearTransactionError(\n result.stderr || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n const txHashMatch = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n\n return {\n success: true,\n txHash: txHashMatch?.[1],\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"near-cli.cjs","names":["Effect","colors"],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: boolean;\n txHash?: string;\n error?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearCliInstallError extends Error {\n readonly _tag = \"NearCliInstallError\";\n constructor(message: string) {\n super(`Failed to install NEAR CLI: ${message}`);\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nconst installNearCli = Effect.tryPromise({\n try: async () => {\n await execa(\"sh\", [\"-c\", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {\n stdin: \"ignore\",\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n },\n catch: (error) => {\n if (error instanceof Error && \"exitCode\" in error) {\n return new NearCliInstallError(\n `Installer exited with code ${(error as { exitCode: number }).exitCode}`,\n );\n }\n return new NearCliInstallError(error instanceof Error ? error.message : String(error));\n },\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n await execa(\"near\", args, { stdin: \"pipe\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n if (process.env.BOS_INSTALL_NEAR_CLI === \"true\") {\n yield* installNearCli;\n return;\n }\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (config.privateKey) {\n args.push(\"sign-with-plaintext-private-key\", config.privateKey, \"send\");\n } else {\n if (!process.stdin.isTTY) {\n return {\n success: false,\n error:\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n };\n }\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const result = await execa(\"near\", args, {\n stdin: config.privateKey ? \"pipe\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n });\n\n process.stdout.write(result.stdout);\n const combined = `${result.stdout}\\n${result.stderr}`;\n const txHashMatch = combined.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess =\n Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);\n }\n return combined;\n }\n\n throw new NearTransactionError(\n result.stderr || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n const txHashMatch = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n\n return {\n success: true,\n txHash: txHashMatch?.[1],\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
package/dist/near-cli.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { colors } from "./utils/theme.mjs";
1
2
  import { generateKeyPairSync } from "node:crypto";
2
3
  import { Effect } from "effect";
3
4
  import { execa } from "execa";
@@ -73,7 +74,11 @@ const checkNearCliInstalled = Effect.tryPromise({
73
74
  });
74
75
  const installNearCli = Effect.tryPromise({
75
76
  try: async () => {
76
- await execa("sh", ["-c", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], { stdio: "inherit" });
77
+ await execa("sh", ["-c", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {
78
+ stdin: "ignore",
79
+ stdout: "inherit",
80
+ stderr: "inherit"
81
+ });
77
82
  },
78
83
  catch: (error) => {
79
84
  if (error instanceof Error && "exitCode" in error) return new NearCliInstallError(`Installer exited with code ${error.exitCode}`);
@@ -81,7 +86,11 @@ const installNearCli = Effect.tryPromise({
81
86
  }
82
87
  });
83
88
  async function runNearCommand(args) {
84
- await execa("near", args, { stdio: "inherit" });
89
+ await execa("near", args, {
90
+ stdin: "pipe",
91
+ stdout: "inherit",
92
+ stderr: "inherit"
93
+ });
85
94
  }
86
95
  const ensureNearCli = Effect.gen(function* () {
87
96
  if (yield* checkNearCliInstalled) return;
@@ -118,13 +127,20 @@ const executeTransaction = (config) => Effect.gen(function* () {
118
127
  network
119
128
  ];
120
129
  if (config.privateKey) args.push("sign-with-plaintext-private-key", config.privateKey, "send");
121
- else args.push("sign-with-keychain", "send");
130
+ else {
131
+ if (!process.stdin.isTTY) return {
132
+ success: false,
133
+ error: "No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally."
134
+ };
135
+ console.log(colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
136
+ args.push("sign-with-keychain", "send");
137
+ }
122
138
  return {
123
139
  success: true,
124
140
  txHash: (yield* Effect.tryPromise({
125
141
  try: async () => {
126
142
  const result = await execa("near", args, {
127
- stdin: "inherit",
143
+ stdin: config.privateKey ? "pipe" : "inherit",
128
144
  stdout: "pipe",
129
145
  stderr: "pipe",
130
146
  reject: false
@@ -1 +1 @@
1
- {"version":3,"file":"near-cli.mjs","names":[],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: boolean;\n txHash?: string;\n error?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearCliInstallError extends Error {\n readonly _tag = \"NearCliInstallError\";\n constructor(message: string) {\n super(`Failed to install NEAR CLI: ${message}`);\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nconst installNearCli = Effect.tryPromise({\n try: async () => {\n await execa(\"sh\", [\"-c\", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {\n stdio: \"inherit\",\n });\n },\n catch: (error) => {\n if (error instanceof Error && \"exitCode\" in error) {\n return new NearCliInstallError(\n `Installer exited with code ${(error as { exitCode: number }).exitCode}`,\n );\n }\n return new NearCliInstallError(error instanceof Error ? error.message : String(error));\n },\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n await execa(\"near\", args, { stdio: \"inherit\" });\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n if (process.env.BOS_INSTALL_NEAR_CLI === \"true\") {\n yield* installNearCli;\n return;\n }\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (config.privateKey) {\n args.push(\"sign-with-plaintext-private-key\", config.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const result = await execa(\"near\", args, {\n stdin: \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n });\n\n process.stdout.write(result.stdout);\n const combined = `${result.stdout}\\n${result.stderr}`;\n const txHashMatch = combined.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess =\n Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);\n }\n return combined;\n }\n\n throw new NearTransactionError(\n result.stderr || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n const txHashMatch = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n\n return {\n success: true,\n txHash: txHashMatch?.[1],\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"near-cli.mjs","names":[],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: boolean;\n txHash?: string;\n error?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearCliInstallError extends Error {\n readonly _tag = \"NearCliInstallError\";\n constructor(message: string) {\n super(`Failed to install NEAR CLI: ${message}`);\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nconst installNearCli = Effect.tryPromise({\n try: async () => {\n await execa(\"sh\", [\"-c\", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {\n stdin: \"ignore\",\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n },\n catch: (error) => {\n if (error instanceof Error && \"exitCode\" in error) {\n return new NearCliInstallError(\n `Installer exited with code ${(error as { exitCode: number }).exitCode}`,\n );\n }\n return new NearCliInstallError(error instanceof Error ? error.message : String(error));\n },\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n await execa(\"near\", args, { stdin: \"pipe\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n if (process.env.BOS_INSTALL_NEAR_CLI === \"true\") {\n yield* installNearCli;\n return;\n }\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (config.privateKey) {\n args.push(\"sign-with-plaintext-private-key\", config.privateKey, \"send\");\n } else {\n if (!process.stdin.isTTY) {\n return {\n success: false,\n error:\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n };\n }\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const result = await execa(\"near\", args, {\n stdin: config.privateKey ? \"pipe\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n });\n\n process.stdout.write(result.stdout);\n const combined = `${result.stdout}\\n${result.stderr}`;\n const txHashMatch = combined.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess =\n Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);\n }\n return combined;\n }\n\n throw new NearTransactionError(\n result.stderr || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n const txHashMatch = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n\n return {\n success: true,\n txHash: txHashMatch?.[1],\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
package/dist/plugin.cjs CHANGED
@@ -15,6 +15,7 @@ const require_status = require('./cli/status.cjs');
15
15
  const require_sync = require('./cli/sync.cjs');
16
16
  const require_shared = require('./shared.cjs');
17
17
  const require_upgrade = require('./cli/upgrade.cjs');
18
+ const require_theme = require('./utils/theme.cjs');
18
19
  const require_near_cli = require('./near-cli.cjs');
19
20
  const require_service_descriptor = require('./service-descriptor.cjs');
20
21
  const require_run = require('./utils/run.cjs');
@@ -252,8 +253,9 @@ async function buildEverythingDevQuietly(cwd) {
252
253
  async function fetchPublishedConfig(accountId, gatewayId) {
253
254
  try {
254
255
  return await require_fastkv.fetchBosConfigFromFastKv(`bos://${accountId}/${gatewayId}`);
255
- } catch {
256
- return null;
256
+ } catch (error) {
257
+ if (error instanceof Error && error.message.startsWith("No config found")) return null;
258
+ throw error;
257
259
  }
258
260
  }
259
261
  function selectWorkspaceTargets(packages, bosConfig) {
@@ -614,20 +616,31 @@ var plugin_default = (0, every_plugin.createPlugin)({
614
616
  phase: "config",
615
617
  status: "running"
616
618
  });
619
+ const bosEnv = input.env ?? (node_process.default.env.BOS_ENV === "staging" ? "staging" : "production");
617
620
  const account = input.account ?? node_process.default.env.BOS_ACCOUNT;
618
621
  const domain = input.domain ?? node_process.default.env.BOS_GATEWAY;
619
622
  let config = null;
620
623
  let remoteConfig = null;
621
- if (account && domain) {
624
+ if (account && domain) try {
622
625
  remoteConfig = await fetchPublishedConfig(account, domain);
623
626
  if (remoteConfig) config = remoteConfig;
624
- else console.warn(`[Start] Failed to fetch remote config for ${account}/${domain}, falling back to local bos.config.json`);
627
+ else return {
628
+ status: "error",
629
+ url: "",
630
+ error: `No config found at bos://${account}/${domain}. Verify the account and gateway are correct and the config has been published.\nExpected URL: ${require_fastkv.buildRegistryConfigUrl(account, domain)}`
631
+ };
632
+ } catch (error) {
633
+ return {
634
+ status: "error",
635
+ url: "",
636
+ error: `Failed to fetch config for bos://${account}/${domain}: ${error instanceof Error ? error.message : "Unknown error"}\nExpected URL: ${require_fastkv.buildRegistryConfigUrl(account, domain)}`
637
+ };
625
638
  }
626
- if (!config) config = deps.bosConfig;
639
+ else config = deps.bosConfig;
627
640
  if (!config) return {
628
641
  status: "error",
629
642
  url: "",
630
- error: "No configuration found. Set BOS_ACCOUNT and BOS_GATEWAY environment variables, or provide a local bos.config.json."
643
+ error: "No configuration found. Provide --account and --gateway flags, or create a local bos.config.json."
631
644
  };
632
645
  if (account) config = {
633
646
  ...config,
@@ -638,7 +651,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
638
651
  domain
639
652
  };
640
653
  const port = input.port ?? require_config.getHostDevelopmentPort(config.app.host.development);
641
- const isStaging = input.env === "staging";
654
+ const isStaging = bosEnv === "staging";
642
655
  const runtimePlugins = await require_config.buildRuntimePluginsForConfig(config, deps.configDir, "production");
643
656
  require_config.suppressWarnings();
644
657
  const runtimeConfig = require_app.buildRuntimeConfig(config, {
@@ -651,6 +664,8 @@ var plugin_default = (0, every_plugin.createPlugin)({
651
664
  });
652
665
  require_config.drainConfigWarnings();
653
666
  require_config.resumeWarnings();
667
+ if (isStaging && config.staging?.domain) runtimeConfig.domain = config.staging.domain;
668
+ if (isStaging) runtimeConfig.env = "staging";
654
669
  require_infra.syncGeneratedInfra(deps.configDir, runtimeConfig);
655
670
  if (!(0, node_fs.existsSync)((0, node_path.join)(deps.configDir, ".env"))) {
656
671
  require_infra.ensureEnvFile(deps.configDir);
@@ -671,12 +686,13 @@ var plugin_default = (0, every_plugin.createPlugin)({
671
686
  const productionEnv = {};
672
687
  const warnings = [];
673
688
  if (!node_process.default.env.CORS_ORIGIN && config.domain) {
674
- const defaultOrigin = `https://${config.domain}`;
689
+ const defaultOrigin = `https://${isStaging ? config.staging?.domain ?? config.domain : config.domain}`;
675
690
  productionEnv.CORS_ORIGIN = defaultOrigin;
676
691
  warnings.push(`CORS_ORIGIN defaulting to ${defaultOrigin}`);
677
692
  }
678
693
  const requiredSecrets = /* @__PURE__ */ new Set();
679
694
  const missingSecrets = [];
695
+ if (runtimeConfig.host.secrets) for (const s of runtimeConfig.host.secrets) requiredSecrets.add(s);
680
696
  if (runtimeConfig.auth?.secrets) for (const s of runtimeConfig.auth.secrets) requiredSecrets.add(s);
681
697
  if (runtimeConfig.api?.secrets) for (const s of runtimeConfig.api.secrets) requiredSecrets.add(s);
682
698
  for (const plugin of Object.values(runtimeConfig.plugins ?? {})) if (plugin.secrets) for (const s of plugin.secrets) requiredSecrets.add(s);
@@ -779,89 +795,134 @@ var plugin_default = (0, every_plugin.createPlugin)({
779
795
  registryUrl: "",
780
796
  error: "No bos.config.json found"
781
797
  };
782
- const account = deps.bosConfig.account;
783
- const gateway = deps.bosConfig.domain;
784
- if (!gateway) return {
798
+ const result = await publishToFastKv({
799
+ bosConfig: deps.bosConfig,
800
+ runtimeConfig: deps.runtimeConfig,
801
+ configDir: deps.configDir,
802
+ env: input.env,
803
+ build: input.deploy,
804
+ dryRun: input.dryRun,
805
+ packages: input.packages,
806
+ network: input.network,
807
+ privateKey: input.privateKey
808
+ });
809
+ if (result.publishConfig) {
810
+ const refreshed = await require_config.loadResolvedConfig({ cwd: deps.configDir });
811
+ if (refreshed?.config) {
812
+ deps.bosConfig = refreshed.config;
813
+ deps.runtimeConfig = refreshed.runtime;
814
+ }
815
+ }
816
+ return {
817
+ status: result.status,
818
+ registryUrl: result.registryUrl,
819
+ txHash: result.txHash,
820
+ error: result.error,
821
+ built: result.built,
822
+ skipped: result.skipped
823
+ };
824
+ }),
825
+ deploy: builder.deploy.handler(async ({ input }) => {
826
+ if (!deps.bosConfig) return {
785
827
  status: "error",
786
828
  registryUrl: "",
787
- error: "bos.config.json must define domain to publish"
829
+ redeployed: false,
830
+ error: "No bos.config.json found"
788
831
  };
789
- const network = input.network ?? require_network.getNetworkIdForAccount(account);
790
- const bosUrl = `bos://${account}/${gateway}`;
791
- const registryUrl = require_fastkv.buildRegistryConfigUrlForNetwork(network, account, gateway);
792
- const targets = selectWorkspaceTargets(input.packages, deps.bosConfig);
793
- let publishConfig = deps.bosConfig;
794
- let built;
795
- let skipped;
796
- if (input.dryRun) return {
832
+ const result = await publishToFastKv({
833
+ bosConfig: deps.bosConfig,
834
+ runtimeConfig: deps.runtimeConfig,
835
+ configDir: deps.configDir,
836
+ env: input.env,
837
+ build: input.build,
838
+ dryRun: input.dryRun,
839
+ packages: input.packages,
840
+ network: input.network,
841
+ privateKey: input.privateKey
842
+ });
843
+ if (result.status === "error") return {
844
+ status: "error",
845
+ registryUrl: result.registryUrl,
846
+ txHash: result.txHash,
847
+ built: result.built,
848
+ skipped: result.skipped,
849
+ redeployed: false,
850
+ error: result.error
851
+ };
852
+ if (result.status === "dry-run") return {
797
853
  status: "dry-run",
798
- registryUrl,
799
- built,
800
- skipped
854
+ registryUrl: result.registryUrl,
855
+ built: result.built,
856
+ skipped: result.skipped,
857
+ redeployed: false
801
858
  };
802
- if (input.deploy) {
803
- await generateCodeArtifacts(deps.configDir, deps.bosConfig, {
804
- env: "production",
805
- runtimeConfig: deps.runtimeConfig ?? void 0
806
- });
807
- const result = await buildWorkspaceTargets({
808
- configDir: deps.configDir,
809
- bosConfig: deps.bosConfig,
810
- runtimeConfig: deps.runtimeConfig,
811
- targets,
812
- deploy: true
813
- });
814
- built = result.built;
815
- skipped = result.skipped;
859
+ if (result.publishConfig) {
816
860
  const refreshed = await require_config.loadResolvedConfig({ cwd: deps.configDir });
817
861
  if (refreshed?.config) {
818
862
  deps.bosConfig = refreshed.config;
819
863
  deps.runtimeConfig = refreshed.runtime;
820
- publishConfig = refreshed.config;
821
864
  }
822
865
  }
823
- const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishConfig) };
824
- const payload = JSON.stringify(registryEntries);
825
- const argsBase64 = Buffer.from(payload).toString("base64");
826
- const privateKey = input.privateKey || node_process.default.env.NEAR_PRIVATE_KEY || node_process.default.env.BOS_NEAR_PRIVATE_KEY;
827
- try {
828
- await effect.Effect.runPromise(require_near_cli.ensureNearCli);
829
- let txHash;
866
+ let redeployed = false;
867
+ let service;
868
+ if (node_process.default.env.RAILWAY_TOKEN) {
869
+ const railwayService = input.service ?? deps.bosConfig.ci?.railway?.service;
870
+ if (!railwayService) {
871
+ console.log();
872
+ console.log(require_theme.colors.yellow(" Railway redeploy skipped: ci.railway.service is not configured in bos.config.json"));
873
+ return {
874
+ status: "published",
875
+ registryUrl: result.registryUrl,
876
+ txHash: result.txHash,
877
+ built: result.built,
878
+ skipped: result.skipped,
879
+ redeployed: false,
880
+ error: "Config published but Railway redeploy failed: ci.railway.service is not configured in bos.config.json"
881
+ };
882
+ }
883
+ service = railwayService;
884
+ console.log();
885
+ console.log(` Redeploying Railway service ${require_theme.colors.cyan(railwayService)}...`);
830
886
  try {
831
- txHash = (await effect.Effect.runPromise(require_near_cli.executeTransaction({
832
- account,
833
- contract: require_fastkv.getRegistryNamespaceForNetwork(network),
834
- method: "__fastdata_kv",
835
- argsBase64,
836
- network,
837
- privateKey,
838
- gas: "300Tgas",
839
- deposit: "0NEAR"
840
- }))).txHash;
887
+ const railResult = await require_run.run("railway", [
888
+ "redeploy",
889
+ "--service",
890
+ railwayService,
891
+ "--yes"
892
+ ], { capture: true });
893
+ if (railResult?.stdout) {
894
+ for (const line of railResult.stdout.split("\n")) if (line.trim()) console.log(` ${require_theme.colors.dim(line.trim())}`);
895
+ }
896
+ redeployed = true;
897
+ console.log(require_theme.colors.green(` Railway redeploy complete`));
841
898
  } catch (error) {
842
- txHash = extractTransactionHash(error);
843
- if (!txHash) throw error;
844
- try {
845
- const verifiedConfig = await require_fastkv.fetchBosConfigFromFastKv(bosUrl);
846
- if (JSON.stringify(verifiedConfig) !== JSON.stringify(publishConfig)) throw error;
847
- } catch {}
899
+ const message = error instanceof Error ? error.message : String(error);
900
+ const railError = message.includes("not found") || message.includes("ENOENT") ? "Railway CLI not found. Install it: npm i -g @railway/cli" : `Railway redeploy failed: ${message}`;
901
+ console.log(require_theme.colors.yellow(` ${railError}`));
902
+ return {
903
+ status: "published",
904
+ registryUrl: result.registryUrl,
905
+ txHash: result.txHash,
906
+ built: result.built,
907
+ skipped: result.skipped,
908
+ redeployed: false,
909
+ service,
910
+ error: `Config published but ${railError}`
911
+ };
848
912
  }
849
- return {
850
- status: "published",
851
- registryUrl,
852
- txHash,
853
- built,
854
- skipped
855
- };
856
- } catch (error) {
857
- return {
858
- status: "error",
859
- registryUrl,
860
- error: error instanceof Error ? error.message : "Unknown error",
861
- built,
862
- skipped
863
- };
913
+ } else {
914
+ console.log();
915
+ console.log(require_theme.colors.yellow(" Railway redeploy skipped (RAILWAY_TOKEN not set)"));
864
916
  }
917
+ return {
918
+ status: "deployed",
919
+ registryUrl: result.registryUrl,
920
+ txHash: result.txHash,
921
+ built: result.built,
922
+ skipped: result.skipped,
923
+ redeployed,
924
+ service
925
+ };
865
926
  }),
866
927
  keyPublish: builder.keyPublish.handler(async ({ input }) => {
867
928
  if (!deps.bosConfig) return {
@@ -1214,6 +1275,112 @@ var plugin_default = (0, every_plugin.createPlugin)({
1214
1275
  })
1215
1276
  })
1216
1277
  });
1278
+ async function publishToFastKv(input) {
1279
+ const { env, dryRun, configDir } = input;
1280
+ let bosConfig = input.bosConfig;
1281
+ const runtimeConfig = input.runtimeConfig;
1282
+ const isStaging = env === "staging";
1283
+ const account = bosConfig.account;
1284
+ const gateway = isStaging ? bosConfig.staging?.domain ?? bosConfig.domain : bosConfig.domain;
1285
+ if (!gateway) return {
1286
+ status: "error",
1287
+ registryUrl: "",
1288
+ error: "bos.config.json must define domain to publish"
1289
+ };
1290
+ const network = input.network ?? require_network.getNetworkIdForAccount(account);
1291
+ const registryUrl = require_fastkv.buildRegistryConfigUrlForNetwork(network, account, gateway);
1292
+ const targets = selectWorkspaceTargets(input.packages, bosConfig);
1293
+ let publishConfig = isStaging ? {
1294
+ ...bosConfig,
1295
+ domain: gateway
1296
+ } : bosConfig;
1297
+ let built;
1298
+ let skipped;
1299
+ if (dryRun) return {
1300
+ status: "dry-run",
1301
+ registryUrl,
1302
+ built,
1303
+ skipped
1304
+ };
1305
+ if (input.build) {
1306
+ await generateCodeArtifacts(configDir, bosConfig, {
1307
+ env: "production",
1308
+ runtimeConfig: runtimeConfig ?? void 0
1309
+ });
1310
+ const result = await buildWorkspaceTargets({
1311
+ configDir,
1312
+ bosConfig,
1313
+ runtimeConfig,
1314
+ targets,
1315
+ deploy: true
1316
+ });
1317
+ built = result.built;
1318
+ skipped = result.skipped;
1319
+ const refreshed = await require_config.loadResolvedConfig({ cwd: configDir });
1320
+ if (refreshed?.config) {
1321
+ bosConfig = refreshed.config;
1322
+ publishConfig = isStaging ? {
1323
+ ...refreshed.config,
1324
+ domain: gateway
1325
+ } : refreshed.config;
1326
+ }
1327
+ }
1328
+ const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishConfig) };
1329
+ const payload = JSON.stringify(registryEntries);
1330
+ const argsBase64 = Buffer.from(payload).toString("base64");
1331
+ const privateKey = input.privateKey || node_process.default.env.NEAR_PRIVATE_KEY || node_process.default.env.BOS_NEAR_PRIVATE_KEY;
1332
+ if (!privateKey) {
1333
+ if (!node_process.default.stdin.isTTY) return {
1334
+ status: "error",
1335
+ registryUrl,
1336
+ error: "No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally."
1337
+ };
1338
+ console.log(require_theme.colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
1339
+ }
1340
+ console.log();
1341
+ console.log(` Publishing to ${require_theme.colors.cyan(registryUrl)}...`);
1342
+ try {
1343
+ await effect.Effect.runPromise(require_near_cli.ensureNearCli);
1344
+ let txHash;
1345
+ console.log(` Submitting transaction on ${network}...`);
1346
+ try {
1347
+ txHash = (await effect.Effect.runPromise(require_near_cli.executeTransaction({
1348
+ account,
1349
+ contract: require_fastkv.getRegistryNamespaceForNetwork(network),
1350
+ method: "__fastdata_kv",
1351
+ argsBase64,
1352
+ network,
1353
+ privateKey,
1354
+ gas: "300Tgas",
1355
+ deposit: "0NEAR"
1356
+ }))).txHash;
1357
+ if (txHash) console.log(` Transaction submitted: ${require_theme.colors.dim(txHash)}`);
1358
+ } catch (error) {
1359
+ txHash = extractTransactionHash(error);
1360
+ if (!txHash) throw error;
1361
+ try {
1362
+ const verifiedConfig = await require_fastkv.fetchBosConfigFromFastKv(`bos://${account}/${gateway}`);
1363
+ if (JSON.stringify(verifiedConfig) !== JSON.stringify(publishConfig)) throw error;
1364
+ } catch {}
1365
+ }
1366
+ return {
1367
+ status: "published",
1368
+ registryUrl,
1369
+ txHash,
1370
+ built,
1371
+ skipped,
1372
+ publishConfig
1373
+ };
1374
+ } catch (error) {
1375
+ return {
1376
+ status: "error",
1377
+ registryUrl,
1378
+ error: error instanceof Error ? error.message : "Unknown error",
1379
+ built,
1380
+ skipped
1381
+ };
1382
+ }
1383
+ }
1217
1384
  function extractTransactionHash(error) {
1218
1385
  return (error instanceof Error ? error.message : String(error)).match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
1219
1386
  }