@loom-forge/check 0.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/index.js ADDED
@@ -0,0 +1,867 @@
1
+ import { s, format, subtype, isSerializable } from '@tslite/type-core';
2
+ import { toJsonSchema, fromJsonSchema } from '@tslite/jsonschema';
3
+ import { inferValue } from '@tslite/infer';
4
+ import { s as s$1, createAnchors, check, spanOf, annotate, createEnv, anchorDiagnostics, lowerValue } from '@tslite/checker';
5
+ import { ASSERTER, createBoundary } from '@tslite/validate';
6
+ import { vanilla } from '@tslite/operators';
7
+ import { addressOf, isLive, compileDefinition, mountScopesOf, mountingOf, compileComponent, EMPTY_MOUNT, settledRoute } from '@loom-forge/forge';
8
+ import * as b from '@tslite/core/builders';
9
+ import { isExprMarker, EXPR_MARKER } from '@tslite/core';
10
+ import { parseExpression } from '@tslite/parser';
11
+ import { compile, DEFAULT_PROFILE } from '@loom-forge/tslite/compile';
12
+ import { FIELDS, slotOf, TREE } from '@loom-forge/core';
13
+ import { PRESETS } from '@tslite/capability';
14
+
15
+ // src/checker.ts
16
+ function createTsliteChecker() {
17
+ const inferType = (value) => inferValue(value);
18
+ const fromJS = (jsonSchema) => fromJsonSchema(jsonSchema);
19
+ return {
20
+ subtype: (a, b2) => subtype(a, b2),
21
+ inferType,
22
+ fromJsonSchema: fromJS,
23
+ toJsonSchema: (schema) => toJsonSchema(schema),
24
+ assignable: (value, jsonSchema) => subtype(inferType(value), fromJS(jsonSchema)),
25
+ format: (schema) => format(schema)
26
+ };
27
+ }
28
+ function checkTree(node, registry, checker) {
29
+ const issues = [];
30
+ const visit = (n) => {
31
+ if (n.kind !== "node") return;
32
+ const descriptor = registry.get(n.type);
33
+ if (descriptor?.schema && !checker.assignable(n.props, descriptor.schema)) {
34
+ issues.push({
35
+ nodeId: n.id,
36
+ type: n.type,
37
+ expected: checker.format(checker.fromJsonSchema(descriptor.schema)),
38
+ got: checker.format(checker.inferType(n.props))
39
+ });
40
+ }
41
+ n.children.forEach(visit);
42
+ };
43
+ visit(node);
44
+ return issues;
45
+ }
46
+ var SCALARS = {
47
+ any: s.any,
48
+ unknown: s.unknown,
49
+ string: s.string,
50
+ number: s.number,
51
+ boolean: s.boolean,
52
+ null: s.null
53
+ };
54
+ function resolveTypeRef(ref, types = {}) {
55
+ if (typeof ref === "string") return types[ref] ?? SCALARS[ref] ?? s.unknown;
56
+ const o = ref;
57
+ if (typeof o.t === "string") return ref;
58
+ return fromJsonSchema(ref);
59
+ }
60
+ var unresolvedName = (ref, types) => typeof ref === "string" && !(ref in types) && !(ref in SCALARS) ? ref : void 0;
61
+ function resolveProps(props, types = {}) {
62
+ const shape = {};
63
+ for (const [rawKey, ref] of Object.entries(props ?? {})) {
64
+ const optional = rawKey.endsWith("?");
65
+ const key = optional ? rawKey.slice(0, -1) : rawKey;
66
+ const type = resolveTypeRef(ref, types);
67
+ shape[key] = optional ? { type: s.union([type, s.undefined]), optional: true } : { type };
68
+ }
69
+ return s.object(shape);
70
+ }
71
+ function componentType(ir, types = {}) {
72
+ return {
73
+ props: resolveProps(ir.props, types),
74
+ ...ir.category ? { category: ir.category } : {},
75
+ entry: ir.entry
76
+ };
77
+ }
78
+ function componentAssignable(child, contract, types = {}) {
79
+ if (contract.props === void 0) return true;
80
+ return subtype(child.props, resolveProps(contract.props, types));
81
+ }
82
+ function checkDeclarations(def, types = {}) {
83
+ const issues = [];
84
+ const report = (path, name) => {
85
+ issues.push({
86
+ code: "unknown-type-name",
87
+ message: `Type '${name}' is not declared: it is neither a scalar (${Object.keys(SCALARS).join(", ")}) nor a name in the type catalog.`,
88
+ severity: "error",
89
+ path,
90
+ address: addressOf(path),
91
+ source: name
92
+ });
93
+ };
94
+ for (const [rawKey, ref] of Object.entries(def.props ?? {})) {
95
+ const name = unresolvedName(ref, types);
96
+ if (name !== void 0) report(["props", rawKey], name);
97
+ }
98
+ for (const [key, decl] of Object.entries(def.state ?? {})) {
99
+ const name = unresolvedName(decl.type, types);
100
+ if (name !== void 0) report(["state", key], name);
101
+ }
102
+ return issues;
103
+ }
104
+ function declaredContextsOf(catalog, types = {}) {
105
+ const cache = /* @__PURE__ */ new Map();
106
+ return (name) => {
107
+ if (cache.has(name)) return cache.get(name);
108
+ const ref = catalog?.[name];
109
+ const schema = ref ? resolveTypeRef(ref, types) : void 0;
110
+ const ok = schema && isSerializable(schema) ? schema : void 0;
111
+ cache.set(name, ok);
112
+ return ok;
113
+ };
114
+ }
115
+ function checkContextCatalog(catalog, types = {}) {
116
+ const issues = [];
117
+ for (const [name, ref] of Object.entries(catalog ?? {})) {
118
+ const unresolved = unresolvedName(ref, types);
119
+ if (unresolved !== void 0) {
120
+ issues.push({
121
+ code: "unknown-type-name",
122
+ message: `Type '${unresolved}' is not declared: it is neither a scalar (${Object.keys(SCALARS).join(", ")}) nor a name in the type catalog.`,
123
+ severity: "error",
124
+ path: ["contexts", name],
125
+ address: addressOf(["contexts", name]),
126
+ source: unresolved
127
+ });
128
+ continue;
129
+ }
130
+ if (!isSerializable(resolveTypeRef(ref, types)))
131
+ issues.push({
132
+ code: "unknown-type-name",
133
+ message: `Context '${name}' must be serializable DATA: a contract with functions (or \`unknown\`/\`any\`) is not a contract. Behavior goes through events \u2192 ActionPort, which is the door that creates an edge in the graph.`,
134
+ severity: "error",
135
+ path: ["contexts", name],
136
+ address: addressOf(["contexts", name]),
137
+ source: name
138
+ });
139
+ }
140
+ return issues;
141
+ }
142
+ function declaredParamsOf(updates, types = {}) {
143
+ return (action) => {
144
+ const decl = updates?.[action]?.params;
145
+ return decl ? resolveProps(decl, types) : void 0;
146
+ };
147
+ }
148
+ function hostParamsOf(port, types = {}) {
149
+ return (action) => {
150
+ const schema = port?.paramsOf?.(action);
151
+ return schema === void 0 || schema === null ? void 0 : resolveTypeRef(schema, types);
152
+ };
153
+ }
154
+ function paramsResolver(...resolvers) {
155
+ return (action) => {
156
+ for (const resolve of resolvers) {
157
+ const found = resolve(action);
158
+ if (found) return found;
159
+ }
160
+ return void 0;
161
+ };
162
+ }
163
+ function partialStateType(state, types = {}) {
164
+ return s.object(
165
+ Object.fromEntries(
166
+ Object.entries(state ?? {}).map(([k, decl]) => [
167
+ k,
168
+ { type: resolveTypeRef(decl.type, types), optional: true }
169
+ ])
170
+ )
171
+ );
172
+ }
173
+ function partialOf(schema) {
174
+ const o = schema;
175
+ if (o?.t !== "object" || !o.props) return schema;
176
+ return {
177
+ ...o,
178
+ props: Object.fromEntries(
179
+ Object.entries(o.props).map(([key, field]) => [
180
+ key,
181
+ { ...field, optional: true }
182
+ ])
183
+ )
184
+ };
185
+ }
186
+ function declaredPropsOf(sys, types = {}) {
187
+ const cache = /* @__PURE__ */ new Map();
188
+ return (type) => {
189
+ if (cache.has(type)) return cache.get(type);
190
+ const ir = sys.components.get(type);
191
+ const schema = ir ? componentType(ir, types).props : void 0;
192
+ cache.set(type, schema);
193
+ return schema;
194
+ };
195
+ }
196
+ function stateTypeOf(state, types = {}) {
197
+ return (key) => {
198
+ const decl = state?.[key];
199
+ return decl ? resolveTypeRef(decl.type, types) : void 0;
200
+ };
201
+ }
202
+ function propTypeOf(schema, key) {
203
+ const o = schema;
204
+ return o?.t === "object" ? o.props?.[key]?.type : void 0;
205
+ }
206
+ function hostResultOf(port, types = {}) {
207
+ return (action) => {
208
+ const schema = port?.resultOf?.(action);
209
+ return schema === void 0 || schema === null ? void 0 : resolveTypeRef(schema, types);
210
+ };
211
+ }
212
+ var DEFAULT_ASSERTER = ASSERTER;
213
+ var ctxRoot = (def, contexts) => {
214
+ const uses = def.context?.uses ?? [];
215
+ if (!contexts || uses.length === 0) return void 0;
216
+ const shape = {};
217
+ for (const name of uses)
218
+ if (contexts[name]) shape[name] = { type: contexts[name] };
219
+ return { ctx: s.object(shape) };
220
+ };
221
+ var stateSchema = (state, types) => s.object(
222
+ Object.fromEntries(
223
+ Object.entries(state ?? {}).map(([k, decl]) => [
224
+ k,
225
+ { type: resolveTypeRef(decl.type, types) }
226
+ ])
227
+ )
228
+ );
229
+ var envOf = (vars, opts) => {
230
+ const operators = opts.operators ?? vanilla;
231
+ const boundary = createBoundary({
232
+ types: opts.types ?? {},
233
+ reserved: [...Object.keys(operators), ...Object.keys(vars)]
234
+ });
235
+ return createEnv(
236
+ { ...operators, ...boundary.check.vars, ...vars },
237
+ { types: boundary.check.types, asserters: boundary.check.asserters }
238
+ );
239
+ };
240
+ function buildEnv(def, opts = {}) {
241
+ const types = opts.types ?? {};
242
+ return envOf(
243
+ {
244
+ props: resolveProps(def.props, types),
245
+ state: stateSchema(def.state, types),
246
+ ...opts.data ? { data: opts.data } : {},
247
+ ...ctxRoot(def, opts.contexts) ?? {},
248
+ // o PENDENTE é fato de uma INSTÂNCIA, e instância é o boundary de um componente vivo: só
249
+ // ele tem a raiz. Num componente puro, `pending` é `unknown-name` — e o remédio é um update
250
+ // ou um efeito, que é o que o torna vivo (ADR-018).
251
+ ...isLive(def) ? { pending: PENDING } : {}
252
+ },
253
+ opts
254
+ );
255
+ }
256
+ var PENDING = s.record(s.boolean);
257
+ function buildInitEnv(def, opts = {}) {
258
+ return envOf(
259
+ {
260
+ props: resolveProps(def.props, opts.types ?? {}),
261
+ ...ctxRoot(def, opts.contexts) ?? {}
262
+ },
263
+ opts
264
+ );
265
+ }
266
+ var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
267
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && !isExprMarker(v);
268
+ var NO_SYSTEM = {
269
+ slotScopesOf: () => void 0,
270
+ vocabulary: /* @__PURE__ */ new Set()
271
+ };
272
+ var ACTION_ERROR = s$1.object({
273
+ code: { type: s$1.string },
274
+ message: { type: s$1.string, optional: true },
275
+ data: { type: s$1.unknown, optional: true }
276
+ });
277
+ function lowerComponent(authored, opts = {}) {
278
+ const shapeOf = opts.shapeOf ?? (() => "list");
279
+ const propsOf = opts.propsOf ?? (() => void 0);
280
+ const paramsOf = opts.paramsOf ?? (() => void 0);
281
+ const exhaustiveParams = opts.exhaustiveParams ?? (() => true);
282
+ const weak = /* @__PURE__ */ new Set();
283
+ const contextOf = opts.contextOf ?? (() => void 0);
284
+ const emitsOf = opts.emitsOf ?? (() => void 0);
285
+ const resultOf = opts.resultOf ?? (() => void 0);
286
+ const compiled = opts.compiled ?? compileDefinition(authored, compile);
287
+ const def = compiled.def;
288
+ const nodes = /* @__PURE__ */ new Map();
289
+ const texts = /* @__PURE__ */ new Map();
290
+ const failed = /* @__PURE__ */ new Set();
291
+ const sugared = (address) => address.startsWith("provides.") || address.startsWith("commands.") ? `#0.${address}` : void 0;
292
+ for (const island of compiled.islands) {
293
+ nodes.set(island.address, island.node);
294
+ texts.set(island.address, island.text);
295
+ const alias = sugared(island.address);
296
+ if (alias !== void 0 && !nodes.has(alias)) {
297
+ nodes.set(alias, island.node);
298
+ texts.set(alias, island.text);
299
+ }
300
+ }
301
+ for (const d of compiled.diagnostics) {
302
+ failed.add(d.address);
303
+ const alias = sugared(d.address);
304
+ if (alias !== void 0) failed.add(alias);
305
+ }
306
+ const anchors = createAnchors();
307
+ const islands = [];
308
+ const frames = /* @__PURE__ */ new Map();
309
+ const pendingFrames = [];
310
+ let temp = 0;
311
+ let call = 0;
312
+ let act = 0;
313
+ let evt = 0;
314
+ let ctxn = 0;
315
+ let ini = 0;
316
+ let aln = 0;
317
+ const root = {
318
+ ...def.body,
319
+ ...def.provides ? { provides: { ...def.provides, ...def.body.provides } } : {},
320
+ ...def.commands ? { commands: { ...def.commands, ...def.body.commands } } : {}
321
+ };
322
+ const mounting = opts.mounting ?? NO_SYSTEM;
323
+ const scopesAt = mountScopesOf(root, mounting);
324
+ const routing = {
325
+ updates: new Set(Object.keys(def.updates ?? {})),
326
+ vocabulary: /* @__PURE__ */ new Set([
327
+ ...mountingOf([
328
+ compileComponent(def, { components: /* @__PURE__ */ new Set([def.component]) })
329
+ ]).vocabulary,
330
+ ...mounting.vocabulary
331
+ ])
332
+ };
333
+ const nameNode = (name, path) => {
334
+ const address = addressOf(path);
335
+ texts.set(address, name);
336
+ const node = b.identifier(name);
337
+ islands.push({ node, path, address, source: name });
338
+ return anchors.stamp(node, path);
339
+ };
340
+ const fromPath = (observed, path) => {
341
+ try {
342
+ const node = parseExpression(observed);
343
+ const address = addressOf(path);
344
+ texts.set(address, observed);
345
+ islands.push({ node, path, address, source: observed });
346
+ return anchors.stamp(node, path);
347
+ } catch {
348
+ return void 0;
349
+ }
350
+ };
351
+ const lowerAt = (value, path, extras = []) => {
352
+ const expr = lowerValue(prepared(value, path), path, anchors, {
353
+ child: (p, key) => [...p, key],
354
+ island: (marker, p) => {
355
+ const address = addressOf(p);
356
+ const node = nodes.get(address) ?? b.fromExprMarker(marker);
357
+ const source = texts.get(address);
358
+ islands.push({
359
+ node,
360
+ path: p,
361
+ address,
362
+ ...source ? { source } : {}
363
+ });
364
+ return node;
365
+ }
366
+ });
367
+ if (extras.length > 0 && expr.type === "ObjectExpression")
368
+ for (const extra of extras)
369
+ expr.properties.push(
370
+ anchors.stamp(
371
+ b.property(
372
+ b.literal(extra.key),
373
+ extra.value
374
+ ),
375
+ extra.path
376
+ )
377
+ );
378
+ return expr;
379
+ };
380
+ const ISLAND = { [EXPR_MARKER]: "Island" };
381
+ const prepared = (value, path) => {
382
+ const address = addressOf(path);
383
+ if (nodes.has(address)) return ISLAND;
384
+ if (typeof value === "string") return failed.has(address) ? null : value;
385
+ if (Array.isArray(value))
386
+ return value.map((x, i) => prepared(x, [...path, i]));
387
+ if (isRecord(value))
388
+ return Object.fromEntries(
389
+ Object.entries(value).map(([k, v]) => [k, prepared(v, [...path, k])])
390
+ );
391
+ return value;
392
+ };
393
+ const stmt = (e) => b.expressionStatement(e);
394
+ const body = [];
395
+ const initBody = [];
396
+ const push = (st) => {
397
+ if (st) body.push(st);
398
+ };
399
+ const hasIsland = (v) => {
400
+ if (isExprMarker(v)) return true;
401
+ if (Array.isArray(v)) return v.some(hasIsland);
402
+ if (v && typeof v === "object") return Object.values(v).some(hasIsland);
403
+ return false;
404
+ };
405
+ const emitValue = (v, path, expects) => {
406
+ if (!hasIsland(v)) return;
407
+ const e = lowerAt(v, path);
408
+ push(
409
+ expects === "boolean" ? b.variableDeclaration("const", [
410
+ b.variableDeclarator(
411
+ annotate(b.identifier(`__t${temp++}`), s$1.boolean),
412
+ e
413
+ )
414
+ ]) : stmt(e)
415
+ );
416
+ };
417
+ const emitIntent = (intent, path, scopes, received) => {
418
+ const at = [...path, "params"];
419
+ const route = typeof intent.action === "string" ? settledRoute(intent.action, scopes, routing) : void 0;
420
+ const target = route === void 0 || route.kind === "command" ? void 0 : route.action;
421
+ const declared = target === void 0 ? void 0 : paramsOf(target);
422
+ if (declared && target !== void 0 && !exhaustiveParams(target))
423
+ weak.add(addressOf(at));
424
+ const supplied = [];
425
+ for (const key of intent.resolve ?? [])
426
+ if (typeof key === "string")
427
+ supplied.push({
428
+ key,
429
+ ...declared && propTypeOf(declared, key) ? { type: propTypeOf(declared, key) } : {},
430
+ path: [...path, "resolve"]
431
+ });
432
+ if (declared && route && route.kind !== "command" && isRecord(route.bound)) {
433
+ const written = isRecord(intent.params) ? intent.params : {};
434
+ for (const key of Object.keys(route.bound))
435
+ if (!(key in written) && !supplied.some((s4) => s4.key === key) && propTypeOf(declared, key))
436
+ supplied.push({
437
+ key,
438
+ type: propTypeOf(declared, key),
439
+ path: [...path, "action"]
440
+ });
441
+ }
442
+ const named = supplied.map((s4, i) => ({
443
+ ...s4,
444
+ local: IDENTIFIER.test(s4.key) && s4.key !== "event" ? s4.key : `__s${i}`
445
+ }));
446
+ const inner = [];
447
+ if (intent.params !== void 0) {
448
+ if (declared && isRecord(intent.params))
449
+ inner.push(
450
+ b.variableDeclaration("const", [
451
+ b.variableDeclarator(
452
+ annotate(b.identifier(`__e${evt++}`), declared),
453
+ lowerAt(
454
+ intent.params,
455
+ at,
456
+ named.map((s4) => ({
457
+ key: s4.key,
458
+ value: b.identifier(s4.local),
459
+ path: s4.path
460
+ }))
461
+ )
462
+ )
463
+ ])
464
+ );
465
+ else if (hasIsland(intent.params))
466
+ inner.push(stmt(lowerAt(intent.params, at)));
467
+ } else if (declared && named.length > 0)
468
+ inner.push(
469
+ b.variableDeclaration("const", [
470
+ b.variableDeclarator(
471
+ annotate(b.identifier(`__e${evt++}`), declared),
472
+ lowerAt(
473
+ {},
474
+ at,
475
+ named.map((s4) => ({
476
+ key: s4.key,
477
+ value: b.identifier(s4.local),
478
+ path: s4.path
479
+ }))
480
+ )
481
+ )
482
+ ])
483
+ );
484
+ const outer = body.length;
485
+ if (intent.then)
486
+ emitIntent(
487
+ intent.then,
488
+ [...path, "then"],
489
+ scopes,
490
+ route?.kind === "update" ? s$1.undefined : (target === void 0 ? void 0 : resultOf(target)) ?? s$1.unknown
491
+ );
492
+ if (intent.catch)
493
+ emitIntent(intent.catch, [...path, "catch"], scopes, ACTION_ERROR);
494
+ inner.push(...body.splice(outer));
495
+ if (inner.length === 0) return;
496
+ const event = annotate(b.identifier("event"), received);
497
+ anchors.stamp(event, path);
498
+ push(
499
+ stmt(
500
+ b.arrowFunctionExpression(
501
+ [
502
+ event,
503
+ ...named.map((s4) => {
504
+ const param = nameNode(s4.local, s4.path);
505
+ return s4.type ? annotate(param, s4.type) : param;
506
+ })
507
+ ],
508
+ b.blockStatement(inner)
509
+ )
510
+ )
511
+ );
512
+ };
513
+ const wholeOf = (v) => isExprMarker(v) ? v : void 0;
514
+ const emitInits = () => {
515
+ for (const [key, decl] of Object.entries(def.state ?? {})) {
516
+ if (decl.init === void 0) continue;
517
+ const at = ["state", key, "init"];
518
+ if (!hasIsland(decl.init) && failed.has(addressOf(at))) continue;
519
+ const expr = lowerAt(decl.init, at);
520
+ const type = opts.stateTypeOf?.(key);
521
+ const id = b.identifier(`__i${ini++}`);
522
+ initBody.push(
523
+ b.variableDeclaration("const", [
524
+ b.variableDeclarator(
525
+ type ? annotate(id, type) : id,
526
+ expr
527
+ )
528
+ ])
529
+ );
530
+ }
531
+ };
532
+ const emitActions = () => {
533
+ const setType = opts.setType;
534
+ if (!setType) return;
535
+ for (const [name, action] of Object.entries(def.updates ?? {})) {
536
+ const set = action.set;
537
+ if (set === void 0) continue;
538
+ const frame = ["updates", name];
539
+ const decl = b.variableDeclaration("const", [
540
+ b.variableDeclarator(
541
+ annotate(b.identifier(`__s${act++}`), setType),
542
+ lowerAt(set, [...frame, "set"])
543
+ )
544
+ ]);
545
+ const param = annotate(
546
+ b.identifier("params"),
547
+ paramsOf(name) ?? s$1.unknown
548
+ );
549
+ anchors.stamp(param, frame);
550
+ const block = b.blockStatement([decl]);
551
+ frames.set(addressOf(frame), block);
552
+ push(
553
+ stmt(
554
+ b.arrowFunctionExpression(
555
+ [param],
556
+ block
557
+ )
558
+ )
559
+ );
560
+ }
561
+ };
562
+ const emitEffects = () => {
563
+ for (const [name, effect] of Object.entries(def.effects ?? {})) {
564
+ const at = ["effects", name];
565
+ effect.on.forEach((observed, i) => {
566
+ const e = fromPath(observed, [...at, "on", i]);
567
+ if (e) push(stmt(e));
568
+ });
569
+ emitIntent(effect, at, [EMPTY_MOUNT], s$1.undefined);
570
+ if (effect.cleanup)
571
+ emitIntent(
572
+ effect.cleanup,
573
+ [...at, "cleanup"],
574
+ [EMPTY_MOUNT],
575
+ s$1.undefined
576
+ );
577
+ }
578
+ };
579
+ const walk = (node, path) => {
580
+ const base = path;
581
+ const data = wholeOf(node.each);
582
+ const binding = typeof node.as === "string" ? node.as : void 0;
583
+ const inner = [];
584
+ const outer = body.length;
585
+ const pending = pendingFrames.length;
586
+ pendingFrames.push(addressOf(base));
587
+ const callee = node.el == null && typeof node.type === "string" ? propsOf(node.type) : void 0;
588
+ for (const [field, role] of Object.entries(FIELDS)) {
589
+ if (role !== "slot" || field === "each") continue;
590
+ if (field === "props" && callee) continue;
591
+ if (field === "provides") continue;
592
+ const value = node[field];
593
+ if (value === void 0) continue;
594
+ const decl = slotOf(field);
595
+ if (field === "commands") {
596
+ for (const [name, alias] of Object.entries(
597
+ value
598
+ )) {
599
+ if (typeof alias === "string") continue;
600
+ const at = [...base, "commands", name, "params"];
601
+ const declared = paramsOf(alias.action);
602
+ if (!declared || !isRecord(alias.params)) {
603
+ emitValue(alias.params, at);
604
+ continue;
605
+ }
606
+ if (!exhaustiveParams(alias.action)) weak.add(addressOf(at));
607
+ push(
608
+ b.variableDeclaration("const", [
609
+ b.variableDeclarator(
610
+ annotate(
611
+ b.identifier(`__a${aln++}`),
612
+ partialOf(declared)
613
+ ),
614
+ lowerAt(alias.params, at)
615
+ )
616
+ ])
617
+ );
618
+ }
619
+ } else if (decl?.shape === "intentParams") {
620
+ const scopes = scopesAt.get(node) ?? [];
621
+ for (const [name, binding2] of Object.entries(
622
+ value
623
+ ))
624
+ emitIntent(
625
+ binding2,
626
+ [...base, field, name],
627
+ scopes,
628
+ (node.el == null && node.type !== void 0 ? emitsOf(node.type, name) : void 0) ?? s$1.unknown
629
+ );
630
+ } else emitValue(value, [...base, field], decl?.expects);
631
+ }
632
+ if (node.provides)
633
+ for (const [name, value] of Object.entries(node.provides)) {
634
+ const declared = contextOf(name);
635
+ const at = [...base, "provides", name];
636
+ if (!declared) {
637
+ emitValue(value, at);
638
+ continue;
639
+ }
640
+ const e = lowerAt(value, at);
641
+ push(
642
+ b.variableDeclaration("const", [
643
+ b.variableDeclarator(
644
+ annotate(b.identifier(`__x${ctxn++}`), declared),
645
+ e
646
+ )
647
+ ])
648
+ );
649
+ }
650
+ if (callee)
651
+ push(
652
+ b.variableDeclaration("const", [
653
+ b.variableDeclarator(
654
+ annotate(b.identifier(`__c${call++}`), callee),
655
+ lowerAt(node.props ?? {}, [...base, "props"])
656
+ )
657
+ ])
658
+ );
659
+ for (const [field, shape] of Object.entries(TREE)) {
660
+ const value = node[field];
661
+ if (value === void 0) continue;
662
+ if (shape === "list" && Array.isArray(value))
663
+ value.forEach((child, i) => walk(child, [...path, i]));
664
+ else if (shape === "node" && value && typeof value === "object")
665
+ walk(value, [...path, field]);
666
+ }
667
+ if (!data || !binding) return;
668
+ inner.push(...body.splice(outer));
669
+ const coll = lowerAt(data, [...base, "each"]);
670
+ const param = nameNode(binding, [...base, "as"]);
671
+ const block = b.blockStatement(inner);
672
+ for (const address of pendingFrames.splice(pending))
673
+ frames.set(address, block);
674
+ const fn = b.arrowFunctionExpression(
675
+ [param],
676
+ block
677
+ );
678
+ push(
679
+ stmt(
680
+ shapeOf(coll) === "list" ? b.callExpression(b.identifier("map"), [
681
+ fn,
682
+ coll
683
+ ]) : b.callExpression(fn, [
684
+ coll
685
+ ])
686
+ )
687
+ );
688
+ };
689
+ walk(root, [0]);
690
+ emitInits();
691
+ emitActions();
692
+ emitEffects();
693
+ const rootBlock = b.blockStatement(body);
694
+ for (const address of pendingFrames.splice(0)) frames.set(address, rootBlock);
695
+ const program = b.arrowFunctionExpression(
696
+ [],
697
+ rootBlock
698
+ );
699
+ const inits = initBody.length ? b.arrowFunctionExpression(
700
+ [],
701
+ b.blockStatement(initBody)
702
+ ) : void 0;
703
+ return {
704
+ program,
705
+ anchors,
706
+ texts,
707
+ frames,
708
+ islands,
709
+ compiled,
710
+ weak,
711
+ ...inits ? { inits } : {}
712
+ };
713
+ }
714
+ var checkerProfileOf = (deploy) => ({
715
+ ...PRESETS.complete,
716
+ name: `${deploy.name}:types`,
717
+ ...deploy.types ? { types: deploy.types } : {}
718
+ });
719
+ var isWeak = (address, weak) => {
720
+ for (const prefix of weak)
721
+ if (address === prefix || address.startsWith(`${prefix}.`)) return true;
722
+ return false;
723
+ };
724
+ var exhaustiveHostParams = (port) => {
725
+ const level = port?.provenanceOf?.("params");
726
+ return level === "inferred" || level === "verified";
727
+ };
728
+ var issuesOf = (root, diagnostics, lowered, fallback) => anchorDiagnostics(root, diagnostics, lowered.anchors, {
729
+ fallback,
730
+ textOf: (path) => lowered.texts.get(addressOf(path))
731
+ }).map(({ diagnostic, anchor, span }) => {
732
+ const address = addressOf(anchor);
733
+ const source = lowered.texts.get(address);
734
+ return {
735
+ code: String(diagnostic.code ?? "error"),
736
+ message: String(diagnostic.message ?? ""),
737
+ severity: diagnostic.severity === "warning" ? "warning" : "error",
738
+ path: anchor,
739
+ address,
740
+ ...source === void 0 ? {} : { source },
741
+ ...span === void 0 ? {} : { span }
742
+ };
743
+ });
744
+ function checkComponent(def, env, opts = {}) {
745
+ return [...analyzeComponent(def, env, opts).issues];
746
+ }
747
+ function analyzeComponent(def, env, opts = {}) {
748
+ const profile = checkerProfileOf(opts.profile ?? DEFAULT_PROFILE);
749
+ const lowered = lowerComponent(def, {
750
+ ...opts.compiled ? { compiled: opts.compiled } : {},
751
+ shapeOf: (expression) => dataShape(expression, env),
752
+ ...opts.propsOf ? { propsOf: opts.propsOf } : {},
753
+ // o `set` de um update local é um call-site sobre o ESTADO: mesmo mecanismo, outra
754
+ // superfície. O tipo sai das declarações do próprio componente, então não há seam.
755
+ setType: partialStateType(def.state, opts.types),
756
+ // a MESMA ordem do runtime: update local primeiro, e o que não resolve aqui sai pela porta.
757
+ paramsOf: paramsResolver(
758
+ declaredParamsOf(def.updates, opts.types),
759
+ hostParamsOf(opts.actions, opts.types)
760
+ ),
761
+ // um update local é sempre exaustivo (a declaração É a verdade); a ação do host vale o que
762
+ // a proveniência disser.
763
+ exhaustiveParams: (action) => def.updates?.[action] !== void 0 || exhaustiveHostParams(opts.actions),
764
+ ...opts.emitsOf ? { emitsOf: opts.emitsOf } : {},
765
+ resultOf: hostResultOf(opts.actions, opts.types),
766
+ ...opts.mounting ? { mounting: opts.mounting } : {},
767
+ stateTypeOf: stateTypeOf(def.state, opts.types),
768
+ contextOf: declaredContextsOf(opts.contexts, opts.types)
769
+ });
770
+ const { program, inits, weak, compiled } = lowered;
771
+ const issues = [
772
+ ...checkDeclarations(def, opts.types),
773
+ ...checkContextCatalog(opts.contexts, opts.types)
774
+ ];
775
+ if (opts.compiled === void 0)
776
+ issues.push(
777
+ ...compiled.diagnostics.map((d) => ({
778
+ code: d.code,
779
+ message: d.message,
780
+ severity: d.severity,
781
+ path: d.path,
782
+ address: d.address,
783
+ ...d.source === void 0 ? {} : { source: d.source },
784
+ ...d.span === void 0 ? {} : { span: d.span }
785
+ }))
786
+ );
787
+ const initEnv = buildInitEnv(def, {
788
+ ...opts.types ? { types: opts.types } : {},
789
+ ...opts.contexts ? {
790
+ contexts: Object.fromEntries(
791
+ Object.entries(opts.contexts).map(([name, ref]) => [
792
+ name,
793
+ resolveTypeRef(ref, opts.types ?? {})
794
+ ])
795
+ )
796
+ } : {}
797
+ });
798
+ const seeded = inits ? check(inits, initEnv, {
799
+ profile,
800
+ ...opts.limits ? { limits: opts.limits } : {}
801
+ }) : void 0;
802
+ if (inits && seeded)
803
+ issues.push(
804
+ ...issuesOf(inits, seeded.diagnostics, lowered, ["state"])
805
+ );
806
+ const body = check(program, env, {
807
+ profile,
808
+ ...opts.limits ? { limits: opts.limits } : {}
809
+ });
810
+ issues.push(...issuesOf(program, body.diagnostics, lowered, [0]));
811
+ return {
812
+ issues: issues.map(
813
+ (issue) => issue.code === "excess-property" && isWeak(issue.address, weak) ? { ...issue, severity: "warning" } : issue
814
+ ),
815
+ lowered,
816
+ body,
817
+ initEnv,
818
+ ...seeded ? { inits: seeded } : {}
819
+ };
820
+ }
821
+ function checkExpression(source, env, path, opts = {}) {
822
+ const address = addressOf(path);
823
+ let ast;
824
+ try {
825
+ ast = parseExpression(source);
826
+ } catch (error) {
827
+ return [
828
+ {
829
+ code: "parse-error",
830
+ message: String(error?.message ?? error),
831
+ severity: "error",
832
+ path,
833
+ address,
834
+ source
835
+ }
836
+ ];
837
+ }
838
+ const { diagnostics } = check(ast, env, {
839
+ profile: checkerProfileOf(opts.profile ?? DEFAULT_PROFILE),
840
+ ...opts.resultType ? { resultType: opts.resultType } : {},
841
+ ...opts.limits ? { limits: opts.limits } : {}
842
+ });
843
+ return diagnostics.map((d) => {
844
+ const span = spanOf(source, d.node?.loc);
845
+ return {
846
+ code: String(d.code ?? "error"),
847
+ message: String(d.message ?? ""),
848
+ severity: d.severity === "warning" ? "warning" : "error",
849
+ path,
850
+ address,
851
+ source,
852
+ ...span === void 0 ? {} : { span }
853
+ };
854
+ });
855
+ }
856
+ function dataShape(expression, env) {
857
+ try {
858
+ const t = check(expression, env).type;
859
+ return t?.t === "array" ? "list" : "value";
860
+ } catch {
861
+ return "list";
862
+ }
863
+ }
864
+
865
+ export { DEFAULT_ASSERTER, analyzeComponent, buildEnv, buildInitEnv, checkComponent, checkContextCatalog, checkDeclarations, checkExpression, checkTree, checkerProfileOf, componentAssignable, componentType, createTsliteChecker, declaredContextsOf, declaredParamsOf, declaredPropsOf, lowerComponent, partialStateType, resolveProps, resolveTypeRef, stateTypeOf };
866
+ //# sourceMappingURL=index.js.map
867
+ //# sourceMappingURL=index.js.map