@invariant-ui/cli 0.0.0-stage → 0.2.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 (190) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +250 -2
  3. package/dist/agent-kit/apply.js +232 -0
  4. package/dist/agent-kit/guidance.js +236 -0
  5. package/dist/agent-kit/index.js +5 -0
  6. package/dist/agent-kit/integrations.js +121 -0
  7. package/dist/agent-kit/plugin.js +115 -0
  8. package/dist/artifact-generator/index.js +75 -0
  9. package/dist/browser-verify/driver.js +2 -0
  10. package/dist/browser-verify/index.js +4 -0
  11. package/dist/browser-verify/playwright.js +82 -0
  12. package/dist/browser-verify/runner.js +175 -0
  13. package/dist/browser-verify/spec.js +103 -0
  14. package/dist/cli/args.js +77 -0
  15. package/dist/cli/baseline.js +64 -0
  16. package/dist/cli/cli.js +121 -0
  17. package/dist/cli/commands-browser.js +104 -0
  18. package/dist/cli/commands-discover.js +312 -0
  19. package/dist/cli/commands-enforcement.js +35 -0
  20. package/dist/cli/commands-governance.js +179 -0
  21. package/dist/cli/commands-hook.js +269 -0
  22. package/dist/cli/commands-patterns.js +324 -0
  23. package/dist/cli/commands-setup.js +485 -0
  24. package/dist/cli/commands-validate.js +157 -0
  25. package/dist/cli/commands.js +517 -0
  26. package/dist/cli/config.js +197 -0
  27. package/dist/cli/diff.js +66 -0
  28. package/dist/cli/enforcement-log.js +83 -0
  29. package/dist/cli/enforcement-report.js +96 -0
  30. package/dist/cli/errors.js +10 -0
  31. package/dist/cli/format.js +22 -0
  32. package/dist/cli/index.js +5 -0
  33. package/dist/cli/io.js +2 -0
  34. package/dist/cli/main.js +31 -0
  35. package/dist/cli/pipeline.js +262 -0
  36. package/dist/cli/publish.js +77 -0
  37. package/dist/cli/report.js +127 -0
  38. package/dist/cli/starter-rules.js +57 -0
  39. package/dist/cli/store.js +60 -0
  40. package/dist/cli/version.js +5 -0
  41. package/dist/cli/watch.js +68 -0
  42. package/dist/cli/workflow.js +52 -0
  43. package/dist/compiler-angular/adapter.js +115 -0
  44. package/dist/compiler-angular/analyze.js +222 -0
  45. package/dist/compiler-angular/classes.js +446 -0
  46. package/dist/compiler-angular/declared.js +285 -0
  47. package/dist/compiler-angular/emit.js +183 -0
  48. package/dist/compiler-angular/index.js +4 -0
  49. package/dist/compiler-angular/template.js +142 -0
  50. package/dist/compiler-core/adapter.js +2 -0
  51. package/dist/compiler-core/adapters/inventory.js +312 -0
  52. package/dist/compiler-core/compile.js +148 -0
  53. package/dist/compiler-core/component-facts.js +123 -0
  54. package/dist/compiler-core/discovery/docs.js +66 -0
  55. package/dist/compiler-core/discovery/entries.js +270 -0
  56. package/dist/compiler-core/discovery/exports.js +207 -0
  57. package/dist/compiler-core/discovery/graph.js +59 -0
  58. package/dist/compiler-core/discovery/index.js +103 -0
  59. package/dist/compiler-core/discovery/packages.js +148 -0
  60. package/dist/compiler-core/discovery/schema.js +144 -0
  61. package/dist/compiler-core/discovery/storybook.js +232 -0
  62. package/dist/compiler-core/discovery/support.js +82 -0
  63. package/dist/compiler-core/discovery/tokens.js +186 -0
  64. package/dist/compiler-core/discovery/tooling.js +146 -0
  65. package/dist/compiler-core/fs.js +89 -0
  66. package/dist/compiler-core/glob.js +3 -0
  67. package/dist/compiler-core/index.js +16 -0
  68. package/dist/compiler-core/ir-builder.js +68 -0
  69. package/dist/compiler-core/json-schema.js +11 -0
  70. package/dist/compiler-core/testing/index.js +81 -0
  71. package/dist/compiler-core/ts/ast.js +166 -0
  72. package/dist/compiler-core/ts/members.js +163 -0
  73. package/dist/compiler-core/ts/program.js +81 -0
  74. package/dist/compiler-core/ts/static-eval.js +145 -0
  75. package/dist/compiler-core/ts/tsconfig-paths.js +60 -0
  76. package/dist/compiler-core/walk.js +46 -0
  77. package/dist/compiler-ir/index.js +4 -0
  78. package/dist/compiler-ir/ir.js +67 -0
  79. package/dist/compiler-ir/json-schema.js +6 -0
  80. package/dist/compiler-ir/validate.js +116 -0
  81. package/dist/compiler-react/adapter.js +147 -0
  82. package/dist/compiler-react/analyze.js +199 -0
  83. package/dist/compiler-react/behavior.js +75 -0
  84. package/dist/compiler-react/detect.js +558 -0
  85. package/dist/compiler-react/emit.js +188 -0
  86. package/dist/compiler-react/index.js +2 -0
  87. package/dist/compiler-react/props.js +157 -0
  88. package/dist/compiler-react/styling.js +138 -0
  89. package/dist/compiler-react/usage.js +116 -0
  90. package/dist/compiler-react/variants.js +111 -0
  91. package/dist/compiler-storybook/adapter.js +253 -0
  92. package/dist/compiler-storybook/csf.js +521 -0
  93. package/dist/compiler-storybook/emit.js +202 -0
  94. package/dist/compiler-storybook/index-json.js +41 -0
  95. package/dist/compiler-storybook/index.js +5 -0
  96. package/dist/compiler-storybook/mdx.js +120 -0
  97. package/dist/compiler-tokens/adapter.js +158 -0
  98. package/dist/compiler-tokens/css.js +59 -0
  99. package/dist/compiler-tokens/index.js +5 -0
  100. package/dist/compiler-tokens/json-lines.js +106 -0
  101. package/dist/compiler-tokens/json-tokens.js +52 -0
  102. package/dist/compiler-vue/adapter.js +107 -0
  103. package/dist/compiler-vue/analyze.js +344 -0
  104. package/dist/compiler-vue/declared.js +343 -0
  105. package/dist/compiler-vue/emit.js +129 -0
  106. package/dist/compiler-vue/index.js +5 -0
  107. package/dist/compiler-vue/script.js +472 -0
  108. package/dist/compiler-vue/sfc.js +44 -0
  109. package/dist/compiler-vue/template.js +73 -0
  110. package/dist/contract/archetype-checks.js +153 -0
  111. package/dist/contract/components.js +102 -0
  112. package/dist/contract/conflicts.js +39 -0
  113. package/dist/contract/contract.js +46 -0
  114. package/dist/contract/evidence.js +84 -0
  115. package/dist/contract/fact-path.js +39 -0
  116. package/dist/contract/facts.js +62 -0
  117. package/dist/contract/index.js +16 -0
  118. package/dist/contract/integrity.js +21 -0
  119. package/dist/contract/json-schema.js +11 -0
  120. package/dist/contract/knowledge.js +95 -0
  121. package/dist/contract/pattern-checks.js +254 -0
  122. package/dist/contract/patterns.js +225 -0
  123. package/dist/contract/primitives.js +81 -0
  124. package/dist/contract/sources.js +30 -0
  125. package/dist/contract/tokens.js +41 -0
  126. package/dist/contract/validate.js +253 -0
  127. package/dist/contract-query/archetype.js +188 -0
  128. package/dist/contract-query/index.js +6 -0
  129. package/dist/contract-query/patterns.js +298 -0
  130. package/dist/contract-query/search.js +132 -0
  131. package/dist/contract-query/system.js +148 -0
  132. package/dist/contract-query/views.js +288 -0
  133. package/dist/governance/decisions.js +229 -0
  134. package/dist/governance/index.js +5 -0
  135. package/dist/governance/patterns-file.js +156 -0
  136. package/dist/governance/patterns.js +510 -0
  137. package/dist/governance/policies.js +148 -0
  138. package/dist/mcp/index.js +7 -0
  139. package/dist/mcp/loader.js +70 -0
  140. package/dist/mcp/protocol.js +27 -0
  141. package/dist/mcp/resources.js +138 -0
  142. package/dist/mcp/server.js +177 -0
  143. package/dist/mcp/stdio.js +28 -0
  144. package/dist/mcp/tools.js +267 -0
  145. package/dist/reconciliation/code.js +62 -0
  146. package/dist/reconciliation/components.js +401 -0
  147. package/dist/reconciliation/conflicts.js +126 -0
  148. package/dist/reconciliation/facts.js +41 -0
  149. package/dist/reconciliation/index.js +7 -0
  150. package/dist/reconciliation/reconcile.js +134 -0
  151. package/dist/reconciliation/resolve.js +158 -0
  152. package/dist/reconciliation/review.js +81 -0
  153. package/dist/reconciliation/storybook.js +370 -0
  154. package/dist/reconciliation/tokens.js +179 -0
  155. package/dist/reconciliation/util.js +55 -0
  156. package/dist/semantic-engine/additive.js +51 -0
  157. package/dist/semantic-engine/compounds.js +91 -0
  158. package/dist/semantic-engine/documents.js +157 -0
  159. package/dist/semantic-engine/enrich.js +42 -0
  160. package/dist/semantic-engine/index.js +7 -0
  161. package/dist/semantic-engine/infer.js +38 -0
  162. package/dist/semantic-engine/tokens.js +120 -0
  163. package/dist/shared/canonical.js +65 -0
  164. package/dist/shared/diagnostic.js +78 -0
  165. package/dist/shared/glob.js +98 -0
  166. package/dist/shared/index.js +4 -0
  167. package/dist/shared/json.js +2 -0
  168. package/dist/validation/card.js +50 -0
  169. package/dist/validation/discovery/arrangements.js +162 -0
  170. package/dist/validation/discovery/discover.js +70 -0
  171. package/dist/validation/discovery/index.js +8 -0
  172. package/dist/validation/discovery/model.js +127 -0
  173. package/dist/validation/discovery/promote.js +24 -0
  174. package/dist/validation/discovery/reviews.js +63 -0
  175. package/dist/validation/discovery/shapes.js +47 -0
  176. package/dist/validation/discovery/similar-files.js +146 -0
  177. package/dist/validation/discovery/util.js +47 -0
  178. package/dist/validation/index.js +11 -0
  179. package/dist/validation/interaction-facts.js +341 -0
  180. package/dist/validation/interaction-workflows.js +633 -0
  181. package/dist/validation/literals.js +251 -0
  182. package/dist/validation/pattern-rules.js +608 -0
  183. package/dist/validation/policy.js +241 -0
  184. package/dist/validation/report.js +163 -0
  185. package/dist/validation/rules.js +269 -0
  186. package/dist/validation/scan.js +295 -0
  187. package/dist/validation/text.js +34 -0
  188. package/dist/validation/validate-code.js +513 -0
  189. package/dist/validation/validate-usage.js +196 -0
  190. package/package.json +38 -4
