uidex 0.2.4 → 0.4.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 (65) hide show
  1. package/README.md +253 -353
  2. package/dist/cli/cli.cjs +3324 -0
  3. package/dist/cli/cli.cjs.map +1 -0
  4. package/dist/cloud/index.cjs +169 -0
  5. package/dist/cloud/index.cjs.map +1 -0
  6. package/dist/cloud/index.js +140 -0
  7. package/dist/cloud/index.js.map +1 -0
  8. package/dist/headless/index.cjs +4143 -0
  9. package/dist/headless/index.cjs.map +1 -0
  10. package/dist/headless/index.d.cts +220 -0
  11. package/dist/headless/index.d.ts +220 -0
  12. package/dist/headless/index.js +4130 -0
  13. package/dist/headless/index.js.map +1 -0
  14. package/dist/index.cjs +8704 -9883
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +968 -146
  17. package/dist/index.d.ts +968 -146
  18. package/dist/index.js +8327 -9492
  19. package/dist/index.js.map +1 -1
  20. package/dist/playwright/index.cjs +164 -24
  21. package/dist/playwright/index.cjs.map +1 -1
  22. package/dist/playwright/index.d.cts +30 -53
  23. package/dist/playwright/index.d.ts +30 -53
  24. package/dist/playwright/index.js +148 -21
  25. package/dist/playwright/index.js.map +1 -1
  26. package/dist/playwright/reporter.cjs +62 -28
  27. package/dist/playwright/reporter.cjs.map +1 -1
  28. package/dist/playwright/reporter.d.cts +24 -12
  29. package/dist/playwright/reporter.d.ts +24 -12
  30. package/dist/playwright/reporter.js +62 -28
  31. package/dist/playwright/reporter.js.map +1 -1
  32. package/dist/react/index.cjs +8706 -9883
  33. package/dist/react/index.cjs.map +1 -1
  34. package/dist/react/index.d.cts +720 -146
  35. package/dist/react/index.d.ts +720 -146
  36. package/dist/react/index.js +8518 -9629
  37. package/dist/react/index.js.map +1 -1
  38. package/dist/scan/index.cjs +3360 -0
  39. package/dist/scan/index.cjs.map +1 -0
  40. package/dist/scan/index.d.cts +378 -0
  41. package/dist/scan/index.d.ts +378 -0
  42. package/dist/scan/index.js +3303 -0
  43. package/dist/scan/index.js.map +1 -0
  44. package/package.json +67 -60
  45. package/templates/claude/audit.md +43 -0
  46. package/templates/claude/rules.md +227 -0
  47. package/claude/audit-command.md +0 -46
  48. package/claude/rules.md +0 -167
  49. package/dist/api/index.cjs +0 -254
  50. package/dist/api/index.cjs.map +0 -1
  51. package/dist/api/index.d.cts +0 -236
  52. package/dist/api/index.d.ts +0 -236
  53. package/dist/api/index.js +0 -226
  54. package/dist/api/index.js.map +0 -1
  55. package/dist/core/index.cjs +0 -11045
  56. package/dist/core/index.cjs.map +0 -1
  57. package/dist/core/index.d.cts +0 -424
  58. package/dist/core/index.d.ts +0 -424
  59. package/dist/core/index.global.js +0 -66516
  60. package/dist/core/index.global.js.map +0 -1
  61. package/dist/core/index.js +0 -10995
  62. package/dist/core/index.js.map +0 -1
  63. package/dist/core/style.css +0 -1529
  64. package/dist/scripts/cli.cjs +0 -3904
  65. package/uidex.schema.json +0 -93
