@jxsuite/compiler 0.23.2 → 0.25.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.
@@ -5,6 +5,8 @@
5
5
  * Schema 2020-12 class definition.
6
6
  */
7
7
 
8
+ import type { JxMutableNode } from "@jxsuite/schema/types";
9
+
8
10
  /**
9
11
  * Compile a .class.json schema to a JavaScript ES module string.
10
12
  *
@@ -12,18 +14,17 @@
12
14
  * @param {Record<string, unknown>} [_opts]
13
15
  * @returns {string} JavaScript module source code
14
16
  */
15
- export function compileClassJson(classDef, _opts = {}) {
17
+ export function compileClassJson(classDef: JxMutableNode, _opts: Record<string, unknown> = {}) {
16
18
  const className = classDef.title;
17
19
  if (!className) throw new Error("compileClassJson: missing title (class name)");
18
20
 
19
21
  const baseClass = resolveBaseClass(classDef.extends);
20
- const defs = /** @type {Record<string, unknown> | undefined} */ (classDef.$defs);
21
- const fields = /** @type {Record<string, JxMutableNode>} */ (defs?.fields ?? {});
22
- const ctor = /** @type {JxMutableNode | undefined} */ (defs?.constructor);
23
- const methods = /** @type {Record<string, JxMutableNode>} */ (defs?.methods ?? {});
22
+ const defs = classDef.$defs as Record<string, unknown> | undefined;
23
+ const fields = (defs?.fields ?? {}) as Record<string, JxMutableNode>;
24
+ const ctor = defs?.constructor as JxMutableNode | undefined;
25
+ const methods = (defs?.methods ?? {}) as Record<string, JxMutableNode>;
24
26
 
25
- /** @type {string[]} */
26
- const lines = [];
27
+ const lines: string[] = [];
27
28
  lines.push("// Generated by @jxsuite/compiler from .class.json — do not edit manually");
28
29
  if (classDef.$id) lines.push(`// Source: ${classDef.$id}`);
29
30
  lines.push("");
@@ -34,7 +35,7 @@ export function compileClassJson(classDef, _opts = {}) {
34
35
 
35
36
  // Static fields
36
37
  for (const [key, field] of Object.entries(fields)) {
37
- const f = /** @type {JxMutableNode} */ (field);
38
+ const f = field as JxMutableNode;
38
39
  if (f.scope !== "static") continue;
39
40
  const name = f.identifier ?? key;
40
41
  const prefix = f.access === "private" ? "#" : "";
@@ -49,7 +50,7 @@ export function compileClassJson(classDef, _opts = {}) {
49
50
 
50
51
  // Instance field declarations (private)
51
52
  for (const [key, field] of Object.entries(fields)) {
52
- const f = /** @type {JxMutableNode} */ (field);
53
+ const f = field as JxMutableNode;
53
54
  if (f.scope === "static") continue;
54
55
  if (f.access !== "private") continue;
55
56
  const name = f.identifier ?? key;
@@ -67,7 +68,7 @@ export function compileClassJson(classDef, _opts = {}) {
67
68
 
68
69
  // Initialize instance fields from config or defaults
69
70
  for (const [key, field] of Object.entries(fields)) {
70
- const f = /** @type {JxMutableNode} */ (field);
71
+ const f = field as JxMutableNode;
71
72
  if (f.scope === "static") continue;
72
73
  const name = f.identifier ?? key;
73
74
  const prefix = f.access === "private" ? "#" : "";
@@ -93,7 +94,7 @@ export function compileClassJson(classDef, _opts = {}) {
93
94
 
94
95
  // Methods
95
96
  for (const [key, method] of Object.entries(methods)) {
96
- const m = /** @type {JxMutableNode} */ (method);
97
+ const m = method as JxMutableNode;
97
98
  const name = m.identifier ?? key;
98
99
  const isStatic = m.scope === "static";
99
100
  const isPrivate = m.access === "private";
@@ -101,7 +102,7 @@ export function compileClassJson(classDef, _opts = {}) {
101
102
  const staticPrefix = isStatic ? "static " : "";
102
103
  const asyncPrefix =
103
104
  m.returnType?.$ref?.includes("Promise") ||
104
- isMethodAsync(/** @type {{ body?: string | string[] }} */ (/** @type {unknown} */ (m)))
105
+ isMethodAsync(m as unknown as { body?: string | string[] })
105
106
  ? "async "
106
107
  : "";
107
108
 
@@ -148,10 +149,10 @@ export function compileClassJson(classDef, _opts = {}) {
148
149
  * @param {unknown} ext
149
150
  * @returns {string}
150
151
  */
151
- function resolveBaseClass(ext) {
152
+ function resolveBaseClass(ext: unknown) {
152
153
  if (!ext) return "Object";
153
154
  if (typeof ext === "string") return ext;
154
- const e = /** @type {JxMutableNode} */ (ext);
155
+ const e = ext as JxMutableNode;
155
156
  if (e.$ref) {
156
157
  const ref = e.$ref;
157
158
  const match = ref.match(/([A-Za-z0-9_]+)\.class\.json/);
@@ -166,10 +167,10 @@ function resolveBaseClass(ext) {
166
167
  * @param {unknown[]} params
167
168
  * @returns {string}
168
169
  */
169
- function resolveParams(params) {
170
+ function resolveParams(params: unknown[]) {
170
171
  return params
171
172
  .map((p) => {
172
- const param = /** @type {JxMutableNode} */ (p);
173
+ const param = p as JxMutableNode;
173
174
  if (param.$ref) return param.$ref.split("/").pop();
174
175
  return param.identifier ?? param.name ?? "arg";
175
176
  })
@@ -182,10 +183,10 @@ function resolveParams(params) {
182
183
  * @param {unknown} body
183
184
  * @returns {string[]}
184
185
  */
185
- function resolveBody(body) {
186
+ function resolveBody(body: unknown) {
186
187
  if (!body) return [""];
187
188
  if (Array.isArray(body)) return body;
188
- return [/** @type {string} */ (body)];
189
+ return [body as string];
189
190
  }
190
191
 
191
192
  /**
@@ -194,7 +195,7 @@ function resolveBody(body) {
194
195
  * @param {{ body?: string | string[] }} method
195
196
  * @returns {boolean}
196
197
  */
197
- function isMethodAsync(method) {
198
+ function isMethodAsync(method: { body?: string | string[] }) {
198
199
  const body = Array.isArray(method.body) ? method.body.join("\n") : (method.body ?? "");
199
200
  return body.includes("await ");
200
201
  }
@@ -25,7 +25,9 @@ import {
25
25
  DEFAULT_LIT_HTML_SRC,
26
26
  compileExpression,
27
27
  isMutating,
28
- } from "../shared.js";
28
+ } from "../shared.ts";
29
+ import type { ExpressionNode } from "../shared.ts";
30
+ import type { JxStyle, JxMutableNode } from "@jxsuite/schema/types";
29
31
 
30
32
  /**
31
33
  * Compile a Jx document to pre-rendered HTML + reactive JS module.
@@ -34,43 +36,38 @@ import {
34
36
  * @param {Record<string, unknown>} opts
35
37
  * @returns {{ html: string; files: { path: string; content: string }[] }}
36
38
  */
37
- export function compileClient(raw, opts) {
39
+ export function compileClient(
40
+ raw: JxMutableNode | Record<string, any>,
41
+ opts: Record<string, unknown>,
42
+ ) {
38
43
  const {
39
44
  title,
40
45
  reactivitySrc = DEFAULT_REACTIVITY_SRC,
41
46
  litHtmlSrc = DEFAULT_LIT_HTML_SRC,
42
47
  modulePath = "app.js",
43
- } = /** @type {JxMutableNode} */ (opts);
48
+ } = opts as JxMutableNode;
44
49
 
45
50
  const context = createCompileContext(raw, null, raw.state ?? {}, raw.$media ?? {});
46
51
  const styleBlock = compileStyles(
47
52
  raw,
48
53
  raw.$media ?? {},
49
- /** @type {JxStyle | null} */ (opts.projectStyle ?? null),
54
+ (opts.projectStyle ?? null) as JxStyle | null,
50
55
  );
51
56
 
52
57
  // Collectors for bindings and handlers
53
58
  const counter = { t: 0, s: 0, h: 0, m: 0, sw: 0, l: 0, needsLit: false };
54
- /** @type {Map<string, string>} */
55
- const bindings = new Map(); // key → expression string
56
- /** @type {Map<string, any>} */
57
- const handlers = new Map(); // key → { body, args }
59
+ const bindings: Map<string, string> = new Map(); // key → expression string
60
+ const handlers: Map<string, any> = new Map(); // key → { body, args }
58
61
 
59
62
  // Classify state entries into reactive state, computed, bind, on, and init blocks
60
- /** @type {[string, any][]} */
61
- const stateEntries = []; // [key, initValue] → reactive({...})
62
- /** @type {[string, string][]} */
63
- const computedEntries = []; // [key, bodyExpr] → state.key = computed(...)
64
- /** @type {[string, string][]} */
65
- const bindEntries = []; // [key, bodyExpr] → bind = {...}
66
- /** @type {[string, any][]} */
67
- const onEntries = []; // [key, { args, body }] → on = {...}
68
- /** @type {string[]} */
69
- const initBlocks = []; // lines emitted after state for prototype init
63
+ const stateEntries: [string, any][] = []; // [key, initValue] → reactive({...})
64
+ const computedEntries: [string, string][] = []; // [key, bodyExpr] → state.key = computed(...)
65
+ const bindEntries: [string, string][] = []; // [key, bodyExpr] → bind = {...}
66
+ const onEntries: [string, any][] = []; // [key, { args, body }] → on = {...}
67
+ const initBlocks: string[] = []; // lines emitted after state for prototype init
70
68
 
71
69
  // Map $src path → Set of function names to import
72
- /** @type {Map<string, Set<string>>} */
73
- const srcImportMap = new Map();
70
+ const srcImportMap: Map<string, Set<string>> = new Map();
74
71
 
75
72
  const defs = raw.state ?? {};
76
73
  for (const [key, def] of Object.entries(defs)) {
@@ -85,11 +82,11 @@ export function compileClient(raw, opts) {
85
82
  continue;
86
83
  }
87
84
 
88
- const d = /** @type {JxMutableNode} */ (def);
85
+ const d = def as JxMutableNode;
89
86
 
90
87
  // $expression: Shape 5
91
88
  if ("$expression" in d) {
92
- const node = /** @type {any} */ (d).$expression;
89
+ const node = (d as Record<string, unknown>).$expression as ExpressionNode;
93
90
  if (isMutating(node.operator)) {
94
91
  const compiled = compileExpression(node, { statePrefix: "state", eventParam: "e" });
95
92
  onEntries.push([key, { args: ["state", "e"], body: compiled }]);
@@ -105,7 +102,7 @@ export function compileClient(raw, opts) {
105
102
  const args = d.parameters ?? d.arguments;
106
103
  if (d.$src) {
107
104
  if (!srcImportMap.has(d.$src)) srcImportMap.set(d.$src, new Set());
108
- /** @type {Set<string>} */ (srcImportMap.get(d.$src)).add(key);
105
+ (srcImportMap.get(d.$src) as Set<string>).add(key);
109
106
 
110
107
  // $src functions always produce computed entries (they return values)
111
108
  computedEntries.push([key, "() => { return " + key + "(state); }"]);
@@ -232,7 +229,14 @@ ${importmapEntries.join(",\n")}
232
229
  * }} counter
233
230
  * @returns {string}
234
231
  */
235
- function buildClientNode(def, raw, context, bindings, handlers, counter) {
232
+ function buildClientNode(
233
+ def: JxMutableNode,
234
+ raw: JxMutableNode,
235
+ context: any,
236
+ bindings: Map<string, string>,
237
+ handlers: Map<string, any>,
238
+ counter: { t: number; s: number; h: number; m: number; sw: number; l: number; needsLit: boolean },
239
+ ) {
236
240
  // String children are text nodes
237
241
  if (typeof def === "string") {
238
242
  return escapeHtml(def);
@@ -255,13 +259,11 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
255
259
 
256
260
  // textContent bindings
257
261
  if (def.textContent !== undefined) {
258
- const tc = /** @type {JxMutableNode} */ (
259
- /** @type {unknown} */ (raw?.textContent ?? def.textContent)
260
- );
262
+ const tc = raw?.textContent ?? (def.textContent as unknown as JxMutableNode);
261
263
  if (isRefObject(tc)) {
262
- const key = refToBindingKey(/** @type {string} */ (tc.$ref));
264
+ const key = refToBindingKey((tc as JxMutableNode).$ref as string);
263
265
  bindAttrs.push(`:text-content="${key}"`);
264
- addRefBinding(bindings, key, /** @type {string} */ (tc.$ref));
266
+ addRefBinding(bindings, key, (tc as JxMutableNode).$ref as string);
265
267
  needsBind = true;
266
268
  } else if (isTemplateString(tc)) {
267
269
  const key = `_t${counter.t++}`;
@@ -276,15 +278,11 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
276
278
  if (!prop.startsWith("on") || prop === "observedAttributes") continue;
277
279
  const eventName = prop.slice(2).toLowerCase();
278
280
  if (isRefObject(val)) {
279
- const key = refToBindingKey(/** @type {string} */ (/** @type {JxMutableNode} */ (val).$ref));
281
+ const key = refToBindingKey((val as JxMutableNode).$ref as string);
280
282
  bindAttrs.push(`@${eventName}="${key}"`);
281
283
  needsBind = true;
282
- } else if (
283
- val &&
284
- typeof val === "object" &&
285
- /** @type {JxMutableNode} */ (val).$prototype === "Function"
286
- ) {
287
- const v = /** @type {JxMutableNode} */ (val);
284
+ } else if (val && typeof val === "object" && (val as JxMutableNode).$prototype === "Function") {
285
+ const v = val as JxMutableNode;
288
286
  const key = `_h${counter.h++}`;
289
287
  bindAttrs.push(`@${eventName}="${key}"`);
290
288
  handlers.set(key, { args: v.parameters ?? v.arguments ?? ["state", "event"], body: v.body });
@@ -292,10 +290,13 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
292
290
  } else if (val && typeof val === "object" && "$expression" in /** @type {any} */ (val)) {
293
291
  const key = `_h${counter.h++}`;
294
292
  bindAttrs.push(`@${eventName}="${key}"`);
295
- const compiled = compileExpression(/** @type {any} */ (val).$expression, {
296
- statePrefix: "state",
297
- eventParam: "e",
298
- });
293
+ const compiled = compileExpression(
294
+ (val as Record<string, unknown>).$expression as ExpressionNode,
295
+ {
296
+ statePrefix: "state",
297
+ eventParam: "e",
298
+ },
299
+ );
299
300
  handlers.set(key, { args: ["state", "e"], body: compiled });
300
301
  needsBind = true;
301
302
  }
@@ -326,15 +327,9 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
326
327
  if (def.attributes && typeof def.attributes === "object") {
327
328
  for (const [attr, val] of Object.entries(def.attributes)) {
328
329
  if (isRefObject(val)) {
329
- const key = refToBindingKey(
330
- /** @type {string} */ (/** @type {JxMutableNode} */ (val).$ref),
331
- );
330
+ const key = refToBindingKey((val as JxMutableNode).$ref as string);
332
331
  bindAttrs.push(`:attr.${attr}="${key}"`);
333
- addRefBinding(
334
- bindings,
335
- key,
336
- /** @type {string} */ (/** @type {JxMutableNode} */ (val).$ref),
337
- );
332
+ addRefBinding(bindings, key, (val as JxMutableNode).$ref as string);
338
333
  needsBind = true;
339
334
  } else if (isTemplateString(val)) {
340
335
  const key = `_t${counter.t++}`;
@@ -362,9 +357,9 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
362
357
  )
363
358
  continue;
364
359
  if (isRefObject(val)) {
365
- const key = refToBindingKey(/** @type {string} */ (/** @type {JxMutableNode} */ (val).$ref));
360
+ const key = refToBindingKey((val as JxMutableNode).$ref as string);
366
361
  bindAttrs.push(`:${camelToKebab(prop)}="${key}"`);
367
- addRefBinding(bindings, key, /** @type {string} */ (/** @type {JxMutableNode} */ (val).$ref));
362
+ addRefBinding(bindings, key, (val as JxMutableNode).$ref as string);
368
363
  needsBind = true;
369
364
  } else if (isTemplateString(val)) {
370
365
  const key = `_t${counter.t++}`;
@@ -391,18 +386,17 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
391
386
  } else if (source.innerHTML) {
392
387
  // resolveStaticValue may return null if innerHTML contains `${` from rendered content
393
388
  // (e.g., code examples) that isn't an actual template expression. Fall back to raw value.
394
- inner = /** @type {string} */ (resolveStaticValue(source.innerHTML, nextContext.scope)) ??
395
- source.innerHTML;
389
+ inner = (resolveStaticValue(source.innerHTML, nextContext.scope) as string) ?? source.innerHTML;
396
390
  } else if (
397
391
  source.children &&
398
392
  typeof source.children === "object" &&
399
393
  !Array.isArray(source.children) &&
400
- /** @type {JxMutableNode} */ (source.children).$prototype === "Array"
394
+ (source.children as JxMutableNode).$prototype === "Array"
401
395
  ) {
402
396
  // ─── Mapped array → lit-html render binding ───
403
397
  counter.needsLit = true;
404
398
  const listKey = `_list${counter.l++}`;
405
- const arrayDef = /** @type {JxMutableNode} */ (source.children);
399
+ const arrayDef = source.children as JxMutableNode;
406
400
 
407
401
  // Resolve items source expression
408
402
  let itemsExpr;
@@ -436,8 +430,8 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
436
430
  .map((c, i) => {
437
431
  const childRaw = rawChildren?.[i] ?? c;
438
432
  return buildClientNode(
439
- /** @type {JxMutableNode} */ (/** @type {unknown} */ (c)),
440
- /** @type {JxMutableNode} */ (/** @type {unknown} */ (childRaw)),
433
+ c as unknown as JxMutableNode,
434
+ childRaw as unknown as JxMutableNode,
441
435
  nextContext,
442
436
  bindings,
443
437
  handlers,
@@ -465,7 +459,7 @@ function buildClientNode(def, raw, context, bindings, handlers, counter) {
465
459
  * @param {JxMutableNode} def
466
460
  * @returns {string}
467
461
  */
468
- function emitLitMapTemplate(def) {
462
+ function emitLitMapTemplate(def: JxMutableNode) {
469
463
  if (!def) return "";
470
464
  const tag = def.tagName ?? "div";
471
465
  let attrs = "";
@@ -486,8 +480,7 @@ function emitLitMapTemplate(def) {
486
480
 
487
481
  // style → inline CSS
488
482
  if (def.style && typeof def.style === "object") {
489
- /** @type {string[]} */
490
- const parts = [];
483
+ const parts: string[] = [];
491
484
  for (const [k, v] of Object.entries(def.style)) {
492
485
  if (
493
486
  k.startsWith(":") ||
@@ -515,20 +508,19 @@ function emitLitMapTemplate(def) {
515
508
  if (!prop.startsWith("on") || prop === "observedAttributes") continue;
516
509
  const eventName = prop.slice(2).toLowerCase();
517
510
  if (isRefObject(val)) {
518
- const key = refToBindingKey(/** @type {string} */ (/** @type {JxMutableNode} */ (val).$ref));
511
+ const key = refToBindingKey((val as JxMutableNode).$ref as string);
519
512
  attrs += " @" + eventName + "=${(e) => { state.$map = { item, index }; on." + key + "(e); }}";
520
- } else if (
521
- val &&
522
- typeof val === "object" &&
523
- /** @type {JxMutableNode} */ (val).$prototype === "Function"
524
- ) {
525
- const body = mapRefsToLit(/** @type {string} */ (/** @type {JxMutableNode} */ (val).body));
513
+ } else if (val && typeof val === "object" && (val as JxMutableNode).$prototype === "Function") {
514
+ const body = mapRefsToLit((val as JxMutableNode).body as string);
526
515
  attrs += " @" + eventName + "=${(e) => { " + body + " }}";
527
516
  } else if (val && typeof val === "object" && "$expression" in /** @type {any} */ (val)) {
528
- const compiled = compileExpression(/** @type {any} */ (val).$expression, {
529
- statePrefix: "state",
530
- eventParam: "e",
531
- });
517
+ const compiled = compileExpression(
518
+ (val as Record<string, unknown>).$expression as ExpressionNode,
519
+ {
520
+ statePrefix: "state",
521
+ eventParam: "e",
522
+ },
523
+ );
532
524
  attrs += " @" + eventName + "=${(e) => { state.$map = { item, index }; " + compiled + "; }}";
533
525
  }
534
526
  }
@@ -545,11 +537,7 @@ function emitLitMapTemplate(def) {
545
537
  if (isTemplateString(tc)) {
546
538
  inner = mapRefsToLit(tc);
547
539
  } else if (isRefObject(def.textContent)) {
548
- const path = refToBindingKey(
549
- /** @type {string} */ (
550
- /** @type {JxMutableNode} */ (/** @type {unknown} */ (def.textContent)).$ref
551
- ),
552
- );
540
+ const path = refToBindingKey((def.textContent as unknown as JxMutableNode).$ref as string);
553
541
  inner = "${state." + path + "}";
554
542
  } else {
555
543
  inner = escapeHtml(tc);
@@ -559,9 +547,7 @@ function emitLitMapTemplate(def) {
559
547
  } else if (Array.isArray(def.children)) {
560
548
  inner =
561
549
  "\n " +
562
- def.children
563
- .map((c) => emitLitMapTemplate(/** @type {JxMutableNode} */ (c)))
564
- .join("\n ") +
550
+ def.children.map((c) => emitLitMapTemplate(c as JxMutableNode)).join("\n ") +
565
551
  "\n ";
566
552
  }
567
553
 
@@ -576,7 +562,7 @@ function emitLitMapTemplate(def) {
576
562
  * @param {string} str
577
563
  * @returns {string}
578
564
  */
579
- function mapRefsToLit(str) {
565
+ function mapRefsToLit(str: string) {
580
566
  return str.replace(/\$map\./g, "");
581
567
  }
582
568
 
@@ -602,17 +588,16 @@ function mapRefsToLit(str) {
602
588
  * @returns {string}
603
589
  */
604
590
  function emitClientModule(
605
- stateEntries,
606
- computedEntries,
607
- bindEntries,
608
- onEntries,
609
- initBlocks,
610
- srcImportMap,
611
- counter,
612
- _reactivitySrc,
591
+ stateEntries: [string, any][],
592
+ computedEntries: [string, string][],
593
+ bindEntries: [string, string][],
594
+ onEntries: [string, any][],
595
+ initBlocks: string[],
596
+ srcImportMap: Map<string, Set<string>>,
597
+ counter: { t: number; s: number; h: number; m: number; sw: number; l: number; needsLit: boolean },
598
+ _reactivitySrc: string,
613
599
  ) {
614
- /** @type {string[]} */
615
- const lines = [];
600
+ const lines: string[] = [];
616
601
  const needsLit = counter.needsLit;
617
602
  const needsComputed = computedEntries.length > 0;
618
603
 
@@ -676,9 +661,7 @@ function emitClientModule(
676
661
  lines.push("const on = {");
677
662
  for (const [key, def] of onEntries) {
678
663
  const argNames = def.args ?? ["state"];
679
- const callArgs = argNames
680
- .map((/** @type {string} */ a) => (a === "state" ? "state" : "e"))
681
- .join(", ");
664
+ const callArgs = argNames.map((a: string) => (a === "state" ? "state" : "e")).join(", ");
682
665
  lines.push(
683
666
  " " +
684
667
  key +
@@ -738,7 +721,7 @@ function emitClientModule(
738
721
  * @param {JxMutableNode} def
739
722
  * @returns {string}
740
723
  */
741
- function emitRequestInit(key, def) {
724
+ function emitRequestInit(key: string, def: JxMutableNode) {
742
725
  const url = def.url;
743
726
  const method = def.method ?? "GET";
744
727
  const isTemplateUrl = isTemplateString(url);
@@ -747,8 +730,7 @@ function emitRequestInit(key, def) {
747
730
  return "// " + key + ": manual Request — fetch triggered by user action";
748
731
  }
749
732
 
750
- /** @type {string[]} */
751
- const lines = [];
733
+ const lines: string[] = [];
752
734
  lines.push("// " + key + ": auto-fetch from " + (isTemplateUrl ? "(dynamic URL)" : url));
753
735
  lines.push("effect(() => {");
754
736
 
@@ -759,8 +741,7 @@ function emitRequestInit(key, def) {
759
741
  lines.push(" const url = " + JSON.stringify(url) + ";");
760
742
  }
761
743
 
762
- /** @type {string[]} */
763
- const fetchOpts = [];
744
+ const fetchOpts: string[] = [];
764
745
  if (method !== "GET") fetchOpts.push("method: " + JSON.stringify(method));
765
746
  if (def.headers) fetchOpts.push("headers: " + JSON.stringify(def.headers));
766
747
  if (def.body) {
@@ -788,9 +769,8 @@ function emitRequestInit(key, def) {
788
769
  * @param {unknown} defaultVal
789
770
  * @returns {string}
790
771
  */
791
- function emitStorageInit(key, storeName, storageKey, defaultVal) {
792
- /** @type {string[]} */
793
- const lines = [];
772
+ function emitStorageInit(key: string, storeName: string, storageKey: string, defaultVal: unknown) {
773
+ const lines: string[] = [];
794
774
  lines.push("// " + key + ": " + storeName + ' (key: "' + storageKey + '")');
795
775
  lines.push("try {");
796
776
  lines.push(" const _s = " + storeName + ".getItem(" + JSON.stringify(storageKey) + ");");
@@ -818,9 +798,8 @@ function emitStorageInit(key, storeName, storageKey, defaultVal) {
818
798
  * @param {unknown} defaultVal
819
799
  * @returns {string}
820
800
  */
821
- function emitCookieInit(key, cookieName, defaultVal) {
822
- /** @type {string[]} */
823
- const lines = [];
801
+ function emitCookieInit(key: string, cookieName: string, defaultVal: unknown) {
802
+ const lines: string[] = [];
824
803
  lines.push("// " + key + ': Cookie (name: "' + cookieName + '")');
825
804
  lines.push("{");
826
805
  lines.push(
@@ -844,7 +823,7 @@ function emitCookieInit(key, cookieName, defaultVal) {
844
823
  * @param {string} ref
845
824
  * @returns {string}
846
825
  */
847
- function refToBindingKey(ref) {
826
+ function refToBindingKey(ref: string) {
848
827
  if (ref.startsWith("#/state/")) {
849
828
  return ref.slice("#/state/".length).replace(/\//g, "_");
850
829
  }
@@ -856,7 +835,7 @@ function refToBindingKey(ref) {
856
835
  * @param {string} key
857
836
  * @param {string} ref
858
837
  */
859
- function addRefBinding(bindings, key, ref) {
838
+ function addRefBinding(bindings: Map<string, string>, key: string, ref: string) {
860
839
  if (bindings.has(key)) return;
861
840
  if (ref.startsWith("#/state/")) {
862
841
  const path = ref.slice("#/state/".length);