@usefragments/core 1.0.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 +21 -0
- package/dist/chunk-243QYRUF.js +2145 -0
- package/dist/chunk-243QYRUF.js.map +1 -0
- package/dist/chunk-3LLRNCPX.js +111 -0
- package/dist/chunk-3LLRNCPX.js.map +1 -0
- package/dist/chunk-EIYNNS77.js +48 -0
- package/dist/chunk-EIYNNS77.js.map +1 -0
- package/dist/chunk-JNBFJ34I.js +326 -0
- package/dist/chunk-JNBFJ34I.js.map +1 -0
- package/dist/chunk-R3X7UBHU.js +228 -0
- package/dist/chunk-R3X7UBHU.js.map +1 -0
- package/dist/chunk-SH4KPIYH.js +393 -0
- package/dist/chunk-SH4KPIYH.js.map +1 -0
- package/dist/chunk-V4VQB57N.js +56 -0
- package/dist/chunk-V4VQB57N.js.map +1 -0
- package/dist/chunk-X34IA4LR.js +319 -0
- package/dist/chunk-X34IA4LR.js.map +1 -0
- package/dist/chunk-YF65VYRY.js +493 -0
- package/dist/chunk-YF65VYRY.js.map +1 -0
- package/dist/codes/index.d.ts +40 -0
- package/dist/codes/index.js +23 -0
- package/dist/codes/index.js.map +1 -0
- package/dist/compiled-types/index.d.ts +5 -0
- package/dist/compiled-types/index.js +1 -0
- package/dist/compiled-types/index.js.map +1 -0
- package/dist/generate/index.d.ts +47 -0
- package/dist/generate/index.js +11 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/governance-BOa3KyiJ.d.ts +3279 -0
- package/dist/graph/index.d.ts +66 -0
- package/dist/graph/index.js +17 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/index.d.ts +11388 -0
- package/dist/index.js +8711 -0
- package/dist/index.js.map +1 -0
- package/dist/package-identity.d.ts +42 -0
- package/dist/package-identity.js +23 -0
- package/dist/package-identity.js.map +1 -0
- package/dist/preview/index.d.ts +484 -0
- package/dist/preview/index.js +1129 -0
- package/dist/preview/index.js.map +1 -0
- package/dist/react-types.d.ts +22 -0
- package/dist/react-types.js +1 -0
- package/dist/react-types.js.map +1 -0
- package/dist/registry.d.ts +2367 -0
- package/dist/registry.js +62 -0
- package/dist/registry.js.map +1 -0
- package/dist/schemas/index.d.ts +2584 -0
- package/dist/schemas/index.js +55 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/severity.d.ts +18 -0
- package/dist/severity.js +27 -0
- package/dist/severity.js.map +1 -0
- package/dist/test-utils.d.ts +14 -0
- package/dist/test-utils.js +63 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/topology/index.d.ts +48 -0
- package/dist/topology/index.js +7 -0
- package/dist/topology/index.js.map +1 -0
- package/dist/types-xJ2xyp_G.d.ts +119 -0
- package/package.json +120 -0
- package/src/__tests__/contract-parser.test.ts +614 -0
- package/src/__tests__/dtcg-generators.test.ts +439 -0
- package/src/__tests__/dtcg-parser.test.ts +884 -0
- package/src/__tests__/preview-runtime.test.tsx +111 -0
- package/src/__tests__/schema.test.ts +31 -0
- package/src/__tests__/severity.test.ts +34 -0
- package/src/__tests__/style-comparison.test.ts +662 -0
- package/src/__tests__/tokens-compat.test.ts +51 -0
- package/src/agent-format.test.ts +105 -0
- package/src/agent-format.ts +141 -0
- package/src/bundle.ts +149 -0
- package/src/codes/__tests__/codes.test.ts +73 -0
- package/src/codes/codes.ts +463 -0
- package/src/codes/index.ts +7 -0
- package/src/codes/source-finding-bridge.ts +113 -0
- package/src/compiled-types/index.ts +293 -0
- package/src/component-contract.ts +231 -0
- package/src/component-discovery.ts +80 -0
- package/src/composition.test.ts +262 -0
- package/src/composition.ts +318 -0
- package/src/config-paths.test.ts +78 -0
- package/src/config-paths.ts +47 -0
- package/src/config.ts +18 -0
- package/src/conform-prove.test.ts +274 -0
- package/src/conform-prove.ts +326 -0
- package/src/conform.ts +160 -0
- package/src/constants.ts +114 -0
- package/src/context.ts +2 -0
- package/src/contract/fixture.ts +110 -0
- package/src/contract/hash.test.ts +86 -0
- package/src/contract/hash.ts +195 -0
- package/src/contract/index.ts +43 -0
- package/src/contract/preimage.test.ts +254 -0
- package/src/contract/preimage.ts +365 -0
- package/src/contract/stamp.test.ts +100 -0
- package/src/contract/stamp.ts +105 -0
- package/src/contract-parser.ts +141 -0
- package/src/defineFragment.test.ts +257 -0
- package/src/defineFragment.ts +293 -0
- package/src/dtcg-generators.ts +324 -0
- package/src/dtcg-parser.ts +1 -0
- package/src/dtcg.ts +237 -0
- package/src/facts/__snapshots__/facts.test.ts.snap +124 -0
- package/src/facts/builders.ts +835 -0
- package/src/facts/compile.ts +422 -0
- package/src/facts/fact-index.ts +394 -0
- package/src/facts/facts.test.ts +494 -0
- package/src/facts/ids.ts +125 -0
- package/src/facts/index.ts +119 -0
- package/src/facts/types.ts +614 -0
- package/src/figma.ts +263 -0
- package/src/fragment-types.ts +214 -0
- package/src/generate/generate.test.ts +594 -0
- package/src/generate/index.ts +438 -0
- package/src/governance-integrity.test.ts +186 -0
- package/src/governance-integrity.ts +282 -0
- package/src/governance.test.ts +300 -0
- package/src/governance.ts +605 -0
- package/src/governance.type-test.ts +75 -0
- package/src/graph/engine.ts +446 -0
- package/src/graph/graph.test.ts +746 -0
- package/src/graph/index.ts +32 -0
- package/src/graph/serialization.ts +55 -0
- package/src/graph/types.ts +178 -0
- package/src/index.ts +891 -0
- package/src/local-canonical.ts +102 -0
- package/src/mcp-snapshot.ts +222 -0
- package/src/package-identity-match.ts +33 -0
- package/src/package-identity.generated.ts +233 -0
- package/src/package-identity.test.ts +99 -0
- package/src/package-identity.ts +157 -0
- package/src/performance-presets.ts +142 -0
- package/src/preview/comparison-artifact.test.ts +228 -0
- package/src/preview/comparison-artifact.ts +181 -0
- package/src/preview/comparison-context.ts +93 -0
- package/src/preview/comparison-evidence.ts +112 -0
- package/src/preview/comparison-format.ts +21 -0
- package/src/preview/comparison-presentation.ts +187 -0
- package/src/preview/comparison-references.test.ts +430 -0
- package/src/preview/comparison-references.ts +72 -0
- package/src/preview/comparison-score.ts +59 -0
- package/src/preview/comparison-styles.ts +197 -0
- package/src/preview/comparison.test.ts +559 -0
- package/src/preview/comparison.ts +488 -0
- package/src/preview/index.ts +10 -0
- package/src/preview/types.ts +309 -0
- package/src/preview/validation.test.ts +290 -0
- package/src/preview/validation.ts +356 -0
- package/src/preview-runtime.tsx +144 -0
- package/src/raw-html-canonical.test.ts +41 -0
- package/src/raw-html-canonical.ts +179 -0
- package/src/react-types.ts +21 -0
- package/src/registry-install-plan.ts +344 -0
- package/src/registry.test.ts +245 -0
- package/src/registry.ts +369 -0
- package/src/rules/a11y-required-accessible-name.ts +93 -0
- package/src/rules/color-math.test.ts +72 -0
- package/src/rules/color-math.ts +192 -0
- package/src/rules/components-forbidden-prop-value.ts +108 -0
- package/src/rules/components-prefer-library.ts +943 -0
- package/src/rules/components-unknown-prop.ts +94 -0
- package/src/rules/composition-pattern-schema.ts +125 -0
- package/src/rules/composition-pattern.test.ts +320 -0
- package/src/rules/composition-pattern.ts +271 -0
- package/src/rules/emit-gate.test.ts +42 -0
- package/src/rules/emit-gate.ts +60 -0
- package/src/rules/finding.ts +54 -0
- package/src/rules/index.ts +235 -0
- package/src/rules/jsx-preferred-component.ts +68 -0
- package/src/rules/jsx-preferred-import-path.ts +67 -0
- package/src/rules/presets.ts +57 -0
- package/src/rules/props-invalid-value.ts +115 -0
- package/src/rules/rules.test.ts +3636 -0
- package/src/rules/spacing-resolution.ts +184 -0
- package/src/rules/styles-no-raw-color.ts +329 -0
- package/src/rules/styles-no-raw-dimensions.ts +357 -0
- package/src/rules/styles-no-raw-spacing.ts +236 -0
- package/src/rules/styles-no-raw-typography.ts +237 -0
- package/src/rules/tailwind-arbitrary-color.test.ts +128 -0
- package/src/rules/tailwind-arbitrary-color.ts +93 -0
- package/src/rules/tailwind-arbitrary-spacing.test.ts +157 -0
- package/src/rules/tailwind-arbitrary-spacing.ts +120 -0
- package/src/rules/tailwind-forbidden-palette.test.ts +116 -0
- package/src/rules/tailwind-forbidden-palette.ts +107 -0
- package/src/rules/tailwind-off-scale-spacing-token.test.ts +100 -0
- package/src/rules/tailwind-off-scale-spacing-token.ts +108 -0
- package/src/rules/tailwind-raw-color-via-token.test.ts +108 -0
- package/src/rules/tailwind-raw-color-via-token.ts +82 -0
- package/src/rules/tailwind-rule-utils.ts +106 -0
- package/src/rules/tailwind-unknown-class.test.ts +157 -0
- package/src/rules/tailwind-unknown-class.ts +121 -0
- package/src/rules/taxonomy.test.ts +238 -0
- package/src/rules/theme-no-theme-coupled-literal.ts +132 -0
- package/src/rules/tiers.ts +111 -0
- package/src/rules/tokens-css-vars-must-be-defined.test.ts +244 -0
- package/src/rules/tokens-css-vars-must-be-defined.ts +156 -0
- package/src/rules/tokens-require-dual-fallback.ts +78 -0
- package/src/rules/types.ts +27 -0
- package/src/rules/utils.test.ts +110 -0
- package/src/rules/utils.ts +599 -0
- package/src/schema.ts +427 -0
- package/src/schemas/index.ts +275 -0
- package/src/schemas/schemas.test.ts +124 -0
- package/src/severity.ts +54 -0
- package/src/storyAdapter.test.ts +571 -0
- package/src/storyAdapter.ts +761 -0
- package/src/storyFilters.test.ts +350 -0
- package/src/storyFilters.ts +253 -0
- package/src/storybook-csf.ts +11 -0
- package/src/style-comparison.ts +423 -0
- package/src/test-utils.ts +68 -0
- package/src/token-parser.ts +2 -0
- package/src/token-types.ts +287 -0
- package/src/tokens/categories.ts +131 -0
- package/src/tokens/color.ts +193 -0
- package/src/tokens/design-token-parser.test.ts +159 -0
- package/src/tokens/design-token-parser.ts +402 -0
- package/src/tokens/dtcg.ts +428 -0
- package/src/tokens/index.ts +130 -0
- package/src/tokens/lookup.ts +19 -0
- package/src/tokens/scss.ts +171 -0
- package/src/tokens/tailwind-v4.ts +187 -0
- package/src/tokens/types.ts +43 -0
- package/src/topology/index.ts +9 -0
- package/src/topology/resolve-area.test.ts +174 -0
- package/src/topology/resolve-area.ts +215 -0
- package/src/types.ts +1057 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Topology — map a repo-relative file path to its product area.
|
|
3
|
+
*
|
|
4
|
+
* This is the DRY keystone of the topology layer: the ONLY area-matching
|
|
5
|
+
* implementation in the monorepo. Consumers (CLI scan, Cloud managed-editor
|
|
6
|
+
* preview, cross-repo reconciliation) import it; none reimplements glob/area
|
|
7
|
+
* logic. Pure and browser-safe — no Node, no parser deps.
|
|
8
|
+
*
|
|
9
|
+
* See `apps/cloud/docs/topology/01-architecture.md §1`.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export type AreaCriticality = "low" | "medium" | "high" | "revenue" | "regulated";
|
|
13
|
+
|
|
14
|
+
export interface Area {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
criticality: AreaCriticality;
|
|
18
|
+
owners: string[];
|
|
19
|
+
/** Globs matched against repo-relative file paths in v0. */
|
|
20
|
+
files: string[];
|
|
21
|
+
/** Stored for later route-topology adapters; NOT matched in v0. */
|
|
22
|
+
routes?: string[];
|
|
23
|
+
/** Tie-break: higher wins. Defaults to declaration order. */
|
|
24
|
+
priority?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface Topology {
|
|
28
|
+
/** Bump signals "re-tag" to consumers that cache. */
|
|
29
|
+
version: number;
|
|
30
|
+
/** Whether area file globs are matched relative to app.path or repo root. Defaults to "app". */
|
|
31
|
+
base?: "app" | "repo";
|
|
32
|
+
/** Array (not a keyed record) so precedence is deterministic. */
|
|
33
|
+
areas: Area[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface AreaMatch {
|
|
37
|
+
areaId: string;
|
|
38
|
+
areaName: string;
|
|
39
|
+
criticality: AreaCriticality;
|
|
40
|
+
owners: string[];
|
|
41
|
+
/** The winning pattern — surfaced in reports for transparency. */
|
|
42
|
+
matchedGlob: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Compile a minimal glob to an anchored RegExp. We intentionally do NOT depend
|
|
47
|
+
* on picomatch: core stays lean, the surface we need is small, and we want
|
|
48
|
+
* exact control over Next.js route-group parens (`(marketing)` is a literal
|
|
49
|
+
* path segment here, not an extglob group).
|
|
50
|
+
*
|
|
51
|
+
* Semantics:
|
|
52
|
+
* - `/**` at a segment boundary (end-of-glob or before `/`) → "this directory
|
|
53
|
+
* and everything under it": the leading slash is optional, so
|
|
54
|
+
* `src/app/checkout/**` matches `src/app/checkout` AND any descendant.
|
|
55
|
+
* - a bare/leading `**` → matches across path separators (`.*`). Note a
|
|
56
|
+
* leading globstar-then-slash does NOT match the root (use a lone `**`
|
|
57
|
+
* for "everything").
|
|
58
|
+
* - `*` → matches within a single segment (`[^/]*`)
|
|
59
|
+
* - `?` → a single non-separator char
|
|
60
|
+
* - `{a,b}` → alternation `(?:a|b)`
|
|
61
|
+
* - every other regex-significant char (`.`, `(`, `)`, `+`, …) is literal
|
|
62
|
+
*
|
|
63
|
+
* Throws on a malformed pattern (e.g. an unbalanced `{`). Callers compile via
|
|
64
|
+
* `compile()`, which catches the throw so a config typo degrades one glob to a
|
|
65
|
+
* non-match instead of aborting the whole scan.
|
|
66
|
+
*/
|
|
67
|
+
function globToRegExp(glob: string): RegExp {
|
|
68
|
+
let out = "";
|
|
69
|
+
let braceDepth = 0;
|
|
70
|
+
let i = 0;
|
|
71
|
+
while (i < glob.length) {
|
|
72
|
+
const ch = glob[i];
|
|
73
|
+
|
|
74
|
+
// `/**` at a segment boundary → optional slash + anything-below. Matches
|
|
75
|
+
// the directory itself (`a/**` ⇒ `a`) and every descendant.
|
|
76
|
+
if (
|
|
77
|
+
ch === "/" &&
|
|
78
|
+
glob[i + 1] === "*" &&
|
|
79
|
+
glob[i + 2] === "*" &&
|
|
80
|
+
(glob[i + 3] === undefined || glob[i + 3] === "/")
|
|
81
|
+
) {
|
|
82
|
+
out += "(?:/.*)?";
|
|
83
|
+
i += 3; // consume `/**`; a trailing `/` (in `a/**/b`) is handled next pass
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Bare/leading globstar — crosses path separators.
|
|
88
|
+
if (ch === "*" && glob[i + 1] === "*") {
|
|
89
|
+
out += ".*";
|
|
90
|
+
i += 2;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
switch (ch) {
|
|
95
|
+
case "*":
|
|
96
|
+
out += "[^/]*"; // single segment
|
|
97
|
+
break;
|
|
98
|
+
case "?":
|
|
99
|
+
out += "[^/]";
|
|
100
|
+
break;
|
|
101
|
+
case "{":
|
|
102
|
+
braceDepth += 1;
|
|
103
|
+
out += "(?:";
|
|
104
|
+
break;
|
|
105
|
+
case "}":
|
|
106
|
+
if (braceDepth > 0) {
|
|
107
|
+
braceDepth -= 1;
|
|
108
|
+
out += ")";
|
|
109
|
+
} else {
|
|
110
|
+
out += "\\}";
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
case ",":
|
|
114
|
+
out += braceDepth > 0 ? "|" : ",";
|
|
115
|
+
break;
|
|
116
|
+
// Regex-significant chars kept literal (parens cover route groups).
|
|
117
|
+
case ".":
|
|
118
|
+
case "(":
|
|
119
|
+
case ")":
|
|
120
|
+
case "+":
|
|
121
|
+
case "^":
|
|
122
|
+
case "$":
|
|
123
|
+
case "|":
|
|
124
|
+
case "[":
|
|
125
|
+
case "]":
|
|
126
|
+
case "\\":
|
|
127
|
+
out += `\\${ch}`;
|
|
128
|
+
break;
|
|
129
|
+
default:
|
|
130
|
+
out += ch;
|
|
131
|
+
}
|
|
132
|
+
i += 1;
|
|
133
|
+
}
|
|
134
|
+
return new RegExp(`^${out}$`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface CompiledArea {
|
|
138
|
+
area: Area;
|
|
139
|
+
matchers: { glob: string; re: RegExp }[];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Cache compiled matchers per topology object. Consumers pass the same
|
|
144
|
+
* `topology` for every finding in a run, so this turns N×globs recompiles into
|
|
145
|
+
* one. A reloaded config is a new object → fresh entry, so `version` bumps need
|
|
146
|
+
* no manual invalidation.
|
|
147
|
+
*/
|
|
148
|
+
const compiledCache = new WeakMap<Topology, CompiledArea[]>();
|
|
149
|
+
|
|
150
|
+
function compile(topology: Topology): CompiledArea[] {
|
|
151
|
+
const cached = compiledCache.get(topology);
|
|
152
|
+
if (cached) return cached;
|
|
153
|
+
|
|
154
|
+
// Order by (priority desc, declaration order). Decorate-sort-undecorate keeps
|
|
155
|
+
// the sort stable across engines.
|
|
156
|
+
const ordered = topology.areas
|
|
157
|
+
.map((area, index) => ({ area, index }))
|
|
158
|
+
.sort((a, b) => {
|
|
159
|
+
const pa = a.area.priority ?? 0;
|
|
160
|
+
const pb = b.area.priority ?? 0;
|
|
161
|
+
if (pa !== pb) return pb - pa;
|
|
162
|
+
return a.index - b.index;
|
|
163
|
+
})
|
|
164
|
+
.map(({ area }) => ({
|
|
165
|
+
area,
|
|
166
|
+
matchers: area.files.flatMap((glob) => {
|
|
167
|
+
try {
|
|
168
|
+
return [{ glob, re: globToRegExp(glob) }];
|
|
169
|
+
} catch {
|
|
170
|
+
// A malformed glob (e.g. unbalanced `{`) compiles to an invalid
|
|
171
|
+
// RegExp. Skip it rather than aborting the entire scan — topology
|
|
172
|
+
// config is user-authored, so one typo must not take down
|
|
173
|
+
// `fragments check`. Its files simply fall through to "Unassigned".
|
|
174
|
+
if (typeof console !== "undefined") {
|
|
175
|
+
console.warn(
|
|
176
|
+
`[topology] ignoring invalid glob in area "${area.id}": ${JSON.stringify(glob)}`
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
}),
|
|
182
|
+
}));
|
|
183
|
+
|
|
184
|
+
compiledCache.set(topology, ordered);
|
|
185
|
+
return ordered;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Normalize to a POSIX, repo-relative path before matching. */
|
|
189
|
+
function normalizePath(repoRelPath: string): string {
|
|
190
|
+
return repoRelPath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/+/, "");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Resolve the product area for a repo-relative path. First match by
|
|
195
|
+
* `(priority desc, declaration order)`. Returns `null` when nothing matches —
|
|
196
|
+
* the caller buckets that as the explicit "Unassigned" area (never dropped;
|
|
197
|
+
* dropping unmatched evidence would make coverage lie).
|
|
198
|
+
*/
|
|
199
|
+
export function resolveArea(repoRelPath: string, topology: Topology): AreaMatch | null {
|
|
200
|
+
const path = normalizePath(repoRelPath);
|
|
201
|
+
for (const { area, matchers } of compile(topology)) {
|
|
202
|
+
for (const { glob, re } of matchers) {
|
|
203
|
+
if (re.test(path)) {
|
|
204
|
+
return {
|
|
205
|
+
areaId: area.id,
|
|
206
|
+
areaName: area.name,
|
|
207
|
+
criticality: area.criticality,
|
|
208
|
+
owners: area.owners,
|
|
209
|
+
matchedGlob: glob,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|