@constela/server 9.0.0 → 10.0.1
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.js +297 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -125,9 +125,278 @@ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
125
125
|
"track",
|
|
126
126
|
"wbr"
|
|
127
127
|
]);
|
|
128
|
+
var SAFE_ARRAY_METHODS = /* @__PURE__ */ new Set([
|
|
129
|
+
"length",
|
|
130
|
+
"at",
|
|
131
|
+
"includes",
|
|
132
|
+
"slice",
|
|
133
|
+
"indexOf",
|
|
134
|
+
"join",
|
|
135
|
+
"filter",
|
|
136
|
+
"map",
|
|
137
|
+
"find",
|
|
138
|
+
"findIndex",
|
|
139
|
+
"some",
|
|
140
|
+
"every"
|
|
141
|
+
]);
|
|
142
|
+
var SAFE_STRING_METHODS = /* @__PURE__ */ new Set([
|
|
143
|
+
"length",
|
|
144
|
+
"charAt",
|
|
145
|
+
"substring",
|
|
146
|
+
"slice",
|
|
147
|
+
"split",
|
|
148
|
+
"trim",
|
|
149
|
+
"toUpperCase",
|
|
150
|
+
"toLowerCase",
|
|
151
|
+
"replace",
|
|
152
|
+
"includes",
|
|
153
|
+
"startsWith",
|
|
154
|
+
"endsWith",
|
|
155
|
+
"indexOf"
|
|
156
|
+
]);
|
|
157
|
+
var SAFE_MATH_METHODS = /* @__PURE__ */ new Set([
|
|
158
|
+
"min",
|
|
159
|
+
"max",
|
|
160
|
+
"round",
|
|
161
|
+
"floor",
|
|
162
|
+
"ceil",
|
|
163
|
+
"abs",
|
|
164
|
+
"sqrt",
|
|
165
|
+
"pow",
|
|
166
|
+
"random",
|
|
167
|
+
"sin",
|
|
168
|
+
"cos",
|
|
169
|
+
"tan"
|
|
170
|
+
]);
|
|
171
|
+
var SAFE_DATE_STATIC_METHODS = /* @__PURE__ */ new Set(["now", "parse"]);
|
|
172
|
+
var SAFE_DATE_INSTANCE_METHODS = /* @__PURE__ */ new Set([
|
|
173
|
+
"toISOString",
|
|
174
|
+
"toDateString",
|
|
175
|
+
"toTimeString",
|
|
176
|
+
"getTime",
|
|
177
|
+
"getFullYear",
|
|
178
|
+
"getMonth",
|
|
179
|
+
"getDate",
|
|
180
|
+
"getHours",
|
|
181
|
+
"getMinutes",
|
|
182
|
+
"getSeconds",
|
|
183
|
+
"getMilliseconds"
|
|
184
|
+
]);
|
|
128
185
|
function isEventHandler(value) {
|
|
129
186
|
return typeof value === "object" && value !== null && "event" in value && "action" in value;
|
|
130
187
|
}
|
|
188
|
+
function createLambdaFunction(lambda, ctx) {
|
|
189
|
+
return (item, index) => {
|
|
190
|
+
const lambdaLocals = {
|
|
191
|
+
...ctx.locals,
|
|
192
|
+
[lambda.param]: item
|
|
193
|
+
};
|
|
194
|
+
if (lambda.index !== void 0) {
|
|
195
|
+
lambdaLocals[lambda.index] = index;
|
|
196
|
+
}
|
|
197
|
+
return evaluate(lambda.body, { ...ctx, locals: lambdaLocals });
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function callArrayMethod(target, method, args, ctx, rawArgs) {
|
|
201
|
+
if (!SAFE_ARRAY_METHODS.has(method)) return void 0;
|
|
202
|
+
switch (method) {
|
|
203
|
+
case "length":
|
|
204
|
+
return target.length;
|
|
205
|
+
case "at": {
|
|
206
|
+
const index = typeof args[0] === "number" ? args[0] : 0;
|
|
207
|
+
return target.at(index);
|
|
208
|
+
}
|
|
209
|
+
case "includes": {
|
|
210
|
+
const searchElement = args[0];
|
|
211
|
+
const fromIndex = typeof args[1] === "number" ? args[1] : void 0;
|
|
212
|
+
return target.includes(searchElement, fromIndex);
|
|
213
|
+
}
|
|
214
|
+
case "slice": {
|
|
215
|
+
const start = typeof args[0] === "number" ? args[0] : void 0;
|
|
216
|
+
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
217
|
+
return target.slice(start, end);
|
|
218
|
+
}
|
|
219
|
+
case "indexOf": {
|
|
220
|
+
const searchElement = args[0];
|
|
221
|
+
const fromIndex = typeof args[1] === "number" ? args[1] : void 0;
|
|
222
|
+
return target.indexOf(searchElement, fromIndex);
|
|
223
|
+
}
|
|
224
|
+
case "join": {
|
|
225
|
+
const separator = typeof args[0] === "string" ? args[0] : ",";
|
|
226
|
+
return target.join(separator);
|
|
227
|
+
}
|
|
228
|
+
case "filter": {
|
|
229
|
+
const lambdaExpr = rawArgs?.[0];
|
|
230
|
+
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
231
|
+
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
232
|
+
return target.filter((item, index) => !!fn(item, index));
|
|
233
|
+
}
|
|
234
|
+
case "map": {
|
|
235
|
+
const lambdaExpr = rawArgs?.[0];
|
|
236
|
+
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
237
|
+
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
238
|
+
return target.map((item, index) => fn(item, index));
|
|
239
|
+
}
|
|
240
|
+
case "find": {
|
|
241
|
+
const lambdaExpr = rawArgs?.[0];
|
|
242
|
+
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
243
|
+
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
244
|
+
return target.find((item, index) => !!fn(item, index));
|
|
245
|
+
}
|
|
246
|
+
case "findIndex": {
|
|
247
|
+
const lambdaExpr = rawArgs?.[0];
|
|
248
|
+
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
249
|
+
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
250
|
+
return target.findIndex((item, index) => !!fn(item, index));
|
|
251
|
+
}
|
|
252
|
+
case "some": {
|
|
253
|
+
const lambdaExpr = rawArgs?.[0];
|
|
254
|
+
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
255
|
+
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
256
|
+
return target.some((item, index) => !!fn(item, index));
|
|
257
|
+
}
|
|
258
|
+
case "every": {
|
|
259
|
+
const lambdaExpr = rawArgs?.[0];
|
|
260
|
+
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
261
|
+
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
262
|
+
return target.every((item, index) => !!fn(item, index));
|
|
263
|
+
}
|
|
264
|
+
default:
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function callStringMethod(target, method, args) {
|
|
269
|
+
if (!SAFE_STRING_METHODS.has(method)) return void 0;
|
|
270
|
+
switch (method) {
|
|
271
|
+
case "length":
|
|
272
|
+
return target.length;
|
|
273
|
+
case "charAt": {
|
|
274
|
+
const index = typeof args[0] === "number" ? args[0] : 0;
|
|
275
|
+
return target.charAt(index);
|
|
276
|
+
}
|
|
277
|
+
case "substring": {
|
|
278
|
+
const start = typeof args[0] === "number" ? args[0] : 0;
|
|
279
|
+
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
280
|
+
return target.substring(start, end);
|
|
281
|
+
}
|
|
282
|
+
case "slice": {
|
|
283
|
+
const start = typeof args[0] === "number" ? args[0] : void 0;
|
|
284
|
+
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
285
|
+
return target.slice(start, end);
|
|
286
|
+
}
|
|
287
|
+
case "split": {
|
|
288
|
+
const separator = typeof args[0] === "string" ? args[0] : "";
|
|
289
|
+
return target.split(separator);
|
|
290
|
+
}
|
|
291
|
+
case "trim":
|
|
292
|
+
return target.trim();
|
|
293
|
+
case "toUpperCase":
|
|
294
|
+
return target.toUpperCase();
|
|
295
|
+
case "toLowerCase":
|
|
296
|
+
return target.toLowerCase();
|
|
297
|
+
case "replace": {
|
|
298
|
+
const search = typeof args[0] === "string" ? args[0] : "";
|
|
299
|
+
const replace = typeof args[1] === "string" ? args[1] : "";
|
|
300
|
+
return target.replace(search, replace);
|
|
301
|
+
}
|
|
302
|
+
case "includes": {
|
|
303
|
+
const search = typeof args[0] === "string" ? args[0] : "";
|
|
304
|
+
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
305
|
+
return target.includes(search, position);
|
|
306
|
+
}
|
|
307
|
+
case "startsWith": {
|
|
308
|
+
const search = typeof args[0] === "string" ? args[0] : "";
|
|
309
|
+
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
310
|
+
return target.startsWith(search, position);
|
|
311
|
+
}
|
|
312
|
+
case "endsWith": {
|
|
313
|
+
const search = typeof args[0] === "string" ? args[0] : "";
|
|
314
|
+
const length = typeof args[1] === "number" ? args[1] : void 0;
|
|
315
|
+
return target.endsWith(search, length);
|
|
316
|
+
}
|
|
317
|
+
case "indexOf": {
|
|
318
|
+
const search = typeof args[0] === "string" ? args[0] : "";
|
|
319
|
+
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
320
|
+
return target.indexOf(search, position);
|
|
321
|
+
}
|
|
322
|
+
default:
|
|
323
|
+
return void 0;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function callMathMethod(method, args) {
|
|
327
|
+
if (!SAFE_MATH_METHODS.has(method)) return void 0;
|
|
328
|
+
const numbers = args.filter((a) => typeof a === "number");
|
|
329
|
+
switch (method) {
|
|
330
|
+
case "min":
|
|
331
|
+
return numbers.length > 0 ? Math.min(...numbers) : void 0;
|
|
332
|
+
case "max":
|
|
333
|
+
return numbers.length > 0 ? Math.max(...numbers) : void 0;
|
|
334
|
+
case "round":
|
|
335
|
+
return numbers[0] !== void 0 ? Math.round(numbers[0]) : void 0;
|
|
336
|
+
case "floor":
|
|
337
|
+
return numbers[0] !== void 0 ? Math.floor(numbers[0]) : void 0;
|
|
338
|
+
case "ceil":
|
|
339
|
+
return numbers[0] !== void 0 ? Math.ceil(numbers[0]) : void 0;
|
|
340
|
+
case "abs":
|
|
341
|
+
return numbers[0] !== void 0 ? Math.abs(numbers[0]) : void 0;
|
|
342
|
+
case "sqrt":
|
|
343
|
+
return numbers[0] !== void 0 ? Math.sqrt(numbers[0]) : void 0;
|
|
344
|
+
case "pow":
|
|
345
|
+
return numbers[0] !== void 0 && numbers[1] !== void 0 ? Math.pow(numbers[0], numbers[1]) : void 0;
|
|
346
|
+
case "random":
|
|
347
|
+
return Math.random();
|
|
348
|
+
case "sin":
|
|
349
|
+
return numbers[0] !== void 0 ? Math.sin(numbers[0]) : void 0;
|
|
350
|
+
case "cos":
|
|
351
|
+
return numbers[0] !== void 0 ? Math.cos(numbers[0]) : void 0;
|
|
352
|
+
case "tan":
|
|
353
|
+
return numbers[0] !== void 0 ? Math.tan(numbers[0]) : void 0;
|
|
354
|
+
default:
|
|
355
|
+
return void 0;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function callDateStaticMethod(method, args) {
|
|
359
|
+
if (!SAFE_DATE_STATIC_METHODS.has(method)) return void 0;
|
|
360
|
+
switch (method) {
|
|
361
|
+
case "now":
|
|
362
|
+
return Date.now();
|
|
363
|
+
case "parse": {
|
|
364
|
+
const dateString = args[0];
|
|
365
|
+
return typeof dateString === "string" ? Date.parse(dateString) : void 0;
|
|
366
|
+
}
|
|
367
|
+
default:
|
|
368
|
+
return void 0;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function callDateInstanceMethod(target, method) {
|
|
372
|
+
if (!SAFE_DATE_INSTANCE_METHODS.has(method)) return void 0;
|
|
373
|
+
switch (method) {
|
|
374
|
+
case "toISOString":
|
|
375
|
+
return target.toISOString();
|
|
376
|
+
case "toDateString":
|
|
377
|
+
return target.toDateString();
|
|
378
|
+
case "toTimeString":
|
|
379
|
+
return target.toTimeString();
|
|
380
|
+
case "getTime":
|
|
381
|
+
return target.getTime();
|
|
382
|
+
case "getFullYear":
|
|
383
|
+
return target.getFullYear();
|
|
384
|
+
case "getMonth":
|
|
385
|
+
return target.getMonth();
|
|
386
|
+
case "getDate":
|
|
387
|
+
return target.getDate();
|
|
388
|
+
case "getHours":
|
|
389
|
+
return target.getHours();
|
|
390
|
+
case "getMinutes":
|
|
391
|
+
return target.getMinutes();
|
|
392
|
+
case "getSeconds":
|
|
393
|
+
return target.getSeconds();
|
|
394
|
+
case "getMilliseconds":
|
|
395
|
+
return target.getMilliseconds();
|
|
396
|
+
default:
|
|
397
|
+
return void 0;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
131
400
|
function evaluate(expr, ctx) {
|
|
132
401
|
switch (expr.expr) {
|
|
133
402
|
case "lit":
|
|
@@ -231,6 +500,34 @@ function evaluate(expr, ctx) {
|
|
|
231
500
|
case "validity": {
|
|
232
501
|
return false;
|
|
233
502
|
}
|
|
503
|
+
case "call": {
|
|
504
|
+
const callExpr = expr;
|
|
505
|
+
const target = evaluate(callExpr.target, ctx);
|
|
506
|
+
if (target == null) return void 0;
|
|
507
|
+
const args = callExpr.args?.map((arg) => {
|
|
508
|
+
if (arg.expr === "lambda") return arg;
|
|
509
|
+
return evaluate(arg, ctx);
|
|
510
|
+
}) ?? [];
|
|
511
|
+
if (Array.isArray(target)) {
|
|
512
|
+
return callArrayMethod(target, callExpr.method, args, ctx, callExpr.args);
|
|
513
|
+
}
|
|
514
|
+
if (typeof target === "string") {
|
|
515
|
+
return callStringMethod(target, callExpr.method, args);
|
|
516
|
+
}
|
|
517
|
+
if (target === Math) {
|
|
518
|
+
return callMathMethod(callExpr.method, args);
|
|
519
|
+
}
|
|
520
|
+
if (target === Date) {
|
|
521
|
+
return callDateStaticMethod(callExpr.method, args);
|
|
522
|
+
}
|
|
523
|
+
if (target instanceof Date) {
|
|
524
|
+
return callDateInstanceMethod(target, callExpr.method);
|
|
525
|
+
}
|
|
526
|
+
return void 0;
|
|
527
|
+
}
|
|
528
|
+
case "lambda": {
|
|
529
|
+
return void 0;
|
|
530
|
+
}
|
|
234
531
|
default: {
|
|
235
532
|
const _exhaustiveCheck = expr;
|
|
236
533
|
throw new Error(`Unknown expression type: ${JSON.stringify(_exhaustiveCheck)}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constela/server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.1",
|
|
4
4
|
"description": "Server-side rendering for Constela UI framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"@constela/compiler": "^0.
|
|
19
|
-
"@constela/core": "^0.
|
|
18
|
+
"@constela/compiler": "^0.13.0",
|
|
19
|
+
"@constela/core": "^0.14.0"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"isomorphic-dompurify": "^2.35.0",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"tsup": "^8.0.0",
|
|
30
30
|
"typescript": "^5.3.0",
|
|
31
31
|
"vitest": "^2.0.0",
|
|
32
|
-
"@constela/
|
|
33
|
-
"@constela/
|
|
32
|
+
"@constela/core": "0.14.0",
|
|
33
|
+
"@constela/compiler": "0.13.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=20.0.0"
|