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