@contractspec/bundle.workspace 1.52.0 → 1.53.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.
- package/dist/adapters/ai.d.mts +2 -2
- package/dist/adapters/ai.d.mts.map +1 -1
- package/dist/adapters/ai.mjs.map +1 -1
- package/dist/adapters/factory.d.mts +2 -2
- package/dist/adapters/factory.d.mts.map +1 -1
- package/dist/adapters/factory.mjs +3 -14
- package/dist/adapters/factory.mjs.map +1 -1
- package/dist/adapters/fs.bun.d.mts +11 -0
- package/dist/adapters/fs.bun.d.mts.map +1 -0
- package/dist/adapters/fs.bun.mjs +81 -0
- package/dist/adapters/fs.bun.mjs.map +1 -0
- package/dist/adapters/fs.d.mts +2 -8
- package/dist/adapters/fs.d.mts.map +1 -1
- package/dist/adapters/fs.mjs +4 -88
- package/dist/adapters/fs.mjs.map +1 -1
- package/dist/adapters/fs.node.d.mts +11 -0
- package/dist/adapters/fs.node.d.mts.map +1 -0
- package/dist/adapters/fs.node.mjs +84 -0
- package/dist/adapters/fs.node.mjs.map +1 -0
- package/dist/adapters/index.d.mts +3 -1
- package/dist/adapters/index.mjs +3 -1
- package/dist/ai/agents/index.d.mts +6 -0
- package/dist/ai/agents/orchestrator.d.mts +4 -4
- package/dist/ai/agents/orchestrator.d.mts.map +1 -1
- package/dist/ai/agents/orchestrator.mjs +5 -0
- package/dist/ai/agents/orchestrator.mjs.map +1 -1
- package/dist/ai/agents/simple-agent.d.mts +2 -2
- package/dist/ai/agents/simple-agent.d.mts.map +1 -1
- package/dist/ai/agents/simple-agent.mjs.map +1 -1
- package/dist/ai/agents/types.d.mts +4 -5
- package/dist/ai/agents/types.d.mts.map +1 -1
- package/dist/ai/agents/unified-adapter.mjs +70 -0
- package/dist/ai/agents/unified-adapter.mjs.map +1 -0
- package/dist/ai/index.d.mts +3 -3
- package/dist/ai/index.mjs +1 -2
- package/dist/ai/prompts/spec-creation.mjs +1 -1
- package/dist/ai/providers.d.mts +3 -18
- package/dist/ai/providers.d.mts.map +1 -1
- package/dist/ai/providers.mjs +2 -22
- package/dist/ai/providers.mjs.map +1 -1
- package/dist/index.d.mts +13 -8
- package/dist/index.mjs +11 -7
- package/dist/ports/ai.d.mts +7 -3
- package/dist/ports/ai.d.mts.map +1 -1
- package/dist/ports/index.d.mts +1 -1
- package/dist/registry.d.mts +15 -0
- package/dist/registry.d.mts.map +1 -0
- package/dist/registry.mjs +19 -0
- package/dist/registry.mjs.map +1 -0
- package/dist/services/action-drift/service.d.mts +11 -0
- package/dist/services/action-drift/service.d.mts.map +1 -0
- package/dist/services/action-drift/service.mjs +43 -0
- package/dist/services/action-drift/service.mjs.map +1 -0
- package/dist/services/action-drift/types.d.mts +23 -0
- package/dist/services/action-drift/types.d.mts.map +1 -0
- package/dist/services/action-pr/service.d.mts +17 -0
- package/dist/services/action-pr/service.d.mts.map +1 -0
- package/dist/services/action-pr/service.mjs +205 -0
- package/dist/services/action-pr/service.mjs.map +1 -0
- package/dist/services/action-pr/types.d.mts +67 -0
- package/dist/services/action-pr/types.d.mts.map +1 -0
- package/dist/services/build.d.mts +3 -2
- package/dist/services/build.d.mts.map +1 -1
- package/dist/services/build.mjs.map +1 -1
- package/dist/services/ci-check/checks/coverage.mjs +30 -41
- package/dist/services/ci-check/checks/coverage.mjs.map +1 -1
- package/dist/services/ci-check/checks/handlers.mjs +3 -3
- package/dist/services/ci-check/checks/handlers.mjs.map +1 -1
- package/dist/services/ci-check/checks/implementation.mjs +1 -1
- package/dist/services/ci-check/checks/implementation.mjs.map +1 -1
- package/dist/services/ci-check/checks/structure.mjs +5 -6
- package/dist/services/ci-check/checks/structure.mjs.map +1 -1
- package/dist/services/ci-check/checks/test-refs.mjs +19 -29
- package/dist/services/ci-check/checks/test-refs.mjs.map +1 -1
- package/dist/services/ci-check/checks/tests.mjs +3 -3
- package/dist/services/ci-check/checks/tests.mjs.map +1 -1
- package/dist/services/ci-check/ci-check-service.d.mts.map +1 -1
- package/dist/services/ci-check/ci-check-service.mjs +7 -12
- package/dist/services/ci-check/ci-check-service.mjs.map +1 -1
- package/dist/services/config.d.mts +3 -3
- package/dist/services/config.d.mts.map +1 -1
- package/dist/services/config.mjs +12 -34
- package/dist/services/config.mjs.map +1 -1
- package/dist/services/create/ai-generator.d.mts +3 -3
- package/dist/services/create/ai-generator.d.mts.map +1 -1
- package/dist/services/create/ai-generator.mjs +1 -1
- package/dist/services/create/ai-generator.mjs.map +1 -1
- package/dist/services/create/index.d.mts +4 -4
- package/dist/services/create/index.d.mts.map +1 -1
- package/dist/services/create/index.mjs.map +1 -1
- package/dist/services/docs/docs-service.mjs +16 -13
- package/dist/services/docs/docs-service.mjs.map +1 -1
- package/dist/services/extract.mjs +2 -10
- package/dist/services/extract.mjs.map +1 -1
- package/dist/services/implementation/discovery.d.mts.map +1 -1
- package/dist/services/implementation/discovery.mjs +6 -14
- package/dist/services/implementation/discovery.mjs.map +1 -1
- package/dist/services/implementation/index.d.mts +1 -1
- package/dist/services/implementation/index.mjs +1 -1
- package/dist/services/implementation/resolver/index.d.mts +8 -6
- package/dist/services/implementation/resolver/index.d.mts.map +1 -1
- package/dist/services/implementation/resolver/index.mjs +33 -31
- package/dist/services/implementation/resolver/index.mjs.map +1 -1
- package/dist/services/implementation/resolver/parsers.d.mts +1 -5
- package/dist/services/implementation/resolver/parsers.d.mts.map +1 -1
- package/dist/services/implementation/resolver/parsers.mjs +1 -19
- package/dist/services/implementation/resolver/parsers.mjs.map +1 -1
- package/dist/services/implementation/types.d.mts +3 -1
- package/dist/services/implementation/types.d.mts.map +1 -1
- package/dist/services/index.d.mts +5 -1
- package/dist/services/index.mjs +4 -2
- package/dist/services/list.d.mts +4 -3
- package/dist/services/list.d.mts.map +1 -1
- package/dist/services/list.mjs +4 -2
- package/dist/services/list.mjs.map +1 -1
- package/dist/services/sync.d.mts +2 -2
- package/dist/services/sync.d.mts.map +1 -1
- package/dist/services/sync.mjs.map +1 -1
- package/dist/services/test/test-generator-service.d.mts +1 -1
- package/dist/services/test/test-service.mjs +1 -1
- package/dist/services/validate/blueprint-validator.mjs +1 -1
- package/dist/services/validate/implementation-agent-validator.d.mts +2 -2
- package/dist/services/validate/implementation-agent-validator.d.mts.map +1 -1
- package/dist/services/validate/implementation-agent-validator.mjs.map +1 -1
- package/dist/services/validate/implementation-validator.d.mts +4 -3
- package/dist/services/validate/implementation-validator.d.mts.map +1 -1
- package/dist/services/validate/implementation-validator.mjs +4 -13
- package/dist/services/validate/implementation-validator.mjs.map +1 -1
- package/dist/services/validate/spec-validator.d.mts +1 -1
- package/dist/services/validate/spec-validator.d.mts.map +1 -1
- package/dist/services/validate/spec-validator.mjs +11 -7
- package/dist/services/validate/spec-validator.mjs.map +1 -1
- package/dist/services/validate/tenant-validator.mjs +1 -1
- package/dist/services/watch.d.mts +2 -2
- package/dist/services/watch.d.mts.map +1 -1
- package/dist/services/watch.mjs.map +1 -1
- package/dist/utils/filter.d.mts +10 -1
- package/dist/utils/filter.d.mts.map +1 -1
- package/dist/utils/filter.mjs +28 -1
- package/dist/utils/filter.mjs.map +1 -1
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +2 -1
- package/package.json +11 -9
- package/dist/ai/client.d.mts +0 -97
- package/dist/ai/client.d.mts.map +0 -1
- package/dist/ai/client.mjs +0 -189
- package/dist/ai/client.mjs.map +0 -1
- package/dist/types/config.d.mts +0 -34
- package/dist/types/config.d.mts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-service.mjs","names":[],"sources":["../../../src/services/docs/docs-service.ts"],"sourcesContent":["import path from 'path';\nimport {\n type DocBlock,\n
|
|
1
|
+
{"version":3,"file":"docs-service.mjs","names":[],"sources":["../../../src/services/docs/docs-service.ts"],"sourcesContent":["import path from 'path';\nimport {\n defaultDocRegistry,\n type DocBlock,\n} from '@contractspec/lib.contracts/docs';\nimport {\n convertSpecToDocBlock,\n loadSpecFromSource,\n scanAllSpecsFromSource,\n scanSpecSource,\n type SpecScanResult,\n} from '@contractspec/module.workspace';\nimport type { WorkspaceAdapters } from '../../ports/logger';\nimport { ModuleResolver } from '../modules/module-resolver';\n\nexport interface DocsServiceOptions {\n outputDir?: string;\n format?: 'markdown' | 'html' | 'json';\n rootPath?: string;\n}\n\nexport interface DocsServiceResult {\n blocks: DocBlock[];\n count: number;\n}\n\n/**\n * Generate documentation from spec files.\n */\nexport async function generateDocsFromSpecs(\n specFiles: string[],\n options: DocsServiceOptions,\n adapters: WorkspaceAdapters\n): Promise<DocsServiceResult> {\n const { fs, logger } = adapters;\n const blocks: DocBlock[] = [];\n\n logger.info(`Generating docs for ${specFiles.length} files...`);\n\n if (options.outputDir) {\n await fs.mkdir(options.outputDir);\n }\n\n // Initialize ModuleResolver\n const resolver = new ModuleResolver(adapters);\n // 1. Scan all specs to build the module index\n const scanResults: SpecScanResult[] = [];\n for (const file of specFiles) {\n try {\n const content = await fs.readFile(file);\n if (file.endsWith('packages/libs/contracts/src/app-config/spec.ts')) {\n console.log('coupable', file);\n }\n const results = scanAllSpecsFromSource(content, file);\n if (results.length > 0) {\n scanResults.push(...results);\n } else {\n // Fallback if no multi-specs found, try single scan logic\n const single = scanSpecSource(content, file);\n if (single.specType !== 'unknown') {\n scanResults.push(single);\n }\n }\n } catch (_err) {\n // ignore read errors\n }\n }\n\n resolver.initialize(scanResults);\n\n for (const file of specFiles) {\n try {\n const parsedList = await loadSpecFromSource(file);\n\n if (!parsedList?.length) {\n logger.warn(`Could not parse spec from ${file}`);\n continue;\n }\n\n for (const parsed of parsedList) {\n const block = convertSpecToDocBlock(parsed, {\n rootPath: options.rootPath,\n });\n // Register in global registry\n defaultDocRegistry.register(block);\n blocks.push(block);\n logger.debug(`Generated doc for ${block.id}`);\n\n if (!options.outputDir) {\n continue;\n }\n\n // Determine grouping based on module resolution\n const moduleDef = resolver.resolve(file);\n let targetDir = options.outputDir;\n\n if (moduleDef) {\n targetDir = path.join(options.outputDir, moduleDef.key);\n } else {\n targetDir = path.join(options.outputDir, '_common'); // Fallback for root-level specs\n }\n\n // Ensure subdirectory exists\n await fs.mkdir(targetDir);\n\n // Flattened structure: [module]/[docId].md\n const filename = `${block.id}.md`;\n const filePath = path.join(targetDir, filename);\n const generatedContent = `<!-- @generated - This file was generated by ContractSpec. Do not edit manually. -->\\n\\n${block.body}`;\n await fs.writeFile(filePath, generatedContent);\n }\n } catch (error) {\n logger.error(\n `Error processing ${file}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n if (options.outputDir) {\n logger.info(`Wrote ${blocks.length} doc files to ${options.outputDir}`);\n }\n\n return { blocks, count: blocks.length };\n}\n"],"mappings":";;;;;;;;;AA6BA,eAAsB,sBACpB,WACA,SACA,UAC4B;CAC5B,MAAM,EAAE,IAAI,WAAW;CACvB,MAAM,SAAqB,EAAE;AAE7B,QAAO,KAAK,uBAAuB,UAAU,OAAO,WAAW;AAE/D,KAAI,QAAQ,UACV,OAAM,GAAG,MAAM,QAAQ,UAAU;CAInC,MAAM,WAAW,IAAI,eAAe,SAAS;CAE7C,MAAM,cAAgC,EAAE;AACxC,MAAK,MAAM,QAAQ,UACjB,KAAI;EACF,MAAM,UAAU,MAAM,GAAG,SAAS,KAAK;AACvC,MAAI,KAAK,SAAS,iDAAiD,CACjE,SAAQ,IAAI,YAAY,KAAK;EAE/B,MAAM,UAAU,uBAAuB,SAAS,KAAK;AACrD,MAAI,QAAQ,SAAS,EACnB,aAAY,KAAK,GAAG,QAAQ;OACvB;GAEL,MAAM,SAAS,eAAe,SAAS,KAAK;AAC5C,OAAI,OAAO,aAAa,UACtB,aAAY,KAAK,OAAO;;UAGrB,MAAM;AAKjB,UAAS,WAAW,YAAY;AAEhC,MAAK,MAAM,QAAQ,UACjB,KAAI;EACF,MAAM,aAAa,MAAM,mBAAmB,KAAK;AAEjD,MAAI,CAAC,YAAY,QAAQ;AACvB,UAAO,KAAK,6BAA6B,OAAO;AAChD;;AAGF,OAAK,MAAM,UAAU,YAAY;GAC/B,MAAM,QAAQ,sBAAsB,QAAQ,EAC1C,UAAU,QAAQ,UACnB,CAAC;AAEF,sBAAmB,SAAS,MAAM;AAClC,UAAO,KAAK,MAAM;AAClB,UAAO,MAAM,qBAAqB,MAAM,KAAK;AAE7C,OAAI,CAAC,QAAQ,UACX;GAIF,MAAM,YAAY,SAAS,QAAQ,KAAK;GACxC,IAAI,YAAY,QAAQ;AAExB,OAAI,UACF,aAAY,KAAK,KAAK,QAAQ,WAAW,UAAU,IAAI;OAEvD,aAAY,KAAK,KAAK,QAAQ,WAAW,UAAU;AAIrD,SAAM,GAAG,MAAM,UAAU;GAGzB,MAAM,WAAW,GAAG,MAAM,GAAG;GAC7B,MAAM,WAAW,KAAK,KAAK,WAAW,SAAS;GAC/C,MAAM,mBAAmB,2FAA2F,MAAM;AAC1H,SAAM,GAAG,UAAU,UAAU,iBAAiB;;UAEzC,OAAO;AACd,SAAO,MACL,oBAAoB,KAAK,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACpF;;AAIL,KAAI,QAAQ,UACV,QAAO,KAAK,SAAS,OAAO,OAAO,gBAAgB,QAAQ,YAAY;AAGzE,QAAO;EAAE;EAAQ,OAAO,OAAO;EAAQ"}
|
|
@@ -8,17 +8,9 @@ async function extractContracts(adapters, options, cwd) {
|
|
|
8
8
|
const { source, outputDir } = options;
|
|
9
9
|
const sourcePath = fs.resolve(cwd ?? process.cwd(), source);
|
|
10
10
|
if (!await fs.exists(sourcePath)) throw new Error(`Source file not found: ${sourcePath}`);
|
|
11
|
-
const config = await loadWorkspaceConfig(fs, cwd);
|
|
12
|
-
const conventions = {
|
|
13
|
-
models: "models",
|
|
14
|
-
groupByFeature: false,
|
|
15
|
-
...config.conventions
|
|
16
|
-
};
|
|
17
11
|
const runConfig = {
|
|
18
|
-
...
|
|
19
|
-
outputDir
|
|
20
|
-
schemaFormat: config.schemaFormat ?? "zod",
|
|
21
|
-
conventions
|
|
12
|
+
...await loadWorkspaceConfig(fs, cwd),
|
|
13
|
+
outputDir
|
|
22
14
|
};
|
|
23
15
|
logger.info(`Extracting contracts from ${sourcePath} to ${outputDir}`);
|
|
24
16
|
return importFromOpenApiService(runConfig, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.mjs","names":[],"sources":["../../src/services/extract.ts"],"sourcesContent":["import type { WorkspaceAdapters } from '../ports/logger';\nimport { loadWorkspaceConfig } from './config';\nimport { importFromOpenApiService } from './openapi/index';\nimport type { OpenApiImportServiceResult } from './openapi/types';\n\nexport interface ExtractOptions {\n source: string;\n outputDir: string;\n}\n\nexport async function extractContracts(\n adapters: WorkspaceAdapters,\n options: ExtractOptions,\n cwd?: string\n): Promise<OpenApiImportServiceResult> {\n const { fs, logger } = adapters;\n const { source, outputDir } = options;\n\n // Verify source existence\n // We resolve source relative to CWD if checking locally, or absolute\n const sourcePath = fs.resolve(cwd ?? process.cwd(), source);\n if (!(await fs.exists(sourcePath))) {\n throw new Error(`Source file not found: ${sourcePath}`);\n }\n\n // Load Base Config\n const config = await loadWorkspaceConfig(fs, cwd);\n\n // Override config if needed or pass as options to import service\n // importFromOpenApiService takes (contractsrcConfig, importOptions, adapters)\n // We need to merge outputDir override if present.\n
|
|
1
|
+
{"version":3,"file":"extract.mjs","names":[],"sources":["../../src/services/extract.ts"],"sourcesContent":["import type { WorkspaceAdapters } from '../ports/logger';\nimport { loadWorkspaceConfig } from './config';\nimport { importFromOpenApiService } from './openapi/index';\nimport type { OpenApiImportServiceResult } from './openapi/types';\n\nexport interface ExtractOptions {\n source: string;\n outputDir: string;\n}\n\nexport async function extractContracts(\n adapters: WorkspaceAdapters,\n options: ExtractOptions,\n cwd?: string\n): Promise<OpenApiImportServiceResult> {\n const { fs, logger } = adapters;\n const { source, outputDir } = options;\n\n // Verify source existence\n // We resolve source relative to CWD if checking locally, or absolute\n const sourcePath = fs.resolve(cwd ?? process.cwd(), source);\n if (!(await fs.exists(sourcePath))) {\n throw new Error(`Source file not found: ${sourcePath}`);\n }\n\n // Load Base Config\n const config = await loadWorkspaceConfig(fs, cwd);\n\n // Override config if needed or pass as options to import service\n // importFromOpenApiService takes (contractsrcConfig, importOptions, adapters)\n // We need to merge outputDir override if present.\n\n const runConfig = {\n ...config,\n outputDir: outputDir, // CLI/Option override\n };\n\n logger.info(`Extracting contracts from ${sourcePath} to ${outputDir}`);\n\n return importFromOpenApiService(\n runConfig,\n {\n source: sourcePath,\n outputDir: outputDir,\n dryRun: false,\n },\n adapters\n );\n}\n"],"mappings":";;;;;AAUA,eAAsB,iBACpB,UACA,SACA,KACqC;CACrC,MAAM,EAAE,IAAI,WAAW;CACvB,MAAM,EAAE,QAAQ,cAAc;CAI9B,MAAM,aAAa,GAAG,QAAQ,OAAO,QAAQ,KAAK,EAAE,OAAO;AAC3D,KAAI,CAAE,MAAM,GAAG,OAAO,WAAW,CAC/B,OAAM,IAAI,MAAM,0BAA0B,aAAa;CAUzD,MAAM,YAAY;EAChB,GAPa,MAAM,oBAAoB,IAAI,IAAI;EAQpC;EACZ;AAED,QAAO,KAAK,6BAA6B,WAAW,MAAM,YAAY;AAEtE,QAAO,yBACL,WACA;EACE,QAAQ;EACG;EACX,QAAQ;EACT,EACD,SACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.mts","names":[],"sources":["../../../src/services/implementation/discovery.ts"],"sourcesContent":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"discovery.d.mts","names":[],"sources":["../../../src/services/implementation/discovery.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AA2KU,iBAvHM,uBAAA,CAuHN,QAAA,EAAA,MAAA,CAAA,EAvHiD,kBAuHjD;AAoCV;;;AAGuB,iBAtIP,qBAAA,CAsIO,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EAnIpB,kBAmIoB,EAAA;;;;iBA3CD,8BAAA;MAEJ;aACP,mBACR,QAAQ;;;;;iBAoCW,0BAAA;MACJ;aACP,mBACR,QAAQ,YAAY"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { DEFAULT_FS_IGNORES, DEFAULT_SPEC_PATTERNS } from "../../adapters/fs.mjs";
|
|
2
|
+
import "../../adapters/index.mjs";
|
|
3
|
+
|
|
1
4
|
//#region src/services/implementation/discovery.ts
|
|
2
5
|
/**
|
|
3
6
|
* Patterns for detecting spec references in source code.
|
|
@@ -81,25 +84,14 @@ function extractSpecReferences(code, filePath) {
|
|
|
81
84
|
/**
|
|
82
85
|
* Default glob patterns for implementation files.
|
|
83
86
|
*/
|
|
84
|
-
const DEFAULT_INCLUDE_PATTERNS = ["**/*.ts"
|
|
85
|
-
const DEFAULT_EXCLUDE_PATTERNS = [
|
|
86
|
-
"**/node_modules/**",
|
|
87
|
-
"**/dist/**",
|
|
88
|
-
"**/.git/**",
|
|
89
|
-
"**/*.d.ts",
|
|
90
|
-
"**/*.operation.ts",
|
|
91
|
-
"**/*.spec.ts",
|
|
92
|
-
"**/*.feature.ts",
|
|
93
|
-
"**/*.event.ts",
|
|
94
|
-
"**/*.presentation.ts"
|
|
95
|
-
];
|
|
87
|
+
const DEFAULT_INCLUDE_PATTERNS = ["**/*.ts(x)"];
|
|
96
88
|
/**
|
|
97
89
|
* Discover implementations that reference a specific spec.
|
|
98
90
|
*/
|
|
99
91
|
async function discoverImplementationsForSpec(specKey, adapters, options = {}) {
|
|
100
92
|
const { fs } = adapters;
|
|
101
93
|
const includePatterns = options.includePatterns ?? DEFAULT_INCLUDE_PATTERNS;
|
|
102
|
-
const excludePatterns = options.excludePatterns ??
|
|
94
|
+
const excludePatterns = options.excludePatterns ?? [...new Set([...DEFAULT_FS_IGNORES, ...DEFAULT_SPEC_PATTERNS])];
|
|
103
95
|
const allMatches = [];
|
|
104
96
|
for (const pattern of includePatterns) {
|
|
105
97
|
const files = await fs.glob({
|
|
@@ -120,7 +112,7 @@ async function discoverImplementationsForSpec(specKey, adapters, options = {}) {
|
|
|
120
112
|
async function discoverAllImplementations(adapters, options = {}) {
|
|
121
113
|
const { fs } = adapters;
|
|
122
114
|
const includePatterns = options.includePatterns ?? DEFAULT_INCLUDE_PATTERNS;
|
|
123
|
-
const excludePatterns = options.excludePatterns ??
|
|
115
|
+
const excludePatterns = options.excludePatterns ?? [...new Set([...DEFAULT_FS_IGNORES, ...DEFAULT_SPEC_PATTERNS])];
|
|
124
116
|
const specToImplementations = /* @__PURE__ */ new Map();
|
|
125
117
|
for (const pattern of includePatterns) {
|
|
126
118
|
const files = await fs.glob({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.mjs","names":[],"sources":["../../../src/services/implementation/discovery.ts"],"sourcesContent":["/**\n * Implementation auto-discovery service.\n *\n * Scans workspace files to find implementations that reference specs.\n * Uses regex-based pattern matching for performance (avoids full AST parsing).\n */\n\nimport type { FsAdapter } from '../../ports/fs';\nimport type { ImplementationType } from '@contractspec/lib.contracts';\nimport type { DiscoveryOptions, SpecReferenceMatch } from './types';\n\n/**\n * Patterns for detecting spec references in source code.\n */\nconst SPEC_REFERENCE_PATTERNS = {\n // import { SpecName } from './path'\n namedImport:\n /import\\s*\\{[^}]*\\b(\\w+(?:Spec|Contract|Command|Query))\\b[^}]*\\}\\s*from/g,\n // import SpecName from './path'\n defaultImport: /import\\s+(\\w+(?:Spec|Contract|Command|Query))\\s+from/g,\n // ContractHandler<typeof SpecName>\n contractHandler: /ContractHandler\\s*<\\s*typeof\\s+(\\w+)\\s*>/g,\n // typeof SpecName (generic usage)\n typeofSpec: /typeof\\s+(\\w+(?:Spec|Contract|Command|Query))\\b/g,\n // spec: SpecKey or spec = SpecKey\n specAssignment:\n /(?:spec|contract)\\s*[:=]\\s*(\\w+(?:Spec|Contract|Command|Query))\\b/gi,\n};\n\n/**\n * File patterns that indicate implementation types.\n */\nconst IMPLEMENTATION_TYPE_PATTERNS: Record<string, ImplementationType> = {\n '.handler.ts': 'handler',\n '.handler.tsx': 'handler',\n '.service.ts': 'service',\n '.service.tsx': 'service',\n '.test.ts': 'test',\n '.test.tsx': 'test',\n '.spec.ts': 'test',\n '.spec.tsx': 'test',\n '.component.tsx': 'component',\n '.tsx': 'component', // Default for TSX files\n '.form.tsx': 'form',\n '.hook.ts': 'hook',\n '.hook.tsx': 'hook',\n};\n\n/**\n * Infer implementation type from file path.\n */\nexport function inferImplementationType(filePath: string): ImplementationType {\n const lowerPath = filePath.toLowerCase();\n\n // Check specific patterns first (order matters)\n for (const [pattern, type] of Object.entries(IMPLEMENTATION_TYPE_PATTERNS)) {\n if (lowerPath.endsWith(pattern)) {\n return type;\n }\n }\n\n // Check directory patterns\n if (lowerPath.includes('/handlers/')) return 'handler';\n if (lowerPath.includes('/services/')) return 'service';\n if (lowerPath.includes('/components/')) return 'component';\n if (lowerPath.includes('/forms/')) return 'form';\n if (lowerPath.includes('/hooks/')) return 'hook';\n if (lowerPath.includes('/__tests__/')) return 'test';\n\n return 'other';\n}\n\n/**\n * Extract spec references from source code.\n */\nexport function extractSpecReferences(\n code: string,\n filePath: string\n): SpecReferenceMatch[] {\n const matches: SpecReferenceMatch[] = [];\n const seenSpecs = new Set<string>();\n\n // Helper to add unique matches\n const addMatch = (\n specKey: string,\n referenceType: SpecReferenceMatch['referenceType'],\n lineNumber?: number\n ) => {\n const key = `${specKey}:${referenceType}`;\n if (seenSpecs.has(key)) return;\n seenSpecs.add(key);\n\n matches.push({\n filePath,\n specKey,\n referenceType,\n lineNumber,\n inferredType: inferImplementationType(filePath),\n });\n };\n\n // Find line number for a match position\n const getLineNumber = (position: number): number => {\n const lines = code.substring(0, position).split('\\n');\n return lines.length;\n };\n\n // Check ContractHandler pattern (most specific)\n let match: RegExpExecArray | null;\n const handlerPattern = new RegExp(SPEC_REFERENCE_PATTERNS.contractHandler);\n while ((match = handlerPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'handler', getLineNumber(match.index));\n }\n }\n\n // Check typeof pattern\n const typeofPattern = new RegExp(SPEC_REFERENCE_PATTERNS.typeofSpec);\n while ((match = typeofPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'typeof', getLineNumber(match.index));\n }\n }\n\n // Check named imports\n const namedPattern = new RegExp(SPEC_REFERENCE_PATTERNS.namedImport);\n while ((match = namedPattern.exec(code)) !== null) {\n // Extract all spec names from the import statement\n const importBlock = match[0];\n const specNames = importBlock.match(\n /\\b(\\w+(?:Spec|Contract|Command|Query))\\b/g\n );\n if (specNames) {\n for (const name of specNames) {\n addMatch(name, 'import', getLineNumber(match.index));\n }\n }\n }\n\n // Check default imports\n const defaultPattern = new RegExp(SPEC_REFERENCE_PATTERNS.defaultImport);\n while ((match = defaultPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'import', getLineNumber(match.index));\n }\n }\n\n // Check spec assignments\n const assignPattern = new RegExp(SPEC_REFERENCE_PATTERNS.specAssignment);\n while ((match = assignPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'unknown', getLineNumber(match.index));\n }\n }\n\n return matches;\n}\n\n/**\n * Default glob patterns for implementation files.\n */\nconst DEFAULT_INCLUDE_PATTERNS = ['**/*.ts', '**/*.tsx'];\n\nconst DEFAULT_EXCLUDE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/.git/**',\n '**/*.d.ts',\n '**/*.operation.ts', // Skip spec files themselves\n '**/*.spec.ts', // Skip test spec files\n '**/*.feature.ts', // Skip feature files\n '**/*.event.ts', // Skip event spec files\n '**/*.presentation.ts', // Skip presentation files\n];\n\n/**\n * Discover implementations that reference a specific spec.\n */\nexport async function discoverImplementationsForSpec(\n specKey: string,\n adapters: { fs: FsAdapter },\n options: DiscoveryOptions = {}\n): Promise<SpecReferenceMatch[]> {\n const { fs } = adapters;\n const includePatterns = options.includePatterns ?? DEFAULT_INCLUDE_PATTERNS;\n const excludePatterns = options.excludePatterns ?? DEFAULT_EXCLUDE_PATTERNS;\n\n const allMatches: SpecReferenceMatch[] = [];\n\n // Scan each include pattern\n for (const pattern of includePatterns) {\n const files = await fs.glob({ pattern, ignore: excludePatterns });\n\n for (const filePath of files) {\n try {\n const content = await fs.readFile(filePath);\n const references = extractSpecReferences(content, filePath);\n\n // Filter to only references for the target spec\n const matchingRefs = references.filter(\n (ref) => ref.specKey === specKey\n );\n allMatches.push(...matchingRefs);\n } catch {\n // Skip files that can't be read\n }\n }\n }\n\n return allMatches;\n}\n\n/**\n * Discover all spec references in the workspace.\n * Returns a map of spec key to implementation references.\n */\nexport async function discoverAllImplementations(\n adapters: { fs: FsAdapter },\n options: DiscoveryOptions = {}\n): Promise<Map<string, SpecReferenceMatch[]>> {\n const { fs } = adapters;\n const includePatterns = options.includePatterns ?? DEFAULT_INCLUDE_PATTERNS;\n const excludePatterns = options.excludePatterns ?? DEFAULT_EXCLUDE_PATTERNS;\n\n const specToImplementations = new Map<string, SpecReferenceMatch[]>();\n\n // Scan each include pattern\n for (const pattern of includePatterns) {\n const files = await fs.glob({ pattern, ignore: excludePatterns });\n\n for (const filePath of files) {\n try {\n const content = await fs.readFile(filePath);\n const references = extractSpecReferences(content, filePath);\n\n // Group by spec key\n for (const ref of references) {\n const existing = specToImplementations.get(ref.specKey) ?? [];\n existing.push(ref);\n specToImplementations.set(ref.specKey, existing);\n }\n } catch {\n // Skip files that can't be read\n }\n }\n }\n\n return specToImplementations;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"discovery.mjs","names":[],"sources":["../../../src/services/implementation/discovery.ts"],"sourcesContent":["/**\n * Implementation auto-discovery service.\n *\n * Scans workspace files to find implementations that reference specs.\n * Uses regex-based pattern matching for performance (avoids full AST parsing).\n */\n\nimport type { FsAdapter } from '../../ports/fs';\nimport type { ImplementationType } from '@contractspec/lib.contracts';\nimport type { DiscoveryOptions, SpecReferenceMatch } from './types';\nimport { DEFAULT_FS_IGNORES, DEFAULT_SPEC_PATTERNS } from '../../adapters';\n\n/**\n * Patterns for detecting spec references in source code.\n */\nconst SPEC_REFERENCE_PATTERNS = {\n // import { SpecName } from './path'\n namedImport:\n /import\\s*\\{[^}]*\\b(\\w+(?:Spec|Contract|Command|Query))\\b[^}]*\\}\\s*from/g,\n // import SpecName from './path'\n defaultImport: /import\\s+(\\w+(?:Spec|Contract|Command|Query))\\s+from/g,\n // ContractHandler<typeof SpecName>\n contractHandler: /ContractHandler\\s*<\\s*typeof\\s+(\\w+)\\s*>/g,\n // typeof SpecName (generic usage)\n typeofSpec: /typeof\\s+(\\w+(?:Spec|Contract|Command|Query))\\b/g,\n // spec: SpecKey or spec = SpecKey\n specAssignment:\n /(?:spec|contract)\\s*[:=]\\s*(\\w+(?:Spec|Contract|Command|Query))\\b/gi,\n};\n\n/**\n * File patterns that indicate implementation types.\n */\nconst IMPLEMENTATION_TYPE_PATTERNS: Record<string, ImplementationType> = {\n '.handler.ts': 'handler',\n '.handler.tsx': 'handler',\n '.service.ts': 'service',\n '.service.tsx': 'service',\n '.test.ts': 'test',\n '.test.tsx': 'test',\n '.spec.ts': 'test',\n '.spec.tsx': 'test',\n '.component.tsx': 'component',\n '.tsx': 'component', // Default for TSX files\n '.form.tsx': 'form',\n '.hook.ts': 'hook',\n '.hook.tsx': 'hook',\n};\n\n/**\n * Infer implementation type from file path.\n */\nexport function inferImplementationType(filePath: string): ImplementationType {\n const lowerPath = filePath.toLowerCase();\n\n // Check specific patterns first (order matters)\n for (const [pattern, type] of Object.entries(IMPLEMENTATION_TYPE_PATTERNS)) {\n if (lowerPath.endsWith(pattern)) {\n return type;\n }\n }\n\n // Check directory patterns\n if (lowerPath.includes('/handlers/')) return 'handler';\n if (lowerPath.includes('/services/')) return 'service';\n if (lowerPath.includes('/components/')) return 'component';\n if (lowerPath.includes('/forms/')) return 'form';\n if (lowerPath.includes('/hooks/')) return 'hook';\n if (lowerPath.includes('/__tests__/')) return 'test';\n\n return 'other';\n}\n\n/**\n * Extract spec references from source code.\n */\nexport function extractSpecReferences(\n code: string,\n filePath: string\n): SpecReferenceMatch[] {\n const matches: SpecReferenceMatch[] = [];\n const seenSpecs = new Set<string>();\n\n // Helper to add unique matches\n const addMatch = (\n specKey: string,\n referenceType: SpecReferenceMatch['referenceType'],\n lineNumber?: number\n ) => {\n const key = `${specKey}:${referenceType}`;\n if (seenSpecs.has(key)) return;\n seenSpecs.add(key);\n\n matches.push({\n filePath,\n specKey,\n referenceType,\n lineNumber,\n inferredType: inferImplementationType(filePath),\n });\n };\n\n // Find line number for a match position\n const getLineNumber = (position: number): number => {\n const lines = code.substring(0, position).split('\\n');\n return lines.length;\n };\n\n // Check ContractHandler pattern (most specific)\n let match: RegExpExecArray | null;\n const handlerPattern = new RegExp(SPEC_REFERENCE_PATTERNS.contractHandler);\n while ((match = handlerPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'handler', getLineNumber(match.index));\n }\n }\n\n // Check typeof pattern\n const typeofPattern = new RegExp(SPEC_REFERENCE_PATTERNS.typeofSpec);\n while ((match = typeofPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'typeof', getLineNumber(match.index));\n }\n }\n\n // Check named imports\n const namedPattern = new RegExp(SPEC_REFERENCE_PATTERNS.namedImport);\n while ((match = namedPattern.exec(code)) !== null) {\n // Extract all spec names from the import statement\n const importBlock = match[0];\n const specNames = importBlock.match(\n /\\b(\\w+(?:Spec|Contract|Command|Query))\\b/g\n );\n if (specNames) {\n for (const name of specNames) {\n addMatch(name, 'import', getLineNumber(match.index));\n }\n }\n }\n\n // Check default imports\n const defaultPattern = new RegExp(SPEC_REFERENCE_PATTERNS.defaultImport);\n while ((match = defaultPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'import', getLineNumber(match.index));\n }\n }\n\n // Check spec assignments\n const assignPattern = new RegExp(SPEC_REFERENCE_PATTERNS.specAssignment);\n while ((match = assignPattern.exec(code)) !== null) {\n if (match[1]) {\n addMatch(match[1], 'unknown', getLineNumber(match.index));\n }\n }\n\n return matches;\n}\n\n/**\n * Default glob patterns for implementation files.\n */\nconst DEFAULT_INCLUDE_PATTERNS = ['**/*.ts(x)'];\n\n/**\n * Discover implementations that reference a specific spec.\n */\nexport async function discoverImplementationsForSpec(\n specKey: string,\n adapters: { fs: FsAdapter },\n options: DiscoveryOptions = {}\n): Promise<SpecReferenceMatch[]> {\n const { fs } = adapters;\n const includePatterns = options.includePatterns ?? DEFAULT_INCLUDE_PATTERNS;\n const excludePatterns = options.excludePatterns ?? [\n ...new Set([...DEFAULT_FS_IGNORES, ...DEFAULT_SPEC_PATTERNS]),\n ];\n\n const allMatches: SpecReferenceMatch[] = [];\n\n // Scan each include pattern\n for (const pattern of includePatterns) {\n const files = await fs.glob({ pattern, ignore: excludePatterns });\n\n for (const filePath of files) {\n try {\n const content = await fs.readFile(filePath);\n const references = extractSpecReferences(content, filePath);\n\n // Filter to only references for the target spec\n const matchingRefs = references.filter(\n (ref) => ref.specKey === specKey\n );\n allMatches.push(...matchingRefs);\n } catch {\n // Skip files that can't be read\n }\n }\n }\n\n return allMatches;\n}\n\n/**\n * Discover all spec references in the workspace.\n * Returns a map of spec key to implementation references.\n */\nexport async function discoverAllImplementations(\n adapters: { fs: FsAdapter },\n options: DiscoveryOptions = {}\n): Promise<Map<string, SpecReferenceMatch[]>> {\n const { fs } = adapters;\n const includePatterns = options.includePatterns ?? DEFAULT_INCLUDE_PATTERNS;\n const excludePatterns = options.excludePatterns ?? [\n ...new Set([...DEFAULT_FS_IGNORES, ...DEFAULT_SPEC_PATTERNS]),\n ];\n\n const specToImplementations = new Map<string, SpecReferenceMatch[]>();\n\n // Scan each include pattern\n for (const pattern of includePatterns) {\n const files = await fs.glob({ pattern, ignore: excludePatterns });\n\n for (const filePath of files) {\n try {\n const content = await fs.readFile(filePath);\n const references = extractSpecReferences(content, filePath);\n\n // Group by spec key\n for (const ref of references) {\n const existing = specToImplementations.get(ref.specKey) ?? [];\n existing.push(ref);\n specToImplementations.set(ref.specKey, existing);\n }\n } catch {\n // Skip files that can't be read\n }\n }\n }\n\n return specToImplementations;\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DiscoveryOptions, ImplementationSource, ImplementationStatus, ResolvedImplementation, ResolverOptions, SpecImplementationResult, SpecReferenceMatch } from "./types.mjs";
|
|
2
2
|
import { discoverAllImplementations, discoverImplementationsForSpec, extractSpecReferences, inferImplementationType } from "./discovery.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { parseExplicitImplementations } from "./resolver/parsers.mjs";
|
|
4
4
|
import { getConventionPaths, toKebabCase } from "./resolver/conventions.mjs";
|
|
5
5
|
import { determineStatus, getImplementationSummary } from "./resolver/status.mjs";
|
|
6
6
|
import { resolveAllImplementations, resolveImplementations } from "./resolver/index.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { discoverAllImplementations, discoverImplementationsForSpec, extractSpecReferences, inferImplementationType } from "./discovery.mjs";
|
|
2
2
|
import { getConventionPaths, toKebabCase } from "./resolver/conventions.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { parseExplicitImplementations } from "./resolver/parsers.mjs";
|
|
4
4
|
import { determineStatus, getImplementationSummary } from "./resolver/status.mjs";
|
|
5
5
|
import { resolveAllImplementations, resolveImplementations } from "./resolver/index.mjs";
|
|
6
6
|
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { FsAdapter } from "../../../ports/fs.mjs";
|
|
2
2
|
import { ResolverOptions, SpecImplementationResult } from "../types.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { parseExplicitImplementations } from "./parsers.mjs";
|
|
4
4
|
import { getConventionPaths, toKebabCase } from "./conventions.mjs";
|
|
5
5
|
import { determineStatus, getImplementationSummary } from "./status.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { SpecScanResult } from "@contractspec/module.workspace";
|
|
7
|
+
import { ResolvedContractsrcConfig } from "@contractspec/lib.contracts";
|
|
8
|
+
import { Ora } from "ora";
|
|
7
9
|
|
|
8
10
|
//#region src/services/implementation/resolver/index.d.ts
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Resolve all implementations for a spec file.
|
|
12
14
|
*/
|
|
13
|
-
declare function resolveImplementations(specFile:
|
|
15
|
+
declare function resolveImplementations(specFile: SpecScanResult, adapters: {
|
|
14
16
|
fs: FsAdapter;
|
|
15
|
-
}, config:
|
|
17
|
+
}, config: ResolvedContractsrcConfig, options?: ResolverOptions, spinner?: Ora): Promise<SpecImplementationResult>;
|
|
16
18
|
/**
|
|
17
19
|
* Resolve implementations for multiple spec files.
|
|
18
20
|
*/
|
|
19
|
-
declare function resolveAllImplementations(specFiles:
|
|
21
|
+
declare function resolveAllImplementations(specFiles: SpecScanResult[], adapters: {
|
|
20
22
|
fs: FsAdapter;
|
|
21
|
-
}, config:
|
|
23
|
+
}, config: ResolvedContractsrcConfig, options?: ResolverOptions, spinner?: Ora): Promise<SpecImplementationResult[]>;
|
|
22
24
|
//#endregion
|
|
23
25
|
export { resolveAllImplementations, resolveImplementations };
|
|
24
26
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/services/implementation/resolver/index.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/services/implementation/resolver/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;AA0KsB,iBAvHA,sBAAA,CAuHyB,QAAA,EAtHnC,cAsHmC,EAAA,QAAA,EAAA;EAClC,EAAA,EAtHK,SAsHL;CACK,EAAA,MAAA,EAtHR,yBAsHQ,EAAA,OAAA,CAAA,EArHP,eAqHO,EAAA,OAAA,CAAA,EApHN,GAoHM,CAAA,EAnHf,OAmHe,CAnHP,wBAmHO,CAAA;;;;AAIP,iBANW,yBAAA,CAMX,SAAA,EALE,cAKF,EAAA,EAAA,QAAA,EAAA;EAAR,EAAA,EAJe,SAIf;CAAO,EAAA,MAAA,EAHA,yBAGA,EAAA,OAAA,CAAA,EAFC,eAED,EAAA,OAAA,CAAA,EADE,GACF,CAAA,EAAP,OAAO,CAAC,wBAAD,EAAA,CAAA"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { discoverImplementationsForSpec } from "../discovery.mjs";
|
|
2
2
|
import { getConventionPaths, toKebabCase } from "./conventions.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { parseExplicitImplementations } from "./parsers.mjs";
|
|
4
4
|
import { determineStatus, getImplementationSummary } from "./status.mjs";
|
|
5
|
-
import { scanSpecSource } from "@contractspec/module.workspace";
|
|
6
5
|
import path from "path";
|
|
7
6
|
import { createHash } from "crypto";
|
|
8
7
|
|
|
@@ -30,78 +29,81 @@ function computeHash(content) {
|
|
|
30
29
|
/**
|
|
31
30
|
* Resolve all implementations for a spec file.
|
|
32
31
|
*/
|
|
33
|
-
async function resolveImplementations(specFile, adapters, config, options = {}) {
|
|
32
|
+
async function resolveImplementations(specFile, adapters, config, options = {}, spinner) {
|
|
34
33
|
const opts = {
|
|
35
34
|
...DEFAULT_OPTIONS,
|
|
36
35
|
...options
|
|
37
36
|
};
|
|
37
|
+
const specHash = opts.computeHashes ? computeHash(specFile.sourceBlock || "") : void 0;
|
|
38
|
+
const specKey = specFile.key ?? path.basename(specFile.filePath).replace(/\.[jt]s$/, "");
|
|
39
|
+
const specVersion = specFile.version ?? "1.0.0";
|
|
38
40
|
const { fs } = adapters;
|
|
39
|
-
if (!await fs.exists(specFile)) throw new Error(`Spec file not found: ${specFile}`);
|
|
40
|
-
const specContent = await fs.readFile(specFile);
|
|
41
|
-
const specHash = opts.computeHashes ? computeHash(specContent) : void 0;
|
|
42
|
-
const scan = scanSpecSource(specContent, specFile);
|
|
43
|
-
const specKey = scan.key ?? path.basename(specFile).replace(/\.[jt]s$/, "");
|
|
44
|
-
const specVersion = scan.version ?? "1.0.0";
|
|
45
|
-
const specType = scan.specType ?? "operation";
|
|
46
41
|
const implementations = [];
|
|
47
42
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
48
43
|
const addImpl = async (path$1, type, source, description) => {
|
|
49
44
|
if (seenPaths.has(path$1)) return;
|
|
50
45
|
seenPaths.add(path$1);
|
|
51
46
|
const exists = await fs.exists(path$1);
|
|
52
|
-
let
|
|
47
|
+
let implementationSourceContent = void 0;
|
|
48
|
+
let implementationSourceHash = void 0;
|
|
53
49
|
if (exists && opts.computeHashes) try {
|
|
54
|
-
|
|
50
|
+
implementationSourceContent = await fs.readFile(path$1);
|
|
51
|
+
implementationSourceHash = computeHash(implementationSourceContent);
|
|
55
52
|
} catch {}
|
|
56
53
|
implementations.push({
|
|
57
54
|
path: path$1,
|
|
58
55
|
type,
|
|
59
56
|
source,
|
|
60
57
|
exists,
|
|
61
|
-
|
|
58
|
+
implementationSourceContent,
|
|
59
|
+
implementationSourceHash,
|
|
62
60
|
description
|
|
63
61
|
});
|
|
64
62
|
};
|
|
65
|
-
if (opts.includeExplicit) {
|
|
66
|
-
|
|
63
|
+
if (opts.includeExplicit && specFile.sourceBlock) {
|
|
64
|
+
if (spinner) spinner.suffixText = `Discover explicit implementations`;
|
|
65
|
+
const explicitImpls = parseExplicitImplementations(specFile.sourceBlock);
|
|
67
66
|
for (const impl of explicitImpls) await addImpl(impl.path, impl.type, "explicit", impl.description);
|
|
68
67
|
}
|
|
69
68
|
if (opts.includeDiscovered) {
|
|
69
|
+
if (spinner) spinner.suffixText = `Discover implementations`;
|
|
70
70
|
const discovered = await discoverImplementationsForSpec(specKey, adapters, opts);
|
|
71
|
-
const specKeyVariants = getSpecKeyVariants(specKey);
|
|
72
|
-
for (const variant of specKeyVariants) {
|
|
73
|
-
const variantDiscovered = await discoverImplementationsForSpec(variant, adapters, opts);
|
|
74
|
-
discovered.push(...variantDiscovered);
|
|
75
|
-
}
|
|
76
71
|
for (const ref of discovered) {
|
|
77
|
-
if (ref.filePath === specFile) continue;
|
|
72
|
+
if (ref.filePath === specFile.filePath) continue;
|
|
78
73
|
await addImpl(ref.filePath, ref.inferredType, "discovered");
|
|
79
74
|
}
|
|
80
75
|
}
|
|
81
76
|
if (opts.includeConvention) {
|
|
82
|
-
|
|
77
|
+
if (spinner) spinner.suffixText = `Discover implementations based on conventions`;
|
|
78
|
+
const outputDir = opts.outputDir ?? config.outputDir ?? "./src";
|
|
79
|
+
const conventionPaths = getConventionPaths(specFile.specType, specKey, outputDir);
|
|
83
80
|
for (const { path: path$1, type } of conventionPaths) await addImpl(path$1, type, "convention");
|
|
84
81
|
}
|
|
82
|
+
if (spinner) spinner.suffixText = `Determine implementation status`;
|
|
83
|
+
const status = determineStatus(implementations);
|
|
85
84
|
return {
|
|
86
85
|
specKey,
|
|
87
86
|
specVersion,
|
|
88
|
-
specPath: specFile,
|
|
89
|
-
specType,
|
|
87
|
+
specPath: specFile.filePath,
|
|
88
|
+
specType: specFile.specType,
|
|
90
89
|
implementations,
|
|
91
|
-
status
|
|
90
|
+
status,
|
|
92
91
|
specHash
|
|
93
92
|
};
|
|
94
93
|
}
|
|
95
94
|
/**
|
|
96
95
|
* Resolve implementations for multiple spec files.
|
|
97
96
|
*/
|
|
98
|
-
async function resolveAllImplementations(specFiles, adapters, config, options = {}) {
|
|
97
|
+
async function resolveAllImplementations(specFiles, adapters, config, options = {}, spinner) {
|
|
99
98
|
const results = [];
|
|
100
|
-
for (const specFile of specFiles)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
for (const specFile of specFiles) {
|
|
100
|
+
if (spinner) spinner.text = `Resolving implementation... (${results.length}/${specFiles.length})`;
|
|
101
|
+
try {
|
|
102
|
+
const result = await resolveImplementations(specFile, adapters, config, options, spinner);
|
|
103
|
+
results.push(result);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error(`Failed to resolve implementations for ${specFile}:`, error);
|
|
106
|
+
}
|
|
105
107
|
}
|
|
106
108
|
return results;
|
|
107
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["path"],"sources":["../../../../src/services/implementation/resolver/index.ts"],"sourcesContent":["/**\n * Implementation resolver service.\n *\n * Resolves all implementations for a spec by merging:\n * 1. Explicit mappings from spec.implementations\n * 2. Auto-discovered references from workspace scanning\n * 3. Convention-based paths (naming conventions)\n */\n\nimport { createHash } from 'crypto';\
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["path"],"sources":["../../../../src/services/implementation/resolver/index.ts"],"sourcesContent":["/**\n * Implementation resolver service.\n *\n * Resolves all implementations for a spec by merging:\n * 1. Explicit mappings from spec.implementations\n * 2. Auto-discovered references from workspace scanning\n * 3. Convention-based paths (naming conventions)\n */\n\nimport { createHash } from 'crypto';\n\nimport type { SpecScanResult } from '@contractspec/module.workspace';\nimport type {\n ImplementationType,\n ResolvedContractsrcConfig,\n} from '@contractspec/lib.contracts';\nimport type { FsAdapter } from '../../../ports/fs';\nimport type {\n ResolvedImplementation,\n ResolverOptions,\n SpecImplementationResult,\n} from '../types';\nimport { discoverImplementationsForSpec } from '../discovery';\n\nimport { getConventionPaths } from './conventions';\nimport { parseExplicitImplementations } from './parsers';\nimport { determineStatus } from './status';\nimport path from 'path';\nimport type { Ora } from 'ora';\n\nexport * from './parsers';\nexport * from './conventions';\nexport * from './status';\n\nconst DEFAULT_OPTIONS: ResolverOptions = {\n includeExplicit: true,\n includeDiscovered: true,\n includeConvention: true,\n computeHashes: true,\n};\n\n/**\n * Compute SHA256 hash of content.\n */\nfunction computeHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\n/**\n * Resolve all implementations for a spec file.\n */\nexport async function resolveImplementations(\n specFile: SpecScanResult,\n adapters: { fs: FsAdapter },\n config: ResolvedContractsrcConfig,\n options: ResolverOptions = {},\n spinner?: Ora\n): Promise<SpecImplementationResult> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const specHash = opts.computeHashes\n ? computeHash(specFile.sourceBlock || '')\n : undefined;\n\n const specKey =\n specFile.key ?? path.basename(specFile.filePath).replace(/\\.[jt]s$/, '');\n const specVersion = specFile.version ?? '1.0.0';\n\n const { fs } = adapters;\n\n const implementations: ResolvedImplementation[] = [];\n const seenPaths = new Set<string>();\n\n // Helper to add unique implementations\n const addImpl = async (\n path: string,\n type: ImplementationType,\n source: ResolvedImplementation['source'],\n description?: string\n ) => {\n if (seenPaths.has(path)) return;\n seenPaths.add(path);\n\n const exists = await fs.exists(path);\n let implementationSourceContent: string | undefined = undefined;\n let implementationSourceHash: string | undefined = undefined;\n\n if (exists && opts.computeHashes) {\n try {\n implementationSourceContent = await fs.readFile(path);\n implementationSourceHash = computeHash(implementationSourceContent);\n } catch {\n // Ignore hash computation errors\n }\n }\n\n implementations.push({\n path,\n type,\n source,\n exists,\n implementationSourceContent,\n implementationSourceHash,\n description,\n });\n };\n\n // 1. Add explicit implementations from spec\n if (opts.includeExplicit && specFile.sourceBlock) {\n if (spinner) spinner.suffixText = `Discover explicit implementations`;\n\n // Parse explicit implementations from spec source\n const explicitImpls = parseExplicitImplementations(specFile.sourceBlock);\n for (const impl of explicitImpls) {\n await addImpl(impl.path, impl.type, 'explicit', impl.description);\n }\n }\n\n // 2. Add auto-discovered implementations\n if (opts.includeDiscovered) {\n if (spinner) spinner.suffixText = `Discover implementations`;\n\n const discovered = await discoverImplementationsForSpec(\n specKey,\n adapters,\n opts\n );\n\n for (const ref of discovered) {\n // Skip the spec file itself\n if (ref.filePath === specFile.filePath) continue;\n\n await addImpl(ref.filePath, ref.inferredType, 'discovered');\n }\n }\n\n // 3. Add convention-based implementations\n if (opts.includeConvention) {\n if (spinner)\n spinner.suffixText = `Discover implementations based on conventions`;\n\n const outputDir = opts.outputDir ?? config.outputDir ?? './src';\n const conventionPaths = getConventionPaths(\n specFile.specType,\n specKey,\n outputDir\n );\n\n for (const { path, type } of conventionPaths) {\n await addImpl(path, type, 'convention');\n }\n }\n\n if (spinner) spinner.suffixText = `Determine implementation status`;\n // Determine overall status\n const status = determineStatus(implementations);\n\n return {\n specKey,\n specVersion,\n specPath: specFile.filePath,\n specType: specFile.specType,\n implementations,\n status,\n specHash,\n };\n}\n\n/**\n * Resolve implementations for multiple spec files.\n */\nexport async function resolveAllImplementations(\n specFiles: SpecScanResult[],\n adapters: { fs: FsAdapter },\n config: ResolvedContractsrcConfig,\n options: ResolverOptions = {},\n spinner?: Ora\n): Promise<SpecImplementationResult[]> {\n const results: SpecImplementationResult[] = [];\n\n for (const specFile of specFiles) {\n if (spinner)\n spinner.text = `Resolving implementation... (${results.length}/${specFiles.length})`;\n\n try {\n const result = await resolveImplementations(\n specFile,\n adapters,\n config,\n options,\n spinner\n );\n results.push(result);\n } catch (error) {\n // Log error but continue with other specs\n console.error(\n `Failed to resolve implementations for ${specFile}:`,\n error\n );\n }\n }\n\n return results;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,MAAM,kBAAmC;CACvC,iBAAiB;CACjB,mBAAmB;CACnB,mBAAmB;CACnB,eAAe;CAChB;;;;AAKD,SAAS,YAAY,SAAyB;AAC5C,QAAO,WAAW,SAAS,CAAC,OAAO,QAAQ,CAAC,OAAO,MAAM;;;;;AAM3D,eAAsB,uBACpB,UACA,UACA,QACA,UAA2B,EAAE,EAC7B,SACmC;CACnC,MAAM,OAAO;EAAE,GAAG;EAAiB,GAAG;EAAS;CAC/C,MAAM,WAAW,KAAK,gBAClB,YAAY,SAAS,eAAe,GAAG,GACvC;CAEJ,MAAM,UACJ,SAAS,OAAO,KAAK,SAAS,SAAS,SAAS,CAAC,QAAQ,YAAY,GAAG;CAC1E,MAAM,cAAc,SAAS,WAAW;CAExC,MAAM,EAAE,OAAO;CAEf,MAAM,kBAA4C,EAAE;CACpD,MAAM,4BAAY,IAAI,KAAa;CAGnC,MAAM,UAAU,OACd,QACA,MACA,QACA,gBACG;AACH,MAAI,UAAU,IAAIA,OAAK,CAAE;AACzB,YAAU,IAAIA,OAAK;EAEnB,MAAM,SAAS,MAAM,GAAG,OAAOA,OAAK;EACpC,IAAI,8BAAkD;EACtD,IAAI,2BAA+C;AAEnD,MAAI,UAAU,KAAK,cACjB,KAAI;AACF,iCAA8B,MAAM,GAAG,SAASA,OAAK;AACrD,8BAA2B,YAAY,4BAA4B;UAC7D;AAKV,kBAAgB,KAAK;GACnB;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;;AAIJ,KAAI,KAAK,mBAAmB,SAAS,aAAa;AAChD,MAAI,QAAS,SAAQ,aAAa;EAGlC,MAAM,gBAAgB,6BAA6B,SAAS,YAAY;AACxE,OAAK,MAAM,QAAQ,cACjB,OAAM,QAAQ,KAAK,MAAM,KAAK,MAAM,YAAY,KAAK,YAAY;;AAKrE,KAAI,KAAK,mBAAmB;AAC1B,MAAI,QAAS,SAAQ,aAAa;EAElC,MAAM,aAAa,MAAM,+BACvB,SACA,UACA,KACD;AAED,OAAK,MAAM,OAAO,YAAY;AAE5B,OAAI,IAAI,aAAa,SAAS,SAAU;AAExC,SAAM,QAAQ,IAAI,UAAU,IAAI,cAAc,aAAa;;;AAK/D,KAAI,KAAK,mBAAmB;AAC1B,MAAI,QACF,SAAQ,aAAa;EAEvB,MAAM,YAAY,KAAK,aAAa,OAAO,aAAa;EACxD,MAAM,kBAAkB,mBACtB,SAAS,UACT,SACA,UACD;AAED,OAAK,MAAM,EAAE,cAAM,UAAU,gBAC3B,OAAM,QAAQA,QAAM,MAAM,aAAa;;AAI3C,KAAI,QAAS,SAAQ,aAAa;CAElC,MAAM,SAAS,gBAAgB,gBAAgB;AAE/C,QAAO;EACL;EACA;EACA,UAAU,SAAS;EACnB,UAAU,SAAS;EACnB;EACA;EACA;EACD;;;;;AAMH,eAAsB,0BACpB,WACA,UACA,QACA,UAA2B,EAAE,EAC7B,SACqC;CACrC,MAAM,UAAsC,EAAE;AAE9C,MAAK,MAAM,YAAY,WAAW;AAChC,MAAI,QACF,SAAQ,OAAO,gCAAgC,QAAQ,OAAO,GAAG,UAAU,OAAO;AAEpF,MAAI;GACF,MAAM,SAAS,MAAM,uBACnB,UACA,UACA,QACA,SACA,QACD;AACD,WAAQ,KAAK,OAAO;WACb,OAAO;AAEd,WAAQ,MACN,yCAAyC,SAAS,IAClD,MACD;;;AAIL,QAAO"}
|
|
@@ -7,10 +7,6 @@ import { ImplementationRef } from "@contractspec/lib.contracts";
|
|
|
7
7
|
* Looks for: implementations: [{ path: '...', type: '...' }] inside the main spec object.
|
|
8
8
|
*/
|
|
9
9
|
declare function parseExplicitImplementations(code: string): ImplementationRef[];
|
|
10
|
-
/**
|
|
11
|
-
* Get common variants of a spec key for discovery.
|
|
12
|
-
*/
|
|
13
|
-
declare function getSpecKeyVariants(specKey: string): string[];
|
|
14
10
|
//#endregion
|
|
15
|
-
export {
|
|
11
|
+
export { parseExplicitImplementations };
|
|
16
12
|
//# sourceMappingURL=parsers.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsers.d.mts","names":[],"sources":["../../../../src/services/implementation/resolver/parsers.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parsers.d.mts","names":[],"sources":["../../../../src/services/implementation/resolver/parsers.ts"],"sourcesContent":[],"mappings":";;;;;;;;iBAcgB,4BAAA,gBAEb"}
|
|
@@ -76,25 +76,7 @@ function parseExplicitImplementations(code) {
|
|
|
76
76
|
}
|
|
77
77
|
return implementations;
|
|
78
78
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Get common variants of a spec key for discovery.
|
|
81
|
-
*/
|
|
82
|
-
function getSpecKeyVariants(specKey) {
|
|
83
|
-
const variants = [];
|
|
84
|
-
const base = specKey.replace(/Spec$/, "").replace(/Contract$/, "").replace(/Command$/, "").replace(/Query$/, "");
|
|
85
|
-
if (base !== specKey) {
|
|
86
|
-
variants.push(base);
|
|
87
|
-
variants.push(`${base}Spec`);
|
|
88
|
-
variants.push(`${base}Contract`);
|
|
89
|
-
}
|
|
90
|
-
const parts = specKey.split(".");
|
|
91
|
-
if (parts.length > 1) {
|
|
92
|
-
const pascalName = parts.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
|
|
93
|
-
variants.push(pascalName);
|
|
94
|
-
}
|
|
95
|
-
return variants;
|
|
96
|
-
}
|
|
97
79
|
|
|
98
80
|
//#endregion
|
|
99
|
-
export {
|
|
81
|
+
export { parseExplicitImplementations };
|
|
100
82
|
//# sourceMappingURL=parsers.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsers.mjs","names":["init"],"sources":["../../../../src/services/implementation/resolver/parsers.ts"],"sourcesContent":["/**\n * Parser utilities for extracting implementation references from source code.\n */\n\nimport type {\n ImplementationRef,\n ImplementationType,\n} from '@contractspec/lib.contracts';\nimport { Node, Project, SyntaxKind } from 'ts-morph';\n\n/**\n * Parse explicit implementations from spec source code using ts-morph.\n * Looks for: implementations: [{ path: '...', type: '...' }] inside the main spec object.\n */\nexport function parseExplicitImplementations(\n code: string\n): ImplementationRef[] {\n const implementations: ImplementationRef[] = [];\n const project = new Project({ useInMemoryFileSystem: true });\n // Create a SourceFile\n const sourceFile = project.createSourceFile('spec.ts', code);\n\n // Helper to extract fields from an object literal\n const extractImpls = (obj: Node) => {\n if (!Node.isObjectLiteralExpression(obj)) return;\n const prop = obj.getProperty('implementations');\n if (prop && Node.isPropertyAssignment(prop)) {\n const init = prop.getInitializer();\n if (init && Node.isArrayLiteralExpression(init)) {\n for (const elem of init.getElements()) {\n if (Node.isObjectLiteralExpression(elem)) {\n let pathVal: string | undefined;\n let typeVal: ImplementationType | undefined;\n let descVal: string | undefined;\n\n const pathProp = elem.getProperty('path');\n if (pathProp && Node.isPropertyAssignment(pathProp)) {\n const init = pathProp.getInitializer();\n if (Node.isStringLiteral(init)) {\n pathVal = init.getLiteralText();\n }\n }\n\n const typeProp = elem.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const init = typeProp.getInitializer();\n if (Node.isStringLiteral(init)) {\n typeVal = init.getLiteralText() as ImplementationType;\n }\n }\n\n const descProp = elem.getProperty('description');\n if (descProp && Node.isPropertyAssignment(descProp)) {\n const init = descProp.getInitializer();\n if (Node.isStringLiteral(init)) {\n descVal = init.getLiteralText();\n }\n }\n\n if (pathVal && typeVal) {\n implementations.push({\n path: pathVal,\n type: typeVal,\n description: descVal,\n });\n }\n }\n }\n }\n }\n };\n\n // Find the spec object\n // 1. defineCommand/Event/etc CallExpression\n // 2. Exported object literal or variable\n\n const callExpressions = sourceFile.getDescendantsOfKind(\n SyntaxKind.CallExpression\n );\n for (const call of callExpressions) {\n const expr = call.getExpression().getText();\n if (\n ['defineCommand', 'defineQuery', 'defineEvent', 'defineFeature'].includes(\n expr\n )\n ) {\n const args = call.getArguments();\n if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {\n extractImpls(args[0]);\n return implementations; // Assume only one main definition per file\n }\n }\n }\n\n // Fallback: search exported variables\n const varStmts = sourceFile.getVariableStatements();\n for (const stmt of varStmts) {\n if (stmt.isExported()) {\n for (const decl of stmt.getDeclarations()) {\n const init = decl.getInitializer();\n if (init && Node.isObjectLiteralExpression(init)) {\n // Check if it has 'implementations'\n if (init.getProperty('implementations')) {\n extractImpls(init);\n return implementations;\n }\n }\n }\n }\n }\n\n // Fallback: default export\n const exportAssign = sourceFile.getExportAssignment(\n (d) => !d.isExportEquals()\n );\n if (exportAssign) {\n const expr = exportAssign.getExpression();\n if (Node.isObjectLiteralExpression(expr)) {\n extractImpls(expr);\n } else if (\n Node.isAsExpression(expr) &&\n Node.isObjectLiteralExpression(expr.getExpression())\n ) {\n extractImpls(expr.getExpression());\n }\n }\n\n return implementations;\n}\n
|
|
1
|
+
{"version":3,"file":"parsers.mjs","names":["init"],"sources":["../../../../src/services/implementation/resolver/parsers.ts"],"sourcesContent":["/**\n * Parser utilities for extracting implementation references from source code.\n */\n\nimport type {\n ImplementationRef,\n ImplementationType,\n} from '@contractspec/lib.contracts';\nimport { Node, Project, SyntaxKind } from 'ts-morph';\n\n/**\n * Parse explicit implementations from spec source code using ts-morph.\n * Looks for: implementations: [{ path: '...', type: '...' }] inside the main spec object.\n */\nexport function parseExplicitImplementations(\n code: string\n): ImplementationRef[] {\n const implementations: ImplementationRef[] = [];\n const project = new Project({ useInMemoryFileSystem: true });\n // Create a SourceFile\n const sourceFile = project.createSourceFile('spec.ts', code);\n\n // Helper to extract fields from an object literal\n const extractImpls = (obj: Node) => {\n if (!Node.isObjectLiteralExpression(obj)) return;\n const prop = obj.getProperty('implementations');\n if (prop && Node.isPropertyAssignment(prop)) {\n const init = prop.getInitializer();\n if (init && Node.isArrayLiteralExpression(init)) {\n for (const elem of init.getElements()) {\n if (Node.isObjectLiteralExpression(elem)) {\n let pathVal: string | undefined;\n let typeVal: ImplementationType | undefined;\n let descVal: string | undefined;\n\n const pathProp = elem.getProperty('path');\n if (pathProp && Node.isPropertyAssignment(pathProp)) {\n const init = pathProp.getInitializer();\n if (Node.isStringLiteral(init)) {\n pathVal = init.getLiteralText();\n }\n }\n\n const typeProp = elem.getProperty('type');\n if (typeProp && Node.isPropertyAssignment(typeProp)) {\n const init = typeProp.getInitializer();\n if (Node.isStringLiteral(init)) {\n typeVal = init.getLiteralText() as ImplementationType;\n }\n }\n\n const descProp = elem.getProperty('description');\n if (descProp && Node.isPropertyAssignment(descProp)) {\n const init = descProp.getInitializer();\n if (Node.isStringLiteral(init)) {\n descVal = init.getLiteralText();\n }\n }\n\n if (pathVal && typeVal) {\n implementations.push({\n path: pathVal,\n type: typeVal,\n description: descVal,\n });\n }\n }\n }\n }\n }\n };\n\n // Find the spec object\n // 1. defineCommand/Event/etc CallExpression\n // 2. Exported object literal or variable\n\n const callExpressions = sourceFile.getDescendantsOfKind(\n SyntaxKind.CallExpression\n );\n for (const call of callExpressions) {\n const expr = call.getExpression().getText();\n if (\n ['defineCommand', 'defineQuery', 'defineEvent', 'defineFeature'].includes(\n expr\n )\n ) {\n const args = call.getArguments();\n if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {\n extractImpls(args[0]);\n return implementations; // Assume only one main definition per file\n }\n }\n }\n\n // Fallback: search exported variables\n const varStmts = sourceFile.getVariableStatements();\n for (const stmt of varStmts) {\n if (stmt.isExported()) {\n for (const decl of stmt.getDeclarations()) {\n const init = decl.getInitializer();\n if (init && Node.isObjectLiteralExpression(init)) {\n // Check if it has 'implementations'\n if (init.getProperty('implementations')) {\n extractImpls(init);\n return implementations;\n }\n }\n }\n }\n }\n\n // Fallback: default export\n const exportAssign = sourceFile.getExportAssignment(\n (d) => !d.isExportEquals()\n );\n if (exportAssign) {\n const expr = exportAssign.getExpression();\n if (Node.isObjectLiteralExpression(expr)) {\n extractImpls(expr);\n } else if (\n Node.isAsExpression(expr) &&\n Node.isObjectLiteralExpression(expr.getExpression())\n ) {\n extractImpls(expr.getExpression());\n }\n }\n\n return implementations;\n}\n"],"mappings":";;;;;;;AAcA,SAAgB,6BACd,MACqB;CACrB,MAAM,kBAAuC,EAAE;CAG/C,MAAM,aAFU,IAAI,QAAQ,EAAE,uBAAuB,MAAM,CAAC,CAEjC,iBAAiB,WAAW,KAAK;CAG5D,MAAM,gBAAgB,QAAc;AAClC,MAAI,CAAC,KAAK,0BAA0B,IAAI,CAAE;EAC1C,MAAM,OAAO,IAAI,YAAY,kBAAkB;AAC/C,MAAI,QAAQ,KAAK,qBAAqB,KAAK,EAAE;GAC3C,MAAM,OAAO,KAAK,gBAAgB;AAClC,OAAI,QAAQ,KAAK,yBAAyB,KAAK,EAC7C;SAAK,MAAM,QAAQ,KAAK,aAAa,CACnC,KAAI,KAAK,0BAA0B,KAAK,EAAE;KACxC,IAAI;KACJ,IAAI;KACJ,IAAI;KAEJ,MAAM,WAAW,KAAK,YAAY,OAAO;AACzC,SAAI,YAAY,KAAK,qBAAqB,SAAS,EAAE;MACnD,MAAMA,SAAO,SAAS,gBAAgB;AACtC,UAAI,KAAK,gBAAgBA,OAAK,CAC5B,WAAUA,OAAK,gBAAgB;;KAInC,MAAM,WAAW,KAAK,YAAY,OAAO;AACzC,SAAI,YAAY,KAAK,qBAAqB,SAAS,EAAE;MACnD,MAAMA,SAAO,SAAS,gBAAgB;AACtC,UAAI,KAAK,gBAAgBA,OAAK,CAC5B,WAAUA,OAAK,gBAAgB;;KAInC,MAAM,WAAW,KAAK,YAAY,cAAc;AAChD,SAAI,YAAY,KAAK,qBAAqB,SAAS,EAAE;MACnD,MAAMA,SAAO,SAAS,gBAAgB;AACtC,UAAI,KAAK,gBAAgBA,OAAK,CAC5B,WAAUA,OAAK,gBAAgB;;AAInC,SAAI,WAAW,QACb,iBAAgB,KAAK;MACnB,MAAM;MACN,MAAM;MACN,aAAa;MACd,CAAC;;;;;CAYd,MAAM,kBAAkB,WAAW,qBACjC,WAAW,eACZ;AACD,MAAK,MAAM,QAAQ,iBAAiB;EAClC,MAAM,OAAO,KAAK,eAAe,CAAC,SAAS;AAC3C,MACE;GAAC;GAAiB;GAAe;GAAe;GAAgB,CAAC,SAC/D,KACD,EACD;GACA,MAAM,OAAO,KAAK,cAAc;AAChC,OAAI,KAAK,SAAS,KAAK,KAAK,0BAA0B,KAAK,GAAG,EAAE;AAC9D,iBAAa,KAAK,GAAG;AACrB,WAAO;;;;CAMb,MAAM,WAAW,WAAW,uBAAuB;AACnD,MAAK,MAAM,QAAQ,SACjB,KAAI,KAAK,YAAY,CACnB,MAAK,MAAM,QAAQ,KAAK,iBAAiB,EAAE;EACzC,MAAM,OAAO,KAAK,gBAAgB;AAClC,MAAI,QAAQ,KAAK,0BAA0B,KAAK,EAE9C;OAAI,KAAK,YAAY,kBAAkB,EAAE;AACvC,iBAAa,KAAK;AAClB,WAAO;;;;CAQjB,MAAM,eAAe,WAAW,qBAC7B,MAAM,CAAC,EAAE,gBAAgB,CAC3B;AACD,KAAI,cAAc;EAChB,MAAM,OAAO,aAAa,eAAe;AACzC,MAAI,KAAK,0BAA0B,KAAK,CACtC,cAAa,KAAK;WAElB,KAAK,eAAe,KAAK,IACzB,KAAK,0BAA0B,KAAK,eAAe,CAAC,CAEpD,cAAa,KAAK,eAAe,CAAC;;AAItC,QAAO"}
|
|
@@ -22,8 +22,10 @@ interface ResolvedImplementation {
|
|
|
22
22
|
source: ImplementationSource;
|
|
23
23
|
/** Whether the file exists on disk */
|
|
24
24
|
exists: boolean;
|
|
25
|
+
/** Content */
|
|
26
|
+
implementationSourceContent?: string;
|
|
25
27
|
/** Content hash for cache invalidation (SHA256) */
|
|
26
|
-
|
|
28
|
+
implementationSourceHash?: string;
|
|
27
29
|
/** Optional description */
|
|
28
30
|
description?: string;
|
|
29
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/services/implementation/types.ts"],"sourcesContent":[],"mappings":";;;;AAcA;AAKA;
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/services/implementation/types.ts"],"sourcesContent":[],"mappings":";;;;AAcA;AAKA;AAoBA;AAoBiB,KAlDL,oBAAA,GAkDqB,UAAA,GAAA,YAAA,GAAA,YAAA;AAcjC;AAWA;;KAtEY,oBAAA;;;;UAKK,sBAAA;;;;QAIT;;UAEE;;;;;;;;;;;;;UAcO,wBAAA;;;;;;;;;;mBAUE;;UAET;;;;;;;UAQO,gBAAA;;;;;;;;;;;;;UAcA,eAAA;;;;;;;;;;UAWA,kBAAA;;;;;;;;;;gBAUD"}
|
|
@@ -36,6 +36,8 @@ import { deepMergeOverwrite, deepMergePreserve, formatJson, safeParseJson } from
|
|
|
36
36
|
import { ALL_CHECK_CATEGORIES, CHECK_CATEGORY_LABELS, CheckCategory, CheckContext, CheckResult, CheckStatus, DoctorOptions, DoctorPromptCallbacks, DoctorResult, FixAction, FixResult } from "./doctor/types.mjs";
|
|
37
37
|
import { formatCheckResult, formatDoctorSummary, runDoctor } from "./doctor/doctor-service.mjs";
|
|
38
38
|
import "./doctor/index.mjs";
|
|
39
|
+
import { ContractVerificationStatus, DriftData, FinalizeResult, ImpactJson, PrActionOptions, ReportData, ReportInputs, RiskData, ValidationData, WhatChangedData } from "./action-pr/types.mjs";
|
|
40
|
+
import { PrActionService } from "./action-pr/service.mjs";
|
|
39
41
|
import { ALL_CI_CHECK_CATEGORIES, CICheckCategory, CICheckCategorySummary, CICheckOptions, CICheckResult, CIFormatOptions, CIIssue, CIIssueSeverity, CIOutputFormat, CI_CHECK_CATEGORY_LABELS } from "./ci-check/types.mjs";
|
|
40
42
|
import { runCIChecks } from "./ci-check/ci-check-service.mjs";
|
|
41
43
|
import "./ci-check/index.mjs";
|
|
@@ -72,7 +74,7 @@ import { createQuickAIReview, verifySemanticFields, verifyWithAI, verifyWithAIEn
|
|
|
72
74
|
import "./verify/index.mjs";
|
|
73
75
|
import { DiscoveryOptions, ImplementationSource, ImplementationStatus, ResolvedImplementation, ResolverOptions, SpecImplementationResult, SpecReferenceMatch } from "./implementation/types.mjs";
|
|
74
76
|
import { discoverAllImplementations, discoverImplementationsForSpec, extractSpecReferences, inferImplementationType } from "./implementation/discovery.mjs";
|
|
75
|
-
import {
|
|
77
|
+
import { parseExplicitImplementations } from "./implementation/resolver/parsers.mjs";
|
|
76
78
|
import { getConventionPaths, toKebabCase } from "./implementation/resolver/conventions.mjs";
|
|
77
79
|
import { determineStatus, getImplementationSummary } from "./implementation/resolver/status.mjs";
|
|
78
80
|
import { resolveAllImplementations, resolveImplementations } from "./implementation/resolver/index.mjs";
|
|
@@ -90,6 +92,8 @@ import { DocsServiceOptions, DocsServiceResult, generateDocsFromSpecs } from "./
|
|
|
90
92
|
import "./docs/index.mjs";
|
|
91
93
|
import { index_d_exports as index_d_exports$1 } from "./impact/index.mjs";
|
|
92
94
|
import { FormatterOptions, formatFiles } from "./formatter.mjs";
|
|
95
|
+
import { DriftActionOptions, DriftReportInputs, FinalizeDriftResult } from "./action-drift/types.mjs";
|
|
96
|
+
import { DriftActionService } from "./action-drift/service.mjs";
|
|
93
97
|
import { SpecVersionAnalysis } from "./versioning/types.mjs";
|
|
94
98
|
import { index_d_exports as index_d_exports$2 } from "./versioning/index.mjs";
|
|
95
99
|
import { index_d_exports as index_d_exports$3 } from "./upgrade/index.mjs";
|
package/dist/services/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { detectPackageManager, findPackageRoot, findWorkspaceRoot, getWorkspaceInfo } from "../adapters/workspace.mjs";
|
|
2
|
+
import { groupSpecsByType, listSpecs } from "./list.mjs";
|
|
2
3
|
import { validateSpec, validateSpecs } from "./validate/spec-validator.mjs";
|
|
3
4
|
import { validateImplementationFiles } from "./validate/implementation-validator.mjs";
|
|
4
5
|
import { validateBlueprint } from "./validate/blueprint-validator.mjs";
|
|
@@ -8,7 +9,6 @@ import "./validate/index.mjs";
|
|
|
8
9
|
import { features_exports } from "./features/index.mjs";
|
|
9
10
|
import { compareSpecs } from "./diff.mjs";
|
|
10
11
|
import { analyzeDeps, exportGraphAsDot, getContractNode, getGraphStats } from "./deps.mjs";
|
|
11
|
-
import { groupSpecsByType, listSpecs } from "./list.mjs";
|
|
12
12
|
import { getApiKey, loadWorkspaceConfig } from "./config.mjs";
|
|
13
13
|
import { buildSpec } from "./build.mjs";
|
|
14
14
|
import { importFromOpenApiService } from "./openapi/import-service.mjs";
|
|
@@ -35,10 +35,11 @@ import { runSetup } from "./setup/setup-service.mjs";
|
|
|
35
35
|
import { ALL_CHECK_CATEGORIES, CHECK_CATEGORY_LABELS } from "./doctor/types.mjs";
|
|
36
36
|
import { formatCheckResult, formatDoctorSummary, runDoctor } from "./doctor/doctor-service.mjs";
|
|
37
37
|
import "./doctor/index.mjs";
|
|
38
|
+
import { PrActionService } from "./action-pr/service.mjs";
|
|
38
39
|
import { ALL_CI_CHECK_CATEGORIES, CI_CHECK_CATEGORY_LABELS } from "./ci-check/types.mjs";
|
|
39
40
|
import { discoverAllImplementations, discoverImplementationsForSpec, extractSpecReferences, inferImplementationType } from "./implementation/discovery.mjs";
|
|
40
41
|
import { getConventionPaths, toKebabCase } from "./implementation/resolver/conventions.mjs";
|
|
41
|
-
import {
|
|
42
|
+
import { parseExplicitImplementations } from "./implementation/resolver/parsers.mjs";
|
|
42
43
|
import { determineStatus, getImplementationSummary } from "./implementation/resolver/status.mjs";
|
|
43
44
|
import { resolveAllImplementations, resolveImplementations } from "./implementation/resolver/index.mjs";
|
|
44
45
|
import { generateDocsFromSpecs } from "./docs/docs-service.mjs";
|
|
@@ -87,6 +88,7 @@ import { formatQuickstartPreview, isContractSpecInstalled, runQuickstart } from
|
|
|
87
88
|
import "./quickstart/index.mjs";
|
|
88
89
|
import { impact_exports } from "./impact/index.mjs";
|
|
89
90
|
import { formatFiles } from "./formatter.mjs";
|
|
91
|
+
import { DriftActionService } from "./action-drift/service.mjs";
|
|
90
92
|
import { versioning_exports } from "./versioning/index.mjs";
|
|
91
93
|
import { upgrade_exports } from "./upgrade/index.mjs";
|
|
92
94
|
import { hooks_exports } from "./hooks/index.mjs";
|
package/dist/services/list.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FsAdapter } from "../ports/fs.mjs";
|
|
2
2
|
import { SpecScanResult, scanSpecSource } from "@contractspec/module.workspace";
|
|
3
|
-
import {
|
|
3
|
+
import { ResolvedContractsrcConfig } from "@contractspec/lib.contracts";
|
|
4
|
+
import { MaybeArray } from "@contractspec/lib.utils-typescript";
|
|
4
5
|
|
|
5
6
|
//#region src/services/list.d.ts
|
|
6
7
|
|
|
@@ -15,11 +16,11 @@ interface ListSpecsOptions {
|
|
|
15
16
|
/**
|
|
16
17
|
* Filter by spec type.
|
|
17
18
|
*/
|
|
18
|
-
type?: string
|
|
19
|
+
type?: MaybeArray<string>;
|
|
19
20
|
/**
|
|
20
21
|
* Workspace configuration
|
|
21
22
|
*/
|
|
22
|
-
config?:
|
|
23
|
+
config?: ResolvedContractsrcConfig;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
26
|
* List all spec files in the workspace.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.mts","names":[],"sources":["../../src/services/list.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"list.d.mts","names":[],"sources":["../../src/services/list.ts"],"sourcesContent":[],"mappings":";;;;;;;AAqCA;;;AAEW,UAtBM,gBAAA,CAsBN;EACA;;;EA8DK,OAAA,CAAA,EAAA,MAAA;EACP;;;EACH,IAAA,CAAA,EA9EG,UA8EH,CAAA,MAAA,CAAA;;;;WAzEK;;;;;iBAMW,SAAA;MACJ;gBAAyB;aAChC,mBACR,QAAQ;;;;iBA8DK,gBAAA,QACP,mBACN,YAAY"}
|