valyrian.js 7.1.1 → 7.2.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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -48
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +71 -48
- package/dist/interfaces.d.ts +1 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/proxy-signal/index.d.ts +23 -0
- package/dist/proxy-signal/index.d.ts.map +1 -0
- package/dist/proxy-signal/index.js +136 -0
- package/dist/proxy-signal/index.mjs +116 -0
- package/dist/router/index.d.ts +2 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +18 -5
- package/dist/router/index.mjs +18 -5
- package/dist/signal/index.d.ts +1 -22
- package/dist/signal/index.d.ts.map +1 -1
- package/dist/signal/index.js +45 -104
- package/dist/signal/index.mjs +46 -105
- package/lib/index.ts +133 -81
- package/lib/interfaces.ts +1 -0
- package/lib/proxy-signal/index.ts +187 -0
- package/lib/router/index.ts +22 -6
- package/lib/signal/index.ts +88 -168
- package/package.json +3 -4
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { update } from "valyrian.js";
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-use-before-define */
|
|
4
|
+
interface Cleanup {
|
|
5
|
+
(): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Subscription {
|
|
9
|
+
// eslint-disable-next-line no-unused-vars
|
|
10
|
+
(value: ProxySignal["value"]): void | Cleanup;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface Subscriptions extends Map<Subscription, Cleanup> {}
|
|
14
|
+
|
|
15
|
+
interface Getter {
|
|
16
|
+
// eslint-disable-next-line no-unused-vars
|
|
17
|
+
(value: ProxySignal["value"]): any;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Getters {
|
|
21
|
+
[key: string | symbol]: Getter;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ProxySignal {
|
|
25
|
+
// Works as a getter of the value
|
|
26
|
+
(): ProxySignal["value"];
|
|
27
|
+
// Works as a subscription to the value
|
|
28
|
+
// eslint-disable-next-line no-unused-vars
|
|
29
|
+
(value: Subscription): ProxySignal;
|
|
30
|
+
// Works as a setter with a path and a handler
|
|
31
|
+
// eslint-disable-next-line no-unused-vars
|
|
32
|
+
(path: string, handler: (valueAtPathPosition: any) => any): ProxySignal["value"];
|
|
33
|
+
// Works as a setter with a path and a value
|
|
34
|
+
// eslint-disable-next-line no-unused-vars
|
|
35
|
+
(path: string, value: any): ProxySignal["value"];
|
|
36
|
+
// Works as a setter with a value
|
|
37
|
+
// eslint-disable-next-line no-unused-vars
|
|
38
|
+
(value: any): ProxySignal["value"];
|
|
39
|
+
// Gets the current value of the signal.
|
|
40
|
+
value: any;
|
|
41
|
+
// Cleanup function to be called to remove all subscriptions.
|
|
42
|
+
cleanup: () => void;
|
|
43
|
+
// Creates a getter on the signal.
|
|
44
|
+
// eslint-disable-next-line no-unused-vars
|
|
45
|
+
getter: (name: string, handler: Getter) => any;
|
|
46
|
+
// To access the getters on the signal.
|
|
47
|
+
[key: string | number | symbol]: any;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function makeUnsubscribe(
|
|
51
|
+
subscriptions: Subscriptions,
|
|
52
|
+
computed: ProxySignal,
|
|
53
|
+
handler: Subscription,
|
|
54
|
+
cleanup?: Cleanup
|
|
55
|
+
) {
|
|
56
|
+
if (typeof cleanup === "function") {
|
|
57
|
+
computed.cleanup = cleanup;
|
|
58
|
+
}
|
|
59
|
+
computed.unsubscribe = () => {
|
|
60
|
+
subscriptions.delete(handler);
|
|
61
|
+
computed?.cleanup();
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function createSubscription(signal: ProxySignal, subscriptions: Subscriptions, handler: Subscription) {
|
|
66
|
+
if (subscriptions.has(handler) === false) {
|
|
67
|
+
// eslint-disable-next-line no-use-before-define
|
|
68
|
+
let computed = ProxySignal(() => handler(signal.value));
|
|
69
|
+
let cleanup = computed(); // Execute to register itself
|
|
70
|
+
makeUnsubscribe(subscriptions, computed, handler, cleanup);
|
|
71
|
+
subscriptions.set(handler, computed);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return subscriptions.get(handler);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let updateTimeout: any;
|
|
78
|
+
function delayedUpdate() {
|
|
79
|
+
clearTimeout(updateTimeout);
|
|
80
|
+
updateTimeout = setTimeout(update);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
84
|
+
export function ProxySignal(value: any): ProxySignal {
|
|
85
|
+
let subscriptions = new Map();
|
|
86
|
+
let getters: Getters = {};
|
|
87
|
+
|
|
88
|
+
let forceUpdate = false;
|
|
89
|
+
|
|
90
|
+
let signal: ProxySignal = new Proxy(
|
|
91
|
+
// eslint-disable-next-line no-unused-vars
|
|
92
|
+
function (valOrPath?: any | Subscription, handler?: (valueAtPathPosition: any) => any) {
|
|
93
|
+
// Works as a getter
|
|
94
|
+
if (typeof valOrPath === "undefined") {
|
|
95
|
+
return signal.value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Works as a subscription
|
|
99
|
+
if (typeof valOrPath === "function") {
|
|
100
|
+
return createSubscription(signal, subscriptions, valOrPath);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Works as a setter with a path
|
|
104
|
+
if (typeof valOrPath === "string" && typeof handler !== "undefined") {
|
|
105
|
+
let parsed = valOrPath.split(".");
|
|
106
|
+
let result = signal.value;
|
|
107
|
+
let next;
|
|
108
|
+
while (parsed.length) {
|
|
109
|
+
next = parsed.shift() as string;
|
|
110
|
+
if (parsed.length > 0) {
|
|
111
|
+
if (typeof result[next] !== "object") {
|
|
112
|
+
result[next] = {};
|
|
113
|
+
}
|
|
114
|
+
result = result[next];
|
|
115
|
+
} else {
|
|
116
|
+
result[next] = typeof handler === "function" ? handler(result[next]) : handler;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
forceUpdate = true;
|
|
120
|
+
signal.value = signal.value;
|
|
121
|
+
return signal.value;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Works as a setter with a value
|
|
125
|
+
signal.value = valOrPath;
|
|
126
|
+
return signal.value;
|
|
127
|
+
} as ProxySignal,
|
|
128
|
+
{
|
|
129
|
+
set(state, prop, val) {
|
|
130
|
+
if (prop === "value" || prop === "unsubscribe" || prop === "cleanup") {
|
|
131
|
+
let old = state[prop];
|
|
132
|
+
state[prop] = val;
|
|
133
|
+
if (prop === "value" && (forceUpdate || val !== old)) {
|
|
134
|
+
forceUpdate = false;
|
|
135
|
+
for (let [handler, computed] of subscriptions) {
|
|
136
|
+
computed.cleanup();
|
|
137
|
+
let cleanup = handler(val);
|
|
138
|
+
makeUnsubscribe(subscriptions, computed, handler, cleanup);
|
|
139
|
+
}
|
|
140
|
+
delayedUpdate();
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
},
|
|
146
|
+
get(state, prop) {
|
|
147
|
+
if (prop === "value") {
|
|
148
|
+
return typeof state.value === "function" ? state.value() : state.value;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (prop === "cleanup" || prop === "unsubscribe" || prop === "getter") {
|
|
152
|
+
return state[prop];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (prop in getters) {
|
|
156
|
+
return getters[prop](state.value);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
Object.defineProperties(signal, {
|
|
163
|
+
value: { value, writable: true, enumerable: true },
|
|
164
|
+
cleanup: {
|
|
165
|
+
value() {
|
|
166
|
+
// eslint-disable-next-line no-unused-vars
|
|
167
|
+
for (let [handler, computed] of subscriptions) {
|
|
168
|
+
computed.unsubscribe();
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
writable: true,
|
|
172
|
+
enumerable: true
|
|
173
|
+
},
|
|
174
|
+
getter: {
|
|
175
|
+
value(name: string, handler: Getter) {
|
|
176
|
+
if (name in getters) {
|
|
177
|
+
throw new Error("Named computed already exists.");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
getters[name] = handler;
|
|
181
|
+
},
|
|
182
|
+
enumerable: true
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
return signal;
|
|
187
|
+
}
|
package/lib/router/index.ts
CHANGED
|
@@ -52,10 +52,11 @@ interface RouterInterface {
|
|
|
52
52
|
path: string;
|
|
53
53
|
params: Record<string, string | number | any>;
|
|
54
54
|
matches: string[];
|
|
55
|
+
pathPrefix: string;
|
|
55
56
|
// eslint-disable-next-line no-unused-vars
|
|
56
57
|
add(method: string, ...args: Middlewares): Router;
|
|
57
58
|
// eslint-disable-next-line no-unused-vars
|
|
58
|
-
use(...args: string
|
|
59
|
+
use(...args: (string | Middleware | Router)[]): Router;
|
|
59
60
|
|
|
60
61
|
routes(): string[];
|
|
61
62
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -71,6 +72,18 @@ function flat(array: any) {
|
|
|
71
72
|
return Array.isArray(array) ? array.flat(Infinity) : [array];
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
function getPathWithoutPrefix(path: string, prefix: string) {
|
|
76
|
+
return getPathWithoutLastSlash(path.replace(new RegExp(`^${prefix}`), ""));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getPathWithoutLastSlash(path: string) {
|
|
80
|
+
let pathWithoutLastSlash = path.replace(/\/$/, "");
|
|
81
|
+
if (pathWithoutLastSlash === "") {
|
|
82
|
+
pathWithoutLastSlash = "/";
|
|
83
|
+
}
|
|
84
|
+
return pathWithoutLastSlash;
|
|
85
|
+
}
|
|
86
|
+
|
|
74
87
|
const addPath = ({
|
|
75
88
|
router,
|
|
76
89
|
method,
|
|
@@ -145,7 +158,7 @@ function searchMiddlewares(router: RouterInterface, path: string): Middlewares {
|
|
|
145
158
|
matches.push(...match);
|
|
146
159
|
|
|
147
160
|
if (item.method === "add") {
|
|
148
|
-
router.path = item.path;
|
|
161
|
+
router.path = getPathWithoutPrefix(item.path, router.pathPrefix);
|
|
149
162
|
break;
|
|
150
163
|
}
|
|
151
164
|
}
|
|
@@ -211,12 +224,15 @@ export class Router implements RouterInterface {
|
|
|
211
224
|
}
|
|
212
225
|
|
|
213
226
|
add(path: string, ...middlewares: Middlewares): Router {
|
|
214
|
-
|
|
227
|
+
let pathWithoutLastSlash = getPathWithoutLastSlash(`${this.pathPrefix}${path}`);
|
|
228
|
+
addPath({ router: this, method: "add", path: pathWithoutLastSlash, middlewares });
|
|
215
229
|
return this;
|
|
216
230
|
}
|
|
217
231
|
|
|
218
232
|
use(...middlewares: Middlewares | Router[] | string[]): Router {
|
|
219
|
-
let path =
|
|
233
|
+
let path = getPathWithoutLastSlash(
|
|
234
|
+
`${this.pathPrefix}${typeof middlewares[0] === "string" ? middlewares.shift() : "/"}`
|
|
235
|
+
);
|
|
220
236
|
|
|
221
237
|
for (const item of middlewares) {
|
|
222
238
|
if (item instanceof Router) {
|
|
@@ -249,7 +265,7 @@ export class Router implements RouterInterface {
|
|
|
249
265
|
throw new Error("router.url.required");
|
|
250
266
|
}
|
|
251
267
|
|
|
252
|
-
|
|
268
|
+
let constructedPath = getPathWithoutLastSlash(`${this.pathPrefix}${path}`);
|
|
253
269
|
const parts = constructedPath.split("?", 2);
|
|
254
270
|
this.url = constructedPath;
|
|
255
271
|
this.query = parseQuery(parts[1]);
|
|
@@ -309,7 +325,7 @@ export function mountRouter(elementContainer: string | any, router: Router): voi
|
|
|
309
325
|
|
|
310
326
|
if (!isNodeJs) {
|
|
311
327
|
function onPopStateGoToRoute(): void {
|
|
312
|
-
let pathWithoutPrefix = document.location.pathname
|
|
328
|
+
let pathWithoutPrefix = getPathWithoutPrefix(document.location.pathname, router.pathPrefix);
|
|
313
329
|
(router as unknown as Router).go(pathWithoutPrefix, undefined, true);
|
|
314
330
|
}
|
|
315
331
|
window.addEventListener("popstate", onPopStateGoToRoute, false);
|
package/lib/signal/index.ts
CHANGED
|
@@ -1,182 +1,102 @@
|
|
|
1
|
-
import { update } from "valyrian.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { VnodeWithDom, current, update, updateVnode, v } from "valyrian.js";
|
|
2
|
+
|
|
3
|
+
export function Signal(initialValue) {
|
|
4
|
+
// Create a copy of the current context object
|
|
5
|
+
const context = { ...current };
|
|
6
|
+
|
|
7
|
+
// Check if the context object has a vnode property
|
|
8
|
+
if (context.vnode) {
|
|
9
|
+
// Is first call
|
|
10
|
+
if (!context.vnode.signals) {
|
|
11
|
+
// Set the signals property to the signals property of the oldVnode object, or an empty array if that doesn't exist
|
|
12
|
+
context.vnode.signals = context.oldVnode?.signals || [];
|
|
13
|
+
// Set the calls property to -1
|
|
14
|
+
context.vnode.calls = -1;
|
|
15
|
+
// Set the subscribers property to the subscribers property of the oldVnode object, or an empty array if that doesn't exist
|
|
16
|
+
context.vnode.subscribers = context.oldVnode?.subscribers || [];
|
|
17
|
+
|
|
18
|
+
// Set the initialChildren property of the vnode object to a copy of the children array of the vnode object
|
|
19
|
+
context.vnode.initialChildren = [...context.vnode.children];
|
|
20
|
+
}
|
|
12
21
|
|
|
13
|
-
|
|
22
|
+
// Assign the signal variable to the signal stored at the index of the vnode object's calls property in the vnode's signals array
|
|
23
|
+
let signal = context.vnode.signals[++context.vnode.calls];
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
25
|
+
// If a signal has already been assigned to the signal variable, return it
|
|
26
|
+
if (signal) {
|
|
27
|
+
return signal;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
31
|
+
// Declare a variable to store the current value of the Signal
|
|
32
|
+
let value = initialValue;
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
(): Signal["value"];
|
|
27
|
-
// Works as a subscription to the value
|
|
28
|
-
// eslint-disable-next-line no-unused-vars
|
|
29
|
-
(value: Subscription): Signal;
|
|
30
|
-
// Works as a setter with a path and a handler
|
|
31
|
-
// eslint-disable-next-line no-unused-vars
|
|
32
|
-
(path: string, handler: (valueAtPathPosition: any) => any): Signal["value"];
|
|
33
|
-
// Works as a setter with a path and a value
|
|
34
|
-
// eslint-disable-next-line no-unused-vars
|
|
35
|
-
(path: string, value: any): Signal["value"];
|
|
36
|
-
// Works as a setter with a value
|
|
37
|
-
// eslint-disable-next-line no-unused-vars
|
|
38
|
-
(value: any): Signal["value"];
|
|
39
|
-
// Gets the current value of the signal.
|
|
40
|
-
value: any;
|
|
41
|
-
// Cleanup function to be called to remove all subscriptions.
|
|
42
|
-
cleanup: () => void;
|
|
43
|
-
// Creates a getter on the signal.
|
|
44
|
-
// eslint-disable-next-line no-unused-vars
|
|
45
|
-
getter: (name: string, handler: Getter) => any;
|
|
46
|
-
// To access the getters on the signal.
|
|
47
|
-
[key: string | number | symbol]: any;
|
|
48
|
-
}
|
|
34
|
+
// Create an array to store functions that have subscribed to changes to the Signal's value
|
|
35
|
+
const subscribers = [];
|
|
49
36
|
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
computed?.cleanup();
|
|
37
|
+
// Define a function that allows other parts of the code to subscribe to changes to the Signal's value
|
|
38
|
+
const subscribe = (callback) => {
|
|
39
|
+
// Add the callback function to the subscribers array
|
|
40
|
+
if (subscribers.indexOf(callback) === -1) {
|
|
41
|
+
subscribers.push(callback);
|
|
42
|
+
}
|
|
57
43
|
};
|
|
58
|
-
}
|
|
59
44
|
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
let computed = Signal(() => handler(signal.value));
|
|
64
|
-
let cleanup = computed(); // Execute to register itself
|
|
65
|
-
makeUnsubscribe(subscriptions, computed, handler, cleanup);
|
|
66
|
-
subscriptions.set(handler, computed);
|
|
45
|
+
// Define a function that returns the current value of the Signal
|
|
46
|
+
function get() {
|
|
47
|
+
return value;
|
|
67
48
|
}
|
|
49
|
+
// Add value, toJSON, valueOf, and toString properties to the get function
|
|
50
|
+
get.value = value;
|
|
51
|
+
get.toJSON = get.valueOf = get;
|
|
52
|
+
get.toString = () => `${value}`;
|
|
53
|
+
|
|
54
|
+
// Define a function that allows the value of the Signal to be updated and notifies any subscribed functions of the change
|
|
55
|
+
const set = (newValue) => {
|
|
56
|
+
// Update the value of the Signal
|
|
57
|
+
value = newValue;
|
|
58
|
+
// Update the value property of the get function
|
|
59
|
+
get.value = value;
|
|
60
|
+
// Call each subscribed function with the new value of the Signal as an argument
|
|
61
|
+
for (let i = 0, l = subscribers.length; i < l; i++) {
|
|
62
|
+
subscribers[i](value);
|
|
63
|
+
}
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
// Check if the context object has a vnode property
|
|
66
|
+
if (context.vnode) {
|
|
67
|
+
// If it does, create a new vnode object based on the original vnode, its children, and its DOM and SVG properties
|
|
68
|
+
let newVnode = v(context.vnode.tag, context.vnode.props, ...context.vnode.initialChildren) as VnodeWithDom;
|
|
69
|
+
newVnode.dom = context.vnode.dom;
|
|
70
|
+
newVnode.isSVG = context.vnode.isSVG;
|
|
71
|
+
|
|
72
|
+
// Clear the subscribers array by setting the length property to 0
|
|
73
|
+
context.vnode.subscribers.forEach(
|
|
74
|
+
(subscribers) =>
|
|
75
|
+
// Setting the length property to 0 is faster than clearing the array with a loop
|
|
76
|
+
(subscribers.length = 0)
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Clear the subscribers array by setting it to an empty array
|
|
80
|
+
context.vnode.subscribers = [];
|
|
81
|
+
|
|
82
|
+
// Return the result of updating the original vnode with the new vnode
|
|
83
|
+
return updateVnode(newVnode, context.vnode);
|
|
84
|
+
}
|
|
71
85
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
updateTimeout = setTimeout(update);
|
|
76
|
-
}
|
|
86
|
+
// If the context object doesn't have a vnode property, return the result of calling the update function
|
|
87
|
+
return update();
|
|
88
|
+
};
|
|
77
89
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
function (valOrPath?: any | Subscription, handler?: (valueAtPathPosition: any) => any) {
|
|
88
|
-
// Works as a getter
|
|
89
|
-
if (typeof valOrPath === "undefined") {
|
|
90
|
-
return signal.value;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Works as a subscription
|
|
94
|
-
if (typeof valOrPath === "function") {
|
|
95
|
-
return createSubscription(signal, subscriptions, valOrPath);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Works as a setter with a path
|
|
99
|
-
if (typeof valOrPath === "string" && typeof handler !== "undefined") {
|
|
100
|
-
let parsed = valOrPath.split(".");
|
|
101
|
-
let result = signal.value;
|
|
102
|
-
let next;
|
|
103
|
-
while (parsed.length) {
|
|
104
|
-
next = parsed.shift() as string;
|
|
105
|
-
if (parsed.length > 0) {
|
|
106
|
-
if (typeof result[next] !== "object") {
|
|
107
|
-
result[next] = {};
|
|
108
|
-
}
|
|
109
|
-
result = result[next];
|
|
110
|
-
} else {
|
|
111
|
-
result[next] = typeof handler === "function" ? handler(result[next]) : handler;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
forceUpdate = true;
|
|
115
|
-
signal.value = signal.value;
|
|
116
|
-
return signal.value;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Works as a setter with a value
|
|
120
|
-
signal.value = valOrPath;
|
|
121
|
-
return signal.value;
|
|
122
|
-
} as Signal,
|
|
123
|
-
{
|
|
124
|
-
set(state, prop, val) {
|
|
125
|
-
if (prop === "value" || prop === "unsubscribe" || prop === "cleanup") {
|
|
126
|
-
let old = state[prop];
|
|
127
|
-
state[prop] = val;
|
|
128
|
-
if (prop === "value" && (forceUpdate || val !== old)) {
|
|
129
|
-
forceUpdate = false;
|
|
130
|
-
for (let [handler, computed] of subscriptions) {
|
|
131
|
-
computed.cleanup();
|
|
132
|
-
let cleanup = handler(val);
|
|
133
|
-
makeUnsubscribe(subscriptions, computed, handler, cleanup);
|
|
134
|
-
}
|
|
135
|
-
delayedUpdate();
|
|
136
|
-
}
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
return false;
|
|
140
|
-
},
|
|
141
|
-
get(state, prop) {
|
|
142
|
-
if (prop === "value") {
|
|
143
|
-
return typeof state.value === "function" ? state.value() : state.value;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (prop === "cleanup" || prop === "unsubscribe" || prop === "getter") {
|
|
147
|
-
return state[prop];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (prop in getters) {
|
|
151
|
-
return getters[prop](state.value);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
Object.defineProperties(signal, {
|
|
158
|
-
value: { value, writable: true, enumerable: true },
|
|
159
|
-
cleanup: {
|
|
160
|
-
value() {
|
|
161
|
-
// eslint-disable-next-line no-unused-vars
|
|
162
|
-
for (let [handler, computed] of subscriptions) {
|
|
163
|
-
computed.unsubscribe();
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
writable: true,
|
|
167
|
-
enumerable: true
|
|
168
|
-
},
|
|
169
|
-
getter: {
|
|
170
|
-
value(name: string, handler: Getter) {
|
|
171
|
-
if (name in getters) {
|
|
172
|
-
throw new Error("Named computed already exists.");
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
getters[name] = handler;
|
|
176
|
-
},
|
|
177
|
-
enumerable: true
|
|
178
|
-
}
|
|
179
|
-
});
|
|
90
|
+
// Assign the signal variable an array containing the get, set, and subscribe functions
|
|
91
|
+
let signal = [get, set, subscribe];
|
|
92
|
+
|
|
93
|
+
// If the context object has a vnode property, add the signal to the vnode's signals array
|
|
94
|
+
// and add the subscribers array to the vnode's subscribers array
|
|
95
|
+
if (context.vnode) {
|
|
96
|
+
context.vnode.signals.push(signal);
|
|
97
|
+
context.vnode.subscribers.push(subscribers);
|
|
98
|
+
}
|
|
180
99
|
|
|
100
|
+
// Return the signal
|
|
181
101
|
return signal;
|
|
182
102
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valyrian.js",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.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>",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"typescript": "^4.8.3"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@release-it/conventional-changelog": "^5.1.
|
|
86
|
+
"@release-it/conventional-changelog": "^5.1.1",
|
|
87
87
|
"@types/clean-css": "^4.2.5",
|
|
88
88
|
"@types/node": "^18.7.16",
|
|
89
89
|
"@types/node-fetch": "^2.6.2",
|
|
@@ -91,7 +91,6 @@
|
|
|
91
91
|
"@types/source-map": "^0.5.7",
|
|
92
92
|
"@typescript-eslint/eslint-plugin": "^5.36.2",
|
|
93
93
|
"@typescript-eslint/parser": "^5.36.2",
|
|
94
|
-
"browser-sync": "^2.27.10",
|
|
95
94
|
"buffalo-test": "^2.0.0",
|
|
96
95
|
"compression": "^1.7.4",
|
|
97
96
|
"cross-env": "^7.0.3",
|
|
@@ -100,7 +99,7 @@
|
|
|
100
99
|
"eslint": "^8.23.1",
|
|
101
100
|
"eslint-plugin-sonarjs": "^0.15.0",
|
|
102
101
|
"expect": "^29.0.3",
|
|
103
|
-
"fastify": "^4.
|
|
102
|
+
"fastify": "^4.10.2",
|
|
104
103
|
"gzip-size": "^7.0.0",
|
|
105
104
|
"mocha": "^10.0.0",
|
|
106
105
|
"nodemon": "^2.0.19",
|