tempest-react-sdk 0.48.0 → 0.49.0

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 (194) hide show
  1. package/dist/audio/sfx-pool.cjs +1 -1
  2. package/dist/audio/sfx-pool.cjs.map +1 -1
  3. package/dist/audio/sfx-pool.js +16 -7
  4. package/dist/audio/sfx-pool.js.map +1 -1
  5. package/dist/audio/use-sfx-pool.cjs +1 -1
  6. package/dist/audio/use-sfx-pool.cjs.map +1 -1
  7. package/dist/audio/use-sfx-pool.js +3 -8
  8. package/dist/audio/use-sfx-pool.js.map +1 -1
  9. package/dist/auth/passkey.cjs +1 -1
  10. package/dist/auth/passkey.cjs.map +1 -1
  11. package/dist/auth/passkey.js +79 -81
  12. package/dist/auth/passkey.js.map +1 -1
  13. package/dist/charts.cjs +1 -1
  14. package/dist/charts.js +4 -4
  15. package/dist/components/BarList/BarList.cjs +1 -1
  16. package/dist/components/BarList/BarList.cjs.map +1 -1
  17. package/dist/components/BarList/BarList.js +31 -24
  18. package/dist/components/BarList/BarList.js.map +1 -1
  19. package/dist/components/BarList/bar-list-model.cjs +1 -1
  20. package/dist/components/BarList/bar-list-model.cjs.map +1 -1
  21. package/dist/components/BarList/bar-list-model.js +5 -5
  22. package/dist/components/BarList/bar-list-model.js.map +1 -1
  23. package/dist/components/ClickOutside/ClickOutside.cjs +1 -1
  24. package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
  25. package/dist/components/ClickOutside/ClickOutside.js +13 -14
  26. package/dist/components/ClickOutside/ClickOutside.js.map +1 -1
  27. package/dist/components/DataTable/DataTable.cjs +1 -1
  28. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  29. package/dist/components/DataTable/DataTable.js +124 -122
  30. package/dist/components/DataTable/DataTable.js.map +1 -1
  31. package/dist/components/FilterBar/filter-apply.cjs +1 -1
  32. package/dist/components/FilterBar/filter-apply.cjs.map +1 -1
  33. package/dist/components/FilterBar/filter-apply.js +35 -38
  34. package/dist/components/FilterBar/filter-apply.js.map +1 -1
  35. package/dist/components/FilterBar/filter-query.cjs +1 -1
  36. package/dist/components/FilterBar/filter-query.cjs.map +1 -1
  37. package/dist/components/FilterBar/filter-query.js +16 -13
  38. package/dist/components/FilterBar/filter-query.js.map +1 -1
  39. package/dist/geo/use-position-tracker.cjs +1 -1
  40. package/dist/geo/use-position-tracker.cjs.map +1 -1
  41. package/dist/geo/use-position-tracker.js +25 -26
  42. package/dist/geo/use-position-tracker.js.map +1 -1
  43. package/dist/hooks/use-async.cjs +1 -1
  44. package/dist/hooks/use-async.cjs.map +1 -1
  45. package/dist/hooks/use-async.js +27 -30
  46. package/dist/hooks/use-async.js.map +1 -1
  47. package/dist/hooks/use-click-outside.cjs +1 -1
  48. package/dist/hooks/use-click-outside.cjs.map +1 -1
  49. package/dist/hooks/use-click-outside.js +8 -9
  50. package/dist/hooks/use-click-outside.js.map +1 -1
  51. package/dist/hooks/use-countdown.cjs +1 -1
  52. package/dist/hooks/use-countdown.cjs.map +1 -1
  53. package/dist/hooks/use-countdown.js +8 -13
  54. package/dist/hooks/use-countdown.js.map +1 -1
  55. package/dist/hooks/use-event-listener.cjs +1 -1
  56. package/dist/hooks/use-event-listener.cjs.map +1 -1
  57. package/dist/hooks/use-event-listener.js +6 -6
  58. package/dist/hooks/use-event-listener.js.map +1 -1
  59. package/dist/hooks/use-interval.cjs +1 -1
  60. package/dist/hooks/use-interval.cjs.map +1 -1
  61. package/dist/hooks/use-interval.js +5 -6
  62. package/dist/hooks/use-interval.js.map +1 -1
  63. package/dist/hooks/use-latest-ref.cjs.map +1 -1
  64. package/dist/hooks/use-latest-ref.js.map +1 -1
  65. package/dist/hooks/use-long-press-handlers.cjs +1 -1
  66. package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
  67. package/dist/hooks/use-long-press-handlers.js +8 -10
  68. package/dist/hooks/use-long-press-handlers.js.map +1 -1
  69. package/dist/hooks/use-long-press.cjs +1 -1
  70. package/dist/hooks/use-long-press.cjs.map +1 -1
  71. package/dist/hooks/use-long-press.js +6 -6
  72. package/dist/hooks/use-long-press.js.map +1 -1
  73. package/dist/hooks/use-online.cjs +1 -1
  74. package/dist/hooks/use-online.cjs.map +1 -1
  75. package/dist/hooks/use-online.js +10 -10
  76. package/dist/hooks/use-online.js.map +1 -1
  77. package/dist/hooks/use-service-worker-update.cjs +1 -1
  78. package/dist/hooks/use-service-worker-update.cjs.map +1 -1
  79. package/dist/hooks/use-service-worker-update.js +24 -25
  80. package/dist/hooks/use-service-worker-update.js.map +1 -1
  81. package/dist/hooks/use-stable-callback.cjs +1 -1
  82. package/dist/hooks/use-stable-callback.cjs.map +1 -1
  83. package/dist/hooks/use-stable-callback.js +4 -3
  84. package/dist/hooks/use-stable-callback.js.map +1 -1
  85. package/dist/hooks/use-timeout.cjs +1 -1
  86. package/dist/hooks/use-timeout.cjs.map +1 -1
  87. package/dist/hooks/use-timeout.js +5 -6
  88. package/dist/hooks/use-timeout.js.map +1 -1
  89. package/dist/hooks/use-typewriter.cjs +1 -1
  90. package/dist/hooks/use-typewriter.cjs.map +1 -1
  91. package/dist/hooks/use-typewriter.js +9 -18
  92. package/dist/hooks/use-typewriter.js.map +1 -1
  93. package/dist/http/api-client.cjs +1 -1
  94. package/dist/http/api-client.cjs.map +1 -1
  95. package/dist/http/api-client.js +11 -16
  96. package/dist/http/api-client.js.map +1 -1
  97. package/dist/http/describe-api-error.cjs +1 -1
  98. package/dist/http/describe-api-error.cjs.map +1 -1
  99. package/dist/http/describe-api-error.js +12 -15
  100. package/dist/http/describe-api-error.js.map +1 -1
  101. package/dist/http/errors.cjs +1 -1
  102. package/dist/http/errors.cjs.map +1 -1
  103. package/dist/http/errors.js +18 -6
  104. package/dist/http/errors.js.map +1 -1
  105. package/dist/http/resumable-upload.cjs +1 -1
  106. package/dist/http/resumable-upload.cjs.map +1 -1
  107. package/dist/http/resumable-upload.js +60 -61
  108. package/dist/http/resumable-upload.js.map +1 -1
  109. package/dist/http/retry.cjs +1 -1
  110. package/dist/http/retry.cjs.map +1 -1
  111. package/dist/http/retry.js +20 -16
  112. package/dist/http/retry.js.map +1 -1
  113. package/dist/http/use-describe-api-error.cjs +1 -1
  114. package/dist/http/use-describe-api-error.cjs.map +1 -1
  115. package/dist/http/use-describe-api-error.js +2 -2
  116. package/dist/http/use-describe-api-error.js.map +1 -1
  117. package/dist/i18n/create-i18n.cjs +1 -1
  118. package/dist/i18n/create-i18n.cjs.map +1 -1
  119. package/dist/i18n/create-i18n.js +6 -6
  120. package/dist/i18n/create-i18n.js.map +1 -1
  121. package/dist/icons/material-symbols.cjs +1 -1
  122. package/dist/icons/material-symbols.cjs.map +1 -1
  123. package/dist/icons/material-symbols.js +136 -5
  124. package/dist/icons/material-symbols.js.map +1 -1
  125. package/dist/icons.d.ts +17 -5
  126. package/dist/offline/create-offline-sync.cjs +1 -1
  127. package/dist/offline/create-offline-sync.cjs.map +1 -1
  128. package/dist/offline/create-offline-sync.js +17 -9
  129. package/dist/offline/create-offline-sync.js.map +1 -1
  130. package/dist/offline/use-offline-sync.cjs +1 -1
  131. package/dist/offline/use-offline-sync.cjs.map +1 -1
  132. package/dist/offline/use-offline-sync.js +7 -8
  133. package/dist/offline/use-offline-sync.js.map +1 -1
  134. package/dist/push/use-push-subscription.cjs +1 -1
  135. package/dist/push/use-push-subscription.cjs.map +1 -1
  136. package/dist/push/use-push-subscription.js +13 -12
  137. package/dist/push/use-push-subscription.js.map +1 -1
  138. package/dist/query/retry-policy.cjs +1 -1
  139. package/dist/query/retry-policy.cjs.map +1 -1
  140. package/dist/query/retry-policy.js +3 -3
  141. package/dist/query/retry-policy.js.map +1 -1
  142. package/dist/sse/use-event-stream.cjs +1 -1
  143. package/dist/sse/use-event-stream.cjs.map +1 -1
  144. package/dist/sse/use-event-stream.js +19 -20
  145. package/dist/sse/use-event-stream.js.map +1 -1
  146. package/dist/tabular/use-tabular-predictor.cjs +1 -1
  147. package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
  148. package/dist/tabular/use-tabular-predictor.js +20 -17
  149. package/dist/tabular/use-tabular-predictor.js.map +1 -1
  150. package/dist/tempest-react-sdk.cjs +1 -1
  151. package/dist/tempest-react-sdk.d.ts +363 -149
  152. package/dist/tempest-react-sdk.js +143 -143
  153. package/dist/theme/ThemeProvider.cjs +1 -1
  154. package/dist/theme/ThemeProvider.cjs.map +1 -1
  155. package/dist/theme/ThemeProvider.js +12 -17
  156. package/dist/theme/ThemeProvider.js.map +1 -1
  157. package/dist/utils/base64.cjs +2 -0
  158. package/dist/utils/base64.cjs.map +1 -0
  159. package/dist/utils/base64.js +16 -0
  160. package/dist/utils/base64.js.map +1 -0
  161. package/dist/utils/compare-values.cjs +1 -1
  162. package/dist/utils/compare-values.cjs.map +1 -1
  163. package/dist/utils/compare-values.js +4 -3
  164. package/dist/utils/compare-values.js.map +1 -1
  165. package/dist/utils/compressed-storage.cjs +1 -1
  166. package/dist/utils/compressed-storage.cjs.map +1 -1
  167. package/dist/utils/compressed-storage.js +16 -46
  168. package/dist/utils/compressed-storage.js.map +1 -1
  169. package/dist/utils/storage.cjs +1 -1
  170. package/dist/utils/storage.cjs.map +1 -1
  171. package/dist/utils/storage.js +37 -17
  172. package/dist/utils/storage.js.map +1 -1
  173. package/dist/vision/use-camera-stream.cjs +1 -1
  174. package/dist/vision/use-camera-stream.cjs.map +1 -1
  175. package/dist/vision/use-camera-stream.js +34 -33
  176. package/dist/vision/use-camera-stream.js.map +1 -1
  177. package/dist/vite/base-url.cjs +2 -0
  178. package/dist/vite/base-url.cjs.map +1 -0
  179. package/dist/vite/base-url.js +8 -0
  180. package/dist/vite/base-url.js.map +1 -0
  181. package/dist/vite/tempest-pwa-dev-sw.cjs +1 -1
  182. package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
  183. package/dist/vite/tempest-pwa-dev-sw.js +54 -29
  184. package/dist/vite/tempest-pwa-dev-sw.js.map +1 -1
  185. package/dist/vite/tempest-pwa-manifest.cjs +2 -2
  186. package/dist/vite/tempest-pwa-manifest.cjs.map +1 -1
  187. package/dist/vite/tempest-pwa-manifest.js +15 -14
  188. package/dist/vite/tempest-pwa-manifest.js.map +1 -1
  189. package/dist/vite.d.ts +2 -2
  190. package/dist/ws/use-web-socket.cjs +1 -1
  191. package/dist/ws/use-web-socket.cjs.map +1 -1
  192. package/dist/ws/use-web-socket.js +40 -42
  193. package/dist/ws/use-web-socket.js.map +1 -1
  194. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tempest-pwa-dev-sw.cjs","names":[],"sources":["../../src/vite/tempest-pwa-dev-sw.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport type { TempestVitePlugin } from \"./tempest-pwa-manifest\";\n\n/** Options for {@link tempestPwaDevSw}. */\nexport interface TempestPwaDevSwOptions {\n /** Service-worker entry, relative to the project root. Default `src/sw.ts`. */\n swSrc?: string;\n /**\n * URL the worker is served at (must match `registerServiceWorker`).\n * Default `/sw.js`.\n *\n * Write it relative to the site root; requests are matched against both the\n * bare path and the path prefixed with the resolved Vite `base`, so a\n * project served from a subpath is handled without extra configuration.\n */\n swUrl?: string;\n /**\n * Dev URL of the precache manifest. Default `/precache-manifest.json`.\n * Matched the same way as {@link TempestPwaDevSwOptions.swUrl}.\n */\n manifestUrl?: string;\n /** Serve the worker in dev. Default `true`; set `false` to opt out. */\n enabled?: boolean;\n}\n\n/**\n * Dev-server plugin that makes the service worker available under `npm run dev`.\n *\n * The production worker is bundled at build time (`vite.sw.config.ts`), so in\n * dev there is no `/sw.js` to register. This plugin compiles `swSrc` on the fly\n * with esbuild and serves it as a classic worker, plus an empty\n * `precache-manifest.json` (there are no hashed build assets to precache in\n * dev — push and runtime caching still work). It closes the \"SW in dev\" gap\n * that otherwise only `vite-plugin-pwa`'s `devOptions` covered.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaDevSw } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({ plugins: [tempestPwaDevSw()] });\n */\nexport function tempestPwaDevSw(options: TempestPwaDevSwOptions = {}): TempestVitePlugin {\n const {\n swSrc = \"src/sw.ts\",\n swUrl = \"/sw.js\",\n manifestUrl = \"/precache-manifest.json\",\n enabled = true,\n } = options;\n\n let root = process.cwd();\n let base = \"/\";\n\n /**\n * Whether a request path addresses `target`.\n *\n * Both the bare path and the base-prefixed one are accepted. Which of the\n * two arrives depends on where this middleware lands relative to Vite's own\n * base handling, and a project served from a subpath would otherwise never\n * match — the browser asks for `/app/sw.js` while the option says `/sw.js`.\n */\n function matches(url: string, target: string): boolean {\n if (url === target) return true;\n const prefix = base.endsWith(\"/\") ? base : `${base}/`;\n if (prefix === \"/\") return false;\n return url === `${prefix}${target.replace(/^\\//, \"\")}`;\n }\n\n const plugin: Plugin = {\n name: \"tempest-pwa-dev-sw\",\n apply: \"serve\",\n configResolved(config) {\n root = config.root ?? process.cwd();\n base = config.base ?? \"/\";\n },\n configureServer(server) {\n if (!enabled) return;\n server.middlewares.use(async (req, res, next) => {\n const url = (req.url ?? \"\").split(\"?\")[0];\n\n if (matches(url, swUrl)) {\n try {\n const esbuild = await import(\"esbuild\");\n const result = await esbuild.build({\n entryPoints: [resolve(root, swSrc)],\n bundle: true,\n format: \"iife\",\n platform: \"browser\",\n target: \"es2020\",\n write: false,\n absWorkingDir: root,\n logLevel: \"silent\",\n });\n res.setHeader(\"Content-Type\", \"application/javascript\");\n res.setHeader(\"Service-Worker-Allowed\", \"/\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(result.outputFiles[0].text);\n } catch (error) {\n res.statusCode = 500;\n res.end(`// SW dev build failed:\\n// ${String(error)}`);\n }\n return;\n }\n\n if (matches(url, manifestUrl)) {\n res.setHeader(\"Content-Type\", \"application/json\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(JSON.stringify({ version: \"dev\", urls: [] }));\n return;\n }\n\n next();\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":"2BA0CA,SAAgB,EAAgB,EAAkC,CAAC,EAAsB,CACrF,GAAM,CACF,QAAQ,YACR,QAAQ,SACR,cAAc,0BACd,UAAU,IACV,EAEA,EAAO,QAAQ,IAAI,EACnB,EAAO,IAUX,SAAS,EAAQ,EAAa,EAAyB,CACnD,GAAI,IAAQ,EAAQ,MAAO,GAC3B,IAAM,EAAS,EAAK,SAAS,GAAG,EAAI,EAAO,GAAG,EAAK,GAEnD,OADI,IAAW,KACR,IAAQ,GAAG,IAAS,EAAO,QAAQ,MAAO,EAAE,GACvD,CAkDA,MAAO,CA/CH,KAAM,qBACN,MAAO,QACP,eAAe,EAAQ,CACnB,EAAO,EAAO,MAAQ,QAAQ,IAAI,EAClC,EAAO,EAAO,MAAQ,GAC1B,EACA,gBAAgB,EAAQ,CACf,GACL,EAAO,YAAY,IAAI,MAAO,EAAK,EAAK,IAAS,CAC7C,IAAM,GAAO,EAAI,KAAO,GAAA,CAAI,MAAM,GAAG,CAAC,CAAC,GAEvC,GAAI,EAAQ,EAAK,CAAK,EAAG,CACrB,GAAI,CAEA,IAAM,EAAS,MAAM,MADC,OAAO,WAAA,CACA,MAAM,CAC/B,YAAa,EAAA,EAAC,EAAA,QAAA,CAAQ,EAAM,CAAK,CAAC,EAClC,OAAQ,GACR,OAAQ,OACR,SAAU,UACV,OAAQ,SACR,MAAO,GACP,cAAe,EACf,SAAU,QACd,CAAC,EACD,EAAI,UAAU,eAAgB,wBAAwB,EACtD,EAAI,UAAU,yBAA0B,GAAG,EAC3C,EAAI,UAAU,gBAAiB,UAAU,EACzC,EAAI,IAAI,EAAO,YAAY,EAAE,CAAC,IAAI,CACtC,OAAS,EAAO,CACZ,EAAI,WAAa,IACjB,EAAI,IAAI,+BAA+B,OAAO,CAAK,GAAG,CAC1D,CACA,MACJ,CAEA,GAAI,EAAQ,EAAK,CAAW,EAAG,CAC3B,EAAI,UAAU,eAAgB,kBAAkB,EAChD,EAAI,UAAU,gBAAiB,UAAU,EACzC,EAAI,IAAI,KAAK,UAAU,CAAE,QAAS,MAAO,KAAM,CAAC,CAAE,CAAC,CAAC,EACpD,MACJ,CAEA,EAAK,CACT,CAAC,CACL,CAGG,CACX"}
