@kernlang/core 3.3.5 → 3.3.7
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/codegen/ground-layer.d.ts +42 -0
- package/dist/codegen/ground-layer.js +886 -0
- package/dist/codegen/ground-layer.js.map +1 -1
- package/dist/codegen/machines.js +35 -3
- package/dist/codegen/machines.js.map +1 -1
- package/dist/codegen/screens.d.ts +11 -0
- package/dist/codegen/screens.js +76 -8
- package/dist/codegen/screens.js.map +1 -1
- package/dist/codegen-core.d.ts +2 -2
- package/dist/codegen-core.js +129 -3
- package/dist/codegen-core.js.map +1 -1
- package/dist/concepts.d.ts +50 -1
- package/dist/concepts.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/node-props.d.ts +226 -0
- package/dist/node-props.js.map +1 -1
- package/dist/schema.js +505 -6
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +2 -2
- package/dist/spec.js +44 -1
- package/dist/spec.js.map +1 -1
- package/package.json +1 -1
package/dist/schema.js
CHANGED
|
@@ -184,12 +184,14 @@ export const NODE_SCHEMAS = {
|
|
|
184
184
|
},
|
|
185
185
|
},
|
|
186
186
|
transition: {
|
|
187
|
-
description: 'A guarded transition between machine states, with optional handler',
|
|
188
|
-
example: 'transition name=
|
|
187
|
+
description: 'A guarded transition between machine states, with optional typed payload and/or guard predicate. `params` uses the same comma-separated typed list shape as `fn` (e.g. "prompt:string,chatId:string") — those parameters enter the emitted transition function signature and are in scope inside the handler and the guard. `guard` is a raw JS boolean expression evaluated AFTER the from-state check; when falsy the transition throws `<Machine>GuardError(\'<transition>\', entity.state)`.',
|
|
188
|
+
example: 'transition name=submit from=idle to=running params="prompt:string,chatId:string" guard="entity.turnsLeft > 0"\n handler <<<\n await notifyUser(prompt)\n >>>',
|
|
189
189
|
props: {
|
|
190
190
|
name: { required: true, kind: 'identifier' },
|
|
191
191
|
from: { required: true, kind: 'string' },
|
|
192
192
|
to: { required: true, kind: 'identifier' },
|
|
193
|
+
params: { kind: 'string' },
|
|
194
|
+
guard: { kind: 'rawExpr' },
|
|
193
195
|
},
|
|
194
196
|
allowedChildren: ['handler'],
|
|
195
197
|
},
|
|
@@ -319,6 +321,492 @@ export const NODE_SCHEMAS = {
|
|
|
319
321
|
},
|
|
320
322
|
allowedChildren: ['handler', 'recover'],
|
|
321
323
|
},
|
|
324
|
+
filter: {
|
|
325
|
+
description: 'Declarative `.filter` binding — `filter name=active in=items where="item.active"` lowers to `const active = items.filter(item => item.active);`. Use `item=x` to rename the per-item binding.',
|
|
326
|
+
example: 'filter name=active in=items where="item.active"',
|
|
327
|
+
props: {
|
|
328
|
+
name: { required: true, kind: 'identifier' },
|
|
329
|
+
in: { required: true, kind: 'rawExpr' },
|
|
330
|
+
item: { kind: 'identifier' },
|
|
331
|
+
where: { required: true, kind: 'rawExpr' },
|
|
332
|
+
type: { kind: 'typeAnnotation' },
|
|
333
|
+
export: { kind: 'boolean' },
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
find: {
|
|
337
|
+
description: "Declarative `.find` binding — `find name=admin in=users where=\"item.role === 'admin'\"` lowers to `const admin = users.find(item => item.role === 'admin');`. Use `item=x` to rename the per-item binding.",
|
|
338
|
+
example: 'find name=admin in=users item=u where="u.role === \'admin\'"',
|
|
339
|
+
props: {
|
|
340
|
+
name: { required: true, kind: 'identifier' },
|
|
341
|
+
in: { required: true, kind: 'rawExpr' },
|
|
342
|
+
item: { kind: 'identifier' },
|
|
343
|
+
where: { required: true, kind: 'rawExpr' },
|
|
344
|
+
type: { kind: 'typeAnnotation' },
|
|
345
|
+
export: { kind: 'boolean' },
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
some: {
|
|
349
|
+
description: 'Declarative `.some` binding — `some name=hasError in=results where="!item.ok"` lowers to `const hasError = results.some(item => !item.ok);`.',
|
|
350
|
+
example: 'some name=hasError in=results where="!item.ok"',
|
|
351
|
+
props: {
|
|
352
|
+
name: { required: true, kind: 'identifier' },
|
|
353
|
+
in: { required: true, kind: 'rawExpr' },
|
|
354
|
+
item: { kind: 'identifier' },
|
|
355
|
+
where: { required: true, kind: 'rawExpr' },
|
|
356
|
+
type: { kind: 'typeAnnotation' },
|
|
357
|
+
export: { kind: 'boolean' },
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
every: {
|
|
361
|
+
description: 'Declarative `.every` binding — `every name=allDone in=tasks where="item.done"` lowers to `const allDone = tasks.every(item => item.done);`.',
|
|
362
|
+
example: 'every name=allDone in=tasks where="item.done"',
|
|
363
|
+
props: {
|
|
364
|
+
name: { required: true, kind: 'identifier' },
|
|
365
|
+
in: { required: true, kind: 'rawExpr' },
|
|
366
|
+
item: { kind: 'identifier' },
|
|
367
|
+
where: { required: true, kind: 'rawExpr' },
|
|
368
|
+
type: { kind: 'typeAnnotation' },
|
|
369
|
+
export: { kind: 'boolean' },
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
reduce: {
|
|
373
|
+
description: 'Declarative `.reduce` binding — two bound names (accumulator + item). `reduce name=total in=items initial="0" expr="acc + item.value"` lowers to `const total = items.reduce((acc, item) => acc + item.value, 0);`. Override the binding names with `acc=` and `item=`.',
|
|
374
|
+
example: 'reduce name=total in=items initial="0" expr="acc + item.value"',
|
|
375
|
+
props: {
|
|
376
|
+
name: { required: true, kind: 'identifier' },
|
|
377
|
+
in: { required: true, kind: 'rawExpr' },
|
|
378
|
+
acc: { kind: 'identifier' },
|
|
379
|
+
item: { kind: 'identifier' },
|
|
380
|
+
initial: { required: true, kind: 'rawExpr' },
|
|
381
|
+
expr: { required: true, kind: 'rawExpr' },
|
|
382
|
+
type: { kind: 'typeAnnotation' },
|
|
383
|
+
export: { kind: 'boolean' },
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
flatMap: {
|
|
387
|
+
description: 'Declarative `.flatMap` binding — `flatMap name=tags in=posts expr="item.tags"` lowers to `const tags = posts.flatMap(item => item.tags);`. Use `item=` to rename the per-item binding. `expr` is the arrow body (an array or iterable), not a predicate.',
|
|
388
|
+
example: 'flatMap name=tags in=posts expr="item.tags"',
|
|
389
|
+
props: {
|
|
390
|
+
name: { required: true, kind: 'identifier' },
|
|
391
|
+
in: { required: true, kind: 'rawExpr' },
|
|
392
|
+
item: { kind: 'identifier' },
|
|
393
|
+
expr: { required: true, kind: 'rawExpr' },
|
|
394
|
+
type: { kind: 'typeAnnotation' },
|
|
395
|
+
export: { kind: 'boolean' },
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
slice: {
|
|
399
|
+
description: 'Declarative `.slice` binding — `slice name=first5 in=items start=0 end=5` lowers to `const first5 = items.slice(0, 5);`. `start` and `end` default to undefined (JS semantics: a bare `.slice()` copies the whole array).',
|
|
400
|
+
example: 'slice name=first5 in=items start=0 end=5',
|
|
401
|
+
props: {
|
|
402
|
+
name: { required: true, kind: 'identifier' },
|
|
403
|
+
in: { required: true, kind: 'rawExpr' },
|
|
404
|
+
start: { kind: 'rawExpr' },
|
|
405
|
+
end: { kind: 'rawExpr' },
|
|
406
|
+
type: { kind: 'typeAnnotation' },
|
|
407
|
+
export: { kind: 'boolean' },
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
map: {
|
|
411
|
+
description: 'Declarative `.map` binding — `map name=names in=users expr="item.name"` lowers to `const names = users.map(item => item.name);`. Sibling to `each` (JSX iteration form); use `map` for data-transformation bindings. `expr` is the arrow body.',
|
|
412
|
+
example: 'map name=names in=users expr="item.name"',
|
|
413
|
+
props: {
|
|
414
|
+
name: { required: true, kind: 'identifier' },
|
|
415
|
+
in: { required: true, kind: 'rawExpr' },
|
|
416
|
+
item: { kind: 'identifier' },
|
|
417
|
+
expr: { required: true, kind: 'rawExpr' },
|
|
418
|
+
type: { kind: 'typeAnnotation' },
|
|
419
|
+
export: { kind: 'boolean' },
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
findIndex: {
|
|
423
|
+
description: 'Declarative `.findIndex` binding — `findIndex name=pos in=users where="item.active"` lowers to `const pos = users.findIndex(item => item.active);`. Returns a number; add `type=number` when the binding is exported.',
|
|
424
|
+
example: 'findIndex name=pos in=users where="item.active"',
|
|
425
|
+
props: {
|
|
426
|
+
name: { required: true, kind: 'identifier' },
|
|
427
|
+
in: { required: true, kind: 'rawExpr' },
|
|
428
|
+
item: { kind: 'identifier' },
|
|
429
|
+
where: { required: true, kind: 'rawExpr' },
|
|
430
|
+
type: { kind: 'typeAnnotation' },
|
|
431
|
+
export: { kind: 'boolean' },
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
flat: {
|
|
435
|
+
description: 'Declarative `.flat` binding — `flat name=flattened in=nested depth=2` lowers to `const flattened = nested.flat(2);`. Omit `depth` for the default depth of 1.',
|
|
436
|
+
example: 'flat name=flattened in=nested depth=2',
|
|
437
|
+
props: {
|
|
438
|
+
name: { required: true, kind: 'identifier' },
|
|
439
|
+
in: { required: true, kind: 'rawExpr' },
|
|
440
|
+
depth: { kind: 'rawExpr' },
|
|
441
|
+
type: { kind: 'typeAnnotation' },
|
|
442
|
+
export: { kind: 'boolean' },
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
at: {
|
|
446
|
+
description: 'Declarative `.at` binding — `at name=last in=items index=-1` lowers to `const last = items.at(-1);`. Supports negative indices for tail access.',
|
|
447
|
+
example: 'at name=last in=items index=-1',
|
|
448
|
+
props: {
|
|
449
|
+
name: { required: true, kind: 'identifier' },
|
|
450
|
+
in: { required: true, kind: 'rawExpr' },
|
|
451
|
+
index: { required: true, kind: 'rawExpr' },
|
|
452
|
+
type: { kind: 'typeAnnotation' },
|
|
453
|
+
export: { kind: 'boolean' },
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
sort: {
|
|
457
|
+
description: 'Declarative immutable sort — `sort name=sorted in=items compare="a.age - b.age"` lowers to `const sorted = [...items].sort((a, b) => a.age - b.age);`. Source collection is never mutated. Omit `compare` for lexicographic sort. Rename bindings with `a=` / `b=`.',
|
|
458
|
+
example: 'sort name=sorted in=items compare="a.age - b.age"',
|
|
459
|
+
props: {
|
|
460
|
+
name: { required: true, kind: 'identifier' },
|
|
461
|
+
in: { required: true, kind: 'rawExpr' },
|
|
462
|
+
a: { kind: 'identifier' },
|
|
463
|
+
b: { kind: 'identifier' },
|
|
464
|
+
compare: { kind: 'rawExpr' },
|
|
465
|
+
type: { kind: 'typeAnnotation' },
|
|
466
|
+
export: { kind: 'boolean' },
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
reverse: {
|
|
470
|
+
description: 'Declarative immutable reverse — `reverse name=reversed in=items` lowers to `const reversed = [...items].reverse();`. Source collection is never mutated.',
|
|
471
|
+
example: 'reverse name=reversed in=items',
|
|
472
|
+
props: {
|
|
473
|
+
name: { required: true, kind: 'identifier' },
|
|
474
|
+
in: { required: true, kind: 'rawExpr' },
|
|
475
|
+
type: { kind: 'typeAnnotation' },
|
|
476
|
+
export: { kind: 'boolean' },
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
join: {
|
|
480
|
+
description: 'Declarative `.join` binding — `join name=csv in=fields separator=","` lowers to `const csv = fields.join(\',\');`. Omit `separator` for the default (`,`). The separator is emitted as a quoted string literal unless wrapped as `{{ expr }}`.',
|
|
481
|
+
example: 'join name=csv in=fields separator=","',
|
|
482
|
+
props: {
|
|
483
|
+
name: { required: true, kind: 'identifier' },
|
|
484
|
+
in: { required: true, kind: 'rawExpr' },
|
|
485
|
+
separator: { kind: 'rawExpr' },
|
|
486
|
+
type: { kind: 'typeAnnotation' },
|
|
487
|
+
export: { kind: 'boolean' },
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
includes: {
|
|
491
|
+
description: "Declarative `.includes` binding — `includes name=hasError in=errors value=\"'fatal'\"` lowers to `const hasError = errors.includes('fatal');`. `value` is a raw expression — quote string literals inside it.",
|
|
492
|
+
example: 'includes name=hasError in=errors value="\'fatal\'"',
|
|
493
|
+
props: {
|
|
494
|
+
name: { required: true, kind: 'identifier' },
|
|
495
|
+
in: { required: true, kind: 'rawExpr' },
|
|
496
|
+
value: { required: true, kind: 'rawExpr' },
|
|
497
|
+
from: { kind: 'rawExpr' },
|
|
498
|
+
type: { kind: 'typeAnnotation' },
|
|
499
|
+
export: { kind: 'boolean' },
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
indexOf: {
|
|
503
|
+
description: 'Declarative `.indexOf` binding — `indexOf name=pos in=items value=target` lowers to `const pos = items.indexOf(target);`. `value` is a raw expression.',
|
|
504
|
+
example: 'indexOf name=pos in=items value=target',
|
|
505
|
+
props: {
|
|
506
|
+
name: { required: true, kind: 'identifier' },
|
|
507
|
+
in: { required: true, kind: 'rawExpr' },
|
|
508
|
+
value: { required: true, kind: 'rawExpr' },
|
|
509
|
+
from: { kind: 'rawExpr' },
|
|
510
|
+
type: { kind: 'typeAnnotation' },
|
|
511
|
+
export: { kind: 'boolean' },
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
lastIndexOf: {
|
|
515
|
+
description: 'Declarative `.lastIndexOf` binding — `lastIndexOf name=pos in=items value=target` lowers to `const pos = items.lastIndexOf(target);`. `value` is a raw expression.',
|
|
516
|
+
example: 'lastIndexOf name=pos in=items value=target',
|
|
517
|
+
props: {
|
|
518
|
+
name: { required: true, kind: 'identifier' },
|
|
519
|
+
in: { required: true, kind: 'rawExpr' },
|
|
520
|
+
value: { required: true, kind: 'rawExpr' },
|
|
521
|
+
from: { kind: 'rawExpr' },
|
|
522
|
+
type: { kind: 'typeAnnotation' },
|
|
523
|
+
export: { kind: 'boolean' },
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
concat: {
|
|
527
|
+
description: 'Declarative `.concat` binding — `concat name=all in=items with="a, b"` lowers to `const all = items.concat(a, b);`. `with` is a raw expression injected directly — supports a single arg or comma-separated spread.',
|
|
528
|
+
example: 'concat name=all in=items with=other',
|
|
529
|
+
props: {
|
|
530
|
+
name: { required: true, kind: 'identifier' },
|
|
531
|
+
in: { required: true, kind: 'rawExpr' },
|
|
532
|
+
with: { required: true, kind: 'rawExpr' },
|
|
533
|
+
type: { kind: 'typeAnnotation' },
|
|
534
|
+
export: { kind: 'boolean' },
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
forEach: {
|
|
538
|
+
description: 'Declarative `.forEach` statement — `forEach in=items` with a `handler <<<>>>` child lowers to `items.forEach((item) => { handler-body });`. No binding (no `name`, no `const`). Distinct from `each` (JSX composition) and `map` (value binding). Use `item=` / `index=` to rename the parameters.',
|
|
539
|
+
example: 'forEach in=items\n handler <<<\n doSomething(item);\n >>>',
|
|
540
|
+
props: {
|
|
541
|
+
in: { required: true, kind: 'rawExpr' },
|
|
542
|
+
item: { kind: 'identifier' },
|
|
543
|
+
index: { kind: 'identifier' },
|
|
544
|
+
},
|
|
545
|
+
allowedChildren: ['handler'],
|
|
546
|
+
},
|
|
547
|
+
compact: {
|
|
548
|
+
description: 'Declarative `.filter(Boolean)` binding — `compact name=truthy in=items` lowers to `const truthy = items.filter(Boolean);`. Named primitive for the common "drop falsy values" pattern (36 sites in agon).',
|
|
549
|
+
example: 'compact name=truthy in=items',
|
|
550
|
+
props: {
|
|
551
|
+
name: { required: true, kind: 'identifier' },
|
|
552
|
+
in: { required: true, kind: 'rawExpr' },
|
|
553
|
+
type: { kind: 'typeAnnotation' },
|
|
554
|
+
export: { kind: 'boolean' },
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
pluck: {
|
|
558
|
+
description: 'Declarative property-extraction map — `pluck name=names in=users prop=name` lowers to `const names = users.map(item => item.name);`. `prop=` is a raw identifier path (e.g. `prop=user.profile.name` emits `item.user.profile.name`). Use `map` when the projection is not a property access.',
|
|
559
|
+
example: 'pluck name=names in=users prop=name',
|
|
560
|
+
props: {
|
|
561
|
+
name: { required: true, kind: 'identifier' },
|
|
562
|
+
in: { required: true, kind: 'rawExpr' },
|
|
563
|
+
item: { kind: 'identifier' },
|
|
564
|
+
prop: { required: true, kind: 'rawExpr' },
|
|
565
|
+
type: { kind: 'typeAnnotation' },
|
|
566
|
+
export: { kind: 'boolean' },
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
unique: {
|
|
570
|
+
description: 'Declarative dedupe — `unique name=distinct in=items` lowers to `const distinct = [...new Set(items)];`. Uses JS `Set` identity (triple-equals on primitives, reference equality on objects). For key-based dedup of object arrays, use `uniqueBy`.',
|
|
571
|
+
example: 'unique name=distinct in=items',
|
|
572
|
+
props: {
|
|
573
|
+
name: { required: true, kind: 'identifier' },
|
|
574
|
+
in: { required: true, kind: 'rawExpr' },
|
|
575
|
+
type: { kind: 'typeAnnotation' },
|
|
576
|
+
export: { kind: 'boolean' },
|
|
577
|
+
},
|
|
578
|
+
},
|
|
579
|
+
uniqueBy: {
|
|
580
|
+
description: 'Key-based dedup (first-wins, matches Lodash uniqBy) — `uniqueBy name=distinct in=users by="item.id"` emits a Set+filter form.',
|
|
581
|
+
example: 'uniqueBy name=distinct in=users by="item.id"',
|
|
582
|
+
props: {
|
|
583
|
+
name: { required: true, kind: 'identifier' },
|
|
584
|
+
in: { required: true, kind: 'rawExpr' },
|
|
585
|
+
item: { kind: 'identifier' },
|
|
586
|
+
by: { required: true, kind: 'rawExpr' },
|
|
587
|
+
type: { kind: 'typeAnnotation' },
|
|
588
|
+
export: { kind: 'boolean' },
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
groupBy: {
|
|
592
|
+
description: 'Partition an array into buckets by a key selector. Emits a reduce-based form (compatible with ES2022) — does not depend on `Object.groupBy` (ES2024).',
|
|
593
|
+
example: 'groupBy name=byType in=items by="item.type"',
|
|
594
|
+
props: {
|
|
595
|
+
name: { required: true, kind: 'identifier' },
|
|
596
|
+
in: { required: true, kind: 'rawExpr' },
|
|
597
|
+
item: { kind: 'identifier' },
|
|
598
|
+
by: { required: true, kind: 'rawExpr' },
|
|
599
|
+
type: { kind: 'typeAnnotation' },
|
|
600
|
+
export: { kind: 'boolean' },
|
|
601
|
+
},
|
|
602
|
+
},
|
|
603
|
+
partition: {
|
|
604
|
+
description: 'Split an array into two by a predicate — single-pass reduce. Emits `const [pass, fail] = ...`. Both `pass` and `fail` prop names are required.',
|
|
605
|
+
example: 'partition pass=active fail=inactive in=users where="item.active"',
|
|
606
|
+
props: {
|
|
607
|
+
name: { kind: 'identifier' },
|
|
608
|
+
pass: { required: true, kind: 'identifier' },
|
|
609
|
+
fail: { required: true, kind: 'identifier' },
|
|
610
|
+
in: { required: true, kind: 'rawExpr' },
|
|
611
|
+
item: { kind: 'identifier' },
|
|
612
|
+
where: { required: true, kind: 'rawExpr' },
|
|
613
|
+
type: { kind: 'typeAnnotation' },
|
|
614
|
+
export: { kind: 'boolean' },
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
indexBy: {
|
|
618
|
+
description: 'Array → keyed record via selector. `indexBy name=byId in=users by="item.id"` lowers to `Object.fromEntries(users.map(...))`. Collisions are last-write-wins.',
|
|
619
|
+
example: 'indexBy name=byId in=users by="item.id"',
|
|
620
|
+
props: {
|
|
621
|
+
name: { required: true, kind: 'identifier' },
|
|
622
|
+
in: { required: true, kind: 'rawExpr' },
|
|
623
|
+
item: { kind: 'identifier' },
|
|
624
|
+
by: { required: true, kind: 'rawExpr' },
|
|
625
|
+
type: { kind: 'typeAnnotation' },
|
|
626
|
+
export: { kind: 'boolean' },
|
|
627
|
+
},
|
|
628
|
+
},
|
|
629
|
+
countBy: {
|
|
630
|
+
description: 'Count occurrences by key. `countBy name=counts in=items by="item.type"` lowers to a reduce with `Object.create(null)` accumulator (prototype-pollution safe).',
|
|
631
|
+
example: 'countBy name=counts in=items by="item.type"',
|
|
632
|
+
props: {
|
|
633
|
+
name: { required: true, kind: 'identifier' },
|
|
634
|
+
in: { required: true, kind: 'rawExpr' },
|
|
635
|
+
item: { kind: 'identifier' },
|
|
636
|
+
by: { required: true, kind: 'rawExpr' },
|
|
637
|
+
type: { kind: 'typeAnnotation' },
|
|
638
|
+
export: { kind: 'boolean' },
|
|
639
|
+
},
|
|
640
|
+
},
|
|
641
|
+
chunk: {
|
|
642
|
+
description: 'Split into fixed-size chunks. `chunk name=batches in=items size=10`.',
|
|
643
|
+
example: 'chunk name=batches in=items size=10',
|
|
644
|
+
props: {
|
|
645
|
+
name: { required: true, kind: 'identifier' },
|
|
646
|
+
in: { required: true, kind: 'rawExpr' },
|
|
647
|
+
size: { required: true, kind: 'rawExpr' },
|
|
648
|
+
type: { kind: 'typeAnnotation' },
|
|
649
|
+
export: { kind: 'boolean' },
|
|
650
|
+
},
|
|
651
|
+
},
|
|
652
|
+
zip: {
|
|
653
|
+
description: 'Pair two arrays element-wise. `zip name=pairs in=items with=other`. Short-side wins — extra right-hand elements are dropped.',
|
|
654
|
+
example: 'zip name=pairs in=items with=other',
|
|
655
|
+
props: {
|
|
656
|
+
name: { required: true, kind: 'identifier' },
|
|
657
|
+
in: { required: true, kind: 'rawExpr' },
|
|
658
|
+
with: { required: true, kind: 'rawExpr' },
|
|
659
|
+
item: { kind: 'identifier' },
|
|
660
|
+
index: { kind: 'identifier' },
|
|
661
|
+
type: { kind: 'typeAnnotation' },
|
|
662
|
+
export: { kind: 'boolean' },
|
|
663
|
+
},
|
|
664
|
+
},
|
|
665
|
+
range: {
|
|
666
|
+
description: 'Generate a numeric range. `range name=nums end=10` → `[0..9]`. `range name=nums start=5 end=10` → `[5..9]`. No `step` in v1.',
|
|
667
|
+
example: 'range name=nums end=10',
|
|
668
|
+
props: {
|
|
669
|
+
name: { required: true, kind: 'identifier' },
|
|
670
|
+
start: { kind: 'rawExpr' },
|
|
671
|
+
end: { required: true, kind: 'rawExpr' },
|
|
672
|
+
type: { kind: 'typeAnnotation' },
|
|
673
|
+
export: { kind: 'boolean' },
|
|
674
|
+
},
|
|
675
|
+
},
|
|
676
|
+
take: {
|
|
677
|
+
description: 'First N elements. Alias for `slice(0, n)` but named for intent clarity.',
|
|
678
|
+
example: 'take name=first5 in=items n=5',
|
|
679
|
+
props: {
|
|
680
|
+
name: { required: true, kind: 'identifier' },
|
|
681
|
+
in: { required: true, kind: 'rawExpr' },
|
|
682
|
+
n: { required: true, kind: 'rawExpr' },
|
|
683
|
+
type: { kind: 'typeAnnotation' },
|
|
684
|
+
export: { kind: 'boolean' },
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
drop: {
|
|
688
|
+
description: 'Drop first N elements. Alias for `slice(n)` but named for intent clarity.',
|
|
689
|
+
example: 'drop name=tail in=items n=5',
|
|
690
|
+
props: {
|
|
691
|
+
name: { required: true, kind: 'identifier' },
|
|
692
|
+
in: { required: true, kind: 'rawExpr' },
|
|
693
|
+
n: { required: true, kind: 'rawExpr' },
|
|
694
|
+
type: { kind: 'typeAnnotation' },
|
|
695
|
+
export: { kind: 'boolean' },
|
|
696
|
+
},
|
|
697
|
+
},
|
|
698
|
+
min: {
|
|
699
|
+
description: 'Scalar min on a number array. Returns `undefined` on empty. Reduce-based — no stack-overflow risk on huge arrays.',
|
|
700
|
+
example: 'min name=lowest in=values',
|
|
701
|
+
props: {
|
|
702
|
+
name: { required: true, kind: 'identifier' },
|
|
703
|
+
in: { required: true, kind: 'rawExpr' },
|
|
704
|
+
type: { kind: 'typeAnnotation' },
|
|
705
|
+
export: { kind: 'boolean' },
|
|
706
|
+
},
|
|
707
|
+
},
|
|
708
|
+
max: {
|
|
709
|
+
description: 'Scalar max on a number array. Returns `undefined` on empty. Reduce-based — no stack-overflow risk on huge arrays.',
|
|
710
|
+
example: 'max name=highest in=values',
|
|
711
|
+
props: {
|
|
712
|
+
name: { required: true, kind: 'identifier' },
|
|
713
|
+
in: { required: true, kind: 'rawExpr' },
|
|
714
|
+
type: { kind: 'typeAnnotation' },
|
|
715
|
+
export: { kind: 'boolean' },
|
|
716
|
+
},
|
|
717
|
+
},
|
|
718
|
+
minBy: {
|
|
719
|
+
description: 'Find the element with the minimum key. `minBy name=youngest in=users by="item.age"`. Returns `undefined` on empty.',
|
|
720
|
+
example: 'minBy name=youngest in=users by="item.age"',
|
|
721
|
+
props: {
|
|
722
|
+
name: { required: true, kind: 'identifier' },
|
|
723
|
+
in: { required: true, kind: 'rawExpr' },
|
|
724
|
+
item: { kind: 'identifier' },
|
|
725
|
+
by: { required: true, kind: 'rawExpr' },
|
|
726
|
+
type: { kind: 'typeAnnotation' },
|
|
727
|
+
export: { kind: 'boolean' },
|
|
728
|
+
},
|
|
729
|
+
},
|
|
730
|
+
maxBy: {
|
|
731
|
+
description: 'Find the element with the maximum key. `maxBy name=oldest in=users by="item.age"`. Returns `undefined` on empty.',
|
|
732
|
+
example: 'maxBy name=oldest in=users by="item.age"',
|
|
733
|
+
props: {
|
|
734
|
+
name: { required: true, kind: 'identifier' },
|
|
735
|
+
in: { required: true, kind: 'rawExpr' },
|
|
736
|
+
item: { kind: 'identifier' },
|
|
737
|
+
by: { required: true, kind: 'rawExpr' },
|
|
738
|
+
type: { kind: 'typeAnnotation' },
|
|
739
|
+
export: { kind: 'boolean' },
|
|
740
|
+
},
|
|
741
|
+
},
|
|
742
|
+
sum: {
|
|
743
|
+
description: 'Sum of a number array. Returns `0` on empty (additive identity).',
|
|
744
|
+
example: 'sum name=total in=prices',
|
|
745
|
+
props: {
|
|
746
|
+
name: { required: true, kind: 'identifier' },
|
|
747
|
+
in: { required: true, kind: 'rawExpr' },
|
|
748
|
+
type: { kind: 'typeAnnotation' },
|
|
749
|
+
export: { kind: 'boolean' },
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
sumBy: {
|
|
753
|
+
description: 'Sum via key selector. `sumBy name=totalCost in=items by="item.price * item.qty"`.',
|
|
754
|
+
example: 'sumBy name=totalCost in=items by="item.price * item.qty"',
|
|
755
|
+
props: {
|
|
756
|
+
name: { required: true, kind: 'identifier' },
|
|
757
|
+
in: { required: true, kind: 'rawExpr' },
|
|
758
|
+
item: { kind: 'identifier' },
|
|
759
|
+
by: { required: true, kind: 'rawExpr' },
|
|
760
|
+
type: { kind: 'typeAnnotation' },
|
|
761
|
+
export: { kind: 'boolean' },
|
|
762
|
+
},
|
|
763
|
+
},
|
|
764
|
+
avg: {
|
|
765
|
+
description: 'Mean of a number array. Returns `NaN` on empty (Lodash parity — preserves the "no data" signal).',
|
|
766
|
+
example: 'avg name=mean in=prices',
|
|
767
|
+
props: {
|
|
768
|
+
name: { required: true, kind: 'identifier' },
|
|
769
|
+
in: { required: true, kind: 'rawExpr' },
|
|
770
|
+
type: { kind: 'typeAnnotation' },
|
|
771
|
+
export: { kind: 'boolean' },
|
|
772
|
+
},
|
|
773
|
+
},
|
|
774
|
+
intersect: {
|
|
775
|
+
description: 'Set intersection of two arrays. `intersect name=shared in=a with=b`. O(N+M) via a Set.',
|
|
776
|
+
example: 'intersect name=shared in=a with=b',
|
|
777
|
+
props: {
|
|
778
|
+
name: { required: true, kind: 'identifier' },
|
|
779
|
+
in: { required: true, kind: 'rawExpr' },
|
|
780
|
+
with: { required: true, kind: 'rawExpr' },
|
|
781
|
+
item: { kind: 'identifier' },
|
|
782
|
+
type: { kind: 'typeAnnotation' },
|
|
783
|
+
export: { kind: 'boolean' },
|
|
784
|
+
},
|
|
785
|
+
},
|
|
786
|
+
findLast: {
|
|
787
|
+
description: 'ES2023 counterpart to `find` — iterate from the end. `findLast name=lastActive in=users where="item.active"`.',
|
|
788
|
+
example: 'findLast name=lastActive in=users where="item.active"',
|
|
789
|
+
props: {
|
|
790
|
+
name: { required: true, kind: 'identifier' },
|
|
791
|
+
in: { required: true, kind: 'rawExpr' },
|
|
792
|
+
item: { kind: 'identifier' },
|
|
793
|
+
where: { required: true, kind: 'rawExpr' },
|
|
794
|
+
type: { kind: 'typeAnnotation' },
|
|
795
|
+
export: { kind: 'boolean' },
|
|
796
|
+
},
|
|
797
|
+
},
|
|
798
|
+
findLastIndex: {
|
|
799
|
+
description: 'ES2023 counterpart to `findIndex` — iterate from the end. `findLastIndex name=pos in=users where="item.active"`.',
|
|
800
|
+
example: 'findLastIndex name=pos in=users where="item.active"',
|
|
801
|
+
props: {
|
|
802
|
+
name: { required: true, kind: 'identifier' },
|
|
803
|
+
in: { required: true, kind: 'rawExpr' },
|
|
804
|
+
item: { kind: 'identifier' },
|
|
805
|
+
where: { required: true, kind: 'rawExpr' },
|
|
806
|
+
type: { kind: 'typeAnnotation' },
|
|
807
|
+
export: { kind: 'boolean' },
|
|
808
|
+
},
|
|
809
|
+
},
|
|
322
810
|
transform: {
|
|
323
811
|
description: 'Data transformation pipeline — maps target through a via function or handler',
|
|
324
812
|
example: 'transform name=normalized target=rawData via=normalize type=NormalizedData',
|
|
@@ -430,6 +918,15 @@ export const NODE_SCHEMAS = {
|
|
|
430
918
|
type: { kind: 'typeAnnotation' },
|
|
431
919
|
},
|
|
432
920
|
},
|
|
921
|
+
local: {
|
|
922
|
+
description: 'Render-scope binding — emits `const name = expr;` at the top of the enclosing screen function, before its JSX return. Use for shared pre-compute that multiple sibling `each`/`conditional`/`handler` nodes inside the same `render` block read. Expression-only (no handler body) — drop to an explicit `derive` / `memo` above the render if a hook or imperative body is needed. Direct child of `render` only.',
|
|
923
|
+
example: 'render wrapper="<Box paddingX={1}>"\n local name=visible expr="items.slice(start, start + pageSize)"\n each name=item in=visible\n handler <<< <Text>{item.label}</Text> >>>',
|
|
924
|
+
props: {
|
|
925
|
+
name: { required: true, kind: 'identifier' },
|
|
926
|
+
expr: { required: true, kind: 'rawExpr' },
|
|
927
|
+
type: { kind: 'typeAnnotation' },
|
|
928
|
+
},
|
|
929
|
+
},
|
|
433
930
|
collect: {
|
|
434
931
|
description: 'Query/collect from a data source with optional filter, sort, and limit',
|
|
435
932
|
example: 'collect name=activeUsers from=users where="u => u.active" order="u => u.name" limit=10',
|
|
@@ -1123,10 +1620,12 @@ export const NODE_SCHEMAS = {
|
|
|
1123
1620
|
},
|
|
1124
1621
|
},
|
|
1125
1622
|
render: {
|
|
1126
|
-
description: 'Render function — JSX output block for a component or hook. Accepts a raw `handler` block OR declarative KERN children (
|
|
1127
|
-
example: 'render\n
|
|
1128
|
-
props: {
|
|
1129
|
-
|
|
1623
|
+
description: 'Render function — JSX output block for a component or hook. Accepts a raw `handler` block OR declarative KERN children (`each`, `conditional`, `local`) that compose into a JSX tree. Optional `wrapper="<Tag attrs>"` prop emits that tag as the outer element around the composed children (replaces the default `<>...</>` Fragment). `local` children emit `const name = expr;` bindings at the enclosing screen-function scope before the return — use them for shared pre-compute that multiple sibling `each`/`conditional`/`handler` nodes read.',
|
|
1624
|
+
example: 'render wrapper="<Box paddingX={1}>"\n local name=visible expr="items.slice(start, start + pageSize)"\n each name=item in=visible\n handler <<< <Text>{item.label}</Text> >>>',
|
|
1625
|
+
props: {
|
|
1626
|
+
wrapper: { kind: 'string' },
|
|
1627
|
+
},
|
|
1628
|
+
allowedChildren: ['handler', 'each', 'conditional', 'local'],
|
|
1130
1629
|
},
|
|
1131
1630
|
template: {
|
|
1132
1631
|
description: 'Reusable template with named slots — defines a composable layout pattern',
|