@invariant-ui/cli 0.0.0-stage → 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 (196) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +248 -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/ast.js +105 -0
  84. package/dist/compiler-react/behavior.js +75 -0
  85. package/dist/compiler-react/detect.js +558 -0
  86. package/dist/compiler-react/emit.js +188 -0
  87. package/dist/compiler-react/index.js +2 -0
  88. package/dist/compiler-react/program.js +58 -0
  89. package/dist/compiler-react/props.js +157 -0
  90. package/dist/compiler-react/styling.js +138 -0
  91. package/dist/compiler-react/usage.js +116 -0
  92. package/dist/compiler-react/variants.js +111 -0
  93. package/dist/compiler-storybook/adapter.js +253 -0
  94. package/dist/compiler-storybook/csf.js +521 -0
  95. package/dist/compiler-storybook/emit.js +202 -0
  96. package/dist/compiler-storybook/index-json.js +41 -0
  97. package/dist/compiler-storybook/index.js +5 -0
  98. package/dist/compiler-storybook/mdx.js +120 -0
  99. package/dist/compiler-storybook/static-eval.js +145 -0
  100. package/dist/compiler-tokens/adapter.js +158 -0
  101. package/dist/compiler-tokens/css.js +59 -0
  102. package/dist/compiler-tokens/index.js +5 -0
  103. package/dist/compiler-tokens/json-lines.js +106 -0
  104. package/dist/compiler-tokens/json-tokens.js +52 -0
  105. package/dist/compiler-vue/adapter.js +107 -0
  106. package/dist/compiler-vue/analyze.js +344 -0
  107. package/dist/compiler-vue/declared.js +343 -0
  108. package/dist/compiler-vue/emit.js +129 -0
  109. package/dist/compiler-vue/index.js +5 -0
  110. package/dist/compiler-vue/script.js +472 -0
  111. package/dist/compiler-vue/sfc.js +44 -0
  112. package/dist/compiler-vue/template.js +73 -0
  113. package/dist/contract/archetype-checks.js +153 -0
  114. package/dist/contract/components.js +102 -0
  115. package/dist/contract/conflicts.js +39 -0
  116. package/dist/contract/contract.js +46 -0
  117. package/dist/contract/evidence.js +84 -0
  118. package/dist/contract/fact-path.js +39 -0
  119. package/dist/contract/facts.js +62 -0
  120. package/dist/contract/index.js +16 -0
  121. package/dist/contract/integrity.js +21 -0
  122. package/dist/contract/json-schema.js +11 -0
  123. package/dist/contract/knowledge.js +95 -0
  124. package/dist/contract/pattern-checks.js +254 -0
  125. package/dist/contract/patterns.js +225 -0
  126. package/dist/contract/primitives.js +81 -0
  127. package/dist/contract/sources.js +30 -0
  128. package/dist/contract/tokens.js +41 -0
  129. package/dist/contract/validate.js +253 -0
  130. package/dist/contract-query/archetype.js +188 -0
  131. package/dist/contract-query/index.js +6 -0
  132. package/dist/contract-query/patterns.js +298 -0
  133. package/dist/contract-query/scan.js +164 -0
  134. package/dist/contract-query/search.js +132 -0
  135. package/dist/contract-query/system.js +148 -0
  136. package/dist/contract-query/validate-code.js +239 -0
  137. package/dist/contract-query/validate-usage.js +150 -0
  138. package/dist/contract-query/views.js +288 -0
  139. package/dist/governance/decisions.js +229 -0
  140. package/dist/governance/index.js +5 -0
  141. package/dist/governance/patterns-file.js +156 -0
  142. package/dist/governance/patterns.js +510 -0
  143. package/dist/governance/policies.js +148 -0
  144. package/dist/mcp/index.js +7 -0
  145. package/dist/mcp/loader.js +70 -0
  146. package/dist/mcp/protocol.js +27 -0
  147. package/dist/mcp/resources.js +138 -0
  148. package/dist/mcp/server.js +177 -0
  149. package/dist/mcp/stdio.js +28 -0
  150. package/dist/mcp/tools.js +267 -0
  151. package/dist/reconciliation/code.js +62 -0
  152. package/dist/reconciliation/components.js +401 -0
  153. package/dist/reconciliation/conflicts.js +126 -0
  154. package/dist/reconciliation/facts.js +41 -0
  155. package/dist/reconciliation/index.js +7 -0
  156. package/dist/reconciliation/reconcile.js +134 -0
  157. package/dist/reconciliation/resolve.js +158 -0
  158. package/dist/reconciliation/review.js +81 -0
  159. package/dist/reconciliation/storybook.js +370 -0
  160. package/dist/reconciliation/tokens.js +179 -0
  161. package/dist/reconciliation/util.js +55 -0
  162. package/dist/semantic-engine/additive.js +51 -0
  163. package/dist/semantic-engine/compounds.js +91 -0
  164. package/dist/semantic-engine/documents.js +157 -0
  165. package/dist/semantic-engine/enrich.js +42 -0
  166. package/dist/semantic-engine/index.js +7 -0
  167. package/dist/semantic-engine/infer.js +38 -0
  168. package/dist/semantic-engine/tokens.js +120 -0
  169. package/dist/shared/canonical.js +65 -0
  170. package/dist/shared/diagnostic.js +78 -0
  171. package/dist/shared/glob.js +98 -0
  172. package/dist/shared/index.js +4 -0
  173. package/dist/shared/json.js +2 -0
  174. package/dist/validation/card.js +50 -0
  175. package/dist/validation/discovery/arrangements.js +162 -0
  176. package/dist/validation/discovery/discover.js +70 -0
  177. package/dist/validation/discovery/index.js +8 -0
  178. package/dist/validation/discovery/model.js +127 -0
  179. package/dist/validation/discovery/promote.js +24 -0
  180. package/dist/validation/discovery/reviews.js +63 -0
  181. package/dist/validation/discovery/shapes.js +47 -0
  182. package/dist/validation/discovery/similar-files.js +146 -0
  183. package/dist/validation/discovery/util.js +47 -0
  184. package/dist/validation/index.js +11 -0
  185. package/dist/validation/interaction-facts.js +341 -0
  186. package/dist/validation/interaction-workflows.js +633 -0
  187. package/dist/validation/literals.js +251 -0
  188. package/dist/validation/pattern-rules.js +608 -0
  189. package/dist/validation/policy.js +241 -0
  190. package/dist/validation/report.js +163 -0
  191. package/dist/validation/rules.js +269 -0
  192. package/dist/validation/scan.js +295 -0
  193. package/dist/validation/text.js +34 -0
  194. package/dist/validation/validate-code.js +513 -0
  195. package/dist/validation/validate-usage.js +196 -0
  196. package/package.json +38 -4
