valyrian.js 7.2.11 → 8.0.0

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 (165) hide show
  1. package/README.md +6 -6
  2. package/dist/flux-store/index.d.ts +32 -0
  3. package/dist/flux-store/index.d.ts.map +1 -0
  4. package/dist/flux-store/index.js +258 -0
  5. package/dist/flux-store/index.js.map +7 -0
  6. package/dist/flux-store/index.min.js +1 -0
  7. package/dist/flux-store/index.min.js.map +1 -0
  8. package/dist/flux-store/index.mjs +237 -0
  9. package/dist/flux-store/index.mjs.map +7 -0
  10. package/dist/hooks/index.d.ts.map +1 -1
  11. package/dist/hooks/index.js +42 -75
  12. package/dist/hooks/index.js.map +2 -2
  13. package/dist/hooks/index.min.js +1 -0
  14. package/dist/hooks/index.min.js.map +1 -0
  15. package/dist/hooks/index.mjs +43 -76
  16. package/dist/hooks/index.mjs.map +2 -2
  17. package/dist/index.d.ts +52 -54
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +397 -328
  20. package/dist/index.js.map +3 -3
  21. package/dist/index.min.js +1 -1
  22. package/dist/index.min.js.map +1 -1
  23. package/dist/index.mjs +397 -328
  24. package/dist/index.mjs.map +3 -3
  25. package/dist/native-store/index.d.ts +14 -0
  26. package/dist/native-store/index.d.ts.map +1 -0
  27. package/dist/native-store/index.js +103 -0
  28. package/dist/native-store/index.js.map +7 -0
  29. package/dist/native-store/index.min.js +1 -0
  30. package/dist/native-store/index.min.js.map +1 -0
  31. package/dist/native-store/index.mjs +82 -0
  32. package/dist/native-store/index.mjs.map +7 -0
  33. package/dist/node/index.d.ts.map +1 -1
  34. package/dist/node/index.js +223 -86
  35. package/dist/node/index.js.map +4 -4
  36. package/dist/node/index.mjs +223 -86
  37. package/dist/node/index.mjs.map +4 -4
  38. package/dist/node/node.sw.js +152 -0
  39. package/dist/node/utils/inline.d.ts.map +1 -1
  40. package/dist/node/utils/node.sw.js +152 -0
  41. package/dist/node/utils/session-storage.d.ts +22 -0
  42. package/dist/node/utils/session-storage.d.ts.map +1 -0
  43. package/dist/node/utils/sw.d.ts.map +1 -1
  44. package/dist/node/utils/tree-adapter.d.ts +9 -0
  45. package/dist/node/utils/tree-adapter.d.ts.map +1 -1
  46. package/dist/pulse-store/index.d.ts +13 -0
  47. package/dist/pulse-store/index.d.ts.map +1 -0
  48. package/dist/pulse-store/index.js +143 -0
  49. package/dist/pulse-store/index.js.map +7 -0
  50. package/dist/pulse-store/index.min.js +1 -0
  51. package/dist/pulse-store/index.min.js.map +1 -0
  52. package/dist/pulse-store/index.mjs +122 -0
  53. package/dist/pulse-store/index.mjs.map +7 -0
  54. package/dist/request/index.d.ts.map +1 -1
  55. package/dist/request/index.js +68 -89
  56. package/dist/request/index.js.map +2 -2
  57. package/dist/request/index.min.js +1 -0
  58. package/dist/request/index.min.js.map +1 -0
  59. package/dist/request/index.mjs +68 -89
  60. package/dist/request/index.mjs.map +2 -2
  61. package/dist/router/index.d.ts +32 -31
  62. package/dist/router/index.d.ts.map +1 -1
  63. package/dist/router/index.js +256 -104
  64. package/dist/router/index.js.map +3 -3
  65. package/dist/router/index.min.js +1 -0
  66. package/dist/router/index.min.js.map +1 -0
  67. package/dist/router/index.mjs +256 -104
  68. package/dist/router/index.mjs.map +3 -3
  69. package/dist/signals/index.d.ts +6 -0
  70. package/dist/signals/index.d.ts.map +1 -0
  71. package/dist/signals/index.js +92 -0
  72. package/dist/signals/index.js.map +7 -0
  73. package/dist/signals/index.min.js +1 -0
  74. package/dist/signals/index.min.js.map +1 -0
  75. package/dist/signals/index.mjs +71 -0
  76. package/dist/signals/index.mjs.map +7 -0
  77. package/dist/suspense/index.d.ts +6 -0
  78. package/dist/suspense/index.d.ts.map +1 -0
  79. package/dist/suspense/index.js +67 -0
  80. package/dist/suspense/index.js.map +7 -0
  81. package/dist/suspense/index.min.js +1 -0
  82. package/dist/suspense/index.min.js.map +1 -0
  83. package/dist/suspense/index.mjs +46 -0
  84. package/dist/suspense/index.mjs.map +7 -0
  85. package/dist/sw/index.min.js +1 -0
  86. package/dist/sw/index.min.js.map +1 -0
  87. package/dist/translate/index.d.ts +19 -0
  88. package/dist/translate/index.d.ts.map +1 -0
  89. package/dist/translate/index.js +150 -0
  90. package/dist/translate/index.js.map +7 -0
  91. package/dist/translate/index.min.js +1 -0
  92. package/dist/translate/index.min.js.map +1 -0
  93. package/dist/translate/index.mjs +129 -0
  94. package/dist/translate/index.mjs.map +7 -0
  95. package/dist/tsconfig.tsbuildinfo +1 -1
  96. package/dist/utils/deep-freeze.d.ts +3 -0
  97. package/dist/utils/deep-freeze.d.ts.map +1 -0
  98. package/dist/utils/getter-setter.d.ts +3 -0
  99. package/dist/utils/getter-setter.d.ts.map +1 -0
  100. package/dist/utils/has-changed.d.ts +2 -0
  101. package/dist/utils/has-changed.d.ts.map +1 -0
  102. package/dist/utils/index.d.ts +4 -0
  103. package/dist/utils/index.d.ts.map +1 -0
  104. package/dist/utils/index.js +138 -0
  105. package/dist/utils/index.js.map +7 -0
  106. package/dist/utils/index.min.js +1 -0
  107. package/dist/utils/index.min.js.map +1 -0
  108. package/dist/utils/index.mjs +115 -0
  109. package/dist/utils/index.mjs.map +7 -0
  110. package/lib/flux-store/index.ts +301 -0
  111. package/lib/hooks/index.ts +52 -101
  112. package/lib/index.ts +479 -719
  113. package/lib/native-store/index.ts +106 -0
  114. package/lib/node/index.ts +5 -3
  115. package/lib/node/utils/icons.ts +5 -5
  116. package/lib/node/utils/inline.ts +17 -17
  117. package/lib/node/utils/node.sw.js +152 -0
  118. package/lib/node/utils/session-storage.ts +117 -0
  119. package/lib/node/utils/sw.ts +35 -11
  120. package/lib/node/utils/tree-adapter.ts +99 -52
  121. package/lib/pulse-store/index.ts +181 -0
  122. package/lib/request/index.ts +86 -116
  123. package/lib/router/index.ts +358 -170
  124. package/lib/signals/index.ts +98 -0
  125. package/lib/suspense/index.ts +57 -0
  126. package/lib/translate/index.ts +156 -0
  127. package/lib/utils/deep-freeze.ts +54 -0
  128. package/lib/utils/getter-setter.ts +40 -0
  129. package/lib/utils/has-changed.ts +43 -0
  130. package/lib/utils/index.ts +3 -0
  131. package/package.json +38 -50
  132. package/tsconfig.json +1 -1
  133. package/dist/dataset/index.d.ts +0 -24
  134. package/dist/dataset/index.d.ts.map +0 -1
  135. package/dist/dataset/index.js +0 -178
  136. package/dist/dataset/index.js.map +0 -7
  137. package/dist/dataset/index.mjs +0 -157
  138. package/dist/dataset/index.mjs.map +0 -7
  139. package/dist/node/node.sw.tpl +0 -133
  140. package/dist/node/utils/node.sw.tpl +0 -133
  141. package/dist/proxy-signal/index.d.ts +0 -23
  142. package/dist/proxy-signal/index.d.ts.map +0 -1
  143. package/dist/proxy-signal/index.js +0 -138
  144. package/dist/proxy-signal/index.js.map +0 -7
  145. package/dist/proxy-signal/index.mjs +0 -117
  146. package/dist/proxy-signal/index.mjs.map +0 -7
  147. package/dist/signal/index.d.ts +0 -20
  148. package/dist/signal/index.d.ts.map +0 -1
  149. package/dist/signal/index.js +0 -95
  150. package/dist/signal/index.js.map +0 -7
  151. package/dist/signal/index.mjs +0 -74
  152. package/dist/signal/index.mjs.map +0 -7
  153. package/dist/store/index.d.ts +0 -16
  154. package/dist/store/index.d.ts.map +0 -1
  155. package/dist/store/index.js +0 -93
  156. package/dist/store/index.js.map +0 -7
  157. package/dist/store/index.mjs +0 -72
  158. package/dist/store/index.mjs.map +0 -7
  159. package/lib/dataset/index.ts +0 -193
  160. package/lib/index.d.ts +0 -0
  161. package/lib/interfaces.ts.bak +0 -141
  162. package/lib/node/utils/node.sw.tpl +0 -133
  163. package/lib/proxy-signal/index.ts +0 -187
  164. package/lib/signal/index.ts +0 -161
  165. package/lib/store/index.ts +0 -101
