frontmcp 0.12.2 → 1.0.0-beta.10

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 (297) hide show
  1. package/README.md +3 -3
  2. package/package.json +8 -7
  3. package/src/commands/build/adapters/cloudflare.js +1 -1
  4. package/src/commands/build/adapters/cloudflare.js.map +1 -1
  5. package/src/commands/build/adapters/lambda.js +1 -1
  6. package/src/commands/build/adapters/lambda.js.map +1 -1
  7. package/src/commands/build/adapters/vercel.js +2 -2
  8. package/src/commands/build/adapters/vercel.js.map +1 -1
  9. package/src/commands/build/browser/index.d.ts +17 -0
  10. package/src/commands/build/browser/index.js +68 -0
  11. package/src/commands/build/browser/index.js.map +1 -0
  12. package/src/commands/build/bundler.js +1 -1
  13. package/src/commands/build/bundler.js.map +1 -1
  14. package/src/commands/build/exec/cli-runtime/cli-bundler.d.ts +17 -0
  15. package/src/commands/build/exec/cli-runtime/cli-bundler.js +75 -0
  16. package/src/commands/build/exec/cli-runtime/cli-bundler.js.map +1 -0
  17. package/src/commands/build/exec/cli-runtime/credential-store.d.ts +22 -0
  18. package/src/commands/build/exec/cli-runtime/credential-store.js +140 -0
  19. package/src/commands/build/exec/cli-runtime/credential-store.js.map +1 -0
  20. package/src/commands/build/exec/cli-runtime/daemon-client.d.ts +16 -0
  21. package/src/commands/build/exec/cli-runtime/daemon-client.js +170 -0
  22. package/src/commands/build/exec/cli-runtime/daemon-client.js.map +1 -0
  23. package/src/commands/build/exec/cli-runtime/generate-cli-entry.d.ts +37 -0
  24. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +1358 -0
  25. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -0
  26. package/src/commands/build/exec/cli-runtime/index.d.ts +9 -0
  27. package/src/commands/build/exec/cli-runtime/index.js +32 -0
  28. package/src/commands/build/exec/cli-runtime/index.js.map +1 -0
  29. package/src/commands/build/exec/cli-runtime/oauth-helper.d.ts +9 -0
  30. package/src/commands/build/exec/cli-runtime/oauth-helper.js +224 -0
  31. package/src/commands/build/exec/cli-runtime/oauth-helper.js.map +1 -0
  32. package/src/commands/build/exec/cli-runtime/output-formatter.d.ts +46 -0
  33. package/src/commands/build/exec/cli-runtime/output-formatter.js +168 -0
  34. package/src/commands/build/exec/cli-runtime/output-formatter.js.map +1 -0
  35. package/src/commands/build/exec/cli-runtime/schema-extractor.d.ts +57 -0
  36. package/src/commands/build/exec/cli-runtime/schema-extractor.js +129 -0
  37. package/src/commands/build/exec/cli-runtime/schema-extractor.js.map +1 -0
  38. package/src/commands/build/exec/cli-runtime/schema-to-commander.d.ts +38 -0
  39. package/src/commands/build/exec/cli-runtime/schema-to-commander.js +172 -0
  40. package/src/commands/build/exec/cli-runtime/schema-to-commander.js.map +1 -0
  41. package/src/commands/build/exec/cli-runtime/session-manager.d.ts +16 -0
  42. package/src/commands/build/exec/cli-runtime/session-manager.js +122 -0
  43. package/src/commands/build/exec/cli-runtime/session-manager.js.map +1 -0
  44. package/src/commands/build/exec/config.d.ts +28 -0
  45. package/src/commands/build/exec/config.js +1 -2
  46. package/src/commands/build/exec/config.js.map +1 -1
  47. package/src/commands/build/exec/esbuild-bundler.d.ts +4 -1
  48. package/src/commands/build/exec/esbuild-bundler.js +29 -10
  49. package/src/commands/build/exec/esbuild-bundler.js.map +1 -1
  50. package/src/commands/build/exec/index.d.ts +11 -3
  51. package/src/commands/build/exec/index.js +159 -9
  52. package/src/commands/build/exec/index.js.map +1 -1
  53. package/src/commands/build/exec/installer-script.js +1 -1
  54. package/src/commands/build/exec/installer-script.js.map +1 -1
  55. package/src/commands/build/exec/manifest.d.ts +14 -0
  56. package/src/commands/build/exec/manifest.js.map +1 -1
  57. package/src/commands/build/exec/runner-script.d.ts +1 -1
  58. package/src/commands/build/exec/runner-script.js +48 -5
  59. package/src/commands/build/exec/runner-script.js.map +1 -1
  60. package/src/commands/build/exec/sea-builder.d.ts +18 -0
  61. package/src/commands/build/exec/sea-builder.js +81 -0
  62. package/src/commands/build/exec/sea-builder.js.map +1 -0
  63. package/src/commands/build/exec/setup.js +0 -2
  64. package/src/commands/build/exec/setup.js.map +1 -1
  65. package/src/commands/build/index.d.ts +9 -14
  66. package/src/commands/build/index.js +51 -30
  67. package/src/commands/build/index.js.map +1 -1
  68. package/src/commands/build/register.d.ts +2 -0
  69. package/src/commands/build/register.js +20 -0
  70. package/src/commands/build/register.js.map +1 -0
  71. package/src/commands/build/sdk/index.d.ts +13 -0
  72. package/src/commands/build/sdk/index.js +76 -0
  73. package/src/commands/build/sdk/index.js.map +1 -0
  74. package/src/commands/{dev.d.ts → dev/dev.d.ts} +1 -1
  75. package/src/commands/dev/dev.js +119 -0
  76. package/src/commands/dev/dev.js.map +1 -0
  77. package/src/commands/{doctor.js → dev/doctor.js} +5 -4
  78. package/src/commands/dev/doctor.js.map +1 -0
  79. package/src/commands/{inspector.js → dev/inspector.js} +1 -1
  80. package/src/commands/dev/inspector.js.map +1 -0
  81. package/src/commands/dev/register.d.ts +2 -0
  82. package/src/commands/dev/register.js +49 -0
  83. package/src/commands/dev/register.js.map +1 -0
  84. package/src/commands/{test.d.ts → dev/test.d.ts} +1 -1
  85. package/src/commands/{test.js → dev/test.js} +5 -5
  86. package/src/commands/dev/test.js.map +1 -0
  87. package/src/commands/{configure.d.ts → package/configure.d.ts} +1 -1
  88. package/src/commands/{configure.js → package/configure.js} +3 -3
  89. package/src/commands/package/configure.js.map +1 -0
  90. package/src/commands/package/esm-update.d.ts +19 -0
  91. package/src/commands/package/esm-update.js +93 -0
  92. package/src/commands/package/esm-update.js.map +1 -0
  93. package/src/commands/{install/index.d.ts → package/install.d.ts} +1 -1
  94. package/src/commands/{install/index.js → package/install.js} +10 -7
  95. package/src/commands/package/install.js.map +1 -0
  96. package/src/commands/{install → package}/questionnaire.js +2 -2
  97. package/src/commands/{install → package}/questionnaire.js.map +1 -1
  98. package/src/commands/package/register.d.ts +2 -0
  99. package/src/commands/package/register.js +35 -0
  100. package/src/commands/package/register.js.map +1 -0
  101. package/src/commands/{install → package}/registry.js +8 -6
  102. package/src/commands/package/registry.js.map +1 -0
  103. package/src/commands/{install → package}/sources/git.js +8 -1
  104. package/src/commands/package/sources/git.js.map +1 -0
  105. package/src/commands/{install → package}/sources/local.js.map +1 -1
  106. package/src/commands/{install → package}/sources/npm.js.map +1 -1
  107. package/src/commands/{install → package}/types.d.ts +7 -1
  108. package/src/commands/{install → package}/types.js +4 -0
  109. package/src/commands/package/types.js.map +1 -0
  110. package/src/commands/{uninstall.d.ts → package/uninstall.d.ts} +1 -1
  111. package/src/commands/{uninstall.js → package/uninstall.js} +2 -2
  112. package/src/commands/package/uninstall.js.map +1 -0
  113. package/src/{pm/pm.format.d.ts → commands/pm/format.d.ts} +1 -1
  114. package/src/{pm/pm.format.js → commands/pm/format.js} +2 -2
  115. package/src/commands/pm/format.js.map +1 -0
  116. package/src/{pm/pm.health.js → commands/pm/health.js} +1 -1
  117. package/src/commands/pm/health.js.map +1 -0
  118. package/src/commands/pm/index.d.ts +9 -0
  119. package/src/{pm → commands/pm}/index.js +32 -32
  120. package/src/commands/pm/index.js.map +1 -0
  121. package/src/commands/{list.d.ts → pm/list.d.ts} +1 -1
  122. package/src/commands/{list.js → pm/list.js} +3 -3
  123. package/src/commands/pm/list.js.map +1 -0
  124. package/src/{pm/pm.logs.js → commands/pm/log-utils.js} +9 -9
  125. package/src/commands/pm/log-utils.js.map +1 -0
  126. package/src/commands/{logs.d.ts → pm/logs.d.ts} +1 -1
  127. package/src/commands/{logs.js → pm/logs.js} +6 -6
  128. package/src/commands/pm/logs.js.map +1 -0
  129. package/src/{pm/pm.manager.d.ts → commands/pm/manager.d.ts} +1 -1
  130. package/src/{pm/pm.manager.js → commands/pm/manager.js} +21 -21
  131. package/src/commands/pm/manager.js.map +1 -0
  132. package/src/{pm/pm.paths.d.ts → commands/pm/paths.d.ts} +1 -0
  133. package/src/{pm/pm.paths.js → commands/pm/paths.js} +2 -1
  134. package/src/commands/pm/paths.js.map +1 -0
  135. package/src/{pm/pm.pidfile.d.ts → commands/pm/pidfile.d.ts} +1 -1
  136. package/src/{pm/pm.pidfile.js → commands/pm/pidfile.js} +8 -8
  137. package/src/commands/pm/pidfile.js.map +1 -0
  138. package/src/commands/pm/register.d.ts +2 -0
  139. package/src/commands/pm/register.js +83 -0
  140. package/src/commands/pm/register.js.map +1 -0
  141. package/src/commands/{restart.d.ts → pm/restart.d.ts} +1 -1
  142. package/src/commands/{restart.js → pm/restart.js} +4 -4
  143. package/src/commands/pm/restart.js.map +1 -0
  144. package/src/{pm/pm.service.d.ts → commands/pm/service-gen.d.ts} +1 -1
  145. package/src/{pm/pm.service.js → commands/pm/service-gen.js} +5 -5
  146. package/src/commands/pm/service-gen.js.map +1 -0
  147. package/src/commands/{service.d.ts → pm/service.d.ts} +1 -1
  148. package/src/commands/{service.js → pm/service.js} +6 -6
  149. package/src/commands/pm/service.js.map +1 -0
  150. package/src/commands/{socket.d.ts → pm/socket.d.ts} +1 -1
  151. package/src/commands/{socket.js → pm/socket.js} +3 -3
  152. package/src/commands/pm/socket.js.map +1 -0
  153. package/src/{pm/pm.spawn.d.ts → commands/pm/spawn.d.ts} +1 -1
  154. package/src/{pm/pm.spawn.js → commands/pm/spawn.js} +15 -15
  155. package/src/commands/pm/spawn.js.map +1 -0
  156. package/src/commands/{start.d.ts → pm/start.d.ts} +1 -1
  157. package/src/commands/{start.js → pm/start.js} +6 -6
  158. package/src/commands/pm/start.js.map +1 -0
  159. package/src/commands/{status.d.ts → pm/status.d.ts} +1 -1
  160. package/src/commands/{status.js → pm/status.js} +5 -5
  161. package/src/commands/pm/status.js.map +1 -0
  162. package/src/commands/{stop.d.ts → pm/stop.d.ts} +1 -1
  163. package/src/commands/{stop.js → pm/stop.js} +3 -3
  164. package/src/commands/pm/stop.js.map +1 -0
  165. package/src/{pm/pm.types.js → commands/pm/types.js} +1 -1
  166. package/src/commands/pm/types.js.map +1 -0
  167. package/src/commands/{create.d.ts → scaffold/create.d.ts} +3 -0
  168. package/src/commands/{create.js → scaffold/create.js} +316 -186
  169. package/src/commands/scaffold/create.js.map +1 -0
  170. package/src/commands/scaffold/register.d.ts +2 -0
  171. package/src/commands/scaffold/register.js +30 -0
  172. package/src/commands/scaffold/register.js.map +1 -0
  173. package/src/commands/skills/catalog.d.ts +42 -0
  174. package/src/commands/skills/catalog.js +276 -0
  175. package/src/commands/skills/catalog.js.map +1 -0
  176. package/src/commands/skills/install.d.ts +8 -0
  177. package/src/commands/skills/install.js +83 -0
  178. package/src/commands/skills/install.js.map +1 -0
  179. package/src/commands/skills/list.d.ts +5 -0
  180. package/src/commands/skills/list.js +44 -0
  181. package/src/commands/skills/list.js.map +1 -0
  182. package/src/commands/skills/register.d.ts +2 -0
  183. package/src/commands/skills/register.js +65 -0
  184. package/src/commands/skills/register.js.map +1 -0
  185. package/src/commands/skills/search.d.ts +5 -0
  186. package/src/commands/skills/search.js +24 -0
  187. package/src/commands/skills/search.js.map +1 -0
  188. package/src/commands/skills/show.d.ts +1 -0
  189. package/src/commands/skills/show.js +46 -0
  190. package/src/commands/skills/show.js.map +1 -0
  191. package/src/{args.d.ts → core/args.d.ts} +10 -3
  192. package/src/{args.js → core/args.js} +23 -7
  193. package/src/core/args.js.map +1 -0
  194. package/src/core/bridge.d.ts +6 -0
  195. package/src/core/bridge.js +70 -0
  196. package/src/core/bridge.js.map +1 -0
  197. package/src/core/cli.d.ts +8 -0
  198. package/src/core/cli.js +23 -0
  199. package/src/core/cli.js.map +1 -0
  200. package/src/core/colors.js.map +1 -0
  201. package/src/core/help.d.ts +7 -0
  202. package/src/core/help.js +88 -0
  203. package/src/core/help.js.map +1 -0
  204. package/src/core/index.d.ts +7 -0
  205. package/src/core/index.js +22 -0
  206. package/src/core/index.js.map +1 -0
  207. package/src/core/program.d.ts +2 -0
  208. package/src/core/program.js +25 -0
  209. package/src/core/program.js.map +1 -0
  210. package/src/core/tsconfig.js.map +1 -0
  211. package/src/{version.js → core/version.js} +1 -1
  212. package/src/core/version.js.map +1 -0
  213. package/src/index.d.ts +1 -1
  214. package/src/index.js +2 -5
  215. package/src/index.js.map +1 -1
  216. package/src/{utils → shared}/env.js +2 -2
  217. package/src/shared/env.js.map +1 -0
  218. package/src/{utils → shared}/fs.js +2 -2
  219. package/src/shared/fs.js.map +1 -0
  220. package/src/shared/index.d.ts +3 -0
  221. package/src/shared/index.js +14 -0
  222. package/src/shared/index.js.map +1 -0
  223. package/src/shared/prompts.js.map +1 -0
  224. package/src/args.js.map +0 -1
  225. package/src/cli.d.ts +0 -5
  226. package/src/cli.js +0 -241
  227. package/src/cli.js.map +0 -1
  228. package/src/colors.js.map +0 -1
  229. package/src/commands/configure.js.map +0 -1
  230. package/src/commands/create.js.map +0 -1
  231. package/src/commands/dev.js +0 -57
  232. package/src/commands/dev.js.map +0 -1
  233. package/src/commands/doctor.js.map +0 -1
  234. package/src/commands/inspector.js.map +0 -1
  235. package/src/commands/install/index.js.map +0 -1
  236. package/src/commands/install/registry.js.map +0 -1
  237. package/src/commands/install/sources/git.js.map +0 -1
  238. package/src/commands/install/types.js.map +0 -1
  239. package/src/commands/list.js.map +0 -1
  240. package/src/commands/logs.js.map +0 -1
  241. package/src/commands/restart.js.map +0 -1
  242. package/src/commands/service.js.map +0 -1
  243. package/src/commands/socket.js.map +0 -1
  244. package/src/commands/start.js.map +0 -1
  245. package/src/commands/status.js.map +0 -1
  246. package/src/commands/stop.js.map +0 -1
  247. package/src/commands/template.d.ts +0 -13
  248. package/src/commands/template.js +0 -193
  249. package/src/commands/template.js.map +0 -1
  250. package/src/commands/test.js.map +0 -1
  251. package/src/commands/uninstall.js.map +0 -1
  252. package/src/pm/index.d.ts +0 -9
  253. package/src/pm/index.js.map +0 -1
  254. package/src/pm/pm.format.js.map +0 -1
  255. package/src/pm/pm.health.js.map +0 -1
  256. package/src/pm/pm.logs.js.map +0 -1
  257. package/src/pm/pm.manager.js.map +0 -1
  258. package/src/pm/pm.paths.js.map +0 -1
  259. package/src/pm/pm.pidfile.js.map +0 -1
  260. package/src/pm/pm.service.js.map +0 -1
  261. package/src/pm/pm.spawn.js.map +0 -1
  262. package/src/pm/pm.types.js.map +0 -1
  263. package/src/templates/3rd-party-integration/src/http-client.d.ts +0 -20
  264. package/src/templates/3rd-party-integration/src/http-client.js +0 -105
  265. package/src/templates/3rd-party-integration/src/http-client.js.map +0 -1
  266. package/src/templates/3rd-party-integration/src/mcp-http-types.d.ts +0 -63
  267. package/src/templates/3rd-party-integration/src/mcp-http-types.js +0 -52
  268. package/src/templates/3rd-party-integration/src/mcp-http-types.js.map +0 -1
  269. package/src/templates/3rd-party-integration/src/tools/example.list.d.ts +0 -45
  270. package/src/templates/3rd-party-integration/src/tools/example.list.js +0 -85
  271. package/src/templates/3rd-party-integration/src/tools/example.list.js.map +0 -1
  272. package/src/tsconfig.js.map +0 -1
  273. package/src/utils/env.js.map +0 -1
  274. package/src/utils/fs.js.map +0 -1
  275. package/src/utils/prompts.js.map +0 -1
  276. package/src/version.js.map +0 -1
  277. /package/src/commands/{doctor.d.ts → dev/doctor.d.ts} +0 -0
  278. /package/src/commands/{inspector.d.ts → dev/inspector.d.ts} +0 -0
  279. /package/src/commands/{install → package}/questionnaire.d.ts +0 -0
  280. /package/src/commands/{install → package}/registry.d.ts +0 -0
  281. /package/src/commands/{install → package}/sources/git.d.ts +0 -0
  282. /package/src/commands/{install → package}/sources/local.d.ts +0 -0
  283. /package/src/commands/{install → package}/sources/local.js +0 -0
  284. /package/src/commands/{install → package}/sources/npm.d.ts +0 -0
  285. /package/src/commands/{install → package}/sources/npm.js +0 -0
  286. /package/src/{pm/pm.health.d.ts → commands/pm/health.d.ts} +0 -0
  287. /package/src/{pm/pm.logs.d.ts → commands/pm/log-utils.d.ts} +0 -0
  288. /package/src/{pm/pm.types.d.ts → commands/pm/types.d.ts} +0 -0
  289. /package/src/{colors.d.ts → core/colors.d.ts} +0 -0
  290. /package/src/{colors.js → core/colors.js} +0 -0
  291. /package/src/{tsconfig.d.ts → core/tsconfig.d.ts} +0 -0
  292. /package/src/{tsconfig.js → core/tsconfig.js} +0 -0
  293. /package/src/{version.d.ts → core/version.d.ts} +0 -0
  294. /package/src/{utils → shared}/env.d.ts +0 -0
  295. /package/src/{utils → shared}/fs.d.ts +0 -0
  296. /package/src/{utils → shared}/prompts.d.ts +0 -0
  297. /package/src/{utils → shared}/prompts.js +0 -0
