@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.
- package/LICENSE +105 -0
- package/README.md +248 -2
- package/dist/agent-kit/apply.js +232 -0
- package/dist/agent-kit/guidance.js +236 -0
- package/dist/agent-kit/index.js +5 -0
- package/dist/agent-kit/integrations.js +121 -0
- package/dist/agent-kit/plugin.js +115 -0
- package/dist/artifact-generator/index.js +75 -0
- package/dist/browser-verify/driver.js +2 -0
- package/dist/browser-verify/index.js +4 -0
- package/dist/browser-verify/playwright.js +82 -0
- package/dist/browser-verify/runner.js +175 -0
- package/dist/browser-verify/spec.js +103 -0
- package/dist/cli/args.js +77 -0
- package/dist/cli/baseline.js +64 -0
- package/dist/cli/cli.js +121 -0
- package/dist/cli/commands-browser.js +104 -0
- package/dist/cli/commands-discover.js +312 -0
- package/dist/cli/commands-enforcement.js +35 -0
- package/dist/cli/commands-governance.js +179 -0
- package/dist/cli/commands-hook.js +269 -0
- package/dist/cli/commands-patterns.js +324 -0
- package/dist/cli/commands-setup.js +485 -0
- package/dist/cli/commands-validate.js +157 -0
- package/dist/cli/commands.js +517 -0
- package/dist/cli/config.js +197 -0
- package/dist/cli/diff.js +66 -0
- package/dist/cli/enforcement-log.js +83 -0
- package/dist/cli/enforcement-report.js +96 -0
- package/dist/cli/errors.js +10 -0
- package/dist/cli/format.js +22 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/io.js +2 -0
- package/dist/cli/main.js +31 -0
- package/dist/cli/pipeline.js +262 -0
- package/dist/cli/publish.js +77 -0
- package/dist/cli/report.js +127 -0
- package/dist/cli/starter-rules.js +57 -0
- package/dist/cli/store.js +60 -0
- package/dist/cli/version.js +5 -0
- package/dist/cli/watch.js +68 -0
- package/dist/cli/workflow.js +52 -0
- package/dist/compiler-angular/adapter.js +115 -0
- package/dist/compiler-angular/analyze.js +222 -0
- package/dist/compiler-angular/classes.js +446 -0
- package/dist/compiler-angular/declared.js +285 -0
- package/dist/compiler-angular/emit.js +183 -0
- package/dist/compiler-angular/index.js +4 -0
- package/dist/compiler-angular/template.js +142 -0
- package/dist/compiler-core/adapter.js +2 -0
- package/dist/compiler-core/adapters/inventory.js +312 -0
- package/dist/compiler-core/compile.js +148 -0
- package/dist/compiler-core/component-facts.js +123 -0
- package/dist/compiler-core/discovery/docs.js +66 -0
- package/dist/compiler-core/discovery/entries.js +270 -0
- package/dist/compiler-core/discovery/exports.js +207 -0
- package/dist/compiler-core/discovery/graph.js +59 -0
- package/dist/compiler-core/discovery/index.js +103 -0
- package/dist/compiler-core/discovery/packages.js +148 -0
- package/dist/compiler-core/discovery/schema.js +144 -0
- package/dist/compiler-core/discovery/storybook.js +232 -0
- package/dist/compiler-core/discovery/support.js +82 -0
- package/dist/compiler-core/discovery/tokens.js +186 -0
- package/dist/compiler-core/discovery/tooling.js +146 -0
- package/dist/compiler-core/fs.js +89 -0
- package/dist/compiler-core/glob.js +3 -0
- package/dist/compiler-core/index.js +16 -0
- package/dist/compiler-core/ir-builder.js +68 -0
- package/dist/compiler-core/json-schema.js +11 -0
- package/dist/compiler-core/testing/index.js +81 -0
- package/dist/compiler-core/ts/ast.js +166 -0
- package/dist/compiler-core/ts/members.js +163 -0
- package/dist/compiler-core/ts/program.js +81 -0
- package/dist/compiler-core/ts/static-eval.js +145 -0
- package/dist/compiler-core/ts/tsconfig-paths.js +60 -0
- package/dist/compiler-core/walk.js +46 -0
- package/dist/compiler-ir/index.js +4 -0
- package/dist/compiler-ir/ir.js +67 -0
- package/dist/compiler-ir/json-schema.js +6 -0
- package/dist/compiler-ir/validate.js +116 -0
- package/dist/compiler-react/adapter.js +147 -0
- package/dist/compiler-react/analyze.js +199 -0
- package/dist/compiler-react/ast.js +105 -0
- package/dist/compiler-react/behavior.js +75 -0
- package/dist/compiler-react/detect.js +558 -0
- package/dist/compiler-react/emit.js +188 -0
- package/dist/compiler-react/index.js +2 -0
- package/dist/compiler-react/program.js +58 -0
- package/dist/compiler-react/props.js +157 -0
- package/dist/compiler-react/styling.js +138 -0
- package/dist/compiler-react/usage.js +116 -0
- package/dist/compiler-react/variants.js +111 -0
- package/dist/compiler-storybook/adapter.js +253 -0
- package/dist/compiler-storybook/csf.js +521 -0
- package/dist/compiler-storybook/emit.js +202 -0
- package/dist/compiler-storybook/index-json.js +41 -0
- package/dist/compiler-storybook/index.js +5 -0
- package/dist/compiler-storybook/mdx.js +120 -0
- package/dist/compiler-storybook/static-eval.js +145 -0
- package/dist/compiler-tokens/adapter.js +158 -0
- package/dist/compiler-tokens/css.js +59 -0
- package/dist/compiler-tokens/index.js +5 -0
- package/dist/compiler-tokens/json-lines.js +106 -0
- package/dist/compiler-tokens/json-tokens.js +52 -0
- package/dist/compiler-vue/adapter.js +107 -0
- package/dist/compiler-vue/analyze.js +344 -0
- package/dist/compiler-vue/declared.js +343 -0
- package/dist/compiler-vue/emit.js +129 -0
- package/dist/compiler-vue/index.js +5 -0
- package/dist/compiler-vue/script.js +472 -0
- package/dist/compiler-vue/sfc.js +44 -0
- package/dist/compiler-vue/template.js +73 -0
- package/dist/contract/archetype-checks.js +153 -0
- package/dist/contract/components.js +102 -0
- package/dist/contract/conflicts.js +39 -0
- package/dist/contract/contract.js +46 -0
- package/dist/contract/evidence.js +84 -0
- package/dist/contract/fact-path.js +39 -0
- package/dist/contract/facts.js +62 -0
- package/dist/contract/index.js +16 -0
- package/dist/contract/integrity.js +21 -0
- package/dist/contract/json-schema.js +11 -0
- package/dist/contract/knowledge.js +95 -0
- package/dist/contract/pattern-checks.js +254 -0
- package/dist/contract/patterns.js +225 -0
- package/dist/contract/primitives.js +81 -0
- package/dist/contract/sources.js +30 -0
- package/dist/contract/tokens.js +41 -0
- package/dist/contract/validate.js +253 -0
- package/dist/contract-query/archetype.js +188 -0
- package/dist/contract-query/index.js +6 -0
- package/dist/contract-query/patterns.js +298 -0
- package/dist/contract-query/scan.js +164 -0
- package/dist/contract-query/search.js +132 -0
- package/dist/contract-query/system.js +148 -0
- package/dist/contract-query/validate-code.js +239 -0
- package/dist/contract-query/validate-usage.js +150 -0
- package/dist/contract-query/views.js +288 -0
- package/dist/governance/decisions.js +229 -0
- package/dist/governance/index.js +5 -0
- package/dist/governance/patterns-file.js +156 -0
- package/dist/governance/patterns.js +510 -0
- package/dist/governance/policies.js +148 -0
- package/dist/mcp/index.js +7 -0
- package/dist/mcp/loader.js +70 -0
- package/dist/mcp/protocol.js +27 -0
- package/dist/mcp/resources.js +138 -0
- package/dist/mcp/server.js +177 -0
- package/dist/mcp/stdio.js +28 -0
- package/dist/mcp/tools.js +267 -0
- package/dist/reconciliation/code.js +62 -0
- package/dist/reconciliation/components.js +401 -0
- package/dist/reconciliation/conflicts.js +126 -0
- package/dist/reconciliation/facts.js +41 -0
- package/dist/reconciliation/index.js +7 -0
- package/dist/reconciliation/reconcile.js +134 -0
- package/dist/reconciliation/resolve.js +158 -0
- package/dist/reconciliation/review.js +81 -0
- package/dist/reconciliation/storybook.js +370 -0
- package/dist/reconciliation/tokens.js +179 -0
- package/dist/reconciliation/util.js +55 -0
- package/dist/semantic-engine/additive.js +51 -0
- package/dist/semantic-engine/compounds.js +91 -0
- package/dist/semantic-engine/documents.js +157 -0
- package/dist/semantic-engine/enrich.js +42 -0
- package/dist/semantic-engine/index.js +7 -0
- package/dist/semantic-engine/infer.js +38 -0
- package/dist/semantic-engine/tokens.js +120 -0
- package/dist/shared/canonical.js +65 -0
- package/dist/shared/diagnostic.js +78 -0
- package/dist/shared/glob.js +98 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/json.js +2 -0
- package/dist/validation/card.js +50 -0
- package/dist/validation/discovery/arrangements.js +162 -0
- package/dist/validation/discovery/discover.js +70 -0
- package/dist/validation/discovery/index.js +8 -0
- package/dist/validation/discovery/model.js +127 -0
- package/dist/validation/discovery/promote.js +24 -0
- package/dist/validation/discovery/reviews.js +63 -0
- package/dist/validation/discovery/shapes.js +47 -0
- package/dist/validation/discovery/similar-files.js +146 -0
- package/dist/validation/discovery/util.js +47 -0
- package/dist/validation/index.js +11 -0
- package/dist/validation/interaction-facts.js +341 -0
- package/dist/validation/interaction-workflows.js +633 -0
- package/dist/validation/literals.js +251 -0
- package/dist/validation/pattern-rules.js +608 -0
- package/dist/validation/policy.js +241 -0
- package/dist/validation/report.js +163 -0
- package/dist/validation/rules.js +269 -0
- package/dist/validation/scan.js +295 -0
- package/dist/validation/text.js +34 -0
- package/dist/validation/validate-code.js +513 -0
- package/dist/validation/validate-usage.js +196 -0
- package/package.json +38 -4
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { normalize } from "../contract-query/index.js";
|
|
2
|
+
import { nearest, quoteList } from "./text.js";
|
|
3
|
+
export const isDynamic = (v) => typeof v === "object" &&
|
|
4
|
+
v !== null &&
|
|
5
|
+
!Array.isArray(v) &&
|
|
6
|
+
Object.keys(v).length === 1 &&
|
|
7
|
+
typeof v.expression === "string";
|
|
8
|
+
/**
|
|
9
|
+
* Attributes frameworks pass through to the rendered element. A component rarely declares them, and whether it
|
|
10
|
+
* forwards them is not in the contract, so an undeclared one is not evidence of a mistake.
|
|
11
|
+
*/
|
|
12
|
+
const HTML_ATTRIBUTES = new Set("accept alt autocomplete autofocus checked cols colspan disabled download draggable for form height href hreflang htmlfor inputmode lang list loading max maxlength method min minlength multiple name novalidate pattern placeholder readonly rel required rows rowspan selected size spellcheck src srcset step target type value width wrap dir content crossorigin enterkeyhint open".split(" "));
|
|
13
|
+
const PASSTHROUGH = /^(data-|aria-)|^(key|ref|class|className|style|id|slot|role|tabindex|title|hidden)$/i;
|
|
14
|
+
const isPassthrough = (name) => PASSTHROUGH.test(name) || HTML_ATTRIBUTES.has(name.toLowerCase());
|
|
15
|
+
function sameValue(allowed, v) {
|
|
16
|
+
if (allowed === v)
|
|
17
|
+
return true;
|
|
18
|
+
return typeof v === "string" && typeof allowed !== "string" && String(allowed) === v;
|
|
19
|
+
}
|
|
20
|
+
export function validateUsage(ds, input) {
|
|
21
|
+
const findings = [];
|
|
22
|
+
const found = ds.findComponent(input.component);
|
|
23
|
+
if (!found.match) {
|
|
24
|
+
const names = found.candidates.map((c) => c.name);
|
|
25
|
+
const close = names.length > 0
|
|
26
|
+
? names
|
|
27
|
+
: nearest(input.component, ds.contract.components.map((c) => c.name));
|
|
28
|
+
findings.push({
|
|
29
|
+
code: found.candidates.length > 1 && names.some((n) => normalize(n) === normalize(input.component))
|
|
30
|
+
? "component-ambiguous"
|
|
31
|
+
: "component-unknown",
|
|
32
|
+
severity: "error",
|
|
33
|
+
message: `"${input.component}" is not a component in the contract${close.length > 0 ? `. Candidates: ${close.join(", ")}` : ""}`,
|
|
34
|
+
basis: "discovered",
|
|
35
|
+
...(close.length > 0
|
|
36
|
+
? { suggestion: `Did you mean ${close.slice(0, 3).join(" or ")}?` }
|
|
37
|
+
: {
|
|
38
|
+
suggestion: "Find a component with search_design_system or `invariant components list`, or add the component to the design system."
|
|
39
|
+
})
|
|
40
|
+
});
|
|
41
|
+
return { findings, unverifiedValues: 0 };
|
|
42
|
+
}
|
|
43
|
+
const c = found.match;
|
|
44
|
+
const framework = input.framework;
|
|
45
|
+
if (framework && !c.implementations.some((i) => i.framework === framework))
|
|
46
|
+
findings.push({
|
|
47
|
+
code: "framework-not-implemented",
|
|
48
|
+
severity: "error",
|
|
49
|
+
subject: c.id,
|
|
50
|
+
message: `${c.name} has no ${framework} implementation (it has: ${c.implementations.map((i) => i.framework).join(", ")})`,
|
|
51
|
+
basis: "discovered",
|
|
52
|
+
suggestion: `Use the ${c.implementations.map((i) => i.framework).join(" or ")} implementation, or a ${framework} component with the same role.`
|
|
53
|
+
});
|
|
54
|
+
if (c.lifecycle === "deprecated") {
|
|
55
|
+
const replacement = c.deprecated?.replacedBy ? ds.component(c.deprecated.replacedBy)?.name : undefined;
|
|
56
|
+
findings.push({
|
|
57
|
+
code: "component-deprecated",
|
|
58
|
+
severity: "warning",
|
|
59
|
+
subject: c.id,
|
|
60
|
+
message: `${c.name} is deprecated${c.deprecated?.reason ? `: ${c.deprecated.reason}` : ""}`,
|
|
61
|
+
basis: ds.factView(c.facts, "lifecycle")?.status === "documented" ? "documented" : "discovered",
|
|
62
|
+
...(ds.factView(c.facts, "lifecycle")?.source
|
|
63
|
+
? { source: ds.factView(c.facts, "lifecycle")?.source }
|
|
64
|
+
: {}),
|
|
65
|
+
suggestion: replacement
|
|
66
|
+
? `Use ${replacement}.`
|
|
67
|
+
: "Migrate to the component that replaces it; check the component's documentation."
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const complete = ds.propsComplete(c, framework);
|
|
71
|
+
const props = input.props ?? {};
|
|
72
|
+
let unverified = 0;
|
|
73
|
+
const basisOf = (path) => {
|
|
74
|
+
const s = ds.factView(c.facts, path)?.status;
|
|
75
|
+
return s === "documented" || s === "inferred" || s === "approved" ? s : "discovered";
|
|
76
|
+
};
|
|
77
|
+
const where = (path) => {
|
|
78
|
+
const s = ds.factView(c.facts, path)?.source;
|
|
79
|
+
return s ? { source: s } : {};
|
|
80
|
+
};
|
|
81
|
+
const eventNames = new Set(c.events.map((e) => normalize(e.name)));
|
|
82
|
+
const slotNames = new Set(c.slots.map((s) => normalize(s.name)));
|
|
83
|
+
for (const [name, value] of Object.entries(props)) {
|
|
84
|
+
const prop = c.props.find((p) => p.name === name);
|
|
85
|
+
if (!prop) {
|
|
86
|
+
if (isPassthrough(name) ||
|
|
87
|
+
eventNames.has(normalize(name.replace(/^on(?=[A-Z])/, ""))) ||
|
|
88
|
+
slotNames.has(normalize(name)))
|
|
89
|
+
continue;
|
|
90
|
+
const close = nearest(name, c.props.map((p) => p.name));
|
|
91
|
+
findings.push(complete
|
|
92
|
+
? {
|
|
93
|
+
code: "unknown-prop",
|
|
94
|
+
severity: "warning",
|
|
95
|
+
subject: c.id,
|
|
96
|
+
message: `${c.name} does not declare a prop "${name}"`,
|
|
97
|
+
path: `props.${name}`,
|
|
98
|
+
basis: "discovered",
|
|
99
|
+
suggestion: close.length > 0
|
|
100
|
+
? `Did you mean ${close.map((x) => `"${x}"`).join(" or ")}?`
|
|
101
|
+
: `Remove "${name}", or check the props ${c.name} declares (get_component).`
|
|
102
|
+
}
|
|
103
|
+
: {
|
|
104
|
+
code: "unverifiable-prop",
|
|
105
|
+
severity: "info",
|
|
106
|
+
subject: c.id,
|
|
107
|
+
message: `${c.name}'s prop list is incomplete, so "${name}" could not be verified`,
|
|
108
|
+
path: `props.${name}`,
|
|
109
|
+
basis: "discovered"
|
|
110
|
+
});
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const base = `props.${name}`;
|
|
114
|
+
if (prop.deprecated)
|
|
115
|
+
findings.push({
|
|
116
|
+
code: "prop-deprecated",
|
|
117
|
+
severity: "warning",
|
|
118
|
+
subject: c.id,
|
|
119
|
+
message: `${c.name}.${name} is deprecated${prop.deprecated.reason ? `: ${prop.deprecated.reason}` : ""}`,
|
|
120
|
+
path: base,
|
|
121
|
+
basis: basisOf(`${base}.deprecated`),
|
|
122
|
+
...where(`${base}.deprecated`),
|
|
123
|
+
suggestion: prop.deprecated.reason
|
|
124
|
+
? `Follow the deprecation note: ${prop.deprecated.reason}`
|
|
125
|
+
: `Stop using "${name}"; see ${c.name}'s documentation for its replacement.`
|
|
126
|
+
});
|
|
127
|
+
if (isDynamic(value)) {
|
|
128
|
+
unverified++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (prop.allowedValues &&
|
|
132
|
+
(typeof value === "string" || typeof value === "number" || typeof value === "boolean")) {
|
|
133
|
+
if (!prop.allowedValues.some((a) => sameValue(a, value))) {
|
|
134
|
+
const close = typeof value === "string" ? nearest(value, prop.allowedValues.map(String)) : [];
|
|
135
|
+
findings.push({
|
|
136
|
+
code: "prop-value-not-allowed",
|
|
137
|
+
severity: "error",
|
|
138
|
+
subject: c.id,
|
|
139
|
+
message: `${c.name}.${name} is ${JSON.stringify(value)}, which is not one of ${quoteList(prop.allowedValues)}`,
|
|
140
|
+
path: `${base}.allowedValues`,
|
|
141
|
+
basis: basisOf(`${base}.allowedValues`),
|
|
142
|
+
...where(`${base}.allowedValues`),
|
|
143
|
+
suggestion: `Use one of ${quoteList(prop.allowedValues)}${close.length > 0 ? ` (closest: ${JSON.stringify(close[0])})` : ""}.`
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const kind = prop.type.kind;
|
|
149
|
+
const bad = (kind === "boolean" && typeof value !== "boolean") ||
|
|
150
|
+
(kind === "number" && typeof value !== "number") ||
|
|
151
|
+
(kind === "string" && typeof value !== "string");
|
|
152
|
+
if (bad)
|
|
153
|
+
findings.push({
|
|
154
|
+
code: "prop-type-mismatch",
|
|
155
|
+
severity: "warning",
|
|
156
|
+
subject: c.id,
|
|
157
|
+
message: `${c.name}.${name} expects ${kind} (${prop.type.text}) but got ${JSON.stringify(value)}`,
|
|
158
|
+
path: `${base}.type`,
|
|
159
|
+
basis: basisOf(`${base}.type.text`),
|
|
160
|
+
...where(`${base}.type.text`),
|
|
161
|
+
suggestion: `Pass a ${kind} value${kind === "boolean" ? ` (for example ${name}={true})` : ""}.`
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (!input.hasSpread)
|
|
166
|
+
for (const p of c.props) {
|
|
167
|
+
if (!p.required || p.name in props)
|
|
168
|
+
continue;
|
|
169
|
+
if (p.name === "children") {
|
|
170
|
+
if (input.hasChildren === false)
|
|
171
|
+
findings.push({
|
|
172
|
+
code: "required-prop-missing",
|
|
173
|
+
severity: "error",
|
|
174
|
+
subject: c.id,
|
|
175
|
+
message: `${c.name} requires children`,
|
|
176
|
+
path: "props.children",
|
|
177
|
+
basis: basisOf("props.children.required"),
|
|
178
|
+
...where("props.children.required"),
|
|
179
|
+
suggestion: `Put content inside ${c.name}.`
|
|
180
|
+
});
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
findings.push({
|
|
184
|
+
code: "required-prop-missing",
|
|
185
|
+
severity: "error",
|
|
186
|
+
subject: c.id,
|
|
187
|
+
message: `${c.name} requires the prop "${p.name}"`,
|
|
188
|
+
path: `props.${p.name}`,
|
|
189
|
+
basis: basisOf(`props.${p.name}.required`),
|
|
190
|
+
...where(`props.${p.name}.required`),
|
|
191
|
+
suggestion: `Add ${p.name} (${p.type.text}${p.allowedValues ? `: ${quoteList(p.allowedValues)}` : ""}).`
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return { component: c.id, findings, unverifiedValues: unverified };
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=validate-usage.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@invariant-ui/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Compile your design system, UX patterns and page layouts into a contract AI agents can read, and check code against it.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"design-system",
|
|
7
|
+
"ai-agents",
|
|
8
|
+
"mcp",
|
|
9
|
+
"design-tokens",
|
|
10
|
+
"storybook",
|
|
11
|
+
"linting",
|
|
12
|
+
"ux-patterns"
|
|
13
|
+
],
|
|
14
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
15
|
+
"homepage": "https://mcarlucci.github.io/invariant/",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/mcarlucci/invariant.git"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/mcarlucci/invariant/issues"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"bin": {
|
|
25
|
+
"invariant": "dist/cli/main.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@vue/compiler-sfc": "3.5.44",
|
|
37
|
+
"typescript": "5.9.3",
|
|
38
|
+
"zod": "4.6.7"
|
|
39
|
+
}
|
|
40
|
+
}
|