@reidelsaltres/pureper 0.1.49

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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -0
  3. package/out/foundation/Fetcher.d.ts +6 -0
  4. package/out/foundation/Fetcher.d.ts.map +1 -0
  5. package/out/foundation/Fetcher.js +18 -0
  6. package/out/foundation/Fetcher.js.map +1 -0
  7. package/out/foundation/Theme.d.ts +9 -0
  8. package/out/foundation/Theme.d.ts.map +1 -0
  9. package/out/foundation/Theme.js +28 -0
  10. package/out/foundation/Theme.js.map +1 -0
  11. package/out/foundation/Triplet.d.ts +44 -0
  12. package/out/foundation/Triplet.d.ts.map +1 -0
  13. package/out/foundation/Triplet.js +174 -0
  14. package/out/foundation/Triplet.js.map +1 -0
  15. package/out/foundation/api/ElementHolder.d.ts +4 -0
  16. package/out/foundation/api/ElementHolder.d.ts.map +1 -0
  17. package/out/foundation/api/ElementHolder.js +2 -0
  18. package/out/foundation/api/ElementHolder.js.map +1 -0
  19. package/out/foundation/api/EmptyConstructor.d.ts +7 -0
  20. package/out/foundation/api/EmptyConstructor.d.ts.map +1 -0
  21. package/out/foundation/api/EmptyConstructor.js +2 -0
  22. package/out/foundation/api/EmptyConstructor.js.map +1 -0
  23. package/out/foundation/api/Lazy.d.ts +7 -0
  24. package/out/foundation/api/Lazy.d.ts.map +1 -0
  25. package/out/foundation/api/Lazy.js +12 -0
  26. package/out/foundation/api/Lazy.js.map +1 -0
  27. package/out/foundation/component_api/Component.d.ts +58 -0
  28. package/out/foundation/component_api/Component.d.ts.map +1 -0
  29. package/out/foundation/component_api/Component.js +61 -0
  30. package/out/foundation/component_api/Component.js.map +1 -0
  31. package/out/foundation/component_api/Page.d.ts +8 -0
  32. package/out/foundation/component_api/Page.d.ts.map +1 -0
  33. package/out/foundation/component_api/Page.js +8 -0
  34. package/out/foundation/component_api/Page.js.map +1 -0
  35. package/out/foundation/component_api/UniHtml.d.ts +43 -0
  36. package/out/foundation/component_api/UniHtml.d.ts.map +1 -0
  37. package/out/foundation/component_api/UniHtml.js +67 -0
  38. package/out/foundation/component_api/UniHtml.js.map +1 -0
  39. package/out/foundation/component_api/mixin/Proto.d.ts +33 -0
  40. package/out/foundation/component_api/mixin/Proto.d.ts.map +1 -0
  41. package/out/foundation/component_api/mixin/Proto.js +43 -0
  42. package/out/foundation/component_api/mixin/Proto.js.map +1 -0
  43. package/out/foundation/worker/Router.d.ts +31 -0
  44. package/out/foundation/worker/Router.d.ts.map +1 -0
  45. package/out/foundation/worker/Router.js +95 -0
  46. package/out/foundation/worker/Router.js.map +1 -0
  47. package/out/foundation/worker/ServiceWorker.d.ts +25 -0
  48. package/out/foundation/worker/ServiceWorker.d.ts.map +1 -0
  49. package/out/foundation/worker/ServiceWorker.js +141 -0
  50. package/out/foundation/worker/ServiceWorker.js.map +1 -0
  51. package/out/foundation/worker/api/Clients.d.ts +4 -0
  52. package/out/foundation/worker/api/Clients.d.ts.map +1 -0
  53. package/out/foundation/worker/api/Clients.js +2 -0
  54. package/out/foundation/worker/api/Clients.js.map +1 -0
  55. package/out/foundation/worker/api/ExtendableEvent.d.ts +4 -0
  56. package/out/foundation/worker/api/ExtendableEvent.d.ts.map +1 -0
  57. package/out/foundation/worker/api/ExtendableEvent.js +2 -0
  58. package/out/foundation/worker/api/ExtendableEvent.js.map +1 -0
  59. package/out/foundation/worker/api/ExtendableMessageEvent.d.ts +6 -0
  60. package/out/foundation/worker/api/ExtendableMessageEvent.d.ts.map +1 -0
  61. package/out/foundation/worker/api/ExtendableMessageEvent.js +2 -0
  62. package/out/foundation/worker/api/ExtendableMessageEvent.js.map +1 -0
  63. package/out/foundation/worker/api/FetchEvent.d.ts +6 -0
  64. package/out/foundation/worker/api/FetchEvent.d.ts.map +1 -0
  65. package/out/foundation/worker/api/FetchEvent.js +2 -0
  66. package/out/foundation/worker/api/FetchEvent.js.map +1 -0
  67. package/out/foundation/worker/api/ServiceWorkerGlobalScope.d.ts +14 -0
  68. package/out/foundation/worker/api/ServiceWorkerGlobalScope.d.ts.map +1 -0
  69. package/out/foundation/worker/api/ServiceWorkerGlobalScope.js +2 -0
  70. package/out/foundation/worker/api/ServiceWorkerGlobalScope.js.map +1 -0
  71. package/out/index.d.ts +13 -0
  72. package/out/index.d.ts.map +1 -0
  73. package/out/index.js +11 -0
  74. package/out/index.js.map +1 -0
  75. package/package.json +39 -0
  76. package/src/foundation/Fetcher.ts +20 -0
  77. package/src/foundation/Theme.ts +37 -0
  78. package/src/foundation/Triplet.ts +208 -0
  79. package/src/foundation/api/ElementHolder.ts +3 -0
  80. package/src/foundation/api/EmptyConstructor.ts +6 -0
  81. package/src/foundation/api/Lazy.ts +12 -0
  82. package/src/foundation/component_api/Component.ts +92 -0
  83. package/src/foundation/component_api/Page.ts +9 -0
  84. package/src/foundation/component_api/UniHtml.ts +82 -0
  85. package/src/foundation/component_api/mixin/Proto.ts +67 -0
  86. package/src/foundation/worker/Router.ts +124 -0
  87. package/src/foundation/worker/ServiceWorker.ts +160 -0
  88. package/src/foundation/worker/api/Clients.ts +3 -0
  89. package/src/foundation/worker/api/ExtendableEvent.ts +3 -0
  90. package/src/foundation/worker/api/ExtendableMessageEvent.ts +6 -0
  91. package/src/foundation/worker/api/FetchEvent.ts +6 -0
  92. package/src/foundation/worker/api/ServiceWorkerGlobalScope.ts +14 -0
  93. package/src/index.ts +22 -0
