@hozu/validator 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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/context.d.ts +13 -0
  4. package/dist/context.d.ts.map +1 -0
  5. package/dist/context.js +27 -0
  6. package/dist/context.js.map +1 -0
  7. package/dist/contracts/lock.d.ts +19 -0
  8. package/dist/contracts/lock.d.ts.map +1 -0
  9. package/dist/contracts/lock.js +61 -0
  10. package/dist/contracts/lock.js.map +1 -0
  11. package/dist/contracts/run.d.ts +14 -0
  12. package/dist/contracts/run.d.ts.map +1 -0
  13. package/dist/contracts/run.js +130 -0
  14. package/dist/contracts/run.js.map +1 -0
  15. package/dist/contracts/skeleton.d.ts +4 -0
  16. package/dist/contracts/skeleton.d.ts.map +1 -0
  17. package/dist/contracts/skeleton.js +108 -0
  18. package/dist/contracts/skeleton.js.map +1 -0
  19. package/dist/contracts/verify.d.ts +5 -0
  20. package/dist/contracts/verify.d.ts.map +1 -0
  21. package/dist/contracts/verify.js +58 -0
  22. package/dist/contracts/verify.js.map +1 -0
  23. package/dist/env.d.ts +40 -0
  24. package/dist/env.d.ts.map +1 -0
  25. package/dist/env.js +79 -0
  26. package/dist/env.js.map +1 -0
  27. package/dist/impact.d.ts +27 -0
  28. package/dist/impact.d.ts.map +1 -0
  29. package/dist/impact.js +154 -0
  30. package/dist/impact.js.map +1 -0
  31. package/dist/index.d.ts +22 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +71 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/resolve.d.ts +13 -0
  36. package/dist/resolve.d.ts.map +1 -0
  37. package/dist/resolve.js +58 -0
  38. package/dist/resolve.js.map +1 -0
  39. package/dist/rules/classes.d.ts +3 -0
  40. package/dist/rules/classes.d.ts.map +1 -0
  41. package/dist/rules/classes.js +60 -0
  42. package/dist/rules/classes.js.map +1 -0
  43. package/dist/rules/data.d.ts +4 -0
  44. package/dist/rules/data.d.ts.map +1 -0
  45. package/dist/rules/data.js +34 -0
  46. package/dist/rules/data.js.map +1 -0
  47. package/dist/rules/dom.d.ts +3 -0
  48. package/dist/rules/dom.d.ts.map +1 -0
  49. package/dist/rules/dom.js +104 -0
  50. package/dist/rules/dom.js.map +1 -0
  51. package/dist/rules/errors.d.ts +3 -0
  52. package/dist/rules/errors.d.ts.map +1 -0
  53. package/dist/rules/errors.js +97 -0
  54. package/dist/rules/errors.js.map +1 -0
  55. package/dist/rules/events.d.ts +5 -0
  56. package/dist/rules/events.d.ts.map +1 -0
  57. package/dist/rules/events.js +87 -0
  58. package/dist/rules/events.js.map +1 -0
  59. package/dist/rules/forms.d.ts +3 -0
  60. package/dist/rules/forms.d.ts.map +1 -0
  61. package/dist/rules/forms.js +19 -0
  62. package/dist/rules/forms.js.map +1 -0
  63. package/dist/rules/html.d.ts +3 -0
  64. package/dist/rules/html.d.ts.map +1 -0
  65. package/dist/rules/html.js +55 -0
  66. package/dist/rules/html.js.map +1 -0
  67. package/dist/rules/http.d.ts +3 -0
  68. package/dist/rules/http.d.ts.map +1 -0
  69. package/dist/rules/http.js +71 -0
  70. package/dist/rules/http.js.map +1 -0
  71. package/dist/rules/i18n.d.ts +3 -0
  72. package/dist/rules/i18n.d.ts.map +1 -0
  73. package/dist/rules/i18n.js +201 -0
  74. package/dist/rules/i18n.js.map +1 -0
  75. package/dist/rules/images.d.ts +3 -0
  76. package/dist/rules/images.d.ts.map +1 -0
  77. package/dist/rules/images.js +32 -0
  78. package/dist/rules/images.js.map +1 -0
  79. package/dist/rules/links.d.ts +3 -0
  80. package/dist/rules/links.d.ts.map +1 -0
  81. package/dist/rules/links.js +60 -0
  82. package/dist/rules/links.js.map +1 -0
  83. package/dist/rules/literals.d.ts +3 -0
  84. package/dist/rules/literals.d.ts.map +1 -0
  85. package/dist/rules/literals.js +147 -0
  86. package/dist/rules/literals.js.map +1 -0
  87. package/dist/rules/paths.d.ts +3 -0
  88. package/dist/rules/paths.d.ts.map +1 -0
  89. package/dist/rules/paths.js +177 -0
  90. package/dist/rules/paths.js.map +1 -0
  91. package/dist/rules/pwa.d.ts +3 -0
  92. package/dist/rules/pwa.d.ts.map +1 -0
  93. package/dist/rules/pwa.js +28 -0
  94. package/dist/rules/pwa.js.map +1 -0
  95. package/dist/rules/refs.d.ts +5 -0
  96. package/dist/rules/refs.d.ts.map +1 -0
  97. package/dist/rules/refs.js +128 -0
  98. package/dist/rules/refs.js.map +1 -0
  99. package/dist/rules/rendering.d.ts +3 -0
  100. package/dist/rules/rendering.d.ts.map +1 -0
  101. package/dist/rules/rendering.js +37 -0
  102. package/dist/rules/rendering.js.map +1 -0
  103. package/dist/rules/routes.d.ts +4 -0
  104. package/dist/rules/routes.d.ts.map +1 -0
  105. package/dist/rules/routes.js +108 -0
  106. package/dist/rules/routes.js.map +1 -0
  107. package/dist/rules/states.d.ts +6 -0
  108. package/dist/rules/states.d.ts.map +1 -0
  109. package/dist/rules/states.js +167 -0
  110. package/dist/rules/states.js.map +1 -0
  111. package/dist/rules/text.d.ts +3 -0
  112. package/dist/rules/text.d.ts.map +1 -0
  113. package/dist/rules/text.js +148 -0
  114. package/dist/rules/text.js.map +1 -0
  115. package/dist/rules/widgets.d.ts +3 -0
  116. package/dist/rules/widgets.d.ts.map +1 -0
  117. package/dist/rules/widgets.js +33 -0
  118. package/dist/rules/widgets.js.map +1 -0
  119. package/dist/schema.d.ts +19 -0
  120. package/dist/schema.d.ts.map +1 -0
  121. package/dist/schema.js +142 -0
  122. package/dist/schema.js.map +1 -0
  123. package/dist/sites.d.ts +15 -0
  124. package/dist/sites.d.ts.map +1 -0
  125. package/dist/sites.js +151 -0
  126. package/dist/sites.js.map +1 -0
  127. package/dist/suggest.d.ts +4 -0
  128. package/dist/suggest.d.ts.map +1 -0
  129. package/dist/suggest.js +30 -0
  130. package/dist/suggest.js.map +1 -0
  131. package/dist/walk.d.ts +37 -0
  132. package/dist/walk.d.ts.map +1 -0
  133. package/dist/walk.js +138 -0
  134. package/dist/walk.js.map +1 -0
  135. package/package.json +46 -0
