@sdods/contracts 0.2.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.
@@ -0,0 +1,440 @@
1
+ /** DTOs shared by runtime, ingest, server and web. Keep these plain (JSON-serialisable). */
2
+ import type { BrowserName, Layer } from './schemas/project.js';
3
+ export type SuiteStatus = 'passed' | 'failed' | 'skipped' | 'timedOut' | 'interrupted' | 'unknown';
4
+ export type RunStatus = 'queued' | 'running' | 'passed' | 'failed' | 'cancelled' | 'error';
5
+ export type RunTrigger = 'cli' | 'ui' | 'ci' | 'agent' | 'mcp' | 'schedule';
6
+ export interface RunManifest {
7
+ runId: string;
8
+ projectSlug: string;
9
+ env: string;
10
+ tagsExpr?: string;
11
+ layers: Layer[];
12
+ browsers: BrowserName[];
13
+ suiteTag?: string;
14
+ trigger: RunTrigger;
15
+ git?: {
16
+ sha?: string;
17
+ branch?: string;
18
+ dirty?: boolean;
19
+ };
20
+ ci?: {
21
+ provider?: string;
22
+ runId?: string;
23
+ url?: string;
24
+ };
25
+ startedAt: string;
26
+ finishedAt?: string;
27
+ command: string;
28
+ shardIndex?: number;
29
+ shardTotal?: number;
30
+ process?: string;
31
+ modules?: string[];
32
+ sdodsVersion: string;
33
+ playwrightVersion?: string;
34
+ exitCode?: number;
35
+ ingestedAt?: string;
36
+ }
37
+ export interface RunTotals {
38
+ total: number;
39
+ passed: number;
40
+ failed: number;
41
+ skipped: number;
42
+ timedOut: number;
43
+ flaky: number;
44
+ healed: number;
45
+ durationMs: number;
46
+ }
47
+ export interface RunRecord {
48
+ id: string;
49
+ projectSlug: string;
50
+ env: string;
51
+ trigger: RunTrigger;
52
+ status: RunStatus;
53
+ suiteTag?: string;
54
+ tagsExpr?: string;
55
+ layers: Layer[];
56
+ browsers: BrowserName[];
57
+ gitSha?: string;
58
+ gitBranch?: string;
59
+ ciProvider?: string;
60
+ ciRunId?: string;
61
+ ciUrl?: string;
62
+ startedAt?: string;
63
+ finishedAt?: string;
64
+ durationMs?: number;
65
+ totals?: RunTotals;
66
+ artifactsDir?: string;
67
+ exitCode?: number;
68
+ errorText?: string;
69
+ }
70
+ export interface ScenarioMeta {
71
+ runId: string;
72
+ fingerprint: string;
73
+ testId: string;
74
+ project: string;
75
+ layer: Layer;
76
+ browser?: BrowserName;
77
+ runnerProject: string;
78
+ featureUri: string;
79
+ featureName: string;
80
+ scenarioName: string;
81
+ pickleLine?: number;
82
+ exampleIndex?: number | null;
83
+ tags: string[];
84
+ module?: string;
85
+ process?: string;
86
+ retry: number;
87
+ workerIndex: number;
88
+ parallelIndex: number;
89
+ status?: SuiteStatus;
90
+ startedAt: string;
91
+ finishedAt?: string;
92
+ durationMs?: number;
93
+ errorMessage?: string;
94
+ apiCalls?: number;
95
+ heals?: number;
96
+ dir: string;
97
+ }
98
+ export interface ScenarioResult {
99
+ id: string;
100
+ runId: string;
101
+ fingerprint: string;
102
+ naturalKey: string;
103
+ source: 'gherkin' | 'runner-json';
104
+ featureUri: string;
105
+ featureName: string;
106
+ scenarioName: string;
107
+ exampleIndex?: number | null;
108
+ runnerProject: string;
109
+ layer: Layer;
110
+ browser?: BrowserName;
111
+ suiteTag?: string;
112
+ tags: string[];
113
+ jiraKeys: string[];
114
+ status: SuiteStatus;
115
+ attemptsCount: number;
116
+ flaky: boolean;
117
+ durationMs?: number;
118
+ errorMessage?: string;
119
+ errorStack?: string;
120
+ startedAt?: string;
121
+ finishedAt?: string;
122
+ }
123
+ export interface StepResult {
124
+ id: string;
125
+ attemptId: string;
126
+ scenarioId: string;
127
+ runId: string;
128
+ stepIndex: number;
129
+ kind: 'step' | 'hook';
130
+ hookType?: 'before' | 'after';
131
+ keyword?: string;
132
+ text: string;
133
+ argument?: unknown;
134
+ status: SuiteStatus;
135
+ durationMs?: number;
136
+ errorMessage?: string;
137
+ errorStack?: string;
138
+ definitionLocation?: string;
139
+ layerHint?: 'ui' | 'api';
140
+ apiSnapshot?: ApiSnapshot;
141
+ perf?: PerformanceMetrics;
142
+ startedAt?: string;
143
+ finishedAt?: string;
144
+ }
145
+ export type ArtifactKind = 'screenshot' | 'trace' | 'video' | 'har' | 'log' | 'report' | 'visual' | 'diff' | 'attachment';
146
+ export type ArtifactPhase = 'before' | 'after' | 'scenario-start' | 'scenario-end' | 'failure' | 'expected' | 'actual' | 'diff';
147
+ export interface ScreenshotArtifact {
148
+ id: string;
149
+ runId: string;
150
+ scenarioId?: string;
151
+ attemptId?: string;
152
+ stepId?: string;
153
+ stepIndex?: number | null;
154
+ kind: ArtifactKind;
155
+ phase?: ArtifactPhase | null;
156
+ mediaType: string;
157
+ fileName: string;
158
+ relPath: string;
159
+ sizeBytes: number;
160
+ sha256?: string;
161
+ width?: number | null;
162
+ height?: number | null;
163
+ meta?: Record<string, unknown>;
164
+ }
165
+ export interface ApiSnapshot {
166
+ request: {
167
+ method: string;
168
+ url: string;
169
+ headers: Record<string, string>;
170
+ body?: unknown;
171
+ query?: Record<string, string>;
172
+ };
173
+ response: {
174
+ status: number;
175
+ statusText: string;
176
+ headers: Record<string, string>;
177
+ body: unknown;
178
+ rawBody?: string;
179
+ responseTime: number;
180
+ };
181
+ startedAt: string;
182
+ replayedFromHar?: boolean;
183
+ }
184
+ export interface HealCandidate {
185
+ strategy: string;
186
+ selector: string;
187
+ score: number;
188
+ count?: number;
189
+ visible?: boolean;
190
+ enabled?: boolean;
191
+ ms?: number;
192
+ }
193
+ export interface HealEvent {
194
+ fingerprint: string;
195
+ runId: string;
196
+ stepIndex: number;
197
+ action: 'click' | 'fill' | 'select' | 'assert' | 'hover' | 'check';
198
+ description: string;
199
+ pageUrl: string;
200
+ originalSelector: string;
201
+ context: Record<string, unknown>;
202
+ strategyUsed: string | null;
203
+ healedSelector: string | null;
204
+ candidates: HealCandidate[];
205
+ succeeded: boolean;
206
+ durationMs: number;
207
+ at: string;
208
+ }
209
+ export interface PerformanceMetrics {
210
+ url: string;
211
+ timestamp: string;
212
+ domContentLoaded: number;
213
+ pageLoadTime: number;
214
+ timeToFirstByte: number;
215
+ totalResources: number;
216
+ totalResourceSizeKB: number;
217
+ firstContentfulPaint: number | null;
218
+ largestContentfulPaint: number | null;
219
+ }
220
+ export interface StepDef {
221
+ keyword: 'Given' | 'When' | 'Then' | 'Unknown';
222
+ pattern: string;
223
+ file?: string;
224
+ line?: number;
225
+ source?: 'core' | 'project';
226
+ }
227
+ export interface LintFinding {
228
+ severity: 'error' | 'warning';
229
+ rule: string;
230
+ message: string;
231
+ file: string;
232
+ line?: number;
233
+ column?: number;
234
+ fix?: {
235
+ description: string;
236
+ insertTag?: string;
237
+ };
238
+ }
239
+ export interface LintResult {
240
+ errors: LintFinding[];
241
+ warnings: LintFinding[];
242
+ filesChecked: number;
243
+ }
244
+ export interface RunSummary {
245
+ runId: string;
246
+ status: RunStatus;
247
+ totals: RunTotals;
248
+ byProject: Record<string, RunTotals>;
249
+ failed: Array<{
250
+ fingerprint: string;
251
+ title: string;
252
+ runnerProject: string;
253
+ error?: string;
254
+ }>;
255
+ flaky: Array<{
256
+ fingerprint: string;
257
+ title: string;
258
+ runnerProject: string;
259
+ }>;
260
+ reportPaths: {
261
+ html?: string;
262
+ dashboard?: string;
263
+ messages?: string;
264
+ junit?: string;
265
+ };
266
+ }
267
+ export interface Evidence {
268
+ file: string;
269
+ line?: number;
270
+ snippet?: string;
271
+ }
272
+ export type FrameworkKind = 'frontend' | 'backend' | 'fullstack' | 'mobile';
273
+ export interface DetectedFramework {
274
+ name: string;
275
+ kind: FrameworkKind;
276
+ version?: string;
277
+ confidence: number;
278
+ evidence: Evidence[];
279
+ }
280
+ export interface DetectedRoute {
281
+ path: string;
282
+ kind: 'page' | 'api';
283
+ method?: string;
284
+ source: string;
285
+ file: string;
286
+ line?: number;
287
+ params: string[];
288
+ }
289
+ export interface DetectedOpenApi {
290
+ file: string;
291
+ version?: string;
292
+ title?: string;
293
+ endpoints: Array<{
294
+ method: string;
295
+ path: string;
296
+ tag?: string;
297
+ operationId?: string;
298
+ }>;
299
+ }
300
+ export interface DetectedTests {
301
+ framework: 'playwright' | 'cypress' | 'cucumber' | 'jest' | 'vitest' | 'other';
302
+ files: number;
303
+ sampleFiles: string[];
304
+ locators: {
305
+ css: number;
306
+ xpath: number;
307
+ role: number;
308
+ testId: number;
309
+ text: number;
310
+ };
311
+ }
312
+ export interface ChecklistItem {
313
+ id: string;
314
+ severity: 'info' | 'warning' | 'error';
315
+ title: string;
316
+ detail: string;
317
+ fix?: string;
318
+ }
319
+ export interface AnalysisReport {
320
+ appPath: string;
321
+ analyzedAt: string;
322
+ filesScanned: number;
323
+ packageManager: {
324
+ name: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'pip' | 'maven' | 'gradle' | 'unknown';
325
+ monorepo: boolean;
326
+ workspaces: string[];
327
+ evidence: Evidence[];
328
+ };
329
+ frameworks: DetectedFramework[];
330
+ routes: DetectedRoute[];
331
+ openapi: DetectedOpenApi[];
332
+ testIds: {
333
+ attribute: string | null;
334
+ counts: Record<string, number>;
335
+ confidence: number;
336
+ };
337
+ existingTests: DetectedTests[];
338
+ auth: {
339
+ pages: string[];
340
+ libraries: string[];
341
+ strategyGuess: 'none' | 'form' | 'token' | 'sso' | 'oauth-client-credentials';
342
+ confidence: number;
343
+ evidence: Evidence[];
344
+ };
345
+ envs: Array<{
346
+ name: string;
347
+ file: string;
348
+ uiBaseUrl?: string;
349
+ apiBaseUrl?: string;
350
+ vars: string[];
351
+ }>;
352
+ baseUrls: {
353
+ ui?: string;
354
+ api?: string;
355
+ evidence: Evidence[];
356
+ };
357
+ ci: {
358
+ provider: 'github' | 'gitlab' | 'circleci' | 'azure' | 'jenkins' | 'bitbucket' | 'none';
359
+ files: string[];
360
+ };
361
+ i18n: {
362
+ libraries: string[];
363
+ locales: string[];
364
+ };
365
+ a11y: {
366
+ tooling: string[];
367
+ };
368
+ checklist: ChecklistItem[];
369
+ }
370
+ export interface CoverageScenarioRef {
371
+ feature: string;
372
+ scenario: string;
373
+ suite?: string;
374
+ tags: string[];
375
+ }
376
+ export interface CoverageRow {
377
+ kind: 'route' | 'endpoint' | 'role';
378
+ name: string;
379
+ target: string;
380
+ module?: string;
381
+ covered: boolean;
382
+ scenarios: CoverageScenarioRef[];
383
+ bySuite: Record<string, number>;
384
+ }
385
+ export interface CoverageReport {
386
+ project: string;
387
+ generatedAt: string;
388
+ suites: string[];
389
+ routes: CoverageRow[];
390
+ endpoints: CoverageRow[];
391
+ roles: CoverageRow[];
392
+ summary: {
393
+ routes: {
394
+ covered: number;
395
+ total: number;
396
+ };
397
+ endpoints: {
398
+ covered: number;
399
+ total: number;
400
+ };
401
+ roles: {
402
+ covered: number;
403
+ total: number;
404
+ };
405
+ scenarios: number;
406
+ bySuite: Record<string, number>;
407
+ uncoveredModules: string[];
408
+ };
409
+ }
410
+ export interface ProjectProposal {
411
+ slug: string;
412
+ name: string;
413
+ projectYaml: string;
414
+ envYamls: Record<string, string>;
415
+ starterFeatures: Record<string, string>;
416
+ files: Record<string, string>;
417
+ coverageMap: Array<{
418
+ kind: 'route' | 'endpoint';
419
+ target: string;
420
+ module: string;
421
+ starterFeature?: string;
422
+ }>;
423
+ checklist: ChecklistItem[];
424
+ notes: string[];
425
+ /** How each module was decided: which signal won, and how confident it was. */
426
+ detectedModules?: Array<{
427
+ name: string;
428
+ confidence: number;
429
+ signals: string[];
430
+ routes: number;
431
+ endpoints: number;
432
+ evidence: Evidence[];
433
+ }>;
434
+ /** Routes deliberately not turned into modules, with the reason. */
435
+ ignoredTargets?: Array<{
436
+ target: string;
437
+ reason: string;
438
+ }>;
439
+ }
440
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@sdods/contracts",
3
+ "version": "0.2.0",
4
+ "description": "Shared schemas, identifiers and DTO types for SDODS.",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": "./dist/index.js",
9
+ "./ids": "./dist/ids.js",
10
+ "./names": "./dist/names.js",
11
+ "./scopes": "./dist/scopes.js",
12
+ "./schemas": "./dist/schemas/index.js",
13
+ "./types": "./dist/types.js"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "engines": {
22
+ "node": ">=22"
23
+ },
24
+ "dependencies": {
25
+ "zod": "^4.5.4"
26
+ },
27
+ "author": "SDODS <admin@sdods.com>",
28
+ "homepage": "https://sdods.com",
29
+ "bugs": {
30
+ "url": "https://github.com/siri1410/SDODS/issues"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/siri1410/SDODS.git",
35
+ "directory": "packages/contracts"
36
+ },
37
+ "keywords": [
38
+ "sdods",
39
+ "automation",
40
+ "orchestration",
41
+ "testing",
42
+ "bdd",
43
+ "ai-agents",
44
+ "mcp"
45
+ ]
46
+ }