skybridge 0.0.0-dev.c2b2b14 → 0.0.0-dev.c2c0f98

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 (504) hide show
  1. package/README.md +126 -116
  2. package/dist/cli/build-helpers.d.ts +11 -0
  3. package/dist/cli/build-helpers.js +107 -0
  4. package/dist/cli/build-helpers.js.map +1 -0
  5. package/dist/cli/build-helpers.test.js +132 -0
  6. package/dist/cli/build-helpers.test.js.map +1 -0
  7. package/dist/cli/build-steps.d.ts +2 -0
  8. package/dist/cli/build-steps.js +73 -0
  9. package/dist/cli/build-steps.js.map +1 -0
  10. package/dist/cli/build-steps.test.js +52 -0
  11. package/dist/cli/build-steps.test.js.map +1 -0
  12. package/dist/cli/detect-port.d.ts +2 -2
  13. package/dist/cli/detect-port.js +9 -20
  14. package/dist/cli/detect-port.js.map +1 -1
  15. package/dist/cli/header.d.ts +1 -1
  16. package/dist/cli/header.js +1 -1
  17. package/dist/cli/header.js.map +1 -1
  18. package/dist/cli/resolve-skybridge-config.d.ts +5 -0
  19. package/dist/cli/resolve-skybridge-config.js +18 -0
  20. package/dist/cli/resolve-skybridge-config.js.map +1 -0
  21. package/dist/cli/run-command.js.map +1 -1
  22. package/dist/cli/run-plain.d.ts +18 -0
  23. package/dist/cli/run-plain.js +89 -0
  24. package/dist/cli/run-plain.js.map +1 -0
  25. package/dist/cli/telemetry.js.map +1 -1
  26. package/dist/cli/tunnel-control-server.d.ts +9 -0
  27. package/dist/cli/tunnel-control-server.js +31 -0
  28. package/dist/cli/tunnel-control-server.js.map +1 -0
  29. package/dist/cli/tunnel-control-server.test.js +39 -0
  30. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  31. package/dist/cli/tunnel-handler.d.ts +3 -0
  32. package/dist/cli/tunnel-handler.js +48 -0
  33. package/dist/cli/tunnel-handler.js.map +1 -0
  34. package/dist/cli/tunnel-handler.test.js +105 -0
  35. package/dist/cli/tunnel-handler.test.js.map +1 -0
  36. package/dist/cli/tunnel.d.ts +57 -0
  37. package/dist/cli/tunnel.js +154 -0
  38. package/dist/cli/tunnel.js.map +1 -0
  39. package/dist/cli/tunnel.test.js +190 -0
  40. package/dist/cli/tunnel.test.js.map +1 -0
  41. package/dist/cli/types.d.ts +5 -0
  42. package/dist/cli/types.js +2 -0
  43. package/dist/cli/types.js.map +1 -0
  44. package/dist/cli/use-execute-steps.d.ts +1 -1
  45. package/dist/cli/use-execute-steps.js.map +1 -1
  46. package/dist/cli/use-messages.d.ts +3 -0
  47. package/dist/cli/use-messages.js +11 -0
  48. package/dist/cli/use-messages.js.map +1 -0
  49. package/dist/cli/use-nodemon.d.ts +16 -7
  50. package/dist/cli/use-nodemon.js +74 -66
  51. package/dist/cli/use-nodemon.js.map +1 -1
  52. package/dist/cli/use-open-browser.d.ts +1 -0
  53. package/dist/cli/use-open-browser.js +44 -0
  54. package/dist/cli/use-open-browser.js.map +1 -0
  55. package/dist/cli/use-tunnel.d.ts +14 -0
  56. package/dist/cli/use-tunnel.js +131 -0
  57. package/dist/cli/use-tunnel.js.map +1 -0
  58. package/dist/cli/use-typescript-check.d.ts +9 -2
  59. package/dist/cli/use-typescript-check.js +89 -51
  60. package/dist/cli/use-typescript-check.js.map +1 -1
  61. package/dist/commands/build.d.ts +0 -3
  62. package/dist/commands/build.js +3 -18
  63. package/dist/commands/build.js.map +1 -1
  64. package/dist/commands/create.d.ts +9 -0
  65. package/dist/commands/create.js +30 -0
  66. package/dist/commands/create.js.map +1 -0
  67. package/dist/commands/dev.d.ts +4 -1
  68. package/dist/commands/dev.js +94 -8
  69. package/dist/commands/dev.js.map +1 -1
  70. package/dist/commands/start.js +13 -10
  71. package/dist/commands/start.js.map +1 -1
  72. package/dist/commands/telemetry/disable.js.map +1 -1
  73. package/dist/commands/telemetry/enable.js.map +1 -1
  74. package/dist/commands/telemetry/status.js.map +1 -1
  75. package/dist/context-warnings.d.ts +5 -0
  76. package/dist/context-warnings.js +31 -0
  77. package/dist/context-warnings.js.map +1 -0
  78. package/dist/context-warnings.test.js +28 -0
  79. package/dist/context-warnings.test.js.map +1 -0
  80. package/dist/server/app.d.ts +143 -0
  81. package/dist/server/app.js +229 -0
  82. package/dist/server/app.js.map +1 -0
  83. package/dist/server/asset-base-url-transform-plugin.d.ts +6 -6
  84. package/dist/server/asset-base-url-transform-plugin.js +25 -11
  85. package/dist/server/asset-base-url-transform-plugin.js.map +1 -1
  86. package/dist/server/asset-base-url-transform-plugin.test.js +92 -14
  87. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -1
  88. package/dist/server/auth/discovery.d.ts +33 -0
  89. package/dist/server/auth/discovery.js +56 -0
  90. package/dist/server/auth/discovery.js.map +1 -0
  91. package/dist/server/auth/discovery.test.d.ts +1 -0
  92. package/dist/server/auth/discovery.test.js +93 -0
  93. package/dist/server/auth/discovery.test.js.map +1 -0
  94. package/dist/server/auth/index.d.ts +30 -0
  95. package/dist/server/auth/index.js +2 -0
  96. package/dist/server/auth/index.js.map +1 -0
  97. package/dist/server/auth/providers/auth0.d.ts +40 -0
  98. package/dist/server/auth/providers/auth0.js +31 -0
  99. package/dist/server/auth/providers/auth0.js.map +1 -0
  100. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  101. package/dist/server/auth/providers/auth0.test.js +50 -0
  102. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  103. package/dist/server/auth/providers/authplane.d.ts +49 -0
  104. package/dist/server/auth/providers/authplane.js +57 -0
  105. package/dist/server/auth/providers/authplane.js.map +1 -0
  106. package/dist/server/auth/providers/authplane.test.d.ts +1 -0
  107. package/dist/server/auth/providers/authplane.test.js +140 -0
  108. package/dist/server/auth/providers/authplane.test.js.map +1 -0
  109. package/dist/server/auth/providers/clerk.d.ts +51 -0
  110. package/dist/server/auth/providers/clerk.js +19 -0
  111. package/dist/server/auth/providers/clerk.js.map +1 -0
  112. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  113. package/dist/server/auth/providers/clerk.test.js +30 -0
  114. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  115. package/dist/server/auth/providers/custom.d.ts +40 -0
  116. package/dist/server/auth/providers/custom.js +56 -0
  117. package/dist/server/auth/providers/custom.js.map +1 -0
  118. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  119. package/dist/server/auth/providers/custom.test.js +158 -0
  120. package/dist/server/auth/providers/custom.test.js.map +1 -0
  121. package/dist/server/auth/providers/descope.d.ts +44 -0
  122. package/dist/server/auth/providers/descope.js +44 -0
  123. package/dist/server/auth/providers/descope.js.map +1 -0
  124. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  125. package/dist/server/auth/providers/descope.test.js +62 -0
  126. package/dist/server/auth/providers/descope.test.js.map +1 -0
  127. package/dist/server/auth/providers/shared.d.ts +2 -0
  128. package/dist/server/auth/providers/shared.js +6 -0
  129. package/dist/server/auth/providers/shared.js.map +1 -0
  130. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  131. package/dist/server/auth/providers/shared.test.js +10 -0
  132. package/dist/server/auth/providers/shared.test.js.map +1 -0
  133. package/dist/server/auth/providers/stytch.d.ts +25 -0
  134. package/dist/server/auth/providers/stytch.js +16 -0
  135. package/dist/server/auth/providers/stytch.js.map +1 -0
  136. package/dist/server/auth/providers/verify-spy.d.ts +12 -0
  137. package/dist/server/auth/providers/verify-spy.js +21 -0
  138. package/dist/server/auth/providers/verify-spy.js.map +1 -0
  139. package/dist/server/auth/providers/workos.d.ts +33 -0
  140. package/dist/server/auth/providers/workos.js +15 -0
  141. package/dist/server/auth/providers/workos.js.map +1 -0
  142. package/dist/server/auth/security-schemes.d.ts +23 -0
  143. package/dist/server/auth/security-schemes.js +64 -0
  144. package/dist/server/auth/security-schemes.js.map +1 -0
  145. package/dist/server/auth/security-schemes.test.d.ts +1 -0
  146. package/dist/server/auth/security-schemes.test.js +99 -0
  147. package/dist/server/auth/security-schemes.test.js.map +1 -0
  148. package/dist/server/auth/setup.d.ts +6 -0
  149. package/dist/server/auth/setup.js +91 -0
  150. package/dist/server/auth/setup.js.map +1 -0
  151. package/dist/server/auth/setup.test.d.ts +1 -0
  152. package/dist/server/auth/setup.test.js +512 -0
  153. package/dist/server/auth/setup.test.js.map +1 -0
  154. package/dist/server/auth/verify.d.ts +46 -0
  155. package/dist/server/auth/verify.js +62 -0
  156. package/dist/server/auth/verify.js.map +1 -0
  157. package/dist/server/auth/verify.test.d.ts +1 -0
  158. package/dist/server/auth/verify.test.js +149 -0
  159. package/dist/server/auth/verify.test.js.map +1 -0
  160. package/dist/server/auth-extra.test-d.d.ts +1 -0
  161. package/dist/server/auth-extra.test-d.js +71 -0
  162. package/dist/server/auth-extra.test-d.js.map +1 -0
  163. package/dist/server/auth.d.ts +57 -0
  164. package/dist/server/auth.js +27 -0
  165. package/dist/server/auth.js.map +1 -0
  166. package/dist/server/build-manifest.test.d.ts +1 -0
  167. package/dist/server/build-manifest.test.js +28 -0
  168. package/dist/server/build-manifest.test.js.map +1 -0
  169. package/dist/server/content-helpers.d.ts +67 -0
  170. package/dist/server/content-helpers.js +79 -0
  171. package/dist/server/content-helpers.js.map +1 -0
  172. package/dist/server/content-helpers.test.d.ts +1 -0
  173. package/dist/server/content-helpers.test.js +70 -0
  174. package/dist/server/content-helpers.test.js.map +1 -0
  175. package/dist/server/express.d.ts +18 -5
  176. package/dist/server/express.js +60 -43
  177. package/dist/server/express.js.map +1 -1
  178. package/dist/server/express.test.js +470 -25
  179. package/dist/server/express.test.js.map +1 -1
  180. package/dist/server/file-ref.d.ts +28 -0
  181. package/dist/server/file-ref.js +27 -0
  182. package/dist/server/file-ref.js.map +1 -0
  183. package/dist/server/host.d.ts +2 -0
  184. package/dist/server/host.js +11 -0
  185. package/dist/server/host.js.map +1 -0
  186. package/dist/server/host.test.d.ts +1 -0
  187. package/dist/server/host.test.js +13 -0
  188. package/dist/server/host.test.js.map +1 -0
  189. package/dist/server/index.d.ts +21 -4
  190. package/dist/server/index.js +16 -2
  191. package/dist/server/index.js.map +1 -1
  192. package/dist/server/inferUtilityTypes.d.ts +6 -6
  193. package/dist/server/inferUtilityTypes.js.map +1 -1
  194. package/dist/server/mcp-errors.test.d.ts +1 -0
  195. package/dist/server/mcp-errors.test.js +37 -0
  196. package/dist/server/mcp-errors.test.js.map +1 -0
  197. package/dist/server/metric.d.ts +14 -0
  198. package/dist/server/metric.js +62 -0
  199. package/dist/server/metric.js.map +1 -0
  200. package/dist/server/middleware.d.ts +80 -14
  201. package/dist/server/middleware.js +33 -0
  202. package/dist/server/middleware.js.map +1 -1
  203. package/dist/server/middleware.test-d.js +42 -19
  204. package/dist/server/middleware.test-d.js.map +1 -1
  205. package/dist/server/middleware.test.js +240 -71
  206. package/dist/server/middleware.test.js.map +1 -1
  207. package/dist/server/register-tool.test.d.ts +1 -0
  208. package/dist/server/register-tool.test.js +23 -0
  209. package/dist/server/register-tool.test.js.map +1 -0
  210. package/dist/server/requestOrigin.d.ts +7 -0
  211. package/dist/server/requestOrigin.js +25 -0
  212. package/dist/server/requestOrigin.js.map +1 -0
  213. package/dist/server/server.d.ts +401 -87
  214. package/dist/server/server.js +529 -194
  215. package/dist/server/server.js.map +1 -1
  216. package/dist/server/skills-integration.test.d.ts +1 -0
  217. package/dist/server/skills-integration.test.js +79 -0
  218. package/dist/server/skills-integration.test.js.map +1 -0
  219. package/dist/server/skills.d.ts +27 -0
  220. package/dist/server/skills.js +188 -0
  221. package/dist/server/skills.js.map +1 -0
  222. package/dist/server/skills.test.d.ts +1 -0
  223. package/dist/server/skills.test.js +243 -0
  224. package/dist/server/skills.test.js.map +1 -0
  225. package/dist/server/templateHelper.d.ts +5 -8
  226. package/dist/server/templateHelper.js +3 -22
  227. package/dist/server/templateHelper.js.map +1 -1
  228. package/dist/server/templates.generated.d.ts +4 -0
  229. package/dist/server/templates.generated.js +47 -0
  230. package/dist/server/templates.generated.js.map +1 -0
  231. package/dist/server/tool-extra.test.d.ts +1 -0
  232. package/dist/server/tool-extra.test.js +72 -0
  233. package/dist/server/tool-extra.test.js.map +1 -0
  234. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  235. package/dist/server/tunnel-proxy-router.js +110 -0
  236. package/dist/server/tunnel-proxy-router.js.map +1 -0
  237. package/dist/server/tunnel-proxy-router.test.d.ts +1 -0
  238. package/dist/server/tunnel-proxy-router.test.js +229 -0
  239. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  240. package/dist/server/view-name.test-d.d.ts +1 -0
  241. package/dist/server/view-name.test-d.js +8 -0
  242. package/dist/server/view-name.test-d.js.map +1 -0
  243. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  244. package/dist/server/view-resource-resolution.test.js +172 -0
  245. package/dist/server/view-resource-resolution.test.js.map +1 -0
  246. package/dist/server/viewsDevServer.d.ts +14 -0
  247. package/dist/server/viewsDevServer.js +48 -0
  248. package/dist/server/viewsDevServer.js.map +1 -0
  249. package/dist/standard-schema.d.ts +3 -0
  250. package/dist/standard-schema.js +2 -0
  251. package/dist/standard-schema.js.map +1 -0
  252. package/dist/test/utils.d.ts +21 -31
  253. package/dist/test/utils.js +55 -45
  254. package/dist/test/utils.js.map +1 -1
  255. package/dist/test/view.test.d.ts +1 -0
  256. package/dist/test/view.test.js +536 -0
  257. package/dist/test/view.test.js.map +1 -0
  258. package/dist/version.d.ts +1 -0
  259. package/dist/version.js +3 -0
  260. package/dist/version.js.map +1 -0
  261. package/dist/views/index.d.ts +3 -0
  262. package/dist/views/index.js +3 -0
  263. package/dist/views/index.js.map +1 -0
  264. package/dist/views/scan-views.d.ts +16 -0
  265. package/dist/views/scan-views.js +88 -0
  266. package/dist/views/scan-views.js.map +1 -0
  267. package/dist/views/scan-views.test.d.ts +1 -0
  268. package/dist/views/scan-views.test.js +99 -0
  269. package/dist/views/scan-views.test.js.map +1 -0
  270. package/dist/views/validate-view.d.ts +1 -0
  271. package/dist/views/validate-view.js +9 -0
  272. package/dist/views/validate-view.js.map +1 -0
  273. package/dist/views/validate-view.test.d.ts +1 -0
  274. package/dist/views/validate-view.test.js +24 -0
  275. package/dist/views/validate-view.test.js.map +1 -0
  276. package/dist/web/bridges/adaptor.d.ts +51 -0
  277. package/dist/web/bridges/adaptor.js +327 -0
  278. package/dist/web/bridges/adaptor.js.map +1 -0
  279. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  280. package/dist/web/bridges/adaptor.test.js +225 -0
  281. package/dist/web/bridges/adaptor.test.js.map +1 -0
  282. package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -1
  283. package/dist/web/bridges/apps-sdk/bridge.js +15 -3
  284. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  285. package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
  286. package/dist/web/bridges/apps-sdk/index.js +0 -1
  287. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  288. package/dist/web/bridges/apps-sdk/types.d.ts +18 -6
  289. package/dist/web/bridges/apps-sdk/types.js.map +1 -1
  290. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +11 -0
  291. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +11 -0
  292. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  293. package/dist/web/bridges/get-adaptor.d.ts +7 -0
  294. package/dist/web/bridges/get-adaptor.js +9 -7
  295. package/dist/web/bridges/get-adaptor.js.map +1 -1
  296. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  297. package/dist/web/bridges/get-adaptor.test.js +32 -0
  298. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  299. package/dist/web/bridges/index.js.map +1 -1
  300. package/dist/web/bridges/mcp-app/bridge.d.ts +27 -31
  301. package/dist/web/bridges/mcp-app/bridge.js +111 -203
  302. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  303. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  304. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  305. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  306. package/dist/web/bridges/mcp-app/index.d.ts +0 -1
  307. package/dist/web/bridges/mcp-app/index.js +0 -1
  308. package/dist/web/bridges/mcp-app/index.js.map +1 -1
  309. package/dist/web/bridges/mcp-app/types.d.ts +2 -0
  310. package/dist/web/bridges/mcp-app/types.js.map +1 -1
  311. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +17 -3
  312. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +14 -2
  313. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  314. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -41
  315. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  316. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  317. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  318. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  319. package/dist/web/bridges/types.d.ts +131 -11
  320. package/dist/web/bridges/types.js +14 -1
  321. package/dist/web/bridges/types.js.map +1 -1
  322. package/dist/web/bridges/types.test.d.ts +1 -0
  323. package/dist/web/bridges/types.test.js +19 -0
  324. package/dist/web/bridges/types.test.js.map +1 -0
  325. package/dist/web/bridges/use-host-context.d.ts +5 -0
  326. package/dist/web/bridges/use-host-context.js +5 -0
  327. package/dist/web/bridges/use-host-context.js.map +1 -1
  328. package/dist/web/components/modal-provider.d.ts +1 -1
  329. package/dist/web/components/modal-provider.js +5 -6
  330. package/dist/web/components/modal-provider.js.map +1 -1
  331. package/dist/web/create-store.d.ts +26 -0
  332. package/dist/web/create-store.js +43 -3
  333. package/dist/web/create-store.js.map +1 -1
  334. package/dist/web/create-store.test.js +26 -23
  335. package/dist/web/create-store.test.js.map +1 -1
  336. package/dist/web/data-llm.d.ts +35 -2
  337. package/dist/web/data-llm.js +31 -3
  338. package/dist/web/data-llm.js.map +1 -1
  339. package/dist/web/data-llm.test.js +42 -28
  340. package/dist/web/data-llm.test.js.map +1 -1
  341. package/dist/web/generate-helpers.d.ts +32 -27
  342. package/dist/web/generate-helpers.js +29 -24
  343. package/dist/web/generate-helpers.js.map +1 -1
  344. package/dist/web/generate-helpers.test-d.js +33 -31
  345. package/dist/web/generate-helpers.test-d.js.map +1 -1
  346. package/dist/web/generate-helpers.test.js +2 -2
  347. package/dist/web/generate-helpers.test.js.map +1 -1
  348. package/dist/web/helpers/state.d.ts +2 -2
  349. package/dist/web/helpers/state.js +11 -11
  350. package/dist/web/helpers/state.js.map +1 -1
  351. package/dist/web/helpers/state.test.js +9 -9
  352. package/dist/web/helpers/state.test.js.map +1 -1
  353. package/dist/web/hooks/index.d.ts +7 -2
  354. package/dist/web/hooks/index.js +7 -2
  355. package/dist/web/hooks/index.js.map +1 -1
  356. package/dist/web/hooks/test/utils.d.ts +7 -2
  357. package/dist/web/hooks/test/utils.js +18 -3
  358. package/dist/web/hooks/test/utils.js.map +1 -1
  359. package/dist/web/hooks/use-call-tool.d.ts +45 -0
  360. package/dist/web/hooks/use-call-tool.js +28 -0
  361. package/dist/web/hooks/use-call-tool.js.map +1 -1
  362. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -1
  363. package/dist/web/hooks/use-call-tool.test.js +64 -29
  364. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  365. package/dist/web/hooks/use-display-mode.d.ts +20 -0
  366. package/dist/web/hooks/use-display-mode.js +20 -0
  367. package/dist/web/hooks/use-display-mode.js.map +1 -1
  368. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -1
  369. package/dist/web/hooks/use-display-mode.test.js +57 -21
  370. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  371. package/dist/web/hooks/use-download.d.ts +3 -0
  372. package/dist/web/hooks/use-download.js +7 -0
  373. package/dist/web/hooks/use-download.js.map +1 -0
  374. package/dist/web/hooks/use-download.test.d.ts +1 -0
  375. package/dist/web/hooks/use-download.test.js +103 -0
  376. package/dist/web/hooks/use-download.test.js.map +1 -0
  377. package/dist/web/hooks/use-files.d.ts +34 -1
  378. package/dist/web/hooks/use-files.js +33 -0
  379. package/dist/web/hooks/use-files.js.map +1 -1
  380. package/dist/web/hooks/use-files.test.js +31 -3
  381. package/dist/web/hooks/use-files.test.js.map +1 -1
  382. package/dist/web/hooks/use-host.d.ts +22 -0
  383. package/dist/web/hooks/use-host.js +30 -0
  384. package/dist/web/hooks/use-host.js.map +1 -0
  385. package/dist/web/hooks/use-host.test.d.ts +1 -0
  386. package/dist/web/hooks/use-host.test.js +59 -0
  387. package/dist/web/hooks/use-host.test.js.map +1 -0
  388. package/dist/web/hooks/use-open-external.d.ts +17 -0
  389. package/dist/web/hooks/use-open-external.js +16 -0
  390. package/dist/web/hooks/use-open-external.js.map +1 -1
  391. package/dist/web/hooks/use-open-external.test.js +29 -14
  392. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  393. package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
  394. package/dist/web/hooks/use-register-view-tool.js +50 -0
  395. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  396. package/dist/web/hooks/use-request-close.d.ts +16 -0
  397. package/dist/web/hooks/use-request-close.js +21 -0
  398. package/dist/web/hooks/use-request-close.js.map +1 -0
  399. package/dist/web/hooks/use-request-close.test.d.ts +1 -0
  400. package/dist/web/hooks/use-request-close.test.js +47 -0
  401. package/dist/web/hooks/use-request-close.test.js.map +1 -0
  402. package/dist/web/hooks/use-request-modal.d.ts +16 -1
  403. package/dist/web/hooks/use-request-modal.js +19 -4
  404. package/dist/web/hooks/use-request-modal.js.map +1 -1
  405. package/dist/web/hooks/use-request-modal.test.js +16 -2
  406. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  407. package/dist/web/hooks/use-request-size.d.ts +20 -0
  408. package/dist/web/hooks/use-request-size.js +24 -0
  409. package/dist/web/hooks/use-request-size.js.map +1 -0
  410. package/dist/web/hooks/use-request-size.test.d.ts +1 -0
  411. package/dist/web/hooks/use-request-size.test.js +47 -0
  412. package/dist/web/hooks/use-request-size.test.js.map +1 -0
  413. package/dist/web/hooks/use-send-follow-up-message.d.ts +19 -1
  414. package/dist/web/hooks/use-send-follow-up-message.js +19 -2
  415. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
  416. package/dist/web/hooks/use-set-open-in-app-url.d.ts +17 -0
  417. package/dist/web/hooks/use-set-open-in-app-url.js +17 -0
  418. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -1
  419. package/dist/web/hooks/use-set-open-in-app-url.test.js +29 -9
  420. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  421. package/dist/web/hooks/use-tool-info.d.ts +46 -14
  422. package/dist/web/hooks/use-tool-info.js +29 -7
  423. package/dist/web/hooks/use-tool-info.js.map +1 -1
  424. package/dist/web/hooks/use-tool-info.test-d.js +11 -34
  425. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  426. package/dist/web/hooks/use-tool-info.test.js +42 -37
  427. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  428. package/dist/web/hooks/use-user.d.ts +5 -2
  429. package/dist/web/hooks/use-user.js +23 -4
  430. package/dist/web/hooks/use-user.js.map +1 -1
  431. package/dist/web/hooks/use-user.test.js +104 -28
  432. package/dist/web/hooks/use-user.test.js.map +1 -1
  433. package/dist/web/hooks/use-view-state.d.ts +25 -0
  434. package/dist/web/hooks/use-view-state.js +42 -0
  435. package/dist/web/hooks/use-view-state.js.map +1 -0
  436. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  437. package/dist/web/hooks/use-view-state.test.js +212 -0
  438. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  439. package/dist/web/hooks/use-viewport.d.ts +20 -0
  440. package/dist/web/hooks/use-viewport.js +21 -0
  441. package/dist/web/hooks/use-viewport.js.map +1 -0
  442. package/dist/web/hooks/use-viewport.test.d.ts +1 -0
  443. package/dist/web/hooks/use-viewport.test.js +109 -0
  444. package/dist/web/hooks/use-viewport.test.js.map +1 -0
  445. package/dist/web/index.d.ts +2 -2
  446. package/dist/web/index.js +1 -2
  447. package/dist/web/index.js.map +1 -1
  448. package/dist/web/mount-view.d.ts +21 -0
  449. package/dist/web/{mount-widget.js → mount-view.js} +22 -2
  450. package/dist/web/mount-view.js.map +1 -0
  451. package/dist/web/proxy.js.map +1 -1
  452. package/dist/web/types.d.ts +4 -0
  453. package/dist/web/types.js.map +1 -1
  454. package/package.json +47 -27
  455. package/tsconfig.base.json +5 -0
  456. package/dist/server/const.d.ts +0 -1
  457. package/dist/server/const.js +0 -2
  458. package/dist/server/const.js.map +0 -1
  459. package/dist/server/templates/development.hbs +0 -67
  460. package/dist/server/templates/production.hbs +0 -6
  461. package/dist/server/widgetsDevServer.d.ts +0 -12
  462. package/dist/server/widgetsDevServer.js +0 -63
  463. package/dist/server/widgetsDevServer.js.map +0 -1
  464. package/dist/test/widget.test.js +0 -261
  465. package/dist/test/widget.test.js.map +0 -1
  466. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -22
  467. package/dist/web/bridges/apps-sdk/adaptor.js +0 -75
  468. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  469. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -36
  470. package/dist/web/bridges/mcp-app/adaptor.js +0 -190
  471. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
  472. package/dist/web/hooks/use-layout.d.ts +0 -22
  473. package/dist/web/hooks/use-layout.js +0 -23
  474. package/dist/web/hooks/use-layout.js.map +0 -1
  475. package/dist/web/hooks/use-layout.test.js +0 -96
  476. package/dist/web/hooks/use-layout.test.js.map +0 -1
  477. package/dist/web/hooks/use-widget-state.d.ts +0 -4
  478. package/dist/web/hooks/use-widget-state.js +0 -32
  479. package/dist/web/hooks/use-widget-state.js.map +0 -1
  480. package/dist/web/hooks/use-widget-state.test.js +0 -64
  481. package/dist/web/hooks/use-widget-state.test.js.map +0 -1
  482. package/dist/web/mount-widget.d.ts +0 -1
  483. package/dist/web/mount-widget.js.map +0 -1
  484. package/dist/web/plugin/data-llm.test.js +0 -81
  485. package/dist/web/plugin/data-llm.test.js.map +0 -1
  486. package/dist/web/plugin/plugin.d.ts +0 -2
  487. package/dist/web/plugin/plugin.js +0 -54
  488. package/dist/web/plugin/plugin.js.map +0 -1
  489. package/dist/web/plugin/transform-data-llm.d.ts +0 -12
  490. package/dist/web/plugin/transform-data-llm.js +0 -96
  491. package/dist/web/plugin/transform-data-llm.js.map +0 -1
  492. package/dist/web/plugin/transform-data-llm.test.js +0 -81
  493. package/dist/web/plugin/transform-data-llm.test.js.map +0 -1
  494. package/dist/web/plugin/validate-widget.d.ts +0 -5
  495. package/dist/web/plugin/validate-widget.js +0 -27
  496. package/dist/web/plugin/validate-widget.js.map +0 -1
  497. package/dist/web/plugin/validate-widget.test.js +0 -42
  498. package/dist/web/plugin/validate-widget.test.js.map +0 -1
  499. /package/dist/{test/widget.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
  500. /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-steps.test.d.ts} +0 -0
  501. /package/dist/{web/hooks/use-widget-state.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
  502. /package/dist/{web/plugin/data-llm.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
  503. /package/dist/{web/plugin/transform-data-llm.test.d.ts → cli/tunnel.test.d.ts} +0 -0
  504. /package/dist/{web/plugin/validate-widget.test.d.ts → context-warnings.test.d.ts} +0 -0
@@ -0,0 +1,143 @@
1
+ import { type Implementation, type McpHttpHandler, type Server as SdkServer, type ServerOptions } from "@modelcontextprotocol/server";
2
+ import type { ErrorRequestHandler, Express, RequestHandler } from "express";
3
+ import type { ExtraClaims } from "./auth.js";
4
+ import { McpServer, type McpServerTypes, type SkybridgeServerOptions, type ToolDef } from "./server.js";
5
+ /**
6
+ * Everything a Skybridge app needs in one bag: the MCP implementation info
7
+ * (`name`, `version`, …), the SDK's {@link ServerOptions} (`capabilities`,
8
+ * `instructions`, …), and the Skybridge-specific options (`oauth`, `json`,
9
+ * `skills`).
10
+ */
11
+ export type SkybridgeConfig<TAuthExtra extends ExtraClaims = ExtraClaims> = Implementation & ServerOptions & SkybridgeServerOptions<TAuthExtra>;
12
+ /**
13
+ * The factory that declares an app's MCP surface. Called with a fresh
14
+ * {@link McpServer} for every request, it must **return** the chained server so
15
+ * `typeof app` carries the registered tool types.
16
+ */
17
+ export type SkybridgeSetup<TTools extends Record<string, ToolDef>, TAuthExtra extends ExtraClaims> = (server: McpServer<Record<never, ToolDef>, TAuthExtra>) => McpServer<TTools, TAuthExtra>;
18
+ /**
19
+ * A Skybridge app: the HTTP surface (Express, OAuth metadata, the `/mcp`
20
+ * route) plus a factory that builds the MCP server for each request.
21
+ *
22
+ * The factory runs once per request, so tools, resources, prompts and views
23
+ * are always registered on the instance that serves the request. It also runs
24
+ * once at construction time, which surfaces registration errors at boot and
25
+ * gives the OAuth layer the set of per-tool security schemes.
26
+ *
27
+ * @typeParam TTools - Accumulated tool registry, inferred from the server the
28
+ * factory returns. You almost never set this manually.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * export const app = new Skybridge(
33
+ * { name: "my-app", version: "1.0.0", capabilities: {} },
34
+ * (server) =>
35
+ * server.registerTool(
36
+ * {
37
+ * name: "search",
38
+ * inputSchema: { query: z.string() },
39
+ * view: { component: "search" },
40
+ * },
41
+ * async ({ query }) => ({ content: `Results for ${query}` }),
42
+ * ),
43
+ * );
44
+ *
45
+ * export type AppType = typeof app;
46
+ * ```
47
+ *
48
+ * @see https://docs.skybridge.tech/api-reference/mcp-server
49
+ */
50
+ export declare class Skybridge<TTools extends Record<string, ToolDef> = Record<never, ToolDef>, TAuthExtra extends ExtraClaims = ExtraClaims> {
51
+ readonly $types: McpServerTypes<TTools>;
52
+ private readonly serverInfo;
53
+ private readonly serverOptions;
54
+ private readonly skybridgeOptions;
55
+ private readonly setup;
56
+ private readonly expressApp;
57
+ private readonly errorMiddleware;
58
+ private readonly monitoringEntry;
59
+ private resolveResourceMetadataUrl?;
60
+ private cachedFetchHandler?;
61
+ constructor(config: SkybridgeConfig<TAuthExtra>, setup: SkybridgeSetup<TTools, TAuthExtra>);
62
+ /**
63
+ * The underlying Express app. Use this to extend the HTTP server with
64
+ * custom routes, middleware, or settings — e.g.
65
+ * `app.express.get("/health", ...)`.
66
+ *
67
+ * `express.json()` is pre-applied — tune it via the `json` config field,
68
+ * e.g. `new Skybridge({ name, version, json: { limit: "10mb" } }, setup)`.
69
+ * Register your handlers before `run()`; after `run()`, dev-mode middleware,
70
+ * the `/mcp` route, and the default error handler are appended in that order.
71
+ *
72
+ * Note: Alpic Cloud only routes traffic to `/mcp` — custom routes work
73
+ * locally and on self-hosted deployments.
74
+ */
75
+ get express(): Express;
76
+ /**
77
+ * The app's fetch handler for `/mcp`: a `Request` → `Response` function that
78
+ * builds a fresh MCP server per request. Memoized, so the same handler is
79
+ * reused across requests.
80
+ */
81
+ get fetchHandler(): McpHttpHandler;
82
+ /**
83
+ * Build a fresh server for one stateless HTTP request, as
84
+ * `createMcpHandler`'s factory contract requires: the factory runs again so
85
+ * the SDK's handler closures belong to the instance whose protocol era it
86
+ * stamps. Sharing one instance's handler maps instead would bind them to an
87
+ * instance that is never marked, pinning every request to the 2025 codec and
88
+ * letting concurrent callers overwrite each other's negotiated version.
89
+ */
90
+ createServerInstance(): SdkServer;
91
+ /**
92
+ * Connect a Skybridge app to an MCP transport. Use this when you're
93
+ * embedding Skybridge in a host that already manages its own transport
94
+ * (e.g. stdio for desktop apps); for HTTP, prefer {@link Skybridge.run}
95
+ * which sets the transport up for you.
96
+ */
97
+ connect(transport: Parameters<SdkServer["connect"]>[0]): Promise<void>;
98
+ /**
99
+ * Register Express middleware on the underlying app. Mirrors `app.use` —
100
+ * pass handlers directly or a path-prefixed handler list. Register before
101
+ * {@link Skybridge.run}; ordering matches Express.
102
+ *
103
+ * Note: Alpic Cloud only routes traffic to `/mcp`. Custom paths work
104
+ * locally and on self-hosted deployments.
105
+ */
106
+ use(...handlers: RequestHandler[]): this;
107
+ use(path: string, ...handlers: RequestHandler[]): this;
108
+ /**
109
+ * Register Express error-handling middleware to run after the built-in
110
+ * `/mcp` route (or your custom route). Use this to log or transform errors
111
+ * thrown by tool handlers before the default error handler responds.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * app.useOnError((err, _req, _res, next) => {
116
+ * logger.error(err);
117
+ * next(err);
118
+ * });
119
+ * ```
120
+ */
121
+ useOnError(...handlers: ErrorRequestHandler[]): this;
122
+ useOnError(path: string, ...handlers: ErrorRequestHandler[]): this;
123
+ /**
124
+ * Start the HTTP server. Listens on `process.env.__PORT` (default `3000`),
125
+ * mounts the `/mcp` route, and applies any custom Express middleware
126
+ * registered via {@link Skybridge.use} / {@link Skybridge.useOnError}.
127
+ *
128
+ * On Cloudflare Workers / workerd, returns an object exposing `fetch` so
129
+ * the runtime can bridge incoming requests to the Node HTTP server. On
130
+ * Vercel (`VERCEL === "1"`), returns the Express app directly so the
131
+ * serverless function entry can call it as a `(req, res)` handler. On
132
+ * Node, returns `undefined` once listening. When the process was spawned
133
+ * with an IPC channel, the bound port is reported to the parent as
134
+ * `{ type: "skybridge:listening", port }`, the readiness signal test runners
135
+ * wait on instead of polling.
136
+ */
137
+ run(): Promise<{
138
+ fetch: (...args: unknown[]) => unknown;
139
+ } | Express | undefined>;
140
+ private buildServer;
141
+ private middlewareEntries;
142
+ private instrumentHandlers;
143
+ }
@@ -0,0 +1,229 @@
1
+ import http from "node:http";
2
+ import { createMcpHandler, } from "@modelcontextprotocol/server";
3
+ import { setupOAuth } from "./auth/setup.js";
4
+ import { createApp, createBaseApp } from "./express.js";
5
+ import { createMiddlewareEntry } from "./metric.js";
6
+ import { buildMiddlewareChain, getHandlerMaps } from "./middleware.js";
7
+ import { McpServer, } from "./server.js";
8
+ /**
9
+ * A Skybridge app: the HTTP surface (Express, OAuth metadata, the `/mcp`
10
+ * route) plus a factory that builds the MCP server for each request.
11
+ *
12
+ * The factory runs once per request, so tools, resources, prompts and views
13
+ * are always registered on the instance that serves the request. It also runs
14
+ * once at construction time, which surfaces registration errors at boot and
15
+ * gives the OAuth layer the set of per-tool security schemes.
16
+ *
17
+ * @typeParam TTools - Accumulated tool registry, inferred from the server the
18
+ * factory returns. You almost never set this manually.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * export const app = new Skybridge(
23
+ * { name: "my-app", version: "1.0.0", capabilities: {} },
24
+ * (server) =>
25
+ * server.registerTool(
26
+ * {
27
+ * name: "search",
28
+ * inputSchema: { query: z.string() },
29
+ * view: { component: "search" },
30
+ * },
31
+ * async ({ query }) => ({ content: `Results for ${query}` }),
32
+ * ),
33
+ * );
34
+ *
35
+ * export type AppType = typeof app;
36
+ * ```
37
+ *
38
+ * @see https://docs.skybridge.tech/api-reference/mcp-server
39
+ */
40
+ export class Skybridge {
41
+ serverInfo;
42
+ serverOptions;
43
+ skybridgeOptions;
44
+ setup;
45
+ expressApp;
46
+ errorMiddleware = [];
47
+ monitoringEntry = createMiddlewareEntry();
48
+ resolveResourceMetadataUrl;
49
+ cachedFetchHandler;
50
+ constructor(config, setup) {
51
+ const { name, title, version, description, icons, websiteUrl, json, oauth, skills, ...serverOptions } = config;
52
+ this.serverInfo = { name, title, version, description, icons, websiteUrl };
53
+ this.serverOptions = serverOptions;
54
+ this.skybridgeOptions = { json, oauth, skills };
55
+ this.setup = setup;
56
+ const sample = this.buildServer();
57
+ this.expressApp = createBaseApp(json);
58
+ if (oauth) {
59
+ this.resolveResourceMetadataUrl = setupOAuth(this.expressApp, oauth, sample.securitySchemesByTool);
60
+ }
61
+ }
62
+ /**
63
+ * The underlying Express app. Use this to extend the HTTP server with
64
+ * custom routes, middleware, or settings — e.g.
65
+ * `app.express.get("/health", ...)`.
66
+ *
67
+ * `express.json()` is pre-applied — tune it via the `json` config field,
68
+ * e.g. `new Skybridge({ name, version, json: { limit: "10mb" } }, setup)`.
69
+ * Register your handlers before `run()`; after `run()`, dev-mode middleware,
70
+ * the `/mcp` route, and the default error handler are appended in that order.
71
+ *
72
+ * Note: Alpic Cloud only routes traffic to `/mcp` — custom routes work
73
+ * locally and on self-hosted deployments.
74
+ */
75
+ get express() {
76
+ return this.expressApp;
77
+ }
78
+ /**
79
+ * The app's fetch handler for `/mcp`: a `Request` → `Response` function that
80
+ * builds a fresh MCP server per request. Memoized, so the same handler is
81
+ * reused across requests.
82
+ */
83
+ get fetchHandler() {
84
+ this.cachedFetchHandler ??= createMcpHandler(() => this.createServerInstance(), {
85
+ onerror: (error) => {
86
+ console.error("Error handling MCP request:", error);
87
+ },
88
+ });
89
+ return this.cachedFetchHandler;
90
+ }
91
+ /**
92
+ * Build a fresh server for one stateless HTTP request, as
93
+ * `createMcpHandler`'s factory contract requires: the factory runs again so
94
+ * the SDK's handler closures belong to the instance whose protocol era it
95
+ * stamps. Sharing one instance's handler maps instead would bind them to an
96
+ * instance that is never marked, pinning every request to the 2025 codec and
97
+ * letting concurrent callers overwrite each other's negotiated version.
98
+ */
99
+ createServerInstance() {
100
+ const server = this.buildServer();
101
+ this.instrumentHandlers(server);
102
+ return server.server;
103
+ }
104
+ /**
105
+ * Connect a Skybridge app to an MCP transport. Use this when you're
106
+ * embedding Skybridge in a host that already manages its own transport
107
+ * (e.g. stdio for desktop apps); for HTTP, prefer {@link Skybridge.run}
108
+ * which sets the transport up for you.
109
+ */
110
+ async connect(transport) {
111
+ await this.createServerInstance().connect(transport);
112
+ }
113
+ use(pathOrHandler, ...handlers) {
114
+ // Branching is load-bearing: Express's `app.use` overloads can't be
115
+ // resolved against a `string | RequestHandler` union, so we narrow.
116
+ if (typeof pathOrHandler === "string") {
117
+ this.expressApp.use(pathOrHandler, ...handlers);
118
+ }
119
+ else {
120
+ this.expressApp.use(pathOrHandler, ...handlers);
121
+ }
122
+ return this;
123
+ }
124
+ useOnError(pathOrHandler, ...handlers) {
125
+ if (typeof pathOrHandler === "string") {
126
+ this.errorMiddleware.push({ path: pathOrHandler, handlers });
127
+ }
128
+ else {
129
+ this.errorMiddleware.push({ handlers: [pathOrHandler, ...handlers] });
130
+ }
131
+ return this;
132
+ }
133
+ /**
134
+ * Start the HTTP server. Listens on `process.env.__PORT` (default `3000`),
135
+ * mounts the `/mcp` route, and applies any custom Express middleware
136
+ * registered via {@link Skybridge.use} / {@link Skybridge.useOnError}.
137
+ *
138
+ * On Cloudflare Workers / workerd, returns an object exposing `fetch` so
139
+ * the runtime can bridge incoming requests to the Node HTTP server. On
140
+ * Vercel (`VERCEL === "1"`), returns the Express app directly so the
141
+ * serverless function entry can call it as a `(req, res)` handler. On
142
+ * Node, returns `undefined` once listening. When the process was spawned
143
+ * with an IPC channel, the bound port is reported to the parent as
144
+ * `{ type: "skybridge:listening", port }`, the readiness signal test runners
145
+ * wait on instead of polling.
146
+ */
147
+ async run() {
148
+ if (process.env.VERCEL === "1") {
149
+ // createApp only reads httpServer inside its dev-only branch
150
+ // (viewsDevServer); under VERCEL=1 + NODE_ENV=production it's a
151
+ // bare object passed to satisfy the required parameter.
152
+ const httpServer = http.createServer();
153
+ await createApp({
154
+ app: this,
155
+ httpServer,
156
+ errorMiddleware: this.errorMiddleware,
157
+ });
158
+ return this.expressApp;
159
+ }
160
+ const httpServer = http.createServer();
161
+ await createApp({
162
+ app: this,
163
+ httpServer,
164
+ errorMiddleware: this.errorMiddleware,
165
+ });
166
+ httpServer.on("request", this.expressApp);
167
+ const intendedPort = parseInt(process.env.__PORT ?? "3000", 10);
168
+ await new Promise((resolve, reject) => {
169
+ httpServer.on("error", (error) => {
170
+ console.error("Failed to start server:", error);
171
+ reject(error);
172
+ });
173
+ httpServer.listen(intendedPort, () => {
174
+ resolve();
175
+ });
176
+ });
177
+ const { port } = httpServer.address();
178
+ process.send?.({ type: "skybridge:listening", port });
179
+ // On workerd, bridge the Node http server to a Workers fetch handler.
180
+ // The specifier is held in a variable to sidestep tsc's module resolution
181
+ // (`cloudflare:node` only exists under wrangler/workerd).
182
+ if (typeof navigator !== "undefined" &&
183
+ navigator.userAgent === "Cloudflare-Workers") {
184
+ const cloudflareNode = "cloudflare:node";
185
+ const { httpServerHandler } = await import(cloudflareNode);
186
+ return httpServerHandler({ port });
187
+ }
188
+ const shutdown = () => {
189
+ // Drop both handlers so a second signal falls through to Node's default
190
+ // (force-quit on a second Ctrl+C while drain is hanging).
191
+ process.off("SIGTERM", shutdown);
192
+ process.off("SIGINT", shutdown);
193
+ httpServer.close(() => process.exit(0));
194
+ // Force exit if connections don't drain in time so the port is still
195
+ // released promptly (e.g. for nodemon restarts).
196
+ setTimeout(() => process.exit(0), 3000).unref();
197
+ };
198
+ process.on("SIGTERM", shutdown);
199
+ process.on("SIGINT", shutdown);
200
+ return undefined;
201
+ }
202
+ buildServer() {
203
+ const server = new McpServer(this.serverInfo, this.serverOptions, this.skybridgeOptions);
204
+ if (this.resolveResourceMetadataUrl) {
205
+ server.setResourceMetadataUrlResolver(this.resolveResourceMetadataUrl);
206
+ }
207
+ return this.setup(server);
208
+ }
209
+ middlewareEntries(server) {
210
+ return [
211
+ ...(this.monitoringEntry ? [this.monitoringEntry] : []),
212
+ ...server.protocolMiddlewareEntries(),
213
+ ];
214
+ }
215
+ instrumentHandlers(server) {
216
+ const entries = this.middlewareEntries(server);
217
+ const { requestHandlers, notificationHandlers } = getHandlerMaps(server.server);
218
+ const instrumentMap = (map, isNotification) => {
219
+ for (const [method, handler] of map) {
220
+ map.set(method, buildMiddlewareChain(method, isNotification, handler, entries));
221
+ }
222
+ const originalSet = map.set.bind(map);
223
+ map.set = (method, handler) => originalSet(method, buildMiddlewareChain(method, isNotification, handler, entries));
224
+ };
225
+ instrumentMap(requestHandlers, false);
226
+ instrumentMap(notificationHandlers, true);
227
+ }
228
+ }
229
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"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","sourcesContent":["import http from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport {\n createMcpHandler,\n type Implementation,\n type McpHttpHandler,\n type Server as SdkServer,\n type ServerOptions,\n} from \"@modelcontextprotocol/server\";\nimport type { ErrorRequestHandler, Express, RequestHandler } from \"express\";\nimport { type ResourceMetadataUrlResolver, setupOAuth } from \"./auth/setup.js\";\nimport type { ExtraClaims } from \"./auth.js\";\nimport { createApp, createBaseApp } from \"./express.js\";\nimport { createMiddlewareEntry } from \"./metric.js\";\nimport type { McpMiddlewareEntry } from \"./middleware.js\";\nimport { buildMiddlewareChain, getHandlerMaps } from \"./middleware.js\";\nimport {\n McpServer,\n type McpServerTypes,\n type SkybridgeServerOptions,\n type ToolDef,\n} from \"./server.js\";\n\ntype ErrorMiddlewareConfig = {\n path?: string;\n handlers: ErrorRequestHandler[];\n};\n\n/**\n * Everything a Skybridge app needs in one bag: the MCP implementation info\n * (`name`, `version`, …), the SDK's {@link ServerOptions} (`capabilities`,\n * `instructions`, …), and the Skybridge-specific options (`oauth`, `json`,\n * `skills`).\n */\nexport type SkybridgeConfig<TAuthExtra extends ExtraClaims = ExtraClaims> =\n Implementation & ServerOptions & SkybridgeServerOptions<TAuthExtra>;\n\n/**\n * The factory that declares an app's MCP surface. Called with a fresh\n * {@link McpServer} for every request, it must **return** the chained server so\n * `typeof app` carries the registered tool types.\n */\nexport type SkybridgeSetup<\n TTools extends Record<string, ToolDef>,\n TAuthExtra extends ExtraClaims,\n> = (\n server: McpServer<Record<never, ToolDef>, TAuthExtra>,\n) => McpServer<TTools, TAuthExtra>;\n\n/**\n * A Skybridge app: the HTTP surface (Express, OAuth metadata, the `/mcp`\n * route) plus a factory that builds the MCP server for each request.\n *\n * The factory runs once per request, so tools, resources, prompts and views\n * are always registered on the instance that serves the request. It also runs\n * once at construction time, which surfaces registration errors at boot and\n * gives the OAuth layer the set of per-tool security schemes.\n *\n * @typeParam TTools - Accumulated tool registry, inferred from the server the\n * factory returns. You almost never set this manually.\n *\n * @example\n * ```ts\n * export const app = new Skybridge(\n * { name: \"my-app\", version: \"1.0.0\", capabilities: {} },\n * (server) =>\n * server.registerTool(\n * {\n * name: \"search\",\n * inputSchema: { query: z.string() },\n * view: { component: \"search\" },\n * },\n * async ({ query }) => ({ content: `Results for ${query}` }),\n * ),\n * );\n *\n * export type AppType = typeof app;\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/mcp-server\n */\nexport class Skybridge<\n TTools extends Record<string, ToolDef> = Record<never, ToolDef>,\n TAuthExtra extends ExtraClaims = ExtraClaims,\n> {\n declare readonly $types: McpServerTypes<TTools>;\n private readonly serverInfo: Implementation;\n private readonly serverOptions: ServerOptions;\n private readonly skybridgeOptions: SkybridgeServerOptions<TAuthExtra>;\n private readonly setup: SkybridgeSetup<TTools, TAuthExtra>;\n private readonly expressApp: Express;\n private readonly errorMiddleware: ErrorMiddlewareConfig[] = [];\n private readonly monitoringEntry: McpMiddlewareEntry | null =\n createMiddlewareEntry();\n private resolveResourceMetadataUrl?: ResourceMetadataUrlResolver;\n private cachedFetchHandler?: McpHttpHandler;\n\n constructor(\n config: SkybridgeConfig<TAuthExtra>,\n setup: SkybridgeSetup<TTools, TAuthExtra>,\n ) {\n const {\n name,\n title,\n version,\n description,\n icons,\n websiteUrl,\n json,\n oauth,\n skills,\n ...serverOptions\n } = config;\n\n this.serverInfo = { name, title, version, description, icons, websiteUrl };\n this.serverOptions = serverOptions;\n this.skybridgeOptions = { json, oauth, skills };\n this.setup = setup;\n\n const sample = this.buildServer();\n\n this.expressApp = createBaseApp(json);\n if (oauth) {\n this.resolveResourceMetadataUrl = setupOAuth(\n this.expressApp,\n oauth,\n sample.securitySchemesByTool,\n );\n }\n }\n\n /**\n * The underlying Express app. Use this to extend the HTTP server with\n * custom routes, middleware, or settings — e.g.\n * `app.express.get(\"/health\", ...)`.\n *\n * `express.json()` is pre-applied — tune it via the `json` config field,\n * e.g. `new Skybridge({ name, version, json: { limit: \"10mb\" } }, setup)`.\n * Register your handlers before `run()`; after `run()`, dev-mode middleware,\n * the `/mcp` route, and the default error handler are appended in that order.\n *\n * Note: Alpic Cloud only routes traffic to `/mcp` — custom routes work\n * locally and on self-hosted deployments.\n */\n get express(): Express {\n return this.expressApp;\n }\n\n /**\n * The app's fetch handler for `/mcp`: a `Request` → `Response` function that\n * builds a fresh MCP server per request. Memoized, so the same handler is\n * reused across requests.\n */\n get fetchHandler(): McpHttpHandler {\n this.cachedFetchHandler ??= createMcpHandler(\n () => this.createServerInstance(),\n {\n onerror: (error) => {\n console.error(\"Error handling MCP request:\", error);\n },\n },\n );\n return this.cachedFetchHandler;\n }\n\n /**\n * Build a fresh server for one stateless HTTP request, as\n * `createMcpHandler`'s factory contract requires: the factory runs again so\n * the SDK's handler closures belong to the instance whose protocol era it\n * stamps. Sharing one instance's handler maps instead would bind them to an\n * instance that is never marked, pinning every request to the 2025 codec and\n * letting concurrent callers overwrite each other's negotiated version.\n */\n createServerInstance(): SdkServer {\n const server = this.buildServer();\n this.instrumentHandlers(server);\n return server.server;\n }\n\n /**\n * Connect a Skybridge app to an MCP transport. Use this when you're\n * embedding Skybridge in a host that already manages its own transport\n * (e.g. stdio for desktop apps); for HTTP, prefer {@link Skybridge.run}\n * which sets the transport up for you.\n */\n async connect(transport: Parameters<SdkServer[\"connect\"]>[0]): Promise<void> {\n await this.createServerInstance().connect(transport);\n }\n\n /**\n * Register Express middleware on the underlying app. Mirrors `app.use` —\n * pass handlers directly or a path-prefixed handler list. Register before\n * {@link Skybridge.run}; ordering matches Express.\n *\n * Note: Alpic Cloud only routes traffic to `/mcp`. Custom paths work\n * locally and on self-hosted deployments.\n */\n use(...handlers: RequestHandler[]): this;\n use(path: string, ...handlers: RequestHandler[]): this;\n use(\n pathOrHandler: string | RequestHandler,\n ...handlers: RequestHandler[]\n ): this {\n // Branching is load-bearing: Express's `app.use` overloads can't be\n // resolved against a `string | RequestHandler` union, so we narrow.\n if (typeof pathOrHandler === \"string\") {\n this.expressApp.use(pathOrHandler, ...handlers);\n } else {\n this.expressApp.use(pathOrHandler, ...handlers);\n }\n return this;\n }\n\n /**\n * Register Express error-handling middleware to run after the built-in\n * `/mcp` route (or your custom route). Use this to log or transform errors\n * thrown by tool handlers before the default error handler responds.\n *\n * @example\n * ```ts\n * app.useOnError((err, _req, _res, next) => {\n * logger.error(err);\n * next(err);\n * });\n * ```\n */\n useOnError(...handlers: ErrorRequestHandler[]): this;\n useOnError(path: string, ...handlers: ErrorRequestHandler[]): this;\n useOnError(\n pathOrHandler: string | ErrorRequestHandler,\n ...handlers: ErrorRequestHandler[]\n ): this {\n if (typeof pathOrHandler === \"string\") {\n this.errorMiddleware.push({ path: pathOrHandler, handlers });\n } else {\n this.errorMiddleware.push({ handlers: [pathOrHandler, ...handlers] });\n }\n return this;\n }\n\n /**\n * Start the HTTP server. Listens on `process.env.__PORT` (default `3000`),\n * mounts the `/mcp` route, and applies any custom Express middleware\n * registered via {@link Skybridge.use} / {@link Skybridge.useOnError}.\n *\n * On Cloudflare Workers / workerd, returns an object exposing `fetch` so\n * the runtime can bridge incoming requests to the Node HTTP server. On\n * Vercel (`VERCEL === \"1\"`), returns the Express app directly so the\n * serverless function entry can call it as a `(req, res)` handler. On\n * Node, returns `undefined` once listening. When the process was spawned\n * with an IPC channel, the bound port is reported to the parent as\n * `{ type: \"skybridge:listening\", port }`, the readiness signal test runners\n * wait on instead of polling.\n */\n async run(): Promise<\n { fetch: (...args: unknown[]) => unknown } | Express | undefined\n > {\n if (process.env.VERCEL === \"1\") {\n // createApp only reads httpServer inside its dev-only branch\n // (viewsDevServer); under VERCEL=1 + NODE_ENV=production it's a\n // bare object passed to satisfy the required parameter.\n const httpServer = http.createServer();\n await createApp({\n app: this,\n httpServer,\n errorMiddleware: this.errorMiddleware,\n });\n return this.expressApp;\n }\n\n const httpServer = http.createServer();\n\n await createApp({\n app: this,\n httpServer,\n errorMiddleware: this.errorMiddleware,\n });\n\n httpServer.on(\"request\", this.expressApp);\n const intendedPort = parseInt(process.env.__PORT ?? \"3000\", 10);\n await new Promise<void>((resolve, reject) => {\n httpServer.on(\"error\", (error: Error) => {\n console.error(\"Failed to start server:\", error);\n reject(error);\n });\n httpServer.listen(intendedPort, () => {\n resolve();\n });\n });\n\n const { port } = httpServer.address() as AddressInfo;\n process.send?.({ type: \"skybridge:listening\", port });\n\n // On workerd, bridge the Node http server to a Workers fetch handler.\n // The specifier is held in a variable to sidestep tsc's module resolution\n // (`cloudflare:node` only exists under wrangler/workerd).\n if (\n typeof navigator !== \"undefined\" &&\n navigator.userAgent === \"Cloudflare-Workers\"\n ) {\n const cloudflareNode = \"cloudflare:node\";\n const { httpServerHandler } = await import(cloudflareNode);\n return httpServerHandler({ port });\n }\n\n const shutdown = () => {\n // Drop both handlers so a second signal falls through to Node's default\n // (force-quit on a second Ctrl+C while drain is hanging).\n process.off(\"SIGTERM\", shutdown);\n process.off(\"SIGINT\", shutdown);\n httpServer.close(() => process.exit(0));\n // Force exit if connections don't drain in time so the port is still\n // released promptly (e.g. for nodemon restarts).\n setTimeout(() => process.exit(0), 3000).unref();\n };\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n return undefined;\n }\n\n private buildServer(): McpServer<TTools, TAuthExtra> {\n const server = new McpServer<Record<never, ToolDef>, TAuthExtra>(\n this.serverInfo,\n this.serverOptions,\n this.skybridgeOptions,\n );\n if (this.resolveResourceMetadataUrl) {\n server.setResourceMetadataUrlResolver(this.resolveResourceMetadataUrl);\n }\n return this.setup(server);\n }\n\n private middlewareEntries(\n server: McpServer<Record<never, ToolDef>, TAuthExtra>,\n ): McpMiddlewareEntry[] {\n return [\n ...(this.monitoringEntry ? [this.monitoringEntry] : []),\n ...server.protocolMiddlewareEntries(),\n ];\n }\n\n private instrumentHandlers(\n server: McpServer<Record<never, ToolDef>, TAuthExtra>,\n ): void {\n const entries = this.middlewareEntries(server);\n const { requestHandlers, notificationHandlers } = getHandlerMaps(\n server.server,\n );\n\n const instrumentMap = (\n map: Map<string, (...args: unknown[]) => Promise<unknown>>,\n isNotification: boolean,\n ) => {\n for (const [method, handler] of map) {\n map.set(\n method,\n buildMiddlewareChain(method, isNotification, handler, entries),\n );\n }\n const originalSet = map.set.bind(map);\n map.set = (\n method: string,\n handler: (...args: unknown[]) => Promise<unknown>,\n ) =>\n originalSet(\n method,\n buildMiddlewareChain(method, isNotification, handler, entries),\n );\n };\n\n instrumentMap(requestHandlers, false);\n instrumentMap(notificationHandlers, true);\n }\n}\n"]}
@@ -1,11 +1,11 @@
1
1
  import type { Plugin } from "vite";
2
+ export declare function isCssRequest(id: string): boolean;
2
3
  /**
3
- * Transforms asset import paths to use the development server base URL.
4
+ * Transforms asset import paths to resolve at runtime via `window.skybridge.serverUrl`,
5
+ * so they work both locally and behind tunnels.
4
6
  */
5
- export declare function assetBaseUrlTransform(code: string, devServerOrigin: string): string;
7
+ export declare function assetBaseUrlTransform(code: string): string;
6
8
  /**
7
- * Vite plugin that transforms asset import paths to use the development server base URL.
9
+ * Vite plugin that transforms asset import paths to resolve at runtime via `window.skybridge.serverUrl`.
8
10
  */
9
- export declare function assetBaseUrlTransformPlugin(options: {
10
- devServerOrigin: string;
11
- }): Plugin;
11
+ export declare function assetBaseUrlTransformPlugin(): Plugin;
@@ -1,26 +1,40 @@
1
+ // Mirrors Vite's own `isCSSRequest`: matches the css family of extensions
2
+ // either at the end of the id or right before the query string. Catches both
3
+ // plain `.css` requests and SFC style blocks (e.g. `Foo.vue?vue&type=style&lang.css`).
4
+ const CSS_LANGS_RE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
5
+ export function isCssRequest(id) {
6
+ return CSS_LANGS_RE.test(id);
7
+ }
1
8
  /**
2
- * Transforms asset import paths to use the development server base URL.
9
+ * Transforms asset import paths to resolve at runtime via `window.skybridge.serverUrl`,
10
+ * so they work both locally and behind tunnels.
3
11
  */
4
- export function assetBaseUrlTransform(code, devServerOrigin) {
5
- const assetStringPattern = /(?<!https?:\/\/)(["'`])(\/[^"'`]+\.(svg|png|jpeg|jpg|gif|webp|mp3|mp4|woff|woff2|ttf|eot))\1/g;
6
- code = code.replace(assetStringPattern, (_match, quote, assetPath) => {
7
- return `${quote}${devServerOrigin}${assetPath}${quote}`;
12
+ export function assetBaseUrlTransform(code) {
13
+ const assetStringPattern = /(?<!\bfrom\s)(?<!https?:\/\/)(["'`])(\/[^"'`]+\.(svg|png|jpeg|jpg|gif|webp|mp3|mp4|woff|woff2|ttf|eot))\1/g;
14
+ code = code.replace(assetStringPattern, (_match, _quote, assetPath) => {
15
+ return `(window.skybridge?.serverUrl ?? "") + "${assetPath}"`;
8
16
  });
9
17
  return code;
10
18
  }
11
19
  /**
12
- * Vite plugin that transforms asset import paths to use the development server base URL.
20
+ * Vite plugin that transforms asset import paths to resolve at runtime via `window.skybridge.serverUrl`.
13
21
  */
14
- export function assetBaseUrlTransformPlugin(options) {
15
- const { devServerOrigin } = options;
22
+ export function assetBaseUrlTransformPlugin() {
16
23
  return {
17
24
  name: "asset-base-url-transform",
18
- enforce: "pre",
19
- transform(code) {
25
+ transform(code, id) {
20
26
  if (!code) {
21
27
  return null;
22
28
  }
23
- const transformedCode = assetBaseUrlTransform(code, devServerOrigin);
29
+ // Vite serves CSS modules as JS that embeds the stylesheet as a string
30
+ // literal. Rewriting `url("/foo.woff2")` inside that string to a JS
31
+ // concatenation expression produces invalid CSS once it lands in a
32
+ // <style> tag. CSS asset URLs are already handled at build time by
33
+ // `experimental.renderBuiltUrl`, so skip CSS requests here.
34
+ if (isCssRequest(id)) {
35
+ return null;
36
+ }
37
+ const transformedCode = assetBaseUrlTransform(code);
24
38
  if (transformedCode === code) {
25
39
  return null;
26
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"asset-base-url-transform-plugin.js","sourceRoot":"","sources":["../../src/server/asset-base-url-transform-plugin.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,eAAuB;IAEvB,MAAM,kBAAkB,GACtB,+FAA+F,CAAC;IAElG,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;QACnE,OAAO,GAAG,KAAK,GAAG,eAAe,GAAG,SAAS,GAAG,KAAK,EAAE,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B,CAAC,OAE3C;IACC,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IAEpC,OAAO;QACL,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,KAAK;QACd,SAAS,CAAC,IAAI;YACZ,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,eAAe,GAAG,qBAAqB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAErE,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO;gBACL,IAAI,EAAE,eAAe;gBACrB,GAAG,EAAE,IAAI;aACV,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"asset-base-url-transform-plugin.js","sourceRoot":"","sources":["../../src/server/asset-base-url-transform-plugin.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,6EAA6E;AAC7E,uFAAuF;AACvF,MAAM,YAAY,GAChB,6DAA6D,CAAC;AAEhE,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,OAAO,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,kBAAkB,GACtB,4GAA4G,CAAC;IAE/G,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE;QACpE,OAAO,0CAA0C,SAAS,GAAG,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO;QACL,IAAI,EAAE,0BAA0B;QAChC,SAAS,CAAC,IAAI,EAAE,EAAE;YAChB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,IAAI,CAAC;YACd,CAAC;YAED,uEAAuE;YACvE,oEAAoE;YACpE,mEAAmE;YACnE,mEAAmE;YACnE,4DAA4D;YAC5D,IAAI,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,eAAe,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAEpD,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO;gBACL,IAAI,EAAE,eAAe;gBACrB,GAAG,EAAE,IAAI;aACV,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { Plugin } from \"vite\";\n\n// Mirrors Vite's own `isCSSRequest`: matches the css family of extensions\n// either at the end of the id or right before the query string. Catches both\n// plain `.css` requests and SFC style blocks (e.g. `Foo.vue?vue&type=style&lang.css`).\nconst CSS_LANGS_RE =\n /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/;\n\nexport function isCssRequest(id: string): boolean {\n return CSS_LANGS_RE.test(id);\n}\n\n/**\n * Transforms asset import paths to resolve at runtime via `window.skybridge.serverUrl`,\n * so they work both locally and behind tunnels.\n */\nexport function assetBaseUrlTransform(code: string): string {\n const assetStringPattern =\n /(?<!\\bfrom\\s)(?<!https?:\\/\\/)([\"'`])(\\/[^\"'`]+\\.(svg|png|jpeg|jpg|gif|webp|mp3|mp4|woff|woff2|ttf|eot))\\1/g;\n\n code = code.replace(assetStringPattern, (_match, _quote, assetPath) => {\n return `(window.skybridge?.serverUrl ?? \"\") + \"${assetPath}\"`;\n });\n\n return code;\n}\n\n/**\n * Vite plugin that transforms asset import paths to resolve at runtime via `window.skybridge.serverUrl`.\n */\nexport function assetBaseUrlTransformPlugin(): Plugin {\n return {\n name: \"asset-base-url-transform\",\n transform(code, id) {\n if (!code) {\n return null;\n }\n\n // Vite serves CSS modules as JS that embeds the stylesheet as a string\n // literal. Rewriting `url(\"/foo.woff2\")` inside that string to a JS\n // concatenation expression produces invalid CSS once it lands in a\n // <style> tag. CSS asset URLs are already handled at build time by\n // `experimental.renderBuiltUrl`, so skip CSS requests here.\n if (isCssRequest(id)) {\n return null;\n }\n\n const transformedCode = assetBaseUrlTransform(code);\n\n if (transformedCode === code) {\n return null;\n }\n\n return {\n code: transformedCode,\n map: null,\n };\n },\n };\n}\n"]}
@@ -1,27 +1,26 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { assetBaseUrlTransform } from "./asset-base-url-transform-plugin.js";
2
+ import { assetBaseUrlTransform, assetBaseUrlTransformPlugin, isCssRequest, } from "./asset-base-url-transform-plugin.js";
3
3
  describe("assetBaseUrlTransform", () => {
4
- const devServerOrigin = "http://localhost:3000";
5
- it("should transform asset paths in single, double, and backtick quotes", () => {
4
+ it("should transform asset paths to use window.skybridge.serverUrl", () => {
6
5
  const cases = [
7
6
  {
8
7
  desc: "single-quoted",
9
8
  code: `const image = '/assets/logo.png';`,
10
- expected: `const image = '${devServerOrigin}/assets/logo.png';`,
9
+ expected: `const image = (window.skybridge?.serverUrl ?? "") + "/assets/logo.png";`,
11
10
  },
12
11
  {
13
12
  desc: "double-quoted",
14
13
  code: `const image = "/assets/logo.png";`,
15
- expected: `const image = "${devServerOrigin}/assets/logo.png";`,
14
+ expected: `const image = (window.skybridge?.serverUrl ?? "") + "/assets/logo.png";`,
16
15
  },
17
16
  {
18
17
  desc: "backtick-quoted",
19
18
  code: "const image = `/assets/logo.png`;",
20
- expected: `const image = \`${devServerOrigin}/assets/logo.png\`;`,
19
+ expected: `const image = (window.skybridge?.serverUrl ?? "") + "/assets/logo.png";`,
21
20
  },
22
21
  ];
23
22
  for (const { code, expected } of cases) {
24
- const result = assetBaseUrlTransform(code, devServerOrigin);
23
+ const result = assetBaseUrlTransform(code);
25
24
  expect(result).toBe(expected);
26
25
  }
27
26
  });
@@ -31,10 +30,10 @@ describe("assetBaseUrlTransform", () => {
31
30
  const icon = '/assets/icon.svg';
32
31
  const font = '/assets/font.woff2';
33
32
  `;
34
- const result = assetBaseUrlTransform(code, devServerOrigin);
35
- expect(result).toContain(`${devServerOrigin}/assets/logo.png`);
36
- expect(result).toContain(`${devServerOrigin}/assets/icon.svg`);
37
- expect(result).toContain(`${devServerOrigin}/assets/font.woff2`);
33
+ const result = assetBaseUrlTransform(code);
34
+ expect(result).toContain(`(window.skybridge?.serverUrl ?? "") + "/assets/logo.png"`);
35
+ expect(result).toContain(`(window.skybridge?.serverUrl ?? "") + "/assets/icon.svg"`);
36
+ expect(result).toContain(`(window.skybridge?.serverUrl ?? "") + "/assets/font.woff2"`);
38
37
  });
39
38
  it("should not transform already absolute URLs", () => {
40
39
  const code = `
@@ -42,15 +41,94 @@ describe("assetBaseUrlTransform", () => {
42
41
  const http = 'http://example.com/image.png';
43
42
  const https = 'https://example.com/image.png';
44
43
  `;
45
- const result = assetBaseUrlTransform(code, devServerOrigin);
46
- expect(result).toContain(`${devServerOrigin}/assets/logo.png`);
44
+ const result = assetBaseUrlTransform(code);
45
+ expect(result).toContain(`(window.skybridge?.serverUrl ?? "") + "/assets/logo.png"`);
47
46
  expect(result).toContain("http://example.com/image.png");
48
47
  expect(result).toContain("https://example.com/image.png");
49
48
  });
50
49
  it("should not transform code without asset paths", () => {
51
50
  const code = `const text = "Hello World";`;
52
- const result = assetBaseUrlTransform(code, devServerOrigin);
51
+ const result = assetBaseUrlTransform(code);
53
52
  expect(result).toBe(code);
54
53
  });
54
+ it("should not transform asset paths inside static `import ... from` clauses", () => {
55
+ // Reproducer for #713: a dep does `import * as sprite from './icons.svg'`,
56
+ // Vite resolves the relative path to absolute, then this transform used
57
+ // to rewrite the resolved string — producing invalid JS like
58
+ // `import * as sprite from (expr) + "..."` that crashes vite:import-analysis.
59
+ const cases = [
60
+ `import * as sprite from "/Users/me/proj/node_modules/pkg/icons.svg";`,
61
+ `import sprite from '/assets/icons.svg';`,
62
+ `import sprite from "/assets/icons.svg";`,
63
+ `export { default } from "/assets/icons.svg";`,
64
+ `export * from '/assets/sprites.svg';`,
65
+ ];
66
+ for (const code of cases) {
67
+ expect(assetBaseUrlTransform(code)).toBe(code);
68
+ }
69
+ });
70
+ it("should still transform value-position asset paths in files that also have unrelated imports", () => {
71
+ const code = [
72
+ `import { foo } from "./foo.js";`,
73
+ `import * as sprite from "/assets/sprite.svg";`,
74
+ `const logo = "/assets/logo.png";`,
75
+ ].join("\n");
76
+ const result = assetBaseUrlTransform(code);
77
+ // Imports untouched
78
+ expect(result).toContain(`from "./foo.js"`);
79
+ expect(result).toContain(`from "/assets/sprite.svg"`);
80
+ // Value-position rewritten
81
+ expect(result).toContain(`const logo = (window.skybridge?.serverUrl ?? "") + "/assets/logo.png";`);
82
+ });
83
+ });
84
+ describe("isCssRequest", () => {
85
+ it("returns true for CSS-family extensions", () => {
86
+ expect(isCssRequest("/src/styles.css")).toBe(true);
87
+ expect(isCssRequest("/src/styles.module.css")).toBe(true);
88
+ expect(isCssRequest("/src/styles.scss")).toBe(true);
89
+ expect(isCssRequest("/src/styles.sass")).toBe(true);
90
+ expect(isCssRequest("/src/styles.less")).toBe(true);
91
+ expect(isCssRequest("/src/styles.styl")).toBe(true);
92
+ });
93
+ it("returns true for CSS modules with Vite query strings", () => {
94
+ expect(isCssRequest("/src/styles.css?direct")).toBe(true);
95
+ expect(isCssRequest("/src/styles.css?inline")).toBe(true);
96
+ expect(isCssRequest("/src/styles.css?used")).toBe(true);
97
+ expect(isCssRequest("/src/Foo.vue?vue&type=style&lang.css")).toBe(true);
98
+ });
99
+ it("returns false for non-CSS modules", () => {
100
+ expect(isCssRequest("/src/index.tsx")).toBe(false);
101
+ expect(isCssRequest("/src/utils.ts")).toBe(false);
102
+ expect(isCssRequest("/src/Logo.svg")).toBe(false);
103
+ expect(isCssRequest("/src/notes.cssx")).toBe(false);
104
+ });
105
+ });
106
+ describe("assetBaseUrlTransformPlugin", () => {
107
+ function runTransform(id, code) {
108
+ const plugin = assetBaseUrlTransformPlugin();
109
+ const hook = plugin.transform;
110
+ if (!hook) {
111
+ throw new Error("plugin.transform is not defined");
112
+ }
113
+ const handler = typeof hook === "function" ? hook : hook.handler;
114
+ return handler.call(
115
+ // biome-ignore lint/suspicious/noExplicitAny: vitest harness for plugin hook
116
+ {}, code, id, { moduleType: "js" });
117
+ }
118
+ it("rewrites asset paths in JS modules", () => {
119
+ const result = runTransform("/src/widget.tsx", `const logo = "/assets/logo.png";`);
120
+ expect(result?.code).toContain(`(window.skybridge?.serverUrl ?? "") + "/assets/logo.png"`);
121
+ });
122
+ // Reproducer for #697: CSS imports are served as JS modules with the
123
+ // stylesheet embedded as a string. Rewriting url("/foo.woff2") inside that
124
+ // string would produce invalid CSS once the styles are injected.
125
+ it("does not rewrite asset paths when transforming a CSS module", () => {
126
+ const cssCode = `__vite__updateStyle("style-id", "@font-face { src: url(\\"/fonts/Brand.woff2\\") format(\\"woff2\\"); }");`;
127
+ expect(runTransform("/src/fonts.css", cssCode)).toBeNull();
128
+ expect(runTransform("/src/fonts.css?direct", cssCode)).toBeNull();
129
+ expect(runTransform("/src/fonts.css?inline", cssCode)).toBeNull();
130
+ expect(runTransform("/src/styles.scss", cssCode)).toBeNull();
131
+ expect(runTransform("/src/Foo.vue?vue&type=style&lang.css", cssCode)).toBeNull();
132
+ });
55
133
  });
56
134
  //# sourceMappingURL=asset-base-url-transform-plugin.test.js.map