@@ -0,0 +1,124 @@
1
+ // Add RouterConfig type to window for TypeScript
2
+ declare global {
3
+ interface Window {
4
+ RouterConfig?: { ASSET_PATH: string };
5
+ }
6
+ }
7
+ import { AnyConstructor } from "../component_api/mixin/Proto";
8
+ import Page from "../component_api/Page";
9
+ import UniHtml from "../component_api/UniHtml.js";
10
+ import { ServiceWorkerGlobalScope } from "./api/ServiceWorkerGlobalScope";
11
+
12
+ const globals = self as any as ServiceWorkerGlobalScope;
13
+
14
+ export interface Route<T extends UniHtml = UniHtml> {
15
+ route: string;
16
+ path: string;
17
+
18
+ pageFactory: (search?: URLSearchParams) => T;
19
+ }
20
+ export enum AccessType {
21
+ OFFLINE,
22
+ ONLINE,
23
+ BOTH
24
+ }
25
+
26
+ export const ROUTES: Route[] = [];
27
+ export const TO_CACHE: string[] = [];
28
+
29
+ export abstract class Router {
30
+ public static savePersistedRoute(url: URL) {
31
+ try {
32
+ sessionStorage.setItem("spa:persisted-route", url.toJSON());
33
+ } catch (error) {
34
+ console.warn("[Router Init]: Unable to access sessionStorage.", error);
35
+ }
36
+ }
37
+ public static getPersistedRoute(): URL | null {
38
+ try {
39
+ const item = sessionStorage.getItem("spa:persisted-route");
40
+ return item ? URL.parse(item) : null;
41
+ } catch (error) {
42
+ console.warn("[Router Init]: Unable to access sessionStorage.", error);
43
+ return null;
44
+ }
45
+ }
46
+ public static clearPersistedRoute() {
47
+ try {
48
+ sessionStorage.removeItem("spa:persisted-route");
49
+ } catch (error) {
50
+ console.warn("[Router Init]: Unable to clear persisted route.", error);
51
+ }
52
+ }
53
+
54
+
55
+ public static legacyRouteTo(route: string) {
56
+ let url = new URL(route, window.location.origin);
57
+ if (window.location.pathname !== route) {
58
+ window.location.replace(url.href);
59
+ }
60
+ }
61
+ public static tryRouteTo(url: URL) {
62
+ try {
63
+ const found: Route = this.tryFindRoute(url);
64
+ const page: UniHtml = this.createPage(found, url.searchParams);
65
+
66
+ page.load(document.getElementById('page')!);
67
+
68
+ if (typeof window !== "undefined" && window.location) {
69
+ window.history.pushState(page, '', url.href);
70
+ }
71
+ } catch (error) {
72
+ console.error("[Router]: Unable to route to ", url.href, error);
73
+ }
74
+ }
75
+ public static tryFindRoute(url: URL): Route {
76
+ const found = ROUTES.find(r => r.route === url.pathname);
77
+ if (!found) {
78
+ throw new Error(`[Router]: Route not found: ${url.pathname}`);
79
+ }
80
+ return found;
81
+ }
82
+
83
+ public static async registerRoute<T extends UniHtml>(path: string, route: string, pageFactory: (search?: URLSearchParams) => T,
84
+ inheritedRoute?: Route): Promise<Route> {
85
+
86
+ let prepRoute = route
87
+ let fullRoute = inheritedRoute ? inheritedRoute.route + prepRoute : prepRoute;
88
+
89
+ let routeObj: Route = { route: fullRoute, path, pageFactory };
90
+
91
+ ROUTES.push(routeObj);
92
+ console.log(`[Router]: Registered route: ${fullRoute} -> ${path}`);
93
+
94
+ return Promise.resolve(routeObj);
95
+ }
96
+
97
+
98
+ private static createPage(route: Route, search?: URLSearchParams): UniHtml {
99
+ return route.pageFactory(search);
100
+ }
101
+ }
102
+
103
+ document.addEventListener('click', e => {
104
+ const target = e.target as Element | null;
105
+ if (target) {
106
+ const link = target.closest('a[data-link]') ?? target.closest('re-button[data-link]');
107
+ if (link) {
108
+ e.preventDefault();
109
+ const url : URL = new URL(link.getAttribute('href')!, window.location.origin);
110
+ Router.tryRouteTo(url);
111
+ }
112
+ }
113
+ });
114
+
115
+ window.addEventListener('DOMContentLoaded', () => {
116
+ const checkRoutes = () => {
117
+ const routes = ROUTES;
118
+ if (routes) {
119
+ console.log('[Init] [Router]: available routes =', routes.map(r => r.route).join(', '));
120
+ }
121
+ };
122
+
123
+ checkRoutes();
124
+ });
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Service Worker for Pureper SPA
3
+ * Handles client-side routing by intercepting navigation requests
4
+ * and serving index.html for all SPA routes
5
+ */
6
+ import type { ExtendableEvent } from './api/ExtendableEvent';
7
+ import type { FetchEvent } from './api/FetchEvent';
8
+ import type { ExtendableMessageEvent } from './api/ExtendableMessageEvent';
9
+ import type { Clients } from './api/Clients';
10
+ import type { ServiceWorkerGlobalScope } from './api/ServiceWorkerGlobalScope';
11
+
12
+ // Type assertion for Service Worker context
13
+ declare let self: ServiceWorkerGlobalScope
14
+ const swSelf = self;
15
+
16
+ // Автоматически генерируем CACHE_NAME из base.json
17
+ //import base from '../../../data/base.json';
18
+ const CACHE_NAME = `pureper-v1`;
19
+
20
+ const BASE_PATH = '/Pureper'; // GitHub Pages base path
21
+ const IS_GITHUB_PAGES = swSelf.location.hostname.includes('github.io');
22
+
23
+ const STATIC_ASSETS: string[] = [
24
+ '/index.html'
25
+ ];
26
+
27
+ if ('serviceWorker' in navigator) {
28
+ window.addEventListener('load', () => {
29
+ navigator.serviceWorker.register('../out/src/foundation/worker/ServiceWorker.js', { type: 'module' })
30
+ .then((registration) => {
31
+ console.log('ServiceWorker registration successful:', registration.scope);
32
+ })
33
+ .catch((error) => {
34
+ console.error('ServiceWorker registration failed:', error);
35
+ });
36
+ });
37
+ window.addEventListener('fetch', (event: FetchEvent) => {
38
+ event.respondWith(
39
+ caches.match(event.request).then((cachedResponse) => {
40
+ console.log(`[ServiceWorker]: Fetching ${event.request.url}`);
41
+ return cachedResponse || fetch(event.request);
42
+ })
43
+ );
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Install event - cache static assets
49
+ */
50
+ window.addEventListener('install', (event: ExtendableEvent) => {
51
+ console.log('ServiceWorker: Installing...');
52
+ const assetsToCache = [
53
+ ...STATIC_ASSETS
54
+ ];
55
+ // Remove duplicates
56
+ const uniqueAssets = Array.from(new Set(assetsToCache));
57
+ event.waitUntil(
58
+ caches.open(CACHE_NAME)
59
+ .then((cache: Cache) => {
60
+ console.log('ServiceWorker: Caching static assets and SPA routes');
61
+ return cache.addAll(uniqueAssets);
62
+ })
63
+ .then(() => {
64
+ console.log('ServiceWorker: Installation complete');
65
+ return swSelf.skipWaiting();
66
+ })
67
+ );
68
+ });
69
+
70
+ export default class ServiceWorker {
71
+ /**
72
+ * Sends a message to the service worker to cache a specific URL.
73
+ * @param url The URL of the resource to cache.
74
+ */
75
+ static async addToCache(url: string): Promise<void> {
76
+ if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
77
+ navigator.serviceWorker.controller.postMessage({
78
+ type: 'CACHE_URL',
79
+ url: url
80
+ });
81
+ } else {
82
+ // Fallback: try to cache directly using the Cache API
83
+ try {
84
+ const cache = await caches.open('pureper-v1');
85
+ const response = await fetch(url);
86
+ if (response.ok) {
87
+ await cache.put(url, response);
88
+ console.log('[ServiceWorker]: Resource cached directly:', url);
89
+ }
90
+ } catch (e) {
91
+ console.warn('[ServiceWorker]: Failed to cache resource:', url, e);
92
+ }
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Asks the service worker to skip waiting and activate the new version.
98
+ */
99
+ static skipWaiting(): void {
100
+ if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
101
+ navigator.serviceWorker.controller.postMessage({ type: 'SKIP_WAITING' });
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Gets the version of the currently active service worker.
107
+ * @returns A promise that resolves with the version string.
108
+ */
109
+ static getVersion(): Promise<string> {
110
+ return new Promise((resolve, reject) => {
111
+ if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
112
+ const messageChannel = new MessageChannel();
113
+ messageChannel.port1.onmessage = (event) => {
114
+ if (event.data.error) {
115
+ reject(event.data.error);
116
+ } else {
117
+ resolve(event.data.version);
118
+ }
119
+ };
120
+ navigator.serviceWorker.controller.postMessage({ type: 'GET_VERSION' }, [messageChannel.port2]);
121
+ } else {
122
+ reject('Service worker not available.');
123
+ }
124
+ });
125
+ }
126
+
127
+ /**
128
+ * Checks if the given URL is present in the Service Worker's cache.
129
+ */
130
+ static isCached(url: string): Promise<boolean> {
131
+ return new Promise((resolve) => {
132
+ if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
133
+ const mc = new MessageChannel();
134
+ mc.port1.onmessage = (ev) => {
135
+ if (ev.data && typeof ev.data.cached === 'boolean') {
136
+ resolve(ev.data.cached);
137
+ } else {
138
+ resolve(false);
139
+ }
140
+ };
141
+ navigator.serviceWorker.controller.postMessage({ type: 'HAS_URL', url }, [mc.port2]);
142
+ } else {
143
+ // Fallback: try CacheStorage directly (same-origin only)
144
+ caches.match(url).then(match => resolve(!!match)).catch(() => resolve(false));
145
+ }
146
+ });
147
+ }
148
+
149
+ /**
150
+ * Checks if the browser is online.
151
+ */
152
+ static async isOnline(): Promise<boolean> {
153
+ try {
154
+ const response = await fetch('./index.html', { cache: 'no-store' });
155
+ return response && response.ok;
156
+ } catch {
157
+ return false;
158
+ }
159
+ }
160
+ }
@@ -0,0 +1,3 @@
1
+ export interface Clients {
2
+ claim(): Promise<void>;
3
+ }
@@ -0,0 +1,3 @@
1
+ export interface ExtendableEvent extends Event {
2
+ waitUntil(promise: Promise<any>): void;
3
+ }
@@ -0,0 +1,6 @@
1
+ import { ExtendableEvent } from './ExtendableEvent';
2
+
3
+ export interface ExtendableMessageEvent extends ExtendableEvent {
4
+ data: any;
5
+ ports: MessagePort[];
6
+ }
@@ -0,0 +1,6 @@
1
+ import { ExtendableEvent } from './ExtendableEvent';
2
+
3
+ export interface FetchEvent extends ExtendableEvent {
4
+ request: Request;
5
+ respondWith(response: Promise<Response> | Response): void;
6
+ }
@@ -0,0 +1,14 @@
1
+ import { Clients } from './Clients';
2
+ import { ExtendableEvent } from './ExtendableEvent';
3
+ import { FetchEvent } from './FetchEvent';
4
+ import { ExtendableMessageEvent } from './ExtendableMessageEvent';
5
+
6
+ export interface ServiceWorkerGlobalScope {
7
+ skipWaiting(): Promise<void>;
8
+ clients: Clients;
9
+ location: Location;
10
+ addEventListener(type: 'install', listener: (event: ExtendableEvent) => void): void;
11
+ addEventListener(type: 'activate', listener: (event: ExtendableEvent) => void): void;
12
+ addEventListener(type: 'fetch', listener: (event: FetchEvent) => void): void;
13
+ addEventListener(type: 'message', listener: (event: ExtendableMessageEvent) => void): void;
14
+ }
package/src/index.ts ADDED
@@ -0,0 +1,22 @@
1
+ // Public package entry — re-export foundation APIs
2
+ export { default as ElementHolder } from './foundation/api/ElementHolder';
3
+ export { default as EmptyConstructor } from './foundation/api/EmptyConstructor';
4
+ export { default as Lazy } from './foundation/api/Lazy';
5
+
6
+ export * from './foundation/component_api/mixin/Proto';
7
+
8
+ export { default as UniHtml } from './foundation/component_api/UniHtml';
9
+ export { default as Page } from './foundation/component_api/Page';
10
+ export { default as Component } from './foundation/component_api/Component';
11
+
12
+ export { default as Triplet } from './foundation/Triplet';
13
+
14
+ export { default as Fetcher } from './foundation/Fetcher';
15
+
16
+
17
+ export { Router } from './foundation/worker/Router';
18
+ export { default as ServiceWorker } from './foundation/worker/ServiceWorker';
19
+
20
+
21
+
22
+ export * from './foundation/Theme';