@reidelsaltres/pureper 0.2.14 → 0.2.17
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/out/foundation/Fetcher.d.ts.map +1 -1
- package/out/foundation/Fetcher.js +8 -13
- package/out/foundation/Fetcher.js.map +1 -1
- package/out/foundation/Injection.d.ts +87 -0
- package/out/foundation/Injection.d.ts.map +1 -0
- package/out/foundation/Injection.js +149 -0
- package/out/foundation/Injection.js.map +1 -0
- package/out/foundation/Theme.d.ts.map +1 -1
- package/out/foundation/Theme.js +16 -1
- package/out/foundation/Theme.js.map +1 -1
- package/out/foundation/Triplet.d.ts +30 -25
- package/out/foundation/Triplet.d.ts.map +1 -1
- package/out/foundation/Triplet.js +96 -115
- package/out/foundation/Triplet.js.map +1 -1
- package/out/foundation/TripletDecorator.d.ts +11 -0
- package/out/foundation/TripletDecorator.d.ts.map +1 -1
- package/out/foundation/TripletDecorator.js +25 -8
- package/out/foundation/TripletDecorator.js.map +1 -1
- package/out/foundation/component_api/Component.d.ts.map +1 -1
- package/out/foundation/component_api/Component.js +1 -0
- package/out/foundation/component_api/Component.js.map +1 -1
- package/out/foundation/component_api/UniHtml.d.ts +6 -1
- package/out/foundation/component_api/UniHtml.d.ts.map +1 -1
- package/out/foundation/component_api/UniHtml.js +32 -7
- package/out/foundation/component_api/UniHtml.js.map +1 -1
- package/out/foundation/engine/Expression.d.ts +2 -0
- package/out/foundation/engine/Expression.d.ts.map +1 -1
- package/out/foundation/engine/Expression.js +26 -11
- package/out/foundation/engine/Expression.js.map +1 -1
- package/out/foundation/engine/StylePreprocessor.js +2 -1
- package/out/foundation/engine/StylePreprocessor.js.map +1 -1
- package/out/foundation/engine/TemplateEngine.d.ts +3 -1
- package/out/foundation/engine/TemplateEngine.d.ts.map +1 -1
- package/out/foundation/engine/TemplateEngine.js +44 -15
- package/out/foundation/engine/TemplateEngine.js.map +1 -1
- package/out/foundation/worker/Router.d.ts.map +1 -1
- package/out/foundation/worker/Router.js +6 -0
- package/out/foundation/worker/Router.js.map +1 -1
- package/out/foundation/worker/ServiceWorker.d.ts +48 -17
- package/out/foundation/worker/ServiceWorker.d.ts.map +1 -1
- package/out/foundation/worker/ServiceWorker.js +186 -119
- package/out/foundation/worker/ServiceWorker.js.map +1 -1
- package/out/index.d.ts +3 -2
- package/out/index.d.ts.map +1 -1
- package/out/index.js +2 -1
- package/out/index.js.map +1 -1
- package/package.json +1 -1
- package/src/foundation/Fetcher.ts +9 -14
- package/src/foundation/Injection.ts +183 -0
- package/src/foundation/Theme.ts +17 -3
- package/src/foundation/Triplet.ts +114 -141
- package/src/foundation/TripletDecorator.ts +32 -8
- package/src/foundation/component_api/Component.ts +1 -0
- package/src/foundation/component_api/UniHtml.ts +35 -7
- package/src/foundation/engine/Expression.ts +34 -20
- package/src/foundation/engine/StylePreprocessor.ts +1 -1
- package/src/foundation/engine/TemplateEngine.ts +42 -15
- package/src/foundation/worker/Router.ts +10 -3
- package/src/foundation/worker/ServiceWorker.ts +203 -129
- package/src/foundation/worker/serviceworker.js +191 -0
- package/src/index.ts +7 -4
- package/out/foundation/worker/serviceworker.d.ts +0 -1
- package/out/foundation/worker/serviceworker.d.ts.map +0 -1
- package/out/foundation/worker/serviceworker.js +0 -2
- package/out/foundation/worker/serviceworker.js.map +0 -1
|
@@ -1,144 +1,211 @@
|
|
|
1
|
-
|
|
2
|
-
// Автоматически генерируем CACHE_NAME из base.json
|
|
3
|
-
//import base from '../../../data/base.json';
|
|
4
|
-
const CACHE_NAME = `pureper-v1`;
|
|
5
|
-
const STATIC_ASSETS = [
|
|
6
|
-
'/index.html'
|
|
7
|
-
];
|
|
8
|
-
/*if ('serviceWorker' in navigator) {
|
|
9
|
-
window.addEventListener('load', () => {
|
|
10
|
-
navigator.serviceWorker.register('./serviceWorker.js', { type: 'module' })
|
|
11
|
-
.then((registration) => {
|
|
12
|
-
console.log('ServiceWorker registration successful:', registration.scope);
|
|
13
|
-
})
|
|
14
|
-
.catch((error) => {
|
|
15
|
-
console.error('ServiceWorker registration failed:', error);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
window.addEventListener('fetch', (event: FetchEvent) => {
|
|
19
|
-
event.respondWith(
|
|
20
|
-
caches.match(event.request).then((cachedResponse) => {
|
|
21
|
-
console.log(`[ServiceWorker]: Fetching ${event.request.url}`);
|
|
22
|
-
return cachedResponse || fetch(event.request);
|
|
23
|
-
})
|
|
24
|
-
);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
1
|
+
import Observable from "../api/Observer.js";
|
|
28
2
|
/**
|
|
29
|
-
*
|
|
3
|
+
* Client-side Service Worker manager for Purper SPA.
|
|
4
|
+
*
|
|
5
|
+
* Provides:
|
|
6
|
+
* - Registration with one call (`ServiceWorker.register()`)
|
|
7
|
+
* - Cache management: add / remove / list / clear
|
|
8
|
+
* - Connectivity detection with reactive `online` observable
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```ts
|
|
12
|
+
* await ServiceWorker.register(); // defaults to './serviceworker.js'
|
|
13
|
+
* await ServiceWorker.addToCache('/data.json');
|
|
14
|
+
* await ServiceWorker.removeFromCache('/old.css');
|
|
15
|
+
* ServiceWorker.online.subscribe(v => console.log('online:', v));
|
|
16
|
+
* ```
|
|
30
17
|
*/
|
|
31
|
-
/*window.addEventListener('install', (event: ExtendableEvent) => {
|
|
32
|
-
console.log('ServiceWorker: Installing...');
|
|
33
|
-
const assetsToCache = [
|
|
34
|
-
...STATIC_ASSETS
|
|
35
|
-
];
|
|
36
|
-
// Remove duplicates
|
|
37
|
-
const uniqueAssets = Array.from(new Set(assetsToCache));
|
|
38
|
-
event.waitUntil(
|
|
39
|
-
caches.open(CACHE_NAME)
|
|
40
|
-
.then((cache: Cache) => {
|
|
41
|
-
console.log('ServiceWorker: Caching static assets and SPA routes');
|
|
42
|
-
return cache.addAll(uniqueAssets);
|
|
43
|
-
})
|
|
44
|
-
.then(() => {
|
|
45
|
-
console.log('ServiceWorker: Installation complete');
|
|
46
|
-
return swSelf.skipWaiting();
|
|
47
|
-
})
|
|
48
|
-
);
|
|
49
|
-
});*/
|
|
50
18
|
export default class ServiceWorker {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
static
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
19
|
+
static _registration;
|
|
20
|
+
/** Observable connectivity state — subscribe for real-time changes. */
|
|
21
|
+
static online = new Observable(navigator.onLine);
|
|
22
|
+
// ── Connectivity listeners (bound once) ─────────────────────────
|
|
23
|
+
static _connectivityBound = false;
|
|
24
|
+
static _bindConnectivity() {
|
|
25
|
+
if (this._connectivityBound)
|
|
26
|
+
return;
|
|
27
|
+
this._connectivityBound = true;
|
|
28
|
+
window.addEventListener('online', () => {
|
|
29
|
+
console.log('[ServiceWorker]: Browser went online');
|
|
30
|
+
this.online.setObject(true);
|
|
31
|
+
});
|
|
32
|
+
window.addEventListener('offline', () => {
|
|
33
|
+
console.log('[ServiceWorker]: Browser went offline');
|
|
34
|
+
this.online.setObject(false);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
// ── Registration ────────────────────────────────────────────────
|
|
38
|
+
static async register(config) {
|
|
39
|
+
if (!('serviceWorker' in navigator)) {
|
|
40
|
+
console.warn('[ServiceWorker]: Service Workers are not supported in this browser');
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
this._bindConnectivity();
|
|
44
|
+
const scriptURL = config?.scriptURL ?? './serviceworker.js';
|
|
45
|
+
const scope = config?.scope ?? '/';
|
|
46
|
+
try {
|
|
47
|
+
const reg = await navigator.serviceWorker.register(scriptURL, { scope });
|
|
48
|
+
this._registration = reg;
|
|
49
|
+
console.log(`[ServiceWorker]: Registered "${scriptURL}" with scope "${reg.scope}"`);
|
|
50
|
+
reg.addEventListener('updatefound', () => {
|
|
51
|
+
const newWorker = reg.installing;
|
|
52
|
+
if (!newWorker)
|
|
53
|
+
return;
|
|
54
|
+
console.log('[ServiceWorker]: New version installing...');
|
|
55
|
+
newWorker.addEventListener('statechange', () => {
|
|
56
|
+
if (newWorker.state === 'activated') {
|
|
57
|
+
console.log('[ServiceWorker]: New version activated');
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
60
|
});
|
|
61
|
+
// Wait for the controller to be available
|
|
62
|
+
if (!navigator.serviceWorker.controller) {
|
|
63
|
+
await new Promise((resolve) => {
|
|
64
|
+
navigator.serviceWorker.addEventListener('controllerchange', () => resolve(), { once: true });
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return reg;
|
|
61
68
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
catch (err) {
|
|
70
|
+
console.error('[ServiceWorker]: Registration failed', err);
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// ── Helpers ─────────────────────────────────────────────────────
|
|
75
|
+
static _postMessage(msg) {
|
|
76
|
+
navigator.serviceWorker?.controller?.postMessage(msg);
|
|
77
|
+
}
|
|
78
|
+
static _request(msg) {
|
|
79
|
+
return new Promise((resolve, reject) => {
|
|
80
|
+
if (!navigator.serviceWorker?.controller) {
|
|
81
|
+
reject('[ServiceWorker]: No active controller');
|
|
82
|
+
return;
|
|
71
83
|
}
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
const mc = new MessageChannel();
|
|
85
|
+
mc.port1.onmessage = (ev) => resolve(ev.data);
|
|
86
|
+
navigator.serviceWorker.controller.postMessage(msg, [mc.port2]);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// ── Cache Management ────────────────────────────────────────────
|
|
90
|
+
/** Add a single URL to the SW cache. */
|
|
91
|
+
static async addToCache(url) {
|
|
92
|
+
if (navigator.serviceWorker?.controller) {
|
|
93
|
+
this._postMessage({ type: 'CACHE_URL', url });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Fallback: use Cache API directly
|
|
97
|
+
try {
|
|
98
|
+
const cache = await caches.open('purper-v1');
|
|
99
|
+
const response = await fetch(url);
|
|
100
|
+
if (response.ok) {
|
|
101
|
+
await cache.put(url, response);
|
|
102
|
+
console.log('[ServiceWorker]: Resource cached directly:', url);
|
|
74
103
|
}
|
|
75
104
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
* Asks the service worker to skip waiting and activate the new version.
|
|
79
|
-
*/
|
|
80
|
-
static skipWaiting() {
|
|
81
|
-
if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
|
|
82
|
-
navigator.serviceWorker.controller.postMessage({ type: 'SKIP_WAITING' });
|
|
105
|
+
catch (e) {
|
|
106
|
+
console.warn('[ServiceWorker]: Failed to cache resource:', url, e);
|
|
83
107
|
}
|
|
84
108
|
}
|
|
85
|
-
/**
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
};
|
|
101
|
-
navigator.serviceWorker.controller.postMessage({ type: 'GET_VERSION' }, [messageChannel.port2]);
|
|
109
|
+
/** Add multiple URLs to the SW cache in one batch. */
|
|
110
|
+
static addAllToCache(urls) {
|
|
111
|
+
this._postMessage({ type: 'CACHE_URLS', urls });
|
|
112
|
+
}
|
|
113
|
+
/** Remove a URL from the SW cache. Returns true if it was found and deleted. */
|
|
114
|
+
static async removeFromCache(url) {
|
|
115
|
+
try {
|
|
116
|
+
const data = await this._request({ type: 'REMOVE_URL', url });
|
|
117
|
+
return data.deleted;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Fallback
|
|
121
|
+
try {
|
|
122
|
+
const cache = await caches.open('purper-v1');
|
|
123
|
+
return await cache.delete(url);
|
|
102
124
|
}
|
|
103
|
-
|
|
104
|
-
|
|
125
|
+
catch {
|
|
126
|
+
return false;
|
|
105
127
|
}
|
|
106
|
-
}
|
|
128
|
+
}
|
|
107
129
|
}
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
130
|
+
/** Return all URLs currently in the SW cache. */
|
|
131
|
+
static async getCacheKeys() {
|
|
132
|
+
try {
|
|
133
|
+
const data = await this._request({ type: 'GET_CACHE_KEYS' });
|
|
134
|
+
return data.keys;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** Wipe the entire SW cache. */
|
|
141
|
+
static async clearCache() {
|
|
142
|
+
try {
|
|
143
|
+
const data = await this._request({ type: 'CLEAR_CACHE' });
|
|
144
|
+
return data.cleared;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Check whether a URL exists in the SW cache. */
|
|
151
|
+
static async isCached(url) {
|
|
152
|
+
try {
|
|
153
|
+
const data = await this._request({ type: 'HAS_URL', url });
|
|
154
|
+
return data.cached;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// Fallback: CacheStorage directly
|
|
158
|
+
try {
|
|
159
|
+
return !!(await caches.match(url));
|
|
124
160
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
caches.match(url).then(match => resolve(!!match)).catch(() => resolve(false));
|
|
161
|
+
catch {
|
|
162
|
+
return false;
|
|
128
163
|
}
|
|
129
|
-
}
|
|
164
|
+
}
|
|
130
165
|
}
|
|
166
|
+
// ── Version & lifecycle ─────────────────────────────────────────
|
|
167
|
+
/** Ask the waiting SW to activate immediately. */
|
|
168
|
+
static skipWaiting() {
|
|
169
|
+
this._postMessage({ type: 'SKIP_WAITING' });
|
|
170
|
+
}
|
|
171
|
+
/** Get the version string from the running SW. */
|
|
172
|
+
static async getVersion() {
|
|
173
|
+
const data = await this._request({ type: 'GET_VERSION' });
|
|
174
|
+
return data.version;
|
|
175
|
+
}
|
|
176
|
+
// ── Connectivity ────────────────────────────────────────────────
|
|
131
177
|
/**
|
|
132
|
-
*
|
|
178
|
+
* Active connectivity probe — makes a real network request.
|
|
179
|
+
* Unlike `online` observable (which relies on browser events), this
|
|
180
|
+
* detects captive portals and lie-fi.
|
|
133
181
|
*/
|
|
134
|
-
static async isOnline() {
|
|
182
|
+
static async isOnline(probeURL) {
|
|
135
183
|
try {
|
|
136
|
-
|
|
137
|
-
|
|
184
|
+
// Try SW-side probe first
|
|
185
|
+
const data = await this._request({
|
|
186
|
+
type: 'IS_ONLINE',
|
|
187
|
+
url: probeURL ?? '/index.html'
|
|
188
|
+
});
|
|
189
|
+
this.online.setObject(data.online);
|
|
190
|
+
return data.online;
|
|
138
191
|
}
|
|
139
192
|
catch {
|
|
140
|
-
|
|
193
|
+
// Fallback: client-side probe
|
|
194
|
+
try {
|
|
195
|
+
const response = await fetch(probeURL ?? './index.html', { cache: 'no-store', method: 'HEAD' });
|
|
196
|
+
const result = response.ok;
|
|
197
|
+
this.online.setObject(result);
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
this.online.setObject(false);
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
141
204
|
}
|
|
142
205
|
}
|
|
206
|
+
/** Current registration, if any. */
|
|
207
|
+
static get registration() {
|
|
208
|
+
return this._registration;
|
|
209
|
+
}
|
|
143
210
|
}
|
|
144
211
|
//# sourceMappingURL=ServiceWorker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceWorker.js","sourceRoot":"","sources":["../../../src/foundation/worker/ServiceWorker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ServiceWorker.js","sourceRoot":"","sources":["../../../src/foundation/worker/ServiceWorker.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,oBAAoB,CAAC;AAO5C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IACtB,MAAM,CAAC,aAAa,CAA6B;IAEzD,uEAAuE;IACvE,MAAM,CAAU,MAAM,GAAwB,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE/E,mEAAmE;IAC3D,MAAM,CAAC,kBAAkB,GAAG,KAAK,CAAC;IAClC,MAAM,CAAC,iBAAiB;QAC5B,IAAI,IAAI,CAAC,kBAAkB;YAAE,OAAO;QACpC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAE/B,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YACnC,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;YACpD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE;YACpC,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;YACrD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACP,CAAC;IAED,mEAAmE;IACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAA4B;QAC9C,IAAI,CAAC,CAAC,eAAe,IAAI,SAAS,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;YACnF,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,oBAAoB,CAAC;QAC5D,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,GAAG,CAAC;QAEnC,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACzE,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,gCAAgC,SAAS,iBAAiB,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;YAEpF,GAAG,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE;gBACrC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC;gBACjC,IAAI,CAAC,SAAS;oBAAE,OAAO;gBACvB,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;gBAC1D,SAAS,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE;oBAC3C,IAAI,SAAS,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;wBAClC,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;oBAC1D,CAAC;gBACL,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;YAEH,0CAA0C;YAC1C,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;gBACtC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBAChC,SAAS,CAAC,aAAa,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClG,CAAC,CAAC,CAAC;YACP,CAAC;YAED,OAAO,GAAG,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;YAC3D,OAAO,SAAS,CAAC;QACrB,CAAC;IACL,CAAC;IAED,mEAAmE;IAC3D,MAAM,CAAC,YAAY,CAAC,GAAW;QACnC,SAAS,CAAC,aAAa,EAAE,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1D,CAAC;IAEO,MAAM,CAAC,QAAQ,CAAI,GAAW;QAClC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,UAAU,EAAE,CAAC;gBACvC,MAAM,CAAC,uCAAuC,CAAC,CAAC;gBAChD,OAAO;YACX,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,cAAc,EAAE,CAAC;YAChC,EAAE,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,IAAS,CAAC,CAAC;YACnD,SAAS,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;IACP,CAAC;IAED,mEAAmE;IAEnE,wCAAwC;IACxC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAW;QAC/B,IAAI,SAAS,CAAC,aAAa,EAAE,UAAU,EAAE,CAAC;YACtC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9C,OAAO;QACX,CAAC;QACD,mCAAmC;QACnC,IAAI,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACd,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;gBAC/B,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAC;YACnE,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,MAAM,CAAC,aAAa,CAAC,IAAc;QAC/B,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,gFAAgF;IAChF,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,GAAW;QACpC,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAuB,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC;YACpF,OAAO,IAAI,CAAC,OAAO,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACL,WAAW;YACX,IAAI,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC7C,OAAO,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACL,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;IACL,CAAC;IAED,iDAAiD;IACjD,MAAM,CAAC,KAAK,CAAC,YAAY;QACrB,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAqB,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;YACjF,OAAO,IAAI,CAAC,IAAI,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,EAAE,CAAC;QACd,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,MAAM,CAAC,KAAK,CAAC,UAAU;QACnB,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAuB,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;YAChF,OAAO,IAAI,CAAC,OAAO,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED,kDAAkD;IAClD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAW;QAC7B,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAsB,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;YAChF,OAAO,IAAI,CAAC,MAAM,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACL,kCAAkC;YAClC,IAAI,CAAC;gBACD,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACL,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;IACL,CAAC;IAED,mEAAmE;IAEnE,kDAAkD;IAClD,MAAM,CAAC,WAAW;QACd,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,kDAAkD;IAClD,MAAM,CAAC,KAAK,CAAC,UAAU;QACnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAsB,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,mEAAmE;IAEnE;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAiB;QACnC,IAAI,CAAC;YACD,0BAA0B;YAC1B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAsB;gBAClD,IAAI,EAAE,WAAW;gBACjB,GAAG,EAAE,QAAQ,IAAI,aAAa;aACjC,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC,MAAM,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACL,8BAA8B;YAC9B,IAAI,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,IAAI,cAAc,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;gBAChG,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC9B,OAAO,MAAM,CAAC;YAClB,CAAC;YAAC,MAAM,CAAC;gBACL,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC7B,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;IACL,CAAC;IAED,oCAAoC;IACpC,MAAM,KAAK,YAAY;QACnB,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC"}
|
package/out/index.d.ts
CHANGED
|
@@ -8,11 +8,12 @@ export { default as Page } from './foundation/component_api/Page.js';
|
|
|
8
8
|
export { default as Component } from './foundation/component_api/Component.js';
|
|
9
9
|
export { default as Attribute } from './foundation/component_api/Attribute.js';
|
|
10
10
|
export { default as Triplet, TripletStruct, AccessType } from './foundation/Triplet.js';
|
|
11
|
-
export { ReComponent, RePage } from './foundation/TripletDecorator.js';
|
|
11
|
+
export { ReComponent, RePage, ReImplementation } from './foundation/TripletDecorator.js';
|
|
12
|
+
export { Implementation, ImplementationStruct, Placeholder } from './foundation/Injection.js';
|
|
12
13
|
export { default as Fetcher } from './foundation/Fetcher.js';
|
|
13
14
|
export * from './foundation/engine/TemplateEngine.js';
|
|
14
15
|
export { Router } from './foundation/worker/Router.js';
|
|
15
|
-
export { default as ServiceWorker } from './foundation/worker/ServiceWorker.js';
|
|
16
|
+
export { default as ServiceWorker, ServiceWorkerConfig } from './foundation/worker/ServiceWorker.js';
|
|
16
17
|
export * from './foundation/Hosting.js';
|
|
17
18
|
export * from './foundation/Theme.js';
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
package/out/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EACrB,SAAS,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAErG,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
|
package/out/index.js
CHANGED
|
@@ -6,7 +6,8 @@ export { default as Page } from './foundation/component_api/Page.js';
|
|
|
6
6
|
export { default as Component } from './foundation/component_api/Component.js';
|
|
7
7
|
export { default as Attribute } from './foundation/component_api/Attribute.js';
|
|
8
8
|
export { default as Triplet, AccessType } from './foundation/Triplet.js';
|
|
9
|
-
export { ReComponent, RePage } from './foundation/TripletDecorator.js';
|
|
9
|
+
export { ReComponent, RePage, ReImplementation } from './foundation/TripletDecorator.js';
|
|
10
|
+
export { Implementation, Placeholder } from './foundation/Injection.js';
|
|
10
11
|
export { default as Fetcher } from './foundation/Fetcher.js';
|
|
11
12
|
export * from './foundation/engine/TemplateEngine.js';
|
|
12
13
|
export { Router } from './foundation/worker/Router.js';
|
package/out/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EAC+B,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAiB,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAwB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAuB,MAAM,sCAAsC,CAAC;AAErG,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AAGtC,qEAAqE;AACrE;;WAEQ;AAER,yEAAyE"}
|
package/package.json
CHANGED
|
@@ -1,45 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HOSTING_ORIGIN } from "./Hosting.js";
|
|
2
2
|
|
|
3
|
-
// cache stores response bodies (text) by resolved URL so we can reuse them safely
|
|
4
|
-
const temporaryCache: Map<string, string> = new Map();
|
|
5
3
|
// keep in-flight promises to deduplicate concurrent identical requests
|
|
6
4
|
const inFlightText: Map<string, Promise<string>> = new Map();
|
|
7
5
|
const inFlightJSON: Map<string, Promise<any>> = new Map();
|
|
8
6
|
export default class Fetcher {
|
|
9
7
|
static async fetchText(url: string): Promise<string> {
|
|
10
8
|
const resolved = this.resolveUrl(url);
|
|
11
|
-
if (temporaryCache.has(resolved))
|
|
12
|
-
return temporaryCache.get(resolved)!;
|
|
13
9
|
|
|
14
10
|
// If a request for the same URL is already in-flight, reuse its promise
|
|
15
11
|
if (inFlightText.has(resolved)) return inFlightText.get(resolved)!;
|
|
16
12
|
|
|
17
13
|
const p = (async () => {
|
|
18
14
|
const response = await this.internalFetch(resolved);
|
|
19
|
-
|
|
20
|
-
temporaryCache.set(resolved, text);
|
|
21
|
-
return text;
|
|
15
|
+
return response.text();
|
|
22
16
|
})();
|
|
23
17
|
|
|
24
18
|
inFlightText.set(resolved, p);
|
|
25
|
-
// cleanup entry when finished
|
|
26
19
|
p.finally(() => inFlightText.delete(resolved));
|
|
27
20
|
|
|
28
21
|
return p;
|
|
29
22
|
}
|
|
30
23
|
static async fetchJSON(url: string): Promise<any> {
|
|
31
24
|
const resolved = this.resolveUrl(url);
|
|
32
|
-
if (temporaryCache.has(resolved))
|
|
33
|
-
return JSON.parse(temporaryCache.get(resolved)!);
|
|
34
25
|
|
|
35
26
|
// If a request for the same URL is already in-flight, reuse its promise
|
|
36
27
|
if (inFlightJSON.has(resolved)) return inFlightJSON.get(resolved)!;
|
|
37
28
|
|
|
38
29
|
const p = (async () => {
|
|
39
30
|
const response = await this.internalFetch(resolved);
|
|
40
|
-
|
|
41
|
-
temporaryCache.set(resolved, JSON.stringify(json));
|
|
42
|
-
return json;
|
|
31
|
+
return response.json();
|
|
43
32
|
})();
|
|
44
33
|
|
|
45
34
|
inFlightJSON.set(resolved, p);
|
|
@@ -65,6 +54,12 @@ export default class Fetcher {
|
|
|
65
54
|
}
|
|
66
55
|
|
|
67
56
|
private static async internalFetch(resolvedUrl: string): Promise<Response> {
|
|
57
|
+
// L2: check ServiceWorker CacheStorage before hitting the network
|
|
58
|
+
if ('caches' in window) {
|
|
59
|
+
const cached = await caches.match(resolvedUrl);
|
|
60
|
+
if (cached) return cached;
|
|
61
|
+
}
|
|
62
|
+
|
|
68
63
|
const response = await fetch(resolvedUrl, { cache: 'default' });
|
|
69
64
|
if (!response.ok) {
|
|
70
65
|
throw new Error(`HTTP error! ${resolvedUrl} status: ${response.status}`);
|