@@ -0,0 +1,446 @@
1
+ import { allowedValuesOf, classifyKind, collapse, declarationOf, externalBases, isProjectNode, lineOf, literalValue, relativeFileOf, resolveSymbol, unwrap } from "../compiler-core/index.js";
2
+ import ts from "typescript";
3
+ const CORE = "@angular/core";
4
+ const SIGNAL_INPUTS = new Set(["input", "model"]);
5
+ /** Local names bound to `@angular/core` exports in a file: `Component`, or `Cmp` for `import { Component as Cmp }`. */
6
+ export function coreBindings(sf) {
7
+ const bindings = new Map();
8
+ for (const statement of sf.statements) {
9
+ if (!ts.isImportDeclaration(statement) ||
10
+ !ts.isStringLiteral(statement.moduleSpecifier) ||
11
+ statement.moduleSpecifier.text !== CORE)
12
+ continue;
13
+ const named = statement.importClause?.namedBindings;
14
+ if (named && ts.isNamedImports(named))
15
+ for (const e of named.elements)
16
+ bindings.set(e.name.text, (e.propertyName ?? e.name).text);
17
+ if (named && ts.isNamespaceImport(named))
18
+ bindings.set(`${named.name.text}.`, "*");
19
+ }
20
+ return bindings;
21
+ }
22
+ /** Reads a class decorated with `@Component`, `@Directive` or `@NgModule`. Nothing is executed. */
23
+ export function readClass(analysis, node) {
24
+ const sf = node.getSourceFile();
25
+ const bindings = coreBindings(sf);
26
+ const decorator = classDecorator(node, bindings);
27
+ if (!decorator || !node.name)
28
+ return undefined;
29
+ const file = relativeFileOf(analysis, node);
30
+ if (!file)
31
+ return undefined;
32
+ const meta = decorator.call.arguments[0] && ts.isObjectLiteralExpression(unwrap(decorator.call.arguments[0]))
33
+ ? unwrap(decorator.call.arguments[0])
34
+ : undefined;
35
+ const result = {
36
+ node,
37
+ name: node.name.text,
38
+ file,
39
+ line: lineOf(node),
40
+ kind: decorator.name === "Component" ? "component" : decorator.name === "Directive" ? "directive" : "module",
41
+ imports: [],
42
+ declarations: [],
43
+ exports: [],
44
+ styles: [],
45
+ styleUrls: [],
46
+ host: {},
47
+ hostDirectives: [],
48
+ metadataInputs: [],
49
+ metadataOutputs: [],
50
+ inputs: [],
51
+ outputs: [],
52
+ hostListeners: [],
53
+ hostBindings: [],
54
+ queries: [],
55
+ inheritsFrom: [],
56
+ notes: []
57
+ };
58
+ if (meta)
59
+ readMetadata(analysis, meta, result);
60
+ readMembers(analysis, node, result, undefined, new Set());
61
+ return result;
62
+ }
63
+ function classDecorator(node, bindings) {
64
+ for (const d of ts.getDecorators(node) ?? []) {
65
+ if (!ts.isCallExpression(d.expression))
66
+ continue;
67
+ const canonical = coreName(d.expression.expression, bindings);
68
+ if (canonical === "Component" || canonical === "Directive" || canonical === "NgModule")
69
+ return { name: canonical, call: d.expression };
70
+ }
71
+ return undefined;
72
+ }
73
+ /** `Component`, or `core.Component` when `@angular/core` is a namespace import. */
74
+ function coreName(expression, bindings) {
75
+ if (ts.isIdentifier(expression))
76
+ return bindings.get(expression.text);
77
+ if (ts.isPropertyAccessExpression(expression) &&
78
+ ts.isIdentifier(expression.expression) &&
79
+ bindings.has(`${expression.expression.text}.`))
80
+ return expression.name.text;
81
+ return undefined;
82
+ }
83
+ function property(object, key) {
84
+ const p = object.properties.find((x) => ts.isPropertyAssignment(x) &&
85
+ (ts.isIdentifier(x.name) || ts.isStringLiteralLike(x.name)) &&
86
+ x.name.text === key);
87
+ return p && ts.isPropertyAssignment(p) ? p : undefined;
88
+ }
89
+ function stringOf(node) {
90
+ const n = node ? unwrap(node) : undefined;
91
+ return n && ts.isStringLiteralLike(n) ? n.text : undefined;
92
+ }
93
+ function readMetadata(analysis, meta, out) {
94
+ const selector = stringOf(property(meta, "selector")?.initializer);
95
+ if (selector !== undefined)
96
+ out.selector = selector;
97
+ else if (property(meta, "selector"))
98
+ out.notes.push("selector is not a string literal");
99
+ const standalone = property(meta, "standalone")?.initializer;
100
+ if (standalone) {
101
+ const v = unwrap(standalone);
102
+ if (v.kind === ts.SyntaxKind.TrueKeyword)
103
+ out.standalone = true;
104
+ else if (v.kind === ts.SyntaxKind.FalseKeyword)
105
+ out.standalone = false;
106
+ }
107
+ out.imports = nameRefs(analysis, property(meta, "imports")?.initializer);
108
+ out.declarations = nameRefs(analysis, property(meta, "declarations")?.initializer);
109
+ out.exports = nameRefs(analysis, property(meta, "exports")?.initializer);
110
+ out.hostDirectives = nameRefs(analysis, property(meta, "hostDirectives")?.initializer).map((r) => r.name);
111
+ const template = property(meta, "template")?.initializer;
112
+ const templateUrl = stringOf(property(meta, "templateUrl")?.initializer);
113
+ if (template) {
114
+ const t = unwrap(template);
115
+ if (ts.isStringLiteralLike(t))
116
+ out.template = { inline: t.text, line: lineOf(t) };
117
+ else
118
+ out.notes.push("template is not a static string");
119
+ }
120
+ else if (templateUrl)
121
+ out.template = { url: templateUrl };
122
+ const styles = property(meta, "styles")?.initializer;
123
+ if (styles) {
124
+ const s = unwrap(styles);
125
+ const items = ts.isArrayLiteralExpression(s) ? s.elements.map(unwrap) : [s];
126
+ for (const item of items) {
127
+ if (ts.isStringLiteralLike(item))
128
+ out.styles.push({ text: item.text, line: lineOf(item) });
129
+ else
130
+ out.notes.push("a styles entry is not a static string");
131
+ }
132
+ }
133
+ const styleUrl = stringOf(property(meta, "styleUrl")?.initializer);
134
+ if (styleUrl)
135
+ out.styleUrls.push(styleUrl);
136
+ const styleUrls = property(meta, "styleUrls")?.initializer;
137
+ if (styleUrls && ts.isArrayLiteralExpression(unwrap(styleUrls))) {
138
+ for (const e of unwrap(styleUrls).elements) {
139
+ const text = stringOf(e);
140
+ if (text)
141
+ out.styleUrls.push(text);
142
+ }
143
+ }
144
+ const host = property(meta, "host")?.initializer;
145
+ if (host && ts.isObjectLiteralExpression(unwrap(host))) {
146
+ for (const p of unwrap(host).properties) {
147
+ if (ts.isPropertyAssignment(p) && (ts.isStringLiteralLike(p.name) || ts.isIdentifier(p.name)))
148
+ out.host[p.name.text] = stringOf(p.initializer) ?? collapse(p.initializer.getText()).slice(0, 120);
149
+ }
150
+ }
151
+ const lastName = (expr) => expr ? collapse(expr.getText()).split(".").pop() : undefined;
152
+ const change = lastName(property(meta, "changeDetection")?.initializer);
153
+ if (change)
154
+ out.changeDetection = change;
155
+ const encapsulation = lastName(property(meta, "encapsulation")?.initializer);
156
+ if (encapsulation)
157
+ out.encapsulation = encapsulation;
158
+ const exportAs = stringOf(property(meta, "exportAs")?.initializer);
159
+ if (exportAs)
160
+ out.exportAs = exportAs;
161
+ for (const [key, target] of [
162
+ ["inputs", out.metadataInputs],
163
+ ["outputs", out.metadataOutputs]
164
+ ]) {
165
+ const arr = property(meta, key)?.initializer;
166
+ if (arr && ts.isArrayLiteralExpression(unwrap(arr))) {
167
+ for (const e of unwrap(arr).elements) {
168
+ const text = stringOf(e);
169
+ if (text)
170
+ target.push(text);
171
+ }
172
+ }
173
+ }
174
+ }
175
+ function nameRefs(analysis, expression) {
176
+ const array = expression ? unwrap(expression) : undefined;
177
+ if (!array || !ts.isArrayLiteralExpression(array))
178
+ return [];
179
+ const refs = [];
180
+ for (const element of array.elements) {
181
+ const e = ts.isSpreadElement(element) ? element.expression : element;
182
+ const name = ts.isObjectLiteralExpression(e) ? collapse(e.getText()).slice(0, 80) : collapse(e.getText());
183
+ const target = ts.isIdentifier(e) || ts.isPropertyAccessExpression(e)
184
+ ? declarationOf(resolveSymbol(analysis.checker, analysis.checker.getSymbolAtLocation(e)))
185
+ : undefined;
186
+ const file = target && isProjectNode(analysis, target) ? relativeFileOf(analysis, target) : undefined;
187
+ const localName = target && "name" in target && target.name && ts.isIdentifier(target.name)
188
+ ? target.name.text
189
+ : undefined;
190
+ refs.push({ name, ...(file ? { file } : {}), ...(file && localName ? { localName } : {}) });
191
+ }
192
+ return refs;
193
+ }
194
+ function readMembers(analysis, node, out, inheritedFrom, seen) {
195
+ if (seen.has(node))
196
+ return;
197
+ seen.add(node);
198
+ const bindings = coreBindings(node.getSourceFile());
199
+ for (const member of node.members) {
200
+ if (!ts.isPropertyDeclaration(member) &&
201
+ !ts.isSetAccessorDeclaration(member) &&
202
+ !ts.isMethodDeclaration(member) &&
203
+ !ts.isGetAccessorDeclaration(member))
204
+ continue;
205
+ if (!member.name || !(ts.isIdentifier(member.name) || ts.isStringLiteralLike(member.name)))
206
+ continue;
207
+ const property = member.name.text;
208
+ const symbol = analysis.checker.getSymbolAtLocation(member.name);
209
+ const doc = symbol ? ts.displayPartsToString(symbol.getDocumentationComment(analysis.checker)).trim() : "";
210
+ const depTag = symbol?.getJsDocTags(analysis.checker).find((t) => t.name === "deprecated");
211
+ const common = {
212
+ ...(doc ? { description: doc } : {}),
213
+ ...(depTag
214
+ ? {
215
+ deprecated: ts.displayPartsToString(depTag.text).trim()
216
+ ? { reason: ts.displayPartsToString(depTag.text).trim() }
217
+ : {}
218
+ }
219
+ : {}),
220
+ ...(inheritedFrom ? { inheritedFrom } : {})
221
+ };
222
+ for (const d of ts.getDecorators(member) ?? []) {
223
+ const call = ts.isCallExpression(d.expression) ? d.expression : undefined;
224
+ const callee = call ? call.expression : d.expression;
225
+ const name = coreName(callee, bindings);
226
+ if (name === "Input")
227
+ out.inputs.push(decoratorInput(analysis, member, property, call, common));
228
+ else if (name === "Output")
229
+ out.outputs.push(decoratorOutput(member, property, call, common));
230
+ else if (name === "HostBinding" && call)
231
+ out.hostBindings.push(`${stringOf(call.arguments[0]) ?? property}`);
232
+ else if (name === "HostListener" && call)
233
+ out.hostListeners.push(stringOf(call.arguments[0]) ?? property);
234
+ else if (name && /^(Content|View)Child(ren)?$/.test(name)) {
235
+ const sel = call?.arguments[0]
236
+ ? (stringOf(call.arguments[0]) ?? collapse(call.arguments[0].getText()))
237
+ : undefined;
238
+ out.queries.push({ kind: name, property, ...(sel ? { selector: sel } : {}) });
239
+ }
240
+ }
241
+ if (ts.isPropertyDeclaration(member) && member.initializer)
242
+ readSignalMember(analysis, member, property, bindings, out, common);
243
+ }
244
+ readBase(analysis, node, out, seen);
245
+ }
246
+ function readSignalMember(analysis, member, property, bindings, out, common) {
247
+ const init = unwrap(member.initializer);
248
+ if (!ts.isCallExpression(init))
249
+ return;
250
+ const callee = init.expression;
251
+ const base = ts.isPropertyAccessExpression(callee) && callee.name.text === "required" ? callee.expression : callee;
252
+ const required = ts.isPropertyAccessExpression(callee) && callee.name.text === "required";
253
+ const fn = coreName(base, bindings);
254
+ if (fn && SIGNAL_INPUTS.has(fn)) {
255
+ const optionsArg = required ? init.arguments[0] : init.arguments[1];
256
+ const options = optionsArg && ts.isObjectLiteralExpression(unwrap(optionsArg))
257
+ ? unwrap(optionsArg)
258
+ : undefined;
259
+ const alias = options ? stringOf(propertyOf(options, "alias")?.initializer) : undefined;
260
+ const transform = options ? propertyOf(options, "transform")?.initializer : undefined;
261
+ const firstGeneric = init.typeArguments?.[0];
262
+ const secondGeneric = init.typeArguments?.[1];
263
+ const defaultNode = required ? undefined : init.arguments[0];
264
+ const fallback = defaultNode ? literalValue(defaultNode) : undefined;
265
+ const inferred = !firstGeneric ? inferLiteralType(defaultNode) : undefined;
266
+ const typeInfo = firstGeneric
267
+ ? typeInfoOf(analysis, firstGeneric)
268
+ : { text: inferred ?? "unknown", kind: kindOfLiteral(inferred), allowedValues: undefined };
269
+ const input = {
270
+ name: alias ?? property,
271
+ property,
272
+ kind: fn === "model" ? "model" : "signal-input",
273
+ typeText: typeInfo.text,
274
+ typeKind: typeInfo.kind,
275
+ required,
276
+ ...(fallback !== undefined ? { default: fallback } : {}),
277
+ ...(defaultNode && fallback === undefined
278
+ ? { defaultExpression: collapse(defaultNode.getText()).slice(0, 200) }
279
+ : {}),
280
+ ...(typeInfo.allowedValues ? { allowedValues: typeInfo.allowedValues } : {}),
281
+ ...(alias ? { alias } : {}),
282
+ ...(transform ? { transform: collapse(transform.getText()) } : {}),
283
+ ...(secondGeneric ? { writeType: collapse(secondGeneric.getText()) } : {}),
284
+ ...(inferred ? { typeInferred: true } : {}),
285
+ ...common,
286
+ node: member
287
+ };
288
+ out.inputs.push(input);
289
+ if (fn === "model")
290
+ out.outputs.push({
291
+ name: `${alias ?? property}Change`,
292
+ property,
293
+ kind: "model",
294
+ payloadText: typeInfo.text,
295
+ ...(common.inheritedFrom ? { inheritedFrom: common.inheritedFrom } : {}),
296
+ node: member
297
+ });
298
+ return;
299
+ }
300
+ if (fn === "output") {
301
+ const optionsArg = init.arguments[0];
302
+ const options = optionsArg && ts.isObjectLiteralExpression(unwrap(optionsArg))
303
+ ? unwrap(optionsArg)
304
+ : undefined;
305
+ const alias = options ? stringOf(propertyOf(options, "alias")?.initializer) : undefined;
306
+ out.outputs.push({
307
+ name: alias ?? property,
308
+ property,
309
+ kind: "signal-output",
310
+ ...(init.typeArguments?.[0] ? { payloadText: collapse(init.typeArguments[0].getText()) } : {}),
311
+ ...(alias ? { alias } : {}),
312
+ ...(common.description ? { description: common.description } : {}),
313
+ ...(common.inheritedFrom ? { inheritedFrom: common.inheritedFrom } : {}),
314
+ node: member
315
+ });
316
+ return;
317
+ }
318
+ if (fn === "outputFromObservable")
319
+ out.notes.push(`outputFromObservable (${property}) is not analyzed`);
320
+ if (fn && /^(content|view)Child(ren)?$/.test(fn)) {
321
+ const sel = init.arguments[0]
322
+ ? (stringOf(init.arguments[0]) ?? collapse(init.arguments[0].getText()))
323
+ : undefined;
324
+ out.queries.push({ kind: fn, property, ...(sel ? { selector: sel } : {}) });
325
+ }
326
+ }
327
+ function decoratorInput(analysis, member, property, call, common) {
328
+ const arg = call?.arguments[0] ? unwrap(call.arguments[0]) : undefined;
329
+ const options = arg && ts.isObjectLiteralExpression(arg) ? arg : undefined;
330
+ const alias = arg && ts.isStringLiteralLike(arg)
331
+ ? arg.text
332
+ : options
333
+ ? stringOf(propertyOf(options, "alias")?.initializer)
334
+ : undefined;
335
+ const required = options
336
+ ? unwrap(propertyOf(options, "required")?.initializer ?? ts.factory.createFalse()).kind ===
337
+ ts.SyntaxKind.TrueKeyword
338
+ : false;
339
+ const transform = options ? propertyOf(options, "transform")?.initializer : undefined;
340
+ const typeNode = ts.isPropertyDeclaration(member)
341
+ ? member.type
342
+ : ts.isSetAccessorDeclaration(member)
343
+ ? member.parameters[0]?.type
344
+ : undefined;
345
+ const init = ts.isPropertyDeclaration(member) ? member.initializer : undefined;
346
+ const fallback = init ? literalValue(init) : undefined;
347
+ // Without a written type, a literal initializer fixes the type (string, number or boolean), as in TypeScript.
348
+ const literalType = typeNode ? undefined : inferLiteralType(init);
349
+ // Otherwise ask the checker: it can infer a type from the project's own declarations (a config class).
350
+ const checked = !typeNode && !literalType && ts.isPropertyDeclaration(member) ? checkedType(analysis, member) : undefined;
351
+ const inferred = literalType ?? checked?.text;
352
+ const info = typeNode
353
+ ? typeInfoOf(analysis, typeNode)
354
+ : checked
355
+ ? { text: checked.text, kind: checked.kind, allowedValues: undefined }
356
+ : { text: literalType ?? "unknown", kind: kindOfLiteral(literalType), allowedValues: undefined };
357
+ return {
358
+ name: alias ?? property,
359
+ property,
360
+ kind: "input",
361
+ typeText: info.text,
362
+ typeKind: info.kind,
363
+ required,
364
+ ...(fallback !== undefined ? { default: fallback } : {}),
365
+ ...(init && fallback === undefined ? { defaultExpression: collapse(init.getText()).slice(0, 200) } : {}),
366
+ ...(info.allowedValues ? { allowedValues: info.allowedValues } : {}),
367
+ ...(alias ? { alias } : {}),
368
+ ...(transform ? { transform: collapse(transform.getText()) } : {}),
369
+ ...(inferred ? { typeInferred: true } : {}),
370
+ ...common,
371
+ node: member
372
+ };
373
+ }
374
+ function decoratorOutput(member, property, call, common) {
375
+ const alias = call?.arguments[0] ? stringOf(call.arguments[0]) : undefined;
376
+ const init = ts.isPropertyDeclaration(member) && member.initializer ? unwrap(member.initializer) : undefined;
377
+ const payload = init && ts.isNewExpression(init) && init.typeArguments?.[0]
378
+ ? collapse(init.typeArguments[0].getText())
379
+ : undefined;
380
+ return {
381
+ name: alias ?? property,
382
+ property,
383
+ kind: "output",
384
+ ...(payload ? { payloadText: payload } : {}),
385
+ ...(alias ? { alias } : {}),
386
+ ...(common.description ? { description: common.description } : {}),
387
+ ...(common.inheritedFrom ? { inheritedFrom: common.inheritedFrom } : {}),
388
+ node: member
389
+ };
390
+ }
391
+ function readBase(analysis, node, out, seen) {
392
+ const base = node.heritageClauses?.find((h) => h.token === ts.SyntaxKind.ExtendsKeyword)?.types[0];
393
+ if (!base)
394
+ return;
395
+ const target = declarationOf(resolveSymbol(analysis.checker, analysis.checker.getSymbolAtLocation(base.expression)));
396
+ if (target && ts.isClassDeclaration(target) && isProjectNode(analysis, target)) {
397
+ readMembers(analysis, target, out, target.name?.text, seen);
398
+ if (ts.getDecorators(target)?.length)
399
+ readInheritedMetadata(analysis, target, out);
400
+ }
401
+ else
402
+ out.inheritsFrom.push(...externalBases(analysis, base));
403
+ }
404
+ /** Metadata `inputs`/`outputs` arrays of a decorated base class also apply to its subclasses. */
405
+ function readInheritedMetadata(analysis, base, out) {
406
+ const parent = readClass(analysis, base);
407
+ if (parent) {
408
+ out.metadataInputs.push(...parent.metadataInputs);
409
+ out.metadataOutputs.push(...parent.metadataOutputs);
410
+ }
411
+ }
412
+ function propertyOf(object, key) {
413
+ return property(object, key);
414
+ }
415
+ export function typeInfoOf(analysis, node) {
416
+ const { checker } = analysis;
417
+ const text = collapse(node.getText());
418
+ const type = checker.getTypeFromTypeNode(node);
419
+ const kind = classifyKind(checker, type, text);
420
+ return { text, kind, allowedValues: allowedValuesOf(checker, node, type, kind) };
421
+ }
422
+ /** The checker's inferred type of a property, unless it is unresolved (`any`/`unknown`). */
423
+ function checkedType(analysis, member) {
424
+ const { checker } = analysis;
425
+ const type = checker.getTypeAtLocation(member.name);
426
+ if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown))
427
+ return undefined;
428
+ const text = checker.typeToString(type);
429
+ return { text, kind: classifyKind(checker, type, text) };
430
+ }
431
+ function inferLiteralType(node) {
432
+ const n = node ? unwrap(node) : undefined;
433
+ if (!n)
434
+ return undefined;
435
+ if (ts.isStringLiteralLike(n))
436
+ return "string";
437
+ if (ts.isNumericLiteral(n))
438
+ return "number";
439
+ if (n.kind === ts.SyntaxKind.TrueKeyword || n.kind === ts.SyntaxKind.FalseKeyword)
440
+ return "boolean";
441
+ return undefined;
442
+ }
443
+ function kindOfLiteral(text) {
444
+ return text === "string" || text === "number" || text === "boolean" ? text : "unknown";
445
+ }
446
+ //# sourceMappingURL=classes.js.map