tempest-react-sdk 0.7.0 → 0.8.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.
- package/README.md +41 -28
- package/bin/create-tempest-app.mjs +141 -70
- package/bin/tempest.mjs +282 -0
- package/dist/sw.cjs +2 -0
- package/dist/sw.cjs.map +1 -0
- package/dist/sw.d.ts +103 -0
- package/dist/sw.js +95 -0
- package/dist/sw.js.map +1 -0
- package/dist/tempest-react-sdk.cjs +3 -3
- package/dist/tempest-react-sdk.cjs.map +1 -1
- package/dist/tempest-react-sdk.js +1541 -1626
- package/dist/tempest-react-sdk.js.map +1 -1
- package/package.json +10 -2
- package/template/_prettierrc.json +9 -0
- package/template/eslint.config.js +18 -1
- package/template/package.json +7 -1
- package/template-pwa/README.md +64 -0
- package/template-pwa/_env.example +7 -0
- package/template-pwa/index.html +22 -0
- package/template-pwa/package.json +6 -0
- package/template-pwa/public/icon-maskable.svg +4 -0
- package/template-pwa/public/icon.svg +4 -0
- package/template-pwa/public/manifest.webmanifest +35 -0
- package/template-pwa/src/main.tsx +36 -0
- package/template-pwa/src/pages/Dashboard.tsx +73 -0
- package/template-pwa/src/sw.ts +35 -0
- package/template-pwa/src/vite-env.d.ts +12 -0
- package/template-pwa/vite.sw.config.ts +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tempest-react-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.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",
|
|
@@ -25,11 +25,13 @@
|
|
|
25
25
|
"dist",
|
|
26
26
|
"bin",
|
|
27
27
|
"template",
|
|
28
|
+
"template-pwa",
|
|
28
29
|
"README.md",
|
|
29
30
|
"LICENSE"
|
|
30
31
|
],
|
|
31
32
|
"bin": {
|
|
32
|
-
"create-tempest-app": "./bin/create-tempest-app.mjs"
|
|
33
|
+
"create-tempest-app": "./bin/create-tempest-app.mjs",
|
|
34
|
+
"tempest": "./bin/tempest.mjs"
|
|
33
35
|
},
|
|
34
36
|
"main": "./dist/tempest-react-sdk.cjs",
|
|
35
37
|
"module": "./dist/tempest-react-sdk.js",
|
|
@@ -53,6 +55,11 @@
|
|
|
53
55
|
"import": "./dist/vite.js",
|
|
54
56
|
"require": "./dist/vite.cjs"
|
|
55
57
|
},
|
|
58
|
+
"./sw": {
|
|
59
|
+
"types": "./dist/sw.d.ts",
|
|
60
|
+
"import": "./dist/sw.js",
|
|
61
|
+
"require": "./dist/sw.cjs"
|
|
62
|
+
},
|
|
56
63
|
"./styles.css": "./dist/styles.css",
|
|
57
64
|
"./package.json": "./package.json"
|
|
58
65
|
},
|
|
@@ -68,6 +75,7 @@
|
|
|
68
75
|
"test:coverage": "vitest run --coverage",
|
|
69
76
|
"clean": "rm -rf dist coverage",
|
|
70
77
|
"size": "size-limit",
|
|
78
|
+
"docs:llms": "node scripts/gen-llms.mjs",
|
|
71
79
|
"prepare": "husky",
|
|
72
80
|
"prepublishOnly": "npm run typecheck && npm run lint && npm run test:run && npm run build"
|
|
73
81
|
},
|
|
@@ -2,6 +2,8 @@ import js from "@eslint/js";
|
|
|
2
2
|
import globals from "globals";
|
|
3
3
|
import reactHooks from "eslint-plugin-react-hooks";
|
|
4
4
|
import reactRefresh from "eslint-plugin-react-refresh";
|
|
5
|
+
import simpleImportSort from "eslint-plugin-simple-import-sort";
|
|
6
|
+
import unusedImports from "eslint-plugin-unused-imports";
|
|
5
7
|
import tseslint from "typescript-eslint";
|
|
6
8
|
|
|
7
9
|
export default tseslint.config(
|
|
@@ -16,12 +18,27 @@ export default tseslint.config(
|
|
|
16
18
|
plugins: {
|
|
17
19
|
"react-hooks": reactHooks,
|
|
18
20
|
"react-refresh": reactRefresh,
|
|
21
|
+
"simple-import-sort": simpleImportSort,
|
|
22
|
+
"unused-imports": unusedImports,
|
|
19
23
|
},
|
|
20
24
|
rules: {
|
|
21
25
|
...reactHooks.configs.recommended.rules,
|
|
22
26
|
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
|
|
23
27
|
"@typescript-eslint/consistent-type-imports": "error",
|
|
24
|
-
|
|
28
|
+
// Organize imports/exports (tempest fix).
|
|
29
|
+
"simple-import-sort/imports": "error",
|
|
30
|
+
"simple-import-sort/exports": "error",
|
|
31
|
+
// Remove dead imports + flag unused vars (tempest fix).
|
|
32
|
+
"@typescript-eslint/no-unused-vars": "off",
|
|
33
|
+
"unused-imports/no-unused-imports": "error",
|
|
34
|
+
"unused-imports/no-unused-vars": [
|
|
35
|
+
"warn",
|
|
36
|
+
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
|
37
|
+
],
|
|
38
|
+
// Tidy whitespace (tempest fix).
|
|
39
|
+
"no-multiple-empty-lines": ["error", { max: 1, maxEOF: 0, maxBOF: 0 }],
|
|
40
|
+
"no-trailing-spaces": "error",
|
|
41
|
+
"eol-last": ["error", "always"],
|
|
25
42
|
},
|
|
26
43
|
},
|
|
27
44
|
);
|
package/template/package.json
CHANGED
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
"preview": "vite preview",
|
|
10
10
|
"typecheck": "tsc --noEmit",
|
|
11
11
|
"lint": "eslint .",
|
|
12
|
-
"lint:fix": "eslint . --fix"
|
|
12
|
+
"lint:fix": "eslint . --fix",
|
|
13
|
+
"format": "prettier --write .",
|
|
14
|
+
"fix": "tempest fix",
|
|
15
|
+
"doctor": "tempest doctor"
|
|
13
16
|
},
|
|
14
17
|
"dependencies": {
|
|
15
18
|
"react": "^19.0.0",
|
|
@@ -24,7 +27,10 @@
|
|
|
24
27
|
"eslint": "^9.36.0",
|
|
25
28
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
26
29
|
"eslint-plugin-react-refresh": "^0.4.22",
|
|
30
|
+
"eslint-plugin-simple-import-sort": "^12.1.0",
|
|
31
|
+
"eslint-plugin-unused-imports": "^4.1.4",
|
|
27
32
|
"globals": "^16.0.0",
|
|
33
|
+
"prettier": "^3.8.0",
|
|
28
34
|
"typescript": "~5.9.0",
|
|
29
35
|
"typescript-eslint": "^8.45.0",
|
|
30
36
|
"vite": "^7.0.0"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Tempest App (PWA)
|
|
2
|
+
|
|
3
|
+
Scaffolded with [`create-tempest-app --pwa`](https://www.npmjs.com/package/tempest-react-sdk) and powered by [`tempest-react-sdk`](https://www.npmjs.com/package/tempest-react-sdk).
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
|
|
7
|
+
- **Vite** with the `@` → `src` alias (`tempest-react-sdk/vite` → `createViteConfig`)
|
|
8
|
+
- **React Router v7** declarative routing (`defineRoutes` + `<AppRouter>`)
|
|
9
|
+
- **Zustand** state (`createAuthStore` + `createSelectors`)
|
|
10
|
+
- **TanStack Query** cache (mounted by `<AppProviders>`)
|
|
11
|
+
- **PWA**: installable manifest + a service worker built from `tempest-react-sdk/sw`, with web-push wiring
|
|
12
|
+
|
|
13
|
+
## Getting started
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install
|
|
17
|
+
cp .env.example .env # adjust VITE_API_URL + VITE_VAPID_PUBLIC_KEY
|
|
18
|
+
npm run dev # http://127.0.0.1:5173
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## PWA layout
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
public/manifest.webmanifest # install metadata (name, icons, theme color)
|
|
25
|
+
public/icon.svg # app icon (replace with your brand; PNG 192/512 recommended)
|
|
26
|
+
src/sw.ts # service worker — push + notificationclick + skip-waiting
|
|
27
|
+
vite.sw.config.ts # bundles src/sw.ts → dist/sw.js (classic worker)
|
|
28
|
+
index.html # manifest link + theme-color + apple meta tags
|
|
29
|
+
src/main.tsx # registers /sw.js in production, cleans up SW in dev
|
|
30
|
+
src/pages/Dashboard.tsx # Install button + push notifications toggle
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## How it works
|
|
34
|
+
|
|
35
|
+
- **Install**: `index.html` links the manifest; `useBeforeInstallPrompt` (in
|
|
36
|
+
`Dashboard.tsx`) surfaces a custom Install button when the browser offers one.
|
|
37
|
+
- **Service worker**: `src/sw.ts` imports `installPushHandler`,
|
|
38
|
+
`installNotificationClickHandler` and `installSkipWaitingListener` from
|
|
39
|
+
`tempest-react-sdk/sw`. `npm run build` bundles it to `dist/sw.js` via
|
|
40
|
+
`vite.sw.config.ts`, and `src/main.tsx` registers it in production.
|
|
41
|
+
- **Web push**: `usePushSubscription` reads `VITE_VAPID_PUBLIC_KEY`, subscribes
|
|
42
|
+
through the active service worker, and hands the subscription to your
|
|
43
|
+
`onSubscribe` callback to POST to your backend.
|
|
44
|
+
|
|
45
|
+
> ⚠️ The service worker is bundled at **build time**, so push and offline behave
|
|
46
|
+
> only in a production build. Test them with:
|
|
47
|
+
>
|
|
48
|
+
> ```bash
|
|
49
|
+
> npm run build && npm run preview
|
|
50
|
+
> ```
|
|
51
|
+
>
|
|
52
|
+
> In `npm run dev` the worker is intentionally unregistered to avoid stale caches.
|
|
53
|
+
|
|
54
|
+
## Replace the icons
|
|
55
|
+
|
|
56
|
+
`public/icon.svg` is a placeholder. For guaranteed installability across all
|
|
57
|
+
browsers, add PNG icons (192×192 and 512×512) to `public/` and point the
|
|
58
|
+
`manifest.webmanifest` `icons` entries at them.
|
|
59
|
+
|
|
60
|
+
## Next steps
|
|
61
|
+
|
|
62
|
+
- Add a route: drop a page in `src/pages/` and an entry in `src/routes.tsx`.
|
|
63
|
+
- Fetch data: `useQuery({ queryKey: queryKeys.me(), queryFn: () => api.get("/me") })`.
|
|
64
|
+
- Generate VAPID keys on your backend and set `VITE_VAPID_PUBLIC_KEY` in `.env`.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Base URL of your backend API (consumed by src/lib/api.ts).
|
|
2
|
+
VITE_API_URL=http://127.0.0.1:8000
|
|
3
|
+
|
|
4
|
+
# VAPID public key for web push (consumed by usePushSubscription in
|
|
5
|
+
# src/pages/Dashboard.tsx). Generate a key pair on your backend; the private
|
|
6
|
+
# half stays on the server, this public half ships to the browser.
|
|
7
|
+
VITE_VAPID_PUBLIC_KEY=
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-BR">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
|
|
6
|
+
<link rel="apple-touch-icon" href="/icon.svg" />
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
8
|
+
<meta name="theme-color" content="#0b1a36" />
|
|
9
|
+
<meta name="description" content="App React fiado com tempest-react-sdk." />
|
|
10
|
+
<meta name="application-name" content="Tempest App" />
|
|
11
|
+
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
12
|
+
<meta name="apple-mobile-web-app-title" content="Tempest App" />
|
|
13
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
14
|
+
<meta name="mobile-web-app-capable" content="yes" />
|
|
15
|
+
<link rel="manifest" href="/manifest.webmanifest" />
|
|
16
|
+
<title>Tempest App</title>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<div id="root"></div>
|
|
20
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Tempest App",
|
|
3
|
+
"short_name": "Tempest",
|
|
4
|
+
"description": "App React fiado com tempest-react-sdk.",
|
|
5
|
+
"id": "/",
|
|
6
|
+
"start_url": "/?source=pwa",
|
|
7
|
+
"scope": "/",
|
|
8
|
+
"display": "standalone",
|
|
9
|
+
"orientation": "portrait",
|
|
10
|
+
"lang": "pt-BR",
|
|
11
|
+
"dir": "ltr",
|
|
12
|
+
"background_color": "#ffffff",
|
|
13
|
+
"theme_color": "#0b1a36",
|
|
14
|
+
"categories": ["productivity", "utilities"],
|
|
15
|
+
"icons": [
|
|
16
|
+
{
|
|
17
|
+
"src": "/icon.svg",
|
|
18
|
+
"sizes": "192x192",
|
|
19
|
+
"type": "image/svg+xml",
|
|
20
|
+
"purpose": "any"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"src": "/icon.svg",
|
|
24
|
+
"sizes": "512x512",
|
|
25
|
+
"type": "image/svg+xml",
|
|
26
|
+
"purpose": "any"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"src": "/icon-maskable.svg",
|
|
30
|
+
"sizes": "512x512",
|
|
31
|
+
"type": "image/svg+xml",
|
|
32
|
+
"purpose": "maskable"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StrictMode } from "react";
|
|
2
|
+
import { createRoot } from "react-dom/client";
|
|
3
|
+
import { registerServiceWorker, skipWaiting } from "tempest-react-sdk";
|
|
4
|
+
import "tempest-react-sdk/styles.css";
|
|
5
|
+
import { App } from "@/App";
|
|
6
|
+
|
|
7
|
+
createRoot(document.getElementById("root")!).render(
|
|
8
|
+
<StrictMode>
|
|
9
|
+
<App />
|
|
10
|
+
</StrictMode>,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
// The service worker is bundled to `/sw.js` at build time, so it only exists in
|
|
14
|
+
// production. In dev we proactively unregister any leftover worker to avoid a
|
|
15
|
+
// stale cache shadowing your `npm run dev` output.
|
|
16
|
+
if (import.meta.env.DEV && "serviceWorker" in navigator) {
|
|
17
|
+
void navigator.serviceWorker
|
|
18
|
+
.getRegistrations()
|
|
19
|
+
.then((regs) => Promise.all(regs.map((r) => r.unregister())))
|
|
20
|
+
.catch((err) => console.warn("[sw] dev cleanup failed", err));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (import.meta.env.PROD) {
|
|
24
|
+
void registerServiceWorker({
|
|
25
|
+
url: "/sw.js",
|
|
26
|
+
onUpdate: (waiting) => {
|
|
27
|
+
// A new worker is ready. Prompt your users however you like; here we
|
|
28
|
+
// just activate it and reload so the next visit is up to date.
|
|
29
|
+
if (confirm("Nova versão disponível. Atualizar agora?")) {
|
|
30
|
+
skipWaiting(waiting);
|
|
31
|
+
window.location.reload();
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
onError: (err) => console.warn("[sw] registration failed", err),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Button, useBeforeInstallPrompt, usePushSubscription } from "tempest-react-sdk";
|
|
2
|
+
import { useAuth } from "@/stores/auth";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Protected page (see the `guard` in src/routes.tsx). Lazy-loaded, so it is
|
|
6
|
+
* code-split into its own chunk. Default export because `lazy` expects one.
|
|
7
|
+
*
|
|
8
|
+
* Adds two PWA controls:
|
|
9
|
+
* - Install button (`useBeforeInstallPrompt`) — appears only when the browser
|
|
10
|
+
* offers an install prompt and the app is not yet installed.
|
|
11
|
+
* - Push toggle (`usePushSubscription`) — subscribes/unsubscribes to web push.
|
|
12
|
+
* The service worker must be active, so this works in a production build
|
|
13
|
+
* (`npm run build && npm run preview`), not in `npm run dev`.
|
|
14
|
+
*/
|
|
15
|
+
export default function Dashboard() {
|
|
16
|
+
const user = useAuth.use.user();
|
|
17
|
+
const install = useBeforeInstallPrompt();
|
|
18
|
+
|
|
19
|
+
const push = usePushSubscription({
|
|
20
|
+
vapidPublicKey: import.meta.env.VITE_VAPID_PUBLIC_KEY ?? "",
|
|
21
|
+
onSubscribe: async (subscription) => {
|
|
22
|
+
// Send the subscription to your backend so it can deliver pushes.
|
|
23
|
+
// await api.post("/webpush/subscribe", { body: subscription });
|
|
24
|
+
console.log("push subscription", subscription);
|
|
25
|
+
},
|
|
26
|
+
onUnsubscribe: async () => {
|
|
27
|
+
// await api.delete("/webpush/my");
|
|
28
|
+
console.log("push unsubscribed");
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<section>
|
|
34
|
+
<h1>Dashboard</h1>
|
|
35
|
+
<p>
|
|
36
|
+
Signed in as <strong>{user?.name}</strong> ({user?.email}).
|
|
37
|
+
</p>
|
|
38
|
+
<p>This route is only reachable while authenticated.</p>
|
|
39
|
+
|
|
40
|
+
<h2>PWA</h2>
|
|
41
|
+
|
|
42
|
+
{install.installed ? (
|
|
43
|
+
<p>✅ App installed.</p>
|
|
44
|
+
) : install.installable ? (
|
|
45
|
+
<Button onClick={() => void install.prompt()}>Install app</Button>
|
|
46
|
+
) : (
|
|
47
|
+
<p>Install prompt not available in this browser/context.</p>
|
|
48
|
+
)}
|
|
49
|
+
|
|
50
|
+
<h2>Notifications</h2>
|
|
51
|
+
|
|
52
|
+
{!push.supported ? (
|
|
53
|
+
<p>Web push is not supported here (needs HTTPS + an active service worker).</p>
|
|
54
|
+
) : (
|
|
55
|
+
<>
|
|
56
|
+
<Button
|
|
57
|
+
onClick={() =>
|
|
58
|
+
void (push.subscribed ? push.unsubscribe() : push.subscribe())
|
|
59
|
+
}
|
|
60
|
+
disabled={push.loading}
|
|
61
|
+
>
|
|
62
|
+
{push.subscribed ? "Disable notifications" : "Enable notifications"}
|
|
63
|
+
</Button>
|
|
64
|
+
<p>
|
|
65
|
+
Permission: <strong>{push.permission}</strong> · Subscribed:{" "}
|
|
66
|
+
<strong>{String(push.subscribed)}</strong>
|
|
67
|
+
</p>
|
|
68
|
+
{push.error && <p style={{ color: "crimson" }}>{push.error.message}</p>}
|
|
69
|
+
</>
|
|
70
|
+
)}
|
|
71
|
+
</section>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/// <reference lib="webworker" />
|
|
2
|
+
import {
|
|
3
|
+
installNotificationClickHandler,
|
|
4
|
+
installPushHandler,
|
|
5
|
+
installSkipWaitingListener,
|
|
6
|
+
} from "tempest-react-sdk/sw";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Service worker. Bundled to `dist/sw.js` by `vite.sw.config.ts` (see the
|
|
10
|
+
* `build:sw` script) and registered from `src/main.tsx`.
|
|
11
|
+
*
|
|
12
|
+
* The three SDK helpers wire the boilerplate:
|
|
13
|
+
* - `installPushHandler` parses the `push` payload (JSON, plain-text fallback)
|
|
14
|
+
* and shows a notification.
|
|
15
|
+
* - `installNotificationClickHandler` focuses an open tab on click, or opens a
|
|
16
|
+
* new one at the payload's `url`.
|
|
17
|
+
* - `installSkipWaitingListener` activates a waiting worker when the page posts
|
|
18
|
+
* `{ type: "SKIP_WAITING" }` (paired with `registerServiceWorker`'s
|
|
19
|
+
* `onUpdate` in `main.tsx`).
|
|
20
|
+
*/
|
|
21
|
+
declare const self: ServiceWorkerGlobalScope;
|
|
22
|
+
|
|
23
|
+
installPushHandler({
|
|
24
|
+
defaultTitle: "Notificação",
|
|
25
|
+
defaultIcon: "/icon.svg",
|
|
26
|
+
defaultBadge: "/icon.svg",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
installNotificationClickHandler();
|
|
30
|
+
installSkipWaitingListener();
|
|
31
|
+
|
|
32
|
+
// Take control of open pages as soon as this worker activates.
|
|
33
|
+
self.addEventListener("activate", (event) => {
|
|
34
|
+
event.waitUntil(self.clients.claim());
|
|
35
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
interface ImportMetaEnv {
|
|
4
|
+
/** Base URL of the backend API (src/lib/api.ts). */
|
|
5
|
+
readonly VITE_API_URL?: string;
|
|
6
|
+
/** VAPID public key for web push (src/pages/Dashboard.tsx). */
|
|
7
|
+
readonly VITE_VAPID_PUBLIC_KEY?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface ImportMeta {
|
|
11
|
+
readonly env: ImportMetaEnv;
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { defineConfig } from "vite";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Standalone build that bundles `src/sw.ts` (and the `tempest-react-sdk/sw`
|
|
6
|
+
* helpers it imports) into a single classic service worker at `dist/sw.js`.
|
|
7
|
+
*
|
|
8
|
+
* Run after the app build via the `build:sw` script — `emptyOutDir: false`
|
|
9
|
+
* keeps the app's `dist/` intact. The IIFE format produces a worker with no
|
|
10
|
+
* `import`/`export` tokens, so it registers as a classic worker (no
|
|
11
|
+
* `type: "module"` needed).
|
|
12
|
+
*/
|
|
13
|
+
export default defineConfig({
|
|
14
|
+
build: {
|
|
15
|
+
emptyOutDir: false,
|
|
16
|
+
sourcemap: true,
|
|
17
|
+
lib: {
|
|
18
|
+
entry: resolve(__dirname, "src/sw.ts"),
|
|
19
|
+
formats: ["iife"],
|
|
20
|
+
name: "sw",
|
|
21
|
+
fileName: () => "sw.js",
|
|
22
|
+
},
|
|
23
|
+
rollupOptions: {
|
|
24
|
+
output: { entryFileNames: "sw.js", inlineDynamicImports: true },
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|