valyrian.js 8.0.13 → 8.1.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.
- package/dist/lib/native-store/index.d.ts +1 -1
- package/dist/lib/native-store/index.d.ts.map +1 -1
- package/dist/lib/node/index.d.ts +2 -2
- package/dist/lib/node/index.d.ts.map +1 -1
- package/dist/lib/node/utils/server-storage.d.ts +12 -0
- package/dist/lib/node/utils/server-storage.d.ts.map +1 -0
- package/dist/lib/node/utils/tree-adapter.d.ts.map +1 -1
- package/dist/lib/pulses/index.d.ts +4 -0
- package/dist/lib/pulses/index.d.ts.map +1 -1
- package/dist/lib/redux-devtools/index.d.ts +15 -0
- package/dist/lib/redux-devtools/index.d.ts.map +1 -0
- package/dist/lib/request/index.d.ts.map +1 -1
- package/dist/lib/translate/index.d.ts +6 -2
- package/dist/lib/translate/index.d.ts.map +1 -1
- package/dist/native-store/index.js +26 -13
- package/dist/native-store/index.js.map +3 -3
- package/dist/native-store/index.min.js +1 -1
- package/dist/native-store/index.min.js.map +1 -1
- package/dist/native-store/index.mjs +26 -13
- package/dist/native-store/index.mjs.map +3 -3
- package/dist/node/index.js +57 -94
- package/dist/node/index.js.map +4 -4
- package/dist/node/index.mjs +57 -94
- package/dist/node/index.mjs.map +4 -4
- package/dist/pulses/index.js +32 -1
- package/dist/pulses/index.js.map +2 -2
- package/dist/pulses/index.min.js +1 -1
- package/dist/pulses/index.min.js.map +1 -1
- package/dist/pulses/index.mjs +32 -1
- package/dist/pulses/index.mjs.map +2 -2
- package/dist/redux-devtools/index.js +81 -0
- package/dist/redux-devtools/index.js.map +7 -0
- package/dist/redux-devtools/index.min.js +1 -0
- package/dist/redux-devtools/index.min.js.map +1 -0
- package/dist/redux-devtools/index.mjs +60 -0
- package/dist/redux-devtools/index.mjs.map +7 -0
- package/dist/request/index.js +20 -7
- package/dist/request/index.js.map +2 -2
- package/dist/request/index.min.js +1 -1
- package/dist/request/index.min.js.map +1 -1
- package/dist/request/index.mjs +20 -7
- package/dist/request/index.mjs.map +2 -2
- package/dist/translate/index.js +36 -26
- package/dist/translate/index.js.map +3 -3
- package/dist/translate/index.min.js +1 -1
- package/dist/translate/index.min.js.map +1 -1
- package/dist/translate/index.mjs +36 -26
- package/dist/translate/index.mjs.map +3 -3
- package/lib/native-store/index.ts +22 -8
- package/lib/node/index.ts +4 -4
- package/lib/node/utils/server-storage.ts +71 -0
- package/lib/node/utils/tree-adapter.ts +25 -1
- package/lib/pulses/index.ts +54 -6
- package/lib/redux-devtools/index.ts +86 -0
- package/lib/request/index.ts +28 -8
- package/lib/translate/index.ts +37 -26
- package/package.json +14 -14
- package/dist/lib/node/utils/session-storage.d.ts +0 -22
- package/dist/lib/node/utils/session-storage.d.ts.map +0 -1
- package/lib/node/utils/session-storage.ts +0 -120
package/lib/pulses/index.ts
CHANGED
|
@@ -56,7 +56,11 @@ function createStore<StateType extends State, PulsesType extends Pulses<StateTyp
|
|
|
56
56
|
initialState: StateType | (() => StateType) | null,
|
|
57
57
|
pulses: PulsesType,
|
|
58
58
|
immutable = false
|
|
59
|
-
): StorePulses<PulsesType> & {
|
|
59
|
+
): StorePulses<PulsesType> & {
|
|
60
|
+
state: ProxyState<StateType>;
|
|
61
|
+
on: (event: string, callback: Function) => void;
|
|
62
|
+
off: (event: string, callback: Function) => void;
|
|
63
|
+
} {
|
|
60
64
|
const subscribers = new Set<Function>();
|
|
61
65
|
const domWithVnodesToUpdate = new WeakSet<DomElement>();
|
|
62
66
|
|
|
@@ -160,7 +164,7 @@ function createStore<StateType extends State, PulsesType extends Pulses<StateTyp
|
|
|
160
164
|
const emptyFlush = async () => {};
|
|
161
165
|
|
|
162
166
|
try {
|
|
163
|
-
const pulseResult = pulses[key].apply(this, [currentState, ...args]);
|
|
167
|
+
const pulseResult = pulses[key].apply(this, [currentState, ...args] as any);
|
|
164
168
|
if (pulseResult instanceof Promise) {
|
|
165
169
|
return pulseResult
|
|
166
170
|
.then((resolvedValue) => {
|
|
@@ -190,38 +194,82 @@ function createStore<StateType extends State, PulsesType extends Pulses<StateTyp
|
|
|
190
194
|
|
|
191
195
|
syncState(localState);
|
|
192
196
|
|
|
197
|
+
const listeners: Record<string, Function[]> = {};
|
|
198
|
+
const trigger = (event: string, ...args: any[]) => {
|
|
199
|
+
if (listeners[event]) {
|
|
200
|
+
listeners[event].forEach((callback) => callback(...args));
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
193
204
|
const pulsesProxy = new Proxy(boundPulses, {
|
|
194
205
|
get: (pulses, prop: string) => {
|
|
195
206
|
if (prop === "state") {
|
|
196
207
|
return proxyState;
|
|
197
208
|
}
|
|
209
|
+
if (prop === "on") {
|
|
210
|
+
return (event: string, callback: Function) => {
|
|
211
|
+
if (!listeners[event]) {
|
|
212
|
+
listeners[event] = [];
|
|
213
|
+
}
|
|
214
|
+
listeners[event].push(callback);
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if (prop === "off") {
|
|
218
|
+
return (event: string, callback: Function) => {
|
|
219
|
+
if (listeners[event]) {
|
|
220
|
+
listeners[event] = listeners[event].filter((cb) => cb !== callback);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
198
224
|
if (!(prop in pulses)) {
|
|
199
225
|
throw new Error(`Pulse '${prop}' does not exist`);
|
|
200
226
|
}
|
|
201
227
|
const pulseMethod = pulses[prop];
|
|
202
228
|
|
|
203
229
|
if (typeof pulseMethod === "function") {
|
|
204
|
-
return
|
|
230
|
+
return (...args: any[]) => {
|
|
231
|
+
const result = pulseMethod.apply(pulsesProxy, args as any);
|
|
232
|
+
if (result instanceof Promise) {
|
|
233
|
+
return result.then((r) => {
|
|
234
|
+
trigger("pulse", prop, args);
|
|
235
|
+
return r;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
trigger("pulse", prop, args);
|
|
239
|
+
return result;
|
|
240
|
+
};
|
|
205
241
|
}
|
|
206
242
|
|
|
207
243
|
return pulseMethod;
|
|
208
244
|
}
|
|
209
245
|
});
|
|
210
246
|
|
|
211
|
-
return pulsesProxy as StorePulses<PulsesType> & {
|
|
247
|
+
return pulsesProxy as StorePulses<PulsesType> & {
|
|
248
|
+
state: ProxyState<StateType>;
|
|
249
|
+
on: (event: string, callback: Function) => void;
|
|
250
|
+
off: (event: string, callback: Function) => void;
|
|
251
|
+
};
|
|
212
252
|
}
|
|
213
253
|
|
|
214
254
|
export function createPulseStore<StateType extends State, PulsesType extends Pulses<StateType>>(
|
|
215
255
|
initialState: StateType,
|
|
216
256
|
pulses: PulsesType
|
|
217
|
-
): StorePulses<PulsesType> & {
|
|
257
|
+
): StorePulses<PulsesType> & {
|
|
258
|
+
state: ProxyState<StateType>;
|
|
259
|
+
on: (event: string, callback: Function) => void;
|
|
260
|
+
off: (event: string, callback: Function) => void;
|
|
261
|
+
} {
|
|
218
262
|
return createStore(initialState, pulses, true);
|
|
219
263
|
}
|
|
220
264
|
|
|
221
265
|
export function createMutableStore<StateType extends State, PulsesType extends Pulses<StateType>>(
|
|
222
266
|
initialState: StateType,
|
|
223
267
|
pulses: PulsesType
|
|
224
|
-
): StorePulses<PulsesType> & {
|
|
268
|
+
): StorePulses<PulsesType> & {
|
|
269
|
+
state: ProxyState<StateType>;
|
|
270
|
+
on: (event: string, callback: Function) => void;
|
|
271
|
+
off: (event: string, callback: Function) => void;
|
|
272
|
+
} {
|
|
225
273
|
console.warn(
|
|
226
274
|
"Warning: You are working with a mutable state. This can lead to unpredictable behavior. All state changes made outside of a pulse will not trigger a re-render."
|
|
227
275
|
);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { FluxStore } from "valyrian.js/flux-store";
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
__REDUX_DEVTOOLS_EXTENSION__: any;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface DevToolsOptions {
|
|
11
|
+
name?: string;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getDevTools() {
|
|
16
|
+
const isBrowser = typeof window !== "undefined";
|
|
17
|
+
if (isBrowser && window.__REDUX_DEVTOOLS_EXTENSION__) {
|
|
18
|
+
return window.__REDUX_DEVTOOLS_EXTENSION__;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function connectFluxStore(store: FluxStore, options: DevToolsOptions = {}) {
|
|
24
|
+
const devTools = getDevTools();
|
|
25
|
+
if (!devTools) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const name = options.name || "FluxStore";
|
|
30
|
+
const dt = devTools.connect({ name, ...options });
|
|
31
|
+
dt.init(store.state);
|
|
32
|
+
|
|
33
|
+
store.on("commit", (_: any, mutation: string, ...args: any[]) => {
|
|
34
|
+
dt.send({ type: mutation, payload: args }, store.state);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
store.on("registerModule", (_: any, namespace: string) => {
|
|
38
|
+
dt.send({ type: `[Module] Register: ${namespace}` }, store.state);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
store.on("unregisterModule", (_: any, namespace: string) => {
|
|
42
|
+
dt.send({ type: `[Module] Unregister: ${namespace}` }, store.state);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function connectPulseStore(store: any, options: DevToolsOptions = {}) {
|
|
47
|
+
const devTools = getDevTools();
|
|
48
|
+
if (!devTools) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const name = options.name || "PulseStore";
|
|
53
|
+
const dt = devTools.connect({ name, ...options });
|
|
54
|
+
dt.init(store.state);
|
|
55
|
+
|
|
56
|
+
if (store.on) {
|
|
57
|
+
store.on("pulse", (pulse: string, args: any[]) => {
|
|
58
|
+
dt.send({ type: pulse, payload: args }, store.state);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function connectPulse(pulse: any, options: DevToolsOptions = {}) {
|
|
64
|
+
// Pulse is [read, write, runSubscribers]
|
|
65
|
+
// We can't easily hook into the write function without wrapping it.
|
|
66
|
+
// But the user asked for "simple" and "using existing apis".
|
|
67
|
+
// If we want to debug individual pulses, we might need to wrap them.
|
|
68
|
+
|
|
69
|
+
const devTools = getDevTools();
|
|
70
|
+
if (!devTools) {
|
|
71
|
+
return pulse;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const name = options.name || "Pulse";
|
|
75
|
+
const dt = devTools.connect({ name, ...options });
|
|
76
|
+
const [read, write, run] = pulse;
|
|
77
|
+
|
|
78
|
+
dt.init(read());
|
|
79
|
+
|
|
80
|
+
const newWrite = (newValue: any) => {
|
|
81
|
+
write(newValue);
|
|
82
|
+
dt.send({ type: "update", payload: newValue }, read());
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return [read, newWrite, run];
|
|
86
|
+
}
|
package/lib/request/index.ts
CHANGED
|
@@ -68,10 +68,17 @@ function serialize(obj: Record<string, any>, prefix: string = ""): URLSearchPara
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
function serializeFormData(data: Record<string, any>): FormData {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return
|
|
74
|
-
|
|
71
|
+
const fd = new FormData();
|
|
72
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
73
|
+
if (value === null || value === undefined) return; // Ignorar nulos
|
|
74
|
+
|
|
75
|
+
if (Array.isArray(value)) {
|
|
76
|
+
value.forEach((v) => fd.append(key, v));
|
|
77
|
+
} else {
|
|
78
|
+
fd.append(key, value);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return fd;
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
function parseUrl(url: string, options: RequestOptionsWithUrls) {
|
|
@@ -97,6 +104,14 @@ function parseUrl(url: string, options: RequestOptionsWithUrls) {
|
|
|
97
104
|
|
|
98
105
|
const defaultOptions: RequestOptions = { allowedMethods: ["get", "post", "put", "patch", "delete", "head", "options"] };
|
|
99
106
|
|
|
107
|
+
const isNativeBody = (data: any) =>
|
|
108
|
+
data instanceof FormData ||
|
|
109
|
+
data instanceof URLSearchParams ||
|
|
110
|
+
data instanceof Blob ||
|
|
111
|
+
data instanceof ArrayBuffer ||
|
|
112
|
+
(typeof DataView !== "undefined" && data instanceof DataView) ||
|
|
113
|
+
(typeof ReadableStream !== "undefined" && data instanceof ReadableStream);
|
|
114
|
+
|
|
100
115
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
101
116
|
function Requester(baseUrl = "", options: RequestOptions = defaultOptions) {
|
|
102
117
|
const url = baseUrl.replace(/\/$/gi, "").trim();
|
|
@@ -157,12 +172,17 @@ function Requester(baseUrl = "", options: RequestOptions = defaultOptions) {
|
|
|
157
172
|
}
|
|
158
173
|
|
|
159
174
|
if (data) {
|
|
160
|
-
const isJson = /json/gi.test(contentType);
|
|
161
|
-
|
|
162
175
|
if (innerOptions.method === "GET" && typeof data === "object") {
|
|
163
176
|
finalUrl.search = serialize(data).toString();
|
|
164
|
-
} else if (
|
|
165
|
-
innerOptions.body =
|
|
177
|
+
} else if (isNativeBody(data) || typeof data === "string") {
|
|
178
|
+
innerOptions.body = data as BodyInit;
|
|
179
|
+
} else {
|
|
180
|
+
const isJson = /json/gi.test(contentType);
|
|
181
|
+
if (isJson) {
|
|
182
|
+
innerOptions.body = JSON.stringify(data);
|
|
183
|
+
} else {
|
|
184
|
+
innerOptions.body = serializeFormData(data);
|
|
185
|
+
}
|
|
166
186
|
}
|
|
167
187
|
}
|
|
168
188
|
|
package/lib/translate/index.ts
CHANGED
|
@@ -1,11 +1,45 @@
|
|
|
1
|
-
import { directive, setPropNameReserved, update, VnodeWithDom } from "valyrian.js";
|
|
1
|
+
import { current, directive, setPropNameReserved, update, VnodeWithDom } from "valyrian.js";
|
|
2
2
|
import { get } from "valyrian.js/utils";
|
|
3
3
|
|
|
4
4
|
const translations: Record<string, Record<string, any>> = {};
|
|
5
|
-
let
|
|
5
|
+
let currentLang = "en";
|
|
6
|
+
|
|
7
|
+
let storeStrategy = {
|
|
8
|
+
get: () => currentLang,
|
|
9
|
+
set: (lang: string) => {
|
|
10
|
+
currentLang = lang;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function setStoreStrategy(strategy: { get: () => string; set: (lang: string) => void }) {
|
|
15
|
+
storeStrategy = strategy;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getLang(): string {
|
|
19
|
+
return storeStrategy.get();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function setLang(newLang: string): void {
|
|
23
|
+
if (typeof newLang !== "string") {
|
|
24
|
+
throw new Error(`Language ${newLang} not found`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const parsedLang = newLang.toLowerCase().split("-").shift()?.split("_").shift();
|
|
28
|
+
|
|
29
|
+
if (typeof parsedLang !== "string") {
|
|
30
|
+
throw new Error(`Language ${newLang} not found`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!translations[parsedLang]) {
|
|
34
|
+
throw new Error(`Language ${newLang} not found`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
storeStrategy.set(parsedLang);
|
|
38
|
+
update();
|
|
39
|
+
}
|
|
6
40
|
|
|
7
41
|
export function t(path: string, params?: Record<string, string>): string {
|
|
8
|
-
const langDef = translations[
|
|
42
|
+
const langDef = translations[getLang()];
|
|
9
43
|
const translation = get(langDef, path);
|
|
10
44
|
|
|
11
45
|
if (typeof translation !== "string") {
|
|
@@ -49,29 +83,6 @@ export function getTranslations(): Record<string, Record<string, any>> {
|
|
|
49
83
|
return translations;
|
|
50
84
|
}
|
|
51
85
|
|
|
52
|
-
export function setLang(newLang: string): void {
|
|
53
|
-
if (typeof newLang !== "string") {
|
|
54
|
-
throw new Error(`Language ${newLang} not found`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const parsedLang = newLang.toLowerCase().split("-").shift()?.split("_").shift();
|
|
58
|
-
|
|
59
|
-
if (typeof parsedLang !== "string") {
|
|
60
|
-
throw new Error(`Language ${newLang} not found`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (!translations[parsedLang]) {
|
|
64
|
-
throw new Error(`Language ${newLang} not found`);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
lang = parsedLang;
|
|
68
|
-
update();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function getLang(): string {
|
|
72
|
-
return lang;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
86
|
export class NumberFormatter {
|
|
76
87
|
#value: number = 0;
|
|
77
88
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valyrian.js",
|
|
3
|
-
"version": "8.0
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Lightweight steel to forge PWAs. (Minimal Frontend Framework with server side rendering and other capabilities)",
|
|
5
5
|
"repository": "git@github.com:Masquerade-Circus/valyrian.js.git",
|
|
6
6
|
"author": "Masquerade <christian@masquerade-circus.net>",
|
|
@@ -70,44 +70,44 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"clean-css": "^5.3.3",
|
|
73
|
-
"esbuild": "^0.
|
|
73
|
+
"esbuild": "^0.27.0",
|
|
74
74
|
"favicons": "^7.2.0",
|
|
75
|
-
"form-data": "^4.0.
|
|
75
|
+
"form-data": "^4.0.5",
|
|
76
76
|
"purgecss": "^7.0.2",
|
|
77
77
|
"remark": "^15.0.1",
|
|
78
|
-
"terser": "^5.44.
|
|
78
|
+
"terser": "^5.44.1",
|
|
79
79
|
"ts-node": "^10.9.2",
|
|
80
80
|
"tsc-prog": "^2.3.0",
|
|
81
81
|
"tslib": "^2.8.1",
|
|
82
82
|
"typescript": "^5.9.3"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@release-it/conventional-changelog": "^10.0.
|
|
86
|
-
"@types/bun": "^1.3.
|
|
85
|
+
"@release-it/conventional-changelog": "^10.0.2",
|
|
86
|
+
"@types/bun": "^1.3.3",
|
|
87
87
|
"@types/clean-css": "^4.2.11",
|
|
88
|
-
"@types/node": "^24.
|
|
88
|
+
"@types/node": "^24.10.1",
|
|
89
89
|
"@types/node-fetch": "^2.6.13",
|
|
90
90
|
"@types/parse-path": "^7.1.0",
|
|
91
91
|
"@types/sharp": "^0.32.0",
|
|
92
92
|
"@types/source-map": "^0.5.7",
|
|
93
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
94
|
-
"@typescript-eslint/parser": "^8.
|
|
93
|
+
"@typescript-eslint/eslint-plugin": "^8.47.0",
|
|
94
|
+
"@typescript-eslint/parser": "^8.47.0",
|
|
95
95
|
"buffalo-test": "^2.0.0",
|
|
96
96
|
"chokidar-cli": "^3.0.0",
|
|
97
97
|
"compression": "^1.8.1",
|
|
98
98
|
"cross-env": "^10.1.0",
|
|
99
99
|
"cz-conventional-changelog": "^3.3.0",
|
|
100
|
-
"dayjs": "^1.11.
|
|
101
|
-
"eslint": "^9.
|
|
100
|
+
"dayjs": "^1.11.19",
|
|
101
|
+
"eslint": "^9.39.1",
|
|
102
102
|
"eslint-plugin-sonarjs": "^3.0.5",
|
|
103
103
|
"expect": "^30.2.0",
|
|
104
|
-
"fastify": "^5.6.
|
|
104
|
+
"fastify": "^5.6.2",
|
|
105
105
|
"gzip-size": "^7.0.0",
|
|
106
106
|
"pirates": "^4.0.7",
|
|
107
|
-
"release-it": "^19.0.
|
|
107
|
+
"release-it": "^19.0.6",
|
|
108
108
|
"remark-cli": "^12.0.1",
|
|
109
109
|
"remark-toc": "^9.0.0",
|
|
110
|
-
"typescript-eslint": "^8.
|
|
110
|
+
"typescript-eslint": "^8.47.0"
|
|
111
111
|
},
|
|
112
112
|
"overrides": {
|
|
113
113
|
"minimist": "^1.2.8",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export declare class SessionStorage {
|
|
2
|
-
private storage;
|
|
3
|
-
private limit;
|
|
4
|
-
private persist;
|
|
5
|
-
private filePath;
|
|
6
|
-
private directory;
|
|
7
|
-
constructor({ persist, filePath }?: {
|
|
8
|
-
persist?: boolean;
|
|
9
|
-
filePath?: string;
|
|
10
|
-
});
|
|
11
|
-
private getStorageSize;
|
|
12
|
-
private checkSizeLimit;
|
|
13
|
-
setItem(key: string | null | undefined, value: string | null | undefined): void;
|
|
14
|
-
getItem(key: string | null | undefined): string | null;
|
|
15
|
-
removeItem(key: string | null | undefined): void;
|
|
16
|
-
clear(): void;
|
|
17
|
-
get length(): number;
|
|
18
|
-
key(index: number): string | null;
|
|
19
|
-
private saveToFile;
|
|
20
|
-
private loadFromFile;
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=session-storage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-storage.d.ts","sourceRoot":"","sources":["../../../../lib/node/utils/session-storage.ts"],"names":[],"mappings":"AAGA,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAA8B;gBAEnC,EAAE,OAAe,EAAE,QAA+B,EAAE,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO;IAiB/G,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAkB/E,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI;IAUtD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAUhD,KAAK,IAAI,IAAI;IAMb,IAAI,MAAM,IAAI,MAAM,CAEnB;IAGD,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOjC,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,YAAY;CAYrB"}
|
|
@@ -1,120 +0,0 @@
|
|
|
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 (this.persist) {
|
|
18
|
-
if (!fs.existsSync(this.directory)) {
|
|
19
|
-
fs.mkdirSync(this.directory, { recursive: true });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Load data from file if persistence is enabled
|
|
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.loadFromFile();
|
|
53
|
-
this.storage[key] = String(value); // Store as string
|
|
54
|
-
this.checkSizeLimit(); // Check storage limit
|
|
55
|
-
this.saveToFile(); // Save to file if persistence is enabled
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Retrieve value stored under the specified key
|
|
59
|
-
getItem(key: string | null | undefined): string | null {
|
|
60
|
-
if (key === null || key === undefined) {
|
|
61
|
-
throw new TypeError("Failed to execute 'getItem' on 'Storage': 1 argument required, but only 0 present.");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
this.loadFromFile();
|
|
65
|
-
return this.storage[key] || null; // Return null if key doesn't exist
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Remove the value under the specified key
|
|
69
|
-
removeItem(key: string | null | undefined): void {
|
|
70
|
-
if (key === null || key === undefined) {
|
|
71
|
-
throw new TypeError("Failed to execute 'removeItem' on 'Storage': 1 argument required, but only 0 present.");
|
|
72
|
-
}
|
|
73
|
-
this.loadFromFile();
|
|
74
|
-
Reflect.deleteProperty(this.storage, key); // Remove key from storage
|
|
75
|
-
this.saveToFile(); // Save to file if persistence is enabled
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Clear all stored values
|
|
79
|
-
clear(): void {
|
|
80
|
-
this.storage = {};
|
|
81
|
-
this.saveToFile(); // Save to file if persistence is enabled
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Return the number of stored items
|
|
85
|
-
get length(): number {
|
|
86
|
-
return Object.keys(this.storage).length;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Return the key at the specified index
|
|
90
|
-
key(index: number): string | null {
|
|
91
|
-
this.loadFromFile();
|
|
92
|
-
const keys = Object.keys(this.storage);
|
|
93
|
-
return keys[index] || null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Save data to a file (only if persistence is enabled)
|
|
97
|
-
private saveToFile(): void {
|
|
98
|
-
if (this.persist) {
|
|
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
|
-
|
|
107
|
-
// Load data from a file (only if persistence is enabled)
|
|
108
|
-
private loadFromFile(): void {
|
|
109
|
-
if (this.persist) {
|
|
110
|
-
try {
|
|
111
|
-
if (fs.existsSync(this.filePath)) {
|
|
112
|
-
const data = fs.readFileSync(this.filePath, "utf-8");
|
|
113
|
-
this.storage = JSON.parse(data || "{}");
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
throw new Error(`Error loading data from file: ${(error as any).message}`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|