@standards-kit/conform 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/dist/{chunk-P7TIZJ4C.js → chunk-DXIYZR62.js} +2 -2
- package/dist/chunk-DXIYZR62.js.map +1 -0
- package/dist/{chunk-RXA4FO7L.js → chunk-NADY2H35.js} +12 -8
- package/dist/chunk-NADY2H35.js.map +1 -0
- package/dist/chunk-O745CMWG.js +29 -0
- package/dist/chunk-O745CMWG.js.map +1 -0
- package/dist/chunk-RHM53NLG.js +49 -0
- package/dist/chunk-RHM53NLG.js.map +1 -0
- package/dist/{chunk-KHO6NIAI.js → chunk-YGDEM6K5.js} +24 -10
- package/dist/chunk-YGDEM6K5.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +49 -38
- package/dist/cli.js.map +1 -1
- package/dist/{cloudwatch-KSZ4A256.js → cloudwatch-3LTDYG6G.js} +6 -10
- package/dist/cloudwatch-3LTDYG6G.js.map +1 -0
- package/dist/code/index.d.ts +11 -0
- package/dist/code/tools/base.d.ts +51 -0
- package/dist/code/tools/comment-utils.d.ts +17 -0
- package/dist/code/tools/coverage-run.d.ts +37 -0
- package/dist/code/tools/disable-comments.d.ts +42 -0
- package/dist/code/tools/eslint.d.ts +99 -0
- package/dist/code/tools/gitleaks.d.ts +42 -0
- package/dist/code/tools/index.d.ts +13 -0
- package/dist/code/tools/knip.d.ts +20 -0
- package/dist/code/tools/naming.d.ts +64 -0
- package/dist/code/tools/pipaudit.d.ts +24 -0
- package/dist/code/tools/pnpmaudit.d.ts +36 -0
- package/dist/code/tools/ruff.d.ts +46 -0
- package/dist/code/tools/tsc.d.ts +57 -0
- package/dist/code/tools/ty.d.ts +34 -0
- package/dist/code/tools/vulture.d.ts +32 -0
- package/dist/constants.d.ts +69 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/loader.d.ts +42 -0
- package/dist/core/registry.d.ts +17 -0
- package/dist/core/schema.d.ts +1857 -0
- package/dist/core/types.d.ts +95 -0
- package/dist/{src-KZRTG3EU.js → core-QRFGIQ42.js} +4 -3
- package/dist/dependencies/index.d.ts +13 -0
- package/dist/dependencies/mappings.d.ts +17 -0
- package/dist/dependencies/output.d.ts +12 -0
- package/dist/dependencies/types.d.ts +34 -0
- package/dist/{dynamodb-5KVESCVJ.js → dynamodb-HQH3IMAI.js} +6 -10
- package/dist/dynamodb-HQH3IMAI.js.map +1 -0
- package/dist/{ec2-HKPE6GZV.js → ec2-AEPT735A.js} +6 -10
- package/dist/ec2-AEPT735A.js.map +1 -0
- package/dist/{ecs-OS3NJZTA.js → ecs-UHKCH5A7.js} +6 -10
- package/dist/ecs-UHKCH5A7.js.map +1 -0
- package/dist/{elasticache-7TCRHYYM.js → elasticache-5Y6K7GKJ.js} +6 -10
- package/dist/elasticache-5Y6K7GKJ.js.map +1 -0
- package/dist/{elb-PEDLXW5R.js → elb-CN6ELVM5.js} +6 -10
- package/dist/elb-CN6ELVM5.js.map +1 -0
- package/dist/{iam-7H5HFWVQ.js → iam-YXMHK2MV.js} +6 -2
- package/dist/iam-YXMHK2MV.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +99 -121
- package/dist/index.js.map +1 -1
- package/dist/infra/arn.d.ts +16 -0
- package/dist/infra/checkers/client-factory.d.ts +45 -0
- package/dist/infra/checkers/cloudwatch.d.ts +8 -0
- package/dist/infra/checkers/dynamodb.d.ts +8 -0
- package/dist/infra/checkers/ec2.d.ts +13 -0
- package/dist/infra/checkers/ecs.d.ts +13 -0
- package/dist/infra/checkers/elasticache.d.ts +13 -0
- package/dist/infra/checkers/elb.d.ts +13 -0
- package/dist/infra/checkers/gcp/artifactregistry.d.ts +5 -0
- package/dist/infra/checkers/gcp/cloudrun.d.ts +5 -0
- package/dist/infra/checkers/gcp/iam.d.ts +5 -0
- package/dist/infra/checkers/gcp/index.d.ts +17 -0
- package/dist/infra/checkers/gcp/secretmanager.d.ts +5 -0
- package/dist/infra/checkers/iam.d.ts +8 -0
- package/dist/infra/checkers/index.d.ts +26 -0
- package/dist/infra/checkers/lambda.d.ts +8 -0
- package/dist/infra/checkers/rds.d.ts +13 -0
- package/dist/infra/checkers/s3.d.ts +8 -0
- package/dist/infra/checkers/secretsmanager.d.ts +8 -0
- package/dist/infra/checkers/sns.d.ts +8 -0
- package/dist/infra/checkers/sqs.d.ts +8 -0
- package/dist/infra/checkers/types.d.ts +28 -0
- package/dist/infra/gcp.d.ts +18 -0
- package/dist/infra/generate.d.ts +74 -0
- package/dist/infra/index.d.ts +59 -0
- package/dist/infra/manifest.d.ts +58 -0
- package/dist/infra/output.d.ts +8 -0
- package/dist/infra/scan.d.ts +25 -0
- package/dist/infra/schemas.d.ts +806 -0
- package/dist/infra/types.d.ts +8 -0
- package/dist/{infra-UXM5XQX3.js → infra-TO54IUSC.js} +21 -19
- package/dist/infra-TO54IUSC.js.map +1 -0
- package/dist/{lambda-NFB5UILT.js → lambda-YTJOCYV5.js} +6 -10
- package/dist/lambda-YTJOCYV5.js.map +1 -0
- package/dist/mcp/index.d.ts +7 -0
- package/dist/mcp/server.d.ts +18 -0
- package/dist/mcp/standards/fetcher.d.ts +29 -0
- package/dist/mcp/standards/index.d.ts +4 -0
- package/dist/mcp/standards/matcher.d.ts +22 -0
- package/dist/mcp/standards/parser.d.ts +46 -0
- package/dist/mcp/standards/types.d.ts +32 -0
- package/dist/mcp/tools/get-guideline.d.ts +26 -0
- package/dist/mcp/tools/get-ruleset.d.ts +26 -0
- package/dist/mcp/tools/get-standards.d.ts +27 -0
- package/dist/mcp/tools/index.d.ts +4 -0
- package/dist/mcp/tools/list-guidelines.d.ts +25 -0
- package/dist/{mcp-O5O7XVFG.js → mcp-73FZXT3P.js} +5 -4
- package/dist/mcp-73FZXT3P.js.map +1 -0
- package/dist/output/index.d.ts +14 -0
- package/dist/process/commands/check-branch.d.ts +13 -0
- package/dist/process/commands/check-commit.d.ts +14 -0
- package/dist/process/commands/index.d.ts +2 -0
- package/dist/process/index.d.ts +11 -0
- package/dist/process/scan/index.d.ts +5 -0
- package/dist/process/scan/remote-fetcher.d.ts +18 -0
- package/dist/process/scan/scanner.d.ts +6 -0
- package/dist/process/scan/types.d.ts +57 -0
- package/dist/process/scan/validators.d.ts +37 -0
- package/dist/process/sync/applier.d.ts +10 -0
- package/dist/process/sync/differ.d.ts +7 -0
- package/dist/process/sync/fetcher.d.ts +14 -0
- package/dist/process/sync/index.d.ts +9 -0
- package/dist/process/sync/types.d.ts +131 -0
- package/dist/process/sync/validator.d.ts +22 -0
- package/dist/process/tools/backups.d.ts +32 -0
- package/dist/process/tools/base.d.ts +52 -0
- package/dist/process/tools/branches.d.ts +41 -0
- package/dist/process/tools/changesets.d.ts +53 -0
- package/dist/process/tools/ci.d.ts +57 -0
- package/dist/process/tools/codeowners.d.ts +68 -0
- package/dist/process/tools/commits.d.ts +39 -0
- package/dist/process/tools/coverage.d.ts +57 -0
- package/dist/process/tools/docs-helpers.d.ts +44 -0
- package/dist/process/tools/docs.d.ts +38 -0
- package/dist/process/tools/forbidden-files.d.ts +40 -0
- package/dist/process/tools/hooks.d.ts +39 -0
- package/dist/process/tools/index.d.ts +14 -0
- package/dist/process/tools/pr.d.ts +59 -0
- package/dist/process/tools/repo.d.ts +65 -0
- package/dist/process/tools/tickets.d.ts +42 -0
- package/dist/projects/detector.d.ts +16 -0
- package/dist/projects/index.d.ts +4 -0
- package/dist/projects/templates.d.ts +15 -0
- package/dist/projects/tier-loader.d.ts +21 -0
- package/dist/projects/types.d.ts +76 -0
- package/dist/{rds-KLG5O5SI.js → rds-GZ5RVPIU.js} +6 -10
- package/dist/rds-GZ5RVPIU.js.map +1 -0
- package/dist/{registry-V65CC7IN.js → registry-JRCQAIHR.js} +3 -2
- package/dist/{s3-2DH7PRVR.js → s3-53UELUWT.js} +16 -12
- package/dist/s3-53UELUWT.js.map +1 -0
- package/dist/s3-S4GXNR7H.js +53 -0
- package/dist/s3-S4GXNR7H.js.map +1 -0
- package/dist/{scan-EELS42BP.js → scan-RHQWHASY.js} +5 -4
- package/dist/{scan-EELS42BP.js.map → scan-RHQWHASY.js.map} +1 -1
- package/dist/{secretsmanager-MOOIHLAO.js → secretsmanager-FJKTPIXI.js} +6 -10
- package/dist/secretsmanager-FJKTPIXI.js.map +1 -0
- package/dist/{sns-Y36LVTWA.js → sns-RV64OMK2.js} +6 -10
- package/dist/sns-RV64OMK2.js.map +1 -0
- package/dist/{sqs-RRS3GRHK.js → sqs-MHBW6UFC.js} +6 -10
- package/dist/sqs-MHBW6UFC.js.map +1 -0
- package/dist/{standards-RXK5G4IG.js → standards-XAZKTKYJ.js} +3 -2
- package/dist/{sync-RLYBGYNY.js → sync-P3UZECLW.js} +4 -3
- package/dist/{sync-RLYBGYNY.js.map → sync-P3UZECLW.js.map} +1 -1
- package/dist/validate/guidelines.d.ts +18 -0
- package/dist/validate/index.d.ts +5 -0
- package/dist/validate/tier.d.ts +17 -0
- package/dist/validate/types.d.ts +50 -0
- package/dist/{validate-AABLVQJS.js → validate-J5E336GX.js} +53 -84
- package/dist/validate-J5E336GX.js.map +1 -0
- package/package.json +22 -25
- package/dist/chunk-KHO6NIAI.js.map +0 -1
- package/dist/chunk-P7TIZJ4C.js.map +0 -1
- package/dist/chunk-RXA4FO7L.js.map +0 -1
- package/dist/cloudwatch-KSZ4A256.js.map +0 -1
- package/dist/dynamodb-5KVESCVJ.js.map +0 -1
- package/dist/ec2-HKPE6GZV.js.map +0 -1
- package/dist/ecs-OS3NJZTA.js.map +0 -1
- package/dist/elasticache-7TCRHYYM.js.map +0 -1
- package/dist/elb-PEDLXW5R.js.map +0 -1
- package/dist/iam-7H5HFWVQ.js.map +0 -1
- package/dist/infra-UXM5XQX3.js.map +0 -1
- package/dist/lambda-NFB5UILT.js.map +0 -1
- package/dist/mcp-O5O7XVFG.js.map +0 -1
- package/dist/rds-KLG5O5SI.js.map +0 -1
- package/dist/s3-2DH7PRVR.js.map +0 -1
- package/dist/secretsmanager-MOOIHLAO.js.map +0 -1
- package/dist/sns-Y36LVTWA.js.map +0 -1
- package/dist/sqs-RRS3GRHK.js.map +0 -1
- package/dist/validate-AABLVQJS.js.map +0 -1
- /package/dist/{registry-V65CC7IN.js.map → core-QRFGIQ42.js.map} +0 -0
- /package/dist/{src-KZRTG3EU.js.map → registry-JRCQAIHR.js.map} +0 -0
- /package/dist/{standards-RXK5G4IG.js.map → standards-XAZKTKYJ.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infra/index.ts","../src/infra/output.ts","../src/infra/checkers/index.ts","../src/infra/checkers/gcp/index.ts","../src/infra/scan.ts"],"sourcesContent":["/**\n * Infra scan module - Public API\n *\n * Provides functionality to verify AWS resources declared in a manifest actually exist.\n */\n\nimport * as path from \"node:path\";\n\nimport chalk from \"chalk\";\n\nimport { getProjectRoot, loadConfigAsync } from \"@standards-kit/core\";\nimport { ExitCode } from \"@standards-kit/core\";\n\nimport { ManifestError, readManifest } from \"./manifest.js\";\nimport { formatScan } from \"./output.js\";\nimport { scanManifest } from \"./scan.js\";\nimport type { InfraScanResult, RunInfraScanOptions, ScanInfraOptions } from \"./types.js\";\n\n// Re-export types\nexport type {\n AccountId,\n AccountScanResult,\n Arn,\n CloudProvider,\n GcpResourcePath,\n InfraScanResult,\n InfraScanSummary,\n LegacyManifest,\n Manifest,\n ManifestAccount,\n MultiAccountManifest,\n ParsedArn,\n ParsedGcpResource,\n PulumiResource,\n PulumiStackExport,\n ResourceCheckResult,\n ResourceIdentifier,\n ScanInfraOptions,\n} from \"./types.js\";\n\n// Re-export Zod schemas and validation functions for public API\nexport {\n // Schemas - for external consumers to validate manifests\n ArnSchema,\n AccountIdSchema,\n AccountKeySchema,\n CloudProviderSchema,\n GcpResourcePathSchema,\n InfraScanResultSchema,\n InfraScanSummarySchema,\n LegacyManifestSchema,\n ManifestAccountSchema,\n ManifestSchema,\n MultiAccountManifestSchema,\n ParsedArnSchema,\n ParsedGcpResourceSchema,\n PulumiResourceSchema,\n PulumiStackExportSchema,\n ResourceCheckResultSchema,\n ResourceIdentifierSchema,\n // Validation functions\n isValidArnFormat,\n isValidGcpResourcePath,\n isValidAccountKey,\n isMultiAccountManifestSchema,\n isLegacyManifestSchema,\n validateArn,\n validateGcpResourcePath,\n validateAccountKey,\n validateManifest,\n validateMultiAccountManifest,\n validateLegacyManifest,\n validateStackExport,\n} from \"./types.js\";\nexport {\n ManifestError,\n isMultiAccountManifest,\n isLegacyManifest,\n parseAccountKey,\n formatAccountKey,\n normalizeManifest,\n detectAccountFromResource,\n getAllResources,\n} from \"./manifest.js\";\nexport { parseArn, isValidArn } from \"./arn.js\";\nexport { parseGcpResource, isValidGcpResource } from \"./gcp.js\";\nexport { SUPPORTED_SERVICES, isSupportedService } from \"./checkers/index.js\";\nexport { SUPPORTED_GCP_SERVICES, isSupportedGcpService } from \"./checkers/gcp/index.js\";\n\n// Re-export generate functionality\nexport {\n DEFAULT_MANIFEST_NAME,\n generateManifestFromStdin,\n generateManifestFromFile,\n generateMultiAccountFromStdin,\n generateMultiAccountFromFile,\n generateWithMerge,\n mergeIntoManifest,\n parseStackExport,\n parseStackExportMultiAccount,\n readExistingManifest,\n writeManifest,\n type GenerateManifestOptions,\n} from \"./generate.js\";\n\n/**\n * Scan infrastructure resources declared in a manifest.\n *\n * This is the programmatic API for drift-toolkit integration.\n *\n * @param options - Options for the scan\n * @returns Scan result with all resource check results and summary\n *\n * @example\n * ```typescript\n * import { scanInfra } from \"check-my-toolkit\";\n *\n * const result = await scanInfra({ manifestPath: \"./infra-manifest.json\" });\n * console.log(result.summary);\n * // { total: 5, found: 4, missing: 1, errors: 0 }\n * ```\n */\nexport async function scanInfra(options: ScanInfraOptions = {}): Promise<InfraScanResult> {\n const resolvedManifestPath = await resolveManifestPath(options);\n const manifest = readManifest(resolvedManifestPath);\n return scanManifest(manifest, resolvedManifestPath, { account: options.account });\n}\n\nasync function resolveManifestPath(options: ScanInfraOptions): Promise<string> {\n const { manifestPath, configPath } = options;\n\n if (manifestPath) {\n return path.isAbsolute(manifestPath)\n ? manifestPath\n : path.resolve(process.cwd(), manifestPath);\n }\n\n const { config, configPath: loadedConfigPath } = await loadConfigAsync(configPath);\n const projectRoot = getProjectRoot(loadedConfigPath);\n\n const infraConfig = config.infra;\n if (!infraConfig?.enabled) {\n throw new ManifestError(\"Infra scanning is not enabled in standards.toml\");\n }\n\n const manifestName = infraConfig.manifest;\n return path.resolve(projectRoot, manifestName);\n}\n\n/**\n * Run infra scan from CLI\n */\nexport async function runInfraScan(options: RunInfraScanOptions = {}): Promise<void> {\n const { format = \"text\", manifestPath, configPath, account } = options;\n\n try {\n const result = await scanInfra({ manifestPath, configPath, account });\n outputResult(result, format);\n } catch (error) {\n handleError(error, format);\n }\n}\n\nfunction outputResult(result: InfraScanResult, format: \"text\" | \"json\"): never {\n process.stdout.write(`${formatScan(result, format)}\\n`);\n\n if (result.summary.errors > 0) {\n process.exit(ExitCode.RUNTIME_ERROR);\n } else if (result.summary.missing > 0) {\n process.exit(ExitCode.VIOLATIONS_FOUND);\n } else {\n process.exit(ExitCode.SUCCESS);\n }\n}\n\nfunction handleError(error: unknown, format: \"text\" | \"json\"): never {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n const isConfigError = error instanceof ManifestError;\n\n if (format === \"json\") {\n process.stdout.write(`${JSON.stringify({ error: message }, null, 2)}\\n`);\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n\n process.exit(isConfigError ? ExitCode.CONFIG_ERROR : ExitCode.RUNTIME_ERROR);\n}\n\n/**\n * Options for CLI generate command\n */\nexport interface RunInfraGenerateOptions {\n /** Input file path (if not provided, reads from stdin) */\n input?: string;\n /** Output file path (defaults to infra-manifest.json) */\n output?: string;\n /** Project name override */\n project?: string;\n /** Output to stdout instead of file */\n stdout?: boolean;\n /** Account alias (e.g., \"prod-aws\") for multi-account manifests */\n account?: string;\n /** Explicit account ID (e.g., \"aws:111111111111\") */\n accountId?: string;\n /** Merge into existing manifest instead of overwriting */\n merge?: boolean;\n}\n\n/**\n * Run infra generate from CLI\n */\nexport async function runInfraGenerate(options: RunInfraGenerateOptions = {}): Promise<void> {\n const {\n generateWithMerge,\n writeManifest,\n DEFAULT_MANIFEST_NAME,\n } = await import(\"./generate.js\");\n const { getAllResources, isMultiAccountManifest } = await import(\"./manifest.js\");\n\n try {\n const manifest = await generateWithMerge(options.input, {\n project: options.project,\n output: options.output,\n account: options.account,\n accountId: options.accountId,\n merge: options.merge,\n });\n\n writeManifest(manifest, { output: options.output, stdout: options.stdout });\n\n if (!options.stdout) {\n const outputPath = options.output ?? DEFAULT_MANIFEST_NAME;\n const resourceCount = getAllResources(manifest).length;\n const accountCount = isMultiAccountManifest(manifest)\n ? Object.keys(manifest.accounts).length\n : 1;\n const accountLabel = accountCount === 1 ? \"account\" : \"accounts\";\n\n console.error(\n chalk.green(`✓ Generated ${outputPath} with ${resourceCount} resources across ${accountCount} ${accountLabel}`)\n );\n }\n\n process.exit(ExitCode.SUCCESS);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n console.error(chalk.red(`Error: ${message}`));\n process.exit(ExitCode.RUNTIME_ERROR);\n }\n}\n","/**\n * Output formatters for infra scan results\n */\n\nimport chalk from \"chalk\";\n\nimport type { AccountScanResult, InfraScanResult, ResourceCheckResult } from \"./types.js\";\n\n/**\n * Format scan result as text output\n */\nfunction formatScanText(result: InfraScanResult): string {\n const lines: string[] = [];\n\n formatHeader(lines, result);\n\n // If we have account results, format by account\n if (result.accountResults && Object.keys(result.accountResults).length > 0) {\n formatAccountResults(lines, result.accountResults);\n formatOverallSummary(lines, result.summary);\n } else {\n // Legacy format - flat results\n formatResultsByStatus(lines, result.results);\n formatSummary(lines, result.summary);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction formatHeader(lines: string[], result: InfraScanResult): void {\n lines.push(chalk.bold(\"Infrastructure Scan Results\"));\n lines.push(`Manifest: ${result.manifest}`);\n if (result.project) {\n lines.push(`Project: ${result.project}`);\n }\n lines.push(\"\");\n}\n\nfunction formatResultsByStatus(lines: string[], results: ResourceCheckResult[]): void {\n const found = results.filter((r) => r.exists && !r.error);\n const missing = results.filter((r) => !r.exists && !r.error);\n const errors = results.filter((r) => r.error);\n\n formatResultSection(lines, found, {\n colorFn: chalk.green.bold,\n label: \"Found\",\n formatLine: formatFoundLine,\n });\n formatResultSection(lines, missing, {\n colorFn: chalk.red.bold,\n label: \"Missing\",\n formatLine: formatMissingLine,\n });\n formatResultSection(lines, errors, {\n colorFn: chalk.yellow.bold,\n label: \"Errors\",\n formatLine: formatErrorLine,\n });\n}\n\ninterface SectionConfig {\n colorFn: (s: string) => string;\n label: string;\n formatLine: (r: ResourceCheckResult) => string;\n}\n\nfunction formatResultSection(\n lines: string[],\n results: ResourceCheckResult[],\n config: SectionConfig\n): void {\n if (results.length === 0) {\n return;\n }\n lines.push(config.colorFn(`${config.label} (${results.length}):`));\n for (const r of results) {\n lines.push(config.formatLine(r));\n }\n lines.push(\"\");\n}\n\nfunction formatFoundLine(r: ResourceCheckResult): string {\n const icon = chalk.green(\"✓\");\n const resourceInfo = `${r.service}/${r.resourceType}/${r.resourceId}`;\n return ` ${icon} ${resourceInfo}`;\n}\n\nfunction formatMissingLine(r: ResourceCheckResult): string {\n const icon = chalk.red(\"✗\");\n const resourceInfo = `${r.service}/${r.resourceType}/${r.resourceId}`;\n return ` ${icon} ${resourceInfo}`;\n}\n\nfunction formatErrorLine(r: ResourceCheckResult): string {\n const icon = chalk.yellow(\"!\");\n const resourceInfo = `${r.service}/${r.resourceType}/${r.resourceId}`;\n const errorText = r.error ?? \"Unknown error\";\n return ` ${icon} ${resourceInfo} - ${chalk.yellow(errorText)}`;\n}\n\nfunction formatSummary(\n lines: string[],\n summary: { total: number; found: number; missing: number; errors: number }\n): void {\n lines.push(chalk.bold(\"Summary:\"));\n lines.push(` Total: ${summary.total}`);\n lines.push(chalk.green(` Found: ${summary.found}`));\n lines.push(chalk.red(` Missing: ${summary.missing}`));\n if (summary.errors > 0) {\n lines.push(chalk.yellow(` Errors: ${summary.errors}`));\n }\n}\n\n/**\n * Format overall summary for multi-account manifests\n */\nfunction formatOverallSummary(\n lines: string[],\n summary: { total: number; found: number; missing: number; errors: number }\n): void {\n lines.push(chalk.bold(\"Overall Summary:\"));\n lines.push(` Total: ${summary.total}`);\n lines.push(chalk.green(` Found: ${summary.found}`));\n lines.push(chalk.red(` Missing: ${summary.missing}`));\n if (summary.errors > 0) {\n lines.push(chalk.yellow(` Errors: ${summary.errors}`));\n }\n}\n\n/**\n * Format results grouped by account\n */\nfunction formatAccountResults(\n lines: string[],\n accountResults: Record<string, AccountScanResult>\n): void {\n for (const [accountKey, account] of Object.entries(accountResults)) {\n const accountLabel = account.alias\n ? `${account.alias} (${accountKey})`\n : accountKey;\n\n lines.push(chalk.bold.cyan(`\\nAccount: ${accountLabel}`));\n lines.push(chalk.gray(\"─\".repeat(40)));\n\n // Format results for this account\n formatAccountResourceResults(lines, account.results);\n\n // Account-level summary\n const { summary } = account;\n const summaryParts: string[] = [];\n if (summary.found > 0) {\n summaryParts.push(chalk.green(`${summary.found} found`));\n }\n if (summary.missing > 0) {\n summaryParts.push(chalk.red(`${summary.missing} missing`));\n }\n if (summary.errors > 0) {\n summaryParts.push(chalk.yellow(`${summary.errors} errors`));\n }\n lines.push(` ${chalk.dim(\"Summary:\")} ${summaryParts.join(\", \")}`);\n }\n lines.push(\"\");\n}\n\n/**\n * Format resource results for a single account (inline style)\n */\nfunction formatAccountResourceResults(lines: string[], results: ResourceCheckResult[]): void {\n for (const r of results) {\n if (r.error) {\n const icon = chalk.yellow(\"!\");\n lines.push(` ${icon} ${r.arn} - ${chalk.yellow(r.error)}`);\n } else if (r.exists) {\n const icon = chalk.green(\"✓\");\n lines.push(` ${icon} ${r.arn}`);\n } else {\n const icon = chalk.red(\"✗\");\n lines.push(` ${icon} ${r.arn}`);\n }\n }\n}\n\n/**\n * Format scan result as JSON output\n */\nfunction formatScanJson(result: InfraScanResult): string {\n return JSON.stringify(result, null, 2);\n}\n\n/**\n * Format scan result based on output format\n */\nexport function formatScan(result: InfraScanResult, format: \"text\" | \"json\"): string {\n return format === \"json\" ? formatScanJson(result) : formatScanText(result);\n}\n","/**\n * Checker registry with lazy loading\n *\n * Checkers are loaded on-demand to avoid loading all AWS SDK clients upfront.\n */\n\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Supported AWS services for resource checking\n */\nexport const SUPPORTED_SERVICES = [\n \"s3\",\n \"lambda\",\n \"dynamodb\",\n \"sqs\",\n \"sns\",\n \"iam\",\n \"secretsmanager\",\n \"logs\",\n \"ecs\",\n \"rds\",\n \"ec2\",\n \"elasticache\",\n \"elasticloadbalancing\",\n] as const;\n\nexport type SupportedService = (typeof SUPPORTED_SERVICES)[number];\n\n/**\n * Check if a service is supported\n */\nexport function isSupportedService(service: string): service is SupportedService {\n return SUPPORTED_SERVICES.includes(service as SupportedService);\n}\n\n/**\n * Factory functions for checkers (lazy-loaded)\n */\nconst checkerFactories: Record<SupportedService, () => Promise<ResourceChecker>> = {\n s3: async () => (await import(\"./s3.js\")).S3Checker,\n lambda: async () => (await import(\"./lambda.js\")).LambdaChecker,\n dynamodb: async () => (await import(\"./dynamodb.js\")).DynamoDBChecker,\n sqs: async () => (await import(\"./sqs.js\")).SQSChecker,\n sns: async () => (await import(\"./sns.js\")).SNSChecker,\n iam: async () => (await import(\"./iam.js\")).IAMChecker,\n secretsmanager: async () => (await import(\"./secretsmanager.js\")).SecretsManagerChecker,\n logs: async () => (await import(\"./cloudwatch.js\")).CloudWatchLogsChecker,\n ecs: async () => (await import(\"./ecs.js\")).ECSChecker,\n rds: async () => (await import(\"./rds.js\")).RDSChecker,\n ec2: async () => (await import(\"./ec2.js\")).EC2Checker,\n elasticache: async () => (await import(\"./elasticache.js\")).ElastiCacheChecker,\n elasticloadbalancing: async () => (await import(\"./elb.js\")).ELBChecker,\n};\n\n/**\n * Cache of loaded checkers\n */\nconst checkerCache = new Map<SupportedService, ResourceChecker>();\n\n/**\n * Get a checker for a service, loading it if necessary\n *\n * @param service - The AWS service name\n * @returns The checker instance, or undefined if the service is not supported\n */\nexport async function getChecker(service: string): Promise<ResourceChecker | undefined> {\n if (!isSupportedService(service)) {\n return undefined;\n }\n\n // Return cached checker if available\n const cached = checkerCache.get(service);\n if (cached) {\n return cached;\n }\n\n // Load and cache the checker\n const factory = checkerFactories[service];\n const checker = await factory();\n checkerCache.set(service, checker);\n\n return checker;\n}\n\n/**\n * Clear the checker cache (useful for testing)\n */\nexport function clearCheckerCache(): void {\n checkerCache.clear();\n}\n","/**\n * GCP checker registry with lazy loading\n */\n\nimport type { GcpResourceChecker } from \"../types.js\";\n\n/**\n * Supported GCP services for resource checking\n */\nexport const SUPPORTED_GCP_SERVICES = [\"run\", \"secretmanager\", \"artifactregistry\", \"iam\"] as const;\n\nexport type SupportedGcpService = (typeof SUPPORTED_GCP_SERVICES)[number];\n\n/**\n * Check if a GCP service is supported\n */\nexport function isSupportedGcpService(service: string): service is SupportedGcpService {\n return SUPPORTED_GCP_SERVICES.includes(service as SupportedGcpService);\n}\n\n/**\n * Factory functions for GCP checkers (lazy-loaded)\n */\nconst checkerFactories: Record<SupportedGcpService, () => Promise<GcpResourceChecker>> = {\n run: async () => (await import(\"./cloudrun.js\")).CloudRunChecker,\n secretmanager: async () => (await import(\"./secretmanager.js\")).SecretManagerChecker,\n artifactregistry: async () => (await import(\"./artifactregistry.js\")).ArtifactRegistryChecker,\n iam: async () => (await import(\"./iam.js\")).ServiceAccountChecker,\n};\n\n/**\n * Cache of loaded GCP checkers\n */\nconst checkerCache = new Map<SupportedGcpService, GcpResourceChecker>();\n\n/**\n * Get a GCP checker for a service, loading it if necessary\n */\nexport async function getGcpChecker(service: string): Promise<GcpResourceChecker | undefined> {\n if (!isSupportedGcpService(service)) {\n return undefined;\n }\n\n const cached = checkerCache.get(service);\n if (cached) {\n return cached;\n }\n\n const factory = checkerFactories[service];\n const checker = await factory();\n checkerCache.set(service, checker);\n\n return checker;\n}\n","/**\n * Scan logic for infra scan\n *\n * Orchestrates checking all resources in a manifest (AWS and GCP)\n */\n\nimport { isValidArn, parseArn } from \"./arn.js\";\nimport { getChecker, isSupportedService, SUPPORTED_SERVICES } from \"./checkers/index.js\";\nimport {\n getGcpChecker,\n isSupportedGcpService,\n SUPPORTED_GCP_SERVICES,\n} from \"./checkers/gcp/index.js\";\nimport { isValidGcpResource, parseGcpResource } from \"./gcp.js\";\nimport { getAllResources, isMultiAccountManifest } from \"./manifest.js\";\nimport type {\n AccountScanResult,\n InfraScanResult,\n InfraScanSummary,\n Manifest,\n MultiAccountManifest,\n ResourceCheckResult,\n} from \"./types.js\";\n\n/**\n * Default concurrency for parallel checks\n */\nconst DEFAULT_CONCURRENCY = 10;\n\n/**\n * Options for scanning\n */\ninterface ScanOptions {\n /** Max number of parallel checks */\n concurrency?: number;\n /** Filter to specific account (by alias or account key) */\n account?: string;\n}\n\n/**\n * Scan all resources in a manifest\n *\n * @param manifest - The manifest containing resources to check\n * @param manifestPath - Path to the manifest file (for result metadata)\n * @param options - Scan options\n * @returns Scan result with all resource check results and summary\n */\nexport async function scanManifest(\n manifest: Manifest,\n manifestPath: string,\n options: ScanOptions = {}\n): Promise<InfraScanResult> {\n const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;\n\n // For multi-account manifests, scan by account\n if (isMultiAccountManifest(manifest)) {\n return scanMultiAccountManifest(manifest, manifestPath, options);\n }\n\n // Legacy manifest - simple flat scan\n const resources = getAllResources(manifest);\n const results = await checkResourcesWithConcurrency(resources, concurrency);\n const summary = calculateSummary(results);\n\n return {\n manifest: manifestPath,\n project: manifest.project,\n results,\n summary,\n };\n}\n\n/**\n * Scan a multi-account manifest\n */\nasync function scanMultiAccountManifest(\n manifest: MultiAccountManifest,\n manifestPath: string,\n options: ScanOptions = {}\n): Promise<InfraScanResult> {\n const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;\n const accountResults: Record<string, AccountScanResult> = {};\n const allResults: ResourceCheckResult[] = [];\n\n // Get accounts to scan (filter by account if specified)\n const accountsToScan = filterAccounts(manifest, options.account);\n\n for (const [accountKey, account] of Object.entries(accountsToScan)) {\n const results = await checkResourcesWithConcurrency(account.resources, concurrency);\n const summary = calculateSummary(results);\n\n accountResults[accountKey] = {\n alias: account.alias,\n results,\n summary,\n };\n\n allResults.push(...results);\n }\n\n // Calculate overall summary\n const overallSummary = calculateSummary(allResults);\n\n return {\n manifest: manifestPath,\n project: manifest.project,\n results: allResults,\n summary: overallSummary,\n accountResults,\n };\n}\n\n/**\n * Filter accounts based on account filter\n * Returns matching accounts or all accounts if no filter\n */\nfunction filterAccounts(\n manifest: MultiAccountManifest,\n accountFilter?: string\n): Record<string, { alias?: string; resources: string[] }> {\n if (!accountFilter) {\n return manifest.accounts;\n }\n\n // Check if filter is an account key (e.g., \"aws:123456\")\n if (accountFilter in manifest.accounts) {\n return { [accountFilter]: manifest.accounts[accountFilter] };\n }\n\n // Check if filter matches an alias\n for (const [key, account] of Object.entries(manifest.accounts)) {\n if (account.alias === accountFilter) {\n return { [key]: account };\n }\n }\n\n // No match found - return empty\n return {};\n}\n\n/**\n * Check resources with controlled concurrency using a simple batching approach\n */\nasync function checkResourcesWithConcurrency(\n arns: string[],\n concurrency: number\n): Promise<ResourceCheckResult[]> {\n const results: ResourceCheckResult[] = [];\n\n // Process in batches\n for (let i = 0; i < arns.length; i += concurrency) {\n const batch = arns.slice(i, i + concurrency);\n const batchResults = await Promise.all(batch.map((arn) => checkResource(arn)));\n results.push(...batchResults);\n }\n\n // Sort results to maintain consistent order (by ARN)\n results.sort((a, b) => a.arn.localeCompare(b.arn));\n\n return results;\n}\n\n/**\n * Check a single resource (AWS or GCP)\n */\nasync function checkResource(resource: string): Promise<ResourceCheckResult> {\n // Detect cloud provider and route to appropriate checker\n if (isValidArn(resource)) {\n return checkAwsResource(resource);\n }\n if (isValidGcpResource(resource)) {\n return checkGcpResource(resource);\n }\n\n return {\n arn: resource,\n exists: false,\n error: \"Invalid resource format (not a valid AWS ARN or GCP resource path)\",\n service: \"unknown\",\n resourceType: \"unknown\",\n resourceId: resource,\n };\n}\n\n/**\n * Check an AWS resource\n */\nasync function checkAwsResource(arn: string): Promise<ResourceCheckResult> {\n const parsed = parseArn(arn);\n if (!parsed) {\n return errorResult({ arn, error: \"Invalid ARN format\" });\n }\n\n if (!isSupportedService(parsed.service)) {\n const msg = `Unsupported AWS service: ${parsed.service}. Supported: ${SUPPORTED_SERVICES.join(\", \")}`;\n return errorResult({\n arn,\n error: msg,\n service: parsed.service,\n resourceType: parsed.resourceType,\n resourceId: parsed.resourceId,\n });\n }\n\n const checker = await getChecker(parsed.service);\n if (!checker) {\n return errorResult({ arn, error: `No checker for AWS service: ${parsed.service}`, service: parsed.service });\n }\n\n return checker.check(parsed);\n}\n\n/**\n * Check a GCP resource\n */\nasync function checkGcpResource(resource: string): Promise<ResourceCheckResult> {\n const parsed = parseGcpResource(resource);\n if (!parsed) {\n return errorResult({ arn: resource, error: \"Invalid GCP resource path format\" });\n }\n\n if (!isSupportedGcpService(parsed.service)) {\n const msg = `Unsupported GCP service: ${parsed.service}. Supported: ${SUPPORTED_GCP_SERVICES.join(\", \")}`;\n return errorResult({\n arn: resource,\n error: msg,\n service: parsed.service,\n resourceType: parsed.resourceType,\n resourceId: parsed.resourceId,\n });\n }\n\n const checker = await getGcpChecker(parsed.service);\n if (!checker) {\n return errorResult({ arn: resource, error: `No checker for GCP service: ${parsed.service}`, service: parsed.service });\n }\n\n return checker.check(parsed);\n}\n\ninterface ErrorResultParams {\n arn: string;\n error: string;\n service?: string;\n resourceType?: string;\n resourceId?: string;\n}\n\n/**\n * Create an error result\n */\nfunction errorResult(params: ErrorResultParams): ResourceCheckResult {\n const { arn, error, service = \"unknown\", resourceType = \"unknown\", resourceId = arn } = params;\n return { arn, exists: false, error, service, resourceType, resourceId };\n}\n\n/**\n * Calculate summary statistics from check results\n */\nfunction calculateSummary(results: ResourceCheckResult[]): InfraScanSummary {\n let found = 0;\n let missing = 0;\n let errors = 0;\n\n for (const result of results) {\n if (result.error) {\n errors++;\n } else if (result.exists) {\n found++;\n } else {\n missing++;\n }\n }\n\n return {\n total: results.length,\n found,\n missing,\n errors,\n };\n}\n"],"mappings":"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","names":["chalk","checkerFactories","checkerCache","chalk","generateWithMerge","writeManifest","DEFAULT_MANIFEST_NAME","getAllResources","isMultiAccountManifest"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infra/checkers/lambda.ts"],"sourcesContent":["/**\n * Lambda resource checker\n */\n\nimport { GetFunctionCommand, LambdaClient } from \"@aws-sdk/client-lambda\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of Lambda clients by region\n */\nconst clientCache = new Map<string, LambdaClient>();\n\n/**\n * Get or create a Lambda client for a region\n */\nfunction getClient(region: string): LambdaClient {\n let client = clientCache.get(region);\n if (!client) {\n client = new LambdaClient({ region });\n clientCache.set(region, client);\n }\n return client;\n}\n\n/**\n * Lambda function checker\n */\nexport const LambdaChecker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceType, resourceId, region, raw } = arn;\n\n // Only check functions (not layers for now)\n if (resourceType !== \"function\") {\n return {\n arn: raw,\n exists: false,\n error: `Unsupported Lambda resource type: ${resourceType}`,\n service: \"lambda\",\n resourceType,\n resourceId,\n };\n }\n\n const client = getClient(region);\n\n try {\n await client.send(new GetFunctionCommand({ FunctionName: resourceId }));\n return {\n arn: raw,\n exists: true,\n service: \"lambda\",\n resourceType: \"function\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"ResourceNotFoundException\") {\n return {\n arn: raw,\n exists: false,\n service: \"lambda\",\n resourceType: \"function\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"lambda\",\n resourceType: \"function\",\n resourceId,\n };\n }\n },\n};\n"],"mappings":";AAIA,SAAS,oBAAoB,oBAAoB;AAQjD,IAAM,cAAc,oBAAI,IAA0B;AAKlD,SAAS,UAAU,QAA8B;AAC/C,MAAI,SAAS,YAAY,IAAI,MAAM;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,aAAa,EAAE,OAAO,CAAC;AACpC,gBAAY,IAAI,QAAQ,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAKO,IAAM,gBAAiC;AAAA,EAC5C,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,cAAc,YAAY,QAAQ,IAAI,IAAI;AAGlD,QAAI,iBAAiB,YAAY;AAC/B,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,qCAAqC,YAAY;AAAA,QACxD,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,MAAM;AAE/B,QAAI;AACF,YAAM,OAAO,KAAK,IAAI,mBAAmB,EAAE,cAAc,WAAW,CAAC,CAAC;AACtE,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,MAAM;AAEZ,UAAI,IAAI,SAAS,6BAA6B;AAC5C,eAAO;AAAA,UACL,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,cAAc;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,WAAW;AAAA,QACtB,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/mcp-O5O7XVFG.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/server.ts","../src/mcp/tools/get-guideline.ts","../src/mcp/tools/get-ruleset.ts","../src/mcp/tools/get-standards.ts","../src/mcp/tools/list-guidelines.ts"],"sourcesContent":["/**\n * MCP Server for coding standards\n */\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { loadConfigAsync } from \"@standards-kit/core\";\nimport {\n createGetGuidelineHandler,\n getGuidelineInputSchema,\n createGetRulesetHandler,\n getRulesetInputSchema,\n createGetStandardsHandler,\n getStandardsInputSchema,\n createListGuidelinesHandler,\n listGuidelinesInputSchema,\n} from \"./tools/index.js\";\n\n/** Options for creating the MCP server */\nexport interface CreateServerOptions {\n /** Standards repository source (e.g., \"github:owner/repo\" or local path) */\n standardsSource?: string;\n}\n\n/**\n * Create and configure the MCP server with all tools registered.\n */\nexport function createServer(options: CreateServerOptions = {}): McpServer {\n const server = new McpServer({\n name: \"cm-standards\",\n version: \"1.0.0\",\n });\n\n const { standardsSource } = options;\n\n // Register get_standards tool - smart context matching\n server.registerTool(\"get_standards\", {\n description:\n \"Get composed coding standards matching a context string. Use this to fetch relevant guidelines for a specific technology stack or task.\",\n inputSchema: getStandardsInputSchema,\n }, createGetStandardsHandler(standardsSource));\n\n // Register list_guidelines tool\n server.registerTool(\"list_guidelines\", {\n description: \"List all available coding guidelines with optional category filter.\",\n inputSchema: listGuidelinesInputSchema,\n }, createListGuidelinesHandler(standardsSource));\n\n // Register get_guideline tool\n server.registerTool(\"get_guideline\", {\n description: \"Get a single coding guideline by its ID.\",\n inputSchema: getGuidelineInputSchema,\n }, createGetGuidelineHandler(standardsSource));\n\n // Register get_ruleset tool\n server.registerTool(\"get_ruleset\", {\n description:\n \"Get a tool configuration ruleset by ID (e.g., typescript-production, python-internal).\",\n inputSchema: getRulesetInputSchema,\n }, createGetRulesetHandler(standardsSource));\n\n return server;\n}\n\n/**\n * Start the MCP server with stdio transport.\n * Loads configuration from standards.toml to get the standards source.\n */\nexport async function startServer(): Promise<void> {\n let standardsSource: string | undefined;\n\n // Try to load config to get standards source\n try {\n const { config } = await loadConfigAsync();\n standardsSource = config.mcp?.standards?.source;\n } catch {\n // Config not found or invalid, use defaults\n }\n\n const server = createServer({ standardsSource });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","/**\n * MCP tool: get_guideline\n * Gets a single coding guideline by ID\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getGuidelinesDir,\n loadGuideline,\n} from \"../standards/index.js\";\n\n/** Input schema for get_guideline tool */\nexport const getGuidelineInputSchema = {\n id: z.string().describe('Guideline ID (e.g., \"auth\", \"database\", \"typescript\")'),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n isError?: boolean;\n}\n\n/**\n * Create a get_guideline handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createGetGuidelineHandler(\n source?: string\n): (args: { id: string }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const guidelinesDir = getGuidelinesDir(repoPath);\n const guideline = loadGuideline(guidelinesDir, args.id);\n\n if (!guideline) {\n return {\n content: [\n {\n type: \"text\",\n text: `Guideline not found: ${args.id}`,\n },\n ],\n isError: true,\n };\n }\n\n // Return full markdown content with frontmatter info\n const header = `# ${guideline.title}\\n\\n**Category:** ${guideline.category} | **Priority:** ${guideline.priority}\\n**Tags:** ${guideline.tags.join(\", \")}\\n\\n---\\n\\n`;\n\n return {\n content: [\n {\n type: \"text\",\n text: header + guideline.content,\n },\n ],\n };\n };\n}\n","/**\n * MCP tool: get_ruleset\n * Gets a tool configuration ruleset by ID\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getRulesetsDir,\n loadRuleset,\n listRulesets,\n} from \"../standards/index.js\";\n\n/** Input schema for get_ruleset tool */\nexport const getRulesetInputSchema = {\n id: z.string().describe('Ruleset ID (e.g., \"typescript-production\", \"python-internal\")'),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n isError?: boolean;\n}\n\n/**\n * Create a get_ruleset handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createGetRulesetHandler(\n source?: string\n): (args: { id: string }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const rulesetsDir = getRulesetsDir(repoPath);\n const ruleset = loadRuleset(rulesetsDir, args.id);\n\n if (!ruleset) {\n const available = listRulesets(rulesetsDir);\n return {\n content: [\n {\n type: \"text\",\n text: `Ruleset not found: ${args.id}\\n\\nAvailable rulesets:\\n${available.map((r) => `- ${r}`).join(\"\\n\")}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `# Ruleset: ${ruleset.id}\\n\\n\\`\\`\\`toml\\n${ruleset.content}\\n\\`\\`\\``,\n },\n ],\n };\n };\n}\n","/**\n * MCP tool: get_standards\n * Gets composed coding standards matching a context string\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getGuidelinesDir,\n loadAllGuidelines,\n matchGuidelines,\n composeGuidelines,\n} from \"../standards/index.js\";\n\n/** Input schema for get_standards tool */\nexport const getStandardsInputSchema = {\n context: z\n .string()\n .describe(\n 'Context string describing the task or technology stack (e.g., \"python fastapi llm postgresql\")'\n ),\n limit: z.number().optional().describe(\"Maximum number of guidelines to return (default: 5)\"),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n}\n\n/**\n * Create a get_standards handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createGetStandardsHandler(\n source?: string\n): (args: { context: string; limit?: number }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const guidelinesDir = getGuidelinesDir(repoPath);\n const guidelines = loadAllGuidelines(guidelinesDir);\n\n const limit = args.limit ?? 5;\n const matches = matchGuidelines(guidelines, args.context, limit);\n\n const composed = composeGuidelines(matches);\n\n // Add summary header\n const summary =\n matches.length > 0\n ? `Found ${matches.length} matching guideline(s) for context: \"${args.context}\"\\n\\nMatched guidelines (by relevance):\\n${matches.map((m) => `- ${m.guideline.title} (score: ${m.score.toFixed(1)})`).join(\"\\n\")}\\n\\n---\\n\\n`\n : \"\";\n\n return {\n content: [\n {\n type: \"text\",\n text: summary + composed,\n },\n ],\n };\n };\n}\n","/**\n * MCP tool: list_guidelines\n * Lists all available coding guidelines with optional category filter\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getGuidelinesDir,\n loadAllGuidelines,\n toListItems,\n} from \"../standards/index.js\";\n\n/** Input schema for list_guidelines tool */\nexport const listGuidelinesInputSchema = {\n category: z.string().optional().describe(\"Optional category filter (e.g., 'security', 'infrastructure')\"),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n}\n\n/**\n * Create a list_guidelines handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createListGuidelinesHandler(\n source?: string\n): (args: { category?: string }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const guidelinesDir = getGuidelinesDir(repoPath);\n let guidelines = loadAllGuidelines(guidelinesDir);\n\n // Filter by category if provided\n if (args.category) {\n const categoryLower = args.category.toLowerCase();\n guidelines = guidelines.filter((g) => g.category.toLowerCase() === categoryLower);\n }\n\n const items = toListItems(guidelines);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(items, null, 2),\n },\n ],\n };\n };\n}\n"],"mappings":"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","names":["z","z","z","z","z","z"]}
|
package/dist/rds-KLG5O5SI.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infra/checkers/rds.ts"],"sourcesContent":["/**\n * RDS resource checker\n *\n * Supports:\n * - DB instances\n * - DB clusters (Aurora)\n * - DB subnet groups\n */\n\nimport {\n DescribeDBInstancesCommand,\n DescribeDBClustersCommand,\n DescribeDBSubnetGroupsCommand,\n RDSClient,\n} from \"@aws-sdk/client-rds\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of RDS clients by region\n */\nconst clientCache = new Map<string, RDSClient>();\n\n/**\n * Get or create an RDS client for a region\n */\nfunction getClient(region: string): RDSClient {\n let client = clientCache.get(region);\n if (!client) {\n client = new RDSClient({ region });\n clientCache.set(region, client);\n }\n return client;\n}\n\n/**\n * Check if an RDS DB instance exists\n */\nasync function checkDBInstance(\n client: RDSClient,\n arn: ParsedArn\n): Promise<ResourceCheckResult> {\n const { resourceId, raw } = arn;\n\n try {\n const response = await client.send(\n new DescribeDBInstancesCommand({ DBInstanceIdentifier: resourceId })\n );\n\n const instance = response.DBInstances?.[0];\n const exists = !!instance && instance.DBInstanceStatus !== \"deleting\";\n\n return {\n arn: raw,\n exists,\n service: \"rds\",\n resourceType: \"db\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"DBInstanceNotFoundFault\") {\n return {\n arn: raw,\n exists: false,\n service: \"rds\",\n resourceType: \"db\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"rds\",\n resourceType: \"db\",\n resourceId,\n };\n }\n}\n\n/**\n * Check if an RDS DB cluster exists (Aurora)\n */\nasync function checkDBCluster(\n client: RDSClient,\n arn: ParsedArn\n): Promise<ResourceCheckResult> {\n const { resourceId, raw } = arn;\n\n try {\n const response = await client.send(\n new DescribeDBClustersCommand({ DBClusterIdentifier: resourceId })\n );\n\n const cluster = response.DBClusters?.[0];\n const exists = !!cluster && cluster.Status !== \"deleting\";\n\n return {\n arn: raw,\n exists,\n service: \"rds\",\n resourceType: \"cluster\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"DBClusterNotFoundFault\") {\n return {\n arn: raw,\n exists: false,\n service: \"rds\",\n resourceType: \"cluster\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"rds\",\n resourceType: \"cluster\",\n resourceId,\n };\n }\n}\n\n/**\n * Check if an RDS DB subnet group exists\n */\nasync function checkDBSubnetGroup(\n client: RDSClient,\n arn: ParsedArn\n): Promise<ResourceCheckResult> {\n const { resourceId, raw } = arn;\n\n try {\n const response = await client.send(\n new DescribeDBSubnetGroupsCommand({ DBSubnetGroupName: resourceId })\n );\n\n const subnetGroup = response.DBSubnetGroups?.[0];\n const exists = !!subnetGroup;\n\n return {\n arn: raw,\n exists,\n service: \"rds\",\n resourceType: \"subgrp\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"DBSubnetGroupNotFoundFault\") {\n return {\n arn: raw,\n exists: false,\n service: \"rds\",\n resourceType: \"subgrp\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"rds\",\n resourceType: \"subgrp\",\n resourceId,\n };\n }\n}\n\n/**\n * RDS resource checker\n */\nexport const RDSChecker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceType, resourceId, region, raw } = arn;\n const client = getClient(region);\n\n switch (resourceType) {\n case \"db\":\n return checkDBInstance(client, arn);\n\n case \"cluster\":\n return checkDBCluster(client, arn);\n\n case \"subgrp\":\n return checkDBSubnetGroup(client, arn);\n\n default:\n return {\n arn: raw,\n exists: false,\n error: `Unsupported RDS resource type: ${resourceType}`,\n service: \"rds\",\n resourceType,\n resourceId,\n };\n }\n },\n};\n"],"mappings":"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","names":[]}
|
package/dist/s3-2DH7PRVR.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infra/checkers/s3.ts"],"sourcesContent":["/**\n * S3 resource checker\n */\n\nimport { HeadBucketCommand, S3Client } from \"@aws-sdk/client-s3\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of S3 clients by region\n */\nconst clientCache = new Map<string, S3Client>();\n\n/**\n * Get or create an S3 client for a region\n */\nfunction getClient(region: string): S3Client {\n // S3 is global, but we use us-east-1 for global operations\n const effectiveRegion = region || \"us-east-1\";\n\n let client = clientCache.get(effectiveRegion);\n if (!client) {\n client = new S3Client({\n region: effectiveRegion,\n followRegionRedirects: true,\n });\n clientCache.set(effectiveRegion, client);\n }\n return client;\n}\n\n/**\n * S3 bucket checker\n */\nexport const S3Checker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceType, resourceId, raw } = arn;\n\n // Only check bucket existence (not individual objects)\n if (resourceType === \"object\") {\n // For objects, we'd need to check if the key exists, which is expensive\n // For now, we just check if the bucket exists\n const bucketName = resourceId.split(\"/\")[0];\n return checkBucket(bucketName, arn.region, raw);\n }\n\n return checkBucket(resourceId, arn.region, raw);\n },\n};\n\n/**\n * Create a bucket check result\n */\nfunction bucketResult(\n arn: string,\n bucketName: string,\n exists: boolean,\n error?: string\n): ResourceCheckResult {\n return { arn, exists, error, service: \"s3\", resourceType: \"bucket\", resourceId: bucketName };\n}\n\n/**\n * Check if error indicates bucket doesn't exist (404 or 403)\n */\nfunction isBucketNotFound(err: Error & { name?: string; $metadata?: { httpStatusCode?: number } }): boolean {\n const httpStatus = err.$metadata?.httpStatusCode;\n // 404 = not found, 403 = access denied (S3 returns 403 for non-existent buckets to prevent enumeration)\n return err.name === \"NotFound\" || err.name === \"NoSuchBucket\" || httpStatus === 404 ||\n err.name === \"Forbidden\" || err.name === \"AccessDenied\" || httpStatus === 403;\n}\n\n/**\n * Check if an S3 bucket exists\n */\nasync function checkBucket(bucketName: string, region: string, arn: string): Promise<ResourceCheckResult> {\n const client = getClient(region);\n\n try {\n await client.send(new HeadBucketCommand({ Bucket: bucketName }));\n return bucketResult(arn, bucketName, true);\n } catch (error) {\n const err = error as Error & { name?: string; $metadata?: { httpStatusCode?: number } };\n if (isBucketNotFound(err)) {\n return bucketResult(arn, bucketName, false);\n }\n return bucketResult(arn, bucketName, false, err.message || \"Unknown error\");\n }\n}\n"],"mappings":";AAIA,SAAS,mBAAmB,gBAAgB;AAQ5C,IAAM,cAAc,oBAAI,IAAsB;AAK9C,SAAS,UAAU,QAA0B;AAE3C,QAAM,kBAAkB,UAAU;AAElC,MAAI,SAAS,YAAY,IAAI,eAAe;AAC5C,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,SAAS;AAAA,MACpB,QAAQ;AAAA,MACR,uBAAuB;AAAA,IACzB,CAAC;AACD,gBAAY,IAAI,iBAAiB,MAAM;AAAA,EACzC;AACA,SAAO;AACT;AAKO,IAAM,YAA6B;AAAA,EACxC,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,cAAc,YAAY,IAAI,IAAI;AAG1C,QAAI,iBAAiB,UAAU;AAG7B,YAAM,aAAa,WAAW,MAAM,GAAG,EAAE,CAAC;AAC1C,aAAO,YAAY,YAAY,IAAI,QAAQ,GAAG;AAAA,IAChD;AAEA,WAAO,YAAY,YAAY,IAAI,QAAQ,GAAG;AAAA,EAChD;AACF;AAKA,SAAS,aACP,KACA,YACA,QACA,OACqB;AACrB,SAAO,EAAE,KAAK,QAAQ,OAAO,SAAS,MAAM,cAAc,UAAU,YAAY,WAAW;AAC7F;AAKA,SAAS,iBAAiB,KAAkF;AAC1G,QAAM,aAAa,IAAI,WAAW;AAElC,SAAO,IAAI,SAAS,cAAc,IAAI,SAAS,kBAAkB,eAAe,OACzE,IAAI,SAAS,eAAe,IAAI,SAAS,kBAAkB,eAAe;AACnF;AAKA,eAAe,YAAY,YAAoB,QAAgB,KAA2C;AACxG,QAAM,SAAS,UAAU,MAAM;AAE/B,MAAI;AACF,UAAM,OAAO,KAAK,IAAI,kBAAkB,EAAE,QAAQ,WAAW,CAAC,CAAC;AAC/D,WAAO,aAAa,KAAK,YAAY,IAAI;AAAA,EAC3C,SAAS,OAAO;AACd,UAAM,MAAM;AACZ,QAAI,iBAAiB,GAAG,GAAG;AACzB,aAAO,aAAa,KAAK,YAAY,KAAK;AAAA,IAC5C;AACA,WAAO,aAAa,KAAK,YAAY,OAAO,IAAI,WAAW,eAAe;AAAA,EAC5E;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infra/checkers/secretsmanager.ts"],"sourcesContent":["/**\n * Secrets Manager resource checker\n */\n\nimport { DescribeSecretCommand, SecretsManagerClient } from \"@aws-sdk/client-secrets-manager\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of Secrets Manager clients by region\n */\nconst clientCache = new Map<string, SecretsManagerClient>();\n\n/**\n * Get or create a Secrets Manager client for a region\n */\nfunction getClient(region: string): SecretsManagerClient {\n let client = clientCache.get(region);\n if (!client) {\n client = new SecretsManagerClient({ region });\n clientCache.set(region, client);\n }\n return client;\n}\n\n/**\n * Secrets Manager secret checker\n */\nexport const SecretsManagerChecker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceId, region, raw } = arn;\n\n const client = getClient(region);\n\n try {\n // Use the full ARN to get the secret\n await client.send(new DescribeSecretCommand({ SecretId: raw }));\n\n return {\n arn: raw,\n exists: true,\n service: \"secretsmanager\",\n resourceType: \"secret\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"ResourceNotFoundException\") {\n return {\n arn: raw,\n exists: false,\n service: \"secretsmanager\",\n resourceType: \"secret\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"secretsmanager\",\n resourceType: \"secret\",\n resourceId,\n };\n }\n },\n};\n"],"mappings":";AAIA,SAAS,uBAAuB,4BAA4B;AAQ5D,IAAM,cAAc,oBAAI,IAAkC;AAK1D,SAAS,UAAU,QAAsC;AACvD,MAAI,SAAS,YAAY,IAAI,MAAM;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,qBAAqB,EAAE,OAAO,CAAC;AAC5C,gBAAY,IAAI,QAAQ,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAKO,IAAM,wBAAyC;AAAA,EACpD,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,YAAY,QAAQ,IAAI,IAAI;AAEpC,UAAM,SAAS,UAAU,MAAM;AAE/B,QAAI;AAEF,YAAM,OAAO,KAAK,IAAI,sBAAsB,EAAE,UAAU,IAAI,CAAC,CAAC;AAE9D,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,MAAM;AAEZ,UAAI,IAAI,SAAS,6BAA6B;AAC5C,eAAO;AAAA,UACL,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,cAAc;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,WAAW;AAAA,QACtB,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/sns-Y36LVTWA.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infra/checkers/sns.ts"],"sourcesContent":["/**\n * SNS resource checker\n */\n\nimport { GetTopicAttributesCommand, SNSClient } from \"@aws-sdk/client-sns\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of SNS clients by region\n */\nconst clientCache = new Map<string, SNSClient>();\n\n/**\n * Get or create an SNS client for a region\n */\nfunction getClient(region: string): SNSClient {\n let client = clientCache.get(region);\n if (!client) {\n client = new SNSClient({ region });\n clientCache.set(region, client);\n }\n return client;\n}\n\n/**\n * SNS topic checker\n */\nexport const SNSChecker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceId, region, raw } = arn;\n\n const client = getClient(region);\n\n try {\n // Use the full ARN to get topic attributes\n await client.send(new GetTopicAttributesCommand({ TopicArn: raw }));\n\n return {\n arn: raw,\n exists: true,\n service: \"sns\",\n resourceType: \"topic\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"NotFoundException\" || err.name === \"NotFound\") {\n return {\n arn: raw,\n exists: false,\n service: \"sns\",\n resourceType: \"topic\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"sns\",\n resourceType: \"topic\",\n resourceId,\n };\n }\n },\n};\n"],"mappings":";AAIA,SAAS,2BAA2B,iBAAiB;AAQrD,IAAM,cAAc,oBAAI,IAAuB;AAK/C,SAAS,UAAU,QAA2B;AAC5C,MAAI,SAAS,YAAY,IAAI,MAAM;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,UAAU,EAAE,OAAO,CAAC;AACjC,gBAAY,IAAI,QAAQ,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAKO,IAAM,aAA8B;AAAA,EACzC,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,YAAY,QAAQ,IAAI,IAAI;AAEpC,UAAM,SAAS,UAAU,MAAM;AAE/B,QAAI;AAEF,YAAM,OAAO,KAAK,IAAI,0BAA0B,EAAE,UAAU,IAAI,CAAC,CAAC;AAElE,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,MAAM;AAEZ,UAAI,IAAI,SAAS,uBAAuB,IAAI,SAAS,YAAY;AAC/D,eAAO;AAAA,UACL,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,cAAc;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,WAAW;AAAA,QACtB,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/sqs-RRS3GRHK.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infra/checkers/sqs.ts"],"sourcesContent":["/**\n * SQS resource checker\n */\n\nimport { GetQueueAttributesCommand, GetQueueUrlCommand, SQSClient } from \"@aws-sdk/client-sqs\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of SQS clients by region\n */\nconst clientCache = new Map<string, SQSClient>();\n\n/**\n * Get or create an SQS client for a region\n */\nfunction getClient(region: string): SQSClient {\n let client = clientCache.get(region);\n if (!client) {\n client = new SQSClient({ region });\n clientCache.set(region, client);\n }\n return client;\n}\n\n/**\n * SQS queue checker\n */\nexport const SQSChecker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceId, region, accountId, raw } = arn;\n\n const client = getClient(region);\n\n try {\n // First, get the queue URL from the queue name and account ID\n const urlResponse = await client.send(\n new GetQueueUrlCommand({\n QueueName: resourceId,\n QueueOwnerAWSAccountId: accountId || undefined,\n })\n );\n\n // Then verify the queue exists by getting its attributes\n await client.send(\n new GetQueueAttributesCommand({\n QueueUrl: urlResponse.QueueUrl,\n AttributeNames: [\"QueueArn\"],\n })\n );\n\n return {\n arn: raw,\n exists: true,\n service: \"sqs\",\n resourceType: \"queue\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (\n err.name === \"QueueDoesNotExist\" ||\n err.name === \"AWS.SimpleQueueService.NonExistentQueue\"\n ) {\n return {\n arn: raw,\n exists: false,\n service: \"sqs\",\n resourceType: \"queue\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"sqs\",\n resourceType: \"queue\",\n resourceId,\n };\n }\n },\n};\n"],"mappings":";AAIA,SAAS,2BAA2B,oBAAoB,iBAAiB;AAQzE,IAAM,cAAc,oBAAI,IAAuB;AAK/C,SAAS,UAAU,QAA2B;AAC5C,MAAI,SAAS,YAAY,IAAI,MAAM;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,UAAU,EAAE,OAAO,CAAC;AACjC,gBAAY,IAAI,QAAQ,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAKO,IAAM,aAA8B;AAAA,EACzC,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,YAAY,QAAQ,WAAW,IAAI,IAAI;AAE/C,UAAM,SAAS,UAAU,MAAM;AAE/B,QAAI;AAEF,YAAM,cAAc,MAAM,OAAO;AAAA,QAC/B,IAAI,mBAAmB;AAAA,UACrB,WAAW;AAAA,UACX,wBAAwB,aAAa;AAAA,QACvC,CAAC;AAAA,MACH;AAGA,YAAM,OAAO;AAAA,QACX,IAAI,0BAA0B;AAAA,UAC5B,UAAU,YAAY;AAAA,UACtB,gBAAgB,CAAC,UAAU;AAAA,QAC7B,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,MAAM;AAEZ,UACE,IAAI,SAAS,uBACb,IAAI,SAAS,2CACb;AACA,eAAO;AAAA,UACL,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,cAAc;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,WAAW;AAAA,QACtB,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/validate/guidelines.ts","../src/validate/tier.ts","../src/validate/types.ts"],"sourcesContent":["/**\n * Validate guideline markdown files against the frontmatter schema\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport chalk from \"chalk\";\nimport matter from \"gray-matter\";\n\nimport { frontmatterSchema } from \"../mcp/standards/index.js\";\nimport { ExitCode } from \"@standards-kit/core\";\n\n/** Single file validation error */\nexport interface GuidelineValidationError {\n file: string;\n errors: string[];\n}\n\n/** Overall validation result */\nexport interface GuidelineValidationResult {\n valid: boolean;\n validCount: number;\n invalidCount: number;\n errors: GuidelineValidationError[];\n}\n\n/** Format text output for validation result */\nfunction formatTextOutput(result: GuidelineValidationResult): string {\n if (result.valid) {\n return chalk.green(`✓ All ${result.validCount} guideline(s) valid`);\n }\n const lines = [chalk.red(`✗ Found ${result.invalidCount} invalid guideline(s)`), \"\"];\n for (const err of result.errors) {\n lines.push(chalk.red(` ${err.file}:`));\n for (const e of err.errors) {\n lines.push(chalk.red(` - ${e}`));\n }\n }\n return lines.join(\"\\n\");\n}\n\n/** Validate a directory of guideline files */\nexport function validateGuidelinesDir(dirPath: string): GuidelineValidationResult {\n const files = fs.readdirSync(dirPath).filter((f) => f.endsWith(\".md\"));\n const result: GuidelineValidationResult = {\n valid: true,\n validCount: 0,\n invalidCount: 0,\n errors: [],\n };\n\n for (const file of files) {\n const filePath = path.join(dirPath, file);\n const content = fs.readFileSync(filePath, \"utf-8\");\n const { data } = matter(content);\n\n const parseResult = frontmatterSchema.safeParse(data);\n if (parseResult.success) {\n result.validCount++;\n } else {\n result.valid = false;\n result.invalidCount++;\n result.errors.push({\n file,\n errors: parseResult.error.errors.map((e) => `${e.path.join(\".\")}: ${e.message}`),\n });\n }\n }\n\n return result;\n}\n\n/** Output error and exit */\nfunction exitWithError(error: string, format: string): never {\n if (format === \"json\") {\n process.stdout.write(`${JSON.stringify({ valid: false, error }, null, 2)}\\n`);\n } else {\n console.error(chalk.red(`✗ ${error}`));\n }\n process.exit(ExitCode.CONFIG_ERROR);\n}\n\n/** Resolve and validate directory path */\nfunction resolveAndValidatePath(dirPath: string, format: string): string {\n const resolvedPath = path.isAbsolute(dirPath) ? dirPath : path.resolve(process.cwd(), dirPath);\n\n if (!fs.existsSync(resolvedPath)) {\n exitWithError(`Path does not exist: ${resolvedPath}`, format);\n }\n\n const stats = fs.statSync(resolvedPath);\n if (!stats.isDirectory()) {\n exitWithError(`Path is not a directory: ${resolvedPath}`, format);\n }\n\n return resolvedPath;\n}\n\n/** Run the validate guidelines command */\nexport async function runValidateGuidelines(\n dirPath: string,\n options: { format: string }\n): Promise<void> {\n const resolvedPath = resolveAndValidatePath(dirPath, options.format);\n const result = validateGuidelinesDir(resolvedPath);\n\n if (options.format === \"json\") {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n process.stdout.write(`${formatTextOutput(result)}\\n`);\n }\n\n process.exit(result.valid ? ExitCode.SUCCESS : ExitCode.CONFIG_ERROR);\n}\n","import { execSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport TOML from \"@iarna/toml\";\nimport chalk from \"chalk\";\nimport * as yaml from \"js-yaml\";\n\nimport { findConfigFile, getProjectRoot } from \"@standards-kit/core\";\nimport {\n type RepoMetadata,\n type Tier,\n type TierSourceDetail,\n VALID_TIERS,\n type ValidateTierOptions,\n type ValidateTierResult,\n} from \"./types.js\";\n\n/** Default tier when not specified */\nconst DEFAULT_TIER: Tier = \"internal\";\n\n/** Extends section from standards.toml */\ninterface ExtendsConfig {\n registry?: string;\n rulesets?: string[];\n}\n\n/** Raw standards.toml structure (just what we need) */\ninterface RawConfig {\n extends?: ExtendsConfig;\n}\n\n/** Result of loading repo-metadata.yaml with detailed source info */\ninterface LoadMetadataResult {\n metadata: RepoMetadata | null;\n sourceDetail: TierSourceDetail;\n parseError?: string;\n}\n\n/**\n * Find the git repository root directory\n */\nfunction findGitRoot(startDir: string): string | null {\n try {\n const gitRoot = execSync(\"git rev-parse --show-toplevel\", {\n cwd: startDir,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n return gitRoot;\n } catch {\n return null;\n }\n}\n\n/**\n * Read file content, returns null if file doesn't exist or can't be read\n */\nfunction readFileContent(filePath: string): string | null {\n if (!fs.existsSync(filePath)) {\n return null;\n }\n try {\n return fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Parse YAML content into RepoMetadata\n */\nfunction parseYamlContent(content: string): LoadMetadataResult {\n try {\n const parsed: unknown = yaml.load(content);\n // yaml.load returns undefined for empty content, null for \"null\"\n if (parsed === undefined || parsed === null) {\n return { metadata: null, sourceDetail: \"default (file empty)\" };\n }\n return { metadata: parsed as RepoMetadata, sourceDetail: \"repo-metadata.yaml\" };\n } catch (error) {\n const parseError = error instanceof Error ? error.message : String(error);\n return { metadata: null, sourceDetail: \"default (parse error)\", parseError };\n }\n}\n\n/**\n * Load and parse repo-metadata.yaml with detailed error tracking\n */\nfunction loadRepoMetadata(projectRoot: string): LoadMetadataResult {\n const metadataPath = path.join(projectRoot, \"repo-metadata.yaml\");\n const content = readFileContent(metadataPath);\n\n if (content === null) {\n return { metadata: null, sourceDetail: \"default (file not found)\" };\n }\n if (!content.trim()) {\n return { metadata: null, sourceDetail: \"default (file empty)\" };\n }\n\n return parseYamlContent(content);\n}\n\n/**\n * Load and parse standards.toml to get extends section\n */\nfunction loadExtendsConfig(configPath: string): ExtendsConfig | null {\n try {\n const content = fs.readFileSync(configPath, \"utf-8\");\n const parsed = TOML.parse(content) as RawConfig;\n return parsed.extends ?? null;\n } catch {\n return null;\n }\n}\n\n/** Result of getTier with detailed info */\ninterface GetTierResult {\n tier: Tier;\n source: \"repo-metadata.yaml\" | \"default\";\n sourceDetail: TierSourceDetail;\n invalidValue?: string;\n}\n\n/**\n * Get tier from repo-metadata.yaml with validation\n */\nfunction getTier(metadataResult: LoadMetadataResult): GetTierResult {\n const { metadata, sourceDetail } = metadataResult;\n\n // If metadata loading failed, return with the detailed reason\n if (!metadata) {\n return { tier: DEFAULT_TIER, source: \"default\", sourceDetail };\n }\n\n // Metadata exists but tier key is missing\n if (metadata.tier === undefined) {\n return { tier: DEFAULT_TIER, source: \"default\", sourceDetail: \"default (tier not specified)\" };\n }\n\n const tier = metadata.tier;\n\n // Check if tier value is valid\n if (!VALID_TIERS.includes(tier)) {\n return {\n tier: DEFAULT_TIER,\n source: \"default\",\n sourceDetail: \"default (invalid value)\",\n invalidValue: String(tier),\n };\n }\n\n return { tier, source: \"repo-metadata.yaml\", sourceDetail: \"repo-metadata.yaml\" };\n}\n\n/**\n * Check if rulesets include a tier-matching ruleset\n */\nfunction findMatchingRulesets(rulesets: string[], tier: Tier): string[] {\n const suffix = `-${tier}`;\n return rulesets.filter((ruleset) => ruleset.endsWith(suffix));\n}\n\n/**\n * Resolve the config path from options\n */\nfunction resolveConfigPath(options: ValidateTierOptions): string | null {\n if (options.config) {\n const absolutePath = path.resolve(options.config);\n return fs.existsSync(absolutePath) ? absolutePath : null;\n }\n return findConfigFile();\n}\n\n/**\n * Create result for missing config\n */\nfunction createNotFoundResult(): ValidateTierResult {\n return {\n valid: false,\n tier: DEFAULT_TIER,\n tierSource: \"default\",\n rulesets: [],\n expectedPattern: `*-${DEFAULT_TIER}`,\n matchedRulesets: [],\n error: \"No standards.toml found\",\n };\n}\n\n/** Options for building the result */\ninterface BuildResultOptions {\n tier: Tier;\n source: \"repo-metadata.yaml\" | \"default\";\n sourceDetail: TierSourceDetail;\n rulesets: string[];\n matchedRulesets: string[];\n invalidTierValue?: string;\n hasEmptyRulesets?: boolean;\n registryUrl?: string;\n warnings?: string[];\n parseError?: string;\n}\n\n/**\n * Build the validation result\n */\nfunction buildResult(options: BuildResultOptions): ValidateTierResult {\n const {\n tier,\n source,\n sourceDetail,\n rulesets,\n matchedRulesets,\n invalidTierValue,\n hasEmptyRulesets,\n registryUrl,\n parseError,\n } = options;\n const warnings: string[] = options.warnings ?? [];\n\n const expectedPattern = `*-${tier}`;\n const valid = rulesets.length === 0 || matchedRulesets.length > 0;\n\n // Add warning for invalid tier value\n if (invalidTierValue) {\n warnings.push(\n `Invalid tier '${invalidTierValue}' in repo-metadata.yaml. Valid values are: ${VALID_TIERS.join(\", \")}`\n );\n }\n\n // Add warning for parse error\n if (parseError) {\n warnings.push(`Failed to parse repo-metadata.yaml: ${parseError}`);\n }\n\n // Add warning for empty rulesets with registry configured\n if (hasEmptyRulesets && registryUrl) {\n warnings.push(\n `[extends] is configured with registry '${registryUrl}' but rulesets is empty - no standards will be inherited`\n );\n }\n\n return {\n valid,\n tier,\n tierSource: source,\n tierSourceDetail: sourceDetail,\n rulesets,\n expectedPattern,\n matchedRulesets,\n error: valid\n ? undefined\n : `No ruleset matching pattern '${expectedPattern}' found. Rulesets: [${rulesets.join(\", \")}]`,\n invalidTierValue,\n hasEmptyRulesets,\n registryUrl,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\n/**\n * Validate that project tier matches its rulesets.\n * This is the programmatic API exported for library consumers.\n */\nexport function validateTierRuleset(options: ValidateTierOptions = {}): ValidateTierResult {\n const configPath = resolveConfigPath(options);\n if (!configPath) {\n return createNotFoundResult();\n }\n\n // Try to find repo-metadata.yaml from git root first, fall back to config directory\n const configDir = getProjectRoot(configPath);\n const gitRoot = findGitRoot(configDir);\n const metadataSearchPath = gitRoot ?? configDir;\n\n const metadataResult = loadRepoMetadata(metadataSearchPath);\n const { tier, source, sourceDetail, invalidValue } = getTier(metadataResult);\n\n const extendsConfig = loadExtendsConfig(configPath);\n const rulesets = extendsConfig?.rulesets ?? [];\n const matchedRulesets = rulesets.length > 0 ? findMatchingRulesets(rulesets, tier) : [];\n\n // Detect empty rulesets with registry configured\n const hasEmptyRulesets = extendsConfig !== null && rulesets.length === 0;\n const registryUrl = extendsConfig?.registry;\n\n return buildResult({\n tier,\n source,\n sourceDetail,\n rulesets,\n matchedRulesets,\n invalidTierValue: invalidValue,\n hasEmptyRulesets,\n registryUrl,\n parseError: metadataResult.parseError,\n });\n}\n\n/** Format warnings section */\nfunction formatWarnings(warnings: string[] | undefined): string[] {\n if (!warnings || warnings.length === 0) {\n return [];\n }\n const lines = warnings.map((w) => chalk.yellow(`⚠ Warning: ${w}`));\n lines.push(\"\"); // Empty line after warnings\n return lines;\n}\n\n/** Format the rulesets message based on configuration */\nfunction formatRulesetsMessage(result: ValidateTierResult): string {\n if (result.matchedRulesets.length > 0) {\n return ` Matching rulesets: ${result.matchedRulesets.join(\", \")}`;\n }\n if (result.hasEmptyRulesets) {\n return \" No rulesets specified (no tier constraint)\";\n }\n return \" No extends configured (no tier constraint)\";\n}\n\n/** Format the failed validation section */\nfunction formatFailedValidation(result: ValidateTierResult, sourceDisplay: string): string[] {\n const lines = [\n chalk.red(\"✗ Tier validation failed\"),\n ` Tier: ${result.tier} (source: ${sourceDisplay})`,\n ` Expected pattern: ${result.expectedPattern}`,\n ` Rulesets: [${result.rulesets.join(\", \")}]`,\n ];\n if (result.error) {\n lines.push(chalk.red(` Error: ${result.error}`));\n }\n if (result.invalidTierValue) {\n lines.push(\"\");\n lines.push(\n chalk.cyan(\n ` Hint: Update repo-metadata.yaml to use a valid tier value: ${VALID_TIERS.join(\", \")}`\n )\n );\n }\n return lines;\n}\n\n/**\n * Format tier validation result as text\n */\nexport function formatTierResultText(result: ValidateTierResult): string {\n const lines: string[] = formatWarnings(result.warnings);\n const sourceDisplay = result.tierSourceDetail ?? result.tierSource;\n\n if (result.valid) {\n lines.push(chalk.green(\"✓ Tier validation passed\"));\n lines.push(` Tier: ${result.tier} (source: ${sourceDisplay})`);\n lines.push(formatRulesetsMessage(result));\n } else {\n lines.push(...formatFailedValidation(result, sourceDisplay));\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format tier validation result as JSON\n */\nexport function formatTierResultJson(result: ValidateTierResult): string {\n return JSON.stringify(result, null, 2);\n}\n","/**\n * Valid project tiers\n */\nexport type Tier = \"production\" | \"internal\" | \"prototype\";\n\n/**\n * Valid tier values as a constant array for validation and export\n */\nexport const VALID_TIERS: readonly Tier[] = [\"production\", \"internal\", \"prototype\"];\n\n/**\n * Parsed repo-metadata.yaml structure\n */\nexport interface RepoMetadata {\n tier?: Tier;\n}\n\n/**\n * Detailed tier source indicating why a default was used\n */\nexport type TierSourceDetail =\n | \"repo-metadata.yaml\" // Tier was read from file\n | \"default\" // Generic default (for backwards compatibility)\n | \"default (file not found)\" // File doesn't exist\n | \"default (file empty)\" // File exists but is empty\n | \"default (parse error)\" // File exists but YAML is invalid\n | \"default (tier not specified)\" // File valid but no tier key\n | \"default (invalid value)\"; // File has tier but value is invalid\n\n/**\n * Options for the tier validation command\n */\nexport interface ValidateTierOptions {\n /** Path to standards.toml config file */\n config?: string;\n /** Output format */\n format?: \"text\" | \"json\";\n}\n\n/**\n * Result of tier validation\n */\nexport interface ValidateTierResult {\n /** Whether validation passed */\n valid: boolean;\n /** Project tier from repo-metadata.yaml (defaults to \"internal\") */\n tier: Tier;\n /** Source of tier value */\n tierSource: \"repo-metadata.yaml\" | \"default\";\n /** Detailed source of tier value with reason for default */\n tierSourceDetail?: TierSourceDetail;\n /** Rulesets from standards.toml extends section */\n rulesets: string[];\n /** Expected ruleset suffix pattern */\n expectedPattern: string;\n /** Matched rulesets (those that satisfy the tier requirement) */\n matchedRulesets: string[];\n /** Error message if invalid */\n error?: string;\n /** Invalid tier value that was rejected (for error messages) */\n invalidTierValue?: string;\n /** Whether extends is configured but has empty rulesets */\n hasEmptyRulesets?: boolean;\n /** Registry URL if extends is configured */\n registryUrl?: string;\n /** Warnings about configuration */\n warnings?: string[];\n}\n"],"mappings":"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","names":["fs","path","chalk","chalk"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|