package/dist/env.js ADDED
@@ -0,0 +1,79 @@
1
+ import { INVALID_ERROR_SCHEMA, UNEXPECTED_ERROR_SCHEMA, } from '@hozu/core/ir';
2
+ import { resolveRef } from './resolve.js';
3
+ import { resolvePath } from './schema.js';
4
+ export const schemaIn = (feature, hash) => (feature && hash !== undefined ? feature.schemas[hash] : undefined) ?? null;
5
+ const invalidSchema = (input) => ({
6
+ ...INVALID_ERROR_SCHEMA,
7
+ properties: {
8
+ message: { type: 'string' },
9
+ fields: {
10
+ type: 'object',
11
+ properties: Object.fromEntries(Object.keys(input?.properties ?? {}).map((k) => [
12
+ k,
13
+ { type: ['string', 'null'] },
14
+ ])),
15
+ additionalProperties: false,
16
+ },
17
+ },
18
+ });
19
+ export function effectSchemas(ir, ref) {
20
+ const r = resolveRef(ir, ref, 'effect');
21
+ if (!r)
22
+ return null;
23
+ const effect = r.registry === 'queries' ? r.feature.queries[r.symbol] : r.feature.mutations[r.symbol];
24
+ return {
25
+ input: schemaIn(r.feature, effect.input),
26
+ output: schemaIn(r.feature, effect.output),
27
+ errors: effect.errors,
28
+ invalid: r.registry === 'mutations',
29
+ error: (name) => name === 'Unexpected'
30
+ ? UNEXPECTED_ERROR_SCHEMA
31
+ : name === 'Invalid' && r.registry === 'mutations' && !effect.errors.Invalid
32
+ ? invalidSchema(schemaIn(r.feature, effect.input))
33
+ : schemaIn(r.feature, effect.errors[name]),
34
+ };
35
+ }
36
+ export function valueSchema(ir, env, value) {
37
+ if ('ref' in value) {
38
+ const base = value.ref === 'binding' ? env.bindings[value.depth] : env.sources[value.ref];
39
+ const r = resolvePath(base ?? null, value.path);
40
+ return r.ok ? r.schema : null;
41
+ }
42
+ if ('test' in value)
43
+ return { type: 'boolean' };
44
+ if ('link' in value)
45
+ return { type: 'string' };
46
+ if ('fn' in value) {
47
+ if (value.fn.startsWith('#'))
48
+ return { type: 'string' };
49
+ const r = resolveRef(ir, value.fn, 'fn');
50
+ return r ? schemaIn(r.feature, r.feature.fns[r.symbol].output) : null;
51
+ }
52
+ return null;
53
+ }
54
+ export function contextEnv(feature) {
55
+ return { feature, sources: { context: schemaIn(feature, feature.machine?.context) }, bindings: [] };
56
+ }
57
+ export function triggerEnv(ctx, feature, site) {
58
+ const key = site.envKey;
59
+ const trigger = site.trigger;
60
+ let env = ctx.envs.get(key);
61
+ if (env)
62
+ return env;
63
+ const base = contextEnv(feature);
64
+ const sources = { ...base.sources };
65
+ if (trigger.kind === 'on')
66
+ sources.event = eventSchema(ctx.ir, trigger.event);
67
+ else if (trigger.kind === 'done')
68
+ sources.result = effectSchemas(ctx.ir, trigger.effect)?.output ?? null;
69
+ else if (trigger.kind === 'failed')
70
+ sources.error = effectSchemas(ctx.ir, trigger.effect)?.error(trigger.error) ?? null;
71
+ env = { ...base, sources };
72
+ ctx.envs.set(key, env);
73
+ return env;
74
+ }
75
+ export function eventSchema(ir, ref) {
76
+ const r = resolveRef(ir, ref, 'event');
77
+ return r ? schemaIn(r.feature, r.feature.events[r.symbol].payload) : null;
78
+ }
79
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type ProjectIR } from '@hozu/core/ir';
2
+ export type ImpactKind = 'event' | 'query' | 'mutation' | 'tag' | 'fn' | 'view';
3
+ export interface ImpactQuery {
4
+ ref: string;
5
+ tag: string;
6
+ precision: 'exact' | 'param-dependent';
7
+ }
8
+ export interface ImpactUse {
9
+ feature: string;
10
+ at: string;
11
+ via: string;
12
+ }
13
+ export interface Impact {
14
+ target: string;
15
+ kind: ImpactKind;
16
+ tags: string[];
17
+ queries: ImpactQuery[];
18
+ invalidatedBy: string[];
19
+ uses: ImpactUse[];
20
+ features: string[];
21
+ }
22
+ export declare class UnknownSymbolError extends Error {
23
+ readonly suggestions: string[];
24
+ constructor(message: string, suggestions: string[]);
25
+ }
26
+ export declare function impact(ir: ProjectIR, target: string): Impact;
27
+ //# sourceMappingURL=impact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact.d.ts","sourceRoot":"","sources":["../src/impact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,eAAe,CAAA;AAKzE,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,GAAG,IAAI,GAAG,MAAM,CAAA;AAE/E,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,OAAO,GAAG,iBAAiB,CAAA;CACvC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,IAAI,EAAE,SAAS,EAAE,CAAA;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAWD,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAA;IAC9B,YAAY,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAGjD;CACF;AAsBD,wBAAgB,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAqG5D"}
package/dist/impact.js ADDED
@@ -0,0 +1,154 @@
1
+ import { resolveAt } from '@hozu/core/ir';
2
+ import { guardRefs, valueRefs } from './sites.js';
3
+ import { closest } from './suggest.js';
4
+ import { transitionsOf, walkView } from './walk.js';
5
+ const registries = [
6
+ ['event', 'events'],
7
+ ['query', 'queries'],
8
+ ['mutation', 'mutations'],
9
+ ['tag', 'tags'],
10
+ ['fn', 'fns'],
11
+ ['view', 'views'],
12
+ ];
13
+ export class UnknownSymbolError extends Error {
14
+ suggestions;
15
+ constructor(message, suggestions) {
16
+ super(message);
17
+ this.suggestions = suggestions;
18
+ }
19
+ }
20
+ function kindOf(ir, target) {
21
+ const dot = target.indexOf('.');
22
+ const [fid, symbol] = dot < 0 ? [target, ''] : [target.slice(0, dot), target.slice(dot + 1)];
23
+ const feature = ir.features[fid];
24
+ const all = Object.values(ir.features).flatMap((f) => registries.flatMap(([, r]) => Object.keys(f[r]).map((s) => `${f.id}.${s}`)));
25
+ if (feature)
26
+ for (const [kind, registry] of registries)
27
+ if (Object.hasOwn(feature[registry], symbol))
28
+ return kind;
29
+ const guess = closest(target, all);
30
+ throw new UnknownSymbolError(`Unknown symbol "${target}"`, guess ? [guess] : all);
31
+ }
32
+ const sameParam = (a, b) => a.param === null && b.param === null
33
+ ? true
34
+ : a.param !== null && b.param !== null && 'literal' in a.param && 'literal' in b.param
35
+ ? JSON.stringify(a.param.literal) === JSON.stringify(b.param.literal)
36
+ : null;
37
+ export function impact(ir, target) {
38
+ const kind = kindOf(ir, target);
39
+ const features = Object.values(ir.features);
40
+ const tags = [];
41
+ const queries = [];
42
+ const invalidatedBy = new Set();
43
+ const uses = [];
44
+ const queriesWith = (tag) => {
45
+ for (const f of features)
46
+ for (const [sym, q] of Object.entries(f.queries))
47
+ for (const t of q.tags)
48
+ if (t.tag === tag.tag) {
49
+ const same = sameParam(tag, t);
50
+ if (same !== false)
51
+ queries.push({
52
+ ref: `${f.id}.${sym}`,
53
+ tag: t.tag,
54
+ precision: same ? 'exact' : 'param-dependent',
55
+ });
56
+ }
57
+ };
58
+ const mutationsWith = (tag) => {
59
+ for (const f of features)
60
+ for (const [sym, m] of Object.entries(f.mutations))
61
+ if (m.invalidates.some((t) => t.tag === tag))
62
+ invalidatedBy.add(`${f.id}.${sym}`);
63
+ };
64
+ const reads = new Set();
65
+ if (kind === 'mutation') {
66
+ const [fid, sym] = target.split('.');
67
+ for (const t of ir.features[fid].mutations[sym].invalidates) {
68
+ tags.push(t.tag);
69
+ queriesWith(t);
70
+ }
71
+ for (const q of queries)
72
+ reads.add(q.ref);
73
+ }
74
+ else if (kind === 'query') {
75
+ const [fid, sym] = target.split('.');
76
+ for (const t of ir.features[fid].queries[sym].tags) {
77
+ tags.push(t.tag);
78
+ mutationsWith(t.tag);
79
+ }
80
+ reads.add(target);
81
+ }
82
+ else if (kind === 'tag') {
83
+ tags.push(target);
84
+ queriesWith({ tag: target, param: null });
85
+ for (const q of queries)
86
+ q.precision = 'param-dependent';
87
+ mutationsWith(target);
88
+ for (const q of queries)
89
+ reads.add(q.ref);
90
+ }
91
+ const effects = kind === 'mutation' ? new Set([target, ...reads]) : reads;
92
+ for (const f of features) {
93
+ for (const site of transitionsOf(f)) {
94
+ if (kind === 'event' && site.trigger.kind === 'on' && site.trigger.event === target)
95
+ uses.push({ feature: f.id, at: site.pointer, via: `handled in "${site.state}"` });
96
+ if (kind === 'fn') {
97
+ const found = (ref) => {
98
+ if (ref === target)
99
+ uses.push({ feature: f.id, at: site.pointer, via: `used by ${site.state} transition` });
100
+ };
101
+ if (site.transition.guard)
102
+ guardRefs(site.transition.guard, '', found);
103
+ for (const a of site.transition.assign)
104
+ valueRefs(a.value, '', found);
105
+ }
106
+ }
107
+ for (const [state, s] of Object.entries(f.machine?.states ?? {}))
108
+ if (s.invoke && effects.has(s.invoke.effect))
109
+ uses.push({
110
+ feature: f.id,
111
+ at: `/features/${f.id}/machine/states/${state}/invoke`,
112
+ via: `"${state}" invokes ${s.invoke.effect}`,
113
+ });
114
+ for (const [vid, view] of Object.entries(f.views))
115
+ walkView(ir, f, vid, view, ({ node, pointer }) => {
116
+ const at = resolveAt(pointer);
117
+ if (node.kind === 'query' && reads.has(node.query))
118
+ uses.push({ feature: f.id, at, via: `${node.id} reads ${node.query}` });
119
+ if (node.kind === 'embed' && kind === 'view' && node.view === target)
120
+ uses.push({ feature: f.id, at, via: `${node.id} embeds ${target}` });
121
+ if (node.kind === 'el' && kind === 'event')
122
+ for (const send of Object.values(node.on))
123
+ if (send.event === target)
124
+ uses.push({ feature: f.id, at, via: `${node.id} sends ${target}` });
125
+ if (kind === 'fn') {
126
+ const found = (ref) => {
127
+ if (ref === target)
128
+ uses.push({ feature: f.id, at, via: `${node.id} uses ${target}` });
129
+ };
130
+ if (node.kind === 'text')
131
+ valueRefs(node.value, '', found);
132
+ if (node.kind === 'each')
133
+ valueRefs(node.source, '', found);
134
+ }
135
+ });
136
+ }
137
+ const touched = new Set([target.split('.')[0]]);
138
+ for (const q of queries)
139
+ touched.add(q.ref.split('.')[0]);
140
+ for (const m of invalidatedBy)
141
+ touched.add(m.split('.')[0]);
142
+ for (const u of uses)
143
+ touched.add(u.feature);
144
+ return {
145
+ target,
146
+ kind,
147
+ tags: [...new Set(tags)],
148
+ queries,
149
+ invalidatedBy: [...invalidatedBy].sort(),
150
+ uses,
151
+ features: [...touched].sort(),
152
+ };
153
+ }
154
+ //# sourceMappingURL=impact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact.js","sourceRoot":"","sources":["../src/impact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Bindings, Diagnostic, ProjectIR, SourceIndex } from '@hozu/core/ir';
2
+ import type { Lockfile } from './contracts/lock.ts';
3
+ export type { Drift, LockEntry, Lockfile } from './contracts/lock.ts';
4
+ export type { ContractRun, Failure } from './contracts/run.ts';
5
+ export { runContract } from './contracts/run.ts';
6
+ export type { Impact, ImpactKind, ImpactQuery, ImpactUse } from './impact.ts';
7
+ export { impact, UnknownSymbolError } from './impact.ts';
8
+ export { closest, distance } from './suggest.ts';
9
+ export interface ValidateOptions {
10
+ sources?: SourceIndex;
11
+ feature?: string;
12
+ bindings?: Bindings;
13
+ lock?: Lockfile | null;
14
+ unknownClasses?: Map<string, string | null> | null;
15
+ }
16
+ export interface Verification {
17
+ diagnostics: Diagnostic[];
18
+ lock: Lockfile | null;
19
+ }
20
+ export declare function verify(ir: ProjectIR, options?: ValidateOptions): Verification;
21
+ export declare const validate: (ir: ProjectIR, options?: ValidateOptions) => Diagnostic[];
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAuBnD,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACrE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC7E,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAuChD,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACtB,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;CACnD;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;CACtB;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,GAAE,eAAoB,GAAG,YAAY,CAajF;AAED,eAAO,MAAM,QAAQ,OAAQ,SAAS,YAAW,eAAe,KAAQ,UAAU,EACjD,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,71 @@
1
+ import { Ctx } from './context.js';
2
+ import { verifyContracts } from './contracts/verify.js';
3
+ import { classNames } from './rules/classes.js';
4
+ import { invalidations, sessions } from './rules/data.js';
5
+ import { domFields } from './rules/dom.js';
6
+ import { declaredErrors } from './rules/errors.js';
7
+ import { conflictingIgnores, unhandledEvents, viewEvents } from './rules/events.js';
8
+ import { progressiveForms } from './rules/forms.js';
9
+ import { unsafeHtml } from './rules/html.js';
10
+ import { httpRules } from './rules/http.js';
11
+ import { i18n } from './rules/i18n.js';
12
+ import { imageDimensions } from './rules/images.js';
13
+ import { internalLinks } from './rules/links.js';
14
+ import { literals } from './rules/literals.js';
15
+ import { paths } from './rules/paths.js';
16
+ import { offlinePage } from './rules/pwa.js';
17
+ import { featureLinks, references, routes } from './rules/refs.js';
18
+ import { rendering } from './rules/rendering.js';
19
+ import { routeParams, searchSchemas } from './rules/routes.js';
20
+ import { deadEnds, reachability, shadowing, stateNames } from './rules/states.js';
21
+ import { domText } from './rules/text.js';
22
+ import { widgetEvents } from './rules/widgets.js';
23
+ export { runContract } from './contracts/run.js';
24
+ export { impact, UnknownSymbolError } from './impact.js';
25
+ export { closest, distance } from './suggest.js';
26
+ const rules = [
27
+ featureLinks,
28
+ references,
29
+ routes,
30
+ stateNames,
31
+ reachability,
32
+ unhandledEvents,
33
+ declaredErrors,
34
+ viewEvents,
35
+ paths,
36
+ shadowing,
37
+ deadEnds,
38
+ invalidations,
39
+ sessions,
40
+ rendering,
41
+ routeParams,
42
+ searchSchemas,
43
+ domFields,
44
+ classNames,
45
+ widgetEvents,
46
+ imageDimensions,
47
+ unsafeHtml,
48
+ literals,
49
+ internalLinks,
50
+ conflictingIgnores,
51
+ domText,
52
+ progressiveForms,
53
+ httpRules,
54
+ i18n,
55
+ offlinePage,
56
+ ];
57
+ const order = (a, b) => (a.location.feature ?? '').localeCompare(b.location.feature ?? '') ||
58
+ a.location.pointer.localeCompare(b.location.pointer) ||
59
+ a.code.localeCompare(b.code);
60
+ export function verify(ir, options = {}) {
61
+ const ctx = new Ctx(ir, options.sources ?? {}, options.unknownClasses ?? null, options.bindings?.assets ?? {});
62
+ for (const rule of rules)
63
+ rule(ctx);
64
+ const lock = options.bindings ? verifyContracts(ctx, options.bindings, options.lock ?? null) : null;
65
+ const out = options.feature
66
+ ? ctx.diagnostics.filter((d) => d.location.feature === options.feature)
67
+ : ctx.diagnostics;
68
+ return { diagnostics: out.sort(order), lock };
69
+ }
70
+ export const validate = (ir, options = {}) => verify(ir, options).diagnostics;
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { FeatureIR, ProjectIR } from '@hozu/core/ir';
2
+ export type RefKind = 'event' | 'query' | 'mutation' | 'effect' | 'tag' | 'fn' | 'view' | 'widget';
3
+ export type Registry = 'events' | 'queries' | 'mutations' | 'tags' | 'fns' | 'views' | 'widgets';
4
+ export declare const registriesOf: Record<RefKind, Registry[]>;
5
+ export interface Resolved {
6
+ feature: FeatureIR;
7
+ symbol: string;
8
+ registry: Registry;
9
+ }
10
+ export declare const splitRef: (ref: string) => [string, string];
11
+ export declare function resolveRef(ir: ProjectIR, ref: string, kind: RefKind): Resolved | null;
12
+ export declare function candidatesFor(ir: ProjectIR, from: FeatureIR, kind: RefKind): string[];
13
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAEpE,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAA;AAElG,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAA;AAEhG,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,CASpD,CAAA;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED,eAAO,MAAM,QAAQ,QAAS,MAAM,KAAG,CAAC,MAAM,EAAE,MAAM,CAGrD,CAAA;AAID,wBAAgB,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAgBrF;AAWD,wBAAgB,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAWrF"}
@@ -0,0 +1,58 @@
1
+ export const registriesOf = {
2
+ event: ['events'],
3
+ query: ['queries'],
4
+ mutation: ['mutations'],
5
+ effect: ['queries', 'mutations'],
6
+ tag: ['tags'],
7
+ fn: ['fns'],
8
+ view: ['views'],
9
+ widget: ['widgets'],
10
+ };
11
+ export const splitRef = (ref) => {
12
+ const dot = ref.indexOf('.');
13
+ return dot < 0 ? [ref, ''] : [ref.slice(0, dot), ref.slice(dot + 1)];
14
+ };
15
+ const memo = new WeakMap();
16
+ export function resolveRef(ir, ref, kind) {
17
+ let byKind = memo.get(ir);
18
+ if (!byKind) {
19
+ byKind = {};
20
+ memo.set(ir, byKind);
21
+ }
22
+ let cache = byKind[kind];
23
+ if (!cache) {
24
+ cache = new Map();
25
+ byKind[kind] = cache;
26
+ }
27
+ const hit = cache.get(ref);
28
+ if (hit !== undefined)
29
+ return hit;
30
+ const resolved = lookup(ir, ref, kind);
31
+ cache.set(ref, resolved);
32
+ return resolved;
33
+ }
34
+ function lookup(ir, ref, kind) {
35
+ const [fid, symbol] = splitRef(ref);
36
+ const feature = ir.features[fid];
37
+ if (!feature)
38
+ return null;
39
+ for (const registry of registriesOf[kind])
40
+ if (Object.hasOwn(feature[registry], symbol))
41
+ return { feature, symbol, registry };
42
+ return null;
43
+ }
44
+ export function candidatesFor(ir, from, kind) {
45
+ const out = [];
46
+ for (const registry of registriesOf[kind]) {
47
+ for (const symbol of Object.keys(from[registry]))
48
+ out.push(`${from.id}.${symbol}`);
49
+ for (const fid of from.imports) {
50
+ const other = ir.features[fid];
51
+ if (other)
52
+ for (const symbol of other.exports[registry] ?? [])
53
+ out.push(`${fid}.${symbol}`);
54
+ }
55
+ }
56
+ return out;
57
+ }
58
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Ctx } from '../context.ts';
2
+ export declare function classNames(ctx: Ctx): void;
3
+ //# sourceMappingURL=classes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../src/rules/classes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAQxC,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,QAiElC"}
@@ -0,0 +1,60 @@
1
+ import { at, motionClasses, resolveAt } from '@hozu/core/ir';
2
+ import { didYouMean } from '../suggest.js';
3
+ import { walkView } from '../walk.js';
4
+ const tokens = (value) => value.split(/\s+/).filter(Boolean);
5
+ export function classNames(ctx) {
6
+ const unknown = ctx.unknownClasses;
7
+ if (!unknown?.size)
8
+ return;
9
+ const { ir } = ctx;
10
+ for (const f of Object.values(ir.features))
11
+ for (const [vid, view] of Object.entries(f.views))
12
+ walkView(ir, f, vid, view, ({ node, pointer }) => {
13
+ if ((node.kind === 'when' || node.kind === 'each' || node.kind === 'if') && node.motion) {
14
+ if (motionClasses(node.motion).every((c) => unknown.has(c)))
15
+ ctx.report('HZ026', f.id, at(pointer, 'motion'), `Motion "${node.motion}" has no CSS`, `Define at least ${node.motion}-enter-active / ${node.motion}-leave-active (and optionally -from, -to, -move) in a stylesheet.`, {
16
+ summary: `Add transition classes for "${node.motion}"`,
17
+ snippet: `.${node.motion}-enter-active, .${node.motion}-leave-active { transition: opacity 200ms; }\n.${node.motion}-enter-from, .${node.motion}-leave-to { opacity: 0; }`,
18
+ patch: null,
19
+ });
20
+ return;
21
+ }
22
+ if (node.kind !== 'el' && node.kind !== 'widget')
23
+ return;
24
+ const lists = [];
25
+ if (node.class)
26
+ lists.push([
27
+ node.class,
28
+ at(pointer, 'class'),
29
+ (fixed) => [{ op: 'replace', path: resolveAt(at(pointer, 'class')), value: fixed }],
30
+ ]);
31
+ for (const key of Object.keys(node.toggle))
32
+ lists.push([
33
+ key,
34
+ at(pointer, 'toggle', key),
35
+ (fixed) => [
36
+ { op: 'add', path: resolveAt(at(pointer, 'toggle', fixed)), value: node.toggle[key] },
37
+ { op: 'remove', path: resolveAt(at(pointer, 'toggle', key)) },
38
+ ],
39
+ ]);
40
+ for (const [value, p, patch] of lists) {
41
+ const bad = tokens(value).filter((c) => unknown.has(c));
42
+ if (!bad.length)
43
+ continue;
44
+ const fixes = bad.map((c) => unknown.get(c) ?? null);
45
+ const fixed = fixes.every((x) => x !== null)
46
+ ? tokens(value)
47
+ .map((c) => unknown.get(c) ?? c)
48
+ .join(' ')
49
+ : null;
50
+ ctx.report('HZ026', f.id, p, bad.length === 1
51
+ ? `Class "${bad[0]}" produces no CSS.${didYouMean(fixes[0])}`
52
+ : `Classes ${bad.map((c) => `"${c}"`).join(', ')} produce no CSS`, 'Every class must be a Tailwind utility or a class defined in the project stylesheets. Use data-* attributes as script hooks.', {
53
+ summary: fixed ? `Use "${fixed}"` : 'Fix the class name or define it in a stylesheet',
54
+ snippet: null,
55
+ patch: fixed ? patch(fixed) : null,
56
+ });
57
+ }
58
+ });
59
+ }
60
+ //# sourceMappingURL=classes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classes.js","sourceRoot":"","sources":["../../src/rules/classes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Ctx } from '../context.ts';
2
+ export declare function invalidations(ctx: Ctx): void;
3
+ export declare function sessions(ctx: Ctx): void;
4
+ //# sourceMappingURL=data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../src/rules/data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAGxC,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,QAsBrC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,QAkBhC"}
@@ -0,0 +1,34 @@
1
+ import { resolveAt } from '@hozu/core/ir';
2
+ import { featurePointer } from '../walk.js';
3
+ export function invalidations(ctx) {
4
+ const carried = new Set();
5
+ for (const f of Object.values(ctx.ir.features))
6
+ for (const q of Object.values(f.queries))
7
+ for (const t of q.tags)
8
+ carried.add(t.tag);
9
+ for (const f of Object.values(ctx.ir.features))
10
+ for (const [sym, m] of Object.entries(f.mutations))
11
+ m.invalidates.forEach((t, i) => {
12
+ if (t.tag === '?' || carried.has(t.tag))
13
+ return;
14
+ const p = featurePointer(f.id, 'mutations', sym, 'invalidates', i);
15
+ ctx.report('HZ019', f.id, p, `${f.id}.${sym} invalidates ${t.tag}, but no query carries that tag`, 'The invalidation has no effect; either a query is missing the tag or the mutation names the wrong one.', {
16
+ summary: 'Tag the affected query, or remove this invalidation',
17
+ snippet: null,
18
+ patch: [{ op: 'remove', path: resolveAt(p) }],
19
+ });
20
+ });
21
+ }
22
+ export function sessions(ctx) {
23
+ if (ctx.ir.session !== null)
24
+ return;
25
+ for (const f of Object.values(ctx.ir.features))
26
+ for (const [sym, q] of Object.entries(f.queries))
27
+ if (q.scope === 'user')
28
+ ctx.report('HZ020', f.id, featurePointer(f.id, 'queries', sym, 'scope'), `${f.id}.${sym} is user-scoped but the project declares no session`, 'User-scoped data needs an authenticated identity to partition its cache (ADR 0005 D2).', {
29
+ summary: "Declare project({ session: schema }), or decide the data is public and change scope to 'public'",
30
+ snippet: 'session: z.object({ userId: z.string() })',
31
+ patch: null,
32
+ });
33
+ }
34
+ //# sourceMappingURL=data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.js","sourceRoot":"","sources":["../../src/rules/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;IACjC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACtF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;YAChD,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBAC7B,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;oBAAE,OAAM;gBAC/C,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAA;gBAClE,GAAG,CAAC,MAAM,CACR,OAAO,EACP,CAAC,CAAC,EAAE,EACJ,CAAC,EACD,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,gBAAgB,CAAC,CAAC,GAAG,iCAAiC,EACpE,wGAAwG,EACxG;oBACE,OAAO,EAAE,qDAAqD;oBAC9D,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC9C,CACF,CAAA;YACH,CAAC,CAAC,CAAA;AACR,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAQ;IAC/B,IAAI,GAAG,CAAC,EAAE,CAAC,OAAO,KAAK,IAAI;QAAE,OAAM;IACnC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;gBACpB,GAAG,CAAC,MAAM,CACR,OAAO,EACP,CAAC,CAAC,EAAE,EACJ,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,EAC7C,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,qDAAqD,EACnE,wFAAwF,EACxF;oBACE,OAAO,EACL,iGAAiG;oBACnG,OAAO,EAAE,2CAA2C;oBACpD,KAAK,EAAE,IAAI;iBACZ,CACF,CAAA;AACT,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Ctx } from '../context.ts';
2
+ export declare function domFields(ctx: Ctx): void;
3
+ //# sourceMappingURL=dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/rules/dom.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAoCxC,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,QAmFjC"}