1
+ {"version":3,"file":"tempest-pwa-dev-sw.cjs","names":[],"sources":["../../src/vite/tempest-pwa-dev-sw.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport { basePrefix } from \"./base-url\";\nimport type { TempestVitePlugin } from \"./tempest-pwa-manifest\";\n\n/** Options for {@link tempestPwaDevSw}. */\nexport interface TempestPwaDevSwOptions {\n /** Service-worker entry, relative to the project root. Default `src/sw.ts`. */\n swSrc?: string;\n /**\n * URL the worker is served at (must match `registerServiceWorker`).\n * Default `/sw.js`.\n *\n * Write it relative to the site root; requests are matched against both the\n * bare path and the path prefixed with the resolved Vite `base`, so a\n * project served from a subpath is handled without extra configuration.\n */\n swUrl?: string;\n /**\n * Dev URL of the precache manifest. Default `/precache-manifest.json`.\n * Matched the same way as {@link TempestPwaDevSwOptions.swUrl}.\n */\n manifestUrl?: string;\n /** Serve the worker in dev. Default `true`; set `false` to opt out. */\n enabled?: boolean;\n}\n\n/**\n * Dev-server plugin that makes the service worker available under `npm run dev`.\n *\n * The production worker is bundled at build time (`vite.sw.config.ts`), so in\n * dev there is no `/sw.js` to register. This plugin compiles `swSrc` on the fly\n * with esbuild — through one incremental context, not a cold build per request —\n * and serves it as a classic worker, plus an empty `precache-manifest.json` (there are no hashed build assets to precache in\n * dev — push and runtime caching still work). It closes the \"SW in dev\" gap\n * that otherwise only `vite-plugin-pwa`'s `devOptions` covered.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaDevSw } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({ plugins: [tempestPwaDevSw()] });\n */\nexport function tempestPwaDevSw(options: TempestPwaDevSwOptions = {}): TempestVitePlugin {\n const {\n swSrc = \"src/sw.ts\",\n swUrl = \"/sw.js\",\n manifestUrl = \"/precache-manifest.json\",\n enabled = true,\n } = options;\n\n let root = process.cwd();\n let base = \"/\";\n\n /**\n * Whether a request path addresses `target`.\n *\n * Both the bare path and the base-prefixed one are accepted. Which of the\n * two arrives depends on where this middleware lands relative to Vite's own\n * base handling, and a project served from a subpath would otherwise never\n * match — the browser asks for `/app/sw.js` while the option says `/sw.js`.\n */\n function matches(url: string, target: string): boolean {\n if (url === target) return true;\n const prefix = basePrefix(base);\n if (prefix === \"/\") return false;\n return url === `${prefix}${target.replace(/^\\//, \"\")}`;\n }\n\n /**\n * The slice of esbuild's incremental API this plugin uses.\n *\n * Typed structurally rather than imported: `esbuild` is not a dependency of\n * this package. It is resolved at runtime from the app's own tree, where Vite\n * already brings it, so importing its types would add a build-time dependency\n * the runtime does not have.\n */\n interface BuildContext {\n rebuild(): Promise<{ outputFiles?: readonly { text: string }[] }>;\n dispose(): Promise<void>;\n }\n\n let context: BuildContext | null = null;\n let pending: Promise<string> | null = null;\n\n /**\n * The incremental build context, created on the first request that needs it.\n *\n * Lazy because a project that never registers a worker should not pay for an\n * esbuild child process, and because `apply: \"serve\"` still loads this module\n * in a build.\n *\n * @returns The context, reused across requests.\n */\n async function ensureContext(): Promise<BuildContext> {\n if (context) return context;\n const esbuild = (await import(\"esbuild\")) as unknown as {\n context(options: Record<string, unknown>): Promise<BuildContext>;\n };\n context = await esbuild.context({\n entryPoints: [resolve(root, swSrc)],\n bundle: true,\n format: \"iife\",\n platform: \"browser\",\n target: \"es2020\",\n write: false,\n absWorkingDir: root,\n logLevel: \"silent\",\n });\n return context;\n }\n\n /**\n * Bundle the worker, reusing the previous graph.\n *\n * `esbuild.build()` per request was a cold bundle every time, and the request\n * count is not one per session: `Cache-Control: no-cache` guarantees one per\n * page load, and Chrome re-fetches the worker script on every navigation and\n * on its own update checks. `rebuild()` reuses the graph and only redoes what\n * changed on disk.\n *\n * Single-flight, because those requests arrive in bursts and esbuild does not\n * promise anything about concurrent `rebuild()` calls on one context. Callers\n * that land while a bundle is in flight share its result, which is the right\n * answer anyway — they asked for the same file at the same moment.\n *\n * @returns The bundled worker source.\n */\n function buildWorker(): Promise<string> {\n if (pending) return pending;\n\n const run = (async (): Promise<string> => {\n const ctx = await ensureContext();\n const result = await ctx.rebuild();\n const text = result.outputFiles?.[0]?.text;\n if (text === undefined) throw new Error(\"esbuild produced no service-worker output\");\n return text;\n })();\n\n pending = run;\n const clear = (): void => {\n pending = null;\n };\n run.then(clear, clear);\n return run;\n }\n\n /**\n * Tear the context down, releasing esbuild's child process.\n *\n * Idempotent, because it is wired to both the dev server closing and the\n * plugin's `buildEnd`. Without it, restarting the dev server leaks one esbuild\n * process per restart.\n */\n async function disposeContext(): Promise<void> {\n const current = context;\n context = null;\n pending = null;\n await current?.dispose();\n }\n\n const plugin: Plugin = {\n name: \"tempest-pwa-dev-sw\",\n apply: \"serve\",\n async buildEnd() {\n await disposeContext();\n },\n configResolved(config) {\n root = config.root ?? process.cwd();\n base = config.base ?? \"/\";\n },\n configureServer(server) {\n if (!enabled) return;\n\n server.httpServer?.once(\"close\", () => void disposeContext());\n\n server.middlewares.use(async (req, res, next) => {\n const url = (req.url ?? \"\").split(\"?\")[0];\n\n if (matches(url, swUrl)) {\n try {\n const source = await buildWorker();\n res.setHeader(\"Content-Type\", \"application/javascript\");\n res.setHeader(\"Service-Worker-Allowed\", \"/\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(source);\n } catch (error) {\n res.statusCode = 500;\n res.end(`// SW dev build failed:\\n// ${String(error)}`);\n }\n return;\n }\n\n if (matches(url, manifestUrl)) {\n res.setHeader(\"Content-Type\", \"application/json\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(JSON.stringify({ version: \"dev\", urls: [] }));\n return;\n }\n\n next();\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":"6DA2CA,SAAgB,EAAgB,EAAkC,CAAC,EAAsB,CACrF,GAAM,CACF,QAAQ,YACR,QAAQ,SACR,cAAc,0BACd,UAAU,IACV,EAEA,EAAO,QAAQ,IAAI,EACnB,EAAO,IAUX,SAAS,EAAQ,EAAa,EAAyB,CACnD,GAAI,IAAQ,EAAQ,MAAO,GAC3B,IAAM,EAAS,EAAA,WAAW,CAAI,EAE9B,OADI,IAAW,KACR,IAAQ,GAAG,IAAS,EAAO,QAAQ,MAAO,EAAE,GACvD,CAeA,IAAI,EAA+B,KAC/B,EAAkC,KAWtC,eAAe,GAAuC,CAelD,OAdI,IAIJ,EAAU,MAAM,MAHO,OAAO,WAAA,CAGN,QAAQ,CAC5B,YAAa,EAAA,EAAC,EAAA,QAAA,CAAQ,EAAM,CAAK,CAAC,EAClC,OAAQ,GACR,OAAQ,OACR,SAAU,UACV,OAAQ,SACR,MAAO,GACP,cAAe,EACf,SAAU,QACd,CAAC,EACM,EACX,CAkBA,SAAS,GAA+B,CACpC,GAAI,EAAS,OAAO,EAEpB,IAAM,GAAO,SAA6B,CAGtC,IAAM,GAAO,MADQ,MADH,EAAc,EAAA,CACP,QAAQ,EAAA,CACb,cAAc,EAAE,EAAE,KACtC,GAAI,IAAS,IAAA,GAAW,MAAU,MAAM,2CAA2C,EACnF,OAAO,CACX,EAAA,CAAG,EAEH,EAAU,EACV,IAAM,MAAoB,CACtB,EAAU,IACd,EAEA,OADA,EAAI,KAAK,EAAO,CAAK,EACd,CACX,CASA,eAAe,GAAgC,CAC3C,IAAM,EAAU,EAChB,EAAU,KACV,EAAU,KACV,MAAM,GAAS,QAAQ,CAC3B,CA8CA,MAAO,CA3CH,KAAM,qBACN,MAAO,QACP,MAAM,UAAW,CACb,MAAM,EAAe,CACzB,EACA,eAAe,EAAQ,CACnB,EAAO,EAAO,MAAQ,QAAQ,IAAI,EAClC,EAAO,EAAO,MAAQ,GAC1B,EACA,gBAAgB,EAAQ,CACf,IAEL,EAAO,YAAY,KAAK,YAAe,KAAK,EAAe,CAAC,EAE5D,EAAO,YAAY,IAAI,MAAO,EAAK,EAAK,IAAS,CAC7C,IAAM,GAAO,EAAI,KAAO,GAAA,CAAI,MAAM,GAAG,CAAC,CAAC,GAEvC,GAAI,EAAQ,EAAK,CAAK,EAAG,CACrB,GAAI,CACA,IAAM,EAAS,MAAM,EAAY,EACjC,EAAI,UAAU,eAAgB,wBAAwB,EACtD,EAAI,UAAU,yBAA0B,GAAG,EAC3C,EAAI,UAAU,gBAAiB,UAAU,EACzC,EAAI,IAAI,CAAM,CAClB,OAAS,EAAO,CACZ,EAAI,WAAa,IACjB,EAAI,IAAI,+BAA+B,OAAO,CAAK,GAAG,CAC1D,CACA,MACJ,CAEA,GAAI,EAAQ,EAAK,CAAW,EAAG,CAC3B,EAAI,UAAU,eAAgB,kBAAkB,EAChD,EAAI,UAAU,gBAAiB,UAAU,EACzC,EAAI,IAAI,KAAK,UAAU,CAAE,QAAS,MAAO,KAAM,CAAC,CAAE,CAAC,CAAC,EACpD,MACJ,CAEA,EAAK,CACT,CAAC,EACL,CAGG,CACX"}
@@ -1,52 +1,77 @@
1
- import { resolve as e } from "node:path";
1
+ import { basePrefix as e } from "./base-url.js";
2
+ import { resolve as t } from "node:path";
2
3
  //#region src/vite/tempest-pwa-dev-sw.ts
3
- function t(t = {}) {
4
- let { swSrc: n = "src/sw.ts", swUrl: r = "/sw.js", manifestUrl: i = "/precache-manifest.json", enabled: a = !0 } = t, o = process.cwd(), s = "/";
5
- function c(e, t) {
6
- if (e === t) return !0;
7
- let n = s.endsWith("/") ? s : `${s}/`;
8
- return n !== "/" && e === `${n}${t.replace(/^\//, "")}`;
4
+ function n(n = {}) {
5
+ let { swSrc: r = "src/sw.ts", swUrl: i = "/sw.js", manifestUrl: a = "/precache-manifest.json", enabled: o = !0 } = n, s = process.cwd(), c = "/";
6
+ function l(t, n) {
7
+ if (t === n) return !0;
8
+ let r = e(c);
9
+ return r !== "/" && t === `${r}${n.replace(/^\//, "")}`;
10
+ }
11
+ let u = null, d = null;
12
+ async function f() {
13
+ return u || (u = await (await import("esbuild")).context({
14
+ entryPoints: [t(s, r)],
15
+ bundle: !0,
16
+ format: "iife",
17
+ platform: "browser",
18
+ target: "es2020",
19
+ write: !1,
20
+ absWorkingDir: s,
21
+ logLevel: "silent"
22
+ }), u);
23
+ }
24
+ function p() {
25
+ if (d) return d;
26
+ let e = (async () => {
27
+ let e = (await (await f()).rebuild()).outputFiles?.[0]?.text;
28
+ if (e === void 0) throw Error("esbuild produced no service-worker output");
29
+ return e;
30
+ })();
31
+ d = e;
32
+ let t = () => {
33
+ d = null;
34
+ };
35
+ return e.then(t, t), e;
36
+ }
37
+ async function m() {
38
+ let e = u;
39
+ u = null, d = null, await e?.dispose();
9
40
  }
10
41
  return {
11
42
  name: "tempest-pwa-dev-sw",
12
43
  apply: "serve",
44
+ async buildEnd() {
45
+ await m();
46
+ },
13
47
  configResolved(e) {
14
- o = e.root ?? process.cwd(), s = e.base ?? "/";
48
+ s = e.root ?? process.cwd(), c = e.base ?? "/";
15
49
  },
16
- configureServer(t) {
17
- a && t.middlewares.use(async (t, a, s) => {
18
- let l = (t.url ?? "").split("?")[0];
19
- if (c(l, r)) {
50
+ configureServer(e) {
51
+ o && (e.httpServer?.once("close", () => void m()), e.middlewares.use(async (e, t, n) => {
52
+ let r = (e.url ?? "").split("?")[0];
53
+ if (l(r, i)) {
20
54
  try {
21
- let t = await (await import("esbuild")).build({
22
- entryPoints: [e(o, n)],
23
- bundle: !0,
24
- format: "iife",
25
- platform: "browser",
26
- target: "es2020",
27
- write: !1,
28
- absWorkingDir: o,
29
- logLevel: "silent"
30
- });
31
- a.setHeader("Content-Type", "application/javascript"), a.setHeader("Service-Worker-Allowed", "/"), a.setHeader("Cache-Control", "no-cache"), a.end(t.outputFiles[0].text);
55
+ let e = await p();
56
+ t.setHeader("Content-Type", "application/javascript"), t.setHeader("Service-Worker-Allowed", "/"), t.setHeader("Cache-Control", "no-cache"), t.end(e);
32
57
  } catch (e) {
33
- a.statusCode = 500, a.end(`// SW dev build failed:\n// ${String(e)}`);
58
+ t.statusCode = 500, t.end(`// SW dev build failed:\n// ${String(e)}`);
34
59
  }
35
60
  return;
36
61
  }
37
- if (c(l, i)) {
38
- a.setHeader("Content-Type", "application/json"), a.setHeader("Cache-Control", "no-cache"), a.end(JSON.stringify({
62
+ if (l(r, a)) {
63
+ t.setHeader("Content-Type", "application/json"), t.setHeader("Cache-Control", "no-cache"), t.end(JSON.stringify({
39
64
  version: "dev",
40
65
  urls: []
41
66
  }));
42
67
  return;
43
68
  }
44
- s();
45
- });
69
+ n();
70
+ }));
46
71
  }
47
72
  };
48
73
  }
49
74
  //#endregion
50
- export { t as tempestPwaDevSw };
75
+ export { n as tempestPwaDevSw };
51
76
 
52
77
  //# sourceMappingURL=tempest-pwa-dev-sw.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tempest-pwa-dev-sw.js","names":[],"sources":["../../src/vite/tempest-pwa-dev-sw.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport type { TempestVitePlugin } from \"./tempest-pwa-manifest\";\n\n/** Options for {@link tempestPwaDevSw}. */\nexport interface TempestPwaDevSwOptions {\n /** Service-worker entry, relative to the project root. Default `src/sw.ts`. */\n swSrc?: string;\n /**\n * URL the worker is served at (must match `registerServiceWorker`).\n * Default `/sw.js`.\n *\n * Write it relative to the site root; requests are matched against both the\n * bare path and the path prefixed with the resolved Vite `base`, so a\n * project served from a subpath is handled without extra configuration.\n */\n swUrl?: string;\n /**\n * Dev URL of the precache manifest. Default `/precache-manifest.json`.\n * Matched the same way as {@link TempestPwaDevSwOptions.swUrl}.\n */\n manifestUrl?: string;\n /** Serve the worker in dev. Default `true`; set `false` to opt out. */\n enabled?: boolean;\n}\n\n/**\n * Dev-server plugin that makes the service worker available under `npm run dev`.\n *\n * The production worker is bundled at build time (`vite.sw.config.ts`), so in\n * dev there is no `/sw.js` to register. This plugin compiles `swSrc` on the fly\n * with esbuild and serves it as a classic worker, plus an empty\n * `precache-manifest.json` (there are no hashed build assets to precache in\n * dev — push and runtime caching still work). It closes the \"SW in dev\" gap\n * that otherwise only `vite-plugin-pwa`'s `devOptions` covered.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaDevSw } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({ plugins: [tempestPwaDevSw()] });\n */\nexport function tempestPwaDevSw(options: TempestPwaDevSwOptions = {}): TempestVitePlugin {\n const {\n swSrc = \"src/sw.ts\",\n swUrl = \"/sw.js\",\n manifestUrl = \"/precache-manifest.json\",\n enabled = true,\n } = options;\n\n let root = process.cwd();\n let base = \"/\";\n\n /**\n * Whether a request path addresses `target`.\n *\n * Both the bare path and the base-prefixed one are accepted. Which of the\n * two arrives depends on where this middleware lands relative to Vite's own\n * base handling, and a project served from a subpath would otherwise never\n * match — the browser asks for `/app/sw.js` while the option says `/sw.js`.\n */\n function matches(url: string, target: string): boolean {\n if (url === target) return true;\n const prefix = base.endsWith(\"/\") ? base : `${base}/`;\n if (prefix === \"/\") return false;\n return url === `${prefix}${target.replace(/^\\//, \"\")}`;\n }\n\n const plugin: Plugin = {\n name: \"tempest-pwa-dev-sw\",\n apply: \"serve\",\n configResolved(config) {\n root = config.root ?? process.cwd();\n base = config.base ?? \"/\";\n },\n configureServer(server) {\n if (!enabled) return;\n server.middlewares.use(async (req, res, next) => {\n const url = (req.url ?? \"\").split(\"?\")[0];\n\n if (matches(url, swUrl)) {\n try {\n const esbuild = await import(\"esbuild\");\n const result = await esbuild.build({\n entryPoints: [resolve(root, swSrc)],\n bundle: true,\n format: \"iife\",\n platform: \"browser\",\n target: \"es2020\",\n write: false,\n absWorkingDir: root,\n logLevel: \"silent\",\n });\n res.setHeader(\"Content-Type\", \"application/javascript\");\n res.setHeader(\"Service-Worker-Allowed\", \"/\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(result.outputFiles[0].text);\n } catch (error) {\n res.statusCode = 500;\n res.end(`// SW dev build failed:\\n// ${String(error)}`);\n }\n return;\n }\n\n if (matches(url, manifestUrl)) {\n res.setHeader(\"Content-Type\", \"application/json\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(JSON.stringify({ version: \"dev\", urls: [] }));\n return;\n }\n\n next();\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":";;AA0CA,SAAgB,EAAgB,IAAkC,CAAC,GAAsB;CACrF,IAAM,EACF,WAAQ,aACR,WAAQ,UACR,iBAAc,2BACd,aAAU,OACV,GAEA,IAAO,QAAQ,IAAI,GACnB,IAAO;CAUX,SAAS,EAAQ,GAAa,GAAyB;EACnD,IAAI,MAAQ,GAAQ,OAAO;EAC3B,IAAM,IAAS,EAAK,SAAS,GAAG,IAAI,IAAO,GAAG,EAAK;EAEnD,OADI,MAAW,OACR,MAAQ,GAAG,IAAS,EAAO,QAAQ,OAAO,EAAE;CACvD;CAkDA,OAAO;EA/CH,MAAM;EACN,OAAO;EACP,eAAe,GAAQ;GAEnB,AADA,IAAO,EAAO,QAAQ,QAAQ,IAAI,GAClC,IAAO,EAAO,QAAQ;EAC1B;EACA,gBAAgB,GAAQ;GACf,KACL,EAAO,YAAY,IAAI,OAAO,GAAK,GAAK,MAAS;IAC7C,IAAM,KAAO,EAAI,OAAO,GAAA,CAAI,MAAM,GAAG,CAAC,CAAC;IAEvC,IAAI,EAAQ,GAAK,CAAK,GAAG;KACrB,IAAI;MAEA,IAAM,IAAS,OAAM,MADC,OAAO,WAAA,CACA,MAAM;OAC/B,aAAa,CAAC,EAAQ,GAAM,CAAK,CAAC;OAClC,QAAQ;OACR,QAAQ;OACR,UAAU;OACV,QAAQ;OACR,OAAO;OACP,eAAe;OACf,UAAU;MACd,CAAC;MAID,AAHA,EAAI,UAAU,gBAAgB,wBAAwB,GACtD,EAAI,UAAU,0BAA0B,GAAG,GAC3C,EAAI,UAAU,iBAAiB,UAAU,GACzC,EAAI,IAAI,EAAO,YAAY,EAAE,CAAC,IAAI;KACtC,SAAS,GAAO;MAEZ,AADA,EAAI,aAAa,KACjB,EAAI,IAAI,+BAA+B,OAAO,CAAK,GAAG;KAC1D;KACA;IACJ;IAEA,IAAI,EAAQ,GAAK,CAAW,GAAG;KAG3B,AAFA,EAAI,UAAU,gBAAgB,kBAAkB,GAChD,EAAI,UAAU,iBAAiB,UAAU,GACzC,EAAI,IAAI,KAAK,UAAU;MAAE,SAAS;MAAO,MAAM,CAAC;KAAE,CAAC,CAAC;KACpD;IACJ;IAEA,EAAK;GACT,CAAC;EACL;CAGG;AACX"}
1
+ {"version":3,"file":"tempest-pwa-dev-sw.js","names":[],"sources":["../../src/vite/tempest-pwa-dev-sw.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport { basePrefix } from \"./base-url\";\nimport type { TempestVitePlugin } from \"./tempest-pwa-manifest\";\n\n/** Options for {@link tempestPwaDevSw}. */\nexport interface TempestPwaDevSwOptions {\n /** Service-worker entry, relative to the project root. Default `src/sw.ts`. */\n swSrc?: string;\n /**\n * URL the worker is served at (must match `registerServiceWorker`).\n * Default `/sw.js`.\n *\n * Write it relative to the site root; requests are matched against both the\n * bare path and the path prefixed with the resolved Vite `base`, so a\n * project served from a subpath is handled without extra configuration.\n */\n swUrl?: string;\n /**\n * Dev URL of the precache manifest. Default `/precache-manifest.json`.\n * Matched the same way as {@link TempestPwaDevSwOptions.swUrl}.\n */\n manifestUrl?: string;\n /** Serve the worker in dev. Default `true`; set `false` to opt out. */\n enabled?: boolean;\n}\n\n/**\n * Dev-server plugin that makes the service worker available under `npm run dev`.\n *\n * The production worker is bundled at build time (`vite.sw.config.ts`), so in\n * dev there is no `/sw.js` to register. This plugin compiles `swSrc` on the fly\n * with esbuild — through one incremental context, not a cold build per request —\n * and serves it as a classic worker, plus an empty `precache-manifest.json` (there are no hashed build assets to precache in\n * dev — push and runtime caching still work). It closes the \"SW in dev\" gap\n * that otherwise only `vite-plugin-pwa`'s `devOptions` covered.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaDevSw } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({ plugins: [tempestPwaDevSw()] });\n */\nexport function tempestPwaDevSw(options: TempestPwaDevSwOptions = {}): TempestVitePlugin {\n const {\n swSrc = \"src/sw.ts\",\n swUrl = \"/sw.js\",\n manifestUrl = \"/precache-manifest.json\",\n enabled = true,\n } = options;\n\n let root = process.cwd();\n let base = \"/\";\n\n /**\n * Whether a request path addresses `target`.\n *\n * Both the bare path and the base-prefixed one are accepted. Which of the\n * two arrives depends on where this middleware lands relative to Vite's own\n * base handling, and a project served from a subpath would otherwise never\n * match — the browser asks for `/app/sw.js` while the option says `/sw.js`.\n */\n function matches(url: string, target: string): boolean {\n if (url === target) return true;\n const prefix = basePrefix(base);\n if (prefix === \"/\") return false;\n return url === `${prefix}${target.replace(/^\\//, \"\")}`;\n }\n\n /**\n * The slice of esbuild's incremental API this plugin uses.\n *\n * Typed structurally rather than imported: `esbuild` is not a dependency of\n * this package. It is resolved at runtime from the app's own tree, where Vite\n * already brings it, so importing its types would add a build-time dependency\n * the runtime does not have.\n */\n interface BuildContext {\n rebuild(): Promise<{ outputFiles?: readonly { text: string }[] }>;\n dispose(): Promise<void>;\n }\n\n let context: BuildContext | null = null;\n let pending: Promise<string> | null = null;\n\n /**\n * The incremental build context, created on the first request that needs it.\n *\n * Lazy because a project that never registers a worker should not pay for an\n * esbuild child process, and because `apply: \"serve\"` still loads this module\n * in a build.\n *\n * @returns The context, reused across requests.\n */\n async function ensureContext(): Promise<BuildContext> {\n if (context) return context;\n const esbuild = (await import(\"esbuild\")) as unknown as {\n context(options: Record<string, unknown>): Promise<BuildContext>;\n };\n context = await esbuild.context({\n entryPoints: [resolve(root, swSrc)],\n bundle: true,\n format: \"iife\",\n platform: \"browser\",\n target: \"es2020\",\n write: false,\n absWorkingDir: root,\n logLevel: \"silent\",\n });\n return context;\n }\n\n /**\n * Bundle the worker, reusing the previous graph.\n *\n * `esbuild.build()` per request was a cold bundle every time, and the request\n * count is not one per session: `Cache-Control: no-cache` guarantees one per\n * page load, and Chrome re-fetches the worker script on every navigation and\n * on its own update checks. `rebuild()` reuses the graph and only redoes what\n * changed on disk.\n *\n * Single-flight, because those requests arrive in bursts and esbuild does not\n * promise anything about concurrent `rebuild()` calls on one context. Callers\n * that land while a bundle is in flight share its result, which is the right\n * answer anyway — they asked for the same file at the same moment.\n *\n * @returns The bundled worker source.\n */\n function buildWorker(): Promise<string> {\n if (pending) return pending;\n\n const run = (async (): Promise<string> => {\n const ctx = await ensureContext();\n const result = await ctx.rebuild();\n const text = result.outputFiles?.[0]?.text;\n if (text === undefined) throw new Error(\"esbuild produced no service-worker output\");\n return text;\n })();\n\n pending = run;\n const clear = (): void => {\n pending = null;\n };\n run.then(clear, clear);\n return run;\n }\n\n /**\n * Tear the context down, releasing esbuild's child process.\n *\n * Idempotent, because it is wired to both the dev server closing and the\n * plugin's `buildEnd`. Without it, restarting the dev server leaks one esbuild\n * process per restart.\n */\n async function disposeContext(): Promise<void> {\n const current = context;\n context = null;\n pending = null;\n await current?.dispose();\n }\n\n const plugin: Plugin = {\n name: \"tempest-pwa-dev-sw\",\n apply: \"serve\",\n async buildEnd() {\n await disposeContext();\n },\n configResolved(config) {\n root = config.root ?? process.cwd();\n base = config.base ?? \"/\";\n },\n configureServer(server) {\n if (!enabled) return;\n\n server.httpServer?.once(\"close\", () => void disposeContext());\n\n server.middlewares.use(async (req, res, next) => {\n const url = (req.url ?? \"\").split(\"?\")[0];\n\n if (matches(url, swUrl)) {\n try {\n const source = await buildWorker();\n res.setHeader(\"Content-Type\", \"application/javascript\");\n res.setHeader(\"Service-Worker-Allowed\", \"/\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(source);\n } catch (error) {\n res.statusCode = 500;\n res.end(`// SW dev build failed:\\n// ${String(error)}`);\n }\n return;\n }\n\n if (matches(url, manifestUrl)) {\n res.setHeader(\"Content-Type\", \"application/json\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.end(JSON.stringify({ version: \"dev\", urls: [] }));\n return;\n }\n\n next();\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":";;;AA2CA,SAAgB,EAAgB,IAAkC,CAAC,GAAsB;CACrF,IAAM,EACF,WAAQ,aACR,WAAQ,UACR,iBAAc,2BACd,aAAU,OACV,GAEA,IAAO,QAAQ,IAAI,GACnB,IAAO;CAUX,SAAS,EAAQ,GAAa,GAAyB;EACnD,IAAI,MAAQ,GAAQ,OAAO;EAC3B,IAAM,IAAS,EAAW,CAAI;EAE9B,OADI,MAAW,OACR,MAAQ,GAAG,IAAS,EAAO,QAAQ,OAAO,EAAE;CACvD;CAeA,IAAI,IAA+B,MAC/B,IAAkC;CAWtC,eAAe,IAAuC;EAelD,OAdI,MAIJ,IAAU,OAAM,MAHO,OAAO,WAAA,CAGN,QAAQ;GAC5B,aAAa,CAAC,EAAQ,GAAM,CAAK,CAAC;GAClC,QAAQ;GACR,QAAQ;GACR,UAAU;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,UAAU;EACd,CAAC,GACM;CACX;CAkBA,SAAS,IAA+B;EACpC,IAAI,GAAS,OAAO;EAEpB,IAAM,KAAO,YAA6B;GAGtC,IAAM,KAAO,OADQ,MADH,EAAc,EAAA,CACP,QAAQ,EAAA,CACb,cAAc,EAAE,EAAE;GACtC,IAAI,MAAS,KAAA,GAAW,MAAU,MAAM,2CAA2C;GACnF,OAAO;EACX,EAAA,CAAG;EAEH,IAAU;EACV,IAAM,UAAoB;GACtB,IAAU;EACd;EAEA,OADA,EAAI,KAAK,GAAO,CAAK,GACd;CACX;CASA,eAAe,IAAgC;EAC3C,IAAM,IAAU;EAGhB,AAFA,IAAU,MACV,IAAU,MACV,MAAM,GAAS,QAAQ;CAC3B;CA8CA,OAAO;EA3CH,MAAM;EACN,OAAO;EACP,MAAM,WAAW;GACb,MAAM,EAAe;EACzB;EACA,eAAe,GAAQ;GAEnB,AADA,IAAO,EAAO,QAAQ,QAAQ,IAAI,GAClC,IAAO,EAAO,QAAQ;EAC1B;EACA,gBAAgB,GAAQ;GACf,MAEL,EAAO,YAAY,KAAK,eAAe,KAAK,EAAe,CAAC,GAE5D,EAAO,YAAY,IAAI,OAAO,GAAK,GAAK,MAAS;IAC7C,IAAM,KAAO,EAAI,OAAO,GAAA,CAAI,MAAM,GAAG,CAAC,CAAC;IAEvC,IAAI,EAAQ,GAAK,CAAK,GAAG;KACrB,IAAI;MACA,IAAM,IAAS,MAAM,EAAY;MAIjC,AAHA,EAAI,UAAU,gBAAgB,wBAAwB,GACtD,EAAI,UAAU,0BAA0B,GAAG,GAC3C,EAAI,UAAU,iBAAiB,UAAU,GACzC,EAAI,IAAI,CAAM;KAClB,SAAS,GAAO;MAEZ,AADA,EAAI,aAAa,KACjB,EAAI,IAAI,+BAA+B,OAAO,CAAK,GAAG;KAC1D;KACA;IACJ;IAEA,IAAI,EAAQ,GAAK,CAAW,GAAG;KAG3B,AAFA,EAAI,UAAU,gBAAgB,kBAAkB,GAChD,EAAI,UAAU,iBAAiB,UAAU,GACzC,EAAI,IAAI,KAAK,UAAU;MAAE,SAAS;MAAO,MAAM,CAAC;KAAE,CAAC,CAAC;KACpD;IACJ;IAEA,EAAK;GACT,CAAC;EACL;CAGG;AACX"}
@@ -1,3 +1,3 @@
1
- function e(e,t){return`${e.endsWith(`/`)?e:`${e}/`}${t}`.replace(/([^:]\/)\/+/g,`$1`)}function t(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return n===`/`?t.startsWith(`/`)?t:`/${t}`:t.startsWith(n)?t:`${n}${t.replace(/^\//,``)}`}function n(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)>>>0;return t.toString(16)}function r(r={}){let{fileName:i=`precache-manifest.json`,additionalUrls:a=[],exclude:o=/\.map$/,includeHtml:s=!0,appShell:c=`/index.html`}=r,l=`/`;return{name:`tempest-pwa-manifest`,apply:`build`,configResolved(e){l=e.base??`/`},generateBundle(r,u){let d=new Set(a.map(e=>t(l,e)));c&&d.add(t(l,c));for(let t of Object.keys(u))t!==i&&(o.test(t)||!s&&t.endsWith(`.html`)||d.add(e(l,t)));let f=[...d].sort(),p=n(f.join(`
2
- `));this.emitFile({type:`asset`,fileName:i,source:JSON.stringify({version:p,urls:f})})}}}exports.tempestPwaManifest=r;
1
+ const e=require("./base-url.cjs");function t(t,n){return`${e.basePrefix(t)}${n}`.replace(/([^:]\/)\/+/g,`$1`)}function n(t,n){let r=e.basePrefix(t);return r===`/`?n.startsWith(`/`)?n:`/${n}`:n.startsWith(r)?n:`${r}${n.replace(/^\//,``)}`}function r(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)>>>0;return t.toString(16)}function i(e={}){let{fileName:i=`precache-manifest.json`,additionalUrls:a=[],exclude:o=/\.map$/,includeHtml:s=!0,appShell:c=`/index.html`}=e,l=`/`;return{name:`tempest-pwa-manifest`,apply:`build`,configResolved(e){l=e.base??`/`},generateBundle(e,u){let d=new Set(a.map(e=>n(l,e)));c&&d.add(n(l,c));for(let e of Object.keys(u))e!==i&&(o.test(e)||!s&&e.endsWith(`.html`)||d.add(t(l,e)));let f=[...d].sort(),p=r(f.join(`
2
+ `));this.emitFile({type:`asset`,fileName:i,source:JSON.stringify({version:p,urls:f})})}}}exports.tempestPwaManifest=i;
3
3
  //# sourceMappingURL=tempest-pwa-manifest.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tempest-pwa-manifest.cjs","names":[],"sources":["../../src/vite/tempest-pwa-manifest.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\n\n/**\n * A Vite plugin object. Typed loosely so the SDK's published declarations stay\n * free of `vite`'s internal types (which the `.d.ts` rollup can't analyze);\n * assign the result straight into a `plugins: [...]` array.\n */\nexport type TempestVitePlugin = { name: string } & Record<string, unknown>;\n\n/** Options for {@link tempestPwaManifest}. */\nexport interface TempestPwaManifestOptions {\n /** Output file name (under the build root). Default `precache-manifest.json`. */\n fileName?: string;\n /**\n * Extra URLs to precache that Vite doesn't emit into the bundle — typically\n * `public/` assets like the web manifest and icons. Default `[]`.\n *\n * Write these relative to the site root (`/icon.svg`); the resolved Vite\n * `base` is prefixed for you. An entry that already carries the base is\n * left alone, so spelling it out by hand is still correct.\n */\n additionalUrls?: string[];\n /** Emitted files matching this are skipped. Default `/\\.map$/` (source maps). */\n exclude?: RegExp;\n /** Include emitted `.html` documents (the app shell). Default `true`. */\n includeHtml?: boolean;\n /**\n * App-shell document always added to the manifest, even if Vite emits it\n * after this plugin runs. Must match `installPrecache`'s `navigateFallback`\n * so offline navigations resolve. Pass `false` to disable. Default `/index.html`.\n *\n * Like {@link TempestPwaManifestOptions.additionalUrls}, this is prefixed\n * with the resolved Vite `base`.\n */\n appShell?: string | false;\n}\n\nfunction joinBase(base: string, file: string): string {\n const prefix = base.endsWith(\"/\") ? base : `${base}/`;\n return `${prefix}${file}`.replace(/([^:]\\/)\\/+/g, \"$1\");\n}\n\n/**\n * Prefix a caller-supplied, root-absolute URL with the resolved Vite `base`.\n *\n * Idempotent: a URL that already starts with the base is returned untouched,\n * so configs written before this was applied — spelling the base out by hand —\n * keep producing the same manifest instead of gaining a doubled prefix.\n */\nfunction withBase(base: string, url: string): string {\n const prefix = base.endsWith(\"/\") ? base : `${base}/`;\n if (prefix === \"/\") return url.startsWith(\"/\") ? url : `/${url}`;\n if (url.startsWith(prefix)) return url;\n return `${prefix}${url.replace(/^\\//, \"\")}`;\n}\n\n/** Deterministic djb2 hash → hex. Stable across rebuilds with the same assets. */\nfunction hash(input: string): string {\n let h = 5381;\n for (let i = 0; i < input.length; i++) {\n h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;\n }\n return h.toString(16);\n}\n\n/**\n * Vite build plugin that emits a `precache-manifest.json` listing every built\n * asset (plus any `additionalUrls`) as root-absolute URLs, with a content-based\n * `version`. It is the dependency-free counterpart to Workbox's `__WB_MANIFEST`:\n * `installPrecache` (from `tempest-react-sdk/sw`) reads this file at the service\n * worker's `install` event to cache the app shell for offline use.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaManifest } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({\n * plugins: [tempestPwaManifest({ additionalUrls: [\"/manifest.webmanifest\", \"/icon.svg\"] })],\n * });\n */\nexport function tempestPwaManifest(options: TempestPwaManifestOptions = {}): TempestVitePlugin {\n const {\n fileName = \"precache-manifest.json\",\n additionalUrls = [],\n exclude = /\\.map$/,\n includeHtml = true,\n appShell = \"/index.html\",\n } = options;\n\n let base = \"/\";\n\n const plugin: Plugin = {\n name: \"tempest-pwa-manifest\",\n apply: \"build\",\n configResolved(config) {\n base = config.base ?? \"/\";\n },\n generateBundle(_outputOptions, bundle) {\n const urls = new Set<string>(additionalUrls.map((url) => withBase(base, url)));\n // Vite may emit index.html after this hook, so guarantee the shell.\n if (appShell) urls.add(withBase(base, appShell));\n for (const file of Object.keys(bundle)) {\n if (file === fileName) continue;\n if (exclude.test(file)) continue;\n if (!includeHtml && file.endsWith(\".html\")) continue;\n urls.add(joinBase(base, file));\n }\n\n const list = [...urls].sort();\n const version = hash(list.join(\"\\n\"));\n this.emitFile({\n type: \"asset\",\n fileName,\n source: JSON.stringify({ version, urls: list }),\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":"AAqCA,SAAS,EAAS,EAAc,EAAsB,CAElD,MAAO,GADQ,EAAK,SAAS,GAAG,EAAI,EAAO,GAAG,EAAK,KAChC,IAAO,QAAQ,eAAgB,IAAI,CAC1D,CASA,SAAS,EAAS,EAAc,EAAqB,CACjD,IAAM,EAAS,EAAK,SAAS,GAAG,EAAI,EAAO,GAAG,EAAK,GAGnD,OAFI,IAAW,IAAY,EAAI,WAAW,GAAG,EAAI,EAAM,IAAI,IACvD,EAAI,WAAW,CAAM,EAAU,EAC5B,GAAG,IAAS,EAAI,QAAQ,MAAO,EAAE,GAC5C,CAGA,SAAS,EAAK,EAAuB,CACjC,IAAI,EAAI,KACR,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAC9B,GAAM,GAAK,GAAK,EAAI,EAAM,WAAW,CAAC,IAAO,EAEjD,OAAO,EAAE,SAAS,EAAE,CACxB,CAiBA,SAAgB,EAAmB,EAAqC,CAAC,EAAsB,CAC3F,GAAM,CACF,WAAW,yBACX,iBAAiB,CAAC,EAClB,UAAU,SACV,cAAc,GACd,WAAW,eACX,EAEA,EAAO,IA6BX,MAAO,CA1BH,KAAM,uBACN,MAAO,QACP,eAAe,EAAQ,CACnB,EAAO,EAAO,MAAQ,GAC1B,EACA,eAAe,EAAgB,EAAQ,CACnC,IAAM,EAAO,IAAI,IAAY,EAAe,IAAK,GAAQ,EAAS,EAAM,CAAG,CAAC,CAAC,EAEzE,GAAU,EAAK,IAAI,EAAS,EAAM,CAAQ,CAAC,EAC/C,IAAK,IAAM,KAAQ,OAAO,KAAK,CAAM,EAC7B,IAAS,IACT,EAAQ,KAAK,CAAI,GACjB,CAAC,GAAe,EAAK,SAAS,OAAO,GACzC,EAAK,IAAI,EAAS,EAAM,CAAI,CAAC,GAGjC,IAAM,EAAO,CAAC,GAAG,CAAI,CAAC,CAAC,KAAK,EACtB,EAAU,EAAK,EAAK,KAAK;CAAI,CAAC,EACpC,KAAK,SAAS,CACV,KAAM,QACN,WACA,OAAQ,KAAK,UAAU,CAAE,UAAS,KAAM,CAAK,CAAC,CAClD,CAAC,CACL,CAGG,CACX"}
1
+ {"version":3,"file":"tempest-pwa-manifest.cjs","names":[],"sources":["../../src/vite/tempest-pwa-manifest.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { basePrefix } from \"./base-url\";\n\n/**\n * A Vite plugin object. Typed loosely so the SDK's published declarations stay\n * free of `vite`'s internal types (which the `.d.ts` rollup can't analyze);\n * assign the result straight into a `plugins: [...]` array.\n */\nexport type TempestVitePlugin = { name: string } & Record<string, unknown>;\n\n/** Options for {@link tempestPwaManifest}. */\nexport interface TempestPwaManifestOptions {\n /** Output file name (under the build root). Default `precache-manifest.json`. */\n fileName?: string;\n /**\n * Extra URLs to precache that Vite doesn't emit into the bundle — typically\n * `public/` assets like the web manifest and icons. Default `[]`.\n *\n * Write these relative to the site root (`/icon.svg`); the resolved Vite\n * `base` is prefixed for you. An entry that already carries the base is\n * left alone, so spelling it out by hand is still correct.\n */\n additionalUrls?: string[];\n /** Emitted files matching this are skipped. Default `/\\.map$/` (source maps). */\n exclude?: RegExp;\n /** Include emitted `.html` documents (the app shell). Default `true`. */\n includeHtml?: boolean;\n /**\n * App-shell document always added to the manifest, even if Vite emits it\n * after this plugin runs. Must match `installPrecache`'s `navigateFallback`\n * so offline navigations resolve. Pass `false` to disable. Default `/index.html`.\n *\n * Like {@link TempestPwaManifestOptions.additionalUrls}, this is prefixed\n * with the resolved Vite `base`.\n */\n appShell?: string | false;\n}\n\nfunction joinBase(base: string, file: string): string {\n return `${basePrefix(base)}${file}`.replace(/([^:]\\/)\\/+/g, \"$1\");\n}\n\n/**\n * Prefix a caller-supplied, root-absolute URL with the resolved Vite `base`.\n *\n * Idempotent: a URL that already starts with the base is returned untouched,\n * so configs written before this was applied — spelling the base out by hand —\n * keep producing the same manifest instead of gaining a doubled prefix.\n */\nfunction withBase(base: string, url: string): string {\n const prefix = basePrefix(base);\n if (prefix === \"/\") return url.startsWith(\"/\") ? url : `/${url}`;\n if (url.startsWith(prefix)) return url;\n return `${prefix}${url.replace(/^\\//, \"\")}`;\n}\n\n/** Deterministic djb2 hash → hex. Stable across rebuilds with the same assets. */\nfunction hash(input: string): string {\n let h = 5381;\n for (let i = 0; i < input.length; i++) {\n h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;\n }\n return h.toString(16);\n}\n\n/**\n * Vite build plugin that emits a `precache-manifest.json` listing every built\n * asset (plus any `additionalUrls`) as root-absolute URLs, with a content-based\n * `version`. It is the dependency-free counterpart to Workbox's `__WB_MANIFEST`:\n * `installPrecache` (from `tempest-react-sdk/sw`) reads this file at the service\n * worker's `install` event to cache the app shell for offline use.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaManifest } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({\n * plugins: [tempestPwaManifest({ additionalUrls: [\"/manifest.webmanifest\", \"/icon.svg\"] })],\n * });\n */\nexport function tempestPwaManifest(options: TempestPwaManifestOptions = {}): TempestVitePlugin {\n const {\n fileName = \"precache-manifest.json\",\n additionalUrls = [],\n exclude = /\\.map$/,\n includeHtml = true,\n appShell = \"/index.html\",\n } = options;\n\n let base = \"/\";\n\n const plugin: Plugin = {\n name: \"tempest-pwa-manifest\",\n apply: \"build\",\n configResolved(config) {\n base = config.base ?? \"/\";\n },\n generateBundle(_outputOptions, bundle) {\n const urls = new Set<string>(additionalUrls.map((url) => withBase(base, url)));\n // Vite may emit index.html after this hook, so guarantee the shell.\n if (appShell) urls.add(withBase(base, appShell));\n for (const file of Object.keys(bundle)) {\n if (file === fileName) continue;\n if (exclude.test(file)) continue;\n if (!includeHtml && file.endsWith(\".html\")) continue;\n urls.add(joinBase(base, file));\n }\n\n const list = [...urls].sort();\n const version = hash(list.join(\"\\n\"));\n this.emitFile({\n type: \"asset\",\n fileName,\n source: JSON.stringify({ version, urls: list }),\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":"kCAsCA,SAAS,EAAS,EAAc,EAAsB,CAClD,MAAO,GAAG,EAAA,WAAW,CAAI,IAAI,IAAO,QAAQ,eAAgB,IAAI,CACpE,CASA,SAAS,EAAS,EAAc,EAAqB,CACjD,IAAM,EAAS,EAAA,WAAW,CAAI,EAG9B,OAFI,IAAW,IAAY,EAAI,WAAW,GAAG,EAAI,EAAM,IAAI,IACvD,EAAI,WAAW,CAAM,EAAU,EAC5B,GAAG,IAAS,EAAI,QAAQ,MAAO,EAAE,GAC5C,CAGA,SAAS,EAAK,EAAuB,CACjC,IAAI,EAAI,KACR,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAC9B,GAAM,GAAK,GAAK,EAAI,EAAM,WAAW,CAAC,IAAO,EAEjD,OAAO,EAAE,SAAS,EAAE,CACxB,CAiBA,SAAgB,EAAmB,EAAqC,CAAC,EAAsB,CAC3F,GAAM,CACF,WAAW,yBACX,iBAAiB,CAAC,EAClB,UAAU,SACV,cAAc,GACd,WAAW,eACX,EAEA,EAAO,IA6BX,MAAO,CA1BH,KAAM,uBACN,MAAO,QACP,eAAe,EAAQ,CACnB,EAAO,EAAO,MAAQ,GAC1B,EACA,eAAe,EAAgB,EAAQ,CACnC,IAAM,EAAO,IAAI,IAAY,EAAe,IAAK,GAAQ,EAAS,EAAM,CAAG,CAAC,CAAC,EAEzE,GAAU,EAAK,IAAI,EAAS,EAAM,CAAQ,CAAC,EAC/C,IAAK,IAAM,KAAQ,OAAO,KAAK,CAAM,EAC7B,IAAS,IACT,EAAQ,KAAK,CAAI,GACjB,CAAC,GAAe,EAAK,SAAS,OAAO,GACzC,EAAK,IAAI,EAAS,EAAM,CAAI,CAAC,GAGjC,IAAM,EAAO,CAAC,GAAG,CAAI,CAAC,CAAC,KAAK,EACtB,EAAU,EAAK,EAAK,KAAK;CAAI,CAAC,EACpC,KAAK,SAAS,CACV,KAAM,QACN,WACA,OAAQ,KAAK,UAAU,CAAE,UAAS,KAAM,CAAK,CAAC,CAClD,CAAC,CACL,CAGG,CACX"}
@@ -1,29 +1,30 @@
1
+ import { basePrefix as e } from "./base-url.js";
1
2
  //#region src/vite/tempest-pwa-manifest.ts
2
- function e(e, t) {
3
- return `${e.endsWith("/") ? e : `${e}/`}${t}`.replace(/([^:]\/)\/+/g, "$1");
3
+ function t(t, n) {
4
+ return `${e(t)}${n}`.replace(/([^:]\/)\/+/g, "$1");
4
5
  }
5
- function t(e, t) {
6
- let n = e.endsWith("/") ? e : `${e}/`;
7
- return n === "/" ? t.startsWith("/") ? t : `/${t}` : t.startsWith(n) ? t : `${n}${t.replace(/^\//, "")}`;
6
+ function n(t, n) {
7
+ let r = e(t);
8
+ return r === "/" ? n.startsWith("/") ? n : `/${n}` : n.startsWith(r) ? n : `${r}${n.replace(/^\//, "")}`;
8
9
  }
9
- function n(e) {
10
+ function r(e) {
10
11
  let t = 5381;
11
12
  for (let n = 0; n < e.length; n++) t = (t << 5) + t + e.charCodeAt(n) >>> 0;
12
13
  return t.toString(16);
13
14
  }
14
- function r(r = {}) {
15
- let { fileName: i = "precache-manifest.json", additionalUrls: a = [], exclude: o = /\.map$/, includeHtml: s = !0, appShell: c = "/index.html" } = r, l = "/";
15
+ function i(e = {}) {
16
+ let { fileName: i = "precache-manifest.json", additionalUrls: a = [], exclude: o = /\.map$/, includeHtml: s = !0, appShell: c = "/index.html" } = e, l = "/";
16
17
  return {
17
18
  name: "tempest-pwa-manifest",
18
19
  apply: "build",
19
20
  configResolved(e) {
20
21
  l = e.base ?? "/";
21
22
  },
22
- generateBundle(r, u) {
23
- let d = new Set(a.map((e) => t(l, e)));
24
- c && d.add(t(l, c));
25
- for (let t of Object.keys(u)) t !== i && (o.test(t) || !s && t.endsWith(".html") || d.add(e(l, t)));
26
- let f = [...d].sort(), p = n(f.join("\n"));
23
+ generateBundle(e, u) {
24
+ let d = new Set(a.map((e) => n(l, e)));
25
+ c && d.add(n(l, c));
26
+ for (let e of Object.keys(u)) e !== i && (o.test(e) || !s && e.endsWith(".html") || d.add(t(l, e)));
27
+ let f = [...d].sort(), p = r(f.join("\n"));
27
28
  this.emitFile({
28
29
  type: "asset",
29
30
  fileName: i,
@@ -36,6 +37,6 @@ function r(r = {}) {
36
37
  };
37
38
  }
38
39
  //#endregion
39
- export { r as tempestPwaManifest };
40
+ export { i as tempestPwaManifest };
40
41
 
41
42
  //# sourceMappingURL=tempest-pwa-manifest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tempest-pwa-manifest.js","names":[],"sources":["../../src/vite/tempest-pwa-manifest.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\n\n/**\n * A Vite plugin object. Typed loosely so the SDK's published declarations stay\n * free of `vite`'s internal types (which the `.d.ts` rollup can't analyze);\n * assign the result straight into a `plugins: [...]` array.\n */\nexport type TempestVitePlugin = { name: string } & Record<string, unknown>;\n\n/** Options for {@link tempestPwaManifest}. */\nexport interface TempestPwaManifestOptions {\n /** Output file name (under the build root). Default `precache-manifest.json`. */\n fileName?: string;\n /**\n * Extra URLs to precache that Vite doesn't emit into the bundle — typically\n * `public/` assets like the web manifest and icons. Default `[]`.\n *\n * Write these relative to the site root (`/icon.svg`); the resolved Vite\n * `base` is prefixed for you. An entry that already carries the base is\n * left alone, so spelling it out by hand is still correct.\n */\n additionalUrls?: string[];\n /** Emitted files matching this are skipped. Default `/\\.map$/` (source maps). */\n exclude?: RegExp;\n /** Include emitted `.html` documents (the app shell). Default `true`. */\n includeHtml?: boolean;\n /**\n * App-shell document always added to the manifest, even if Vite emits it\n * after this plugin runs. Must match `installPrecache`'s `navigateFallback`\n * so offline navigations resolve. Pass `false` to disable. Default `/index.html`.\n *\n * Like {@link TempestPwaManifestOptions.additionalUrls}, this is prefixed\n * with the resolved Vite `base`.\n */\n appShell?: string | false;\n}\n\nfunction joinBase(base: string, file: string): string {\n const prefix = base.endsWith(\"/\") ? base : `${base}/`;\n return `${prefix}${file}`.replace(/([^:]\\/)\\/+/g, \"$1\");\n}\n\n/**\n * Prefix a caller-supplied, root-absolute URL with the resolved Vite `base`.\n *\n * Idempotent: a URL that already starts with the base is returned untouched,\n * so configs written before this was applied — spelling the base out by hand —\n * keep producing the same manifest instead of gaining a doubled prefix.\n */\nfunction withBase(base: string, url: string): string {\n const prefix = base.endsWith(\"/\") ? base : `${base}/`;\n if (prefix === \"/\") return url.startsWith(\"/\") ? url : `/${url}`;\n if (url.startsWith(prefix)) return url;\n return `${prefix}${url.replace(/^\\//, \"\")}`;\n}\n\n/** Deterministic djb2 hash → hex. Stable across rebuilds with the same assets. */\nfunction hash(input: string): string {\n let h = 5381;\n for (let i = 0; i < input.length; i++) {\n h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;\n }\n return h.toString(16);\n}\n\n/**\n * Vite build plugin that emits a `precache-manifest.json` listing every built\n * asset (plus any `additionalUrls`) as root-absolute URLs, with a content-based\n * `version`. It is the dependency-free counterpart to Workbox's `__WB_MANIFEST`:\n * `installPrecache` (from `tempest-react-sdk/sw`) reads this file at the service\n * worker's `install` event to cache the app shell for offline use.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaManifest } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({\n * plugins: [tempestPwaManifest({ additionalUrls: [\"/manifest.webmanifest\", \"/icon.svg\"] })],\n * });\n */\nexport function tempestPwaManifest(options: TempestPwaManifestOptions = {}): TempestVitePlugin {\n const {\n fileName = \"precache-manifest.json\",\n additionalUrls = [],\n exclude = /\\.map$/,\n includeHtml = true,\n appShell = \"/index.html\",\n } = options;\n\n let base = \"/\";\n\n const plugin: Plugin = {\n name: \"tempest-pwa-manifest\",\n apply: \"build\",\n configResolved(config) {\n base = config.base ?? \"/\";\n },\n generateBundle(_outputOptions, bundle) {\n const urls = new Set<string>(additionalUrls.map((url) => withBase(base, url)));\n // Vite may emit index.html after this hook, so guarantee the shell.\n if (appShell) urls.add(withBase(base, appShell));\n for (const file of Object.keys(bundle)) {\n if (file === fileName) continue;\n if (exclude.test(file)) continue;\n if (!includeHtml && file.endsWith(\".html\")) continue;\n urls.add(joinBase(base, file));\n }\n\n const list = [...urls].sort();\n const version = hash(list.join(\"\\n\"));\n this.emitFile({\n type: \"asset\",\n fileName,\n source: JSON.stringify({ version, urls: list }),\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":";AAqCA,SAAS,EAAS,GAAc,GAAsB;CAElD,OAAO,GADQ,EAAK,SAAS,GAAG,IAAI,IAAO,GAAG,EAAK,KAChC,IAAO,QAAQ,gBAAgB,IAAI;AAC1D;AASA,SAAS,EAAS,GAAc,GAAqB;CACjD,IAAM,IAAS,EAAK,SAAS,GAAG,IAAI,IAAO,GAAG,EAAK;CAGnD,OAFI,MAAW,MAAY,EAAI,WAAW,GAAG,IAAI,IAAM,IAAI,MACvD,EAAI,WAAW,CAAM,IAAU,IAC5B,GAAG,IAAS,EAAI,QAAQ,OAAO,EAAE;AAC5C;AAGA,SAAS,EAAK,GAAuB;CACjC,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAC9B,KAAM,KAAK,KAAK,IAAI,EAAM,WAAW,CAAC,MAAO;CAEjD,OAAO,EAAE,SAAS,EAAE;AACxB;AAiBA,SAAgB,EAAmB,IAAqC,CAAC,GAAsB;CAC3F,IAAM,EACF,cAAW,0BACX,oBAAiB,CAAC,GAClB,aAAU,UACV,iBAAc,IACd,cAAW,kBACX,GAEA,IAAO;CA6BX,OAAO;EA1BH,MAAM;EACN,OAAO;EACP,eAAe,GAAQ;GACnB,IAAO,EAAO,QAAQ;EAC1B;EACA,eAAe,GAAgB,GAAQ;GACnC,IAAM,IAAO,IAAI,IAAY,EAAe,KAAK,MAAQ,EAAS,GAAM,CAAG,CAAC,CAAC;GAE7E,AAAI,KAAU,EAAK,IAAI,EAAS,GAAM,CAAQ,CAAC;GAC/C,KAAK,IAAM,KAAQ,OAAO,KAAK,CAAM,GAC7B,MAAS,MACT,EAAQ,KAAK,CAAI,KACjB,CAAC,KAAe,EAAK,SAAS,OAAO,KACzC,EAAK,IAAI,EAAS,GAAM,CAAI,CAAC;GAGjC,IAAM,IAAO,CAAC,GAAG,CAAI,CAAC,CAAC,KAAK,GACtB,IAAU,EAAK,EAAK,KAAK,IAAI,CAAC;GACpC,KAAK,SAAS;IACV,MAAM;IACN;IACA,QAAQ,KAAK,UAAU;KAAE;KAAS,MAAM;IAAK,CAAC;GAClD,CAAC;EACL;CAGG;AACX"}
1
+ {"version":3,"file":"tempest-pwa-manifest.js","names":[],"sources":["../../src/vite/tempest-pwa-manifest.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { basePrefix } from \"./base-url\";\n\n/**\n * A Vite plugin object. Typed loosely so the SDK's published declarations stay\n * free of `vite`'s internal types (which the `.d.ts` rollup can't analyze);\n * assign the result straight into a `plugins: [...]` array.\n */\nexport type TempestVitePlugin = { name: string } & Record<string, unknown>;\n\n/** Options for {@link tempestPwaManifest}. */\nexport interface TempestPwaManifestOptions {\n /** Output file name (under the build root). Default `precache-manifest.json`. */\n fileName?: string;\n /**\n * Extra URLs to precache that Vite doesn't emit into the bundle — typically\n * `public/` assets like the web manifest and icons. Default `[]`.\n *\n * Write these relative to the site root (`/icon.svg`); the resolved Vite\n * `base` is prefixed for you. An entry that already carries the base is\n * left alone, so spelling it out by hand is still correct.\n */\n additionalUrls?: string[];\n /** Emitted files matching this are skipped. Default `/\\.map$/` (source maps). */\n exclude?: RegExp;\n /** Include emitted `.html` documents (the app shell). Default `true`. */\n includeHtml?: boolean;\n /**\n * App-shell document always added to the manifest, even if Vite emits it\n * after this plugin runs. Must match `installPrecache`'s `navigateFallback`\n * so offline navigations resolve. Pass `false` to disable. Default `/index.html`.\n *\n * Like {@link TempestPwaManifestOptions.additionalUrls}, this is prefixed\n * with the resolved Vite `base`.\n */\n appShell?: string | false;\n}\n\nfunction joinBase(base: string, file: string): string {\n return `${basePrefix(base)}${file}`.replace(/([^:]\\/)\\/+/g, \"$1\");\n}\n\n/**\n * Prefix a caller-supplied, root-absolute URL with the resolved Vite `base`.\n *\n * Idempotent: a URL that already starts with the base is returned untouched,\n * so configs written before this was applied — spelling the base out by hand —\n * keep producing the same manifest instead of gaining a doubled prefix.\n */\nfunction withBase(base: string, url: string): string {\n const prefix = basePrefix(base);\n if (prefix === \"/\") return url.startsWith(\"/\") ? url : `/${url}`;\n if (url.startsWith(prefix)) return url;\n return `${prefix}${url.replace(/^\\//, \"\")}`;\n}\n\n/** Deterministic djb2 hash → hex. Stable across rebuilds with the same assets. */\nfunction hash(input: string): string {\n let h = 5381;\n for (let i = 0; i < input.length; i++) {\n h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;\n }\n return h.toString(16);\n}\n\n/**\n * Vite build plugin that emits a `precache-manifest.json` listing every built\n * asset (plus any `additionalUrls`) as root-absolute URLs, with a content-based\n * `version`. It is the dependency-free counterpart to Workbox's `__WB_MANIFEST`:\n * `installPrecache` (from `tempest-react-sdk/sw`) reads this file at the service\n * worker's `install` event to cache the app shell for offline use.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaManifest } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({\n * plugins: [tempestPwaManifest({ additionalUrls: [\"/manifest.webmanifest\", \"/icon.svg\"] })],\n * });\n */\nexport function tempestPwaManifest(options: TempestPwaManifestOptions = {}): TempestVitePlugin {\n const {\n fileName = \"precache-manifest.json\",\n additionalUrls = [],\n exclude = /\\.map$/,\n includeHtml = true,\n appShell = \"/index.html\",\n } = options;\n\n let base = \"/\";\n\n const plugin: Plugin = {\n name: \"tempest-pwa-manifest\",\n apply: \"build\",\n configResolved(config) {\n base = config.base ?? \"/\";\n },\n generateBundle(_outputOptions, bundle) {\n const urls = new Set<string>(additionalUrls.map((url) => withBase(base, url)));\n // Vite may emit index.html after this hook, so guarantee the shell.\n if (appShell) urls.add(withBase(base, appShell));\n for (const file of Object.keys(bundle)) {\n if (file === fileName) continue;\n if (exclude.test(file)) continue;\n if (!includeHtml && file.endsWith(\".html\")) continue;\n urls.add(joinBase(base, file));\n }\n\n const list = [...urls].sort();\n const version = hash(list.join(\"\\n\"));\n this.emitFile({\n type: \"asset\",\n fileName,\n source: JSON.stringify({ version, urls: list }),\n });\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n"],"mappings":";;AAsCA,SAAS,EAAS,GAAc,GAAsB;CAClD,OAAO,GAAG,EAAW,CAAI,IAAI,IAAO,QAAQ,gBAAgB,IAAI;AACpE;AASA,SAAS,EAAS,GAAc,GAAqB;CACjD,IAAM,IAAS,EAAW,CAAI;CAG9B,OAFI,MAAW,MAAY,EAAI,WAAW,GAAG,IAAI,IAAM,IAAI,MACvD,EAAI,WAAW,CAAM,IAAU,IAC5B,GAAG,IAAS,EAAI,QAAQ,OAAO,EAAE;AAC5C;AAGA,SAAS,EAAK,GAAuB;CACjC,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAC9B,KAAM,KAAK,KAAK,IAAI,EAAM,WAAW,CAAC,MAAO;CAEjD,OAAO,EAAE,SAAS,EAAE;AACxB;AAiBA,SAAgB,EAAmB,IAAqC,CAAC,GAAsB;CAC3F,IAAM,EACF,cAAW,0BACX,oBAAiB,CAAC,GAClB,aAAU,UACV,iBAAc,IACd,cAAW,kBACX,GAEA,IAAO;CA6BX,OAAO;EA1BH,MAAM;EACN,OAAO;EACP,eAAe,GAAQ;GACnB,IAAO,EAAO,QAAQ;EAC1B;EACA,eAAe,GAAgB,GAAQ;GACnC,IAAM,IAAO,IAAI,IAAY,EAAe,KAAK,MAAQ,EAAS,GAAM,CAAG,CAAC,CAAC;GAE7E,AAAI,KAAU,EAAK,IAAI,EAAS,GAAM,CAAQ,CAAC;GAC/C,KAAK,IAAM,KAAQ,OAAO,KAAK,CAAM,GAC7B,MAAS,MACT,EAAQ,KAAK,CAAI,KACjB,CAAC,KAAe,EAAK,SAAS,OAAO,KACzC,EAAK,IAAI,EAAS,GAAM,CAAI,CAAC;GAGjC,IAAM,IAAO,CAAC,GAAG,CAAI,CAAC,CAAC,KAAK,GACtB,IAAU,EAAK,EAAK,KAAK,IAAI,CAAC;GACpC,KAAK,SAAS;IACV,MAAM;IACN;IACA,QAAQ,KAAK,UAAU;KAAE;KAAS,MAAM;IAAK,CAAC;GAClD,CAAC;EACL;CAGG;AACX"}
package/dist/vite.d.ts CHANGED
@@ -121,8 +121,8 @@ export declare interface TempestIconsOptions {
121
121
  *
122
122
  * The production worker is bundled at build time (`vite.sw.config.ts`), so in
123
123
  * dev there is no `/sw.js` to register. This plugin compiles `swSrc` on the fly
124
- * with esbuild and serves it as a classic worker, plus an empty
125
- * `precache-manifest.json` (there are no hashed build assets to precache in
124
+ * with esbuild through one incremental context, not a cold build per request
125
+ * and serves it as a classic worker, plus an empty `precache-manifest.json` (there are no hashed build assets to precache in
126
126
  * dev — push and runtime caching still work). It closes the "SW in dev" gap
127
127
  * that otherwise only `vite-plugin-pwa`'s `devOptions` covered.
128
128
  *
@@ -1,2 +1,2 @@
1
- const e=require("./create-web-socket.cjs");let t=require("react");function n(e){try{return JSON.parse(e)}catch{return e}}function r(r,i={}){let{enabled:a=!0,protocols:o,maxRetries:s,initialBackoff:c,maxBackoff:l,pingInterval:u,respondToPing:d,queueWhileClosed:f,maxQueuedMessages:p}=i,[m,h]=(0,t.useState)(`idle`),[g,_]=(0,t.useState)(null),v=(0,t.useRef)(null),y=(0,t.useRef)(i);(0,t.useEffect)(()=>{y.current=i});let b=Array.isArray(o)?o.join(`,`):o??``;return(0,t.useEffect)(()=>{if(!a||!r){h(`idle`);return}let t=e.createWebSocket(r,{protocols:y.current.protocols,maxRetries:s,initialBackoff:c,maxBackoff:l,pingInterval:u,pingPayload:y.current.pingPayload,respondToPing:d,pongPayload:y.current.pongPayload,queueWhileClosed:f,maxQueuedMessages:p,parser:e=>(y.current.parser??n)(e),onStatusChange:h,onOpen:e=>y.current.onOpen?.(e),onClose:e=>y.current.onClose?.(e),onError:e=>y.current.onError?.(e),onMessage:e=>{_(e),y.current.onMessage?.(e)}});return v.current=t,()=>{t.close(),v.current=null}},[r,a,b,s,c,l,u,d,f,p]),{status:m,lastMessage:g,send:(0,t.useCallback)(e=>v.current?.send(e)??!1,[]),reconnect:(0,t.useCallback)(()=>{v.current?.reconnect()},[])}}exports.useWebSocket=r;
1
+ const e=require("../hooks/use-latest-ref.cjs"),t=require("./create-web-socket.cjs");let n=require("react");function r(e){try{return JSON.parse(e)}catch{return e}}function i(i,a={}){let{enabled:o=!0,protocols:s,maxRetries:c,initialBackoff:l,maxBackoff:u,pingInterval:d,respondToPing:f,queueWhileClosed:p,maxQueuedMessages:m}=a,[h,g]=(0,n.useState)(`idle`),[_,v]=(0,n.useState)(null),y=(0,n.useRef)(null),b=e.useLatestRef(a),x=Array.isArray(s)?s.join(`,`):s??``;return(0,n.useEffect)(()=>{if(!o||!i){g(`idle`);return}let e=t.createWebSocket(i,{protocols:b.current.protocols,maxRetries:c,initialBackoff:l,maxBackoff:u,pingInterval:d,pingPayload:b.current.pingPayload,respondToPing:f,pongPayload:b.current.pongPayload,queueWhileClosed:p,maxQueuedMessages:m,parser:e=>(b.current.parser??r)(e),onStatusChange:g,onOpen:e=>b.current.onOpen?.(e),onClose:e=>b.current.onClose?.(e),onError:e=>b.current.onError?.(e),onMessage:e=>{v(e),b.current.onMessage?.(e)}});return y.current=e,()=>{e.close(),y.current=null}},[i,o,x,c,l,u,d,f,p,m,b]),{status:h,lastMessage:_,send:(0,n.useCallback)(e=>y.current?.send(e)??!1,[]),reconnect:(0,n.useCallback)(()=>{y.current?.reconnect()},[])}}exports.useWebSocket=i;
2
2
  //# sourceMappingURL=use-web-socket.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-web-socket.cjs","names":[],"sources":["../../src/ws/use-web-socket.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n createWebSocket,\n type CreateWebSocketOptions,\n type WebSocketController,\n type WebSocketMessage,\n type WebSocketStatus,\n} from \"./create-web-socket\";\n\nexport interface UseWebSocketOptions<T> extends Omit<CreateWebSocketOptions<T>, \"onStatusChange\"> {\n /** When false, the socket is not opened. Default: true. */\n enabled?: boolean;\n}\n\nexport interface UseWebSocketResult<T> {\n status: WebSocketStatus;\n /**\n * Last decoded frame received.\n *\n * A snapshot, not a stream: two frames arriving in the same tick collapse\n * into a single render and only the later one is ever visible. One server\n * action often emits several frames in a row, so anything that must see\n * every message has to use `onMessage`, which fires once per frame. Read\n * `lastMessage` for \"what is the current state\" rendering only.\n */\n lastMessage: WebSocketMessage<T> | null;\n /** Send a payload through the active connection. Returns false when not open. */\n send: (payload: string | Blob | BufferSource) => boolean;\n /** Force a reconnect, resetting the retry counter. */\n reconnect: () => void;\n}\n\n/** Mirror of `createWebSocket`'s default parser: JSON, raw string on failure. */\nfunction defaultParse<T>(raw: string): T {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return raw as unknown as T;\n }\n}\n\n/**\n * React hook around {@link createWebSocket}. Manages the connection lifecycle\n * for the host component and tears it down on unmount.\n *\n * Every callback is read through a ref, so `onOpen` / `onMessage` / `onClose` /\n * `onError` always run the latest closure — an inline arrow function is fine\n * and never reopens the socket. Connection-shaping options (`protocols`,\n * `maxRetries`, `initialBackoff`, `maxBackoff`, `pingInterval`,\n * `queueWhileClosed`) are baked into the connection, so changing one reopens\n * it with the new value rather than being silently ignored.\n *\n * @param url - Full ws:// or wss:// URL.\n * @param options - Connection configuration and callbacks.\n * @returns Status, last frame, and the `send` / `reconnect` controls.\n */\nexport function useWebSocket<T = unknown>(\n url: string,\n options: UseWebSocketOptions<T> = {},\n): UseWebSocketResult<T> {\n const {\n enabled = true,\n protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n } = options;\n const [status, setStatus] = useState<WebSocketStatus>(\"idle\");\n const [lastMessage, setLastMessage] = useState<WebSocketMessage<T> | null>(null);\n const controllerRef = useRef<WebSocketController | null>(null);\n\n const optionsRef = useRef(options);\n useEffect(() => {\n optionsRef.current = options;\n });\n\n const protocolsKey = Array.isArray(protocols) ? protocols.join(\",\") : (protocols ?? \"\");\n\n useEffect(() => {\n if (!enabled || !url) {\n setStatus(\"idle\");\n return;\n }\n\n const controller = createWebSocket<T>(url, {\n protocols: optionsRef.current.protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n pingPayload: optionsRef.current.pingPayload,\n respondToPing,\n pongPayload: optionsRef.current.pongPayload,\n queueWhileClosed,\n maxQueuedMessages,\n parser: (raw) => (optionsRef.current.parser ?? defaultParse<T>)(raw),\n onStatusChange: setStatus,\n onOpen: (event) => optionsRef.current.onOpen?.(event),\n onClose: (event) => optionsRef.current.onClose?.(event),\n onError: (event) => optionsRef.current.onError?.(event),\n onMessage: (message) => {\n setLastMessage(message);\n optionsRef.current.onMessage?.(message);\n },\n });\n controllerRef.current = controller;\n\n return () => {\n controller.close();\n controllerRef.current = null;\n };\n }, [\n url,\n enabled,\n protocolsKey,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n ]);\n\n const send = useCallback((payload: string | Blob | BufferSource): boolean => {\n return controllerRef.current?.send(payload) ?? false;\n }, []);\n\n const reconnect = useCallback((): void => {\n controllerRef.current?.reconnect();\n }, []);\n\n return { status, lastMessage, send, reconnect };\n}\n"],"mappings":"kEAiCA,SAAS,EAAgB,EAAgB,CACrC,GAAI,CACA,OAAO,KAAK,MAAM,CAAG,CACzB,MAAQ,CACJ,OAAO,CACX,CACJ,CAiBA,SAAgB,EACZ,EACA,EAAkC,CAAC,EACd,CACrB,GAAM,CACF,UAAU,GACV,YACA,aACA,iBACA,aACA,eACA,gBACA,mBACA,qBACA,EACE,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAA0B,MAAM,EACtD,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAqC,IAAI,EACzE,GAAA,EAAgB,EAAA,OAAA,CAAmC,IAAI,EAEvD,GAAA,EAAa,EAAA,OAAA,CAAO,CAAO,GACjC,EAAA,EAAA,UAAA,KAAgB,CACZ,EAAW,QAAU,CACzB,CAAC,EAED,IAAM,EAAe,MAAM,QAAQ,CAAS,EAAI,EAAU,KAAK,GAAG,EAAK,GAAa,GAwDpF,OAtDA,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,CAAC,GAAW,CAAC,EAAK,CAClB,EAAU,MAAM,EAChB,MACJ,CAEA,IAAM,EAAa,EAAA,gBAAmB,EAAK,CACvC,UAAW,EAAW,QAAQ,UAC9B,aACA,iBACA,aACA,eACA,YAAa,EAAW,QAAQ,YAChC,gBACA,YAAa,EAAW,QAAQ,YAChC,mBACA,oBACA,OAAS,IAAS,EAAW,QAAQ,QAAU,EAAA,CAAiB,CAAG,EACnE,eAAgB,EAChB,OAAS,GAAU,EAAW,QAAQ,SAAS,CAAK,EACpD,QAAU,GAAU,EAAW,QAAQ,UAAU,CAAK,EACtD,QAAU,GAAU,EAAW,QAAQ,UAAU,CAAK,EACtD,UAAY,GAAY,CACpB,EAAe,CAAO,EACtB,EAAW,QAAQ,YAAY,CAAO,CAC1C,CACJ,CAAC,EAGD,MAFA,GAAc,QAAU,MAEX,CACT,EAAW,MAAM,EACjB,EAAc,QAAU,IAC5B,CACJ,EAAG,CACC,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,CACJ,CAAC,EAUM,CAAE,SAAQ,cAAa,MAAA,EARjB,EAAA,YAAA,CAAa,GACf,EAAc,SAAS,KAAK,CAAO,GAAK,GAChD,CAAC,CAM0B,EAAM,WAAA,EAJlB,EAAA,YAAA,KAAwB,CACtC,EAAc,SAAS,UAAU,CACrC,EAAG,CAAC,CAEgC,CAAU,CAClD"}
1
+ {"version":3,"file":"use-web-socket.cjs","names":[],"sources":["../../src/ws/use-web-socket.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useLatestRef } from \"@/hooks/use-latest-ref\";\nimport {\n createWebSocket,\n type CreateWebSocketOptions,\n type WebSocketController,\n type WebSocketMessage,\n type WebSocketStatus,\n} from \"./create-web-socket\";\n\nexport interface UseWebSocketOptions<T> extends Omit<CreateWebSocketOptions<T>, \"onStatusChange\"> {\n /** When false, the socket is not opened. Default: true. */\n enabled?: boolean;\n}\n\nexport interface UseWebSocketResult<T> {\n status: WebSocketStatus;\n /**\n * Last decoded frame received.\n *\n * A snapshot, not a stream: two frames arriving in the same tick collapse\n * into a single render and only the later one is ever visible. One server\n * action often emits several frames in a row, so anything that must see\n * every message has to use `onMessage`, which fires once per frame. Read\n * `lastMessage` for \"what is the current state\" rendering only.\n */\n lastMessage: WebSocketMessage<T> | null;\n /** Send a payload through the active connection. Returns false when not open. */\n send: (payload: string | Blob | BufferSource) => boolean;\n /** Force a reconnect, resetting the retry counter. */\n reconnect: () => void;\n}\n\n/** Mirror of `createWebSocket`'s default parser: JSON, raw string on failure. */\nfunction defaultParse<T>(raw: string): T {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return raw as unknown as T;\n }\n}\n\n/**\n * React hook around {@link createWebSocket}. Manages the connection lifecycle\n * for the host component and tears it down on unmount.\n *\n * Every callback is read through a ref, so `onOpen` / `onMessage` / `onClose` /\n * `onError` always run the latest closure — an inline arrow function is fine\n * and never reopens the socket. Connection-shaping options (`protocols`,\n * `maxRetries`, `initialBackoff`, `maxBackoff`, `pingInterval`,\n * `queueWhileClosed`) are baked into the connection, so changing one reopens\n * it with the new value rather than being silently ignored.\n *\n * @param url - Full ws:// or wss:// URL.\n * @param options - Connection configuration and callbacks.\n * @returns Status, last frame, and the `send` / `reconnect` controls.\n */\nexport function useWebSocket<T = unknown>(\n url: string,\n options: UseWebSocketOptions<T> = {},\n): UseWebSocketResult<T> {\n const {\n enabled = true,\n protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n } = options;\n const [status, setStatus] = useState<WebSocketStatus>(\"idle\");\n const [lastMessage, setLastMessage] = useState<WebSocketMessage<T> | null>(null);\n const controllerRef = useRef<WebSocketController | null>(null);\n\n const optionsRef = useLatestRef(options);\n\n const protocolsKey = Array.isArray(protocols) ? protocols.join(\",\") : (protocols ?? \"\");\n\n useEffect(() => {\n if (!enabled || !url) {\n setStatus(\"idle\");\n return;\n }\n\n const controller = createWebSocket<T>(url, {\n protocols: optionsRef.current.protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n pingPayload: optionsRef.current.pingPayload,\n respondToPing,\n pongPayload: optionsRef.current.pongPayload,\n queueWhileClosed,\n maxQueuedMessages,\n parser: (raw) => (optionsRef.current.parser ?? defaultParse<T>)(raw),\n onStatusChange: setStatus,\n onOpen: (event) => optionsRef.current.onOpen?.(event),\n onClose: (event) => optionsRef.current.onClose?.(event),\n onError: (event) => optionsRef.current.onError?.(event),\n onMessage: (message) => {\n setLastMessage(message);\n optionsRef.current.onMessage?.(message);\n },\n });\n controllerRef.current = controller;\n\n return () => {\n controller.close();\n controllerRef.current = null;\n };\n }, [\n url,\n enabled,\n protocolsKey,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n optionsRef,\n ]);\n\n const send = useCallback((payload: string | Blob | BufferSource): boolean => {\n return controllerRef.current?.send(payload) ?? false;\n }, []);\n\n const reconnect = useCallback((): void => {\n controllerRef.current?.reconnect();\n }, []);\n\n return { status, lastMessage, send, reconnect };\n}\n"],"mappings":"2GAkCA,SAAS,EAAgB,EAAgB,CACrC,GAAI,CACA,OAAO,KAAK,MAAM,CAAG,CACzB,MAAQ,CACJ,OAAO,CACX,CACJ,CAiBA,SAAgB,EACZ,EACA,EAAkC,CAAC,EACd,CACrB,GAAM,CACF,UAAU,GACV,YACA,aACA,iBACA,aACA,eACA,gBACA,mBACA,qBACA,EACE,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAA0B,MAAM,EACtD,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAqC,IAAI,EACzE,GAAA,EAAgB,EAAA,OAAA,CAAmC,IAAI,EAEvD,EAAa,EAAA,aAAa,CAAO,EAEjC,EAAe,MAAM,QAAQ,CAAS,EAAI,EAAU,KAAK,GAAG,EAAK,GAAa,GAyDpF,OAvDA,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,CAAC,GAAW,CAAC,EAAK,CAClB,EAAU,MAAM,EAChB,MACJ,CAEA,IAAM,EAAa,EAAA,gBAAmB,EAAK,CACvC,UAAW,EAAW,QAAQ,UAC9B,aACA,iBACA,aACA,eACA,YAAa,EAAW,QAAQ,YAChC,gBACA,YAAa,EAAW,QAAQ,YAChC,mBACA,oBACA,OAAS,IAAS,EAAW,QAAQ,QAAU,EAAA,CAAiB,CAAG,EACnE,eAAgB,EAChB,OAAS,GAAU,EAAW,QAAQ,SAAS,CAAK,EACpD,QAAU,GAAU,EAAW,QAAQ,UAAU,CAAK,EACtD,QAAU,GAAU,EAAW,QAAQ,UAAU,CAAK,EACtD,UAAY,GAAY,CACpB,EAAe,CAAO,EACtB,EAAW,QAAQ,YAAY,CAAO,CAC1C,CACJ,CAAC,EAGD,MAFA,GAAc,QAAU,MAEX,CACT,EAAW,MAAM,EACjB,EAAc,QAAU,IAC5B,CACJ,EAAG,CACC,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,CACJ,CAAC,EAUM,CAAE,SAAQ,cAAa,MAAA,EARjB,EAAA,YAAA,CAAa,GACf,EAAc,SAAS,KAAK,CAAO,GAAK,GAChD,CAAC,CAM0B,EAAM,WAAA,EAJlB,EAAA,YAAA,KAAwB,CACtC,EAAc,SAAS,UAAU,CACrC,EAAG,CAAC,CAEgC,CAAU,CAClD"}
@@ -1,68 +1,66 @@
1
- import { createWebSocket as e } from "./create-web-socket.js";
2
- import { useCallback as t, useEffect as n, useRef as r, useState as i } from "react";
1
+ import { useLatestRef as e } from "../hooks/use-latest-ref.js";
2
+ import { createWebSocket as t } from "./create-web-socket.js";
3
+ import { useCallback as n, useEffect as r, useRef as i, useState as a } from "react";
3
4
  //#region src/ws/use-web-socket.ts
4
- function a(e) {
5
+ function o(e) {
5
6
  try {
6
7
  return JSON.parse(e);
7
8
  } catch {
8
9
  return e;
9
10
  }
10
11
  }
11
- function o(o, s = {}) {
12
- let { enabled: c = !0, protocols: l, maxRetries: u, initialBackoff: d, maxBackoff: f, pingInterval: p, respondToPing: m, queueWhileClosed: h, maxQueuedMessages: g } = s, [_, v] = i("idle"), [y, b] = i(null), x = r(null), S = r(s);
13
- n(() => {
14
- S.current = s;
15
- });
16
- let C = Array.isArray(l) ? l.join(",") : l ?? "";
17
- return n(() => {
18
- if (!c || !o) {
19
- v("idle");
12
+ function s(s, c = {}) {
13
+ let { enabled: l = !0, protocols: u, maxRetries: d, initialBackoff: f, maxBackoff: p, pingInterval: m, respondToPing: h, queueWhileClosed: g, maxQueuedMessages: _ } = c, [v, y] = a("idle"), [b, x] = a(null), S = i(null), C = e(c), w = Array.isArray(u) ? u.join(",") : u ?? "";
14
+ return r(() => {
15
+ if (!l || !s) {
16
+ y("idle");
20
17
  return;
21
18
  }
22
- let t = e(o, {
23
- protocols: S.current.protocols,
24
- maxRetries: u,
25
- initialBackoff: d,
26
- maxBackoff: f,
27
- pingInterval: p,
28
- pingPayload: S.current.pingPayload,
29
- respondToPing: m,
30
- pongPayload: S.current.pongPayload,
31
- queueWhileClosed: h,
32
- maxQueuedMessages: g,
33
- parser: (e) => (S.current.parser ?? a)(e),
34
- onStatusChange: v,
35
- onOpen: (e) => S.current.onOpen?.(e),
36
- onClose: (e) => S.current.onClose?.(e),
37
- onError: (e) => S.current.onError?.(e),
19
+ let e = t(s, {
20
+ protocols: C.current.protocols,
21
+ maxRetries: d,
22
+ initialBackoff: f,
23
+ maxBackoff: p,
24
+ pingInterval: m,
25
+ pingPayload: C.current.pingPayload,
26
+ respondToPing: h,
27
+ pongPayload: C.current.pongPayload,
28
+ queueWhileClosed: g,
29
+ maxQueuedMessages: _,
30
+ parser: (e) => (C.current.parser ?? o)(e),
31
+ onStatusChange: y,
32
+ onOpen: (e) => C.current.onOpen?.(e),
33
+ onClose: (e) => C.current.onClose?.(e),
34
+ onError: (e) => C.current.onError?.(e),
38
35
  onMessage: (e) => {
39
- b(e), S.current.onMessage?.(e);
36
+ x(e), C.current.onMessage?.(e);
40
37
  }
41
38
  });
42
- return x.current = t, () => {
43
- t.close(), x.current = null;
39
+ return S.current = e, () => {
40
+ e.close(), S.current = null;
44
41
  };
45
42
  }, [
46
- o,
47
- c,
48
- C,
49
- u,
43
+ s,
44
+ l,
45
+ w,
50
46
  d,
51
47
  f,
52
48
  p,
53
49
  m,
54
50
  h,
55
- g
51
+ g,
52
+ _,
53
+ C
56
54
  ]), {
57
- status: _,
58
- lastMessage: y,
59
- send: t((e) => x.current?.send(e) ?? !1, []),
60
- reconnect: t(() => {
61
- x.current?.reconnect();
55
+ status: v,
56
+ lastMessage: b,
57
+ send: n((e) => S.current?.send(e) ?? !1, []),
58
+ reconnect: n(() => {
59
+ S.current?.reconnect();
62
60
  }, [])
63
61
  };
64
62
  }
65
63
  //#endregion
66
- export { o as useWebSocket };
64
+ export { s as useWebSocket };
67
65
 
68
66
  //# sourceMappingURL=use-web-socket.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-web-socket.js","names":[],"sources":["../../src/ws/use-web-socket.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n createWebSocket,\n type CreateWebSocketOptions,\n type WebSocketController,\n type WebSocketMessage,\n type WebSocketStatus,\n} from \"./create-web-socket\";\n\nexport interface UseWebSocketOptions<T> extends Omit<CreateWebSocketOptions<T>, \"onStatusChange\"> {\n /** When false, the socket is not opened. Default: true. */\n enabled?: boolean;\n}\n\nexport interface UseWebSocketResult<T> {\n status: WebSocketStatus;\n /**\n * Last decoded frame received.\n *\n * A snapshot, not a stream: two frames arriving in the same tick collapse\n * into a single render and only the later one is ever visible. One server\n * action often emits several frames in a row, so anything that must see\n * every message has to use `onMessage`, which fires once per frame. Read\n * `lastMessage` for \"what is the current state\" rendering only.\n */\n lastMessage: WebSocketMessage<T> | null;\n /** Send a payload through the active connection. Returns false when not open. */\n send: (payload: string | Blob | BufferSource) => boolean;\n /** Force a reconnect, resetting the retry counter. */\n reconnect: () => void;\n}\n\n/** Mirror of `createWebSocket`'s default parser: JSON, raw string on failure. */\nfunction defaultParse<T>(raw: string): T {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return raw as unknown as T;\n }\n}\n\n/**\n * React hook around {@link createWebSocket}. Manages the connection lifecycle\n * for the host component and tears it down on unmount.\n *\n * Every callback is read through a ref, so `onOpen` / `onMessage` / `onClose` /\n * `onError` always run the latest closure — an inline arrow function is fine\n * and never reopens the socket. Connection-shaping options (`protocols`,\n * `maxRetries`, `initialBackoff`, `maxBackoff`, `pingInterval`,\n * `queueWhileClosed`) are baked into the connection, so changing one reopens\n * it with the new value rather than being silently ignored.\n *\n * @param url - Full ws:// or wss:// URL.\n * @param options - Connection configuration and callbacks.\n * @returns Status, last frame, and the `send` / `reconnect` controls.\n */\nexport function useWebSocket<T = unknown>(\n url: string,\n options: UseWebSocketOptions<T> = {},\n): UseWebSocketResult<T> {\n const {\n enabled = true,\n protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n } = options;\n const [status, setStatus] = useState<WebSocketStatus>(\"idle\");\n const [lastMessage, setLastMessage] = useState<WebSocketMessage<T> | null>(null);\n const controllerRef = useRef<WebSocketController | null>(null);\n\n const optionsRef = useRef(options);\n useEffect(() => {\n optionsRef.current = options;\n });\n\n const protocolsKey = Array.isArray(protocols) ? protocols.join(\",\") : (protocols ?? \"\");\n\n useEffect(() => {\n if (!enabled || !url) {\n setStatus(\"idle\");\n return;\n }\n\n const controller = createWebSocket<T>(url, {\n protocols: optionsRef.current.protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n pingPayload: optionsRef.current.pingPayload,\n respondToPing,\n pongPayload: optionsRef.current.pongPayload,\n queueWhileClosed,\n maxQueuedMessages,\n parser: (raw) => (optionsRef.current.parser ?? defaultParse<T>)(raw),\n onStatusChange: setStatus,\n onOpen: (event) => optionsRef.current.onOpen?.(event),\n onClose: (event) => optionsRef.current.onClose?.(event),\n onError: (event) => optionsRef.current.onError?.(event),\n onMessage: (message) => {\n setLastMessage(message);\n optionsRef.current.onMessage?.(message);\n },\n });\n controllerRef.current = controller;\n\n return () => {\n controller.close();\n controllerRef.current = null;\n };\n }, [\n url,\n enabled,\n protocolsKey,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n ]);\n\n const send = useCallback((payload: string | Blob | BufferSource): boolean => {\n return controllerRef.current?.send(payload) ?? false;\n }, []);\n\n const reconnect = useCallback((): void => {\n controllerRef.current?.reconnect();\n }, []);\n\n return { status, lastMessage, send, reconnect };\n}\n"],"mappings":";;;AAiCA,SAAS,EAAgB,GAAgB;CACrC,IAAI;EACA,OAAO,KAAK,MAAM,CAAG;CACzB,QAAQ;EACJ,OAAO;CACX;AACJ;AAiBA,SAAgB,EACZ,GACA,IAAkC,CAAC,GACd;CACrB,IAAM,EACF,aAAU,IACV,cACA,eACA,mBACA,eACA,iBACA,kBACA,qBACA,yBACA,GACE,CAAC,GAAQ,KAAa,EAA0B,MAAM,GACtD,CAAC,GAAa,KAAkB,EAAqC,IAAI,GACzE,IAAgB,EAAmC,IAAI,GAEvD,IAAa,EAAO,CAAO;CACjC,QAAgB;EACZ,EAAW,UAAU;CACzB,CAAC;CAED,IAAM,IAAe,MAAM,QAAQ,CAAS,IAAI,EAAU,KAAK,GAAG,IAAK,KAAa;CAwDpF,OAtDA,QAAgB;EACZ,IAAI,CAAC,KAAW,CAAC,GAAK;GAClB,EAAU,MAAM;GAChB;EACJ;EAEA,IAAM,IAAa,EAAmB,GAAK;GACvC,WAAW,EAAW,QAAQ;GAC9B;GACA;GACA;GACA;GACA,aAAa,EAAW,QAAQ;GAChC;GACA,aAAa,EAAW,QAAQ;GAChC;GACA;GACA,SAAS,OAAS,EAAW,QAAQ,UAAU,EAAA,CAAiB,CAAG;GACnE,gBAAgB;GAChB,SAAS,MAAU,EAAW,QAAQ,SAAS,CAAK;GACpD,UAAU,MAAU,EAAW,QAAQ,UAAU,CAAK;GACtD,UAAU,MAAU,EAAW,QAAQ,UAAU,CAAK;GACtD,YAAY,MAAY;IAEpB,AADA,EAAe,CAAO,GACtB,EAAW,QAAQ,YAAY,CAAO;GAC1C;EACJ,CAAC;EAGD,OAFA,EAAc,UAAU,SAEX;GAET,AADA,EAAW,MAAM,GACjB,EAAc,UAAU;EAC5B;CACJ,GAAG;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACJ,CAAC,GAUM;EAAE;EAAQ;EAAa,MARjB,GAAa,MACf,EAAc,SAAS,KAAK,CAAO,KAAK,IAChD,CAAC,CAM0B;EAAM,WAJlB,QAAwB;GACtC,EAAc,SAAS,UAAU;EACrC,GAAG,CAAC,CAEgC;CAAU;AAClD"}
1
+ {"version":3,"file":"use-web-socket.js","names":[],"sources":["../../src/ws/use-web-socket.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useLatestRef } from \"@/hooks/use-latest-ref\";\nimport {\n createWebSocket,\n type CreateWebSocketOptions,\n type WebSocketController,\n type WebSocketMessage,\n type WebSocketStatus,\n} from \"./create-web-socket\";\n\nexport interface UseWebSocketOptions<T> extends Omit<CreateWebSocketOptions<T>, \"onStatusChange\"> {\n /** When false, the socket is not opened. Default: true. */\n enabled?: boolean;\n}\n\nexport interface UseWebSocketResult<T> {\n status: WebSocketStatus;\n /**\n * Last decoded frame received.\n *\n * A snapshot, not a stream: two frames arriving in the same tick collapse\n * into a single render and only the later one is ever visible. One server\n * action often emits several frames in a row, so anything that must see\n * every message has to use `onMessage`, which fires once per frame. Read\n * `lastMessage` for \"what is the current state\" rendering only.\n */\n lastMessage: WebSocketMessage<T> | null;\n /** Send a payload through the active connection. Returns false when not open. */\n send: (payload: string | Blob | BufferSource) => boolean;\n /** Force a reconnect, resetting the retry counter. */\n reconnect: () => void;\n}\n\n/** Mirror of `createWebSocket`'s default parser: JSON, raw string on failure. */\nfunction defaultParse<T>(raw: string): T {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return raw as unknown as T;\n }\n}\n\n/**\n * React hook around {@link createWebSocket}. Manages the connection lifecycle\n * for the host component and tears it down on unmount.\n *\n * Every callback is read through a ref, so `onOpen` / `onMessage` / `onClose` /\n * `onError` always run the latest closure — an inline arrow function is fine\n * and never reopens the socket. Connection-shaping options (`protocols`,\n * `maxRetries`, `initialBackoff`, `maxBackoff`, `pingInterval`,\n * `queueWhileClosed`) are baked into the connection, so changing one reopens\n * it with the new value rather than being silently ignored.\n *\n * @param url - Full ws:// or wss:// URL.\n * @param options - Connection configuration and callbacks.\n * @returns Status, last frame, and the `send` / `reconnect` controls.\n */\nexport function useWebSocket<T = unknown>(\n url: string,\n options: UseWebSocketOptions<T> = {},\n): UseWebSocketResult<T> {\n const {\n enabled = true,\n protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n } = options;\n const [status, setStatus] = useState<WebSocketStatus>(\"idle\");\n const [lastMessage, setLastMessage] = useState<WebSocketMessage<T> | null>(null);\n const controllerRef = useRef<WebSocketController | null>(null);\n\n const optionsRef = useLatestRef(options);\n\n const protocolsKey = Array.isArray(protocols) ? protocols.join(\",\") : (protocols ?? \"\");\n\n useEffect(() => {\n if (!enabled || !url) {\n setStatus(\"idle\");\n return;\n }\n\n const controller = createWebSocket<T>(url, {\n protocols: optionsRef.current.protocols,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n pingPayload: optionsRef.current.pingPayload,\n respondToPing,\n pongPayload: optionsRef.current.pongPayload,\n queueWhileClosed,\n maxQueuedMessages,\n parser: (raw) => (optionsRef.current.parser ?? defaultParse<T>)(raw),\n onStatusChange: setStatus,\n onOpen: (event) => optionsRef.current.onOpen?.(event),\n onClose: (event) => optionsRef.current.onClose?.(event),\n onError: (event) => optionsRef.current.onError?.(event),\n onMessage: (message) => {\n setLastMessage(message);\n optionsRef.current.onMessage?.(message);\n },\n });\n controllerRef.current = controller;\n\n return () => {\n controller.close();\n controllerRef.current = null;\n };\n }, [\n url,\n enabled,\n protocolsKey,\n maxRetries,\n initialBackoff,\n maxBackoff,\n pingInterval,\n respondToPing,\n queueWhileClosed,\n maxQueuedMessages,\n optionsRef,\n ]);\n\n const send = useCallback((payload: string | Blob | BufferSource): boolean => {\n return controllerRef.current?.send(payload) ?? false;\n }, []);\n\n const reconnect = useCallback((): void => {\n controllerRef.current?.reconnect();\n }, []);\n\n return { status, lastMessage, send, reconnect };\n}\n"],"mappings":";;;;AAkCA,SAAS,EAAgB,GAAgB;CACrC,IAAI;EACA,OAAO,KAAK,MAAM,CAAG;CACzB,QAAQ;EACJ,OAAO;CACX;AACJ;AAiBA,SAAgB,EACZ,GACA,IAAkC,CAAC,GACd;CACrB,IAAM,EACF,aAAU,IACV,cACA,eACA,mBACA,eACA,iBACA,kBACA,qBACA,yBACA,GACE,CAAC,GAAQ,KAAa,EAA0B,MAAM,GACtD,CAAC,GAAa,KAAkB,EAAqC,IAAI,GACzE,IAAgB,EAAmC,IAAI,GAEvD,IAAa,EAAa,CAAO,GAEjC,IAAe,MAAM,QAAQ,CAAS,IAAI,EAAU,KAAK,GAAG,IAAK,KAAa;CAyDpF,OAvDA,QAAgB;EACZ,IAAI,CAAC,KAAW,CAAC,GAAK;GAClB,EAAU,MAAM;GAChB;EACJ;EAEA,IAAM,IAAa,EAAmB,GAAK;GACvC,WAAW,EAAW,QAAQ;GAC9B;GACA;GACA;GACA;GACA,aAAa,EAAW,QAAQ;GAChC;GACA,aAAa,EAAW,QAAQ;GAChC;GACA;GACA,SAAS,OAAS,EAAW,QAAQ,UAAU,EAAA,CAAiB,CAAG;GACnE,gBAAgB;GAChB,SAAS,MAAU,EAAW,QAAQ,SAAS,CAAK;GACpD,UAAU,MAAU,EAAW,QAAQ,UAAU,CAAK;GACtD,UAAU,MAAU,EAAW,QAAQ,UAAU,CAAK;GACtD,YAAY,MAAY;IAEpB,AADA,EAAe,CAAO,GACtB,EAAW,QAAQ,YAAY,CAAO;GAC1C;EACJ,CAAC;EAGD,OAFA,EAAc,UAAU,SAEX;GAET,AADA,EAAW,MAAM,GACjB,EAAc,UAAU;EAC5B;CACJ,GAAG;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACJ,CAAC,GAUM;EAAE;EAAQ;EAAa,MARjB,GAAa,MACf,EAAc,SAAS,KAAK,CAAO,KAAK,IAChD,CAAC,CAM0B;EAAM,WAJlB,QAAwB;GACtC,EAAc,SAAS,UAAU;EACrC,GAAG,CAAC,CAEgC;CAAU;AAClD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tempest-react-sdk",
3
- "version": "0.48.0",
3
+ "version": "0.49.0",
4
4
  "description": "SDK público da Tempest com componentes, hooks e integrações para projetos React.",
5
5
  "type": "module",
6
6
  "license": "MIT",