@@ -0,0 +1,106 @@
1
+ import { isNodeJs } from "valyrian.js";
2
+
3
+ /* eslint-disable no-console */
4
+ export enum StorageType {
5
+ // eslint-disable-next-line no-unused-vars
6
+ Session = "session",
7
+ // eslint-disable-next-line no-unused-vars
8
+ Local = "local"
9
+ }
10
+
11
+ export interface NativeStorageInterface {
12
+ state: Record<string, any>;
13
+ // eslint-disable-next-line no-unused-vars
14
+ set(key: string, value: any): void;
15
+ // eslint-disable-next-line no-unused-vars
16
+ get(key: string): any;
17
+ // eslint-disable-next-line no-unused-vars
18
+ delete(key: string): void;
19
+ load(): void;
20
+ clear(): void;
21
+ }
22
+
23
+ const ids = new Set<string>();
24
+
25
+ function getStorage(storageType: StorageType) {
26
+ if (isNodeJs && typeof localStorage === "undefined") {
27
+ throw new Error(
28
+ `localStorage and sessionStorage are not available in Node.js, to use it in your project, you need to "import "valyrian.js/node"`
29
+ );
30
+ }
31
+ return storageType === StorageType.Session ? sessionStorage : localStorage;
32
+ }
33
+
34
+ export function createNativeStore<T>(
35
+ key: string,
36
+ definition: Record<string, any> = {},
37
+ storageType: StorageType = StorageType.Local,
38
+ reuseIfExist = false
39
+ ): NativeStorageInterface & T {
40
+ const nativeStore = getStorage(storageType);
41
+
42
+ if (ids.has(key)) {
43
+ if (reuseIfExist) {
44
+ // eslint-disable-next-line no-console
45
+ console.warn(`Store with key ${key} already exists and will be reused`);
46
+ } else {
47
+ throw new Error(`Store with key ${key} already exists`);
48
+ }
49
+ }
50
+ ids.add(key);
51
+
52
+ const id = key;
53
+
54
+ const Store: NativeStorageInterface = {
55
+ state: {},
56
+ set(key, value) {
57
+ try {
58
+ this.state[key] = value;
59
+ nativeStore.setItem(id, JSON.stringify(this.state));
60
+ } catch (e) {
61
+ console.error("Error setting item in storage:", e);
62
+ }
63
+ },
64
+ get(key) {
65
+ if (Object.keys(this.state).length === 0) {
66
+ this.load();
67
+ }
68
+ return this.state[key];
69
+ },
70
+ delete(key) {
71
+ try {
72
+ Reflect.deleteProperty(this.state, key);
73
+ nativeStore.setItem(id, JSON.stringify(this.state));
74
+ } catch (e) {
75
+ console.error("Error deleting item in storage:", e);
76
+ }
77
+ },
78
+ load() {
79
+ try {
80
+ const state = nativeStore.getItem(id);
81
+ if (!state) {
82
+ this.state = {};
83
+ nativeStore.setItem(id, JSON.stringify(this.state));
84
+ return;
85
+ }
86
+ this.state = JSON.parse(state);
87
+ } catch (e) {
88
+ console.error("Error loading state from storage:", e);
89
+ this.state = {};
90
+ }
91
+ },
92
+ clear() {
93
+ try {
94
+ this.state = {};
95
+ nativeStore.removeItem(id);
96
+ } catch (e) {
97
+ console.error("Error clearing storage:", e);
98
+ }
99
+ },
100
+ ...definition
101
+ };
102
+
103
+ Store.load();
104
+
105
+ return Store as NativeStorageInterface & T;
106
+ }
package/lib/node/index.ts CHANGED
@@ -2,17 +2,19 @@ import { document, domToHtml, domToHyperscript, htmlToDom, htmlToHyperscript } f
2
2
  import { mount, unmount } from "valyrian.js";
