tempest-react-sdk 0.7.0 → 0.9.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/lib/openapi/generate.mjs +259 -0
- package/bin/lib/openapi/generate.test.mjs +129 -0
- package/bin/lib/openapi/load.mjs +24 -0
- package/bin/lib/openapi/schema-to-zod.mjs +123 -0
- package/bin/lib/openapi/schema-to-zod.test.mjs +81 -0
- package/bin/tempest.mjs +364 -0
- package/dist/sw.cjs +2 -0
- package/dist/sw.cjs.map +1 -0
- package/dist/sw.d.ts +233 -0
- package/dist/sw.js +361 -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.d.ts +130 -0
- package/dist/tempest-react-sdk.js +1565 -1646
- package/dist/tempest-react-sdk.js.map +1 -1
- package/dist/vite.cjs +3 -1
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.ts +136 -0
- package/dist/vite.js +253 -34
- package/dist/vite.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 +9 -0
- package/template-pwa/public/icon.svg +4 -0
- package/template-pwa/public/manifest.webmanifest +35 -0
- package/template-pwa/src/main.tsx +29 -0
- package/template-pwa/src/pages/Dashboard.tsx +73 -0
- package/template-pwa/src/sw.ts +70 -0
- package/template-pwa/src/vite-env.d.ts +12 -0
- package/template-pwa/vite.config.ts +21 -0
- package/template-pwa/vite.sw.config.ts +27 -0
package/dist/vite.cjs
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";var z=Object.create;var $=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var H=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty;var O=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of I(t))!D.call(e,s)&&s!==n&&$(e,s,{get:()=>t[s],enumerable:!(a=B(t,s))||a.enumerable});return e};var T=(e,t,n)=>(n=e!=null?z(H(e)):{},O(t||!e||!e.__esModule?$(n,"default",{value:e,enumerable:!0}):n,e));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("node:path"),A=require("vite"),F=require("@vitejs/plugin-react"),R=require("node:fs/promises");function W(e){const t={};for(const[n,a]of Object.entries(e))t[n]=typeof a=="string"?{target:a,changeOrigin:!0}:a;return t}function q(e={}){const{srcDir:t="src",port:n=5173,host:a="127.0.0.1",open:s=!1,proxy:c,alias:d={},plugins:g=[],overrides:u={}}=e,r=u,l={plugins:[F(),...g],resolve:{alias:{"@":S.resolve(process.cwd(),t),...d}},server:{port:n,host:a,open:s,...c?{proxy:W(c)}:{}}},p={...l,...r,plugins:[...l.plugins??[],...r.plugins??[]],resolve:{...l.resolve,...r.resolve},server:{...l.server,...r.server}};return A.defineConfig(p)}function N(e,t){return`${e.endsWith("/")?e:`${e}/`}${t}`.replace(/([^:]\/)\/+/g,"$1")}function U(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 L(e={}){const{fileName:t="precache-manifest.json",additionalUrls:n=[],exclude:a=/\.map$/,includeHtml:s=!0,appShell:c="/index.html"}=e;let d="/";return{name:"tempest-pwa-manifest",apply:"build",configResolved(u){d=u.base??"/"},generateBundle(u,r){const l=new Set(n);c&&l.add(c);for(const w of Object.keys(r))w!==t&&(a.test(w)||!s&&w.endsWith(".html")||l.add(N(d,w)));const p=[...l].sort(),f=U(p.join(`
|
|
2
|
+
`));this.emitFile({type:"asset",fileName:t,source:JSON.stringify({version:f,urls:p})})}}}const _=[{width:375,height:667,ratio:2},{width:375,height:812,ratio:3},{width:390,height:844,ratio:3},{width:393,height:852,ratio:3},{width:414,height:896,ratio:2},{width:414,height:896,ratio:3},{width:428,height:926,ratio:3},{width:430,height:932,ratio:3},{width:768,height:1024,ratio:2},{width:834,height:1194,ratio:2},{width:1024,height:1366,ratio:2}];function M(e){return`splash/apple-splash-${e.width*e.ratio}x${e.height*e.ratio}.png`}function J(e){return`(device-width: ${e.width}px) and (device-height: ${e.height}px) and (-webkit-device-pixel-ratio: ${e.ratio}) and (orientation: portrait)`}function P(e){const t=e.replace("#",""),n=t.length===3?t.split("").map(a=>a+a).join(""):t;return{r:parseInt(n.slice(0,2),16),g:parseInt(n.slice(2,4),16),b:parseInt(n.slice(4,6),16)}}function V(e={}){const{source:t="public/icon.svg",sizes:n=[192,512],maskableSizes:a=[512],appleTouchIcon:s=180,outDir:c="icons",background:d="#ffffff",maskablePadding:g=.1,appleSplash:u=!1,splashBackground:r,splashIconScale:l=.3}=e,p=u?Array.isArray(u)?u:_:[];let f=process.cwd();return{name:"tempest-pwa-icons",apply:"build",configResolved(h){f=h.root??process.cwd()},transformIndexHtml(){if(p.length)return p.map(h=>({tag:"link",attrs:{rel:"apple-touch-startup-image",media:J(h),href:`/${M(h)}`},injectTo:"head"}))},async generateBundle(){let h;try{const o=await import("sharp");h=o.default??o}catch{this.warn("tempestPwaIcons: `sharp` is not installed — skipping icon generation. Run `npm i -D sharp` to enable it.");return}const m=await R.readFile(S.resolve(f,t)),y=P(d),v=(i,o)=>{this.emitFile({type:"asset",fileName:i,source:o})};for(const i of n){const o=await h(m,{density:Math.max(i,512)}).resize(i,i,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toBuffer();v(`${c}/icon-${i}.png`,o)}for(const i of a){const o=Math.round(i*(1-g*2)),b=await h(m,{density:Math.max(i,512)}).resize(o,o,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).extend({top:Math.round((i-o)/2),bottom:Math.round((i-o)/2),left:Math.round((i-o)/2),right:Math.round((i-o)/2),background:{...y,alpha:1}}).resize(i,i).png().toBuffer();v(`${c}/maskable-${i}.png`,b)}if(s){const i=await h(m,{density:Math.max(s,512)}).resize(s,s,{fit:"contain",background:{...y,alpha:1}}).flatten({background:y}).png().toBuffer();v("apple-touch-icon.png",i)}if(p.length){const i=P(r??d);for(const o of p){const b=o.width*o.ratio,k=o.height*o.ratio,x=Math.round(Math.min(b,k)*l),j=await h(m,{density:Math.max(x,512)}).resize(x,x,{fit:"contain",background:{r:0,g:0,b:0,alpha:0}}).png().toBuffer(),C=await h({create:{width:b,height:k,channels:4,background:{...i,alpha:1}}}).composite([{input:j,gravity:"center"}]).png().toBuffer();v(M(o),C)}}}}}function E(e={}){const{swSrc:t="src/sw.ts",swUrl:n="/sw.js",manifestUrl:a="/precache-manifest.json",enabled:s=!0}=e;let c=process.cwd();return{name:"tempest-pwa-dev-sw",apply:"serve",configResolved(g){c=g.root??process.cwd()},configureServer(g){s&&g.middlewares.use(async(u,r,l)=>{const p=(u.url??"").split("?")[0];if(p===n){try{const w=await(await import("esbuild")).build({entryPoints:[S.resolve(c,t)],bundle:!0,format:"iife",platform:"browser",target:"es2020",write:!1,absWorkingDir:c,logLevel:"silent"});r.setHeader("Content-Type","application/javascript"),r.setHeader("Service-Worker-Allowed","/"),r.setHeader("Cache-Control","no-cache"),r.end(w.outputFiles[0].text)}catch(f){r.statusCode=500,r.end(`// SW dev build failed:
|
|
3
|
+
// ${String(f)}`)}return}if(p===a){r.setHeader("Content-Type","application/json"),r.setHeader("Cache-Control","no-cache"),r.end(JSON.stringify({version:"dev",urls:[]}));return}l()})}}}exports.createViteConfig=q;exports.tempestPwaDevSw=E;exports.tempestPwaIcons=V;exports.tempestPwaManifest=L;
|
|
2
4
|
//# sourceMappingURL=vite.cjs.map
|
package/dist/vite.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.cjs","sources":["../src/vite/create-vite-config.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { defineConfig } from \"vite\";\nimport type { ProxyOptions, UserConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\n/**\n * A Vite proxy entry: either a target URL string (expanded to\n * `{ target, changeOrigin: true }`) or a raw Vite `ProxyOptions` object.\n */\nexport type ProxyEntry = string | Record<string, unknown>;\n\nexport interface CreateViteConfigOptions {\n /**\n * Source directory aliased to `@`, relative to the project root.\n * Default: `\"src\"` (so `@/components/Button` → `<root>/src/components/Button`).\n */\n srcDir?: string;\n /** Dev server port. Default: `5173`. */\n port?: number;\n /** Dev server host. Default: `\"127.0.0.1\"`. */\n host?: string | boolean;\n /** Open the browser on `dev` start. Default: `false`. */\n open?: boolean;\n /**\n * Dev proxy table. String values are expanded to\n * `{ target, changeOrigin: true }`; objects are passed through untouched.\n *\n * @example { \"/api\": \"http://127.0.0.1:8000\" }\n */\n proxy?: Record<string, ProxyEntry>;\n /** Extra path aliases merged on top of the default `@` → src alias. */\n alias?: Record<string, string>;\n /** Vite plugins appended after `@vitejs/plugin-react`. */\n plugins?: unknown[];\n /**\n * Arbitrary Vite config (a `UserConfig` object) deep-merged last, for\n * escape-hatch overrides (build target, define, extra `server` keys, …).\n */\n overrides?: Record<string, unknown>;\n}\n\n/**\n * The resulting Vite config object. Typed loosely so the SDK's published\n * declarations stay free of `vite`'s internal types; assign it straight to a\n * `vite.config.ts` default export.\n */\nexport type TempestViteConfig = Record<string, unknown>;\n\nfunction normalizeProxy(proxy: Record<string, ProxyEntry>): Record<string, ProxyOptions> {\n const out: Record<string, ProxyOptions> = {};\n for (const [path, value] of Object.entries(proxy)) {\n out[path] =\n typeof value === \"string\"\n ? { target: value, changeOrigin: true }\n : (value as ProxyOptions);\n }\n return out;\n}\n\n/**\n * Build a Tempest-flavored Vite config for a React app: the `@vitejs/plugin-react`\n * plugin, the `@` → `src` import alias, and sane dev-server defaults — so a\n * consuming app's `vite.config.ts` is a single call instead of repeated\n * boilerplate. Everything is overridable.\n *\n * Import it from the dedicated Node entry point:\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({\n * proxy: { \"/api\": \"http://127.0.0.1:8000\" },\n * });\n */\nexport function createViteConfig(options: CreateViteConfigOptions = {}): TempestViteConfig {\n const {\n srcDir = \"src\",\n port = 5173,\n host = \"127.0.0.1\",\n open = false,\n proxy,\n alias = {},\n plugins = [],\n overrides = {},\n } = options;\n\n const overridesConfig = overrides as UserConfig;\n\n const base: UserConfig = {\n plugins: [react(), ...plugins] as UserConfig[\"plugins\"],\n resolve: {\n alias: {\n \"@\": resolve(process.cwd(), srcDir),\n ...alias,\n },\n },\n server: {\n port,\n host,\n open,\n ...(proxy ? { proxy: normalizeProxy(proxy) } : {}),\n },\n };\n\n const merged: UserConfig = {\n ...base,\n ...overridesConfig,\n plugins: [...(base.plugins ?? []), ...(overridesConfig.plugins ?? [])],\n resolve: { ...base.resolve, ...overridesConfig.resolve },\n server: { ...base.server, ...overridesConfig.server },\n };\n\n return defineConfig(merged) as TempestViteConfig;\n}\n"],"names":["normalizeProxy","proxy","out","path","value","createViteConfig","options","srcDir","port","host","open","alias","plugins","overrides","overridesConfig","base","react","resolve","merged","defineConfig"],"mappings":"iKAgDA,SAASA,EAAeC,EAAiE,CACrF,MAAMC,EAAoC,CAAA,EAC1C,SAAW,CAACC,EAAMC,CAAK,IAAK,OAAO,QAAQH,CAAK,EAC5CC,EAAIC,CAAI,EACJ,OAAOC,GAAU,SACX,CAAE,OAAQA,EAAO,aAAc,EAAA,EAC9BA,EAEf,OAAOF,CACX,CAkBO,SAASG,EAAiBC,EAAmC,GAAuB,CACvF,KAAM,CACF,OAAAC,EAAS,MACT,KAAAC,EAAO,KACP,KAAAC,EAAO,YACP,KAAAC,EAAO,GACP,MAAAT,EACA,MAAAU,EAAQ,CAAA,EACR,QAAAC,EAAU,CAAA,EACV,UAAAC,EAAY,CAAA,CAAC,EACbP,EAEEQ,EAAkBD,EAElBE,EAAmB,CACrB,QAAS,CAACC,IAAS,GAAGJ,CAAO,EAC7B,QAAS,CACL,MAAO,CACH,IAAKK,EAAAA,QAAQ,QAAQ,IAAA,EAAOV,CAAM,EAClC,GAAGI,CAAA,CACP,EAEJ,OAAQ,CACJ,KAAAH,EACA,KAAAC,EACA,KAAAC,EACA,GAAIT,EAAQ,CAAE,MAAOD,EAAeC,CAAK,CAAA,EAAM,CAAA,CAAC,CACpD,EAGEiB,EAAqB,CACvB,GAAGH,EACH,GAAGD,EACH,QAAS,CAAC,GAAIC,EAAK,SAAW,CAAA,EAAK,GAAID,EAAgB,SAAW,EAAG,EACrE,QAAS,CAAE,GAAGC,EAAK,QAAS,GAAGD,EAAgB,OAAA,EAC/C,OAAQ,CAAE,GAAGC,EAAK,OAAQ,GAAGD,EAAgB,MAAA,CAAO,EAGxD,OAAOK,EAAAA,aAAaD,CAAM,CAC9B"}
|
|
1
|
+
{"version":3,"file":"vite.cjs","sources":["../src/vite/create-vite-config.ts","../src/vite/tempest-pwa-manifest.ts","../src/vite/tempest-pwa-icons.ts","../src/vite/tempest-pwa-dev-sw.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { defineConfig } from \"vite\";\nimport type { ProxyOptions, UserConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\n/**\n * A Vite proxy entry: either a target URL string (expanded to\n * `{ target, changeOrigin: true }`) or a raw Vite `ProxyOptions` object.\n */\nexport type ProxyEntry = string | Record<string, unknown>;\n\nexport interface CreateViteConfigOptions {\n /**\n * Source directory aliased to `@`, relative to the project root.\n * Default: `\"src\"` (so `@/components/Button` → `<root>/src/components/Button`).\n */\n srcDir?: string;\n /** Dev server port. Default: `5173`. */\n port?: number;\n /** Dev server host. Default: `\"127.0.0.1\"`. */\n host?: string | boolean;\n /** Open the browser on `dev` start. Default: `false`. */\n open?: boolean;\n /**\n * Dev proxy table. String values are expanded to\n * `{ target, changeOrigin: true }`; objects are passed through untouched.\n *\n * @example { \"/api\": \"http://127.0.0.1:8000\" }\n */\n proxy?: Record<string, ProxyEntry>;\n /** Extra path aliases merged on top of the default `@` → src alias. */\n alias?: Record<string, string>;\n /** Vite plugins appended after `@vitejs/plugin-react`. */\n plugins?: unknown[];\n /**\n * Arbitrary Vite config (a `UserConfig` object) deep-merged last, for\n * escape-hatch overrides (build target, define, extra `server` keys, …).\n */\n overrides?: Record<string, unknown>;\n}\n\n/**\n * The resulting Vite config object. Typed loosely so the SDK's published\n * declarations stay free of `vite`'s internal types; assign it straight to a\n * `vite.config.ts` default export.\n */\nexport type TempestViteConfig = Record<string, unknown>;\n\nfunction normalizeProxy(proxy: Record<string, ProxyEntry>): Record<string, ProxyOptions> {\n const out: Record<string, ProxyOptions> = {};\n for (const [path, value] of Object.entries(proxy)) {\n out[path] =\n typeof value === \"string\"\n ? { target: value, changeOrigin: true }\n : (value as ProxyOptions);\n }\n return out;\n}\n\n/**\n * Build a Tempest-flavored Vite config for a React app: the `@vitejs/plugin-react`\n * plugin, the `@` → `src` import alias, and sane dev-server defaults — so a\n * consuming app's `vite.config.ts` is a single call instead of repeated\n * boilerplate. Everything is overridable.\n *\n * Import it from the dedicated Node entry point:\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({\n * proxy: { \"/api\": \"http://127.0.0.1:8000\" },\n * });\n */\nexport function createViteConfig(options: CreateViteConfigOptions = {}): TempestViteConfig {\n const {\n srcDir = \"src\",\n port = 5173,\n host = \"127.0.0.1\",\n open = false,\n proxy,\n alias = {},\n plugins = [],\n overrides = {},\n } = options;\n\n const overridesConfig = overrides as UserConfig;\n\n const base: UserConfig = {\n plugins: [react(), ...plugins] as UserConfig[\"plugins\"],\n resolve: {\n alias: {\n \"@\": resolve(process.cwd(), srcDir),\n ...alias,\n },\n },\n server: {\n port,\n host,\n open,\n ...(proxy ? { proxy: normalizeProxy(proxy) } : {}),\n },\n };\n\n const merged: UserConfig = {\n ...base,\n ...overridesConfig,\n plugins: [...(base.plugins ?? []), ...(overridesConfig.plugins ?? [])],\n resolve: { ...base.resolve, ...overridesConfig.resolve },\n server: { ...base.server, ...overridesConfig.server },\n };\n\n return defineConfig(merged) as TempestViteConfig;\n}\n","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 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 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/** 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);\n // Vite may emit index.html after this hook, so guarantee the shell.\n if (appShell) urls.add(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","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport type { TempestVitePlugin } from \"./tempest-pwa-manifest\";\n\n/** Options for {@link tempestPwaIcons}. */\nexport interface TempestPwaIconsOptions {\n /** Source image (SVG or large PNG), relative to the project root. Default `public/icon.svg`. */\n source?: string;\n /** Square \"any\"-purpose icon sizes to emit. Default `[192, 512]`. */\n sizes?: number[];\n /** Square \"maskable\" icon sizes to emit (with safe-zone padding). Default `[512]`. */\n maskableSizes?: number[];\n /** Apple touch icon size, or `false` to skip. Default `180`. */\n appleTouchIcon?: number | false;\n /** Output directory for the icon set, under the build root. Default `icons`. */\n outDir?: string;\n /** Opaque background for maskable + apple icons (no transparency allowed). Default `#ffffff`. */\n background?: string;\n /** Maskable safe-zone padding as a fraction of the icon. Default `0.1` (10% each side). */\n maskablePadding?: number;\n /**\n * Generate Apple splash screens (launch images) and inject the matching\n * `<link rel=\"apple-touch-startup-image\">` tags. `true` uses a built-in set\n * of common iPhone/iPad portrait sizes; pass an array to override. Default `false`.\n */\n appleSplash?: boolean | AppleSplashSpec[];\n /** Background color for splash screens. Default: `background`. */\n splashBackground?: string;\n /** Icon size on the splash as a fraction of the shorter side. Default `0.3`. */\n splashIconScale?: number;\n}\n\n/** A single Apple splash target (CSS px + device pixel ratio). */\nexport interface AppleSplashSpec {\n /** CSS width (device-width in the media query). */\n width: number;\n /** CSS height (device-height in the media query). */\n height: number;\n /** Device pixel ratio. */\n ratio: number;\n}\n\n/** Common iPhone/iPad portrait splash sizes (CSS px @ ratio). */\nconst DEFAULT_SPLASH: AppleSplashSpec[] = [\n { width: 375, height: 667, ratio: 2 }, // iPhone SE / 8\n { width: 375, height: 812, ratio: 3 }, // iPhone X / 11 Pro\n { width: 390, height: 844, ratio: 3 }, // iPhone 12 / 13 / 14\n { width: 393, height: 852, ratio: 3 }, // iPhone 14 Pro / 15\n { width: 414, height: 896, ratio: 2 }, // iPhone XR / 11\n { width: 414, height: 896, ratio: 3 }, // iPhone XS Max / 11 Pro Max\n { width: 428, height: 926, ratio: 3 }, // iPhone 13/14 Pro Max\n { width: 430, height: 932, ratio: 3 }, // iPhone 15 Pro Max\n { width: 768, height: 1024, ratio: 2 }, // iPad\n { width: 834, height: 1194, ratio: 2 }, // iPad Pro 11\"\n { width: 1024, height: 1366, ratio: 2 }, // iPad Pro 12.9\"\n];\n\nfunction splashFileName(spec: AppleSplashSpec): string {\n return `splash/apple-splash-${spec.width * spec.ratio}x${spec.height * spec.ratio}.png`;\n}\n\nfunction splashMedia(spec: AppleSplashSpec): string {\n return (\n `(device-width: ${spec.width}px) and (device-height: ${spec.height}px) ` +\n `and (-webkit-device-pixel-ratio: ${spec.ratio}) and (orientation: portrait)`\n );\n}\n\ninterface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nfunction hexToRgb(hex: string): Rgb {\n const value = hex.replace(\"#\", \"\");\n const full =\n value.length === 3\n ? value\n .split(\"\")\n .map((c) => c + c)\n .join(\"\")\n : value;\n return {\n r: parseInt(full.slice(0, 2), 16),\n g: parseInt(full.slice(2, 4), 16),\n b: parseInt(full.slice(4, 6), 16),\n };\n}\n\n/**\n * Build plugin that rasterizes a single source image into a full PWA icon set\n * (regular + maskable + apple-touch-icon), the dependency-free counterpart to\n * `@vite-pwa/assets-generator`. Rendering uses **`sharp`**, imported lazily and\n * treated as optional: if it isn't installed the plugin logs a warning and skips\n * generation (your build still succeeds; the icons just aren't produced).\n *\n * Point your `manifest.webmanifest` icon entries at the emitted files\n * (`/icons/icon-192.png`, `/icons/icon-512.png`, `/icons/maskable-512.png`) and\n * the apple touch icon at `/apple-touch-icon.png`.\n *\n * @example\n * // vite.config.ts\n * import { createViteConfig, tempestPwaIcons } from \"tempest-react-sdk/vite\";\n *\n * export default createViteConfig({\n * plugins: [tempestPwaIcons({ source: \"public/icon.svg\" })],\n * });\n */\nexport function tempestPwaIcons(options: TempestPwaIconsOptions = {}): TempestVitePlugin {\n const {\n source = \"public/icon.svg\",\n sizes = [192, 512],\n maskableSizes = [512],\n appleTouchIcon = 180,\n outDir = \"icons\",\n background = \"#ffffff\",\n maskablePadding = 0.1,\n appleSplash = false,\n splashBackground,\n splashIconScale = 0.3,\n } = options;\n\n const splashSpecs: AppleSplashSpec[] = appleSplash\n ? Array.isArray(appleSplash)\n ? appleSplash\n : DEFAULT_SPLASH\n : [];\n\n let root = process.cwd();\n\n const plugin: Plugin = {\n name: \"tempest-pwa-icons\",\n apply: \"build\",\n configResolved(config) {\n root = config.root ?? process.cwd();\n },\n transformIndexHtml() {\n if (!splashSpecs.length) return;\n return splashSpecs.map((spec) => ({\n tag: \"link\",\n attrs: {\n rel: \"apple-touch-startup-image\",\n media: splashMedia(spec),\n href: `/${splashFileName(spec)}`,\n },\n injectTo: \"head\" as const,\n }));\n },\n async generateBundle() {\n let sharp: SharpFactory;\n try {\n // Non-literal specifier so TS doesn't require `sharp`'s types\n // (it is an optional, lazily-loaded dependency).\n const specifier = \"sharp\";\n const mod = (await import(specifier)) as { default?: SharpFactory } & SharpFactory;\n sharp = (mod.default ?? mod) as SharpFactory;\n } catch {\n this.warn(\n \"tempestPwaIcons: `sharp` is not installed — skipping icon generation. \" +\n \"Run `npm i -D sharp` to enable it.\",\n );\n return;\n }\n\n const input = await readFile(resolve(root, source));\n const bg = hexToRgb(background);\n const emit = (fileName: string, data: Buffer): void => {\n this.emitFile({ type: \"asset\", fileName, source: data });\n };\n\n // Regular \"any\" icons — transparent background, full bleed.\n for (const size of sizes) {\n const png = await sharp(input, { density: Math.max(size, 512) })\n .resize(size, size, {\n fit: \"contain\",\n background: { r: 0, g: 0, b: 0, alpha: 0 },\n })\n .png()\n .toBuffer();\n emit(`${outDir}/icon-${size}.png`, png);\n }\n\n // Maskable icons — content shrunk into the safe zone over a solid bg.\n for (const size of maskableSizes) {\n const content = Math.round(size * (1 - maskablePadding * 2));\n const png = await sharp(input, { density: Math.max(size, 512) })\n .resize(content, content, {\n fit: \"contain\",\n background: { r: 0, g: 0, b: 0, alpha: 0 },\n })\n .extend({\n top: Math.round((size - content) / 2),\n bottom: Math.round((size - content) / 2),\n left: Math.round((size - content) / 2),\n right: Math.round((size - content) / 2),\n background: { ...bg, alpha: 1 },\n })\n .resize(size, size)\n .png()\n .toBuffer();\n emit(`${outDir}/maskable-${size}.png`, png);\n }\n\n // Apple touch icon — opaque, no alpha.\n if (appleTouchIcon) {\n const png = await sharp(input, { density: Math.max(appleTouchIcon, 512) })\n .resize(appleTouchIcon, appleTouchIcon, {\n fit: \"contain\",\n background: { ...bg, alpha: 1 },\n })\n .flatten({ background: bg })\n .png()\n .toBuffer();\n emit(\"apple-touch-icon.png\", png);\n }\n\n // Apple splash screens — icon centered on a solid background.\n if (splashSpecs.length) {\n const splashBg = hexToRgb(splashBackground ?? background);\n for (const spec of splashSpecs) {\n const w = spec.width * spec.ratio;\n const h = spec.height * spec.ratio;\n const iconPx = Math.round(Math.min(w, h) * splashIconScale);\n const icon = await sharp(input, { density: Math.max(iconPx, 512) })\n .resize(iconPx, iconPx, {\n fit: \"contain\",\n background: { r: 0, g: 0, b: 0, alpha: 0 },\n })\n .png()\n .toBuffer();\n const png = await sharp({\n create: {\n width: w,\n height: h,\n channels: 4,\n background: { ...splashBg, alpha: 1 },\n },\n })\n .composite([{ input: icon, gravity: \"center\" }])\n .png()\n .toBuffer();\n emit(splashFileName(spec), png);\n }\n }\n },\n };\n\n return plugin as TempestVitePlugin;\n}\n\n/** Options for the sharp `create` (blank canvas) form. */\ninterface SharpCreate {\n create: {\n width: number;\n height: number;\n channels: number;\n background: { r: number; g: number; b: number; alpha: number };\n };\n}\n\n/** The sharp factory function (minimal typing — sharp is an optional dep). */\ntype SharpFactory = (input: Buffer | SharpCreate, opts?: { density?: number }) => SharpInstance;\n\n/** Minimal subset of the sharp chainable API this plugin uses. */\ninterface SharpInstance {\n resize(\n width: number,\n height: number,\n opts?: { fit?: string; background?: { r: number; g: number; b: number; alpha: number } },\n ): SharpInstance;\n extend(opts: {\n top: number;\n bottom: number;\n left: number;\n right: number;\n background: { r: number; g: number; b: number; alpha: number };\n }): SharpInstance;\n flatten(opts: { background: Rgb }): SharpInstance;\n composite(items: { input: Buffer; gravity?: string }[]): SharpInstance;\n png(): SharpInstance;\n toBuffer(): Promise<Buffer>;\n}\n","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 /** URL the worker is served at (must match `registerServiceWorker`). Default `/sw.js`. */\n swUrl?: string;\n /** Dev URL of the precache manifest. Default `/precache-manifest.json`. */\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\n const plugin: Plugin = {\n name: \"tempest-pwa-dev-sw\",\n apply: \"serve\",\n configResolved(config) {\n root = config.root ?? process.cwd();\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 (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 (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"],"names":["normalizeProxy","proxy","out","path","value","createViteConfig","options","srcDir","port","host","open","alias","plugins","overrides","overridesConfig","base","react","resolve","merged","defineConfig","joinBase","file","hash","input","h","i","tempestPwaManifest","fileName","additionalUrls","exclude","includeHtml","appShell","config","_outputOptions","bundle","urls","list","version","DEFAULT_SPLASH","splashFileName","spec","splashMedia","hexToRgb","hex","full","c","tempestPwaIcons","source","sizes","maskableSizes","appleTouchIcon","outDir","background","maskablePadding","appleSplash","splashBackground","splashIconScale","splashSpecs","root","sharp","mod","readFile","bg","emit","data","size","png","content","splashBg","w","iconPx","icon","tempestPwaDevSw","swSrc","swUrl","manifestUrl","enabled","server","req","res","next","url","result","error"],"mappings":"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"}
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/** A single Apple splash target (CSS px + device pixel ratio). */
|
|
2
|
+
export declare interface AppleSplashSpec {
|
|
3
|
+
/** CSS width (device-width in the media query). */
|
|
4
|
+
width: number;
|
|
5
|
+
/** CSS height (device-height in the media query). */
|
|
6
|
+
height: number;
|
|
7
|
+
/** Device pixel ratio. */
|
|
8
|
+
ratio: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
/**
|
|
2
12
|
* Build a Tempest-flavored Vite config for a React app: the `@vitejs/plugin-react`
|
|
3
13
|
* plugin, the `@` → `src` import alias, and sane dev-server defaults — so a
|
|
@@ -52,6 +62,123 @@ export declare interface CreateViteConfigOptions {
|
|
|
52
62
|
*/
|
|
53
63
|
export declare type ProxyEntry = string | Record<string, unknown>;
|
|
54
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Dev-server plugin that makes the service worker available under `npm run dev`.
|
|
67
|
+
*
|
|
68
|
+
* The production worker is bundled at build time (`vite.sw.config.ts`), so in
|
|
69
|
+
* dev there is no `/sw.js` to register. This plugin compiles `swSrc` on the fly
|
|
70
|
+
* with esbuild and serves it as a classic worker, plus an empty
|
|
71
|
+
* `precache-manifest.json` (there are no hashed build assets to precache in
|
|
72
|
+
* dev — push and runtime caching still work). It closes the "SW in dev" gap
|
|
73
|
+
* that otherwise only `vite-plugin-pwa`'s `devOptions` covered.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // vite.config.ts
|
|
77
|
+
* import { createViteConfig, tempestPwaDevSw } from "tempest-react-sdk/vite";
|
|
78
|
+
*
|
|
79
|
+
* export default createViteConfig({ plugins: [tempestPwaDevSw()] });
|
|
80
|
+
*/
|
|
81
|
+
export declare function tempestPwaDevSw(options?: TempestPwaDevSwOptions): TempestVitePlugin;
|
|
82
|
+
|
|
83
|
+
/** Options for {@link tempestPwaDevSw}. */
|
|
84
|
+
export declare interface TempestPwaDevSwOptions {
|
|
85
|
+
/** Service-worker entry, relative to the project root. Default `src/sw.ts`. */
|
|
86
|
+
swSrc?: string;
|
|
87
|
+
/** URL the worker is served at (must match `registerServiceWorker`). Default `/sw.js`. */
|
|
88
|
+
swUrl?: string;
|
|
89
|
+
/** Dev URL of the precache manifest. Default `/precache-manifest.json`. */
|
|
90
|
+
manifestUrl?: string;
|
|
91
|
+
/** Serve the worker in dev. Default `true`; set `false` to opt out. */
|
|
92
|
+
enabled?: boolean;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Build plugin that rasterizes a single source image into a full PWA icon set
|
|
97
|
+
* (regular + maskable + apple-touch-icon), the dependency-free counterpart to
|
|
98
|
+
* `@vite-pwa/assets-generator`. Rendering uses **`sharp`**, imported lazily and
|
|
99
|
+
* treated as optional: if it isn't installed the plugin logs a warning and skips
|
|
100
|
+
* generation (your build still succeeds; the icons just aren't produced).
|
|
101
|
+
*
|
|
102
|
+
* Point your `manifest.webmanifest` icon entries at the emitted files
|
|
103
|
+
* (`/icons/icon-192.png`, `/icons/icon-512.png`, `/icons/maskable-512.png`) and
|
|
104
|
+
* the apple touch icon at `/apple-touch-icon.png`.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // vite.config.ts
|
|
108
|
+
* import { createViteConfig, tempestPwaIcons } from "tempest-react-sdk/vite";
|
|
109
|
+
*
|
|
110
|
+
* export default createViteConfig({
|
|
111
|
+
* plugins: [tempestPwaIcons({ source: "public/icon.svg" })],
|
|
112
|
+
* });
|
|
113
|
+
*/
|
|
114
|
+
export declare function tempestPwaIcons(options?: TempestPwaIconsOptions): TempestVitePlugin;
|
|
115
|
+
|
|
116
|
+
/** Options for {@link tempestPwaIcons}. */
|
|
117
|
+
export declare interface TempestPwaIconsOptions {
|
|
118
|
+
/** Source image (SVG or large PNG), relative to the project root. Default `public/icon.svg`. */
|
|
119
|
+
source?: string;
|
|
120
|
+
/** Square "any"-purpose icon sizes to emit. Default `[192, 512]`. */
|
|
121
|
+
sizes?: number[];
|
|
122
|
+
/** Square "maskable" icon sizes to emit (with safe-zone padding). Default `[512]`. */
|
|
123
|
+
maskableSizes?: number[];
|
|
124
|
+
/** Apple touch icon size, or `false` to skip. Default `180`. */
|
|
125
|
+
appleTouchIcon?: number | false;
|
|
126
|
+
/** Output directory for the icon set, under the build root. Default `icons`. */
|
|
127
|
+
outDir?: string;
|
|
128
|
+
/** Opaque background for maskable + apple icons (no transparency allowed). Default `#ffffff`. */
|
|
129
|
+
background?: string;
|
|
130
|
+
/** Maskable safe-zone padding as a fraction of the icon. Default `0.1` (10% each side). */
|
|
131
|
+
maskablePadding?: number;
|
|
132
|
+
/**
|
|
133
|
+
* Generate Apple splash screens (launch images) and inject the matching
|
|
134
|
+
* `<link rel="apple-touch-startup-image">` tags. `true` uses a built-in set
|
|
135
|
+
* of common iPhone/iPad portrait sizes; pass an array to override. Default `false`.
|
|
136
|
+
*/
|
|
137
|
+
appleSplash?: boolean | AppleSplashSpec[];
|
|
138
|
+
/** Background color for splash screens. Default: `background`. */
|
|
139
|
+
splashBackground?: string;
|
|
140
|
+
/** Icon size on the splash as a fraction of the shorter side. Default `0.3`. */
|
|
141
|
+
splashIconScale?: number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Vite build plugin that emits a `precache-manifest.json` listing every built
|
|
146
|
+
* asset (plus any `additionalUrls`) as root-absolute URLs, with a content-based
|
|
147
|
+
* `version`. It is the dependency-free counterpart to Workbox's `__WB_MANIFEST`:
|
|
148
|
+
* `installPrecache` (from `tempest-react-sdk/sw`) reads this file at the service
|
|
149
|
+
* worker's `install` event to cache the app shell for offline use.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* // vite.config.ts
|
|
153
|
+
* import { createViteConfig, tempestPwaManifest } from "tempest-react-sdk/vite";
|
|
154
|
+
*
|
|
155
|
+
* export default createViteConfig({
|
|
156
|
+
* plugins: [tempestPwaManifest({ additionalUrls: ["/manifest.webmanifest", "/icon.svg"] })],
|
|
157
|
+
* });
|
|
158
|
+
*/
|
|
159
|
+
export declare function tempestPwaManifest(options?: TempestPwaManifestOptions): TempestVitePlugin;
|
|
160
|
+
|
|
161
|
+
/** Options for {@link tempestPwaManifest}. */
|
|
162
|
+
export declare interface TempestPwaManifestOptions {
|
|
163
|
+
/** Output file name (under the build root). Default `precache-manifest.json`. */
|
|
164
|
+
fileName?: string;
|
|
165
|
+
/**
|
|
166
|
+
* Extra URLs to precache that Vite doesn't emit into the bundle — typically
|
|
167
|
+
* `public/` assets like the web manifest and icons. Default `[]`.
|
|
168
|
+
*/
|
|
169
|
+
additionalUrls?: string[];
|
|
170
|
+
/** Emitted files matching this are skipped. Default `/\.map$/` (source maps). */
|
|
171
|
+
exclude?: RegExp;
|
|
172
|
+
/** Include emitted `.html` documents (the app shell). Default `true`. */
|
|
173
|
+
includeHtml?: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* App-shell document always added to the manifest, even if Vite emits it
|
|
176
|
+
* after this plugin runs. Must match `installPrecache`'s `navigateFallback`
|
|
177
|
+
* so offline navigations resolve. Pass `false` to disable. Default `/index.html`.
|
|
178
|
+
*/
|
|
179
|
+
appShell?: string | false;
|
|
180
|
+
}
|
|
181
|
+
|
|
55
182
|
/**
|
|
56
183
|
* The resulting Vite config object. Typed loosely so the SDK's published
|
|
57
184
|
* declarations stay free of `vite`'s internal types; assign it straight to a
|
|
@@ -59,4 +186,13 @@ export declare type ProxyEntry = string | Record<string, unknown>;
|
|
|
59
186
|
*/
|
|
60
187
|
export declare type TempestViteConfig = Record<string, unknown>;
|
|
61
188
|
|
|
189
|
+
/**
|
|
190
|
+
* A Vite plugin object. Typed loosely so the SDK's published declarations stay
|
|
191
|
+
* free of `vite`'s internal types (which the `.d.ts` rollup can't analyze);
|
|
192
|
+
* assign the result straight into a `plugins: [...]` array.
|
|
193
|
+
*/
|
|
194
|
+
export declare type TempestVitePlugin = {
|
|
195
|
+
name: string;
|
|
196
|
+
} & Record<string, unknown>;
|
|
197
|
+
|
|
62
198
|
export { }
|
package/dist/vite.js
CHANGED
|
@@ -1,46 +1,265 @@
|
|
|
1
|
-
import { resolve as
|
|
2
|
-
import { defineConfig as
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { resolve as k } from "node:path";
|
|
2
|
+
import { defineConfig as z } from "vite";
|
|
3
|
+
import B from "@vitejs/plugin-react";
|
|
4
|
+
import { readFile as P } from "node:fs/promises";
|
|
5
|
+
function H(t) {
|
|
6
|
+
const e = {};
|
|
7
|
+
for (const [o, a] of Object.entries(t))
|
|
8
|
+
e[o] = typeof a == "string" ? { target: a, changeOrigin: !0 } : a;
|
|
9
|
+
return e;
|
|
10
|
+
}
|
|
11
|
+
function N(t = {}) {
|
|
11
12
|
const {
|
|
12
|
-
srcDir:
|
|
13
|
-
port:
|
|
14
|
-
host:
|
|
15
|
-
open:
|
|
16
|
-
proxy:
|
|
17
|
-
alias:
|
|
18
|
-
plugins:
|
|
19
|
-
overrides:
|
|
20
|
-
} = t,
|
|
21
|
-
plugins: [
|
|
13
|
+
srcDir: e = "src",
|
|
14
|
+
port: o = 5173,
|
|
15
|
+
host: a = "127.0.0.1",
|
|
16
|
+
open: h = !1,
|
|
17
|
+
proxy: s,
|
|
18
|
+
alias: d = {},
|
|
19
|
+
plugins: f = [],
|
|
20
|
+
overrides: u = {}
|
|
21
|
+
} = t, r = u, c = {
|
|
22
|
+
plugins: [B(), ...f],
|
|
22
23
|
resolve: {
|
|
23
24
|
alias: {
|
|
24
|
-
"@":
|
|
25
|
-
...
|
|
25
|
+
"@": k(process.cwd(), e),
|
|
26
|
+
...d
|
|
26
27
|
}
|
|
27
28
|
},
|
|
28
29
|
server: {
|
|
29
|
-
port:
|
|
30
|
-
host:
|
|
31
|
-
open:
|
|
32
|
-
...
|
|
30
|
+
port: o,
|
|
31
|
+
host: a,
|
|
32
|
+
open: h,
|
|
33
|
+
...s ? { proxy: H(s) } : {}
|
|
34
|
+
}
|
|
35
|
+
}, l = {
|
|
36
|
+
...c,
|
|
37
|
+
...r,
|
|
38
|
+
plugins: [...c.plugins ?? [], ...r.plugins ?? []],
|
|
39
|
+
resolve: { ...c.resolve, ...r.resolve },
|
|
40
|
+
server: { ...c.server, ...r.server }
|
|
41
|
+
};
|
|
42
|
+
return z(l);
|
|
43
|
+
}
|
|
44
|
+
function I(t, e) {
|
|
45
|
+
return `${t.endsWith("/") ? t : `${t}/`}${e}`.replace(/([^:]\/)\/+/g, "$1");
|
|
46
|
+
}
|
|
47
|
+
function A(t) {
|
|
48
|
+
let e = 5381;
|
|
49
|
+
for (let o = 0; o < t.length; o++)
|
|
50
|
+
e = (e << 5) + e + t.charCodeAt(o) >>> 0;
|
|
51
|
+
return e.toString(16);
|
|
52
|
+
}
|
|
53
|
+
function U(t = {}) {
|
|
54
|
+
const {
|
|
55
|
+
fileName: e = "precache-manifest.json",
|
|
56
|
+
additionalUrls: o = [],
|
|
57
|
+
exclude: a = /\.map$/,
|
|
58
|
+
includeHtml: h = !0,
|
|
59
|
+
appShell: s = "/index.html"
|
|
60
|
+
} = t;
|
|
61
|
+
let d = "/";
|
|
62
|
+
return {
|
|
63
|
+
name: "tempest-pwa-manifest",
|
|
64
|
+
apply: "build",
|
|
65
|
+
configResolved(u) {
|
|
66
|
+
d = u.base ?? "/";
|
|
67
|
+
},
|
|
68
|
+
generateBundle(u, r) {
|
|
69
|
+
const c = new Set(o);
|
|
70
|
+
s && c.add(s);
|
|
71
|
+
for (const m of Object.keys(r))
|
|
72
|
+
m !== e && (a.test(m) || !h && m.endsWith(".html") || c.add(I(d, m)));
|
|
73
|
+
const l = [...c].sort(), g = A(l.join(`
|
|
74
|
+
`));
|
|
75
|
+
this.emitFile({
|
|
76
|
+
type: "asset",
|
|
77
|
+
fileName: e,
|
|
78
|
+
source: JSON.stringify({ version: g, urls: l })
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const D = [
|
|
84
|
+
{ width: 375, height: 667, ratio: 2 },
|
|
85
|
+
// iPhone SE / 8
|
|
86
|
+
{ width: 375, height: 812, ratio: 3 },
|
|
87
|
+
// iPhone X / 11 Pro
|
|
88
|
+
{ width: 390, height: 844, ratio: 3 },
|
|
89
|
+
// iPhone 12 / 13 / 14
|
|
90
|
+
{ width: 393, height: 852, ratio: 3 },
|
|
91
|
+
// iPhone 14 Pro / 15
|
|
92
|
+
{ width: 414, height: 896, ratio: 2 },
|
|
93
|
+
// iPhone XR / 11
|
|
94
|
+
{ width: 414, height: 896, ratio: 3 },
|
|
95
|
+
// iPhone XS Max / 11 Pro Max
|
|
96
|
+
{ width: 428, height: 926, ratio: 3 },
|
|
97
|
+
// iPhone 13/14 Pro Max
|
|
98
|
+
{ width: 430, height: 932, ratio: 3 },
|
|
99
|
+
// iPhone 15 Pro Max
|
|
100
|
+
{ width: 768, height: 1024, ratio: 2 },
|
|
101
|
+
// iPad
|
|
102
|
+
{ width: 834, height: 1194, ratio: 2 },
|
|
103
|
+
// iPad Pro 11"
|
|
104
|
+
{ width: 1024, height: 1366, ratio: 2 }
|
|
105
|
+
// iPad Pro 12.9"
|
|
106
|
+
];
|
|
107
|
+
function $(t) {
|
|
108
|
+
return `splash/apple-splash-${t.width * t.ratio}x${t.height * t.ratio}.png`;
|
|
109
|
+
}
|
|
110
|
+
function F(t) {
|
|
111
|
+
return `(device-width: ${t.width}px) and (device-height: ${t.height}px) and (-webkit-device-pixel-ratio: ${t.ratio}) and (orientation: portrait)`;
|
|
112
|
+
}
|
|
113
|
+
function M(t) {
|
|
114
|
+
const e = t.replace("#", ""), o = e.length === 3 ? e.split("").map((a) => a + a).join("") : e;
|
|
115
|
+
return {
|
|
116
|
+
r: parseInt(o.slice(0, 2), 16),
|
|
117
|
+
g: parseInt(o.slice(2, 4), 16),
|
|
118
|
+
b: parseInt(o.slice(4, 6), 16)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function L(t = {}) {
|
|
122
|
+
const {
|
|
123
|
+
source: e = "public/icon.svg",
|
|
124
|
+
sizes: o = [192, 512],
|
|
125
|
+
maskableSizes: a = [512],
|
|
126
|
+
appleTouchIcon: h = 180,
|
|
127
|
+
outDir: s = "icons",
|
|
128
|
+
background: d = "#ffffff",
|
|
129
|
+
maskablePadding: f = 0.1,
|
|
130
|
+
appleSplash: u = !1,
|
|
131
|
+
splashBackground: r,
|
|
132
|
+
splashIconScale: c = 0.3
|
|
133
|
+
} = t, l = u ? Array.isArray(u) ? u : D : [];
|
|
134
|
+
let g = process.cwd();
|
|
135
|
+
return {
|
|
136
|
+
name: "tempest-pwa-icons",
|
|
137
|
+
apply: "build",
|
|
138
|
+
configResolved(p) {
|
|
139
|
+
g = p.root ?? process.cwd();
|
|
140
|
+
},
|
|
141
|
+
transformIndexHtml() {
|
|
142
|
+
if (l.length)
|
|
143
|
+
return l.map((p) => ({
|
|
144
|
+
tag: "link",
|
|
145
|
+
attrs: {
|
|
146
|
+
rel: "apple-touch-startup-image",
|
|
147
|
+
media: F(p),
|
|
148
|
+
href: `/${$(p)}`
|
|
149
|
+
},
|
|
150
|
+
injectTo: "head"
|
|
151
|
+
}));
|
|
152
|
+
},
|
|
153
|
+
async generateBundle() {
|
|
154
|
+
let p;
|
|
155
|
+
try {
|
|
156
|
+
const i = await import("sharp");
|
|
157
|
+
p = i.default ?? i;
|
|
158
|
+
} catch {
|
|
159
|
+
this.warn(
|
|
160
|
+
"tempestPwaIcons: `sharp` is not installed — skipping icon generation. Run `npm i -D sharp` to enable it."
|
|
161
|
+
);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const w = await P(k(g, e)), y = M(d), b = (n, i) => {
|
|
165
|
+
this.emitFile({ type: "asset", fileName: n, source: i });
|
|
166
|
+
};
|
|
167
|
+
for (const n of o) {
|
|
168
|
+
const i = await p(w, { density: Math.max(n, 512) }).resize(n, n, {
|
|
169
|
+
fit: "contain",
|
|
170
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
|
171
|
+
}).png().toBuffer();
|
|
172
|
+
b(`${s}/icon-${n}.png`, i);
|
|
173
|
+
}
|
|
174
|
+
for (const n of a) {
|
|
175
|
+
const i = Math.round(n * (1 - f * 2)), v = await p(w, { density: Math.max(n, 512) }).resize(i, i, {
|
|
176
|
+
fit: "contain",
|
|
177
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
|
178
|
+
}).extend({
|
|
179
|
+
top: Math.round((n - i) / 2),
|
|
180
|
+
bottom: Math.round((n - i) / 2),
|
|
181
|
+
left: Math.round((n - i) / 2),
|
|
182
|
+
right: Math.round((n - i) / 2),
|
|
183
|
+
background: { ...y, alpha: 1 }
|
|
184
|
+
}).resize(n, n).png().toBuffer();
|
|
185
|
+
b(`${s}/maskable-${n}.png`, v);
|
|
186
|
+
}
|
|
187
|
+
if (h) {
|
|
188
|
+
const n = await p(w, { density: Math.max(h, 512) }).resize(h, h, {
|
|
189
|
+
fit: "contain",
|
|
190
|
+
background: { ...y, alpha: 1 }
|
|
191
|
+
}).flatten({ background: y }).png().toBuffer();
|
|
192
|
+
b("apple-touch-icon.png", n);
|
|
193
|
+
}
|
|
194
|
+
if (l.length) {
|
|
195
|
+
const n = M(r ?? d);
|
|
196
|
+
for (const i of l) {
|
|
197
|
+
const v = i.width * i.ratio, S = i.height * i.ratio, x = Math.round(Math.min(v, S) * c), j = await p(w, { density: Math.max(x, 512) }).resize(x, x, {
|
|
198
|
+
fit: "contain",
|
|
199
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
|
200
|
+
}).png().toBuffer(), C = await p({
|
|
201
|
+
create: {
|
|
202
|
+
width: v,
|
|
203
|
+
height: S,
|
|
204
|
+
channels: 4,
|
|
205
|
+
background: { ...n, alpha: 1 }
|
|
206
|
+
}
|
|
207
|
+
}).composite([{ input: j, gravity: "center" }]).png().toBuffer();
|
|
208
|
+
b($(i), C);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function J(t = {}) {
|
|
215
|
+
const {
|
|
216
|
+
swSrc: e = "src/sw.ts",
|
|
217
|
+
swUrl: o = "/sw.js",
|
|
218
|
+
manifestUrl: a = "/precache-manifest.json",
|
|
219
|
+
enabled: h = !0
|
|
220
|
+
} = t;
|
|
221
|
+
let s = process.cwd();
|
|
222
|
+
return {
|
|
223
|
+
name: "tempest-pwa-dev-sw",
|
|
224
|
+
apply: "serve",
|
|
225
|
+
configResolved(f) {
|
|
226
|
+
s = f.root ?? process.cwd();
|
|
227
|
+
},
|
|
228
|
+
configureServer(f) {
|
|
229
|
+
h && f.middlewares.use(async (u, r, c) => {
|
|
230
|
+
const l = (u.url ?? "").split("?")[0];
|
|
231
|
+
if (l === o) {
|
|
232
|
+
try {
|
|
233
|
+
const m = await (await import("esbuild")).build({
|
|
234
|
+
entryPoints: [k(s, e)],
|
|
235
|
+
bundle: !0,
|
|
236
|
+
format: "iife",
|
|
237
|
+
platform: "browser",
|
|
238
|
+
target: "es2020",
|
|
239
|
+
write: !1,
|
|
240
|
+
absWorkingDir: s,
|
|
241
|
+
logLevel: "silent"
|
|
242
|
+
});
|
|
243
|
+
r.setHeader("Content-Type", "application/javascript"), r.setHeader("Service-Worker-Allowed", "/"), r.setHeader("Cache-Control", "no-cache"), r.end(m.outputFiles[0].text);
|
|
244
|
+
} catch (g) {
|
|
245
|
+
r.statusCode = 500, r.end(`// SW dev build failed:
|
|
246
|
+
// ${String(g)}`);
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (l === a) {
|
|
251
|
+
r.setHeader("Content-Type", "application/json"), r.setHeader("Cache-Control", "no-cache"), r.end(JSON.stringify({ version: "dev", urls: [] }));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
c();
|
|
255
|
+
});
|
|
33
256
|
}
|
|
34
|
-
}, f = {
|
|
35
|
-
...s,
|
|
36
|
-
...o,
|
|
37
|
-
plugins: [...s.plugins ?? [], ...o.plugins ?? []],
|
|
38
|
-
resolve: { ...s.resolve, ...o.resolve },
|
|
39
|
-
server: { ...s.server, ...o.server }
|
|
40
257
|
};
|
|
41
|
-
return u(f);
|
|
42
258
|
}
|
|
43
259
|
export {
|
|
44
|
-
|
|
260
|
+
N as createViteConfig,
|
|
261
|
+
J as tempestPwaDevSw,
|
|
262
|
+
L as tempestPwaIcons,
|
|
263
|
+
U as tempestPwaManifest
|
|
45
264
|
};
|
|
46
265
|
//# sourceMappingURL=vite.js.map
|