speckeeper 0.8.1 → 0.9.1

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.
@@ -511,6 +511,56 @@ interface CheckResult {
511
511
  relationType: 'verifiedBy' | 'implements' | 'traces';
512
512
  }>;
513
513
  }
514
+ /** OpenAPI deep validation mapping */
515
+ interface OpenAPIValidationMapping {
516
+ path: string;
517
+ method?: string;
518
+ parameters?: Array<{
519
+ name: string;
520
+ in?: string;
521
+ type?: string;
522
+ }>;
523
+ responseProperties?: Array<{
524
+ name: string;
525
+ type?: string;
526
+ }>;
527
+ }
528
+ /** DDL deep validation mapping */
529
+ interface DDLValidationMapping {
530
+ tableName: string;
531
+ columns?: Array<{
532
+ name: string;
533
+ type?: string;
534
+ }>;
535
+ checkTypes?: boolean;
536
+ }
537
+ /**
538
+ * Deep validation rule for a specific source type.
539
+ * The mapper extracts expected structure from a spec for detailed comparison
540
+ * against the matched source object.
541
+ */
542
+ interface DeepValidationRule<T, TMapping = unknown> {
543
+ mapper: (spec: T) => TMapping;
544
+ }
545
+ /**
546
+ * Deep validation configuration keyed by source type.
547
+ * Models define this to enable Level 2/3 checks beyond existence.
548
+ */
549
+ interface DeepValidationConfig<T> {
550
+ openapi?: DeepValidationRule<T, OpenAPIValidationMapping>;
551
+ ddl?: DeepValidationRule<T, DDLValidationMapping>;
552
+ [sourceType: string]: DeepValidationRule<T, unknown> | undefined;
553
+ }
554
+ /**
555
+ * Lookup key configuration keyed by source type.
556
+ * When a model's spec ID differs from the external identifier
557
+ * (e.g. entity ID "user" vs DDL table name "users"),
558
+ * define a mapper per source type to derive the external key.
559
+ * If not defined for a source type, spec.id is used as-is.
560
+ */
561
+ interface LookupKeyConfig<T> {
562
+ [sourceType: string]: ((spec: T) => string) | undefined;
563
+ }
514
564
  /**
515
565
  * Coverage result
516
566
  */
