@sovereignbase/pwa 0.0.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.
@@ -0,0 +1,128 @@
1
+ /*
2
+ * Copyright 2026 Sovereignbase
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ const require_htmlDocument = require("../htmlDocument-Cx-dprM5.cjs");
18
+ //#region src/serviceWorker/entrypoint.ts
19
+ const worker = self;
20
+ const cachePrefix = "@sovereignbase/pwa:";
21
+ const cacheName = `${cachePrefix}${buildId}`;
22
+ const backgroundStartup = Promise.resolve(customWaitUntil?.());
23
+ customInitialize?.();
24
+ const routes = Object.freeze({
25
+ document: buildDocumentResponse,
26
+ static: negotiateCache
27
+ });
28
+ worker.addEventListener("fetch", (event) => {
29
+ event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]));
30
+ if (event.request.method !== "GET" || bypassesServiceWorker(event.request)) return;
31
+ const route = event.request.mode === "navigate" ? routes.document : routes.static;
32
+ event.respondWith(route(event));
33
+ });
34
+ worker.addEventListener("install", (event) => {
35
+ event.waitUntil(Promise.all([
36
+ caches.open(cacheName).then((cache) => cache.addAll(precache)),
37
+ worker.skipWaiting(),
38
+ backgroundStartup
39
+ ]));
40
+ });
41
+ worker.addEventListener("activate", (event) => {
42
+ event.waitUntil(activateServiceWorker());
43
+ });
44
+ worker.addEventListener("message", (event) => {
45
+ if (event.data === "SKIP_WAITING") event.waitUntil(worker.skipWaiting());
46
+ });
47
+ async function buildDocumentResponse(event) {
48
+ const cache = await caches.open(cacheName);
49
+ const cached = await cache.match(event.request);
50
+ const rendered = renderDocument(event.request).then(async (response) => {
51
+ await cache.put(event.request, response.clone());
52
+ return response;
53
+ });
54
+ if (cached === void 0) return rendered;
55
+ event.waitUntil(rendered);
56
+ return cached;
57
+ }
58
+ async function negotiateCache(event) {
59
+ const cached = await caches.match(event.request);
60
+ const updated = fetch(event.request).then(async (response) => {
61
+ if (response.ok) await (await caches.open(cacheName)).put(event.request, response.clone());
62
+ return response;
63
+ });
64
+ if (cached === void 0) return updated;
65
+ event.waitUntil(updated);
66
+ return cached;
67
+ }
68
+ async function renderDocument(request) {
69
+ const language = documentLanguage(request);
70
+ const options = documentOptions[language] ?? documentOptions[defaultLanguage];
71
+ const markup = await require_htmlDocument.documentMarkup({
72
+ ...options,
73
+ entrypoint,
74
+ language,
75
+ manifestUrl: `/${language}/manifest.webmanifest`,
76
+ stylesheet
77
+ });
78
+ return new Response(markup, { headers: {
79
+ "content-type": "text/html;charset=UTF-8",
80
+ "x-pwaize-build-id": buildId
81
+ } });
82
+ }
83
+ function documentLanguage(request) {
84
+ const pathLanguage = new URL(request.url).pathname.split("/").filter(Boolean)[0];
85
+ if (pathLanguage in documentOptions) return pathLanguage;
86
+ const accepted = request.headers.get("accept-language") ?? "";
87
+ for (const preference of accepted.split(",")) {
88
+ const language = preference.split(";")[0].trim();
89
+ if (language in documentOptions) return language;
90
+ const baseLanguage = language.split("-")[0];
91
+ if (baseLanguage in documentOptions) return baseLanguage;
92
+ }
93
+ return defaultLanguage;
94
+ }
95
+ function bypassesServiceWorker(request) {
96
+ const url = new URL(request.url);
97
+ for (const rule of bypassRules) {
98
+ const value = rule.absolute ? url.href : `${url.pathname}${url.search}`;
99
+ if (new RegExp(rule.source, rule.flags).test(value)) return true;
100
+ }
101
+ return false;
102
+ }
103
+ async function checkForUpdate() {
104
+ try {
105
+ const response = await fetch(buildIdUrl, { cache: "no-store" });
106
+ if (!response.ok || (await response.text()).trim() === buildId) return;
107
+ await worker.registration.update();
108
+ } catch {}
109
+ }
110
+ async function activateServiceWorker() {
111
+ await Promise.all([
112
+ deleteOldCaches(),
113
+ worker.clients.claim(),
114
+ backgroundStartup
115
+ ]);
116
+ const clients = await worker.clients.matchAll({
117
+ includeUncontrolled: true,
118
+ type: "window"
119
+ });
120
+ await Promise.all(clients.map((client) => client.navigate(client.url)));
121
+ }
122
+ async function deleteOldCaches() {
123
+ const names = await caches.keys();
124
+ await Promise.all(names.filter((name) => name.startsWith(cachePrefix) && name !== cacheName).map((name) => caches.delete(name)));
125
+ }
126
+ //#endregion
127
+
128
+ //# sourceMappingURL=entrypoint.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.cjs","names":["documentMarkup"],"sources":["../../src/serviceWorker/entrypoint.ts"],"sourcesContent":["import type { DocumentMarkupOptions } from '../.types/index.js'\nimport { documentMarkup } from '../htmlDocument/index.js'\n\ndeclare const buildId: string\ndeclare const buildIdUrl: string\ndeclare const bypassRules: ReadonlyArray<{\n absolute: boolean\n flags: string\n source: string\n}>\ndeclare const customInitialize: (() => void) | undefined\ndeclare const customWaitUntil: (() => Promise<void>) | undefined\ndeclare const defaultLanguage: DocumentMarkupOptions['language']\ndeclare const documentOptions: Readonly<\n Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n >\n>\ndeclare const entrypoint: string\ndeclare const precache: readonly string[]\ndeclare const stylesheet: string\n\nconst worker = self as unknown as ServiceWorkerGlobalScope\nconst cachePrefix = '@sovereignbase/pwa:'\nconst cacheName = `${cachePrefix}${buildId}`\nconst backgroundStartup = Promise.resolve(customWaitUntil?.())\n\ncustomInitialize?.()\n\nconst routes = Object.freeze({\n document: buildDocumentResponse,\n static: negotiateCache,\n})\n\nworker.addEventListener('fetch', (event) => {\n event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]))\n\n if (event.request.method !== 'GET' || bypassesServiceWorker(event.request)) {\n return\n }\n\n const route =\n event.request.mode === 'navigate' ? routes.document : routes.static\n event.respondWith(route(event))\n})\n\nworker.addEventListener('install', (event) => {\n event.waitUntil(\n Promise.all([\n caches.open(cacheName).then((cache) => cache.addAll(precache)),\n worker.skipWaiting(),\n backgroundStartup,\n ])\n )\n})\n\nworker.addEventListener('activate', (event) => {\n event.waitUntil(activateServiceWorker())\n})\n\nworker.addEventListener('message', (event) => {\n if (event.data === 'SKIP_WAITING') {\n event.waitUntil(worker.skipWaiting())\n }\n})\n\nasync function buildDocumentResponse(event: FetchEvent): Promise<Response> {\n const cache = await caches.open(cacheName)\n const cached = await cache.match(event.request)\n const rendered = renderDocument(event.request).then(async (response) => {\n await cache.put(event.request, response.clone())\n return response\n })\n\n if (cached === undefined) return rendered\n\n event.waitUntil(rendered)\n return cached\n}\n\nasync function negotiateCache(event: FetchEvent): Promise<Response> {\n const cached = await caches.match(event.request)\n const updated = fetch(event.request).then(async (response) => {\n if (response.ok) {\n const cache = await caches.open(cacheName)\n await cache.put(event.request, response.clone())\n }\n return response\n })\n\n if (cached === undefined) return updated\n\n event.waitUntil(updated)\n return cached\n}\n\nasync function renderDocument(request: Request): Promise<Response> {\n const language = documentLanguage(request)\n const options = documentOptions[language] ?? documentOptions[defaultLanguage]\n const markup = await documentMarkup({\n ...options,\n entrypoint,\n language,\n manifestUrl: `/${language}/manifest.webmanifest`,\n stylesheet,\n })\n\n return new Response(markup, {\n headers: {\n 'content-type': 'text/html;charset=UTF-8',\n 'x-pwaize-build-id': buildId,\n },\n })\n}\n\nfunction documentLanguage(request: Request): DocumentMarkupOptions['language'] {\n const pathLanguage = new URL(request.url).pathname\n .split('/')\n .filter(Boolean)[0]\n if (pathLanguage in documentOptions) {\n return pathLanguage as DocumentMarkupOptions['language']\n }\n\n const accepted = request.headers.get('accept-language') ?? ''\n for (const preference of accepted.split(',')) {\n const language = preference.split(';')[0].trim()\n if (language in documentOptions) {\n return language as DocumentMarkupOptions['language']\n }\n\n const baseLanguage = language.split('-')[0]\n if (baseLanguage in documentOptions) {\n return baseLanguage as DocumentMarkupOptions['language']\n }\n }\n\n return defaultLanguage\n}\n\nfunction bypassesServiceWorker(request: Request): boolean {\n const url = new URL(request.url)\n\n for (const rule of bypassRules) {\n const value = rule.absolute ? url.href : `${url.pathname}${url.search}`\n if (new RegExp(rule.source, rule.flags).test(value)) return true\n }\n\n return false\n}\n\nasync function checkForUpdate(): Promise<void> {\n try {\n const response = await fetch(buildIdUrl, { cache: 'no-store' })\n if (!response.ok || (await response.text()).trim() === buildId) return\n\n await worker.registration.update()\n } catch {\n // Offline version checks must not prevent offline responses.\n }\n}\n\nasync function activateServiceWorker(): Promise<void> {\n await Promise.all([\n deleteOldCaches(),\n worker.clients.claim(),\n backgroundStartup,\n ])\n\n const clients = await worker.clients.matchAll({\n includeUncontrolled: true,\n type: 'window',\n })\n await Promise.all(clients.map((client) => client.navigate(client.url)))\n}\n\nasync function deleteOldCaches(): Promise<void> {\n const names = await caches.keys()\n await Promise.all(\n names\n .filter((name) => name.startsWith(cachePrefix) && name !== cacheName)\n .map((name) => caches.delete(name))\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+
2
+ export {}
@@ -0,0 +1,2 @@
1
+
2
+ export {}
@@ -0,0 +1,129 @@
1
+ /*
2
+ * Copyright 2026 Sovereignbase
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { t as documentMarkup } from "../htmlDocument-DABSNDvf.js";
18
+ //#region src/serviceWorker/entrypoint.ts
19
+ const worker = self;
20
+ const cachePrefix = "@sovereignbase/pwa:";
21
+ const cacheName = `${cachePrefix}${buildId}`;
22
+ const backgroundStartup = Promise.resolve(customWaitUntil?.());
23
+ customInitialize?.();
24
+ const routes = Object.freeze({
25
+ document: buildDocumentResponse,
26
+ static: negotiateCache
27
+ });
28
+ worker.addEventListener("fetch", (event) => {
29
+ event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]));
30
+ if (event.request.method !== "GET" || bypassesServiceWorker(event.request)) return;
31
+ const route = event.request.mode === "navigate" ? routes.document : routes.static;
32
+ event.respondWith(route(event));
33
+ });
34
+ worker.addEventListener("install", (event) => {
35
+ event.waitUntil(Promise.all([
36
+ caches.open(cacheName).then((cache) => cache.addAll(precache)),
37
+ worker.skipWaiting(),
38
+ backgroundStartup
39
+ ]));
40
+ });
41
+ worker.addEventListener("activate", (event) => {
42
+ event.waitUntil(activateServiceWorker());
43
+ });
44
+ worker.addEventListener("message", (event) => {
45
+ if (event.data === "SKIP_WAITING") event.waitUntil(worker.skipWaiting());
46
+ });
47
+ async function buildDocumentResponse(event) {
48
+ const cache = await caches.open(cacheName);
49
+ const cached = await cache.match(event.request);
50
+ const rendered = renderDocument(event.request).then(async (response) => {
51
+ await cache.put(event.request, response.clone());
52
+ return response;
53
+ });
54
+ if (cached === void 0) return rendered;
55
+ event.waitUntil(rendered);
56
+ return cached;
57
+ }
58
+ async function negotiateCache(event) {
59
+ const cached = await caches.match(event.request);
60
+ const updated = fetch(event.request).then(async (response) => {
61
+ if (response.ok) await (await caches.open(cacheName)).put(event.request, response.clone());
62
+ return response;
63
+ });
64
+ if (cached === void 0) return updated;
65
+ event.waitUntil(updated);
66
+ return cached;
67
+ }
68
+ async function renderDocument(request) {
69
+ const language = documentLanguage(request);
70
+ const options = documentOptions[language] ?? documentOptions[defaultLanguage];
71
+ const markup = await documentMarkup({
72
+ ...options,
73
+ entrypoint,
74
+ language,
75
+ manifestUrl: `/${language}/manifest.webmanifest`,
76
+ stylesheet
77
+ });
78
+ return new Response(markup, { headers: {
79
+ "content-type": "text/html;charset=UTF-8",
80
+ "x-pwaize-build-id": buildId
81
+ } });
82
+ }
83
+ function documentLanguage(request) {
84
+ const pathLanguage = new URL(request.url).pathname.split("/").filter(Boolean)[0];
85
+ if (pathLanguage in documentOptions) return pathLanguage;
86
+ const accepted = request.headers.get("accept-language") ?? "";
87
+ for (const preference of accepted.split(",")) {
88
+ const language = preference.split(";")[0].trim();
89
+ if (language in documentOptions) return language;
90
+ const baseLanguage = language.split("-")[0];
91
+ if (baseLanguage in documentOptions) return baseLanguage;
92
+ }
93
+ return defaultLanguage;
94
+ }
95
+ function bypassesServiceWorker(request) {
96
+ const url = new URL(request.url);
97
+ for (const rule of bypassRules) {
98
+ const value = rule.absolute ? url.href : `${url.pathname}${url.search}`;
99
+ if (new RegExp(rule.source, rule.flags).test(value)) return true;
100
+ }
101
+ return false;
102
+ }
103
+ async function checkForUpdate() {
104
+ try {
105
+ const response = await fetch(buildIdUrl, { cache: "no-store" });
106
+ if (!response.ok || (await response.text()).trim() === buildId) return;
107
+ await worker.registration.update();
108
+ } catch {}
109
+ }
110
+ async function activateServiceWorker() {
111
+ await Promise.all([
112
+ deleteOldCaches(),
113
+ worker.clients.claim(),
114
+ backgroundStartup
115
+ ]);
116
+ const clients = await worker.clients.matchAll({
117
+ includeUncontrolled: true,
118
+ type: "window"
119
+ });
120
+ await Promise.all(clients.map((client) => client.navigate(client.url)));
121
+ }
122
+ async function deleteOldCaches() {
123
+ const names = await caches.keys();
124
+ await Promise.all(names.filter((name) => name.startsWith(cachePrefix) && name !== cacheName).map((name) => caches.delete(name)));
125
+ }
126
+ //#endregion
127
+ export {};
128
+
129
+ //# sourceMappingURL=entrypoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.js","names":[],"sources":["../../src/serviceWorker/entrypoint.ts"],"sourcesContent":["import type { DocumentMarkupOptions } from '../.types/index.js'\nimport { documentMarkup } from '../htmlDocument/index.js'\n\ndeclare const buildId: string\ndeclare const buildIdUrl: string\ndeclare const bypassRules: ReadonlyArray<{\n absolute: boolean\n flags: string\n source: string\n}>\ndeclare const customInitialize: (() => void) | undefined\ndeclare const customWaitUntil: (() => Promise<void>) | undefined\ndeclare const defaultLanguage: DocumentMarkupOptions['language']\ndeclare const documentOptions: Readonly<\n Record<\n string,\n Omit<\n DocumentMarkupOptions,\n 'entrypoint' | 'language' | 'manifestUrl' | 'stylesheet'\n >\n >\n>\ndeclare const entrypoint: string\ndeclare const precache: readonly string[]\ndeclare const stylesheet: string\n\nconst worker = self as unknown as ServiceWorkerGlobalScope\nconst cachePrefix = '@sovereignbase/pwa:'\nconst cacheName = `${cachePrefix}${buildId}`\nconst backgroundStartup = Promise.resolve(customWaitUntil?.())\n\ncustomInitialize?.()\n\nconst routes = Object.freeze({\n document: buildDocumentResponse,\n static: negotiateCache,\n})\n\nworker.addEventListener('fetch', (event) => {\n event.waitUntil(Promise.all([backgroundStartup, checkForUpdate()]))\n\n if (event.request.method !== 'GET' || bypassesServiceWorker(event.request)) {\n return\n }\n\n const route =\n event.request.mode === 'navigate' ? routes.document : routes.static\n event.respondWith(route(event))\n})\n\nworker.addEventListener('install', (event) => {\n event.waitUntil(\n Promise.all([\n caches.open(cacheName).then((cache) => cache.addAll(precache)),\n worker.skipWaiting(),\n backgroundStartup,\n ])\n )\n})\n\nworker.addEventListener('activate', (event) => {\n event.waitUntil(activateServiceWorker())\n})\n\nworker.addEventListener('message', (event) => {\n if (event.data === 'SKIP_WAITING') {\n event.waitUntil(worker.skipWaiting())\n }\n})\n\nasync function buildDocumentResponse(event: FetchEvent): Promise<Response> {\n const cache = await caches.open(cacheName)\n const cached = await cache.match(event.request)\n const rendered = renderDocument(event.request).then(async (response) => {\n await cache.put(event.request, response.clone())\n return response\n })\n\n if (cached === undefined) return rendered\n\n event.waitUntil(rendered)\n return cached\n}\n\nasync function negotiateCache(event: FetchEvent): Promise<Response> {\n const cached = await caches.match(event.request)\n const updated = fetch(event.request).then(async (response) => {\n if (response.ok) {\n const cache = await caches.open(cacheName)\n await cache.put(event.request, response.clone())\n }\n return response\n })\n\n if (cached === undefined) return updated\n\n event.waitUntil(updated)\n return cached\n}\n\nasync function renderDocument(request: Request): Promise<Response> {\n const language = documentLanguage(request)\n const options = documentOptions[language] ?? documentOptions[defaultLanguage]\n const markup = await documentMarkup({\n ...options,\n entrypoint,\n language,\n manifestUrl: `/${language}/manifest.webmanifest`,\n stylesheet,\n })\n\n return new Response(markup, {\n headers: {\n 'content-type': 'text/html;charset=UTF-8',\n 'x-pwaize-build-id': buildId,\n },\n })\n}\n\nfunction documentLanguage(request: Request): DocumentMarkupOptions['language'] {\n const pathLanguage = new URL(request.url).pathname\n .split('/')\n .filter(Boolean)[0]\n if (pathLanguage in documentOptions) {\n return pathLanguage as DocumentMarkupOptions['language']\n }\n\n const accepted = request.headers.get('accept-language') ?? ''\n for (const preference of accepted.split(',')) {\n const language = preference.split(';')[0].trim()\n if (language in documentOptions) {\n return language as DocumentMarkupOptions['language']\n }\n\n const baseLanguage = language.split('-')[0]\n if (baseLanguage in documentOptions) {\n return baseLanguage as DocumentMarkupOptions['language']\n }\n }\n\n return defaultLanguage\n}\n\nfunction bypassesServiceWorker(request: Request): boolean {\n const url = new URL(request.url)\n\n for (const rule of bypassRules) {\n const value = rule.absolute ? url.href : `${url.pathname}${url.search}`\n if (new RegExp(rule.source, rule.flags).test(value)) return true\n }\n\n return false\n}\n\nasync function checkForUpdate(): Promise<void> {\n try {\n const response = await fetch(buildIdUrl, { cache: 'no-store' })\n if (!response.ok || (await response.text()).trim() === buildId) return\n\n await worker.registration.update()\n } catch {\n // Offline version checks must not prevent offline responses.\n }\n}\n\nasync function activateServiceWorker(): Promise<void> {\n await Promise.all([\n deleteOldCaches(),\n worker.clients.claim(),\n backgroundStartup,\n ])\n\n const clients = await worker.clients.matchAll({\n includeUncontrolled: true,\n type: 'window',\n })\n await Promise.all(clients.map((client) => client.navigate(client.url)))\n}\n\nasync function deleteOldCaches(): Promise<void> {\n const names = await caches.keys()\n await Promise.all(\n names\n .filter((name) => name.startsWith(cachePrefix) && name !== cacheName)\n .map((name) => caches.delete(name))\n )\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@sovereignbase/pwa",
3
+ "version": "0.0.0",
4
+ "description": "Build offline-first, search-engine-optimized progressive web applications.",
5
+ "keywords": [
6
+ "build-tool",
7
+ "offline-first",
8
+ "progressive-web-app",
9
+ "pwa",
10
+ "service-worker",
11
+ "static-site-generation",
12
+ "typescript"
13
+ ],
14
+ "license": "Apache-2.0",
15
+ "type": "module",
16
+ "main": "./dist/index.cjs",
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js",
23
+ "require": "./dist/index.cjs",
24
+ "default": "./dist/index.js"
25
+ },
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "LICENSE",
31
+ "README.md"
32
+ ],
33
+ "engines": {
34
+ "node": ">=20"
35
+ },
36
+ "sideEffects": false,
37
+ "scripts": {
38
+ "format": "prettier . --write",
39
+ "format:check": "prettier . --check",
40
+ "build": "npm run build:package && npm run build:docs",
41
+ "build:package": "tsdown",
42
+ "build:docs": "typedoc",
43
+ "build:example": "npm run build:package && node test/index.js",
44
+ "typecheck": "tsc --noEmit && tsc --noEmit --project test/tsconfig.json",
45
+ "test": "npm run build && npm run typecheck && npm run test:vitest && npm run test:runtimes && npm run test:e2e",
46
+ "test:vitest": "vitest run --config test/vitest.config.ts --coverage",
47
+ "test:runtimes": "npm run test:runtime:node && npm run test:runtime:bun",
48
+ "test:runtime:node": "node test/runtimes/run.mjs",
49
+ "test:runtime:bun": "bun test/runtimes/run.mjs",
50
+ "test:e2e": "playwright test --config test/playwright.config.ts",
51
+ "prepare": "husky"
52
+ },
53
+ "dependencies": {
54
+ "@sovereignbase/bytecodec": "^1.7.0",
55
+ "@sovereignbase/utils": "^2.0.0",
56
+ "esbuild": "^0.28.2",
57
+ "fs-extra": "^11.4.0",
58
+ "html-minifier-terser": "^7.2.0",
59
+ "lightningcss": "^1.33.0",
60
+ "terser": "^5.51.2"
61
+ },
62
+ "devDependencies": {
63
+ "@commitlint/cli": "^21.2.2",
64
+ "@commitlint/config-conventional": "^21.2.2",
65
+ "@playwright/test": "^1.62.1",
66
+ "@types/html-minifier-terser": "^7.0.2",
67
+ "@types/node": "^26.4.0",
68
+ "@vitest/coverage-v8": "^4.1.11",
69
+ "husky": "^9.1.7",
70
+ "playwright": "^1.62.1",
71
+ "prettier": "^3.9.6",
72
+ "tsdown": "^0.22.14",
73
+ "typedoc": "^0.28.20",
74
+ "typescript": "^5.9.3",
75
+ "vitest": "^4.1.11"
76
+ },
77
+ "repository": {
78
+ "type": "git",
79
+ "url": "git+https://github.com/sovereignbase/pwa.git"
80
+ },
81
+ "bugs": {
82
+ "url": "https://github.com/sovereignbase/pwa/issues"
83
+ },
84
+ "homepage": "https://sovereignbase.dev/pwa"
85
+ }