3
3
 
4
4
  import FormData from "form-data";
5
- // import fetch from "node-fetch";
6
5
  import { icons } from "./utils/icons";
7
6
  import { inline } from "./utils/inline";
8
7
  import { sw } from "./utils/sw";
8
+ import { SessionStorage } from "./utils/session-storage";
9
9
 
10
10
  global.FormData = FormData as any;
11
11
  global.document = document as any;
12
+ global.sessionStorage = new SessionStorage();
13
+ global.localStorage = new SessionStorage();
12
14
 
13
15
  function render(...args: any[]) {
14
- let Component = () => args;
15
- let result = mount("div", Component);
16
+ const Component = () => args;
17
+ const result = mount("div", Component);
16
18
  unmount();
17
19
  return result;
18
20
  }
@@ -33,7 +33,7 @@ interface IconsOptions {
33
33
  }
34
34
 
35
35
  export async function icons(source: string, configuration?: IconsOptions) {
36
- let options = {
36
+ const options = {
37
37
  ...icons.options,
38
38
  ...(configuration || {})
39
39
  };
@@ -49,20 +49,20 @@ export async function icons(source: string, configuration?: IconsOptions) {
49
49
  const { favicons } = await import("favicons");
50
50
 
51
51
  try {
52
- let response = await favicons(source, options);
52
+ const response = await favicons(source, options);
53
53
 
54
54
  if (options.iconsPath) {
55
- for (let i in response.images) {
55
+ for (const i in response.images) {
56
56
  fs.writeFileSync(options.iconsPath + response.images[i].name, response.images[i].contents);
57
57
  }
58
58
 
59
- for (let i in response.files) {
59
+ for (const i in response.files) {
60
60
  fs.writeFileSync(options.iconsPath + response.files[i].name, response.files[i].contents);
61
61
  }
62
62
  }
63
63
 
64
64
  if (options.linksViewPath) {
65
- let html = `
65
+ const html = `
66
66
  function Links(){
67
67
  return ${htmlToHyperscript(response.html.join(""))};
68
68
  }
@@ -12,13 +12,13 @@ export async function inline(
12
12
  options: Record<string, any> = {}
13
13
  ) {
14
14
  if (typeof file === "string") {
15
- let ext = file.split(".").pop();
15
+ const ext = file.split(".").pop();
16
16
  if (ext && /(js|cjs|jsx|mjs|ts|tsx)/.test(ext)) {
17
17
  if (/(ts|tsx)/.test(ext) && !options.noValidate) {
18
- let declarationDir = options.declarationDir;
19
- let emitDeclaration = !!declarationDir;
18
+ const declarationDir = options.declarationDir;
19
+ const emitDeclaration = !!declarationDir;
20
20
 
21
- let tscProgOptions = {
21
+ const tscProgOptions = {
22
22
  basePath: process.cwd(), // always required, used for relative paths
23
23
  configFilePath: "tsconfig.json", // config to inherit from (optional)
24
24
  files: [file],
@@ -53,7 +53,7 @@ export async function inline(
53
53
  tsc.build(tscProgOptions);
54
54
  }
55
55
 
56
- let esbuildOptions = {
56
+ const esbuildOptions = {
57
57
  entryPoints: [file],
58
58
  bundle: "bundle" in options ? options.bundle : true,
59
59
  sourcemap: "external",
@@ -72,14 +72,14 @@ export async function inline(
72
72
  ...(options.esbuild || {})
73
73
  };
74
74
 
75
- let result = await esbuild.build(esbuildOptions);
75
+ const result = await esbuild.build(esbuildOptions);
76
76
  if (result.outputFiles?.length !== 2) {
77
77
  throw new Error(result.errors.join("\n"));
78
78
  }
79
79
 
80
80
  if (options.compact) {
81
81
  const terser = await import("terser");
82
- let result2 = await terser.minify(result.outputFiles[1].text, {
82
+ const result2 = await terser.minify(result.outputFiles[1].text, {
83
83
  sourceMap: {
84
84
  content: result.outputFiles[0].text.toString()
85
85
  },
@@ -97,16 +97,16 @@ export async function inline(
97
97
  throw new Error("Unknown error");
98
98
  }
99
99
 
100
- let mapBase64 = Buffer.from(result2.map.toString()).toString("base64");
101
- let suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`;
100
+ const mapBase64 = Buffer.from(result2.map.toString()).toString("base64");
101
+ const suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`;
102
102
  return { raw: result2.code, map: suffix, file };
103
103
  } else {
104
- let mapBase64 = Buffer.from(result.outputFiles[0].text.toString()).toString("base64");
105
- let suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`;
104
+ const mapBase64 = Buffer.from(result.outputFiles[0].text.toString()).toString("base64");
105
+ const suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`;
106
106
  return { raw: result.outputFiles[1].text, map: suffix, file };
107
107
  }
108
108
  } else if (ext && /(css|scss|styl)/.test(ext)) {
109
- let result = await new CleanCSS({
109
+ const result = await new CleanCSS({
110
110
  sourceMap: true,
111
111
  level: {
112
112
  1: {
@@ -133,18 +133,18 @@ inline.uncss = async function (
133
133
  css: string,
134
134
  options: Record<string, any> = {}
135
135
  ) {
136
- let html = await Promise.all(renderedHtml);
136
+ const html = await Promise.all(renderedHtml);
137
137
 
138
- let contents = html.map((item) => {
138
+ const contents = html.map((item) => {
139
139
  return {
140
140
  raw: item,
141
141
  extension: "html"
142
142
  };
143
143
  });
144
144
 
145
- let purgecss = new PurgeCSS();
145
+ const purgecss = new PurgeCSS();
146
146
 
147
- let output = await purgecss.purge({
147
+ const output = await purgecss.purge({
148
148
  fontFace: true,
149
149
  keyframes: true,
150
150
  variables: true,
@@ -154,7 +154,7 @@ inline.uncss = async function (
154
154
  css: [{ raw: css }]
155
155
  });
156
156
 
157
- let cleanCss = await new CleanCSS({
157
+ const cleanCss = await new CleanCSS({
158
158
  sourceMap: false,
159
159
  level: {
160
160
  1: {
@@ -0,0 +1,152 @@
1
+ // eslint-disable-next-line no-console
2
+ const Log = console.log;
3
+
4
+ const config = {
5
+ version: "v1.2::",
6
+ name: "Valyrian.js",
7
+ // Critical resources and offline page
8
+ urls: ["/"]
9
+ };
10
+
11
+ const cacheName = config.version + config.name;
12
+ const MAX_CACHE_SIZE = 50; // Max cache size
13
+
14
+ // Send messages to clients (controlled pages)
15
+ function sendMessageToClients(message) {
16
+ self.clients.matchAll().then((clients) => {
17
+ clients.forEach((client) => {
18
+ client.postMessage(message);
19
+ });
20
+ });
21
+ }
22
+
23
+ // Limit the cache size by deleting the oldest entries
24
+ function limitCacheSize(name, size) {
25
+ caches.open(name).then((cache) => {
26
+ cache.keys().then((keys) => {
27
+ if (keys.length > size) {
28
+ cache.delete(keys[0]).then(() => {
29
+ limitCacheSize(name, size);
30
+ });
31
+ }
32
+ });
33
+ });
34
+ }
35
+
36
+ async function fetchRequest(event) {
37
+ Log("WORKER: fetch event for " + event.request.url);
38
+ try {
39
+ // Clone the request to store it in the cache
40
+ const fetchRequest = event.request.clone();
41
+ const response = await fetch(fetchRequest);
42
+
43
+ // Verify if the response is valid
44
+ if (response && response.status === 200 && response.type === "basic") {
45
+ // Clone the response to store it in the cache
46
+ const responseToCache = response.clone();
47
+ const cache = await caches.open(cacheName);
48
+ cache.put(event.request, responseToCache);
49
+
50
+ // Limit the cache size
51
+ limitCacheSize(cacheName, MAX_CACHE_SIZE);
52
+
53
+ Log("WORKER: fetch response stored in cache.", event.request.url);
54
+ }
55
+ return response;
56
+ } catch (error) {
57
+ Log("WORKER: fetch request failed.", error);
58
+
59
+ // Try to serve the cached response if available
60
+ const cachedResponse = await caches.match(event.request);
61
+ if (cachedResponse) {
62
+ Log("WORKER: fetch request failed, responding with cache.");
63
+ return cachedResponse;
64
+ }
65
+
66
+ // Send the offline page if no cache is available
67
+ const cache = await caches.open(cacheName);
68
+ const offlineResponse = await cache.match("/offline.html");
69
+ if (offlineResponse) {
70
+ return offlineResponse;
71
+ }
72
+
73
+ // Generic offline page
74
+ return new Response("<h1>Offline</h1>", {
75
+ status: 503,
76
+ statusText: "Service Unavailable",
77
+ headers: new Headers({
78
+ "Content-Type": "text/html"
79
+ })
80
+ });
81
+ }
82
+ }
83
+
84
+ self.addEventListener("fetch", (event) => {
85
+ // Ignore requests with the "only-if-cached" cache mode
86
+ if (event.request.cache === "only-if-cached" && event.request.mode !== "same-origin") {
87
+ return;
88
+ }
89
+
90
+ Log("WORKER: fetch event in progress.", event.request.url);
91
+
92
+ // Ignore requests that are not GET
93
+ if (event.request.method !== "GET") {
94
+ return;
95
+ }
96
+
97
+ // If the request is for the API, use the network first
98
+ if (event.request.url.includes("/api/")) {
99
+ event.respondWith(fetchRequest(event));
100
+ } else {
101
+ // Use the cache first for other requests
102
+ event.respondWith(
103
+ caches.match(event.request).then((response) => {
104
+ if (response) {
105
+ Log("WORKER: returning from cache.", event.request.url);
106
+ return response;
107
+ }
108
+ return fetchRequest(event);
109
+ })
110
+ );
111
+ }
112
+ });
113
+
114
+ self.addEventListener("install", (event) => {
115
+ Log("WORKER: installing version", cacheName);
116
+ event.waitUntil(
117
+ caches
118
+ .open(cacheName)
119
+ .then((cache) => {
120
+ return cache.addAll(config.urls);
121
+ })
122
+ .then(() => {
123
+ Log("WORKER: install completed.");
124
+ })
125
+ );
126
+ });
127
+
128
+ self.addEventListener("activate", (event) => {
129
+ Log("WORKER: activating new version", cacheName);
130
+
131
+ event.waitUntil(
132
+ caches.keys().then((keys) =>
133
+ Promise.all(
134
+ keys
135
+ // Filter the caches that belong to this app version
136
+ .filter((key) => key !== cacheName)
137
+ .map((key) => caches.delete(key))
138
+ ).then(() => {
139
+ Log("WORKER: old caches cleared.");
140
+ // Notify clients about the new version
141
+ sendMessageToClients({ type: "NEW_VERSION" });
142
+ })
143
+ )
144
+ );
145
+ });
146
+
147
+ // Listen for messages from clients
148
+ self.addEventListener("message", (event) => {
149
+ if (event.data && event.data.type === "SKIP_WAITING") {
150
+ self.skipWaiting();
151
+ }
152
+ });
@@ -0,0 +1,117 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ export class SessionStorage {
5
+ private storage: { [key: string]: string };
6
+ private limit: number;
7
+ private persist: boolean;
8
+ private filePath: string;
9
+ private directory: string = ".session-storage";
10
+
11
+ constructor({ persist = false, filePath = "./sessionData.json" }: { persist?: boolean; filePath?: string } = {}) {
12
+ this.storage = {};
13
+ this.limit = 5 * 1024 * 1024; // 5MB storage limit
14
+ this.persist = persist;
15
+ this.filePath = path.resolve(this.directory, filePath);
16
+
17
+ if (!fs.existsSync(this.directory)) {
18
+ fs.mkdirSync(this.directory, { recursive: true });
19
+ }
20
+
21
+ // Load data from file if persistence is enabled
22
+ if (this.persist) {
23
+ this.loadFromFile();
24
+ }
25
+ }
26
+
27
+ // Calculate total size in bytes of stored data
28
+ private getStorageSize(): number {
29
+ return new TextEncoder().encode(JSON.stringify(this.storage)).length;
30
+ }
31
+
32
+ // Check if storage limit is exceeded
33
+ private checkSizeLimit(): void {
34
+ const size = this.getStorageSize();
35
+ if (size > this.limit) {
36
+ throw new DOMException("Storage limit exceeded", "QuotaExceededError");
37
+ }
38
+ }
39
+
40
+ // Store value under the specified key
41
+ setItem(key: string | null | undefined, value: string | null | undefined): void {
42
+ if (key === null || key === undefined) {
43
+ throw new TypeError("Failed to execute 'setItem' on 'Storage': 1 argument required, but only 0 present.");
44
+ }
45
+
46
+ if (value === null) {
47
+ value = "null"; // Convert null to "null"
48
+ } else if (value === undefined) {
49
+ value = "undefined"; // Convert undefined to "undefined"
50
+ }
51
+
52
+ this.storage[key] = String(value); // Store as string
53
+ this.checkSizeLimit(); // Check storage limit
54
+ if (this.persist) {
55
+ this.saveToFile(); // Save to file if persistence is enabled
56
+ }
57
+ }
58
+
59
+ // Retrieve value stored under the specified key
60
+ getItem(key: string | null | undefined): string | null {
61
+ if (key === null || key === undefined) {
62
+ throw new TypeError("Failed to execute 'getItem' on 'Storage': 1 argument required, but only 0 present.");
63
+ }
64
+ return this.storage[key] || null; // Return null if key doesn't exist
65
+ }
66
+
67
+ // Remove the value under the specified key
68
+ removeItem(key: string | null | undefined): void {
69
+ if (key === null || key === undefined) {
70
+ throw new TypeError("Failed to execute 'removeItem' on 'Storage': 1 argument required, but only 0 present.");
71
+ }
72
+ delete this.storage[key];
73
+ if (this.persist) {
74
+ this.saveToFile(); // Save to file if persistence is enabled
75
+ }
76
+ }
77
+
78
+ // Clear all stored values
79
+ clear(): void {
80
+ this.storage = {};
81
+ if (this.persist) {
82
+ this.saveToFile(); // Save to file if persistence is enabled
83
+ }
84
+ }
85
+
86
+ // Return the number of stored items
87
+ get length(): number {
88
+ return Object.keys(this.storage).length;
89
+ }
90
+
91
+ // Return the key at the specified index
92
+ key(index: number): string | null {
93
+ const keys = Object.keys(this.storage);
94
+ return keys[index] || null;
95
+ }
96
+
97
+ // Save data to a file (only if persistence is enabled)
98
+ private saveToFile(): void {
99
+ try {
100
+ fs.writeFileSync(this.filePath, JSON.stringify(this.storage), "utf-8");
101
+ } catch (error) {
102
+ throw new Error(`Error saving data to file: ${(error as any).message}`);
103
+ }
104
+ }
105
+
106
+ // Load data from a file (only if persistence is enabled)
107
+ private loadFromFile(): void {
108
+ try {
109
+ if (fs.existsSync(this.filePath)) {
110
+ const data = fs.readFileSync(this.filePath, "utf-8");
111
+ this.storage = JSON.parse(data || "{}");
112
+ }
113
+ } catch (error) {
114
+ throw new Error(`Error loading data from file: ${(error as any).message}`);
115
+ }
116
+ }
117
+ }
@@ -2,17 +2,15 @@ import fs from "fs";
2
2
  import path from "path";
3
3
 
4
4
  export function sw(file: string, options = {}) {
5
- let swfiletemplate = path.resolve(__dirname, "./node.sw.tpl");
6
- let swTpl = fs.readFileSync(swfiletemplate, "utf8");
7
- let opt = Object.assign(
8
- {
9
- version: "v1::",
10
- name: "Valyrian.js",
11
- urls: ["/"],
12
- debug: false
13
- },
14
- options
15
- );
5
+ const swfiletemplate = path.resolve(__dirname, "./node.sw.js");
6
+ const swTpl = fs.readFileSync(swfiletemplate, "utf8");
7
+ const opt = {
8
+ version: "v1::",
9
+ name: "Valyrian.js",
10
+ urls: ["/"],
11
+ debug: false,
12
+ ...options
13
+ };
16
14
  let contents = swTpl
17
15
  .replace("v1::", "v" + opt.version + "::")
18
16
  .replace("Valyrian.js", opt.name)
@@ -24,3 +22,29 @@ export function sw(file: string, options = {}) {
24
22
 
25
23
  fs.writeFileSync(file, contents, "utf8");
26
24
  }
25
+
26
+ /*
27
+ sw("sw.js", {
28
+ version: "1",
29
+ name: "Valyrian.js",
30
+ urls: ["/", "/index.html"],
31
+ debug: false
32
+ });
33
+
34
+
35
+ // On the client side
36
+ if ("serviceWorker" in navigator) {
37
+ navigator.serviceWorker.register("/service-worker.js");
38
+
39
+ navigator.serviceWorker.addEventListener("message", (event) => {
40
+ if (event.data && event.data.type === "NEW_VERSION") {
41
+ // Notify the user about the new version and ask if they want to update
42
+ if (confirm("Hay una nueva versión disponible. ¿Deseas actualizar?")) {
43
+ // Send a message to the service worker to skip the waiting
44
+ navigator.serviceWorker.controller.postMessage({ type: "SKIP_WAITING" });
45
+ window.location.reload();
46
+ }
47
+ }
48
+ });
49
+ }
50
+ */