@@ -604,8 +654,12 @@ declare abstract class Model<TSchema extends ZodType> {
604
654
  protected lintRules: LintRule<z.infer<TSchema>>[];
605
655
  /** Exporters (override in subclass) */
606
656
  protected exporters: Exporter<z.infer<TSchema>>[];
607
- /** External checker (optional) */
657
+ /** External checker (optional) — deprecated, use deepValidation instead */
608
658
  protected externalChecker?: ExternalChecker<z.infer<TSchema>>;
659
+ /** Deep validation rules keyed by source type (replaces externalChecker) */
660
+ protected deepValidation?: DeepValidationConfig<z.infer<TSchema>>;
661
+ /** Lookup key overrides per source type (when spec ID differs from external identifier) */
662
+ protected lookupKeys?: LookupKeyConfig<z.infer<TSchema>>;
609
663
  /** Coverage checker (optional) */
610
664
  protected coverageChecker?: CoverageChecker<z.infer<TSchema>>;
611
665
  /** Model level (set in _models/) */
@@ -683,6 +737,19 @@ declare abstract class Model<TSchema extends ZodType> {
683
737
  * Get coverage checker
684
738
  */
685
739
  getCoverageChecker(): CoverageChecker<z.infer<TSchema>> | undefined;
740
+ /**
741
+ * Get deep validation config
742
+ */
743
+ getDeepValidation(): DeepValidationConfig<z.infer<TSchema>> | undefined;
744
+ /**
745
+ * Get lookup key config
746
+ */
747
+ getLookupKeys(): LookupKeyConfig<z.infer<TSchema>> | undefined;
748
+ /**
749
+ * Resolve the lookup key for a spec and source type.
750
+ * Returns the lookup key if an override is defined, otherwise spec.id.
751
+ */
752
+ resolveLookupKey(spec: z.infer<TSchema>, sourceType: string): string;
686
753
  /**
687
754
  * Get lint rules
688
755
  */
@@ -791,6 +858,45 @@ interface ArtifactConfig {
791
858
  /** Content search patterns (RegExp). First capture group = spec IDs (comma or space separated) */
792
859
  contentPatterns?: RegExp[];
793
860
  }
861
+ /** A single match found by a source scanner */
862
+ interface SourceMatch {
863
+ /** Matched spec ID */
864
+ specId: string;
865
+ /** Match location description (path key, table name, file:line, etc.) */
866
+ location: string;
867
+ /** Parsed object context for deep validation (e.g. OpenAPI operation, DDL table) */
868
+ context?: unknown;
869
+ }
870
+ /**
871
+ * Source scanner plugin interface.
872
+ * Built-in scanners exist for 'openapi', 'ddl', and 'annotation'.
873
+ * Users can provide custom scanners for additional file types.
874
+ */
875
+ interface SourceScanner {
876
+ /**
877
+ * Search for spec IDs in a parsed document or raw content.
878
+ * @param content - Parsed document (object for openapi/ddl) or raw string
879
+ * @param specIds - Set of all known spec IDs to search for
880
+ * @param filePath - Path to the source file being scanned
881
+ * @returns Array of matches found
882
+ */
883
+ findSpecIds(content: unknown, specIds: string[], filePath: string): SourceMatch[];
884
+ }
885
+ /** Source configuration for global scan */
886
+ interface SourceConfig {
887
+ /** Source type identifier. Built-in: 'openapi', 'ddl', 'annotation' */
888
+ type: string;
889
+ /** File path glob patterns to scan */
890
+ paths: string[];
891
+ /** Exclusion patterns */
892
+ exclude?: string[];
893
+ /** Relation type: how matches relate to specs */
894
+ relation: 'implements' | 'verifiedBy';
895
+ /** Content search patterns (for annotation type) */
896
+ contentPatterns?: RegExp[];
897
+ /** Custom scanner plugin (required when type is not a built-in) */
898
+ scanner?: SourceScanner;
899
+ }
794
900
  /**
795
901
  * speckeeper configuration type
796
902
  */
@@ -837,6 +943,8 @@ interface SpeckeeperConfigInput {
837
943
  };
838
944
  /** Artifact scan configurations keyed by artifact class (e.g. 'test', 'typescript', 'openapi') */
839
945
  artifacts?: Record<string, ArtifactConfig>;
946
+ /** Global source definitions for spec ID scanning */
947
+ sources?: SourceConfig[];
840
948
  }
841
949
  /**
842
950
  * Resolved speckeeper configuration
@@ -967,4 +1075,4 @@ declare function createLintRule<T>(config: {
967
1075
  */
968
1076
  declare function loadSpeckeeperConfig(configPath?: string): Promise<ResolvedSpeckeeperConfig | null>;
969
1077
 
970
- export { detectCycles as $, type ArtifactConfig as A, type BaseModelInstance as B, type CheckContext as C, ReferenceDefinitionSchema as D, type ExportContext as E, type Relation as F, RelationSchema as G, type RelationValidationError as H, type InferModelType as I, type JsonSchemaExporter as J, RelationsFieldSchema as K, type LintContext as L, type ModelDefinition as M, type RenderContext as N, type Renderer as O, type ResolvedSpeckeeperConfig as P, type SpecModule as Q, RELATION_CONSTRAINTS as R, type SpecEntry as S, type SpeckeeperConfigInput as T, buildRegistryFromConfig as U, createLintRule as V, createMarkdownExporter as W, createMermaidExporter as X, defineConfig as Y, defineModel as Z, defineSpecs as _, type CheckResult$1 as a, findModelTypeFromConfig as a0, getLevelIndex as a1, getSpecsFromConfig as a2, inferModelIdFromSpecId as a3, loadSpeckeeperConfig as a4, mergeSpecs as a5, validateRelationLevel as a6, type MetaModelRegistry as b, type LintRule$1 as c, type LintIssue as d, type CheckError as e, CheckErrorSchema as f, type CheckResult as g, CheckResultSchema as h, type CheckWarning as i, CheckWarningSchema as j, type CoverageChecker as k, type CoverageResult as l, type Exporter as m, type ExternalChecker as n, LintIssueSchema as o, type LintResult as p, type LintRule as q, type MarkdownExporter as r, type MergedDesign as s, type MermaidExporter as t, type MetaModelConfig as u, Model as v, type ModelDefinitionInput as w, type ModelLevel as x, RELATION_TYPES as y, type ReferenceDefinition as z };
1078
+ export { type SpeckeeperConfigInput as $, type ArtifactConfig as A, type BaseModelInstance as B, type CheckContext as C, type DDLValidationMapping as D, type ExportContext as E, type ModelDefinitionInput as F, type ModelLevel as G, RELATION_TYPES as H, type InferModelType as I, type JsonSchemaExporter as J, type ReferenceDefinition as K, type LintContext as L, type ModelDefinition as M, ReferenceDefinitionSchema as N, type OpenAPIValidationMapping as O, type Relation as P, RelationSchema as Q, RELATION_CONSTRAINTS as R, type SourceConfig as S, type RelationValidationError as T, RelationsFieldSchema as U, type RenderContext as V, type Renderer as W, type ResolvedSpeckeeperConfig as X, type SourceMatch as Y, type SourceScanner as Z, type SpecModule as _, type CheckResult$1 as a, buildRegistryFromConfig as a0, createLintRule as a1, createMarkdownExporter as a2, createMermaidExporter as a3, defineConfig as a4, defineModel as a5, defineSpecs as a6, detectCycles as a7, findModelTypeFromConfig as a8, getLevelIndex as a9, getSpecsFromConfig as aa, inferModelIdFromSpecId as ab, loadSpeckeeperConfig as ac, mergeSpecs as ad, validateRelationLevel as ae, type MetaModelRegistry as b, type LintRule$1 as c, type LintIssue as d, type SpecEntry as e, type CheckError as f, CheckErrorSchema as g, type CheckResult as h, CheckResultSchema as i, type CheckWarning as j, CheckWarningSchema as k, type CoverageChecker as l, type CoverageResult as m, type DeepValidationConfig as n, type DeepValidationRule as o, type Exporter as p, type ExternalChecker as q, LintIssueSchema as r, type LintResult as s, type LintRule as t, type LookupKeyConfig as u, type MarkdownExporter as v, type MergedDesign as w, type MermaidExporter as x, type MetaModelConfig as y, Model as z };
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { q as LintRule, m as Exporter, n as ExternalChecker, k as CoverageChecker, A as ArtifactConfig } from '../config-api-U2pt1aHJ.js';
2
+ import { t as LintRule, p as Exporter, l as CoverageChecker, A as ArtifactConfig, Y as SourceMatch, Z as SourceScanner, n as DeepValidationConfig, h as CheckResult, S as SourceConfig } from '../config-api-CfxXt9Zt.js';
3
3
 
4
4
  /**
5
5
  * Core DSL — Base spec schema
@@ -116,37 +116,9 @@ declare function markdownExporter<T extends {
116
116
  id: string;
117
117
  }>(config: MarkdownExporterConfig<T>): Exporter<T>;
118
118
 
119
- interface TestCheckerConfig<T> {
120
- sourcePath?: (spec: T) => string;
121
- }
122
- /**
123
- * Creates an ExternalChecker that verifies test file existence and spec ID references.
124
- */
125
- declare function testChecker<T extends {
126
- id: string;
127
- }>(config?: TestCheckerConfig<T>): ExternalChecker<T>;
128
119
  type AnnotationRelationType = 'verifiedBy' | 'implements' | 'traces';
129
- interface AnnotationCheckEntry {
130
- artifact: string;
131
- relationType: AnnotationRelationType;
132
- contentPatterns?: RegExp[];
133
- checker?: ExternalChecker<{
134
- id: string;
135
- }>;
136
- }
137
- interface AnnotationCheckerConfig<_T extends {
138
- id: string;
139
- }> {
140
- artifact?: string;
141
- relationType?: AnnotationRelationType;
142
- checks?: AnnotationCheckEntry[];
143
- contentPatterns?: RegExp[];
144
- }
145
120
  declare function setArtifactsConfig(config: Record<string, ArtifactConfig>): void;
146
121
  declare function getArtifactsConfig(): Record<string, ArtifactConfig> | undefined;
147
- declare function annotationChecker<T extends {
148
- id: string;
149
- }>(config?: AnnotationCheckerConfig<T>): ExternalChecker<T>;
150
122
  interface AnnotationCoverageConfig {
151
123
  artifact: string;
152
124
  relationType: AnnotationRelationType;
@@ -156,64 +128,12 @@ interface AnnotationCoverageConfig {
156
128
  declare function annotationCoverage<T extends {
157
129
  id: string;
158
130
  }>(config: AnnotationCoverageConfig): CoverageChecker<T>;
159
- interface OpenAPICheckerConfig<T> {
160
- sourcePath?: (spec: T) => string;
161
- mapper: (spec: T) => {
162
- path: string;
163
- method?: string;
164
- parameters?: Array<{
165
- name: string;
166
- in?: string;
167
- type?: string;
168
- }>;
169
- responseProperties?: Array<{
170
- name: string;
171
- type?: string;
172
- }>;
173
- };
174
- }
175
- /**
176
- * Creates an ExternalChecker that verifies consistency with an OpenAPI spec file.
177
- *
178
- * Three validation levels:
179
- * 1. Existence: spec ID found in operationId, path segment, schema name, or x-spec-id
180
- * 2. Structural: HTTP method matches the matched path
181
- * 3. Type: parameter/response property names and types match
182
- */
183
- declare function externalOpenAPIChecker<T extends {
184
- id: string;
185
- }>(config?: OpenAPICheckerConfig<T>): ExternalChecker<T>;
186
- interface SqlSchemaCheckerConfig<T> {
187
- sourcePath?: (spec: T) => string;
188
- mapper: (spec: T) => {
189
- tableName: string;
190
- columns?: Array<{
191
- name: string;
192
- type?: string;
193
- }>;
194
- };
195
- checkTypes?: boolean;
196
- }
197
- /**
198
- * Creates an ExternalChecker that verifies consistency with a SQL schema (DDL).
199
- *
200
- * Three validation levels:
201
- * 1. Existence: table name found in DDL
202
- * 2. Structural: column names exist in the DDL table
203
- * 3. Type: column types use containment-based comparison
204
- */
205
- declare function externalSqlSchemaChecker<T extends {
206
- id: string;
207
- }>(config?: SqlSchemaCheckerConfig<T>): ExternalChecker<T>;
208
131
  interface RelationCoverageConfig {
209
132
  targetModel: string;
210
133
  description: string;
211
134
  relationType?: string;
212
135
  targetPrefix?: string;
213
136
  }
214
- /**
215
- * Creates a CoverageChecker that computes coverage of a target model via relations.
216
- */
217
137
  declare function relationCoverage<T extends {
218
138
  id: string;
219
139
  relations?: Array<{
@@ -281,4 +201,52 @@ declare const VerifiedByRelationSchema: z.ZodObject<{
281
201
  }>;
282
202
  type VerifiedByRelation = z.infer<typeof VerifiedByRelationSchema>;
283
203
 
284
- export { type AnnotationCheckEntry, type AnnotationCheckerConfig, type AnnotationCoverageConfig, type BaseSpec, type ImplementsRelation, ImplementsRelationSchema, type MarkdownExporterConfig, type VerifiedByRelation, VerifiedByRelationSchema, annotationChecker, annotationCoverage, arrayMinLength, baseSpecSchema, childIdFormat, externalOpenAPIChecker, externalSqlSchemaChecker, getArtifactsConfig, idFormat, isTypeContainedBy, markdownExporter, relationCoverage, requireField, setArtifactsConfig, testChecker };
204
+ interface GlobalScanMatch extends SourceMatch {
205
+ /** Which source config produced this match */
206
+ sourceType: string;
207
+ /** Relation type from the source config */
208
+ relation: 'implements' | 'verifiedBy';
209
+ /** File path where the match was found */
210
+ filePath: string;
211
+ }
212
+ type GlobalScanResult = Map<string, GlobalScanMatch[]>;
213
+ declare const openapiScanner: SourceScanner;
214
+ declare const ddlScanner: SourceScanner;
215
+ declare const annotationScanner: SourceScanner;
216
+ /**
217
+ * Create an annotation scanner with custom content patterns.
218
+ */
219
+ declare function createAnnotationScanner(contentPatterns: RegExp[]): SourceScanner;
220
+ interface ScanWarning {
221
+ message: string;
222
+ sourceType: string;
223
+ filePath?: string;
224
+ }
225
+ interface GlobalScanOutput {
226
+ matches: GlobalScanResult;
227
+ warnings: ScanWarning[];
228
+ }
229
+ /**
230
+ * Lookup key map: specId -> Record<sourceType, lookupKey>.
231
+ * When a model's spec ID differs from the external identifier
232
+ * (e.g. entity "user" vs DDL table "users"), the check command
233
+ * builds this map so the scanner searches for the correct key.
234
+ */
235
+ type LookupKeyMap = Map<string, Record<string, string>>;
236
+ /**
237
+ * Run global scan across all configured sources.
238
+ * Returns a map of specId -> matches for all spec IDs found.
239
+ *
240
+ * @param sources - Source configurations to scan
241
+ * @param specIds - All known spec IDs
242
+ * @param basePath - Base directory for resolving file paths
243
+ * @param lookupKeyMap - Optional per-spec, per-source-type key overrides
244
+ */
245
+ declare function runGlobalScan(sources: SourceConfig[], specIds: string[], basePath?: string, lookupKeyMap?: LookupKeyMap): GlobalScanOutput;
246
+ /**
247
+ * Run deep validation for a spec against its matched sources.
248
+ * Uses the model's deepValidation config to perform Level 2/3 checks.
249
+ */
250
+ declare function runDeepValidation(specId: string, matches: GlobalScanMatch[], deepValidation: DeepValidationConfig<any>, spec: unknown): CheckResult;
251
+
252
+ export { type AnnotationCoverageConfig, type BaseSpec, type GlobalScanMatch, type GlobalScanOutput, type GlobalScanResult, type ImplementsRelation, ImplementsRelationSchema, type LookupKeyMap, type MarkdownExporterConfig, type ScanWarning, type VerifiedByRelation, VerifiedByRelationSchema, annotationCoverage, annotationScanner, arrayMinLength, baseSpecSchema, childIdFormat, createAnnotationScanner, ddlScanner, getArtifactsConfig, idFormat, isTypeContainedBy, markdownExporter, openapiScanner, relationCoverage, requireField, runDeepValidation, runGlobalScan, setArtifactsConfig };