speckeeper 0.10.1 → 0.11.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.
@@ -848,6 +848,26 @@ declare function getSpecsFromConfig(specs: SpecEntry[] | undefined, modelId: str
848
848
  * Pure function — no global state.
849
849
  */
850
850
  declare function findModelTypeFromConfig(specs: SpecEntry[] | undefined, specId: string): string | null;
851
+ /**
852
+ * Load spec data from a YAML or JSON file.
853
+ * Supports two formats:
854
+ * - Single-model shorthand: `{ model: "term", specs: [...] }`
855
+ * - Multi-model entries: `{ entries: [{ model: "...", specs: [...] }, ...] }`
856
+ *
857
+ * Each spec is validated against the model's Zod schema.
858
+ *
859
+ * @param yamlPath - Path to the .yaml / .yml / .json file
860
+ * @param models - Array of Model instances to resolve `model` field against
861
+ */
862
+ declare function loadYamlSpecs(yamlPath: string, models: Model<any>[]): SpecModule;
863
+ /**
864
+ * Load all YAML / JSON spec files from a directory.
865
+ * Scans for `*.yaml`, `*.yml`, `*.json` files, excluding `_models/` subdirectory.
866
+ *
867
+ * @param dirPath - Directory to scan (typically `design/`)
868
+ * @param models - Array of Model instances
869
+ */
870
+ declare function loadYamlDir(dirPath: string, models: Model<any>[]): SpecModule[];
851
871
 
852
872
  /** Artifact scan configuration */
853
873
  interface ArtifactConfig {
@@ -1080,4 +1100,4 @@ declare function createLintRule<T>(config: {
1080
1100
  */
1081
1101
  declare function loadSpeckeeperConfig(configPath?: string): Promise<ResolvedSpeckeeperConfig | null>;
1082
1102
 
1083
- 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 };
1103
+ 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, loadYamlDir as ad, loadYamlSpecs as ae, mergeSpecs as af, validateRelationLevel as ag, 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 { 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-CLVjdgIP.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-coyCX1SB.js';
3
3
 
4
4
  /**
5
5
  * Core DSL — Base spec schema
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { C as CheckContext, a as CheckResult, E as ExportContext, M as ModelDefinition, b as MetaModelRegistry, L as LintContext, c as LintRule, d as LintIssue, S as SourceConfig, e as SpecEntry } from './config-api-CLVjdgIP.js';
3
- export { A as ArtifactConfig, B as BaseModelInstance, f as CheckError, g as CheckErrorSchema, h as CheckResult, i as CheckResultSchema, j as CheckWarning, k as CheckWarningSchema, l as CoverageChecker, m as CoverageResult, D as DDLValidationMapping, n as DeepValidationConfig, o as DeepValidationRule, p as Exporter, q as ExternalChecker, I as InferModelType, J as JsonSchemaExporter, r as LintIssueSchema, s as LintResult, t as LintRule, u as LookupKeyConfig, v as MarkdownExporter, w as MergedDesign, x as MermaidExporter, y as MetaModelConfig, z as Model, F as ModelDefinitionInput, G as ModelLevel, O as OpenAPIValidationMapping, R as RELATION_CONSTRAINTS, H as RELATION_TYPES, K as ReferenceDefinition, N as ReferenceDefinitionSchema, P as Relation, Q as RelationSchema, T as RelationValidationError, U as RelationsFieldSchema, V as RenderContext, W as Renderer, X as ResolvedSpeckeeperConfig, Y as SourceMatch, Z as SourceScanner, _ as SpecModule, $ as SpeckeeperConfigInput, a0 as buildRegistryFromConfig, a1 as createLintRule, a2 as createMarkdownExporter, a3 as createMermaidExporter, a4 as defineConfig, a5 as defineModel, a6 as defineSpecs, a7 as detectCycles, a8 as findModelTypeFromConfig, a9 as getLevelIndex, aa as getSpecsFromConfig, ab as inferModelIdFromSpecId, ac as loadSpeckeeperConfig, ad as mergeSpecs, ae as validateRelationLevel } from './config-api-CLVjdgIP.js';
2
+ import { C as CheckContext, a as CheckResult, E as ExportContext, M as ModelDefinition, b as MetaModelRegistry, L as LintContext, c as LintRule, d as LintIssue, S as SourceConfig, e as SpecEntry } from './config-api-coyCX1SB.js';
3
+ export { A as ArtifactConfig, B as BaseModelInstance, f as CheckError, g as CheckErrorSchema, h as CheckResult, i as CheckResultSchema, j as CheckWarning, k as CheckWarningSchema, l as CoverageChecker, m as CoverageResult, D as DDLValidationMapping, n as DeepValidationConfig, o as DeepValidationRule, p as Exporter, q as ExternalChecker, I as InferModelType, J as JsonSchemaExporter, r as LintIssueSchema, s as LintResult, t as LintRule, u as LookupKeyConfig, v as MarkdownExporter, w as MergedDesign, x as MermaidExporter, y as MetaModelConfig, z as Model, F as ModelDefinitionInput, G as ModelLevel, O as OpenAPIValidationMapping, R as RELATION_CONSTRAINTS, H as RELATION_TYPES, K as ReferenceDefinition, N as ReferenceDefinitionSchema, P as Relation, Q as RelationSchema, T as RelationValidationError, U as RelationsFieldSchema, V as RenderContext, W as Renderer, X as ResolvedSpeckeeperConfig, Y as SourceMatch, Z as SourceScanner, _ as SpecModule, $ as SpeckeeperConfigInput, a0 as buildRegistryFromConfig, a1 as createLintRule, a2 as createMarkdownExporter, a3 as createMermaidExporter, a4 as defineConfig, a5 as defineModel, a6 as defineSpecs, a7 as detectCycles, a8 as findModelTypeFromConfig, a9 as getLevelIndex, aa as getSpecsFromConfig, ab as inferModelIdFromSpecId, ac as loadSpeckeeperConfig, ad as loadYamlDir, ae as loadYamlSpecs, af as mergeSpecs, ag as validateRelationLevel } from './config-api-coyCX1SB.js';
4
4
 
5
5
  declare const PhaseSchema: z.ZodEnum<["REQ", "HLD", "LLD", "IMPL", "OPS", "CI"]>;
6
6
  type Phase = z.infer<typeof PhaseSchema>;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
3
- import { resolve, join, dirname } from 'path';
2
+ import { readFileSync, readdirSync, statSync, existsSync, mkdirSync, writeFileSync } from 'fs';
3
+ import { extname, join, resolve, dirname } from 'path';
4
4
  import { parse } from 'yaml';
5
5
  import { createHash } from 'crypto';
6
6
  import { glob } from 'glob';
@@ -645,6 +645,78 @@ function findModelTypeFromConfig(specs, specId) {
645
645
  }
646
646
  return null;
647
647
  }
648
+ function isMultiModelFormat(data) {
649
+ return "entries" in data && Array.isArray(data.entries);
650
+ }
651
+ function resolveModel(modelId, models, filePath) {
652
+ const found = models.find((m) => m.id === modelId);
653
+ if (!found) {
654
+ const available = models.map((m) => m.id).join(", ");
655
+ throw new Error(
656
+ `Unknown model "${modelId}" in ${filePath}. Available models: ${available}`
657
+ );
658
+ }
659
+ return found;
660
+ }
661
+ function validateSpecs(model, specs, filePath) {
662
+ const validated = [];
663
+ for (let i = 0; i < specs.length; i++) {
664
+ const raw = specs[i];
665
+ const result = model.safeParse(raw);
666
+ if (!result.success) {
667
+ const specId = raw?.id ?? `[index ${i}]`;
668
+ const issues = result.error.issues.map((iss) => ` - ${iss.path.join(".")}: ${iss.message}`).join("\n");
669
+ throw new Error(
670
+ `Validation failed for spec "${specId}" (model: ${model.id}) in ${filePath}:
671
+ ${issues}`
672
+ );
673
+ }
674
+ validated.push(result.data);
675
+ }
676
+ return validated;
677
+ }
678
+ function loadYamlSpecs(yamlPath, models) {
679
+ const ext = extname(yamlPath).toLowerCase();
680
+ const raw = readFileSync(yamlPath, "utf-8");
681
+ let data;
682
+ try {
683
+ data = ext === ".json" ? JSON.parse(raw) : parse(raw);
684
+ } catch (err) {
685
+ throw new Error(
686
+ `Failed to parse ${yamlPath}: ${err instanceof Error ? err.message : String(err)}`
687
+ );
688
+ }
689
+ const groups = isMultiModelFormat(data) ? data.entries : [data];
690
+ const entries = groups.map((group) => {
691
+ const model = resolveModel(group.model, models, yamlPath);
692
+ const validatedData = validateSpecs(model, group.specs, yamlPath);
693
+ return { model, data: validatedData };
694
+ });
695
+ return { entries };
696
+ }
697
+ function loadYamlDir(dirPath, models) {
698
+ const YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yaml", ".yml", ".json"]);
699
+ const results = [];
700
+ let entries;
701
+ try {
702
+ entries = readdirSync(dirPath);
703
+ } catch {
704
+ return results;
705
+ }
706
+ for (const entry of entries) {
707
+ if (entry === "_models") continue;
708
+ const fullPath = join(dirPath, entry);
709
+ const ext = extname(entry).toLowerCase();
710
+ if (!YAML_EXTENSIONS.has(ext)) continue;
711
+ try {
712
+ if (!statSync(fullPath).isFile()) continue;
713
+ } catch {
714
+ continue;
715
+ }
716
+ results.push(loadYamlSpecs(fullPath, models));
717
+ }
718
+ return results;
719
+ }
648
720
 
649
721
  // src/core/model-registry.ts
650
722
  var globalRegistry = {
@@ -1180,6 +1252,6 @@ function generateSpecsPath(baseDir, category, filename) {
1180
1252
  return join(baseDir, category, filename);
1181
1253
  }
1182
1254
 
1183
- export { CheckErrorSchema, CheckResultSchema, CheckWarningSchema, ConcretizationSlotSchema, ID_PATTERNS, LinkSchema, LintIssueSchema, Model, PhaseSchema, PrioritySchema, RELATION_CONSTRAINTS, RELATION_TYPES, ReferenceDefinitionSchema, RelationSchema, RelationsFieldSchema, batchWriteFiles, buildRegistryFromConfig, checkBatchDrift, checkExternalSsot, checkFileDrift, checkReferenceIntegrity, computeHash, createAPIRefId, createActorId, createBatchRefId, createBoundaryId, createComponentId, createDTORequirementId, createEntityId, createErrorCaseId, createEventRequirementId, createFormId, createIaCRefId, createLayerId, createLintRule, createMarkdownExporter, createMermaidExporter, createProcessFlowId, createRelationId, createRequirementId, createRuleId, createScreenId, createStateId, createTableRefId, createTermId, createTransitionId, createUIComponentId, createUseCaseId, defineConfig, defineModel, defineSpecs, detectCycles, ensureDir, exportAllModels, exportMarkdown, exportMermaid, findConfigFile, findDefinitionFiles, findFiles, findModelTypeFromConfig, findTypeScriptFiles, generateDocsPath, generateSpecsPath, getAllInstances, getAllModelDefinitions, getAllModelInstances, getExpectedOutputDirs, getGlobalModelRegistry, getLevelIndex, getModelDefinition, getModelInstance, getModelRegistryStats, getOutputPaths, getSpecsFromConfig, inferModelIdFromSpecId, lintAllModels, lintModel, loadConfig, loadSpeckeeperConfig, mergeSpecs, registerModelDefinition, registerModelDefinitions, registerModelInstance, resetModelInstances, resetModelRegistry, resolveReference, validateConfig, validateOutputPaths, validateRelationLevel, writeFile, writeJsonFile };
1255
+ export { CheckErrorSchema, CheckResultSchema, CheckWarningSchema, ConcretizationSlotSchema, ID_PATTERNS, LinkSchema, LintIssueSchema, Model, PhaseSchema, PrioritySchema, RELATION_CONSTRAINTS, RELATION_TYPES, ReferenceDefinitionSchema, RelationSchema, RelationsFieldSchema, batchWriteFiles, buildRegistryFromConfig, checkBatchDrift, checkExternalSsot, checkFileDrift, checkReferenceIntegrity, computeHash, createAPIRefId, createActorId, createBatchRefId, createBoundaryId, createComponentId, createDTORequirementId, createEntityId, createErrorCaseId, createEventRequirementId, createFormId, createIaCRefId, createLayerId, createLintRule, createMarkdownExporter, createMermaidExporter, createProcessFlowId, createRelationId, createRequirementId, createRuleId, createScreenId, createStateId, createTableRefId, createTermId, createTransitionId, createUIComponentId, createUseCaseId, defineConfig, defineModel, defineSpecs, detectCycles, ensureDir, exportAllModels, exportMarkdown, exportMermaid, findConfigFile, findDefinitionFiles, findFiles, findModelTypeFromConfig, findTypeScriptFiles, generateDocsPath, generateSpecsPath, getAllInstances, getAllModelDefinitions, getAllModelInstances, getExpectedOutputDirs, getGlobalModelRegistry, getLevelIndex, getModelDefinition, getModelInstance, getModelRegistryStats, getOutputPaths, getSpecsFromConfig, inferModelIdFromSpecId, lintAllModels, lintModel, loadConfig, loadSpeckeeperConfig, loadYamlDir, loadYamlSpecs, mergeSpecs, registerModelDefinition, registerModelDefinitions, registerModelInstance, resetModelInstances, resetModelRegistry, resolveReference, validateConfig, validateOutputPaths, validateRelationLevel, writeFile, writeJsonFile };
1184
1256
  //# sourceMappingURL=index.js.map
1185
1257
  //# sourceMappingURL=index.js.map