@@ -0,0 +1,378 @@
1
+ declare const ENTITY_KINDS: readonly ["route", "page", "feature", "widget", "region", "element", "primitive", "flow"];
2
+ type EntityKind = (typeof ENTITY_KINDS)[number];
3
+ type Scope = string;
4
+ interface Location {
5
+ file: string;
6
+ line?: number;
7
+ column?: number;
8
+ }
9
+ interface EntityRef {
10
+ kind: EntityKind;
11
+ id: string;
12
+ }
13
+ interface Metadata {
14
+ name?: string;
15
+ description?: string;
16
+ acceptance?: string[];
17
+ notes?: string;
18
+ composes?: EntityRef[];
19
+ flows?: readonly string[];
20
+ features?: string[];
21
+ widgets?: string[];
22
+ }
23
+ interface EntityWithMetaBase {
24
+ id: string;
25
+ loc?: Location;
26
+ scopes?: Scope[];
27
+ meta?: Metadata;
28
+ }
29
+ interface Route {
30
+ kind: "route";
31
+ path: string;
32
+ page: string;
33
+ }
34
+ interface FlowStep {
35
+ entityId: string;
36
+ action?: string;
37
+ }
38
+ interface Flow {
39
+ kind: "flow";
40
+ id: string;
41
+ loc: Location;
42
+ touches: string[];
43
+ steps: FlowStep[];
44
+ }
45
+ interface Page extends EntityWithMetaBase {
46
+ kind: "page";
47
+ }
48
+ interface Feature extends EntityWithMetaBase {
49
+ kind: "feature";
50
+ }
51
+ interface Widget extends EntityWithMetaBase {
52
+ kind: "widget";
53
+ }
54
+ interface Region extends EntityWithMetaBase {
55
+ kind: "region";
56
+ }
57
+ interface Element extends EntityWithMetaBase {
58
+ kind: "element";
59
+ }
60
+ interface Primitive extends EntityWithMetaBase {
61
+ kind: "primitive";
62
+ }
63
+ type Entity = Route | Page | Feature | Widget | Region | Element | Primitive | Flow;
64
+ type EntityByKind<K extends EntityKind> = Extract<Entity, {
65
+ kind: K;
66
+ }>;
67
+
68
+ interface Registry {
69
+ add(entity: Entity): void;
70
+ get<K extends EntityKind>(kind: K, id: string): EntityByKind<K> | undefined;
71
+ list<K extends EntityKind>(kind: K): ReadonlyArray<EntityByKind<K>>;
72
+ query(predicate: (entity: Entity) => boolean): Entity[];
73
+ byScope(scope: Scope): Entity[];
74
+ touchedBy(flowId: string): Entity[];
75
+ }
76
+
77
+ interface SourceConfig {
78
+ rootDir: string;
79
+ include?: string[];
80
+ exclude?: string[];
81
+ prefix?: string;
82
+ }
83
+ interface ConventionsConfig {
84
+ primitives?: string[] | false;
85
+ features?: string | false;
86
+ pages?: "auto" | false;
87
+ flows?: string[] | false;
88
+ regions?: "landmarks" | false;
89
+ }
90
+ interface AuditConfig {
91
+ scopeLeak?: boolean;
92
+ coverage?: boolean;
93
+ acceptance?: boolean;
94
+ }
95
+ type TypeMode = "strict" | "loose";
96
+ interface UidexConfig {
97
+ $schema?: string;
98
+ sources: SourceConfig[];
99
+ exclude?: string[];
100
+ output: string;
101
+ flows?: string[];
102
+ typeMode?: TypeMode;
103
+ audit?: AuditConfig;
104
+ conventions?: ConventionsConfig;
105
+ }
106
+ interface DiscoveredConfig {
107
+ configPath: string;
108
+ configDir: string;
109
+ config: UidexConfig;
110
+ }
111
+ interface ScannedFile {
112
+ sourcePath: string;
113
+ relativePath: string;
114
+ displayPath: string;
115
+ content: string;
116
+ }
117
+ type AnnotationKind = "element" | "region" | "widget" | "primitive" | "page-doc" | "feature-doc" | "widget-doc" | "not-flow" | "orphan-acceptance";
118
+ type DomAttrKind = "element" | "region" | "widget" | "primitive";
119
+ interface AnnotationAncestor {
120
+ kind: DomAttrKind;
121
+ id: string;
122
+ }
123
+ interface Annotation {
124
+ kind: AnnotationKind;
125
+ id: string;
126
+ file: string;
127
+ line: number;
128
+ description?: string;
129
+ acceptance?: string[];
130
+ /** JSX ancestor chain, outermost to innermost. Only populated for DOM-attribute kinds. */
131
+ ancestors?: AnnotationAncestor[];
132
+ }
133
+ type MetadataExportKind = "page" | "feature" | "primitive" | "widget" | "flow";
134
+ interface MetadataExport {
135
+ source: "ts-export";
136
+ kind: MetadataExportKind;
137
+ id: string | false;
138
+ name?: string;
139
+ acceptance?: string[];
140
+ description?: string;
141
+ features?: string[];
142
+ widgets?: string[];
143
+ notFlow?: boolean;
144
+ loc: Location;
145
+ }
146
+ interface ExtractedFile {
147
+ file: ScannedFile;
148
+ annotations: Annotation[];
149
+ metadata?: MetadataExport[];
150
+ diagnostics?: Diagnostic[];
151
+ }
152
+ interface DetectedRoute {
153
+ id: string;
154
+ path: string;
155
+ file: string;
156
+ }
157
+ type DiagnosticSeverity = "error" | "warning" | "info";
158
+ interface Diagnostic {
159
+ code: string;
160
+ severity: DiagnosticSeverity;
161
+ message: string;
162
+ file?: string;
163
+ line?: number;
164
+ entity?: {
165
+ kind: EntityKind;
166
+ id: string;
167
+ };
168
+ hint?: string;
169
+ }
170
+ interface AuditSummary {
171
+ diagnostics: Diagnostic[];
172
+ summary: {
173
+ errors: number;
174
+ warnings: number;
175
+ };
176
+ }
177
+ interface GitContext {
178
+ branch: string | null;
179
+ commit: string | null;
180
+ pr: string | null;
181
+ }
182
+
183
+ declare const CONFIG_FILENAME = ".uidex.json";
184
+ interface DiscoverOptions {
185
+ cwd?: string;
186
+ maxDepth?: number;
187
+ }
188
+ declare function discover(options?: DiscoverOptions): DiscoveredConfig[];
189
+
190
+ /**
191
+ * Translate a glob to a RegExp. Supports `**`, `*`, `?`, and `{a,b,c}` alternation.
192
+ * The produced pattern matches the full relative path with forward slashes.
193
+ */
194
+ declare function globToRegExp(glob: string): RegExp;
195
+ interface WalkOptions {
196
+ cwd: string;
197
+ globalExcludes?: string[];
198
+ /**
199
+ * When true, do not auto-exclude `*.spec.{ts,tsx}` and `*.test.{ts,tsx}`.
200
+ * Used by flow-file walking, where spec files are the targets.
201
+ */
202
+ includeTests?: boolean;
203
+ }
204
+ declare function walk(sources: SourceConfig[], options: WalkOptions): ScannedFile[];
205
+
206
+ declare function extract(files: ScannedFile[]): ExtractedFile[];
207
+
208
+ interface UidexExportExtractResult {
209
+ exports: MetadataExport[];
210
+ diagnostics: Diagnostic[];
211
+ }
212
+ declare function extractUidexExports(file: ScannedFile): UidexExportExtractResult;
213
+
214
+ interface ResolveContext {
215
+ config: UidexConfig;
216
+ extracted: ExtractedFile[];
217
+ flowFiles?: ExtractedFile[];
218
+ }
219
+ interface ResolveOutput {
220
+ registry: Registry;
221
+ entities: Entity[];
222
+ routes: DetectedRoute[];
223
+ diagnostics: Diagnostic[];
224
+ }
225
+ /**
226
+ * Resolve annotations + conventions into a typed Registry.
227
+ * Precedence: configuration > `export const uidex` > DOM attribute > convention.
228
+ */
229
+ declare function resolve(ctx: ResolveContext): ResolveOutput;
230
+
231
+ interface AuditOptions {
232
+ registry: Registry;
233
+ extracted: ExtractedFile[];
234
+ files: ScannedFile[];
235
+ config: UidexConfig;
236
+ check?: boolean;
237
+ lint?: boolean;
238
+ resolveDiagnostics?: Diagnostic[];
239
+ /** Freshly-emitted gen-file bytes, required for --check. */
240
+ generated?: string;
241
+ /** On-disk contents of the gen file at scan time; `null` if the file does not exist. */
242
+ existingOnDisk?: string | null;
243
+ /** Relative path of the configured `output` file; used in diagnostics. */
244
+ outputPath?: string;
245
+ }
246
+ declare function audit(opts: AuditOptions): AuditSummary;
247
+
248
+ interface EmitOptions {
249
+ registry: Registry;
250
+ gitContext?: GitContext;
251
+ /** The import source for `createUidex` in the generated preconfigured export. */
252
+ uidexImport?: string;
253
+ /** Controls id-union emission: "strict" emits literal unions, "loose" emits `string`. */
254
+ typeMode?: TypeMode;
255
+ }
256
+ declare function emit(opts: EmitOptions): string;
257
+
258
+ /**
259
+ * Detect framework-aware routes:
260
+ * - Next.js App Router: `**\/app/**\/page.tsx` -> `/segments`
261
+ * - Next.js Pages Router: `**\/pages/**\/*.tsx` -> `/segments` (excludes _app, _document, api/)
262
+ * - Vite + React Router / TanStack Router:
263
+ * `**\/routes/**\/*.tsx` -> `/segments`
264
+ */
265
+ declare function detectRoutes(files: ScannedFile[]): DetectedRoute[];
266
+ declare function pathToId(routePath: string): string;
267
+
268
+ interface GitResolveOptions {
269
+ cwd?: string;
270
+ env?: NodeJS.ProcessEnv;
271
+ }
272
+ declare function resolveGitContext(opts?: GitResolveOptions): GitContext;
273
+
274
+ interface ScaffoldOptions {
275
+ registry: Registry;
276
+ widgetId: string;
277
+ outDir: string;
278
+ force?: boolean;
279
+ fixtureImport?: string;
280
+ }
281
+ interface ScaffoldResult {
282
+ outputPath: string;
283
+ written: boolean;
284
+ skipped: boolean;
285
+ reason?: string;
286
+ }
287
+ declare function scaffoldWidgetSpec(opts: ScaffoldOptions): ScaffoldResult;
288
+
289
+ interface RunScanOptions {
290
+ cwd?: string;
291
+ check?: boolean;
292
+ lint?: boolean;
293
+ configs?: DiscoveredConfig[];
294
+ }
295
+ interface ScanResult {
296
+ config: UidexConfig;
297
+ configDir: string;
298
+ registry: Registry;
299
+ gitContext: GitContext;
300
+ audit?: AuditSummary;
301
+ generated: string;
302
+ outputPath: string;
303
+ }
304
+ declare function runScan(opts?: RunScanOptions): ScanResult[];
305
+ declare function writeScanResult(result: ScanResult): void;
306
+
307
+ interface CliResult {
308
+ exitCode: number;
309
+ stdout: string;
310
+ stderr: string;
311
+ }
312
+ interface CliOptions {
313
+ argv: string[];
314
+ cwd?: string;
315
+ }
316
+ declare function run(opts: CliOptions): Promise<CliResult>;
317
+
318
+ declare const DEFAULT_TYPE_MODE: TypeMode;
319
+ declare class ConfigError extends Error {
320
+ constructor(message: string);
321
+ }
322
+ declare function validateConfig(raw: unknown): UidexConfig;
323
+ declare function parseConfig(json: string): UidexConfig;
324
+ declare const DEFAULT_CONVENTIONS: Required<Pick<NonNullable<UidexConfig["conventions"]>, "primitives" | "features" | "pages" | "flows" | "regions">>;
325
+
326
+ /**
327
+ * Authoring-surface shape types for `export const uidex = { ... }` declarations.
328
+ *
329
+ * The gen-file emitter specialises each shape with the project's emitted id
330
+ * unions (or `string` in loose mode), producing a project-specific `Uidex`
331
+ * namespace that lives alongside the generated registry. Authors write:
332
+ *
333
+ * export const uidex = { page: "checkout", features: ["billing"] }
334
+ * as const satisfies Uidex.Page
335
+ *
336
+ * and `tsc` validates the ids at the literal site.
337
+ *
338
+ * The generic parameters default to `string` so these shapes remain usable in
339
+ * contexts that have not yet regenerated the gen file (e.g. loose mode, or
340
+ * bootstrapping before the first scan).
341
+ */
342
+ declare namespace Uidex {
343
+ interface Page<PageIds extends string = string, FeatureIds extends string = string, WidgetIds extends string = string> {
344
+ page: PageIds | false;
345
+ name?: string;
346
+ features?: readonly FeatureIds[];
347
+ widgets?: readonly WidgetIds[];
348
+ acceptance?: readonly string[];
349
+ description?: string;
350
+ }
351
+ interface Feature<FeatureIds extends string = string> {
352
+ feature: FeatureIds | false;
353
+ name?: string;
354
+ acceptance?: readonly string[];
355
+ description?: string;
356
+ }
357
+ interface Primitive<PrimitiveIds extends string = string> {
358
+ primitive: PrimitiveIds;
359
+ name?: string;
360
+ description?: string;
361
+ }
362
+ interface Widget<WidgetIds extends string = string> {
363
+ widget: WidgetIds;
364
+ name?: string;
365
+ acceptance?: readonly string[];
366
+ description?: string;
367
+ }
368
+ interface Flow<FlowIds extends string = string> {
369
+ flow: FlowIds;
370
+ name?: string;
371
+ description?: string;
372
+ }
373
+ interface NotFlow {
374
+ notFlow: true;
375
+ }
376
+ }
377
+
378
+ export { type Annotation, type AnnotationKind, type AuditConfig, type AuditSummary, CONFIG_FILENAME, type CliOptions, type CliResult, ConfigError, type ConventionsConfig, DEFAULT_CONVENTIONS, DEFAULT_TYPE_MODE, type DetectedRoute, type Diagnostic, type DiagnosticSeverity, type DiscoveredConfig, type ExtractedFile, type GitContext, type MetadataExport, type MetadataExportKind, type RunScanOptions, type ScaffoldOptions, type ScaffoldResult, type ScanResult, type ScannedFile, type SourceConfig, type TypeMode, Uidex, type UidexConfig, audit, detectRoutes, discover, emit, extract, extractUidexExports, globToRegExp, parseConfig, pathToId, resolve, resolveGitContext, run as runCli, runScan, scaffoldWidgetSpec, validateConfig, walk, writeScanResult };