package/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
  [![License](https://img.shields.io/github/license/agentfront/frontmcp.svg?v=1)](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
15
15
  [![Snyk](https://snyk.io/test/github/agentfront/frontmcp/badge.svg)](https://snyk.io/test/github/agentfront/frontmcp)
16
16
 
17
- [Docs][docs-home] • [Quickstart][docs-quickstart] • [API Reference][docs-sdk-ref] • [Discord](https://discord.gg/frontmcp)
17
+ [Docs][docs-home] • [Quickstart][docs-quickstart] • [API Reference][docs-sdk-ref] • [Discord](https://discord.gg/53AHnJnmwR)
18
18
 
19
19
  </div>
20
20
 
@@ -39,14 +39,14 @@ export default class Server {}
39
39
 
40
40
  ## Installation
41
41
 
42
- **Node.js 22+** required (24 recommended).
42
+ **Node.js 24+** required.
43
43
 
44
44
  ```bash
45
45
  # New project (recommended)
46
46
  npx frontmcp create my-app
47
47
 
48
48
  # Existing project
49
- npm i -D frontmcp @types/node@^22
49
+ npm i -D frontmcp @types/node@^24
50
50
  npx frontmcp init
51
51
  ```
52
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontmcp",
3
- "version": "0.12.2",
3
+ "version": "1.0.0-beta.10",
4
4
  "description": "FrontMCP command line interface",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -23,24 +23,25 @@
23
23
  },
24
24
  "main": "./src/index.js",
25
25
  "bin": {
26
- "frontmcp": "./src/cli.js"
26
+ "frontmcp": "./src/core/cli.js"
27
27
  },
28
28
  "engines": {
29
- "node": ">=22.0.0"
29
+ "node": ">=24.0.0"
30
30
  },
31
31
  "dependencies": {
32
32
  "@clack/prompts": "^0.10.0",
33
- "@frontmcp/utils": "0.12.2",
33
+ "@frontmcp/utils": "1.0.0-beta.10",
34
+ "commander": "^13.0.0",
34
35
  "tslib": "^2.3.0",
36
+ "vectoriadb": "^2.1.3",
35
37
  "@rspack/core": "^1.7.6",
36
38
  "esbuild": "^0.27.3"
37
39
  },
38
40
  "devDependencies": {
39
41
  "typescript": "^5.5.3",
40
42
  "tsx": "^4.20.6",
41
- "@types/node": "^24.0.0",
42
- "@modelcontextprotocol/inspector": "^0.20.0"
43
+ "@types/node": "^24.0.0"
43
44
  },
44
- "types": "./src/index.d.ts",
45
+ "types": "./index.d.js",
45
46
  "type": "commonjs"
46
47
  }
@@ -10,7 +10,7 @@ exports.cloudflareAdapter = void 0;
10
10
  exports.cloudflareAdapter = {
11
11
  moduleFormat: 'commonjs',
12
12
  getEntryTemplate: (mainModulePath) => `// Auto-generated Cloudflare Workers entry point
13
- // Generated by: frontmcp build --adapter cloudflare
13
+ // Generated by: frontmcp build --target cloudflare
14
14
  process.env.FRONTMCP_SERVERLESS = '1';
15
15
 
16
16
  require('${mainModulePath}');
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/cloudflare.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACU,QAAA,iBAAiB,GAAoB;IAChD,YAAY,EAAE,UAAU;IAExB,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;WAIrC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDxB;IAEC,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;;CAG9B;IAEC,cAAc,EAAE,eAAe;CAChC,CAAC","sourcesContent":["import { AdapterTemplate } from '../types';\n\n/**\n * Cloudflare Workers adapter - edge deployment on Cloudflare.\n * Compiles to CommonJS and adapts the Express app to Cloudflare's fetch API.\n *\n * @see https://developers.cloudflare.com/workers/\n */\nexport const cloudflareAdapter: AdapterTemplate = {\n moduleFormat: 'commonjs',\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Cloudflare Workers entry point\n// Generated by: frontmcp build --adapter cloudflare\nprocess.env.FRONTMCP_SERVERLESS = '1';\n\nrequire('${mainModulePath}');\nconst { getServerlessHandlerAsync } = require('@frontmcp/sdk');\n\nlet app = null;\n\nasync function handleRequest(request) {\n if (!app) {\n app = await getServerlessHandlerAsync();\n }\n\n // Convert Cloudflare Request to Node.js format\n const url = new URL(request.url);\n const req = {\n method: request.method,\n url: url.pathname + url.search,\n headers: Object.fromEntries(request.headers),\n body: request.body,\n };\n\n return new Promise((resolve) => {\n const res = {\n statusCode: 200,\n headers: {},\n body: '',\n status(code) { this.statusCode = code; return this; },\n setHeader(key, value) { this.headers[key] = value; },\n json(data) {\n this.headers['Content-Type'] = 'application/json';\n this.body = JSON.stringify(data);\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n send(data) {\n this.body = data;\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n end() {\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n };\n app(req, res);\n });\n}\n\nmodule.exports = {\n async fetch(request, env, ctx) {\n return handleRequest(request);\n }\n};\n`,\n\n getConfig: (_cwd: string) => `name = \"frontmcp-worker\"\nmain = \"dist/index.js\"\ncompatibility_date = \"2024-01-01\"\n`,\n\n configFileName: 'wrangler.toml',\n};\n"]}
1
+ {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/cloudflare.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACU,QAAA,iBAAiB,GAAoB;IAChD,YAAY,EAAE,UAAU;IAExB,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;WAIrC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDxB;IAEC,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;;CAG9B;IAEC,cAAc,EAAE,eAAe;CAChC,CAAC","sourcesContent":["import { AdapterTemplate } from '../types';\n\n/**\n * Cloudflare Workers adapter - edge deployment on Cloudflare.\n * Compiles to CommonJS and adapts the Express app to Cloudflare's fetch API.\n *\n * @see https://developers.cloudflare.com/workers/\n */\nexport const cloudflareAdapter: AdapterTemplate = {\n moduleFormat: 'commonjs',\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Cloudflare Workers entry point\n// Generated by: frontmcp build --target cloudflare\nprocess.env.FRONTMCP_SERVERLESS = '1';\n\nrequire('${mainModulePath}');\nconst { getServerlessHandlerAsync } = require('@frontmcp/sdk');\n\nlet app = null;\n\nasync function handleRequest(request) {\n if (!app) {\n app = await getServerlessHandlerAsync();\n }\n\n // Convert Cloudflare Request to Node.js format\n const url = new URL(request.url);\n const req = {\n method: request.method,\n url: url.pathname + url.search,\n headers: Object.fromEntries(request.headers),\n body: request.body,\n };\n\n return new Promise((resolve) => {\n const res = {\n statusCode: 200,\n headers: {},\n body: '',\n status(code) { this.statusCode = code; return this; },\n setHeader(key, value) { this.headers[key] = value; },\n json(data) {\n this.headers['Content-Type'] = 'application/json';\n this.body = JSON.stringify(data);\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n send(data) {\n this.body = data;\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n end() {\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n };\n app(req, res);\n });\n}\n\nmodule.exports = {\n async fetch(request, env, ctx) {\n return handleRequest(request);\n }\n};\n`,\n\n getConfig: (_cwd: string) => `name = \"frontmcp-worker\"\nmain = \"dist/index.js\"\ncompatibility_date = \"2024-01-01\"\n`,\n\n configFileName: 'wrangler.toml',\n};\n"]}
@@ -26,7 +26,7 @@ exports.lambdaAdapter = {
26
26
  process.env.FRONTMCP_SERVERLESS = '1';
27
27
  `,
28
28
  getEntryTemplate: (mainModulePath) => `// Auto-generated AWS Lambda entry point
29
- // Generated by: frontmcp build --adapter lambda
29
+ // Generated by: frontmcp build --target lambda
30
30
  //
31
31
  // IMPORTANT: This adapter requires @codegenie/serverless-express
32
32
  // Install it with: npm install @codegenie/serverless-express
@@ -1 +1 @@
1
- {"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/lambda.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;GAcG;AACU,QAAA,aAAa,GAAoB;IAC5C,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,aAAa;IAE3B,gBAAgB,EAAE,GAAG,EAAE,CAAC;;;;CAIzB;IAEC,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;;;;UAOtC,cAAc;;;;;;;;;;;;;;;;;CAiBvB;IAEC,qEAAqE;CACtE,CAAC","sourcesContent":["import { AdapterTemplate } from '../types';\n\n/**\n * AWS Lambda adapter - serverless deployment on AWS Lambda.\n * Compiles to ESM, bundles with rspack to CJS for maximum compatibility.\n *\n * Prerequisites:\n * npm install @codegenie/serverless-express\n *\n * The build process:\n * 1. TypeScript compiles to ESM in dist/\n * 2. serverless-setup.js is generated (sets FRONTMCP_SERVERLESS=1)\n * 3. index.js imports setup first, then main module\n * 4. rspack bundles everything into handler.cjs\n *\n * @see https://github.com/codegenie/serverless-express\n */\nexport const lambdaAdapter: AdapterTemplate = {\n moduleFormat: 'esnext',\n shouldBundle: true,\n bundleOutput: 'handler.cjs',\n\n getSetupTemplate: () => `// Serverless environment setup - MUST be imported first\n// This sets FRONTMCP_SERVERLESS before any decorators run\n// Required because ESM hoists imports before other statements\nprocess.env.FRONTMCP_SERVERLESS = '1';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated AWS Lambda entry point\n// Generated by: frontmcp build --adapter lambda\n//\n// IMPORTANT: This adapter requires @codegenie/serverless-express\n// Install it with: npm install @codegenie/serverless-express\n//\nimport './serverless-setup.js';\nimport '${mainModulePath}';\nimport { getServerlessHandlerAsync } from '@frontmcp/sdk';\nimport serverlessExpress from '@codegenie/serverless-express';\n\nlet serverlessExpressInstance = null;\n\nasync function setup() {\n const app = await getServerlessHandlerAsync();\n serverlessExpressInstance = serverlessExpress({ app });\n}\n\nexport const handler = async (event, context) => {\n if (!serverlessExpressInstance) {\n await setup();\n }\n return serverlessExpressInstance(event, context);\n};\n`,\n\n // No config file - user manages serverless.yml, SAM template, or CDK\n};\n"]}
1
+ {"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/lambda.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;GAcG;AACU,QAAA,aAAa,GAAoB;IAC5C,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,aAAa;IAE3B,gBAAgB,EAAE,GAAG,EAAE,CAAC;;;;CAIzB;IAEC,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;;;;UAOtC,cAAc;;;;;;;;;;;;;;;;;CAiBvB;IAEC,qEAAqE;CACtE,CAAC","sourcesContent":["import { AdapterTemplate } from '../types';\n\n/**\n * AWS Lambda adapter - serverless deployment on AWS Lambda.\n * Compiles to ESM, bundles with rspack to CJS for maximum compatibility.\n *\n * Prerequisites:\n * npm install @codegenie/serverless-express\n *\n * The build process:\n * 1. TypeScript compiles to ESM in dist/\n * 2. serverless-setup.js is generated (sets FRONTMCP_SERVERLESS=1)\n * 3. index.js imports setup first, then main module\n * 4. rspack bundles everything into handler.cjs\n *\n * @see https://github.com/codegenie/serverless-express\n */\nexport const lambdaAdapter: AdapterTemplate = {\n moduleFormat: 'esnext',\n shouldBundle: true,\n bundleOutput: 'handler.cjs',\n\n getSetupTemplate: () => `// Serverless environment setup - MUST be imported first\n// This sets FRONTMCP_SERVERLESS before any decorators run\n// Required because ESM hoists imports before other statements\nprocess.env.FRONTMCP_SERVERLESS = '1';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated AWS Lambda entry point\n// Generated by: frontmcp build --target lambda\n//\n// IMPORTANT: This adapter requires @codegenie/serverless-express\n// Install it with: npm install @codegenie/serverless-express\n//\nimport './serverless-setup.js';\nimport '${mainModulePath}';\nimport { getServerlessHandlerAsync } from '@frontmcp/sdk';\nimport serverlessExpress from '@codegenie/serverless-express';\n\nlet serverlessExpressInstance = null;\n\nasync function setup() {\n const app = await getServerlessHandlerAsync();\n serverlessExpressInstance = serverlessExpress({ app });\n}\n\nexport const handler = async (event, context) => {\n if (!serverlessExpressInstance) {\n await setup();\n }\n return serverlessExpressInstance(event, context);\n};\n`,\n\n // No config file - user manages serverless.yml, SAM template, or CDK\n};\n"]}
@@ -57,7 +57,7 @@ exports.vercelAdapter = {
57
57
  process.env.FRONTMCP_SERVERLESS = '1';
58
58
  `,
59
59
  getEntryTemplate: (mainModulePath) => `// Auto-generated Vercel entry point
60
- // Generated by: frontmcp build --adapter vercel
60
+ // Generated by: frontmcp build --target vercel
61
61
  import './serverless-setup.js';
62
62
  import '${mainModulePath}';
63
63
  import { getServerlessHandlerAsync } from '@frontmcp/sdk';
@@ -150,7 +150,7 @@ export default async function handler(req, res) {
150
150
  }
151
151
  // Create function config (.vc-config.json)
152
152
  const vcConfig = {
153
- runtime: 'nodejs22.x',
153
+ runtime: 'nodejs24.x',
154
154
  handler: bundleOutput,
155
155
  launcherType: 'Nodejs',
156
156
  };
@@ -1 +1 @@
1
- {"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/vercel.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { existsSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { mkdir, readdir, stat, cp, copyFile, readFile, writeFile } from '@frontmcp/utils';\nimport { AdapterTemplate } from '../types';\n\ntype PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\n\ninterface PackageManagerConfig {\n install: string;\n run: string;\n}\n\nconst PACKAGE_MANAGERS: Record<PackageManager, PackageManagerConfig> = {\n bun: { install: 'bun install', run: 'bun run build' },\n pnpm: { install: 'pnpm install', run: 'pnpm run build' },\n yarn: { install: 'yarn install', run: 'yarn build' },\n npm: { install: 'npm install', run: 'npm run build' },\n};\n\nconst LOCKFILE_TO_PM: Record<string, PackageManager> = {\n 'bun.lockb': 'bun',\n 'pnpm-lock.yaml': 'pnpm',\n 'yarn.lock': 'yarn',\n 'package-lock.json': 'npm',\n};\n\n/**\n * Detect package manager based on lockfile presence.\n * Priority: bun > pnpm > yarn > npm (fastest to slowest install times)\n */\nfunction detectPackageManager(cwd: string): PackageManager {\n for (const [lockfile, pm] of Object.entries(LOCKFILE_TO_PM)) {\n if (existsSync(path.join(cwd, lockfile))) {\n return pm;\n }\n }\n return 'npm'; // Default fallback\n}\n\n/**\n * Vercel adapter - serverless deployment on Vercel.\n * Compiles to ESM, bundles with rspack to CJS for maximum compatibility.\n *\n * Uses Vercel Build Output API for deployment:\n * - Creates .vercel/output/config.json with routing\n * - Creates .vercel/output/functions/index.func/ with handler\n *\n * The build process:\n * 1. TypeScript compiles to ESM in dist/\n * 2. serverless-setup.js is generated (sets FRONTMCP_SERVERLESS=1)\n * 3. index.js imports setup first, then main module\n * 4. rspack bundles everything into handler.cjs\n * 5. Build Output API structure is created in .vercel/output/\n *\n * @see https://vercel.com/docs/build-output-api/v3\n */\nexport const vercelAdapter: AdapterTemplate = {\n moduleFormat: 'esnext',\n shouldBundle: true,\n bundleOutput: 'handler.cjs',\n\n getSetupTemplate: () => `// Serverless environment setup - MUST be imported first\n// This sets FRONTMCP_SERVERLESS before any decorators run\n// Required because ESM hoists imports before other statements\nprocess.env.FRONTMCP_SERVERLESS = '1';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Vercel entry point\n// Generated by: frontmcp build --adapter vercel\nimport './serverless-setup.js';\nimport '${mainModulePath}';\nimport { getServerlessHandlerAsync } from '@frontmcp/sdk';\n\nlet handlerPromise = null;\n\nexport default async function handler(req, res) {\n if (!handlerPromise) {\n handlerPromise = getServerlessHandlerAsync();\n }\n const app = await handlerPromise;\n return app(req, res);\n}\n`,\n\n // Detect package manager and generate appropriate vercel.json\n getConfig: (cwd: string) => {\n const pm = detectPackageManager(cwd);\n const config = PACKAGE_MANAGERS[pm];\n return {\n version: 2,\n buildCommand: config.run,\n installCommand: config.install,\n };\n },\n\n configFileName: 'vercel.json',\n\n /**\n * Create Vercel Build Output API structure after bundling.\n * This allows Vercel to deploy the function without needing an /api folder.\n *\n * Structure created:\n * .vercel/output/\n * ├── config.json (routes all requests to index function)\n * └── functions/\n * └── index.func/\n * ├── .vc-config.json (Node.js 22 runtime config)\n * ├── handler.cjs (bundled handler + chunks)\n * └── node_modules/ (runtime dependencies that can't be bundled)\n */\n postBundle: async (outDir: string, cwd: string, bundleOutput: string) => {\n const outputDir = path.join(cwd, '.vercel', 'output');\n const funcDir = path.join(outputDir, 'functions', 'index.func');\n\n // Create directories\n await mkdir(funcDir, { recursive: true });\n\n // Copy all files from dist to the function directory\n // This includes handler.cjs and any chunk files (*.handler.cjs)\n const distFiles = await readdir(outDir);\n for (const file of distFiles) {\n const srcPath = path.join(outDir, file);\n const destPath = path.join(funcDir, file);\n const fileStat = await stat(srcPath);\n\n if (fileStat.isDirectory()) {\n // Recursively copy directories\n await cp(srcPath, destPath, { recursive: true });\n } else {\n // Copy files\n await copyFile(srcPath, destPath);\n }\n }\n\n // Install runtime dependencies that can't be statically bundled (dynamic requires)\n // These are packages loaded via require() inside functions that rspack can't analyze\n // We install them fresh to ensure correct platform binaries (linux-x64 for Vercel)\n const runtimeDeps = ['@vercel/kv', 'esbuild', '@swc/core'];\n\n // Read package.json to get the exact versions\n const pkgJsonPath = path.join(cwd, 'package.json');\n const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };\n\n // Build list of deps with versions\n const depsToInstall: string[] = [];\n for (const dep of runtimeDeps) {\n const version = allDeps[dep];\n if (version) {\n depsToInstall.push(`${dep}@${version}`);\n }\n }\n\n if (depsToInstall.length > 0) {\n // Create package.json in function directory\n const funcPkgJson = { name: 'index.func', private: true, dependencies: {} };\n await writeFile(path.join(funcDir, 'package.json'), JSON.stringify(funcPkgJson, null, 2));\n\n // Install dependencies using npm (works on all platforms)\n try {\n execSync(`npm install ${depsToInstall.join(' ')} --omit=dev`, {\n cwd: funcDir,\n stdio: 'pipe',\n });\n } catch {\n // Silently continue if install fails - the dep might not be needed\n }\n }\n\n // Create function config (.vc-config.json)\n const vcConfig = {\n runtime: 'nodejs22.x',\n handler: bundleOutput,\n launcherType: 'Nodejs',\n };\n await writeFile(\n path.join(funcDir, '.vc-config.json'),\n JSON.stringify(vcConfig, null, 2),\n );\n\n // Create output config (config.json) with routing\n const outputConfig = {\n version: 3,\n routes: [{ src: '/(.*)', dest: '/index' }],\n };\n await writeFile(\n path.join(outputDir, 'config.json'),\n JSON.stringify(outputConfig, null, 2),\n );\n },\n};\n"]}
1
+ {"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/vercel.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { existsSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { mkdir, readdir, stat, cp, copyFile, readFile, writeFile } from '@frontmcp/utils';\nimport { AdapterTemplate } from '../types';\n\ntype PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\n\ninterface PackageManagerConfig {\n install: string;\n run: string;\n}\n\nconst PACKAGE_MANAGERS: Record<PackageManager, PackageManagerConfig> = {\n bun: { install: 'bun install', run: 'bun run build' },\n pnpm: { install: 'pnpm install', run: 'pnpm run build' },\n yarn: { install: 'yarn install', run: 'yarn build' },\n npm: { install: 'npm install', run: 'npm run build' },\n};\n\nconst LOCKFILE_TO_PM: Record<string, PackageManager> = {\n 'bun.lockb': 'bun',\n 'pnpm-lock.yaml': 'pnpm',\n 'yarn.lock': 'yarn',\n 'package-lock.json': 'npm',\n};\n\n/**\n * Detect package manager based on lockfile presence.\n * Priority: bun > pnpm > yarn > npm (fastest to slowest install times)\n */\nfunction detectPackageManager(cwd: string): PackageManager {\n for (const [lockfile, pm] of Object.entries(LOCKFILE_TO_PM)) {\n if (existsSync(path.join(cwd, lockfile))) {\n return pm;\n }\n }\n return 'npm'; // Default fallback\n}\n\n/**\n * Vercel adapter - serverless deployment on Vercel.\n * Compiles to ESM, bundles with rspack to CJS for maximum compatibility.\n *\n * Uses Vercel Build Output API for deployment:\n * - Creates .vercel/output/config.json with routing\n * - Creates .vercel/output/functions/index.func/ with handler\n *\n * The build process:\n * 1. TypeScript compiles to ESM in dist/\n * 2. serverless-setup.js is generated (sets FRONTMCP_SERVERLESS=1)\n * 3. index.js imports setup first, then main module\n * 4. rspack bundles everything into handler.cjs\n * 5. Build Output API structure is created in .vercel/output/\n *\n * @see https://vercel.com/docs/build-output-api/v3\n */\nexport const vercelAdapter: AdapterTemplate = {\n moduleFormat: 'esnext',\n shouldBundle: true,\n bundleOutput: 'handler.cjs',\n\n getSetupTemplate: () => `// Serverless environment setup - MUST be imported first\n// This sets FRONTMCP_SERVERLESS before any decorators run\n// Required because ESM hoists imports before other statements\nprocess.env.FRONTMCP_SERVERLESS = '1';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Vercel entry point\n// Generated by: frontmcp build --target vercel\nimport './serverless-setup.js';\nimport '${mainModulePath}';\nimport { getServerlessHandlerAsync } from '@frontmcp/sdk';\n\nlet handlerPromise = null;\n\nexport default async function handler(req, res) {\n if (!handlerPromise) {\n handlerPromise = getServerlessHandlerAsync();\n }\n const app = await handlerPromise;\n return app(req, res);\n}\n`,\n\n // Detect package manager and generate appropriate vercel.json\n getConfig: (cwd: string) => {\n const pm = detectPackageManager(cwd);\n const config = PACKAGE_MANAGERS[pm];\n return {\n version: 2,\n buildCommand: config.run,\n installCommand: config.install,\n };\n },\n\n configFileName: 'vercel.json',\n\n /**\n * Create Vercel Build Output API structure after bundling.\n * This allows Vercel to deploy the function without needing an /api folder.\n *\n * Structure created:\n * .vercel/output/\n * ├── config.json (routes all requests to index function)\n * └── functions/\n * └── index.func/\n * ├── .vc-config.json (Node.js 22 runtime config)\n * ├── handler.cjs (bundled handler + chunks)\n * └── node_modules/ (runtime dependencies that can't be bundled)\n */\n postBundle: async (outDir: string, cwd: string, bundleOutput: string) => {\n const outputDir = path.join(cwd, '.vercel', 'output');\n const funcDir = path.join(outputDir, 'functions', 'index.func');\n\n // Create directories\n await mkdir(funcDir, { recursive: true });\n\n // Copy all files from dist to the function directory\n // This includes handler.cjs and any chunk files (*.handler.cjs)\n const distFiles = await readdir(outDir);\n for (const file of distFiles) {\n const srcPath = path.join(outDir, file);\n const destPath = path.join(funcDir, file);\n const fileStat = await stat(srcPath);\n\n if (fileStat.isDirectory()) {\n // Recursively copy directories\n await cp(srcPath, destPath, { recursive: true });\n } else {\n // Copy files\n await copyFile(srcPath, destPath);\n }\n }\n\n // Install runtime dependencies that can't be statically bundled (dynamic requires)\n // These are packages loaded via require() inside functions that rspack can't analyze\n // We install them fresh to ensure correct platform binaries (linux-x64 for Vercel)\n const runtimeDeps = ['@vercel/kv', 'esbuild', '@swc/core'];\n\n // Read package.json to get the exact versions\n const pkgJsonPath = path.join(cwd, 'package.json');\n const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };\n\n // Build list of deps with versions\n const depsToInstall: string[] = [];\n for (const dep of runtimeDeps) {\n const version = allDeps[dep];\n if (version) {\n depsToInstall.push(`${dep}@${version}`);\n }\n }\n\n if (depsToInstall.length > 0) {\n // Create package.json in function directory\n const funcPkgJson = { name: 'index.func', private: true, dependencies: {} };\n await writeFile(path.join(funcDir, 'package.json'), JSON.stringify(funcPkgJson, null, 2));\n\n // Install dependencies using npm (works on all platforms)\n try {\n execSync(`npm install ${depsToInstall.join(' ')} --omit=dev`, {\n cwd: funcDir,\n stdio: 'pipe',\n });\n } catch {\n // Silently continue if install fails - the dep might not be needed\n }\n }\n\n // Create function config (.vc-config.json)\n const vcConfig = {\n runtime: 'nodejs24.x',\n handler: bundleOutput,\n launcherType: 'Nodejs',\n };\n await writeFile(\n path.join(funcDir, '.vc-config.json'),\n JSON.stringify(vcConfig, null, 2),\n );\n\n // Create output config (config.json) with routing\n const outputConfig = {\n version: 3,\n routes: [{ src: '/(.*)', dest: '/index' }],\n };\n await writeFile(\n path.join(outputDir, 'config.json'),\n JSON.stringify(outputConfig, null, 2),\n );\n },\n};\n"]}
@@ -0,0 +1,17 @@
1
+ import { ParsedArgs } from '../../../core/args';
2
+ /**
3
+ * Build a browser-compatible ESM bundle.
4
+ *
5
+ * Uses esbuild with `platform: 'browser'` which resolves conditional imports
6
+ * (`#imports` in package.json) to browser implementations automatically:
7
+ * - Crypto → @noble/hashes + @noble/ciphers (no node:crypto)
8
+ * - AsyncLocalStorage → stack-based polyfill
9
+ * - EventEmitter → Map-based polyfill
10
+ * - SSE/Express/Stdio → stubs that throw on instantiation
11
+ *
12
+ * @example
13
+ * ```bash
14
+ * frontmcp build --target browser
15
+ * ```
16
+ */
17
+ export declare function buildBrowser(opts: ParsedArgs): Promise<void>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildBrowser = buildBrowser;
4
+ const tslib_1 = require("tslib");
5
+ const path = tslib_1.__importStar(require("path"));
6
+ const colors_1 = require("../../../core/colors");
7
+ const utils_1 = require("@frontmcp/utils");
8
+ const fs_1 = require("../../../shared/fs");
9
+ /**
10
+ * Build a browser-compatible ESM bundle.
11
+ *
12
+ * Uses esbuild with `platform: 'browser'` which resolves conditional imports
13
+ * (`#imports` in package.json) to browser implementations automatically:
14
+ * - Crypto → @noble/hashes + @noble/ciphers (no node:crypto)
15
+ * - AsyncLocalStorage → stack-based polyfill
16
+ * - EventEmitter → Map-based polyfill
17
+ * - SSE/Express/Stdio → stubs that throw on instantiation
18
+ *
19
+ * @example
20
+ * ```bash
21
+ * frontmcp build --target browser
22
+ * ```
23
+ */
24
+ async function buildBrowser(opts) {
25
+ const cwd = process.cwd();
26
+ const entry = await (0, fs_1.resolveEntry)(cwd, opts.entry);
27
+ const outDir = path.resolve(cwd, opts.outDir || 'dist');
28
+ await (0, utils_1.ensureDir)(outDir);
29
+ const pkg = require(path.join(cwd, 'package.json'));
30
+ const appName = pkg.name || path.basename(cwd);
31
+ console.log(`${(0, colors_1.c)('cyan', '[build:browser]')} entry: ${path.relative(cwd, entry)}`);
32
+ console.log(`${(0, colors_1.c)('cyan', '[build:browser]')} outDir: ${path.relative(cwd, outDir)}`);
33
+ const esbuild = await import('esbuild');
34
+ // Build ESM bundle for browsers
35
+ console.log((0, colors_1.c)('cyan', '[build:browser] Bundling ESM for browser...'));
36
+ await esbuild.build({
37
+ entryPoints: [entry],
38
+ bundle: true,
39
+ platform: 'browser',
40
+ format: 'esm',
41
+ target: 'es2022',
42
+ outfile: path.join(outDir, `${appName}.browser.mjs`),
43
+ keepNames: true,
44
+ treeShaking: true,
45
+ sourcemap: true,
46
+ // Browser-safe: keep React and peer deps external (user's bundler handles them)
47
+ external: [
48
+ 'react', 'react-dom', 'react-router', 'react-router-dom',
49
+ // Keep @frontmcp/* external — user installs them
50
+ '@frontmcp/sdk', '@frontmcp/di', '@frontmcp/utils',
51
+ '@frontmcp/auth', '@frontmcp/react',
52
+ 'reflect-metadata',
53
+ // Node.js-only — these should be tree-shaken by platform: 'browser'
54
+ // but list explicitly to avoid accidental bundling
55
+ 'better-sqlite3', 'fsevents', 'ioredis',
56
+ ...Object.keys(pkg.peerDependencies || {}),
57
+ ],
58
+ // Resolve conditional imports to browser variants
59
+ conditions: ['browser', 'import', 'default'],
60
+ define: {
61
+ 'process.env.NODE_ENV': '"production"',
62
+ },
63
+ });
64
+ console.log((0, colors_1.c)('green', `\n Browser build complete:`));
65
+ console.log((0, colors_1.c)('gray', ` ESM: ${appName}.browser.mjs`));
66
+ console.log((0, colors_1.c)('gray', ` Source map: ${appName}.browser.mjs.map`));
67
+ }
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/browser/index.ts"],"names":[],"mappings":";;AAqBA,oCAgDC;;AArED,mDAA6B;AAE7B,iDAAyC;AACzC,2CAA4C;AAC5C,2CAAkD;AAElD;;;;;;;;;;;;;;GAcG;AACI,KAAK,UAAU,YAAY,CAAC,IAAgB;IACjD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,MAAM,IAAA,iBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IACxD,MAAM,IAAA,iBAAS,EAAC,MAAM,CAAC,CAAC;IAExB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE/C,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IACnF,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAErF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAExC,gCAAgC;IAChC,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,6CAA6C,CAAC,CAAC,CAAC;IACtE,MAAM,OAAO,CAAC,KAAK,CAAC;QAClB,WAAW,EAAE,CAAC,KAAK,CAAC;QACpB,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,cAAc,CAAC;QACpD,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,IAAI;QACf,gFAAgF;QAChF,QAAQ,EAAE;YACR,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB;YACxD,iDAAiD;YACjD,eAAe,EAAE,cAAc,EAAE,iBAAiB;YAClD,gBAAgB,EAAE,iBAAiB;YACnC,kBAAkB;YAClB,oEAAoE;YACpE,mDAAmD;YACnD,gBAAgB,EAAE,UAAU,EAAE,SAAS;YACvC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;SAC3C;QACD,kDAAkD;QAClD,UAAU,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAC5C,MAAM,EAAE;YACN,sBAAsB,EAAE,cAAc;SACvC;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,UAAU,OAAO,cAAc,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,OAAO,kBAAkB,CAAC,CAAC,CAAC;AACrE,CAAC","sourcesContent":["import * as path from 'path';\nimport { ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { ensureDir } from '@frontmcp/utils';\nimport { resolveEntry } from '../../../shared/fs';\n\n/**\n * Build a browser-compatible ESM bundle.\n *\n * Uses esbuild with `platform: 'browser'` which resolves conditional imports\n * (`#imports` in package.json) to browser implementations automatically:\n * - Crypto → @noble/hashes + @noble/ciphers (no node:crypto)\n * - AsyncLocalStorage → stack-based polyfill\n * - EventEmitter → Map-based polyfill\n * - SSE/Express/Stdio → stubs that throw on instantiation\n *\n * @example\n * ```bash\n * frontmcp build --target browser\n * ```\n */\nexport async function buildBrowser(opts: ParsedArgs): Promise<void> {\n const cwd = process.cwd();\n const entry = await resolveEntry(cwd, opts.entry);\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n await ensureDir(outDir);\n\n const pkg = require(path.join(cwd, 'package.json'));\n const appName = pkg.name || path.basename(cwd);\n\n console.log(`${c('cyan', '[build:browser]')} entry: ${path.relative(cwd, entry)}`);\n console.log(`${c('cyan', '[build:browser]')} outDir: ${path.relative(cwd, outDir)}`);\n\n const esbuild = await import('esbuild');\n\n // Build ESM bundle for browsers\n console.log(c('cyan', '[build:browser] Bundling ESM for browser...'));\n await esbuild.build({\n entryPoints: [entry],\n bundle: true,\n platform: 'browser',\n format: 'esm',\n target: 'es2022',\n outfile: path.join(outDir, `${appName}.browser.mjs`),\n keepNames: true,\n treeShaking: true,\n sourcemap: true,\n // Browser-safe: keep React and peer deps external (user's bundler handles them)\n external: [\n 'react', 'react-dom', 'react-router', 'react-router-dom',\n // Keep @frontmcp/* external — user installs them\n '@frontmcp/sdk', '@frontmcp/di', '@frontmcp/utils',\n '@frontmcp/auth', '@frontmcp/react',\n 'reflect-metadata',\n // Node.js-only — these should be tree-shaken by platform: 'browser'\n // but list explicitly to avoid accidental bundling\n 'better-sqlite3', 'fsevents', 'ioredis',\n ...Object.keys(pkg.peerDependencies || {}),\n ],\n // Resolve conditional imports to browser variants\n conditions: ['browser', 'import', 'default'],\n define: {\n 'process.env.NODE_ENV': '\"production\"',\n },\n });\n\n console.log(c('green', `\\n Browser build complete:`));\n console.log(c('gray', ` ESM: ${appName}.browser.mjs`));\n console.log(c('gray', ` Source map: ${appName}.browser.mjs.map`));\n}\n"]}
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.bundleForServerless = bundleForServerless;
4
4
  const core_1 = require("@rspack/core");
5
- const colors_1 = require("../../colors");
5
+ const colors_1 = require("../../core/colors");
6
6
  /**
7
7
  * Bundle the serverless entry point into a single CJS file using rspack.
8
8
  * This resolves ESM/CJS compatibility issues and dynamic import problems.
@@ -1 +1 @@
1
- {"version":3,"file":"bundler.js","sourceRoot":"","sources":["../../../../src/commands/build/bundler.ts"],"names":[],"mappings":"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","sourcesContent":["import { rspack } from '@rspack/core';\nimport { c } from '../../colors';\n\n/**\n * Bundle the serverless entry point into a single CJS file using rspack.\n * This resolves ESM/CJS compatibility issues and dynamic import problems.\n *\n * @param entryPath - Absolute path to the entry file (e.g., dist/index.js)\n * @param outDir - Output directory for the bundled file\n * @param outputFilename - Name of the output bundle (e.g., 'handler.cjs')\n */\nexport async function bundleForServerless(\n entryPath: string,\n outDir: string,\n outputFilename: string,\n): Promise<void> {\n const compiler = rspack({\n mode: 'production',\n target: 'node',\n entry: entryPath,\n output: {\n path: outDir,\n filename: outputFilename,\n library: { type: 'commonjs2' },\n clean: false,\n },\n // Use node externals preset for built-in modules\n externalsPresets: { node: true },\n // Exclude problematic optional dependencies (native binaries that can't be bundled)\n externals: {\n '@swc/core': '@swc/core',\n fsevents: 'fsevents',\n esbuild: 'esbuild',\n // React is optional - only needed for MDX/JSX rendering\n react: 'react',\n 'react-dom': 'react-dom',\n 'react-dom/server': 'react-dom/server',\n 'react/jsx-runtime': 'react/jsx-runtime',\n },\n resolve: {\n extensions: ['.js', '.mjs', '.cjs', '.json'],\n // Allow imports without file extensions (TypeScript compiles without .js but ESM requires them)\n fullySpecified: false,\n },\n module: {\n rules: [],\n parser: {\n javascript: {\n // Handle dynamic requires like require('@vercel/kv') inside functions\n // by wrapping them instead of externalizing them\n dynamicImportMode: 'eager',\n exprContextCritical: false,\n unknownContextCritical: false,\n },\n },\n },\n // Don't minimize to preserve readability for debugging\n optimization: {\n minimize: false,\n },\n // Suppress known third-party library warnings that don't affect runtime\n ignoreWarnings: [\n // Express view engine dynamic require - expected behavior, harmless at runtime\n /Critical dependency: the request of a dependency is an expression/,\n // Handlebars require.extensions - deprecated Node.js API but works at runtime\n /require\\.extensions is not supported by Rspack/,\n ],\n // Suppress verbose output\n stats: 'errors-warnings',\n });\n\n return new Promise((resolve, reject) => {\n compiler.run((err, stats) => {\n if (err) {\n return reject(err);\n }\n if (stats?.hasErrors()) {\n const info = stats.toJson();\n const errorMessages = info.errors?.map((e) => e.message).join('\\n') || 'Unknown error';\n return reject(new Error(`Bundle failed:\\n${errorMessages}`));\n }\n if (stats?.hasWarnings()) {\n const info = stats.toJson();\n info.warnings?.forEach((w) => {\n console.log(c('yellow', ` Warning: ${w.message}`));\n });\n }\n compiler.close((closeErr) => {\n if (closeErr) {\n console.log(c('yellow', ` Warning closing compiler: ${closeErr.message}`));\n }\n resolve();\n });\n });\n });\n}\n"]}
1
+ {"version":3,"file":"bundler.js","sourceRoot":"","sources":["../../../../src/commands/build/bundler.ts"],"names":[],"mappings":"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","sourcesContent":["import { rspack } from '@rspack/core';\nimport { c } from '../../core/colors';\n\n/**\n * Bundle the serverless entry point into a single CJS file using rspack.\n * This resolves ESM/CJS compatibility issues and dynamic import problems.\n *\n * @param entryPath - Absolute path to the entry file (e.g., dist/index.js)\n * @param outDir - Output directory for the bundled file\n * @param outputFilename - Name of the output bundle (e.g., 'handler.cjs')\n */\nexport async function bundleForServerless(\n entryPath: string,\n outDir: string,\n outputFilename: string,\n): Promise<void> {\n const compiler = rspack({\n mode: 'production',\n target: 'node',\n entry: entryPath,\n output: {\n path: outDir,\n filename: outputFilename,\n library: { type: 'commonjs2' },\n clean: false,\n },\n // Use node externals preset for built-in modules\n externalsPresets: { node: true },\n // Exclude problematic optional dependencies (native binaries that can't be bundled)\n externals: {\n '@swc/core': '@swc/core',\n fsevents: 'fsevents',\n esbuild: 'esbuild',\n // React is optional - only needed for MDX/JSX rendering\n react: 'react',\n 'react-dom': 'react-dom',\n 'react-dom/server': 'react-dom/server',\n 'react/jsx-runtime': 'react/jsx-runtime',\n },\n resolve: {\n extensions: ['.js', '.mjs', '.cjs', '.json'],\n // Allow imports without file extensions (TypeScript compiles without .js but ESM requires them)\n fullySpecified: false,\n },\n module: {\n rules: [],\n parser: {\n javascript: {\n // Handle dynamic requires like require('@vercel/kv') inside functions\n // by wrapping them instead of externalizing them\n dynamicImportMode: 'eager',\n exprContextCritical: false,\n unknownContextCritical: false,\n },\n },\n },\n // Don't minimize to preserve readability for debugging\n optimization: {\n minimize: false,\n },\n // Suppress known third-party library warnings that don't affect runtime\n ignoreWarnings: [\n // Express view engine dynamic require - expected behavior, harmless at runtime\n /Critical dependency: the request of a dependency is an expression/,\n // Handlebars require.extensions - deprecated Node.js API but works at runtime\n /require\\.extensions is not supported by Rspack/,\n ],\n // Suppress verbose output\n stats: 'errors-warnings',\n });\n\n return new Promise((resolve, reject) => {\n compiler.run((err, stats) => {\n if (err) {\n return reject(err);\n }\n if (stats?.hasErrors()) {\n const info = stats.toJson();\n const errorMessages = info.errors?.map((e) => e.message).join('\\n') || 'Unknown error';\n return reject(new Error(`Bundle failed:\\n${errorMessages}`));\n }\n if (stats?.hasWarnings()) {\n const info = stats.toJson();\n info.warnings?.forEach((w) => {\n console.log(c('yellow', ` Warning: ${w.message}`));\n });\n }\n compiler.close((closeErr) => {\n if (closeErr) {\n console.log(c('yellow', ` Warning closing compiler: ${closeErr.message}`));\n }\n resolve();\n });\n });\n });\n}\n"]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * esbuild configuration for the CLI bundle.
3
+ * Bundles the generated CLI entry point with commander.js inlined.
4
+ */
5
+ import { FrontmcpExecConfig } from '../config';
6
+ export interface CliBundleResult {
7
+ bundlePath: string;
8
+ bundleSize: number;
9
+ }
10
+ /**
11
+ * Bundle the generated CLI entry with esbuild.
12
+ * Commander.js and runtime modules are inlined; the server bundle is external
13
+ * unless selfContained mode is enabled (for SEA builds).
14
+ */
15
+ export declare function bundleCliWithEsbuild(cliEntryPath: string, outDir: string, config: FrontmcpExecConfig, options?: {
16
+ selfContained?: boolean;
17
+ }): Promise<CliBundleResult>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ /**
3
+ * esbuild configuration for the CLI bundle.
4
+ * Bundles the generated CLI entry point with commander.js inlined.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.bundleCliWithEsbuild = bundleCliWithEsbuild;
8
+ const tslib_1 = require("tslib");
9
+ const path = tslib_1.__importStar(require("path"));
10
+ /**
11
+ * Bundle the generated CLI entry with esbuild.
12
+ * Commander.js and runtime modules are inlined; the server bundle is external
13
+ * unless selfContained mode is enabled (for SEA builds).
14
+ */
15
+ async function bundleCliWithEsbuild(cliEntryPath, outDir, config, options) {
16
+ let esbuild;
17
+ try {
18
+ esbuild = require('esbuild');
19
+ }
20
+ catch {
21
+ throw new Error('esbuild is required for CLI builds. Install it: npm install -D esbuild');
22
+ }
23
+ const cliBundleName = `${config.name}-cli.bundle.js`;
24
+ const bundlePath = path.join(outDir, cliBundleName);
25
+ const selfContained = options?.selfContained ?? false;
26
+ // The server bundle is loaded via require() at runtime — keep external
27
+ // unless selfContained mode where everything is inlined for SEA
28
+ const serverBundleName = `${config.name}.bundle.js`;
29
+ const external = selfContained
30
+ ? [
31
+ // Only true native addons and optional peer deps stay external in self-contained mode
32
+ 'better-sqlite3',
33
+ 'fsevents',
34
+ '@vercel/kv',
35
+ '@frontmcp/storage-sqlite',
36
+ '@enclave-vm/core',
37
+ ...(config.dependencies?.nativeAddons || []),
38
+ ]
39
+ : [
40
+ `./${serverBundleName}`,
41
+ '@frontmcp/sdk',
42
+ 'better-sqlite3',
43
+ 'fsevents',
44
+ '@vercel/kv',
45
+ '@frontmcp/storage-sqlite',
46
+ '@enclave-vm/core',
47
+ ...(config.dependencies?.nativeAddons || []),
48
+ ...(config.esbuild?.external || []),
49
+ ];
50
+ await esbuild.build({
51
+ entryPoints: [cliEntryPath],
52
+ bundle: true,
53
+ platform: 'node',
54
+ format: 'cjs',
55
+ target: config.esbuild?.target || 'node22',
56
+ outfile: bundlePath,
57
+ external,
58
+ keepNames: true,
59
+ treeShaking: true,
60
+ minify: config.esbuild?.minify ?? false,
61
+ banner: {
62
+ js: '#!/usr/bin/env node',
63
+ },
64
+ define: config.esbuild?.define,
65
+ sourcemap: false,
66
+ logLevel: 'warning',
67
+ });
68
+ const fs = require('fs');
69
+ const stat = fs.statSync(bundlePath);
70
+ return {
71
+ bundlePath,
72
+ bundleSize: stat.size,
73
+ };
74
+ }
75
+ //# sourceMappingURL=cli-bundler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-bundler.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/cli-bundler.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAeH,oDAuEC;;AApFD,mDAA6B;AAQ7B;;;;GAIG;AACI,KAAK,UAAU,oBAAoB,CACxC,YAAoB,EACpB,MAAc,EACd,MAA0B,EAC1B,OAAqC;IAErC,IAAI,OAAiC,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,MAAM,CAAC,IAAI,gBAAgB,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,KAAK,CAAC;IAEtD,uEAAuE;IACvE,gEAAgE;IAChE,MAAM,gBAAgB,GAAG,GAAG,MAAM,CAAC,IAAI,YAAY,CAAC;IAEpD,MAAM,QAAQ,GAAG,aAAa;QAC5B,CAAC,CAAC;YACE,sFAAsF;YACtF,gBAAgB;YAChB,UAAU;YACV,YAAY;YACZ,0BAA0B;YAC1B,kBAAkB;YAClB,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE,CAAC;SAC7C;QACH,CAAC,CAAC;YACE,KAAK,gBAAgB,EAAE;YACvB,eAAe;YACf,gBAAgB;YAChB,UAAU;YACV,YAAY;YACZ,0BAA0B;YAC1B,kBAAkB;YAClB,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE,CAAC;YAC5C,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;SACpC,CAAC;IAEN,MAAM,OAAO,CAAC,KAAK,CAAC;QAClB,WAAW,EAAE,CAAC,YAAY,CAAC;QAC3B,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,QAAQ;QAC1C,OAAO,EAAE,UAAU;QACnB,QAAQ;QACR,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK;QACvC,MAAM,EAAE;YACN,EAAE,EAAE,qBAAqB;SAC1B;QACD,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM;QAC9B,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAErC,OAAO;QACL,UAAU;QACV,UAAU,EAAE,IAAI,CAAC,IAAI;KACtB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * esbuild configuration for the CLI bundle.\n * Bundles the generated CLI entry point with commander.js inlined.\n */\n\nimport * as path from 'path';\nimport { FrontmcpExecConfig } from '../config';\n\nexport interface CliBundleResult {\n bundlePath: string;\n bundleSize: number;\n}\n\n/**\n * Bundle the generated CLI entry with esbuild.\n * Commander.js and runtime modules are inlined; the server bundle is external\n * unless selfContained mode is enabled (for SEA builds).\n */\nexport async function bundleCliWithEsbuild(\n cliEntryPath: string,\n outDir: string,\n config: FrontmcpExecConfig,\n options?: { selfContained?: boolean },\n): Promise<CliBundleResult> {\n let esbuild: typeof import('esbuild');\n try {\n esbuild = require('esbuild');\n } catch {\n throw new Error(\n 'esbuild is required for CLI builds. Install it: npm install -D esbuild',\n );\n }\n\n const cliBundleName = `${config.name}-cli.bundle.js`;\n const bundlePath = path.join(outDir, cliBundleName);\n const selfContained = options?.selfContained ?? false;\n\n // The server bundle is loaded via require() at runtime — keep external\n // unless selfContained mode where everything is inlined for SEA\n const serverBundleName = `${config.name}.bundle.js`;\n\n const external = selfContained\n ? [\n // Only true native addons and optional peer deps stay external in self-contained mode\n 'better-sqlite3',\n 'fsevents',\n '@vercel/kv',\n '@frontmcp/storage-sqlite',\n '@enclave-vm/core',\n ...(config.dependencies?.nativeAddons || []),\n ]\n : [\n `./${serverBundleName}`,\n '@frontmcp/sdk',\n 'better-sqlite3',\n 'fsevents',\n '@vercel/kv',\n '@frontmcp/storage-sqlite',\n '@enclave-vm/core',\n ...(config.dependencies?.nativeAddons || []),\n ...(config.esbuild?.external || []),\n ];\n\n await esbuild.build({\n entryPoints: [cliEntryPath],\n bundle: true,\n platform: 'node',\n format: 'cjs',\n target: config.esbuild?.target || 'node22',\n outfile: bundlePath,\n external,\n keepNames: true,\n treeShaking: true,\n minify: config.esbuild?.minify ?? false,\n banner: {\n js: '#!/usr/bin/env node',\n },\n define: config.esbuild?.define,\n sourcemap: false,\n logLevel: 'warning',\n });\n\n const fs = require('fs');\n const stat = fs.statSync(bundlePath);\n\n return {\n bundlePath,\n bundleSize: stat.size,\n };\n}\n"]}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Credential store for CLI executables.
3
+ * Generates runtime module code for secure credential storage with
4
+ * platform-aware backends: macOS Keychain, Linux secret-tool, encrypted file fallback.
5
+ */
6
+ export interface CredentialBlob {
7
+ token: string;
8
+ refreshToken?: string;
9
+ expiresAt?: string;
10
+ user?: string;
11
+ metadata?: Record<string, unknown>;
12
+ }
13
+ export interface CredentialStore {
14
+ get(session: string): Promise<CredentialBlob | null>;
15
+ set(session: string, blob: CredentialBlob): Promise<void>;
16
+ delete(session: string): Promise<boolean>;
17
+ list(): Promise<string[]>;
18
+ }
19
+ /**
20
+ * Generate the credential-store runtime module source for embedding in CLI bundle.
21
+ */
22
+ export declare function generateCredentialStoreSource(appName: string): string;
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /**
3
+ * Credential store for CLI executables.
4
+ * Generates runtime module code for secure credential storage with
5
+ * platform-aware backends: macOS Keychain, Linux secret-tool, encrypted file fallback.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.generateCredentialStoreSource = generateCredentialStoreSource;
9
+ /**
10
+ * Generate the credential-store runtime module source for embedding in CLI bundle.
11
+ */
12
+ function generateCredentialStoreSource(appName) {
13
+ return `
14
+ 'use strict';
15
+
16
+ var crypto = require('crypto');
17
+ var os = require('os');
18
+ var path = require('path');
19
+ var fs = require('fs');
20
+ var childProcess = require('child_process');
21
+
22
+ var APP_NAME = ${JSON.stringify(appName)};
23
+ var CRED_DIR = path.join(os.homedir(), '.frontmcp', 'apps', APP_NAME, 'credentials');
24
+
25
+ function ensureCredDir() {
26
+ fs.mkdirSync(CRED_DIR, { recursive: true });
27
+ }
28
+
29
+ function runCmd(cmd, args, input) {
30
+ return new Promise(function(resolve, reject) {
31
+ var proc = childProcess.spawn(cmd, args, { stdio: ['pipe', 'pipe', 'pipe'] });
32
+ var stdout = '';
33
+ var stderr = '';
34
+ proc.stdout.on('data', function(d) { stdout += d; });
35
+ proc.stderr.on('data', function(d) { stderr += d; });
36
+ if (input) { proc.stdin.write(input); proc.stdin.end(); }
37
+ proc.on('close', function(code) {
38
+ if (code === 0) resolve(stdout.trim());
39
+ else reject(new Error(stderr.trim() || 'Command failed: ' + cmd + ' ' + args.join(' ')));
40
+ });
41
+ });
42
+ }
43
+
44
+ function deriveKey() {
45
+ var hostname = os.hostname();
46
+ var salt = APP_NAME + ':' + hostname;
47
+ return crypto.createHash('sha256').update(salt).digest();
48
+ }
49
+
50
+ function encryptBlob(data) {
51
+ var key = deriveKey();
52
+ var iv = crypto.randomBytes(12);
53
+ var cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
54
+ var encrypted = Buffer.concat([cipher.update(JSON.stringify(data), 'utf8'), cipher.final()]);
55
+ var tag = cipher.getAuthTag();
56
+ return Buffer.concat([iv, tag, encrypted]).toString('base64');
57
+ }
58
+
59
+ function decryptBlob(encoded) {
60
+ var key = deriveKey();
61
+ var buf = Buffer.from(encoded, 'base64');
62
+ var iv = buf.subarray(0, 12);
63
+ var tag = buf.subarray(12, 28);
64
+ var encrypted = buf.subarray(28);
65
+ var decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
66
+ decipher.setAuthTag(tag);
67
+ var decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
68
+ return JSON.parse(decrypted.toString('utf8'));
69
+ }
70
+
71
+ // macOS Keychain backend
72
+ var KeychainStore = {
73
+ get: async function(session) {
74
+ try {
75
+ var encoded = await runCmd('security', ['find-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session, '-w']);
76
+ return decryptBlob(encoded);
77
+ } catch (_) { return null; }
78
+ },
79
+ set: async function(session, blob) {
80
+ var encoded = encryptBlob(blob);
81
+ try { await runCmd('security', ['delete-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session]); } catch (_) { /* ok */ }
82
+ await runCmd('security', ['add-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session, '-w', encoded, '-U']);
83
+ },
84
+ delete: async function(session) {
85
+ try {
86
+ await runCmd('security', ['delete-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session]);
87
+ return true;
88
+ } catch (_) { return false; }
89
+ },
90
+ list: async function() {
91
+ try {
92
+ var out = await runCmd('security', ['dump-keychain']);
93
+ var matches = [];
94
+ var re = new RegExp('"svce"<blob>="frontmcp\\\\.' + APP_NAME.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&') + '"[\\\\s\\\\S]*?"acct"<blob>="([^"]*)"', 'g');
95
+ var m; while ((m = re.exec(out)) !== null) { matches.push(m[1]); }
96
+ return [...new Set(matches)];
97
+ } catch (_) { return []; }
98
+ }
99
+ };
100
+
101
+ // Encrypted file backend (fallback)
102
+ var FileStore = {
103
+ get: async function(session) {
104
+ var filePath = path.join(CRED_DIR, session + '.enc');
105
+ try {
106
+ var encoded = fs.readFileSync(filePath, 'utf8');
107
+ return decryptBlob(encoded);
108
+ } catch (_) { return null; }
109
+ },
110
+ set: async function(session, blob) {
111
+ ensureCredDir();
112
+ var encoded = encryptBlob(blob);
113
+ var filePath = path.join(CRED_DIR, session + '.enc');
114
+ fs.writeFileSync(filePath, encoded, { mode: 0o600 });
115
+ },
116
+ delete: async function(session) {
117
+ var filePath = path.join(CRED_DIR, session + '.enc');
118
+ try { fs.unlinkSync(filePath); return true; } catch (_) { return false; }
119
+ },
120
+ list: async function() {
121
+ ensureCredDir();
122
+ try {
123
+ return fs.readdirSync(CRED_DIR)
124
+ .filter(function(f) { return f.endsWith('.enc'); })
125
+ .map(function(f) { return f.replace(/\\.enc$/, ''); });
126
+ } catch (_) { return []; }
127
+ }
128
+ };
129
+
130
+ function createCredentialStore() {
131
+ if (process.platform === 'darwin') {
132
+ return KeychainStore;
133
+ }
134
+ return FileStore;
135
+ }
136
+
137
+ module.exports = { createCredentialStore, encryptBlob, decryptBlob };
138
+ `.trim();
139
+ }
140
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/credential-store.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAoBH,sEA+HC;AAlID;;GAEG;AACH,SAAgB,6BAA6B,CAAC,OAAe;IAC3D,OAAO;;;;;;;;;iBASQ,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoHvC,CAAC,IAAI,EAAE,CAAC;AACT,CAAC","sourcesContent":["/**\n * Credential store for CLI executables.\n * Generates runtime module code for secure credential storage with\n * platform-aware backends: macOS Keychain, Linux secret-tool, encrypted file fallback.\n */\n\nexport interface CredentialBlob {\n token: string;\n refreshToken?: string;\n expiresAt?: string;\n user?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CredentialStore {\n get(session: string): Promise<CredentialBlob | null>;\n set(session: string, blob: CredentialBlob): Promise<void>;\n delete(session: string): Promise<boolean>;\n list(): Promise<string[]>;\n}\n\n/**\n * Generate the credential-store runtime module source for embedding in CLI bundle.\n */\nexport function generateCredentialStoreSource(appName: string): string {\n return `\n'use strict';\n\nvar crypto = require('crypto');\nvar os = require('os');\nvar path = require('path');\nvar fs = require('fs');\nvar childProcess = require('child_process');\n\nvar APP_NAME = ${JSON.stringify(appName)};\nvar CRED_DIR = path.join(os.homedir(), '.frontmcp', 'apps', APP_NAME, 'credentials');\n\nfunction ensureCredDir() {\n fs.mkdirSync(CRED_DIR, { recursive: true });\n}\n\nfunction runCmd(cmd, args, input) {\n return new Promise(function(resolve, reject) {\n var proc = childProcess.spawn(cmd, args, { stdio: ['pipe', 'pipe', 'pipe'] });\n var stdout = '';\n var stderr = '';\n proc.stdout.on('data', function(d) { stdout += d; });\n proc.stderr.on('data', function(d) { stderr += d; });\n if (input) { proc.stdin.write(input); proc.stdin.end(); }\n proc.on('close', function(code) {\n if (code === 0) resolve(stdout.trim());\n else reject(new Error(stderr.trim() || 'Command failed: ' + cmd + ' ' + args.join(' ')));\n });\n });\n}\n\nfunction deriveKey() {\n var hostname = os.hostname();\n var salt = APP_NAME + ':' + hostname;\n return crypto.createHash('sha256').update(salt).digest();\n}\n\nfunction encryptBlob(data) {\n var key = deriveKey();\n var iv = crypto.randomBytes(12);\n var cipher = crypto.createCipheriv('aes-256-gcm', key, iv);\n var encrypted = Buffer.concat([cipher.update(JSON.stringify(data), 'utf8'), cipher.final()]);\n var tag = cipher.getAuthTag();\n return Buffer.concat([iv, tag, encrypted]).toString('base64');\n}\n\nfunction decryptBlob(encoded) {\n var key = deriveKey();\n var buf = Buffer.from(encoded, 'base64');\n var iv = buf.subarray(0, 12);\n var tag = buf.subarray(12, 28);\n var encrypted = buf.subarray(28);\n var decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);\n decipher.setAuthTag(tag);\n var decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);\n return JSON.parse(decrypted.toString('utf8'));\n}\n\n// macOS Keychain backend\nvar KeychainStore = {\n get: async function(session) {\n try {\n var encoded = await runCmd('security', ['find-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session, '-w']);\n return decryptBlob(encoded);\n } catch (_) { return null; }\n },\n set: async function(session, blob) {\n var encoded = encryptBlob(blob);\n try { await runCmd('security', ['delete-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session]); } catch (_) { /* ok */ }\n await runCmd('security', ['add-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session, '-w', encoded, '-U']);\n },\n delete: async function(session) {\n try {\n await runCmd('security', ['delete-generic-password', '-s', 'frontmcp.' + APP_NAME, '-a', session]);\n return true;\n } catch (_) { return false; }\n },\n list: async function() {\n try {\n var out = await runCmd('security', ['dump-keychain']);\n var matches = [];\n var re = new RegExp('\"svce\"<blob>=\"frontmcp\\\\\\\\.' + APP_NAME.replace(/[.*+?^\\${}()|[\\\\]\\\\\\\\]/g, '\\\\\\\\$&') + '\"[\\\\\\\\s\\\\\\\\S]*?\"acct\"<blob>=\"([^\"]*)\"', 'g');\n var m; while ((m = re.exec(out)) !== null) { matches.push(m[1]); }\n return [...new Set(matches)];\n } catch (_) { return []; }\n }\n};\n\n// Encrypted file backend (fallback)\nvar FileStore = {\n get: async function(session) {\n var filePath = path.join(CRED_DIR, session + '.enc');\n try {\n var encoded = fs.readFileSync(filePath, 'utf8');\n return decryptBlob(encoded);\n } catch (_) { return null; }\n },\n set: async function(session, blob) {\n ensureCredDir();\n var encoded = encryptBlob(blob);\n var filePath = path.join(CRED_DIR, session + '.enc');\n fs.writeFileSync(filePath, encoded, { mode: 0o600 });\n },\n delete: async function(session) {\n var filePath = path.join(CRED_DIR, session + '.enc');\n try { fs.unlinkSync(filePath); return true; } catch (_) { return false; }\n },\n list: async function() {\n ensureCredDir();\n try {\n return fs.readdirSync(CRED_DIR)\n .filter(function(f) { return f.endsWith('.enc'); })\n .map(function(f) { return f.replace(/\\\\.enc$/, ''); });\n } catch (_) { return []; }\n }\n};\n\nfunction createCredentialStore() {\n if (process.platform === 'darwin') {\n return KeychainStore;\n }\n return FileStore;\n}\n\nmodule.exports = { createCredentialStore, encryptBlob, decryptBlob };\n`.trim();\n}\n"]}