Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
aebcbe4a61 | |||
c5cb8c1f01 | |||
8202ce6227 | |||
4598bd0e25 | |||
021c980a4f | |||
c7dca75827 | |||
4f7b2888ab | |||
e552a48c02 | |||
2ea4139974 | |||
e225c693a8 | |||
6393336ea6 | |||
d7158734d2 | |||
557724718c | |||
d7a9b26873 | |||
511de8040a | |||
952e95f82f | |||
42115cb6be | |||
e1206bdf4c | |||
e32e7272ba | |||
3f317fffd5 | |||
a49309566c | |||
0fb1d54e06 |
128
.gitlab-ci.yml
128
.gitlab-ci.yml
@ -1,128 +0,0 @@
|
||||
# gitzone ci_default
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- .npmci_cache/
|
||||
key: '$CI_BUILD_STAGE'
|
||||
|
||||
stages:
|
||||
- security
|
||||
- test
|
||||
- release
|
||||
- metadata
|
||||
|
||||
before_script:
|
||||
- pnpm install -g pnpm
|
||||
- pnpm install -g @shipzone/npmci
|
||||
- npmci npm prepare
|
||||
|
||||
# ====================
|
||||
# security stage
|
||||
# ====================
|
||||
# ====================
|
||||
# security stage
|
||||
# ====================
|
||||
auditProductionDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command pnpm audit --audit-level=high --prod
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
allow_failure: true
|
||||
|
||||
auditDevDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command pnpm audit --audit-level=high --dev
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
allow_failure: true
|
||||
|
||||
# ====================
|
||||
# test stage
|
||||
# ====================
|
||||
|
||||
testStable:
|
||||
stage: test
|
||||
script:
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
|
||||
testBuild:
|
||||
stage: test
|
||||
script:
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm build
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
|
||||
release:
|
||||
stage: release
|
||||
script:
|
||||
- npmci node install stable
|
||||
- npmci npm publish
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
# ====================
|
||||
# metadata stage
|
||||
# ====================
|
||||
codequality:
|
||||
stage: metadata
|
||||
allow_failure: true
|
||||
only:
|
||||
- tags
|
||||
script:
|
||||
- npmci command npm install -g typescript
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- priv
|
||||
|
||||
trigger:
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci trigger
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
pages:
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci command npm run buildDocs
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
only:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- public
|
||||
allow_failure: true
|
193
changelog.md
Normal file
193
changelog.md
Normal file
@ -0,0 +1,193 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-02-03 - 3.0.57 - fix(updateManager)
|
||||
Refine cache management for service worker updates.
|
||||
|
||||
- Ensured cache is forcibly updated if older than defined maximum age.
|
||||
- Implemented interval checks and forced updates for cache staleness.
|
||||
- Updated version information and cache timestamps upon forced updates or validations.
|
||||
|
||||
## 2025-02-03 - 3.0.56 - fix(cachemanager)
|
||||
Adjust cache control headers and fix redundant code
|
||||
|
||||
- Remove duplicate assetbroker URLs in the cache evaluation logic.
|
||||
- Update cache control headers to improve caching behavior.
|
||||
- Increase the timeout for fetch operations to improve compatibility.
|
||||
|
||||
## 2025-01-28 - 3.0.55 - fix(server)
|
||||
Fix response content manipulation for HTML files with injectReload
|
||||
|
||||
- Moved fileString declaration inside HTML file handling block to prevent unnecessary string conversion for non-HTML files.
|
||||
- Corrected responseContent assignment to ensure modified HTML strings are converted back to Buffer format.
|
||||
|
||||
## 2025-01-28 - 3.0.54 - fix(servertools)
|
||||
Fixed an issue with compression results handling in HandlerStatic where content was always being written even if not compressed.
|
||||
|
||||
- Corrected the double writing of response in HandlerStatic.
|
||||
- Ensured that file buffers are only conditionally written based on compression availability.
|
||||
|
||||
## 2024-12-26 - 3.0.53 - fix(infohtml)
|
||||
Remove Sentry script and logo from HTML template
|
||||
|
||||
- Removed Sentry script from the HTML template.
|
||||
- Removed Lossless GmbH logo and contact info.
|
||||
- Updated footer link to point to foss.global.
|
||||
|
||||
## 2024-12-25 - 3.0.52 - fix(dependencies)
|
||||
Bump package versions in dependencies and exports.
|
||||
|
||||
- Updated package dependencies to their latest versions.
|
||||
- Added './infohtml' in package exports.
|
||||
|
||||
## 2024-08-27 - 3.0.51 - fix(core)
|
||||
Update dependencies and fix service worker cache manager and task manager functionalities
|
||||
|
||||
- Updated dependencies in package.json to their latest versions
|
||||
- Enhanced service worker cache manager to include additional scoped URLs
|
||||
- Fixed task manager to start the task manager and added update task functionality
|
||||
- Removed .gitlab-ci.yml from the repository as part of the cleanup
|
||||
|
||||
## 2024-05-25 - 3.0.43 to 3.0.50 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.43 to 3.0.50
|
||||
|
||||
## 2024-05-23 - 3.0.37 to 3.0.42 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.37 to 3.0.42
|
||||
|
||||
## 2024-05-17 - 3.0.37 - Core
|
||||
Routine update and bug fix
|
||||
|
||||
- Updated core functionalities
|
||||
|
||||
## 2024-05-14 - 3.0.33 to 3.0.36 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.33 to 3.0.36
|
||||
|
||||
## 2024-05-13 - 3.0.31 to 3.0.32 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.31 to 3.0.32
|
||||
|
||||
## 2024-05-11 - 3.0.29 to 3.0.31 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.29 to 3.0.31
|
||||
|
||||
## 2024-04-19 - 3.0.27 to 3.0.28 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.27 to 3.0.28
|
||||
|
||||
## 2024-04-14 - 3.0.27 - Documentation
|
||||
Updated Documentation
|
||||
|
||||
- Improved and updated documentation
|
||||
|
||||
## 2024-03-01 - 3.0.25 to 3.0.26 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.25 to 3.0.26
|
||||
|
||||
## 2024-02-21 - 3.0.20 to 3.0.24 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.20 to 3.0.24
|
||||
|
||||
## 2024-01-19 - 3.0.19 to 3.0.20 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.19 to 3.0.20
|
||||
|
||||
## 2024-01-09 - 3.0.14 to 3.0.18 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.14 to 3.0.18
|
||||
|
||||
## 2024-01-08 - 3.0.11 to 3.0.13 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.11 to 3.0.13
|
||||
|
||||
## 2024-01-07 - 3.0.9 to 3.0.10 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.9 to 3.0.10
|
||||
|
||||
## 2023-11-06 - 3.0.8 to 3.0.9 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.8 to 3.0.9
|
||||
|
||||
## 2023-10-23 - 3.0.6 to 3.0.7 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.6 to 3.0.7
|
||||
|
||||
## 2023-10-20 - 3.0.5 to 3.0.6 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.5 to 3.0.6
|
||||
|
||||
## 2023-09-21 - 3.0.4 to 3.0.5 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.4 to 3.0.5
|
||||
|
||||
## 2023-08-06 - 3.0.2 to 3.0.3 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.2 to 3.0.3
|
||||
|
||||
## 2023-08-03 - 3.0.1 to 3.0.0 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 3.0.1 to 3.0.0
|
||||
|
||||
## 2023-08-03 - 2.0.65 - Core
|
||||
Breaking change in core update
|
||||
|
||||
- Introduced breaking changes updating core functionalities
|
||||
|
||||
## 2023-07-02 - 2.0.59 to 2.0.64 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 2.0.59 to 2.0.64
|
||||
|
||||
## 2023-07-01 - 2.0.54 to 2.0.58 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 2.0.54 to 2.0.58
|
||||
|
||||
## 2023-06-12 - 2.0.53 - Core
|
||||
Routine update and bug fix
|
||||
|
||||
- Updated core functionalities
|
||||
|
||||
## 2023-04-10 - 2.0.52 to 2.0.53 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 2.0.52 to 2.0.53
|
||||
|
||||
## 2023-04-04 - 2.0.49 to 2.0.51 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 2.0.49 to 2.0.51
|
||||
|
||||
## 2023-03-31 - 2.0.45 to 2.0.48 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 2.0.45 to 2.0.48
|
||||
|
||||
## 2023-03-30 - 2.0.37 to 2.0.44 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 2.0.37 to 2.0.44
|
||||
|
||||
## 2023-03-29 - 2.0.33 to 2.0.36 - Core
|
||||
Routine updates and bug fixes
|
||||
|
||||
- Updated core functionalities for better performance and stability in versions 2.0.33 to 2.0.36
|
51
package.json
51
package.json
@ -1,10 +1,11 @@
|
||||
{
|
||||
"name": "@api.global/typedserver",
|
||||
"version": "3.0.46",
|
||||
"version": "3.0.57",
|
||||
"description": "A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./dist_ts/index.js",
|
||||
"./infohtml": "./dist_ts/infohtml/index.js",
|
||||
"./backend": "./dist_ts/index.js",
|
||||
"./edgeworker": "./dist_ts_edgeworker/index.js",
|
||||
"./web_inject": "./dist_ts_web_inject/index.js",
|
||||
@ -57,51 +58,51 @@
|
||||
],
|
||||
"homepage": "https://github.com/pushrocks/easyserve",
|
||||
"dependencies": {
|
||||
"@api.global/typedrequest": "^3.0.25",
|
||||
"@api.global/typedrequest": "^3.1.10",
|
||||
"@api.global/typedrequest-interfaces": "^3.0.19",
|
||||
"@api.global/typedsocket": "^3.0.1",
|
||||
"@cloudflare/workers-types": "^4.20240512.0",
|
||||
"@cloudflare/workers-types": "^4.20241224.0",
|
||||
"@design.estate/dees-comms": "^1.0.27",
|
||||
"@push.rocks/lik": "^6.0.15",
|
||||
"@push.rocks/lik": "^6.1.0",
|
||||
"@push.rocks/smartchok": "^1.0.34",
|
||||
"@push.rocks/smartdelay": "^3.0.5",
|
||||
"@push.rocks/smartenv": "^5.0.12",
|
||||
"@push.rocks/smartfeed": "^1.0.11",
|
||||
"@push.rocks/smartfile": "^11.0.15",
|
||||
"@push.rocks/smartjson": "^5.0.19",
|
||||
"@push.rocks/smartlog": "^3.0.6",
|
||||
"@push.rocks/smartlog-destination-devtools": "^1.0.10",
|
||||
"@push.rocks/smartlog-interfaces": "^3.0.0",
|
||||
"@push.rocks/smartfile": "^11.0.23",
|
||||
"@push.rocks/smartjson": "^5.0.20",
|
||||
"@push.rocks/smartlog": "^3.0.7",
|
||||
"@push.rocks/smartlog-destination-devtools": "^1.0.12",
|
||||
"@push.rocks/smartlog-interfaces": "^3.0.2",
|
||||
"@push.rocks/smartmanifest": "^2.0.2",
|
||||
"@push.rocks/smartmatch": "^2.0.0",
|
||||
"@push.rocks/smartmime": "^2.0.0",
|
||||
"@push.rocks/smartntml": "^2.0.4",
|
||||
"@push.rocks/smartmime": "^2.0.4",
|
||||
"@push.rocks/smartntml": "^2.0.8",
|
||||
"@push.rocks/smartopen": "^2.0.0",
|
||||
"@push.rocks/smartpath": "^5.0.18",
|
||||
"@push.rocks/smartpromise": "^4.0.2",
|
||||
"@push.rocks/smartrequest": "^2.0.22",
|
||||
"@push.rocks/smartpromise": "^4.0.4",
|
||||
"@push.rocks/smartrequest": "^2.0.23",
|
||||
"@push.rocks/smartrx": "^3.0.7",
|
||||
"@push.rocks/smartsitemap": "^2.0.3",
|
||||
"@push.rocks/smartstream": "^3.0.38",
|
||||
"@push.rocks/smarttime": "^4.0.6",
|
||||
"@push.rocks/smartstream": "^3.2.5",
|
||||
"@push.rocks/smarttime": "^4.1.1",
|
||||
"@push.rocks/taskbuffer": "^3.1.7",
|
||||
"@push.rocks/webrequest": "^3.0.37",
|
||||
"@push.rocks/webstore": "^2.0.19",
|
||||
"@tsclass/tsclass": "^4.0.54",
|
||||
"@push.rocks/webstore": "^2.0.20",
|
||||
"@tsclass/tsclass": "^4.2.0",
|
||||
"@types/express": "^4.17.21",
|
||||
"body-parser": "^1.20.2",
|
||||
"body-parser": "^1.20.3",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.19.2",
|
||||
"express": "^4.21.2",
|
||||
"express-force-ssl": "^0.3.2",
|
||||
"lit": "^3.1.3"
|
||||
"lit": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.1.80",
|
||||
"@git.zone/tsbundle": "^2.0.15",
|
||||
"@git.zone/tsrun": "^1.2.44",
|
||||
"@git.zone/tsbuild": "^2.2.0",
|
||||
"@git.zone/tsbundle": "^2.1.0",
|
||||
"@git.zone/tsrun": "^1.3.3",
|
||||
"@git.zone/tstest": "^1.0.90",
|
||||
"@push.rocks/tapbundle": "^5.0.23",
|
||||
"@types/node": "^20.12.11"
|
||||
"@push.rocks/tapbundle": "^5.5.3",
|
||||
"@types/node": "^22.10.2"
|
||||
},
|
||||
"private": false,
|
||||
"browserslist": [
|
||||
|
5786
pnpm-lock.yaml
generated
5786
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* autocreated commitinfo by @pushrocks/commitinfo
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@api.global/typedserver',
|
||||
version: '3.0.46',
|
||||
version: '3.0.57',
|
||||
description: 'A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.'
|
||||
}
|
||||
|
@ -135,8 +135,8 @@ export class TypedServer {
|
||||
'/*',
|
||||
new servertools.HandlerStatic(this.options.serveDir, {
|
||||
responseModifier: async (responseArg) => {
|
||||
let fileString = responseArg.responseContent.toString();
|
||||
if (plugins.path.parse(responseArg.path).ext === '.html') {
|
||||
let fileString = responseArg.responseContent.toString();
|
||||
const fileStringArray = fileString.split('<head>');
|
||||
if (this.options.injectReload && fileStringArray.length === 2) {
|
||||
fileStringArray[0] = `${fileStringArray[0]}<head>
|
||||
@ -152,6 +152,7 @@ export class TypedServer {
|
||||
`;
|
||||
fileString = fileStringArray.join('');
|
||||
console.log('injected typedserver script.');
|
||||
responseArg.responseContent = Buffer.from(fileString);
|
||||
} else if (this.options.injectReload) {
|
||||
console.log('Could not insert typedserver script');
|
||||
}
|
||||
@ -164,7 +165,7 @@ export class TypedServer {
|
||||
return {
|
||||
headers,
|
||||
path: responseArg.path,
|
||||
responseContent: Buffer.from(fileString),
|
||||
responseContent: responseArg.responseContent,
|
||||
};
|
||||
},
|
||||
serveIndexHtmlDefault: true,
|
||||
|
@ -96,26 +96,9 @@ export const simpleInfo = async (
|
||||
name="viewport"
|
||||
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi"
|
||||
/>
|
||||
<script
|
||||
src="https://browser.sentry-cdn.com/5.4.0/bundle.min.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script>
|
||||
if (optionsArg.sentryDsn && optionsArg.sentryMessage) {
|
||||
Sentry.init({
|
||||
dsn: '${optionsArg.sentryDsn}',
|
||||
// ...
|
||||
});
|
||||
Sentry.setExtra('location', window.location.href);
|
||||
Sentry.captureMessage('${optionsArg.sentryMessage} @ ' + window.location.host);
|
||||
}
|
||||
</script>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="logo">
|
||||
<img src="https://assetbroker.lossless.one/brandfiles/lossless/svg-minimal-bright.svg" />
|
||||
</div>
|
||||
<div class="content">
|
||||
${(() => {
|
||||
const returnArray: plugins.smartntml.deesElement.TemplateResult[] = [];
|
||||
@ -129,15 +112,6 @@ export const simpleInfo = async (
|
||||
} else {
|
||||
returnArray.push(html` <div class="maintext">${optionsArg.text}</div> `);
|
||||
}
|
||||
if (optionsArg.sentryDsn && optionsArg.sentryMessage) {
|
||||
returnArray.push(
|
||||
html`<div class="addontext">
|
||||
We recorded this event. Should you continue to see this page against your
|
||||
expectations, feel free to mail us at
|
||||
<a href="mailto:hello@lossless.com">hello@lossless.com</a>
|
||||
</div>`
|
||||
);
|
||||
}
|
||||
if (optionsArg.redirectTo) {
|
||||
returnArray.push(
|
||||
html`<div class="addontext">
|
||||
@ -149,9 +123,7 @@ export const simpleInfo = async (
|
||||
})()}
|
||||
</div>
|
||||
<div class="legal">
|
||||
<a href="https://lossless.com">Lossless GmbH</a> / © 2014-${new Date().getFullYear()}
|
||||
/ <a href="https://lossless.gmbh">Legal Info</a> /
|
||||
<a href="https://lossless.gmbh">Privacy Policy</a>
|
||||
<a href="https://foss.global">learn more about foss.global</a> / © 2014-${new Date().getFullYear()} Task Venture Capital GmbH
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -134,8 +134,10 @@ export class HandlerStatic extends Handler {
|
||||
res.status(200);
|
||||
if (compressionResult?.compressionMethod) {
|
||||
res.header('Content-Encoding', compressionResult.compressionMethod);
|
||||
res.write(compressionResult.result);
|
||||
} else {
|
||||
res.write(fileBuffer);
|
||||
}
|
||||
res.write(compressionResult.result);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
|
@ -6,7 +6,13 @@ import { type IRoute as IExpressRoute } from 'express';
|
||||
|
||||
export class Route {
|
||||
public routeString: string;
|
||||
|
||||
/**
|
||||
* an object map of handlers
|
||||
* Why multiple? Because GET, POST, PUT, DELETE, etc. can all have different handlers
|
||||
*/
|
||||
public handlerObjectMap = new plugins.lik.ObjectMap<Handler>();
|
||||
|
||||
public expressMiddlewareObjectMap = new plugins.lik.ObjectMap<any>();
|
||||
public expressRoute: IExpressRoute; // will be set to server route on server start
|
||||
constructor(ServerArg: Server, routeStringArg: string) {
|
||||
|
@ -77,6 +77,11 @@ export class Server {
|
||||
return route;
|
||||
}
|
||||
|
||||
/**
|
||||
* starts the server and sets up the routes
|
||||
* @param portArg
|
||||
* @param doListen
|
||||
*/
|
||||
public async start(portArg: number | string = this.options.port, doListen = true) {
|
||||
const done = plugins.smartpromise.defer();
|
||||
|
||||
|
@ -38,7 +38,7 @@ export const addServiceWorkerRoute = (
|
||||
swVersionInfo = swDataFunc();
|
||||
|
||||
// the basic stuff
|
||||
typedserverInstance.server.addRoute('/serviceworker.js*', serviceworkerHandler);
|
||||
typedserverInstance.server.addRoute('/serviceworker.*', serviceworkerHandler);
|
||||
|
||||
// the typed stuff
|
||||
const typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
|
@ -75,12 +75,14 @@ export class CacheManager {
|
||||
// A list of local resources we always want to be cached.
|
||||
this.losslessServiceWorkerRef.serviceWindowRef.addEventListener('fetch', async (fetchEventArg: any) => {
|
||||
// Lets block scopes we don't want to be passing through the serviceworker
|
||||
const parsedUrl = new URL(fetchEventArg.request.url)
|
||||
const originalRequest: Request = fetchEventArg.request;
|
||||
const parsedUrl = new URL(originalRequest.url);
|
||||
if (
|
||||
parsedUrl.hostname.includes('paddle.com')
|
||||
|| parsedUrl.hostname.includes('paypal.com')
|
||||
|| parsedUrl.hostname.includes('reception.lossless.one')
|
||||
|| parsedUrl.pathname.startsWith('/socket.io')
|
||||
|| originalRequest.url.startsWith('https://umami.')
|
||||
) {
|
||||
logger.log('note',`serviceworker not active for ${parsedUrl.toString()}`);
|
||||
return;
|
||||
@ -89,16 +91,13 @@ export class CacheManager {
|
||||
// lets continue for the rest
|
||||
const done = plugins.smartpromise.defer<Response>();
|
||||
fetchEventArg.respondWith(done.promise);
|
||||
const originalRequest: Request = fetchEventArg.request;
|
||||
|
||||
if (
|
||||
(originalRequest.method === 'GET' &&
|
||||
(originalRequest.url.startsWith(this.losslessServiceWorkerRef.serviceWindowRef.location.origin) &&
|
||||
!originalRequest.url.includes('/api/') &&
|
||||
!originalRequest.url.includes('smartserve/reloadcheck'))) ||
|
||||
originalRequest.url.includes('https://assetbroker.lossless.one/public') ||
|
||||
originalRequest.url.includes('https://assetbroker.lossless.one/brandfiles') ||
|
||||
originalRequest.url.includes('https://assetbroker.lossless.one/websites') ||
|
||||
originalRequest.url.includes('https://assetbroker.') ||
|
||||
originalRequest.url.includes('https://unpkg.com') ||
|
||||
originalRequest.url.includes('https://fonts.googleapis.com') ||
|
||||
originalRequest.url.includes('https://fonts.gstatic.com')
|
||||
@ -149,9 +148,11 @@ export class CacheManager {
|
||||
headers.set(key, value);
|
||||
}
|
||||
});
|
||||
headers.set('Cache-Control', 'no-cache, no-store, must-revalidate');
|
||||
// Prevent browser caching while allowing service worker caching
|
||||
headers.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
|
||||
headers.set('Pragma', 'no-cache');
|
||||
headers.set('Expires', '0');
|
||||
headers.set('Surrogate-Control', 'no-store');
|
||||
await cache.put(matchRequest, new Response(responseToPutToCache.body, {
|
||||
...responseToPutToCache,
|
||||
headers
|
||||
@ -214,7 +215,7 @@ export class CacheManager {
|
||||
|
||||
// lets get a new response for comparison
|
||||
const clonedRequest = requestArg.clone();
|
||||
const response = await plugins.smartpromise.timeoutWrap(fetch(clonedRequest), 1000);
|
||||
const response = await plugins.smartpromise.timeoutWrap(fetch(clonedRequest), 5000); // Increased timeout for better mobile compatibility
|
||||
if (response && response.status >= 200 && response.status < 300) {
|
||||
await runtimeCache.delete(requestArg);
|
||||
await runtimeCache.put(requestArg, response);
|
||||
|
@ -7,9 +7,18 @@ import { ServiceWorker } from './classes.serviceworker.js';
|
||||
*/
|
||||
export class TaskManager {
|
||||
public serviceworkerRef: ServiceWorker;
|
||||
public taskmanager = new plugins.taskbuffer.TaskManager();
|
||||
|
||||
constructor(serviceWorkerRefArg: ServiceWorker) {
|
||||
this.serviceworkerRef = serviceWorkerRefArg;
|
||||
this.taskmanager.start();
|
||||
}
|
||||
|
||||
public updateTask = new plugins.taskbuffer.Task({
|
||||
name: 'updateTask',
|
||||
taskFunction: async () => {
|
||||
await this.serviceworkerRef.cacheManager.cleanCaches('a new app version has been communicated by the server.');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
@ -17,24 +17,42 @@ export class UpdateManager {
|
||||
/**
|
||||
* checks wether an update is needed
|
||||
*/
|
||||
private readonly MAX_CACHE_AGE = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
|
||||
private readonly MIN_CHECK_INTERVAL = 100000; // 100 seconds in milliseconds
|
||||
private lastCacheTimestamp: number = 0;
|
||||
|
||||
public async checkUpdate(cacheManager: CacheManager): Promise<boolean> {
|
||||
const lswVersionInfoKey = 'versionInfo';
|
||||
const cacheTimestampKey = 'cacheTimestamp';
|
||||
|
||||
// Initialize or load version info
|
||||
if (!this.lastVersionInfo && !(await this.serviceworkerRef.store.check(lswVersionInfoKey))) {
|
||||
this.lastVersionInfo = {
|
||||
appHash: '',
|
||||
appSemVer: 'v0.0.0',
|
||||
};
|
||||
} else if (
|
||||
!this.lastVersionInfo &&
|
||||
(await this.serviceworkerRef.store.check(lswVersionInfoKey))
|
||||
) {
|
||||
} else if (!this.lastVersionInfo && (await this.serviceworkerRef.store.check(lswVersionInfoKey))) {
|
||||
this.lastVersionInfo = await this.serviceworkerRef.store.get(lswVersionInfoKey);
|
||||
}
|
||||
|
||||
// Load or initialize cache timestamp
|
||||
if (await this.serviceworkerRef.store.check(cacheTimestampKey)) {
|
||||
this.lastCacheTimestamp = await this.serviceworkerRef.store.get(cacheTimestampKey);
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const millisSinceLastCheck = now - this.lastUpdateCheck;
|
||||
if (millisSinceLastCheck < 100000) {
|
||||
// TODO account for being offline
|
||||
const cacheAge = now - this.lastCacheTimestamp;
|
||||
|
||||
// Force update if cache is too old
|
||||
if (cacheAge > this.MAX_CACHE_AGE) {
|
||||
logger.log('info', `Cache is older than ${this.MAX_CACHE_AGE}ms, forcing update...`);
|
||||
await this.forceUpdate(cacheManager);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Regular update check interval
|
||||
if (millisSinceLastCheck < this.MIN_CHECK_INTERVAL && cacheAge < this.MAX_CACHE_AGE) {
|
||||
return false;
|
||||
}
|
||||
logger.log('info', 'checking for update of the app by comparing app hashes...');
|
||||
@ -49,9 +67,17 @@ export class UpdateManager {
|
||||
this.performAsyncUpdateDebouncedTask.trigger();
|
||||
this.lastVersionInfo = currentVersionInfo;
|
||||
await this.serviceworkerRef.store.set(lswVersionInfoKey, this.lastVersionInfo);
|
||||
|
||||
// Update cache timestamp
|
||||
this.lastCacheTimestamp = now;
|
||||
await this.serviceworkerRef.store.set('cacheTimestamp', now);
|
||||
} else {
|
||||
logger.log('ok', 'caches are still valid, performing revalidation in a bit...');
|
||||
this.performAsyncCacheRevalidationDebouncedTask.trigger();
|
||||
|
||||
// Update cache timestamp after successful revalidation
|
||||
this.lastCacheTimestamp = now;
|
||||
await this.serviceworkerRef.store.set('cacheTimestamp', now);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +96,17 @@ export class UpdateManager {
|
||||
/**
|
||||
* this task is executed once we know that there is a new version available
|
||||
*/
|
||||
private async forceUpdate(cacheManager: CacheManager) {
|
||||
logger.log('info', 'Forcing cache update due to staleness');
|
||||
await this.serviceworkerRef.cacheManager.cleanCaches('Cache is stale, forcing update.');
|
||||
const currentVersionInfo = await this.getVersionInfoFromServer();
|
||||
this.lastVersionInfo = currentVersionInfo;
|
||||
await this.serviceworkerRef.store.set('versionInfo', this.lastVersionInfo);
|
||||
this.lastCacheTimestamp = Date.now();
|
||||
await this.serviceworkerRef.store.set('cacheTimestamp', this.lastCacheTimestamp);
|
||||
await this.serviceworkerRef.leleServiceWorkerBackend.triggerReloadAll();
|
||||
}
|
||||
|
||||
public performAsyncUpdateDebouncedTask = new plugins.taskbuffer.TaskDebounced({
|
||||
name: 'performAsyncUpdate',
|
||||
taskFunction: async () => {
|
||||
|
@ -13,7 +13,7 @@ export class ServiceworkerClient {
|
||||
logger.log('info', 'trying to register serviceworker');
|
||||
// this is some magic for Parcel to not pick up the serviceworker
|
||||
const serviceworkerInNavigator: ServiceWorkerContainer = navigator.serviceWorker;
|
||||
const swRegistration: ServiceWorkerRegistration = await serviceworkerInNavigator.register('/lsw.js', {
|
||||
const swRegistration: ServiceWorkerRegistration = await serviceworkerInNavigator.register('/serviceworker.bundle.js', {
|
||||
scope: '/',
|
||||
updateViaCache: 'none'
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ logger.log('note', 'mainthread console initialized!');
|
||||
import { ServiceworkerClient } from './classes.serviceworkerclient.js';
|
||||
|
||||
export type {
|
||||
ServiceworkerClient as LosslessServiceworker
|
||||
ServiceworkerClient
|
||||
}
|
||||
|
||||
export const getServiceworkerClient = async () => {
|
||||
|
Reference in New Issue
Block a user