@swoff/cli 0.3.14 → 0.3.15
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/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/cli/help.js +3 -3
- package/dist/lib/cli/help.js.map +1 -1
- package/dist/lib/commands/clean.js +8 -17
- package/dist/lib/commands/clean.js.map +1 -1
- package/dist/lib/commands/generate.js +4 -3
- package/dist/lib/commands/generate.js.map +1 -1
- package/dist/lib/commands/init.js +233 -174
- package/dist/lib/commands/init.js.map +1 -1
- package/dist/lib/commands/validate.js.map +1 -1
- package/dist/lib/config/minimal-config.js +64 -0
- package/dist/lib/config/minimal-config.js.map +1 -0
- package/dist/lib/config/validator.js +18 -15
- package/dist/lib/config/validator.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-generator-build.js +11 -5
- package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
- package/dist/lib/generators/sw-sections/activate-handler.js +4 -1
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +8 -4
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/background-precache.js +126 -0
- package/dist/lib/generators/sw-sections/background-precache.js.map +1 -0
- package/dist/lib/generators/sw-sections/default-template.js +6 -2
- package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +2 -2
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/install-handler.js +8 -7
- package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/message-handler.js +9 -0
- package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/shared.js +2 -0
- package/dist/lib/generators/sw-sections/shared.js.map +1 -1
- package/dist/lib/shared/config-types.js +17 -16
- package/dist/lib/shared/config-types.js.map +1 -1
- package/dist/runtime/client-injector.js +15 -0
- package/dist/runtime/client-injector.js.map +1 -1
- package/package.json +9 -3
- package/dist/lib/commands/add.js +0 -62
- package/dist/lib/commands/add.js.map +0 -1
- package/dist/lib/commands/assets.js +0 -45
- package/dist/lib/commands/assets.js.map +0 -1
- package/dist/lib/commands/generate-assets.js +0 -44
- package/dist/lib/commands/generate-assets.js.map +0 -1
- package/dist/lib/commands/info.js +0 -183
- package/dist/lib/commands/info.js.map +0 -1
- package/dist/lib/generators/asset-generator/dependency-resolver.js +0 -85
- package/dist/lib/generators/asset-generator/dependency-resolver.js.map +0 -1
- package/dist/lib/generators/asset-generator/generate.js +0 -111
- package/dist/lib/generators/asset-generator/generate.js.map +0 -1
- package/dist/lib/generators/asset-generator/guide.js +0 -43
- package/dist/lib/generators/asset-generator/guide.js.map +0 -1
- package/dist/lib/generators/asset-generator/html-patcher.js +0 -65
- package/dist/lib/generators/asset-generator/html-patcher.js.map +0 -1
- package/dist/lib/generators/asset-generator/ico-encoder.js +0 -29
- package/dist/lib/generators/asset-generator/ico-encoder.js.map +0 -1
- package/dist/lib/generators/asset-generator/manifest-patcher.js +0 -23
- package/dist/lib/generators/asset-generator/manifest-patcher.js.map +0 -1
- package/dist/lib/generators/asset-generator/maskable.js +0 -15
- package/dist/lib/generators/asset-generator/maskable.js.map +0 -1
- package/dist/lib/generators/asset-generator/rasterize.js +0 -32
- package/dist/lib/generators/asset-generator/rasterize.js.map +0 -1
- package/dist/lib/generators/asset-generator/sizes.js +0 -25
- package/dist/lib/generators/asset-generator/sizes.js.map +0 -1
- package/dist/lib/generators/file-generators/auth-fetch.js +0 -151
- package/dist/lib/generators/file-generators/auth-fetch.js.map +0 -1
- package/dist/lib/generators/file-generators/auth-user.js +0 -13
- package/dist/lib/generators/file-generators/auth-user.js.map +0 -1
- package/dist/lib/generators/file-generators/connectivity-manager.js +0 -12
- package/dist/lib/generators/file-generators/connectivity-manager.js.map +0 -1
- package/dist/lib/generators/file-generators/fetch-state.js +0 -6
- package/dist/lib/generators/file-generators/fetch-state.js.map +0 -1
- package/dist/lib/generators/file-generators/generate-hooks.js +0 -44
- package/dist/lib/generators/file-generators/generate-hooks.js.map +0 -1
- package/dist/lib/generators/file-generators/indexeddb.js +0 -74
- package/dist/lib/generators/file-generators/indexeddb.js.map +0 -1
- package/dist/lib/generators/file-generators/manifest.js +0 -46
- package/dist/lib/generators/file-generators/manifest.js.map +0 -1
- package/dist/lib/generators/file-generators/mutation-reconcile.js +0 -57
- package/dist/lib/generators/file-generators/mutation-reconcile.js.map +0 -1
- package/dist/lib/generators/file-generators/notification-generator.js +0 -6
- package/dist/lib/generators/file-generators/notification-generator.js.map +0 -1
- package/dist/lib/generators/file-generators/quick-readme.js +0 -21
- package/dist/lib/generators/file-generators/quick-readme.js.map +0 -1
- package/dist/lib/generators/file-generators/reconcile.js +0 -50
- package/dist/lib/generators/file-generators/reconcile.js.map +0 -1
- package/dist/lib/generators/file-generators/storage-generator.js +0 -6
- package/dist/lib/generators/file-generators/storage-generator.js.map +0 -1
- package/dist/lib/generators/file-generators/storage-notify.js +0 -6
- package/dist/lib/generators/file-generators/storage-notify.js.map +0 -1
- package/dist/lib/generators/file-generators/store.js +0 -86
- package/dist/lib/generators/file-generators/store.js.map +0 -1
- package/dist/lib/generators/file-generators/sw-push.js +0 -67
- package/dist/lib/generators/file-generators/sw-push.js.map +0 -1
- package/dist/lib/generators/file-generators/sw-version-gen.js +0 -32
- package/dist/lib/generators/file-generators/sw-version-gen.js.map +0 -1
- package/dist/lib/generators/sw-sections/glob-matcher-code.js.map +0 -1
- package/dist/lib/utils/build-script.js +0 -35
- package/dist/lib/utils/build-script.js.map +0 -1
- package/dist/lib/utils/tty-status.js +0 -21
- package/dist/lib/utils/tty-status.js.map +0 -1
- package/dist/runtime/auth-user.js +0 -154
- package/dist/runtime/auth-user.js.map +0 -1
- package/dist/runtime/connectivity-manager.js +0 -83
- package/dist/runtime/connectivity-manager.js.map +0 -1
- package/dist/runtime/fetch-state.js +0 -42
- package/dist/runtime/fetch-state.js.map +0 -1
- package/dist/runtime/notification.js +0 -65
- package/dist/runtime/notification.js.map +0 -1
- package/dist/runtime/pwa-index.js +0 -11
- package/dist/runtime/pwa-index.js.map +0 -1
- package/dist/runtime/pwa-injector.js +0 -15
- package/dist/runtime/pwa-injector.js.map +0 -1
- package/dist/runtime/pwa-install.js +0 -83
- package/dist/runtime/pwa-install.js.map +0 -1
- package/dist/runtime/sw-version.js +0 -13
- package/dist/runtime/sw-version.js.map +0 -1
- package/dist/swoff-nkdhhmw8. +0 -18
- package/dist/swoff.js +0 -5
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generates store.js - IndexedDB CRUD operations.
|
|
3
|
-
*/
|
|
4
|
-
import { writeFile } from "./context.js";
|
|
5
|
-
export function generateStore(ctx) {
|
|
6
|
-
const ext = ctx.ext;
|
|
7
|
-
const ts = ext === "ts";
|
|
8
|
-
const T = (type) => (ts ? `: ${type}` : "");
|
|
9
|
-
const R = (type) => (ts ? `: ${type} ` : " ");
|
|
10
|
-
const PT = (type) => (ts ? `<${type}>` : "");
|
|
11
|
-
const AS = (type) => (ts ? ` as ${type}` : "");
|
|
12
|
-
const dbName = "app-db";
|
|
13
|
-
const code = `/**
|
|
14
|
-
* Swoff IndexedDB Store
|
|
15
|
-
* Generic CRUD operations for app's IndexedDB database.
|
|
16
|
-
*
|
|
17
|
-
* Usage:
|
|
18
|
-
* import { getRecord, putRecord, deleteRecord, openAppDB } from './swoff/store.${ext}';
|
|
19
|
-
*
|
|
20
|
-
* const record = await getRecord('todos', 'todo-123');
|
|
21
|
-
* await putRecord('todos', { id: 'todo-123', title: 'New task', $synced: false });
|
|
22
|
-
* await deleteRecord('todos', 'todo-123');
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
const DB_NAME = "${dbName}";
|
|
26
|
-
|
|
27
|
-
/** Open the app's IndexedDB database. Creates it if it doesn't exist. */
|
|
28
|
-
export function openAppDB()${R("Promise<IDBDatabase>")}{
|
|
29
|
-
return new Promise${PT("IDBDatabase")}((resolve, reject) => {
|
|
30
|
-
const request = indexedDB.open(DB_NAME);
|
|
31
|
-
request.onsuccess = (e) => resolve((e.target${AS("IDBOpenDBRequest")}).result);
|
|
32
|
-
request.onerror = (e) => reject((e.target${AS("IDBRequest")}).error);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Get a record by ID from an IndexedDB store. Returns undefined if not found. */
|
|
37
|
-
export async function getRecord(storeName${T("string")}, id${T("IDBValidKey")})${R("Promise<Record<string, unknown> | undefined>")}{
|
|
38
|
-
const db = await openAppDB();
|
|
39
|
-
return new Promise${PT("Record<string, unknown> | undefined")}((resolve, reject) => {
|
|
40
|
-
const tx = db.transaction(storeName, "readonly");
|
|
41
|
-
const store = tx.objectStore(storeName);
|
|
42
|
-
const request = store.get(id);
|
|
43
|
-
request.onsuccess = () => resolve((request${AS("IDBRequest<Record<string, unknown> | undefined>")}).result);
|
|
44
|
-
request.onerror = () => reject((request${AS("IDBRequest")}).error);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Store a record in an IndexedDB store (insert or update). Returns the record's key. */
|
|
49
|
-
export async function putRecord(storeName${T("string")}, record${T("Record<string, unknown>")})${R("Promise<IDBValidKey>")}{
|
|
50
|
-
const db = await openAppDB();
|
|
51
|
-
return new Promise${PT("IDBValidKey")}((resolve, reject) => {
|
|
52
|
-
const tx = db.transaction(storeName, "readwrite");
|
|
53
|
-
const store = tx.objectStore(storeName);
|
|
54
|
-
const request = store.put(record);
|
|
55
|
-
tx.oncomplete = () => resolve((request${AS("IDBRequest<IDBValidKey>")}).result);
|
|
56
|
-
tx.onerror = () => reject((tx${AS("IDBTransaction")}).error);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** Delete a record by ID from an IndexedDB store. */
|
|
61
|
-
export async function deleteRecord(storeName${T("string")}, id${T("IDBValidKey")})${R("Promise<void>")}{
|
|
62
|
-
const db = await openAppDB();
|
|
63
|
-
return new Promise${PT("void")}((resolve, reject) => {
|
|
64
|
-
const tx = db.transaction(storeName, "readwrite");
|
|
65
|
-
const store = tx.objectStore(storeName);
|
|
66
|
-
store.delete(id);
|
|
67
|
-
tx.oncomplete = () => resolve();
|
|
68
|
-
tx.onerror = () => reject((tx${AS("IDBTransaction")}).error);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** Get all records from an IndexedDB store. */
|
|
73
|
-
export async function getAllRecords(storeName${T("string")})${R("Promise<Record<string, unknown>[]>")}{
|
|
74
|
-
const db = await openAppDB();
|
|
75
|
-
return new Promise${PT("Record<string, unknown>[]")}((resolve, reject) => {
|
|
76
|
-
const tx = db.transaction(storeName, "readonly");
|
|
77
|
-
const store = tx.objectStore(storeName);
|
|
78
|
-
const request = store.getAll();
|
|
79
|
-
request.onsuccess = () => resolve((request${AS("IDBRequest<Record<string, unknown>[]>")}).result);
|
|
80
|
-
request.onerror = () => reject((request${AS("IDBRequest")}).error);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
`;
|
|
84
|
-
writeFile(ctx, `store.${ext}`, code);
|
|
85
|
-
}
|
|
86
|
-
//# sourceMappingURL=store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,aAAa,CAAC,GAAqB;IACjD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,QAAQ,CAAC;IAExB,MAAM,IAAI,GAAG;;;;;oFAKqE,GAAG;;;;;;;mBAOpE,MAAM;;;6BAGI,CAAC,CAAC,sBAAsB,CAAC;sBAChC,EAAE,CAAC,aAAa,CAAC;;kDAEW,EAAE,CAAC,kBAAkB,CAAC;+CACzB,EAAE,CAAC,YAAY,CAAC;;;;;2CAKpB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,8CAA8C,CAAC;;sBAE5G,EAAE,CAAC,qCAAqC,CAAC;;;;gDAIf,EAAE,CAAC,iDAAiD,CAAC;6CACxD,EAAE,CAAC,YAAY,CAAC;;;;;2CAKlB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,sBAAsB,CAAC;;sBAEpG,EAAE,CAAC,aAAa,CAAC;;;;4CAIK,EAAE,CAAC,yBAAyB,CAAC;mCACtC,EAAE,CAAC,gBAAgB,CAAC;;;;;8CAKT,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC;;sBAEhF,EAAE,CAAC,MAAM,CAAC;;;;;mCAKG,EAAE,CAAC,gBAAgB,CAAC;;;;;+CAKR,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,oCAAoC,CAAC;;sBAE/E,EAAE,CAAC,2BAA2B,CAAC;;;;gDAIL,EAAE,CAAC,uCAAuC,CAAC;6CAC9C,EAAE,CAAC,YAAY,CAAC;;;CAG5D,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generates SW push notification event handlers.
|
|
3
|
-
* Appended to the SW template via the // [[PUSH_HANDLERS]] placeholder.
|
|
4
|
-
*/
|
|
5
|
-
export function generateSwPushHandlers() {
|
|
6
|
-
return `
|
|
7
|
-
// --- Push Notification Handlers ---
|
|
8
|
-
|
|
9
|
-
self.addEventListener("push", (event) => {
|
|
10
|
-
let data;
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
data = event.data ? event.data.json() : {};
|
|
14
|
-
} catch {
|
|
15
|
-
data = { title: "New Update", body: event.data?.text() || "" };
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const options = {
|
|
19
|
-
body: data.body || "",
|
|
20
|
-
icon: data.icon || "/icon-192.png",
|
|
21
|
-
badge: data.badge || "",
|
|
22
|
-
image: data.image || undefined,
|
|
23
|
-
vibrate: data.vibrate || [200, 100, 200],
|
|
24
|
-
data: {
|
|
25
|
-
url: data.url || "/",
|
|
26
|
-
...(data.data || {}),
|
|
27
|
-
},
|
|
28
|
-
actions: data.actions || [],
|
|
29
|
-
tag: data.tag || undefined,
|
|
30
|
-
requireInteraction: data.requireInteraction || false,
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
event.waitUntil(self.registration.showNotification(data.title || "Update", options));
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
self.addEventListener("notificationclick", (event) => {
|
|
37
|
-
event.notification.close();
|
|
38
|
-
|
|
39
|
-
const url = event.notification.data?.url || "/";
|
|
40
|
-
const action = event.action;
|
|
41
|
-
|
|
42
|
-
event.waitUntil(
|
|
43
|
-
(async () => {
|
|
44
|
-
if (action) {
|
|
45
|
-
// Handle action clicks (e.g., "reply", "dismiss")
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const clients = await self.clients.matchAll({ type: "window" });
|
|
49
|
-
|
|
50
|
-
for (const client of clients) {
|
|
51
|
-
const clientUrl = new URL(client.url);
|
|
52
|
-
const targetUrl = new URL(url, self.location.origin);
|
|
53
|
-
|
|
54
|
-
if (clientUrl.pathname === targetUrl.pathname && "focus" in client) {
|
|
55
|
-
return client.focus();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (clients.openWindow) {
|
|
60
|
-
return clients.openWindow(url);
|
|
61
|
-
}
|
|
62
|
-
})(),
|
|
63
|
-
);
|
|
64
|
-
});
|
|
65
|
-
`;
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=sw-push.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sw-push.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/sw-push.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DR,CAAC;AACF,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "fs";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { writeFile } from "./context.js";
|
|
4
|
-
import { generateSwVersionCode } from "../../../runtime/sw-version.js";
|
|
5
|
-
export function generateSwVersion(ctx) {
|
|
6
|
-
const v = ctx.config.features.serviceWorker.version;
|
|
7
|
-
let version;
|
|
8
|
-
if (v === "hash") {
|
|
9
|
-
version = "0.0.0";
|
|
10
|
-
}
|
|
11
|
-
else if (v === "package") {
|
|
12
|
-
const pkgPath = join(ctx.projectRoot, "package.json");
|
|
13
|
-
if (existsSync(pkgPath)) {
|
|
14
|
-
try {
|
|
15
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
16
|
-
version = pkg.version || "1.0.0";
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
version = "1.0.0";
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
version = "1.0.0";
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
// "manual" — start with a default; user edits this file directly
|
|
28
|
-
version = "1.0.0";
|
|
29
|
-
}
|
|
30
|
-
writeFile(ctx, `sw/version.${ctx.ext}`, generateSwVersionCode({ ts: ctx.ext === "ts", ext: ctx.ext, version }));
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=sw-version-gen.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sw-version-gen.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/sw-version-gen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAEvE,MAAM,UAAU,iBAAiB,CAAC,GAAqB;IACrD,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;IAEpD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;QACjB,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC;SAAM,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QACtD,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;gBACtD,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,OAAO,CAAC;YACpB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,OAAO,CAAC;QACpB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,iEAAiE;QACjE,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC;IAED,SAAS,CACP,GAAG,EACH,cAAc,GAAG,CAAC,GAAG,EAAE,EACvB,qBAAqB,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CACvE,CAAC;AACJ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"glob-matcher-code.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/glob-matcher-code.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI;IACrC,oCAAoC;IACpC,IAAI;IACJ,gCAAgC;IAChC,0DAA0D;IAC1D,KAAK;IACL,IAAI;IACJ,+BAA+B;IAC/B,qDAAqD;IACrD,wBAAwB;IACxB,wCAAwC;IACxC,4CAA4C;IAC5C,6BAA6B;IAC7B,wCAAwC;IACxC,6CAA6C;IAC7C,gBAAgB;IAChB,gIAAgI;IAChI,mBAAmB;IACnB,WAAW;IACX,mCAAmC;IACnC,OAAO;IACP,eAAe;IACf,KAAK;IACL,IAAI;IACJ,uCAAuC;IACvC,+EAA+E;IAC/E,qDAAqD;IACrD,gDAAgD;IAChD,0BAA0B;IAC1B,qDAAqD;IACrD,6BAA6B;IAC7B,4BAA4B;IAC5B,mDAAmD;IACnD,kCAAkC;IAClC,yBAAyB;IACzB,kDAAkD;IAClD,0FAA0F;IAC1F,6FAA6F;IAC7F,4DAA4D;IAC5D,WAAW;IACX,yCAAyC;IACzC,sBAAsB;IACtB,eAAe;IACf,mBAAmB;IACnB,SAAS;IACT,yFAAyF;IACzF,qFAAqF;IACrF,mDAAmD;IACnD,aAAa;IACb,cAAc;IACd,OAAO;IACP,uDAAuD;IACvD,KAAK;IACL,IAAI,CAAC"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utilities for managing the SW generator step in package.json build scripts.
|
|
3
|
-
*/
|
|
4
|
-
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
5
|
-
import { join } from "path";
|
|
6
|
-
const SW_GENERATOR_STEP = " && node swoff/sw/generator.js";
|
|
7
|
-
export function appendGeneratorToBuildScript(projectRoot) {
|
|
8
|
-
const pkgPath = join(projectRoot, "package.json");
|
|
9
|
-
if (!existsSync(pkgPath))
|
|
10
|
-
return false;
|
|
11
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
12
|
-
const build = pkg.scripts?.build;
|
|
13
|
-
if (!build || typeof build !== "string")
|
|
14
|
-
return false;
|
|
15
|
-
if (build.includes(SW_GENERATOR_STEP))
|
|
16
|
-
return false;
|
|
17
|
-
pkg.scripts.build = build + SW_GENERATOR_STEP;
|
|
18
|
-
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
export function removeGeneratorFromBuildScript(projectRoot) {
|
|
22
|
-
const pkgPath = join(projectRoot, "package.json");
|
|
23
|
-
if (!existsSync(pkgPath))
|
|
24
|
-
return false;
|
|
25
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
26
|
-
const build = pkg.scripts?.build;
|
|
27
|
-
if (!build || typeof build !== "string")
|
|
28
|
-
return false;
|
|
29
|
-
if (!build.includes(SW_GENERATOR_STEP))
|
|
30
|
-
return false;
|
|
31
|
-
pkg.scripts.build = build.replace(SW_GENERATOR_STEP, "");
|
|
32
|
-
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=build-script.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-script.js","sourceRoot":"","sources":["../../../src/lib/utils/build-script.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,iBAAiB,GAAG,gCAAgC,CAAC;AAE3D,MAAM,UAAU,4BAA4B,CAAC,WAAmB;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC;IAEjC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAAE,OAAO,KAAK,CAAC;IAEpD,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,GAAG,iBAAiB,CAAC;IAC9C,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,WAAmB;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC;IAEjC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAAE,OAAO,KAAK,CAAC;IAErD,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;IACzD,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export function statusLine(msg) {
|
|
2
|
-
if (process.stdout.isTTY) {
|
|
3
|
-
const cols = process.stdout.columns || 80;
|
|
4
|
-
process.stdout.write(`\r${" ".repeat(cols - 1)}\r ${msg}`);
|
|
5
|
-
}
|
|
6
|
-
else {
|
|
7
|
-
console.log(` ${msg}`);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
export function clearStatusLine() {
|
|
11
|
-
if (process.stdout.isTTY) {
|
|
12
|
-
const cols = process.stdout.columns || 80;
|
|
13
|
-
process.stdout.write(`\r${" ".repeat(cols - 1)}\r`);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
export function ttyStatus(onStatus) {
|
|
17
|
-
if (onStatus)
|
|
18
|
-
return onStatus;
|
|
19
|
-
return statusLine;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=tty-status.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tty-status.js","sourceRoot":"","sources":["../../../src/lib/utils/tty-status.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgC;IACxD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { T, R, PT, AS } from "./utils.js";
|
|
2
|
-
export function generateAuthUserCode(ctx, refreshPath, userEndpoint, authType) {
|
|
3
|
-
const { ext, ts } = ctx;
|
|
4
|
-
const cookieAuth = authType === "cookie";
|
|
5
|
-
const authTypeName = cookieAuth ? "cookie" : "bearer";
|
|
6
|
-
const refreshDocs = cookieAuth
|
|
7
|
-
? ` *
|
|
8
|
-
* Cookie auth: credentials ("include") are automatically sent with the request.
|
|
9
|
-
* The browser attaches the session cookie — no token management needed.
|
|
10
|
-
* Change method, URL, headers, or body below if your server expects something different.
|
|
11
|
-
* Example: if your refresh endpoint expects a specific content-type, add:
|
|
12
|
-
* headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
13
|
-
* Example: if your endpoint uses PUT instead of POST:
|
|
14
|
-
* method: "PUT",`
|
|
15
|
-
: ` *
|
|
16
|
-
* Bearer auth: the optional \`token\` parameter is passed by auth/store.ts when the user
|
|
17
|
-
* has an existing session. The generated template adds "Authorization: Bearer <token>".
|
|
18
|
-
* If your refresh endpoint doesn't need the token (e.g., uses a refresh token cookie),
|
|
19
|
-
* simply remove the \`token\` parameter and the header logic below.
|
|
20
|
-
* To send a refresh token in the body instead:
|
|
21
|
-
* body: JSON.stringify({ refreshToken: "..." }),
|
|
22
|
-
* To change the content type:
|
|
23
|
-
* headers: { "Content-Type": "application/x-www-form-urlencoded" },`;
|
|
24
|
-
const userDocs = cookieAuth
|
|
25
|
-
? ` *
|
|
26
|
-
* Cookie auth: credentials ("include") sends the session cookie automatically.
|
|
27
|
-
* Edit the URL, method, or headers below if your user endpoint differs.
|
|
28
|
-
* Example: if your server uses /api/v1/me with a different method:
|
|
29
|
-
* const response = await fetch(API_BASE + "/api/v1/me", {
|
|
30
|
-
* method: "GET",
|
|
31
|
-
* credentials: "include",
|
|
32
|
-
* });`
|
|
33
|
-
: ` *
|
|
34
|
-
* Bearer auth: add the Authorization header using the user's token.
|
|
35
|
-
* Get the token from auth/store.ts:
|
|
36
|
-
* import { getAuth } from "./store.${ext}";
|
|
37
|
-
* const auth = await getAuth();
|
|
38
|
-
* const response = await fetch(API_BASE + "${userEndpoint}", {
|
|
39
|
-
* headers: { "Authorization": \`Bearer \${auth?.token}\` },
|
|
40
|
-
* });
|
|
41
|
-
* If your endpoint uses a different method or body, edit accordingly below.`;
|
|
42
|
-
return `/**
|
|
43
|
-
* Auth User — refresh session and fetch current user.
|
|
44
|
-
*
|
|
45
|
-
* This file is YOUR control panel for auth HTTP calls. swoff generates sensible
|
|
46
|
-
* defaults based on your swoff.config.json auth type (cookie/bearer), then you
|
|
47
|
-
* edit the functions below to match your server exactly.
|
|
48
|
-
*
|
|
49
|
-
* Both functions are imported by swoff's auth store (auth/store.${ext}) so your
|
|
50
|
-
* edits flow through to session refresh, 401 retry, and user caching.
|
|
51
|
-
*
|
|
52
|
-
* Usage:
|
|
53
|
-
* import { refreshSession, fetchCurrentUser, cacheUser, getCachedUser, clearCachedUser } from "./auth/user.${ext}";
|
|
54
|
-
*
|
|
55
|
-
* // Refresh the session (called automatically by the auth store)
|
|
56
|
-
* const response = await refreshSession();
|
|
57
|
-
* const data = await response.json();
|
|
58
|
-
*
|
|
59
|
-
* // Fetch and cache the current user
|
|
60
|
-
* const user = await fetchCurrentUser();
|
|
61
|
-
*
|
|
62
|
-
* // Get cached user (offline-capable)
|
|
63
|
-
* const cached = await getCachedUser();
|
|
64
|
-
*
|
|
65
|
-
* // Clear on logout
|
|
66
|
-
* await clearCachedUser();
|
|
67
|
-
*/
|
|
68
|
-
|
|
69
|
-
import { API_BASE } from "../config.${ext}";
|
|
70
|
-
|
|
71
|
-
import { openDB } from "../db.${ext}";
|
|
72
|
-
|
|
73
|
-
const DB_NAME = "swoff-auth-user";
|
|
74
|
-
const STORE_NAME = "current-user";
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Refresh the auth session.
|
|
78
|
-
*
|
|
79
|
-
* Called automatically by auth/store.{{ext}} when the access token expires
|
|
80
|
-
* (ensureValidAuth) or to restore a session after page reload (tryRestoreSession).
|
|
81
|
-
*
|
|
82
|
-
* ${authTypeName} defaults:${refreshDocs}
|
|
83
|
-
*
|
|
84
|
-
* ${cookieAuth ? "" : "@param token - Bearer token from the existing session (only passed for bearer auth)."}
|
|
85
|
-
* @returns A fetch Response. The auth store reads response.json() to extract
|
|
86
|
-
* { token, expiresAt } and merges them with cached user data.
|
|
87
|
-
*/
|
|
88
|
-
export async function refreshSession(${cookieAuth ? "" : "token" + T(ts, "string")})${R(ts, "Promise<Response>")}{
|
|
89
|
-
${cookieAuth
|
|
90
|
-
? `return fetch(API_BASE + "${refreshPath}", {
|
|
91
|
-
method: "POST",
|
|
92
|
-
credentials: "include" as RequestCredentials,
|
|
93
|
-
});`
|
|
94
|
-
: `const headers${T(ts, "Record<string, string>")} = { "Content-Type": "application/json" };
|
|
95
|
-
if (token) headers["Authorization"] = \`Bearer \${token}\`;
|
|
96
|
-
return fetch(API_BASE + "${refreshPath}", {
|
|
97
|
-
method: "POST",
|
|
98
|
-
headers,
|
|
99
|
-
});`}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**${userDocs}
|
|
103
|
-
*/
|
|
104
|
-
export async function fetchCurrentUser()${R(ts, "Promise<Record<string, unknown>>")}{
|
|
105
|
-
${cookieAuth
|
|
106
|
-
? `const response = await fetch(API_BASE + "${userEndpoint}", {
|
|
107
|
-
credentials: "include" as RequestCredentials,
|
|
108
|
-
});`
|
|
109
|
-
: `const response = await fetch(API_BASE + "${userEndpoint}");`}
|
|
110
|
-
if (!response.ok) throw new Error("Failed to fetch user");
|
|
111
|
-
|
|
112
|
-
const user = await response.json();
|
|
113
|
-
await cacheUser(user);
|
|
114
|
-
return user;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Persist user data to IndexedDB for offline access. */
|
|
118
|
-
export async function cacheUser(user${T(ts, "Record<string, unknown>")})${R(ts, "Promise<void>")}{
|
|
119
|
-
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
120
|
-
return new Promise<void>((resolve, reject) => {
|
|
121
|
-
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
122
|
-
const store = tx.objectStore(STORE_NAME);
|
|
123
|
-
store.put({ key: "user", value: user });
|
|
124
|
-
tx.oncomplete = () => resolve();
|
|
125
|
-
tx.onerror = () => reject(tx.error);
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** Load user data from IndexedDB cache (no token — only user object survives refresh). */
|
|
130
|
-
export async function getCachedUser()${R(ts, "Promise<Record<string, unknown> | null>")}{
|
|
131
|
-
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
132
|
-
return new Promise${PT(ts, "Record<string, unknown> | null")}((resolve, reject) => {
|
|
133
|
-
const tx = db.transaction(STORE_NAME, "readonly");
|
|
134
|
-
const store = tx.objectStore(STORE_NAME);
|
|
135
|
-
const request = store.get("user");
|
|
136
|
-
request.onsuccess = () => resolve((request${AS(ts, "IDBRequest")}).result?.value ?? null);
|
|
137
|
-
request.onerror = () => reject((request${AS(ts, "IDBRequest")}).error);
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/** Remove user data from IndexedDB cache. Call on logout. */
|
|
142
|
-
export async function clearCachedUser()${R(ts, "Promise<void>")}{
|
|
143
|
-
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
144
|
-
return new Promise${PT(ts, "void")}((resolve, reject) => {
|
|
145
|
-
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
146
|
-
const store = tx.objectStore(STORE_NAME);
|
|
147
|
-
store.delete("user");
|
|
148
|
-
tx.oncomplete = () => resolve();
|
|
149
|
-
tx.onerror = () => reject((tx${AS(ts, "IDBTransaction")}).error);
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
`;
|
|
153
|
-
}
|
|
154
|
-
//# sourceMappingURL=auth-user.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-user.js","sourceRoot":"","sources":["../../src/runtime/auth-user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,UAAU,oBAAoB,CAClC,GAAmB,EACnB,WAAmB,EACnB,YAAoB,EACpB,QAAgB;IAEhB,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,UAAU,GAAG,QAAQ,KAAK,QAAQ,CAAC;IACzC,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEtD,MAAM,WAAW,GAAG,UAAU;QAC5B,CAAC,CAAC;;;;;;;sBAOgB;QAClB,CAAC,CAAC;;;;;;;;yEAQmE,CAAC;IAExE,MAAM,QAAQ,GAAG,UAAU;QACzB,CAAC,CAAC;;;;;;;WAOK;QACP,CAAC,CAAC;;;0CAGoC,GAAG;;kDAEK,YAAY;;;+EAGiB,CAAC;IAE9E,OAAO;;;;;;;mEAO0D,GAAG;;;;gHAI0C,GAAG;;;;;;;;;;;;;;;;sCAgB7E,GAAG;;gCAET,GAAG;;;;;;;;;;;KAW9B,YAAY,aAAa,WAAW;;KAEpC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,sFAAsF;;;;uCAItE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,GAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,mBAAmB,CAAC;IAC1G,UAAU;QACV,CAAC,CAAC,4BAA4B,WAAW;;;MAGvC;QACF,CAAC,CAAC,gBAAgB,CAAC,CAAC,EAAE,EAAE,wBAAwB,CAAC;;6BAExB,WAAW;;;MAGlC;;;KAGD,QAAQ;;0CAE6B,CAAC,CAAC,EAAE,EAAE,kCAAkC,CAAC;IAC/E,UAAU;QACV,CAAC,CAAC,4CAA4C,YAAY;;MAExD;QACF,CAAC,CAAC,4CAA4C,YAAY,KAAK;;;;;;;;;sCAS7B,CAAC,CAAC,EAAE,EAAE,yBAAyB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;uCAYzD,CAAC,CAAC,EAAE,EAAE,yCAAyC,CAAC;;sBAEjE,EAAE,CAAC,EAAE,EAAE,gCAAgC,CAAC;;;;gDAId,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC;6CACvB,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC;;;;;yCAKxB,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;sBAEzC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;mCAKD,EAAE,CAAC,EAAE,EAAE,gBAAgB,CAAC;;;CAG1D,CAAC;AACF,CAAC"}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { T } from "./utils.js";
|
|
2
|
-
export function generateConnectivityManagerCode(ctx) {
|
|
3
|
-
const { ts } = ctx;
|
|
4
|
-
return `/**
|
|
5
|
-
**/
|
|
6
|
-
export const CONNECTIVITY_EVENT = 'app-connectivity-change'
|
|
7
|
-
|
|
8
|
-
let heartbeatIntervalId${T(ts, "ReturnType<typeof setInterval> | null")} = null
|
|
9
|
-
const HEARTBEAT_DELAY = 30000
|
|
10
|
-
|
|
11
|
-
let _currentOnlineStatus = typeof navigator !== 'undefined' ? navigator.onLine : true
|
|
12
|
-
|
|
13
|
-
export function getCurrentOnlineStatus(): boolean {
|
|
14
|
-
return _currentOnlineStatus
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function createTimeoutSignal(ms) {
|
|
18
|
-
if (typeof AbortSignal.timeout === "function") return AbortSignal.timeout(ms);
|
|
19
|
-
var ctrl = new AbortController();
|
|
20
|
-
setTimeout(function() { ctrl.abort(); }, ms);
|
|
21
|
-
return ctrl.signal;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function verifyAndNotify() {
|
|
25
|
-
if (typeof window === 'undefined') return false
|
|
26
|
-
|
|
27
|
-
if (!navigator.onLine) {
|
|
28
|
-
dispatchState(false)
|
|
29
|
-
return false
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
await fetch(\`/\${Date.now()}?hb=1\`, {
|
|
34
|
-
method: 'HEAD',
|
|
35
|
-
cache: 'no-cache',
|
|
36
|
-
signal: createTimeoutSignal(5000),
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
if (navigator.serviceWorker.controller) {
|
|
40
|
-
navigator.serviceWorker.controller.postMessage({ type: 'ONLINE' })
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
dispatchState(true)
|
|
44
|
-
return true
|
|
45
|
-
} catch (error) {
|
|
46
|
-
if (navigator.serviceWorker.controller) {
|
|
47
|
-
navigator.serviceWorker.controller.postMessage({ type: 'OFFLINE' })
|
|
48
|
-
}
|
|
49
|
-
dispatchState(false)
|
|
50
|
-
return false
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function dispatchState(isTrulyOnline: boolean) {
|
|
55
|
-
_currentOnlineStatus = isTrulyOnline
|
|
56
|
-
const event = new CustomEvent(CONNECTIVITY_EVENT, {
|
|
57
|
-
detail: { online: isTrulyOnline },
|
|
58
|
-
})
|
|
59
|
-
window.dispatchEvent(event)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function startHeartbeat() {
|
|
63
|
-
if (heartbeatIntervalId) return
|
|
64
|
-
heartbeatIntervalId = setInterval(async () => {
|
|
65
|
-
if (document.hidden) return
|
|
66
|
-
await verifyAndNotify()
|
|
67
|
-
}, HEARTBEAT_DELAY)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function stopHeartbeat() {
|
|
71
|
-
if (!heartbeatIntervalId) return
|
|
72
|
-
clearInterval(heartbeatIntervalId)
|
|
73
|
-
heartbeatIntervalId = null
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export async function forceRetry() {
|
|
77
|
-
stopHeartbeat()
|
|
78
|
-
await verifyAndNotify()
|
|
79
|
-
startHeartbeat()
|
|
80
|
-
}
|
|
81
|
-
`;
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=connectivity-manager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connectivity-manager.js","sourceRoot":"","sources":["../../src/runtime/connectivity-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAE/B,MAAM,UAAU,+BAA+B,CAAC,GAAmB;IACjE,MAAM,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACnB,OAAO;;;;yBAIgB,CAAC,CAAC,EAAE,EAAE,uCAAuC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyEtE,CAAC;AACF,CAAC"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { R } from "./utils.js";
|
|
2
|
-
export function generateFetchStateCode(ctx) {
|
|
3
|
-
const { ext, ts } = ctx;
|
|
4
|
-
return `/**
|
|
5
|
-
* Swoff Fetch State
|
|
6
|
-
* Global in-flight fetch counter. Incremented by fetchWithCache and used by
|
|
7
|
-
* useIsFetching for a reactive global loading indicator.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* import { incrementFetchCount, decrementFetchCount, getFetchCount } from './swoff/fetch-state.${ext}';
|
|
11
|
-
*
|
|
12
|
-
* // Manual tracking (if you bypass fetchWithCache):
|
|
13
|
-
* incrementFetchCount();
|
|
14
|
-
* // ... fetch ...
|
|
15
|
-
* decrementFetchCount();
|
|
16
|
-
*
|
|
17
|
-
* Custom event:
|
|
18
|
-
* fetch-count-changed — dispatched on every increment/decrement
|
|
19
|
-
* detail: { count: number }
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
let _fetchCount = 0;
|
|
23
|
-
|
|
24
|
-
/** Increment the global fetch counter. Dispatches fetch-count-changed. */
|
|
25
|
-
export function incrementFetchCount()${R(ts, "void")}{
|
|
26
|
-
_fetchCount++;
|
|
27
|
-
window.dispatchEvent(new CustomEvent("fetch-count-changed", { detail: { count: _fetchCount } }));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Decrement the global fetch counter. Dispatches fetch-count-changed. Never goes below 0. */
|
|
31
|
-
export function decrementFetchCount()${R(ts, "void")}{
|
|
32
|
-
_fetchCount = Math.max(0, _fetchCount - 1);
|
|
33
|
-
window.dispatchEvent(new CustomEvent("fetch-count-changed", { detail: { count: _fetchCount } }));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Synchronously get the current fetch count. */
|
|
37
|
-
export function getFetchCount()${R(ts, "number")}{
|
|
38
|
-
return _fetchCount;
|
|
39
|
-
}
|
|
40
|
-
`;
|
|
41
|
-
}
|
|
42
|
-
//# sourceMappingURL=fetch-state.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-state.js","sourceRoot":"","sources":["../../src/runtime/fetch-state.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAE/B,MAAM,UAAU,sBAAsB,CAAC,GAAmB;IACxD,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,OAAO;;;;;;oGAM2F,GAAG;;;;;;;;;;;;;;;uCAehE,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;;uCAMb,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;;iCAMnB,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC;;;CAG/C,CAAC;AACF,CAAC"}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { T, R } from "./utils.js";
|
|
2
|
-
export function generateNotificationCode(ctx) {
|
|
3
|
-
const { ext, ts } = ctx;
|
|
4
|
-
return `/**
|
|
5
|
-
* Swoff Notification
|
|
6
|
-
* Dispatches \`swoff:notification\` custom events so your app can
|
|
7
|
-
* show toast/alert UI for offline-first events (fetch failures,
|
|
8
|
-
* storage quota warnings, background sync errors, etc.).
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* import { checkStorage } from "./swoff/notification.${ext}";
|
|
12
|
-
* const { usage, quota, percentUsed } = await checkStorage();
|
|
13
|
-
*
|
|
14
|
-
* Window events:
|
|
15
|
-
* swoff:notification — dispatched by the service worker or by checkStorage()
|
|
16
|
-
* detail: { level: "error"|"warn"|"info", code: string, message: string }
|
|
17
|
-
*
|
|
18
|
-
* ── Placeholder listener ────────────────────────────────
|
|
19
|
-
* Add a listener in your app entry point and replace the body
|
|
20
|
-
* with your own toast library (e.g. react-hot-toast, vue-toastification):
|
|
21
|
-
*
|
|
22
|
-
* window.addEventListener("swoff:notification", (event) => {
|
|
23
|
-
* const { level, code, message } = event.detail;
|
|
24
|
-
* // console.log(\`[swoff:\${level}] \${code}: \${message}\`);
|
|
25
|
-
* // alert(\`\${code}: \${message}\`);
|
|
26
|
-
* });
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/** Get raw storage estimate without dispatching events. Reuse in your own UI. */
|
|
30
|
-
export async function getStorageEstimate()${R(ts, "Promise<{ usage: number; quota: number; percentUsed: number }>")}{
|
|
31
|
-
if (!navigator.storage?.estimate) {
|
|
32
|
-
return { usage: 0, quota: 0, percentUsed: 0 };
|
|
33
|
-
}
|
|
34
|
-
const { usage = 0, quota = 0 } = await navigator.storage.estimate();
|
|
35
|
-
const percentUsed = quota > 0 ? Math.round((usage / quota) * 100) : 0;
|
|
36
|
-
return { usage, quota, percentUsed };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Check available storage and dispatch a warning if >80% used. */
|
|
40
|
-
export async function checkStorage()${R(ts, "Promise<{ usage: number; quota: number; percentUsed: number }>")}{
|
|
41
|
-
const result = await getStorageEstimate();
|
|
42
|
-
if (result.percentUsed > 80) {
|
|
43
|
-
window.dispatchEvent(
|
|
44
|
-
new CustomEvent("swoff:notification", {
|
|
45
|
-
detail: {
|
|
46
|
-
level: "warn",
|
|
47
|
-
code: "STORAGE_QUOTA_HIGH",
|
|
48
|
-
message: \`Storage at \${result.percentUsed}% capacity (\${formatBytes(result.usage)} / \${formatBytes(result.quota)})\`,
|
|
49
|
-
},
|
|
50
|
-
}),
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
return result;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Format bytes to a human-readable string (e.g. "1.5 MB"). */
|
|
57
|
-
export function formatBytes(bytes${T(ts, "number")})${R(ts, "string")}{
|
|
58
|
-
if (bytes === 0) return "0 B";
|
|
59
|
-
const units = ["B", "KB", "MB", "GB"];
|
|
60
|
-
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
61
|
-
return \`\${(bytes / Math.pow(1024, i)).toFixed(1)} \${units[i]}\`;
|
|
62
|
-
}
|
|
63
|
-
`;
|
|
64
|
-
}
|
|
65
|
-
//# sourceMappingURL=notification.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notification.js","sourceRoot":"","sources":["../../src/runtime/notification.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,wBAAwB,CAAC,GAAmB;IAC1D,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,OAAO;;;;;;;0DAOiD,GAAG;;;;;;;;;;;;;;;;;;;4CAmBjB,CAAC,CAAC,EAAE,EAAE,gEAAgE,CAAC;;;;;;;;;;sCAU7E,CAAC,CAAC,EAAE,EAAE,gEAAgE,CAAC;;;;;;;;;;;;;;;;;mCAiB1E,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC;;;;;;CAMpE,CAAC;AACF,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export function generatePwaIndexCode(ctx) {
|
|
2
|
-
const { ext } = ctx;
|
|
3
|
-
return `/**
|
|
4
|
-
* Swoff PWA
|
|
5
|
-
* Re-exports from PWA sub-modules for convenience imports.
|
|
6
|
-
*/
|
|
7
|
-
export { setupPwaInstall } from "./injector.${ext}";
|
|
8
|
-
export { isInstallable, promptInstall } from "./prompt.${ext}";
|
|
9
|
-
`;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=pwa-index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pwa-index.js","sourceRoot":"","sources":["../../src/runtime/pwa-index.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAAC,GAAmB;IACtD,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IAEpB,OAAO;;;;8CAIqC,GAAG;yDACQ,GAAG;CAC3D,CAAC;AACF,CAAC"}
|