Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f107b6876 | |||
| 4a8cd4b4b7 | |||
| 54d2cd1eb7 | |||
| 94eb289081 | |||
| e022ffc2ba | |||
| 25e92f4351 | |||
| b508cbe927 | |||
| 4cbc37c888 | |||
| 16f759c2b9 | |||
| f8fee04751 | |||
| 9406cfa0e2 | |||
| 1f310ef8f1 | |||
| 9cd10118e3 | |||
| 6308e0126d | |||
| e1310269fe | |||
| 1aadc2da21 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@api.global/typedserver",
|
||||
"version": "7.8.2",
|
||||
"version": "7.8.10",
|
||||
"description": "A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
@@ -58,7 +58,7 @@
|
||||
],
|
||||
"homepage": "https://code.foss.global/api.global/typedserver",
|
||||
"dependencies": {
|
||||
"@api.global/typedrequest": "^3.1.11",
|
||||
"@api.global/typedrequest": "^3.2.2",
|
||||
"@api.global/typedrequest-interfaces": "^3.0.19",
|
||||
"@api.global/typedsocket": "^4.1.0",
|
||||
"@cloudflare/workers-types": "^4.20251202.0",
|
||||
@@ -87,7 +87,7 @@
|
||||
"@push.rocks/smartstream": "^3.2.5",
|
||||
"@push.rocks/smarttime": "^4.1.1",
|
||||
"@push.rocks/smartwatch": "^5.0.0",
|
||||
"@push.rocks/taskbuffer": "^3.4.0",
|
||||
"@push.rocks/taskbuffer": "^3.5.0",
|
||||
"@push.rocks/webrequest": "^4.0.1",
|
||||
"@push.rocks/webstore": "^2.0.20",
|
||||
"@tsclass/tsclass": "^9.3.0",
|
||||
|
||||
42
pnpm-lock.yaml
generated
42
pnpm-lock.yaml
generated
@@ -9,8 +9,8 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@api.global/typedrequest':
|
||||
specifier: ^3.1.11
|
||||
version: 3.1.11
|
||||
specifier: ^3.2.2
|
||||
version: 3.2.2
|
||||
'@api.global/typedrequest-interfaces':
|
||||
specifier: ^3.0.19
|
||||
version: 3.0.19
|
||||
@@ -96,8 +96,8 @@ importers:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
'@push.rocks/taskbuffer':
|
||||
specifier: ^3.4.0
|
||||
version: 3.4.0
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0
|
||||
'@push.rocks/webrequest':
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
@@ -135,8 +135,8 @@ packages:
|
||||
'@api.global/typedrequest-interfaces@3.0.19':
|
||||
resolution: {integrity: sha512-uuHUXJeOy/inWSDrwD0Cwax2rovpxYllDhM2RWh+6mVpQuNmZ3uw6IVg6dA2G1rOe24Ebs+Y9SzEogo+jYN7vw==}
|
||||
|
||||
'@api.global/typedrequest@3.1.11':
|
||||
resolution: {integrity: sha512-j8EO3na0WMw8pFkAfEaEui2a4TaAL1G/dv1CYl8LEPXckSKkl1BCAS1kFOW2xuI9pwZkmSqlo3xpQ3KmkmHaGQ==}
|
||||
'@api.global/typedrequest@3.2.2':
|
||||
resolution: {integrity: sha512-tUmpq+JRcrj8mjb44zLfcWDnArKqqRxPra5oZo4Ghp0P/wf2MhEthZcaD9iz8goJ6PnvBrbmrIz94I7VrfLIcA==}
|
||||
|
||||
'@api.global/typedserver@3.0.80':
|
||||
resolution: {integrity: sha512-dcp0oXsjBL+XdFg1wUUP08uJQid5bQ0Yv3V3Y3lnI2QCbat0FU+Tsb0TZRnZ4+P150Vj/ITBqJUgDzFsF34grA==}
|
||||
@@ -1256,8 +1256,8 @@ packages:
|
||||
'@push.rocks/smartyaml@3.0.4':
|
||||
resolution: {integrity: sha512-1JRt+hnoc2zHw3AW+vXKlCdSVwqOmY/01fu+2HBviS0UDjoZCa+/rp6E3GaQb5lEEafKi8ENbffAfjXXp3N2xQ==}
|
||||
|
||||
'@push.rocks/taskbuffer@3.4.0':
|
||||
resolution: {integrity: sha512-Rvwr1CzYztB9PMboojRzVSq3xGp8288kvtvWx4Mg3rvps913znMja1UOjNn52ivOxu3dHUNYE3NDSP+j84cUWQ==}
|
||||
'@push.rocks/taskbuffer@3.5.0':
|
||||
resolution: {integrity: sha512-Y9WwIEIyp6oVFdj06j84tfrZIvjhbMb3DF52rYxlTeYLk3W7RPhSg1bGPCbtkXWeKdBrSe37V90BkOG7Qq8Pqg==}
|
||||
|
||||
'@push.rocks/webrequest@3.0.37':
|
||||
resolution: {integrity: sha512-fLN7kP6GeHFxE4UH4r9C9pjcQb0QkJxHeAMwXvbOqB9hh0MFNKhtGU7GoaTn8SVRGRMPc9UqZVNwo6u5l8Wn0A==}
|
||||
@@ -3896,7 +3896,7 @@ snapshots:
|
||||
|
||||
'@api.global/typedrequest-interfaces@3.0.19': {}
|
||||
|
||||
'@api.global/typedrequest@3.1.11':
|
||||
'@api.global/typedrequest@3.2.2':
|
||||
dependencies:
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@push.rocks/isounique': 1.0.5
|
||||
@@ -3910,7 +3910,7 @@ snapshots:
|
||||
|
||||
'@api.global/typedserver@3.0.80(@push.rocks/smartserve@1.1.2)':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@api.global/typedsocket': 3.1.1(@push.rocks/smartserve@1.1.2)
|
||||
'@cloudflare/workers-types': 4.20251202.0
|
||||
@@ -3937,7 +3937,7 @@ snapshots:
|
||||
'@push.rocks/smartsitemap': 2.0.4
|
||||
'@push.rocks/smartstream': 3.2.5
|
||||
'@push.rocks/smarttime': 4.1.1
|
||||
'@push.rocks/taskbuffer': 3.4.0
|
||||
'@push.rocks/taskbuffer': 3.5.0
|
||||
'@push.rocks/webrequest': 3.0.37
|
||||
'@push.rocks/webstore': 2.0.20
|
||||
'@tsclass/tsclass': 9.3.0
|
||||
@@ -3958,7 +3958,7 @@ snapshots:
|
||||
|
||||
'@api.global/typedsocket@3.1.1(@push.rocks/smartserve@1.1.2)':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@push.rocks/isohash': 2.0.1
|
||||
'@push.rocks/smartjson': 5.2.0
|
||||
@@ -3978,7 +3978,7 @@ snapshots:
|
||||
|
||||
'@api.global/typedsocket@4.1.0(@push.rocks/smartserve@1.1.2)':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@push.rocks/isohash': 2.0.1
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
@@ -5259,14 +5259,14 @@ snapshots:
|
||||
|
||||
'@design.estate/dees-comms@1.0.27':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
broadcast-channel: 7.0.0
|
||||
|
||||
'@design.estate/dees-domtools@2.0.65':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@design.estate/dees-comms': 1.0.27
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
@@ -5288,7 +5288,7 @@ snapshots:
|
||||
|
||||
'@design.estate/dees-domtools@2.3.6':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@design.estate/dees-comms': 1.0.27
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
@@ -5849,7 +5849,7 @@ snapshots:
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartstring': 4.1.0
|
||||
'@push.rocks/smartunique': 3.0.9
|
||||
'@push.rocks/taskbuffer': 3.4.0
|
||||
'@push.rocks/taskbuffer': 3.5.0
|
||||
'@tsclass/tsclass': 9.3.0
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
@@ -5889,7 +5889,7 @@ snapshots:
|
||||
|
||||
'@push.rocks/qenv@6.1.3':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@configvault.io/interfaces': 1.0.17
|
||||
'@push.rocks/smartfile': 11.2.7
|
||||
'@push.rocks/smartlog': 3.1.10
|
||||
@@ -6015,7 +6015,7 @@ snapshots:
|
||||
'@push.rocks/smartstring': 4.1.0
|
||||
'@push.rocks/smarttime': 4.1.1
|
||||
'@push.rocks/smartunique': 3.0.9
|
||||
'@push.rocks/taskbuffer': 3.4.0
|
||||
'@push.rocks/taskbuffer': 3.5.0
|
||||
'@tsclass/tsclass': 9.3.0
|
||||
mongodb: 6.21.0(@aws-sdk/credential-providers@3.787.0)(socks@2.8.7)
|
||||
transitivePeerDependencies:
|
||||
@@ -6376,7 +6376,7 @@ snapshots:
|
||||
|
||||
'@push.rocks/smartserve@1.1.2':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.1.11
|
||||
'@api.global/typedrequest': 3.2.2
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartenv': 6.0.0
|
||||
'@push.rocks/smartlog': 3.1.10
|
||||
@@ -6523,7 +6523,7 @@ snapshots:
|
||||
dependencies:
|
||||
yaml: 2.8.1
|
||||
|
||||
'@push.rocks/taskbuffer@3.4.0':
|
||||
'@push.rocks/taskbuffer@3.5.0':
|
||||
dependencies:
|
||||
'@design.estate/dees-element': 2.1.3
|
||||
'@push.rocks/lik': 6.2.2
|
||||
|
||||
@@ -203,4 +203,25 @@ export class BuiltInRoutesController {
|
||||
return new Response('SW-Dash bundle not found', { status: 404 });
|
||||
}
|
||||
}
|
||||
|
||||
@plugins.smartserve.Get('/serviceworker.bundle.js')
|
||||
async getServiceWorkerBundle(): Promise<Response> {
|
||||
try {
|
||||
const bundleContent = (await plugins.fsInstance
|
||||
.file(paths.serviceworkerBundlePath)
|
||||
.encoding('utf8')
|
||||
.read()) as string;
|
||||
|
||||
return new Response(bundleContent, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
'Cache-Control': 'no-cache',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to serve serviceworker bundle:', error);
|
||||
return new Response('ServiceWorker bundle not found', { status: 404 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export class TypedRequestController {
|
||||
this.typedRouter = typedRouter;
|
||||
}
|
||||
|
||||
@plugins.smartserve.Post('/')
|
||||
@plugins.smartserve.Post('')
|
||||
async handleTypedRequest(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
|
||||
try {
|
||||
const response = await this.typedRouter.routeAndAddResponse(ctx.body as plugins.typedrequestInterfaces.ITypedRequest);
|
||||
@@ -31,4 +31,15 @@ export class TypedRequestController {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@plugins.smartserve.Head('')
|
||||
async handleTypedRequestHead(): Promise<Response> {
|
||||
// HEAD request for online checking from service worker
|
||||
return new Response(null, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ export const injectBundleDir = plugins.path.join(packageDir, './dist_ts_web_inje
|
||||
export const injectBundlePath = plugins.path.join(injectBundleDir, './bundle.js');
|
||||
|
||||
export const serviceworkerBundleDir = plugins.path.join(packageDir, './dist_ts_web_serviceworker');
|
||||
export const serviceworkerBundlePath = plugins.path.join(serviceworkerBundleDir, './serviceworker.bundle.js');
|
||||
|
||||
export const swdashBundleDir = plugins.path.join(packageDir, './dist_ts_swdash');
|
||||
export const swdashBundlePath = plugins.path.join(swdashBundleDir, './bundle.js');
|
||||
@@ -303,8 +303,9 @@ export class ReloadChecker {
|
||||
|
||||
// Helper function to log entries
|
||||
const logEntry = (entry: ITypedRequestLogEntry) => {
|
||||
// Skip logging our own logging requests to avoid infinite loops
|
||||
if (entry.method === 'serviceworker_typedRequestLog') {
|
||||
// Skip logging serviceworker_* methods to avoid infinite loops
|
||||
// These are internal SW communication methods, not app traffic
|
||||
if (entry.method.startsWith('serviceworker_')) {
|
||||
return;
|
||||
}
|
||||
actionManager.logTypedRequest(entry);
|
||||
|
||||
@@ -64,7 +64,7 @@ export class NetworkManager {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/sw-typedrequest', {
|
||||
const response = await fetch('/typedrequest', {
|
||||
method: 'HEAD',
|
||||
cache: 'no-cache'
|
||||
});
|
||||
|
||||
@@ -31,6 +31,7 @@ export class ServiceWorker {
|
||||
// TypedSocket connection for server communication
|
||||
public typedsocket: plugins.typedsocket.TypedSocket;
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
private handlersInitialized = false;
|
||||
|
||||
constructor(selfArg: interfaces.ServiceWindow) {
|
||||
logger.log('info', `Service worker instantiating at ${Date.now()}`);
|
||||
@@ -119,33 +120,43 @@ export class ServiceWorker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize typed handlers (idempotent - safe to call multiple times)
|
||||
*/
|
||||
private initHandlers(): void {
|
||||
if (this.handlersInitialized) return;
|
||||
this.handlersInitialized = true;
|
||||
|
||||
// Register handler for cache invalidation from server
|
||||
this.typedrouter.addTypedHandler<interfaces.serviceworker.IRequest_Serviceworker_CacheInvalidate>(
|
||||
new plugins.typedrequest.TypedHandler('serviceworker_cacheInvalidate', async (reqArg) => {
|
||||
logger.log('info', `Cache invalidation requested from server: ${reqArg.reason}`);
|
||||
|
||||
// Log cache invalidation event (survives)
|
||||
const persistentStore = getPersistentStore();
|
||||
await persistentStore.init(); // Ensure store is initialized
|
||||
await persistentStore.logEvent('cache_invalidated', `Cache invalidated: ${reqArg.reason}`, {
|
||||
reason: reqArg.reason,
|
||||
timestamp: reqArg.timestamp,
|
||||
});
|
||||
|
||||
// Reset cumulative metrics (they don't survive cache invalidation)
|
||||
await persistentStore.resetCumulativeMetrics();
|
||||
|
||||
await this.cacheManager.cleanCaches(reqArg.reason);
|
||||
// Notify all clients to reload
|
||||
await this.leleServiceWorkerBackend.triggerReloadAll();
|
||||
return { success: true };
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to TypedServer via TypedSocket for cache invalidation
|
||||
*/
|
||||
private async connectToServer(): Promise<void> {
|
||||
try {
|
||||
// Register handler for cache invalidation from server
|
||||
this.typedrouter.addTypedHandler<interfaces.serviceworker.IRequest_Serviceworker_CacheInvalidate>(
|
||||
new plugins.typedrequest.TypedHandler('serviceworker_cacheInvalidate', async (reqArg) => {
|
||||
logger.log('info', `Cache invalidation requested from server: ${reqArg.reason}`);
|
||||
|
||||
// Log cache invalidation event (survives)
|
||||
const persistentStore = getPersistentStore();
|
||||
await persistentStore.init(); // Ensure store is initialized
|
||||
await persistentStore.logEvent('cache_invalidated', `Cache invalidated: ${reqArg.reason}`, {
|
||||
reason: reqArg.reason,
|
||||
timestamp: reqArg.timestamp,
|
||||
});
|
||||
|
||||
// Reset cumulative metrics (they don't survive cache invalidation)
|
||||
await persistentStore.resetCumulativeMetrics();
|
||||
|
||||
await this.cacheManager.cleanCaches(reqArg.reason);
|
||||
// Notify all clients to reload
|
||||
await this.leleServiceWorkerBackend.triggerReloadAll();
|
||||
return { success: true };
|
||||
})
|
||||
);
|
||||
this.initHandlers();
|
||||
|
||||
// Connect to server via TypedSocket
|
||||
this.typedsocket = await plugins.typedsocket.TypedSocket.createClient(
|
||||
|
||||
@@ -177,7 +177,7 @@ export class UpdateManager {
|
||||
try {
|
||||
const getAppHashRequest = new plugins.typedrequest.TypedRequest<
|
||||
interfaces.serviceworker.IRequest_Serviceworker_Backend_VersionInfo
|
||||
>('/sw-typedrequest', 'serviceworker_versionInfo');
|
||||
>('/typedrequest', 'serviceworker_versionInfo');
|
||||
|
||||
// Use networkManager for the request with retries and timeout
|
||||
const response = await getAppHashRequest.fire({});
|
||||
|
||||
@@ -202,6 +202,7 @@ export class ActionManager {
|
||||
public async logTypedRequest(entry: interfaces.serviceworker.ITypedRequestLogEntry): Promise<void> {
|
||||
try {
|
||||
const tr = this.deesComms.createTypedRequest<interfaces.serviceworker.IMessage_Serviceworker_TypedRequestLog>('serviceworker_typedRequestLog');
|
||||
tr.skipHooks = true; // Prevent infinite loops - don't log the logging request
|
||||
await tr.fire(entry);
|
||||
} catch (error) {
|
||||
// Silently ignore logging errors to avoid infinite loops
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import { ServiceworkerClient } from './classes.serviceworkerclient.js';
|
||||
import { ActionManager } from './classes.actionmanager.js';
|
||||
|
||||
export class GlobalSW {
|
||||
losslessSw: ServiceworkerClient;
|
||||
@@ -8,6 +9,13 @@ export class GlobalSW {
|
||||
globalThis.globalSw = this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exposes the action manager for traffic logging and SW communication
|
||||
*/
|
||||
public get actionManager(): ActionManager {
|
||||
return this.losslessSw.actionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* purges the cache of the app's serviceworker
|
||||
* @returns
|
||||
|
||||
Reference in New Issue
Block a user