@@ -0,0 +1,343 @@
1
+ import { declarationOf, describeMember, literalDomain, ownProperties, resolveSymbol, typeReferenceInfo } from "../compiler-core/index.js";
2
+ import ts from "typescript";
3
+ const RENDERABLE = /^(?:VNode|VNodeChild|VNodeArrayChildren|Component|DefineComponent)(?:<.*>)?$/;
4
+ const INSTANCE_TYPES = /^(?:CreateComponentPublicInstance(?:WithMixins)?|ComponentPublicInstance)$/;
5
+ const CONSTRUCTORS = {
6
+ StringConstructor: { text: "string", kind: "string" },
7
+ NumberConstructor: { text: "number", kind: "number" },
8
+ BooleanConstructor: { text: "boolean", kind: "boolean" },
9
+ ArrayConstructor: { text: "unknown[]", kind: "array" },
10
+ ObjectConstructor: { text: "object", kind: "object" },
11
+ FunctionConstructor: { text: "Function", kind: "function" },
12
+ DateConstructor: { text: "Date", kind: "object" }
13
+ };
14
+ /** Positions of `DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, Emits, …>`. */
15
+ const PROPS = 0;
16
+ const EMITS = 7;
17
+ /** Helpers that vue-tsc writes around the props type of a `<script setup lang="ts">` component. */
18
+ const PROPS_WRAPPERS = /^__VLS_(?:TypePropsToRuntimeProps|TypePropsToOption|WithDefaults|Prettify)$/;
19
+ const SLOTS_WRAPPER = /^__VLS_WithTemplateSlots$/;
20
+ /**
21
+ * A component a declaration file declares by type: `declare const _default: DefineComponent<Props, …, Emits, …>`
22
+ * (what vue-tsc and vite-plugin-dts write for a `.vue` file or a `defineComponent` call). There is no script
23
+ * to read, so props, events and slots come from the written type arguments. Default values are not part of
24
+ * a declaration file and are not reported.
25
+ */
26
+ export function analyzeDeclaredComponent(analysis, declaration) {
27
+ if (declaration.initializer || !declaration.type)
28
+ return undefined;
29
+ const found = findDefineComponent(analysis, declaration.type, 0);
30
+ if (!found)
31
+ return undefined;
32
+ const info = {
33
+ props: [],
34
+ emits: [],
35
+ slots: [],
36
+ exposed: [],
37
+ options: {},
38
+ inheritsFrom: [],
39
+ complete: true,
40
+ notes: [],
41
+ optionsApi: false,
42
+ imports: new Map()
43
+ };
44
+ const props = found.args[PROPS];
45
+ if (props)
46
+ readProps(analysis, props, info, 0);
47
+ const emits = found.args[EMITS];
48
+ if (emits)
49
+ readEmits(analysis, emits, info);
50
+ if (found.slots)
51
+ readSlots(analysis, found.slots, info);
52
+ return info;
53
+ }
54
+ function unparen(type) {
55
+ return ts.isParenthesizedTypeNode(type) ? unparen(type.type) : type;
56
+ }
57
+ function targetOf(analysis, name) {
58
+ return declarationOf(resolveSymbol(analysis.checker, analysis.checker.getSymbolAtLocation(name)));
59
+ }
60
+ function findDefineComponent(analysis, type, depth) {
61
+ if (depth > 5)
62
+ return undefined;
63
+ const t = unparen(type);
64
+ if (ts.isIntersectionTypeNode(t)) {
65
+ let found;
66
+ let slots;
67
+ for (const part of t.types) {
68
+ found ??= findDefineComponent(analysis, part, depth + 1);
69
+ slots ??= slotsOfConstructor(part);
70
+ }
71
+ const slot = found?.slots ?? slots;
72
+ return found ? { args: found.args, ...(slot ? { slots: slot } : {}) } : undefined;
73
+ }
74
+ if (ts.isTypeQueryNode(t)) {
75
+ const target = targetOf(analysis, t.exprName);
76
+ return target && ts.isVariableDeclaration(target) && target.type
77
+ ? findDefineComponent(analysis, target.type, depth + 1)
78
+ : undefined;
79
+ }
80
+ // `{ new (...args: any[]): CreateComponentPublicInstanceWithMixins<Props, …, Emits, …> }`: what Vuetify and other
81
+ // `defineComponent` libraries write, with the same type-argument positions as `DefineComponent`.
82
+ if (ts.isTypeLiteralNode(t)) {
83
+ for (const member of t.members) {
84
+ if (!ts.isConstructSignatureDeclaration(member) || !member.type)
85
+ continue;
86
+ const instance = typeReferenceInfo(member.type);
87
+ if (instance && INSTANCE_TYPES.test(instance.name))
88
+ return { args: instance.typeArguments };
89
+ }
90
+ return undefined;
91
+ }
92
+ const ref = typeReferenceInfo(t);
93
+ if (!ref)
94
+ return undefined;
95
+ if (ref.name === "DefineComponent")
96
+ return { args: ref.typeArguments };
97
+ if (SLOTS_WRAPPER.test(ref.name) && ref.typeArguments[0]) {
98
+ const inner = findDefineComponent(analysis, ref.typeArguments[0], depth + 1);
99
+ return inner ? { ...inner, ...(ref.typeArguments[1] ? { slots: ref.typeArguments[1] } : {}) } : undefined;
100
+ }
101
+ // `type ButtonComponent = DefineComponent<…>`
102
+ if (ts.isTypeReferenceNode(t)) {
103
+ const target = targetOf(analysis, t.typeName);
104
+ if (target && ts.isTypeAliasDeclaration(target) && !target.typeParameters)
105
+ return findDefineComponent(analysis, target.type, depth + 1);
106
+ // `type SFCWithInstall<T> = T & Plugin` (Element Plus): the component is the argument passed for `T`.
107
+ if (target && ts.isTypeAliasDeclaration(target) && target.typeParameters && t.typeArguments) {
108
+ const body = unparen(target.type);
109
+ const members = ts.isIntersectionTypeNode(body) ? body.types : [body];
110
+ for (const member of members) {
111
+ const param = ts.isTypeReferenceNode(member)
112
+ ? target.typeParameters.findIndex((p) => p.name.text === member.typeName.getText())
113
+ : -1;
114
+ const arg = param >= 0 ? t.typeArguments[param] : undefined;
115
+ const found = arg ? findDefineComponent(analysis, arg, depth + 1) : undefined;
116
+ if (found)
117
+ return found;
118
+ }
119
+ }
120
+ }
121
+ return undefined;
122
+ }
123
+ /** `{ new (): { $slots: S } }`, the way a declaration file attaches slot types to a component. */
124
+ function slotsOfConstructor(type) {
125
+ const t = unparen(type);
126
+ if (!ts.isTypeLiteralNode(t))
127
+ return undefined;
128
+ for (const member of t.members) {
129
+ if (!ts.isConstructSignatureDeclaration(member) || !member.type || !ts.isTypeLiteralNode(member.type))
130
+ continue;
131
+ for (const inner of member.type.members)
132
+ if (ts.isPropertySignature(inner) && inner.name.getText() === "$slots")
133
+ return inner.type;
134
+ }
135
+ return undefined;
136
+ }
137
+ function readProps(analysis, type, info, depth) {
138
+ const t = unparen(type);
139
+ const ref = typeReferenceInfo(t);
140
+ if (depth < 4 && ref && PROPS_WRAPPERS.test(ref.name) && ref.typeArguments[0]) {
141
+ readProps(analysis, ref.typeArguments[0], info, depth + 1);
142
+ return;
143
+ }
144
+ // `ExtractPropTypes<{ size: { type: PropType<"a" | "b">; default: string } }>`: the runtime options, as a type.
145
+ if (ref?.name === "ExtractPropTypes" && ref.typeArguments[0]) {
146
+ readRuntimeProps(analysis, ref.typeArguments[0], info, 0);
147
+ return;
148
+ }
149
+ // `("size" | "tone")[]`: props declared as an array of names.
150
+ if (ts.isArrayTypeNode(t) || ts.isTupleTypeNode(t)) {
151
+ const names = ts.isArrayTypeNode(t)
152
+ ? literalDomain(analysis.checker, t.elementType)
153
+ : t.elements.flatMap((e) => literalDomain(analysis.checker, e) ?? []);
154
+ for (const name of names ?? [])
155
+ info.props.push({
156
+ name: String(name),
157
+ typeText: "unknown",
158
+ kind: "unknown",
159
+ required: false,
160
+ source: "array",
161
+ node: t
162
+ });
163
+ if (!names)
164
+ info.complete = false;
165
+ return;
166
+ }
167
+ const type_ = analysis.checker.getTypeFromTypeNode(t);
168
+ if (type_.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) {
169
+ info.complete = false;
170
+ info.notes.push("the props type did not resolve");
171
+ return;
172
+ }
173
+ for (const { symbol, declaration } of ownProperties(analysis, type_)) {
174
+ const member = describeMember(analysis, symbol, declaration, { renderable: RENDERABLE });
175
+ info.props.push({
176
+ name: member.name,
177
+ typeText: member.typeText,
178
+ kind: member.kind,
179
+ required: member.required,
180
+ ...(member.allowedValues ? { allowedValues: member.allowedValues } : {}),
181
+ ...(member.description ? { description: member.description } : {}),
182
+ ...(member.deprecated ? { deprecated: member.deprecated } : {}),
183
+ source: "type",
184
+ node: declaration
185
+ });
186
+ }
187
+ }
188
+ function readRuntimeProps(analysis, type, info, depth) {
189
+ let t = unparen(type);
190
+ // `typeof props`: follow to the declared type of the constant.
191
+ if (ts.isTypeQueryNode(t) && depth < 3) {
192
+ const target = targetOf(analysis, t.exprName);
193
+ if (target && ts.isVariableDeclaration(target) && target.type) {
194
+ readRuntimeProps(analysis, target.type, info, depth + 1);
195
+ return;
196
+ }
197
+ }
198
+ if (!ts.isTypeLiteralNode(t)) {
199
+ info.complete = false;
200
+ info.notes.push("the runtime props type is not an object type");
201
+ return;
202
+ }
203
+ for (const member of t.members) {
204
+ if (!ts.isPropertySignature(member) || !member.name || !member.type)
205
+ continue;
206
+ if (!(ts.isIdentifier(member.name) || ts.isStringLiteralLike(member.name)))
207
+ continue;
208
+ t = unparen(member.type);
209
+ const spec = ts.isTypeLiteralNode(t) ? t : undefined;
210
+ const field = (key) => spec?.members.find((m) => ts.isPropertySignature(m) && m.name.getText() === key);
211
+ // A bare constructor (`name: StringConstructor`) or a list of them is the shorthand for `{ type }`.
212
+ const typeNode = spec ? field("type")?.type : t;
213
+ const required = field("required")?.type?.getText() === "true";
214
+ const described = typeNode ? describeRuntimeType(analysis, typeNode) : undefined;
215
+ info.props.push({
216
+ name: member.name.text,
217
+ typeText: described?.text ?? "unknown",
218
+ kind: described?.kind ?? "unknown",
219
+ required,
220
+ ...(described?.allowedValues ? { allowedValues: described.allowedValues } : {}),
221
+ source: "runtime",
222
+ node: member
223
+ });
224
+ }
225
+ }
226
+ function describeRuntimeType(analysis, node) {
227
+ const t = unparen(node);
228
+ const ref = typeReferenceInfo(t);
229
+ if (ref?.name === "PropType" && ref.typeArguments[0]) {
230
+ const inner = ref.typeArguments[0];
231
+ const checkerType = analysis.checker.getTypeFromTypeNode(inner);
232
+ const text = inner.getText().replace(/\s+/g, " ");
233
+ const kind = kindOf(analysis, checkerType);
234
+ const allowedValues = kind === "enum" ? literalDomain(analysis.checker, inner) : undefined;
235
+ return { text, kind, ...(allowedValues ? { allowedValues } : {}) };
236
+ }
237
+ if (ref && CONSTRUCTORS[ref.name])
238
+ return CONSTRUCTORS[ref.name];
239
+ if (ts.isUnionTypeNode(t)) {
240
+ const parts = t.types.map((p) => describeRuntimeType(analysis, p));
241
+ if (parts.every((p) => p))
242
+ return { text: parts.map((p) => p?.text).join(" | "), kind: "union" };
243
+ }
244
+ return undefined;
245
+ }
246
+ function kindOf(analysis, type) {
247
+ const text = analysis.checker.typeToString(type);
248
+ if (type.flags & ts.TypeFlags.Any)
249
+ return "unknown";
250
+ if (type.getCallSignatures().length > 0)
251
+ return "function";
252
+ if (type.isUnion()) {
253
+ return type.types.every((x) => x.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral))
254
+ ? "enum"
255
+ : "union";
256
+ }
257
+ if (type.flags & ts.TypeFlags.StringLike)
258
+ return "string";
259
+ if (type.flags & ts.TypeFlags.NumberLike)
260
+ return "number";
261
+ if (type.flags & ts.TypeFlags.BooleanLike)
262
+ return "boolean";
263
+ if (analysis.checker.isArrayType(type))
264
+ return "array";
265
+ return text === "unknown" ? "unknown" : "object";
266
+ }
267
+ function readEmits(analysis, type, info) {
268
+ const t = unparen(type);
269
+ // `{}` and `string[]`-like placeholders: Vue's own default for a component with no emits.
270
+ if (ts.isTypeLiteralNode(t) && t.members.length === 0)
271
+ return;
272
+ if (ts.isArrayTypeNode(t) || ts.isTupleTypeNode(t)) {
273
+ const names = ts.isArrayTypeNode(t)
274
+ ? literalDomain(analysis.checker, t.elementType)
275
+ : t.elements.flatMap((e) => literalDomain(analysis.checker, e) ?? []);
276
+ for (const name of names ?? [])
277
+ info.emits.push({ name: String(name), source: "array", node: t });
278
+ return;
279
+ }
280
+ const checker = analysis.checker;
281
+ const resolved = checker.getTypeFromTypeNode(t);
282
+ // Call-signature form: `(e: "change", id: number): void`
283
+ for (const signature of resolved.getCallSignatures()) {
284
+ const [first, ...rest] = signature.getParameters();
285
+ const eventType = first ? checker.getTypeOfSymbolAtLocation(first, t) : undefined;
286
+ if (!eventType?.isStringLiteral())
287
+ continue;
288
+ const payload = rest
289
+ .map((p) => `${p.name}: ${checker.typeToString(checker.getTypeOfSymbolAtLocation(p, t))}`)
290
+ .join(", ");
291
+ info.emits.push({
292
+ name: eventType.value,
293
+ ...(payload ? { payloadText: payload } : {}),
294
+ source: "type",
295
+ node: t
296
+ });
297
+ }
298
+ // Object form: `change: (id: number) => void` or the named-tuple form `change: [id: number]`.
299
+ for (const property of resolved.getProperties()) {
300
+ const propType = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(property, t));
301
+ const node = property.valueDeclaration ?? t;
302
+ const signature = propType.getCallSignatures()[0];
303
+ if (signature) {
304
+ const payload = signature
305
+ .getParameters()
306
+ .map((p) => `${p.name}: ${checker.typeToString(checker.getTypeOfSymbolAtLocation(p, t))}`)
307
+ .join(", ");
308
+ info.emits.push({
309
+ name: property.name,
310
+ ...(payload ? { payloadText: payload } : {}),
311
+ source: "type",
312
+ node
313
+ });
314
+ }
315
+ else if (checker.isTupleType(propType) || checker.isArrayType(propType)) {
316
+ const text = checker.typeToString(propType);
317
+ info.emits.push({
318
+ name: property.name,
319
+ ...(text !== "[]" ? { payloadText: text } : {}),
320
+ source: "type",
321
+ node
322
+ });
323
+ }
324
+ else
325
+ info.emits.push({ name: property.name, source: "type", node });
326
+ }
327
+ }
328
+ function readSlots(analysis, type, info) {
329
+ const checker = analysis.checker;
330
+ for (const property of checker.getTypeFromTypeNode(type).getProperties()) {
331
+ const propType = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(property, type));
332
+ const parameter = propType.getCallSignatures()[0]?.getParameters()[0];
333
+ const propsText = parameter
334
+ ? checker.typeToString(checker.getTypeOfSymbolAtLocation(parameter, type))
335
+ : undefined;
336
+ info.slots.push({
337
+ name: property.name,
338
+ ...(propsText && propsText !== "{}" ? { propsText } : {}),
339
+ node: property.valueDeclaration ?? type
340
+ });
341
+ }
342
+ }
343
+ //# sourceMappingURL=declared.js.map
@@ -0,0 +1,129 @@
1
+ import { ComponentFacts, excerpt } from "../compiler-core/index.js";
2
+ export const CAPABILITIES = [
3
+ "name",
4
+ "implementations.*",
5
+ "props.*",
6
+ "events.*",
7
+ "slots.*",
8
+ "variants.*",
9
+ "accessibility.*",
10
+ "styling.*",
11
+ "composition.*"
12
+ ];
13
+ /** Writes one component with the neutral fact paths shared with the other framework adapters. */
14
+ export function emitComponent(builder, c, pkg) {
15
+ const ref = builder.entity(c.ref, "component", c.localName);
16
+ const facts = new ComponentFacts(builder, ref, "vue");
17
+ const at = (node, method = "compiler-api") => {
18
+ const location = c.locate(node);
19
+ return builder.evidence({
20
+ sourceRef: `${location.file}#${c.localName}`,
21
+ location: { type: "file", path: location.file, line: location.line },
22
+ method,
23
+ original: excerpt(node)
24
+ });
25
+ };
26
+ const block = (line, method = "ast", original) => builder.evidence({
27
+ sourceRef: `${c.file}#${c.localName}`,
28
+ location: { type: "file", path: c.file, line },
29
+ method,
30
+ ...(original ? { original } : {})
31
+ });
32
+ const decl = block(c.line);
33
+ facts.put("name", c.localName, decl);
34
+ facts.link(c.file, c.localName, decl);
35
+ if (pkg.name)
36
+ facts.put("implementations.vue.packageName", pkg.name, decl);
37
+ const primary = [...c.exports].sort((a, b) => (a.subpath === "." ? 0 : 1) - (b.subpath === "." ? 0 : 1) ||
38
+ (a.name === "default" ? 1 : 0) - (b.name === "default" ? 1 : 0) ||
39
+ (a.name < b.name ? -1 : 1))[0];
40
+ if (primary) {
41
+ facts.put("implementations.vue.exportName", primary.name, decl);
42
+ if (pkg.name)
43
+ facts.put("implementations.vue.importPath", primary.subpath === "." ? pkg.name : `${pkg.name}/${primary.subpath.replace(/^\.\//, "")}`, decl);
44
+ }
45
+ facts.ext("kind", c.kind, decl);
46
+ facts.ext("exports", c.exports, decl);
47
+ facts.ext("propsComplete", c.propsComplete, decl);
48
+ if (c.sfc) {
49
+ const d = c.sfc.descriptor;
50
+ facts.ext("scriptSetup", d.scriptSetup !== null, decl);
51
+ facts.ext("optionsApi", c.script.optionsApi, decl);
52
+ const lang = d.scriptSetup?.lang ?? d.script?.lang;
53
+ if (lang)
54
+ facts.ext("scriptLang", lang, decl);
55
+ if (d.template?.lang)
56
+ facts.ext("templateLang", d.template.lang, decl);
57
+ }
58
+ if (c.generic)
59
+ facts.ext("generic", c.generic, decl);
60
+ if (c.script.inheritsFrom.length > 0)
61
+ facts.ext("inheritedPropsFrom", [...new Set(c.script.inheritsFrom)].sort(), decl);
62
+ if (c.script.exposed.length > 0)
63
+ facts.ext("exposed", c.script.exposed, decl);
64
+ if (c.script.options.name)
65
+ facts.ext("options.name", c.script.options.name, decl);
66
+ if (c.script.options.inheritAttrs !== undefined)
67
+ facts.ext("options.inheritAttrs", c.script.options.inheritAttrs, decl);
68
+ const dynamicSlots = (c.template?.slots ?? []).filter((s) => s.dynamic).length;
69
+ if (dynamicSlots > 0)
70
+ facts.ext("dynamicSlots", dynamicSlots, decl);
71
+ for (const p of [...c.script.props].sort((a, b) => (a.name < b.name ? -1 : 1))) {
72
+ const evidence = at(p.node, p.source === "type" ? "compiler-api" : "ast");
73
+ facts.prop({
74
+ name: p.name,
75
+ typeText: p.typeText,
76
+ kind: p.kind,
77
+ required: p.required,
78
+ ...(p.default !== undefined ? { default: p.default } : {}),
79
+ ...(p.defaultExpression !== undefined ? { defaultExpression: p.defaultExpression } : {}),
80
+ ...(p.allowedValues ? { allowedValues: p.allowedValues } : {}),
81
+ ...(p.description ? { description: p.description } : {}),
82
+ ...(p.deprecated ? { deprecated: p.deprecated } : {}),
83
+ extensions: { kind: p.source === "model" ? "model" : "prop", source: p.source }
84
+ }, evidence);
85
+ }
86
+ for (const e of [...c.script.emits].sort((a, b) => (a.name < b.name ? -1 : 1))) {
87
+ facts.event({
88
+ name: e.name,
89
+ ...(e.payloadText ? { payloadText: e.payloadText } : {}),
90
+ extensions: { kind: e.source === "model" ? "model" : "emit", source: e.source, emit: e.name }
91
+ }, at(e.node, e.source === "type" ? "compiler-api" : "ast"));
92
+ }
93
+ for (const s of c.slots) {
94
+ const evidence = s.node ? at(s.node) : block(s.line ?? c.templateLine ?? c.line);
95
+ facts.slot({
96
+ name: s.name,
97
+ extensions: {
98
+ source: s.sources.length === 2 ? "both" : s.sources[0],
99
+ ...(s.propsText ? { props: s.propsText } : {}),
100
+ ...(s.templateProps.length > 0 ? { propNames: s.templateProps } : {})
101
+ }
102
+ }, evidence);
103
+ }
104
+ for (const v of c.variants) {
105
+ const prop = c.script.props.find((p) => p.name === v.name);
106
+ facts.variant({ ...v, extensions: { source: "prop-union" } }, prop ? at(prop.node) : decl);
107
+ }
108
+ const a11y = c.template?.accessibility;
109
+ if (a11y && (a11y.roles.length > 0 || a11y.attributes.length > 0)) {
110
+ const evidence = block(c.templateLine ?? c.line);
111
+ facts.accessibility({ ...(a11y.roles.length === 1 ? { role: a11y.roles[0] } : {}), attributes: a11y.attributes }, evidence);
112
+ }
113
+ const s = c.styling;
114
+ if (s.blocks > 0) {
115
+ const evidence = block(c.line);
116
+ if (s.variables.length > 0) {
117
+ const refs = s.variables.map((v) => block(v.line, "structured-parse", `var(${v.name})`));
118
+ facts.put("styling.cssVariables", s.variables.map((v) => v.name), refs);
119
+ }
120
+ facts.put("styling.scoped", s.scoped, evidence);
121
+ if (s.module)
122
+ facts.put("styling.cssModules", [c.file], evidence);
123
+ if (s.preprocessors.length > 0)
124
+ facts.put("styling.preprocessors", s.preprocessors, evidence);
125
+ }
126
+ if (c.renders.length > 0)
127
+ facts.put("composition.renders", c.renders, block(c.templateLine ?? c.line));
128
+ }
129
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1,5 @@
1
+ export { ADAPTER_ID, ADAPTER_VERSION, vueAdapter } from "./adapter.js";
2
+ export { analyzeScript } from "./script.js";
3
+ export { parseSfc, sfcLocalName } from "./sfc.js";
4
+ export { analyzeTemplate } from "./template.js";
5
+ //# sourceMappingURL=index.js.map