sdd-tool 0.3.0 → 0.5.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/README.md +320 -74
- package/dist/cli/index.js +4521 -1701
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
package/dist/index.d.ts
CHANGED
|
@@ -165,6 +165,7 @@ declare const ErrorCode: {
|
|
|
165
165
|
readonly CONSTITUTION_NOT_FOUND: "E301";
|
|
166
166
|
readonly CONSTITUTION_PARSE_ERROR: "E302";
|
|
167
167
|
readonly CONSTITUTION_VIOLATION: "E303";
|
|
168
|
+
readonly CONSTITUTION_VERSION_MISMATCH: "E304";
|
|
168
169
|
readonly PROPOSAL_NOT_FOUND: "E401";
|
|
169
170
|
readonly PROPOSAL_INVALID: "E402";
|
|
170
171
|
readonly DELTA_CONFLICT: "E403";
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ var ErrorCode = {
|
|
|
36
36
|
CONSTITUTION_NOT_FOUND: "E301",
|
|
37
37
|
CONSTITUTION_PARSE_ERROR: "E302",
|
|
38
38
|
CONSTITUTION_VIOLATION: "E303",
|
|
39
|
+
CONSTITUTION_VERSION_MISMATCH: "E304",
|
|
39
40
|
// 변경 워크플로우 에러 (E4xx)
|
|
40
41
|
PROPOSAL_NOT_FOUND: "E401",
|
|
41
42
|
PROPOSAL_INVALID: "E402",
|
|
@@ -68,6 +69,7 @@ var ErrorMessages = {
|
|
|
68
69
|
[ErrorCode.CONSTITUTION_NOT_FOUND]: "constitution.md\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
69
70
|
[ErrorCode.CONSTITUTION_PARSE_ERROR]: "Constitution \uD30C\uC2F1 \uC2E4\uD328: {0}",
|
|
70
71
|
[ErrorCode.CONSTITUTION_VIOLATION]: "Constitution \uC6D0\uCE59 \uC704\uBC18: {0}",
|
|
72
|
+
[ErrorCode.CONSTITUTION_VERSION_MISMATCH]: "Constitution \uBC84\uC804 \uBD88\uC77C\uCE58: {0}",
|
|
71
73
|
// 변경 워크플로우 에러
|
|
72
74
|
[ErrorCode.PROPOSAL_NOT_FOUND]: "\uC81C\uC548\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: {0}",
|
|
73
75
|
[ErrorCode.PROPOSAL_INVALID]: "\uC798\uBABB\uB41C \uC81C\uC548\uC11C \uD615\uC2DD: {0}",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/index.ts","../src/errors/codes.ts","../src/errors/messages.ts","../src/errors/base.ts"],"sourcesContent":["/**\r\n * 공통 타입 정의\r\n */\r\n\r\n// ============================================================\r\n// 스펙 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 스펙 문서 구조\r\n */\r\nexport interface Spec {\r\n id: string;\r\n title: string;\r\n status: SpecStatus;\r\n requirements: Requirement[];\r\n scenarios: Scenario[];\r\n dependencies: string[];\r\n metadata: SpecMetadata;\r\n}\r\n\r\nexport type SpecStatus = 'draft' | 'approved' | 'implemented';\r\n\r\nexport interface SpecMetadata {\r\n created?: string;\r\n updated?: string;\r\n author?: string;\r\n}\r\n\r\n/**\r\n * 요구사항 (RFC 2119)\r\n */\r\nexport interface Requirement {\r\n id: string;\r\n level: RequirementLevel;\r\n description: string;\r\n}\r\n\r\nexport type RequirementLevel = 'SHALL' | 'MUST' | 'SHOULD' | 'MAY';\r\n\r\n/**\r\n * 시나리오 (GIVEN-WHEN-THEN)\r\n */\r\nexport interface Scenario {\r\n name: string;\r\n given: string[];\r\n when: string;\r\n then: string[];\r\n}\r\n\r\n// ============================================================\r\n// Constitution 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * Constitution 원칙\r\n */\r\nexport interface Principle {\r\n id: string;\r\n title: string;\r\n description: string;\r\n level: PrincipleLevel;\r\n}\r\n\r\nexport type PrincipleLevel = 'core' | 'technical' | 'forbidden';\r\n\r\nexport interface Constitution {\r\n projectName: string;\r\n principles: Principle[];\r\n technicalStack?: string[];\r\n constraints?: string[];\r\n}\r\n\r\n// ============================================================\r\n// 변경 워크플로우 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 변경 제안\r\n */\r\nexport interface Proposal {\r\n id: string;\r\n title: string;\r\n rationale: string;\r\n affectedSpecs: string[];\r\n deltas: Delta[];\r\n status: ProposalStatus;\r\n createdAt: string;\r\n}\r\n\r\nexport type ProposalStatus = 'draft' | 'review' | 'approved' | 'applied' | 'archived';\r\n\r\n/**\r\n * 델타 (변경사항)\r\n */\r\nexport interface Delta {\r\n type: DeltaType;\r\n target: string;\r\n before?: string;\r\n after?: string;\r\n}\r\n\r\nexport type DeltaType = 'ADDED' | 'MODIFIED' | 'REMOVED';\r\n\r\n// ============================================================\r\n// 검증 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 검증 결과\r\n */\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: SpecValidationError[];\r\n warnings: SpecValidationWarning[];\r\n}\r\n\r\nexport interface SpecValidationError {\r\n code: string;\r\n message: string;\r\n location?: Location;\r\n}\r\n\r\nexport interface SpecValidationWarning {\r\n code: string;\r\n message: string;\r\n location?: Location;\r\n}\r\n\r\nexport interface Location {\r\n file?: string;\r\n line?: number;\r\n column?: number;\r\n}\r\n\r\n// ============================================================\r\n// 분석 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 분석 결과\r\n */\r\nexport interface AnalysisResult {\r\n scale: Scale;\r\n recommendation: WorkflowRecommendation;\r\n confidence: number;\r\n rationale: string;\r\n alternatives: string[];\r\n}\r\n\r\nexport type Scale = 'small' | 'medium' | 'large';\r\nexport type WorkflowRecommendation = 'direct' | 'change' | 'new';\r\n\r\n// ============================================================\r\n// 유틸리티 타입\r\n// ============================================================\r\n\r\n/**\r\n * Result 타입 (에러 처리용)\r\n */\r\nexport type Result<T, E = Error> =\r\n | { success: true; data: T }\r\n | { success: false; error: E };\r\n\r\n/**\r\n * 성공 결과 생성 헬퍼\r\n */\r\nexport function success<T>(data: T): Result<T, never> {\r\n return { success: true, data };\r\n}\r\n\r\n/**\r\n * 실패 결과 생성 헬퍼\r\n */\r\nexport function failure<E>(error: E): Result<never, E> {\r\n return { success: false, error };\r\n}\r\n","/**\r\n * 에러 코드 정의\r\n */\r\n\r\n/**\r\n * CLI 종료 코드\r\n */\r\nexport const ExitCode = {\r\n SUCCESS: 0,\r\n GENERAL_ERROR: 1,\r\n VALIDATION_FAILED: 2,\r\n CONSTITUTION_VIOLATION: 3,\r\n FILE_SYSTEM_ERROR: 4,\r\n USER_CANCELLED: 5,\r\n} as const;\r\n\r\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\r\n\r\n/**\r\n * 에러 코드\r\n */\r\nexport const ErrorCode = {\r\n // 일반 에러 (E0xx)\r\n UNKNOWN: 'E001',\r\n INVALID_ARGUMENT: 'E002',\r\n NOT_INITIALIZED: 'E003',\r\n\r\n // 파일 시스템 에러 (E1xx)\r\n FILE_NOT_FOUND: 'E101',\r\n FILE_READ_ERROR: 'E102',\r\n FILE_WRITE_ERROR: 'E103',\r\n DIRECTORY_NOT_FOUND: 'E104',\r\n DIRECTORY_EXISTS: 'E105',\r\n\r\n // 스펙 검증 에러 (E2xx)\r\n SPEC_PARSE_ERROR: 'E201',\r\n SPEC_INVALID_FORMAT: 'E202',\r\n SPEC_MISSING_REQUIRED: 'E203',\r\n RFC2119_VIOLATION: 'E204',\r\n GWT_INVALID_FORMAT: 'E205',\r\n\r\n // Constitution 에러 (E3xx)\r\n CONSTITUTION_NOT_FOUND: 'E301',\r\n CONSTITUTION_PARSE_ERROR: 'E302',\r\n CONSTITUTION_VIOLATION: 'E303',\r\n\r\n // 변경 워크플로우 에러 (E4xx)\r\n PROPOSAL_NOT_FOUND: 'E401',\r\n PROPOSAL_INVALID: 'E402',\r\n DELTA_CONFLICT: 'E403',\r\n ARCHIVE_FAILED: 'E404',\r\n\r\n // 분석 에러 (E5xx)\r\n ANALYSIS_FAILED: 'E501',\r\n INSUFFICIENT_DATA: 'E502',\r\n} as const;\r\n\r\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\r\n","/**\r\n * 에러 메시지 정의\r\n */\r\nimport { ErrorCode } from './codes.js';\r\n\r\n/**\r\n * 에러 코드별 메시지 템플릿\r\n */\r\nexport const ErrorMessages: Record<ErrorCode, string> = {\r\n // 일반 에러\r\n [ErrorCode.UNKNOWN]: '알 수 없는 오류가 발생했습니다',\r\n [ErrorCode.INVALID_ARGUMENT]: '잘못된 인자입니다: {0}',\r\n [ErrorCode.NOT_INITIALIZED]: 'SDD 프로젝트가 초기화되지 않았습니다. `sdd init`을 먼저 실행하세요',\r\n\r\n // 파일 시스템 에러\r\n [ErrorCode.FILE_NOT_FOUND]: '파일을 찾을 수 없습니다: {0}',\r\n [ErrorCode.FILE_READ_ERROR]: '파일 읽기 실패: {0}',\r\n [ErrorCode.FILE_WRITE_ERROR]: '파일 쓰기 실패: {0}',\r\n [ErrorCode.DIRECTORY_NOT_FOUND]: '디렉토리를 찾을 수 없습니다: {0}',\r\n [ErrorCode.DIRECTORY_EXISTS]: '디렉토리가 이미 존재합니다: {0}',\r\n\r\n // 스펙 검증 에러\r\n [ErrorCode.SPEC_PARSE_ERROR]: '스펙 파싱 실패: {0}',\r\n [ErrorCode.SPEC_INVALID_FORMAT]: '잘못된 스펙 형식: {0}',\r\n [ErrorCode.SPEC_MISSING_REQUIRED]: '필수 필드 누락: {0}',\r\n [ErrorCode.RFC2119_VIOLATION]: 'RFC 2119 형식 위반: {0}',\r\n [ErrorCode.GWT_INVALID_FORMAT]: 'GIVEN-WHEN-THEN 형식 위반: {0}',\r\n\r\n // Constitution 에러\r\n [ErrorCode.CONSTITUTION_NOT_FOUND]: 'constitution.md를 찾을 수 없습니다',\r\n [ErrorCode.CONSTITUTION_PARSE_ERROR]: 'Constitution 파싱 실패: {0}',\r\n [ErrorCode.CONSTITUTION_VIOLATION]: 'Constitution 원칙 위반: {0}',\r\n\r\n // 변경 워크플로우 에러\r\n [ErrorCode.PROPOSAL_NOT_FOUND]: '제안서를 찾을 수 없습니다: {0}',\r\n [ErrorCode.PROPOSAL_INVALID]: '잘못된 제안서 형식: {0}',\r\n [ErrorCode.DELTA_CONFLICT]: '델타 충돌: {0}',\r\n [ErrorCode.ARCHIVE_FAILED]: '아카이브 실패: {0}',\r\n\r\n // 분석 에러\r\n [ErrorCode.ANALYSIS_FAILED]: '분석 실패: {0}',\r\n [ErrorCode.INSUFFICIENT_DATA]: '분석에 필요한 데이터 부족: {0}',\r\n};\r\n\r\n/**\r\n * 메시지 템플릿에 인자를 적용\r\n */\r\nexport function formatMessage(code: ErrorCode, ...args: string[]): string {\r\n let message = ErrorMessages[code];\r\n args.forEach((arg, index) => {\r\n message = message.replace(`{${index}}`, arg);\r\n });\r\n return message;\r\n}\r\n","/**\r\n * 에러 기본 클래스\r\n */\r\nimport { ErrorCode, ExitCode } from './codes.js';\r\nimport { formatMessage } from './messages.js';\r\n\r\n/**\r\n * SDD 도구의 기본 에러 클래스\r\n */\r\nexport class SddError extends Error {\r\n readonly code: ErrorCode;\r\n readonly exitCode: ExitCode;\r\n\r\n constructor(\r\n code: ErrorCode,\r\n message?: string,\r\n exitCode: ExitCode = ExitCode.GENERAL_ERROR\r\n ) {\r\n super(message ?? formatMessage(code));\r\n this.name = 'SddError';\r\n this.code = code;\r\n this.exitCode = exitCode;\r\n Error.captureStackTrace?.(this, this.constructor);\r\n }\r\n\r\n /**\r\n * 사용자 친화적 메시지\r\n */\r\n toUserMessage(): string {\r\n return `[${this.code}] ${this.message}`;\r\n }\r\n}\r\n\r\n/**\r\n * 파일 시스템 에러\r\n */\r\nexport class FileSystemError extends SddError {\r\n readonly path: string;\r\n\r\n constructor(code: ErrorCode, path: string) {\r\n super(code, formatMessage(code, path), ExitCode.FILE_SYSTEM_ERROR);\r\n this.name = 'FileSystemError';\r\n this.path = path;\r\n }\r\n}\r\n\r\n/**\r\n * 스펙 검증 에러\r\n */\r\nexport class ValidationError extends SddError {\r\n readonly details: string;\r\n\r\n constructor(code: ErrorCode, details: string) {\r\n super(code, formatMessage(code, details), ExitCode.VALIDATION_FAILED);\r\n this.name = 'ValidationError';\r\n this.details = details;\r\n }\r\n}\r\n\r\n/**\r\n * Constitution 위반 에러\r\n */\r\nexport class ConstitutionError extends SddError {\r\n readonly principle: string;\r\n\r\n constructor(principle: string) {\r\n super(\r\n ErrorCode.CONSTITUTION_VIOLATION,\r\n formatMessage(ErrorCode.CONSTITUTION_VIOLATION, principle),\r\n ExitCode.CONSTITUTION_VIOLATION\r\n );\r\n this.name = 'ConstitutionError';\r\n this.principle = principle;\r\n }\r\n}\r\n\r\n/**\r\n * 사용자 취소 에러\r\n */\r\nexport class UserCancelledError extends SddError {\r\n constructor(message = '사용자가 작업을 취소했습니다') {\r\n super(ErrorCode.UNKNOWN, message, ExitCode.USER_CANCELLED);\r\n this.name = 'UserCancelledError';\r\n }\r\n}\r\n\r\n/**\r\n * 변경 워크플로우 에러\r\n */\r\nexport class ChangeError extends SddError {\r\n constructor(message: string) {\r\n super(ErrorCode.UNKNOWN, message, ExitCode.GENERAL_ERROR);\r\n this.name = 'ChangeError';\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types/index.ts","../src/errors/codes.ts","../src/errors/messages.ts","../src/errors/base.ts"],"sourcesContent":["/**\r\n * 공통 타입 정의\r\n */\r\n\r\n// ============================================================\r\n// 스펙 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 스펙 문서 구조\r\n */\r\nexport interface Spec {\r\n id: string;\r\n title: string;\r\n status: SpecStatus;\r\n requirements: Requirement[];\r\n scenarios: Scenario[];\r\n dependencies: string[];\r\n metadata: SpecMetadata;\r\n}\r\n\r\nexport type SpecStatus = 'draft' | 'approved' | 'implemented';\r\n\r\nexport interface SpecMetadata {\r\n created?: string;\r\n updated?: string;\r\n author?: string;\r\n}\r\n\r\n/**\r\n * 요구사항 (RFC 2119)\r\n */\r\nexport interface Requirement {\r\n id: string;\r\n level: RequirementLevel;\r\n description: string;\r\n}\r\n\r\nexport type RequirementLevel = 'SHALL' | 'MUST' | 'SHOULD' | 'MAY';\r\n\r\n/**\r\n * 시나리오 (GIVEN-WHEN-THEN)\r\n */\r\nexport interface Scenario {\r\n name: string;\r\n given: string[];\r\n when: string;\r\n then: string[];\r\n}\r\n\r\n// ============================================================\r\n// Constitution 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * Constitution 원칙\r\n */\r\nexport interface Principle {\r\n id: string;\r\n title: string;\r\n description: string;\r\n level: PrincipleLevel;\r\n}\r\n\r\nexport type PrincipleLevel = 'core' | 'technical' | 'forbidden';\r\n\r\nexport interface Constitution {\r\n projectName: string;\r\n principles: Principle[];\r\n technicalStack?: string[];\r\n constraints?: string[];\r\n}\r\n\r\n// ============================================================\r\n// 변경 워크플로우 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 변경 제안\r\n */\r\nexport interface Proposal {\r\n id: string;\r\n title: string;\r\n rationale: string;\r\n affectedSpecs: string[];\r\n deltas: Delta[];\r\n status: ProposalStatus;\r\n createdAt: string;\r\n}\r\n\r\nexport type ProposalStatus = 'draft' | 'review' | 'approved' | 'applied' | 'archived';\r\n\r\n/**\r\n * 델타 (변경사항)\r\n */\r\nexport interface Delta {\r\n type: DeltaType;\r\n target: string;\r\n before?: string;\r\n after?: string;\r\n}\r\n\r\nexport type DeltaType = 'ADDED' | 'MODIFIED' | 'REMOVED';\r\n\r\n// ============================================================\r\n// 검증 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 검증 결과\r\n */\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: SpecValidationError[];\r\n warnings: SpecValidationWarning[];\r\n}\r\n\r\nexport interface SpecValidationError {\r\n code: string;\r\n message: string;\r\n location?: Location;\r\n}\r\n\r\nexport interface SpecValidationWarning {\r\n code: string;\r\n message: string;\r\n location?: Location;\r\n}\r\n\r\nexport interface Location {\r\n file?: string;\r\n line?: number;\r\n column?: number;\r\n}\r\n\r\n// ============================================================\r\n// 분석 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 분석 결과\r\n */\r\nexport interface AnalysisResult {\r\n scale: Scale;\r\n recommendation: WorkflowRecommendation;\r\n confidence: number;\r\n rationale: string;\r\n alternatives: string[];\r\n}\r\n\r\nexport type Scale = 'small' | 'medium' | 'large';\r\nexport type WorkflowRecommendation = 'direct' | 'change' | 'new';\r\n\r\n// ============================================================\r\n// 유틸리티 타입\r\n// ============================================================\r\n\r\n/**\r\n * Result 타입 (에러 처리용)\r\n */\r\nexport type Result<T, E = Error> =\r\n | { success: true; data: T }\r\n | { success: false; error: E };\r\n\r\n/**\r\n * 성공 결과 생성 헬퍼\r\n */\r\nexport function success<T>(data: T): Result<T, never> {\r\n return { success: true, data };\r\n}\r\n\r\n/**\r\n * 실패 결과 생성 헬퍼\r\n */\r\nexport function failure<E>(error: E): Result<never, E> {\r\n return { success: false, error };\r\n}\r\n","/**\r\n * 에러 코드 정의\r\n */\r\n\r\n/**\r\n * CLI 종료 코드\r\n */\r\nexport const ExitCode = {\r\n SUCCESS: 0,\r\n GENERAL_ERROR: 1,\r\n VALIDATION_FAILED: 2,\r\n CONSTITUTION_VIOLATION: 3,\r\n FILE_SYSTEM_ERROR: 4,\r\n USER_CANCELLED: 5,\r\n} as const;\r\n\r\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\r\n\r\n/**\r\n * 에러 코드\r\n */\r\nexport const ErrorCode = {\r\n // 일반 에러 (E0xx)\r\n UNKNOWN: 'E001',\r\n INVALID_ARGUMENT: 'E002',\r\n NOT_INITIALIZED: 'E003',\r\n\r\n // 파일 시스템 에러 (E1xx)\r\n FILE_NOT_FOUND: 'E101',\r\n FILE_READ_ERROR: 'E102',\r\n FILE_WRITE_ERROR: 'E103',\r\n DIRECTORY_NOT_FOUND: 'E104',\r\n DIRECTORY_EXISTS: 'E105',\r\n\r\n // 스펙 검증 에러 (E2xx)\r\n SPEC_PARSE_ERROR: 'E201',\r\n SPEC_INVALID_FORMAT: 'E202',\r\n SPEC_MISSING_REQUIRED: 'E203',\r\n RFC2119_VIOLATION: 'E204',\r\n GWT_INVALID_FORMAT: 'E205',\r\n\r\n // Constitution 에러 (E3xx)\r\n CONSTITUTION_NOT_FOUND: 'E301',\r\n CONSTITUTION_PARSE_ERROR: 'E302',\r\n CONSTITUTION_VIOLATION: 'E303',\r\n CONSTITUTION_VERSION_MISMATCH: 'E304',\r\n\r\n // 변경 워크플로우 에러 (E4xx)\r\n PROPOSAL_NOT_FOUND: 'E401',\r\n PROPOSAL_INVALID: 'E402',\r\n DELTA_CONFLICT: 'E403',\r\n ARCHIVE_FAILED: 'E404',\r\n\r\n // 분석 에러 (E5xx)\r\n ANALYSIS_FAILED: 'E501',\r\n INSUFFICIENT_DATA: 'E502',\r\n} as const;\r\n\r\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\r\n","/**\r\n * 에러 메시지 정의\r\n */\r\nimport { ErrorCode } from './codes.js';\r\n\r\n/**\r\n * 에러 코드별 메시지 템플릿\r\n */\r\nexport const ErrorMessages: Record<ErrorCode, string> = {\r\n // 일반 에러\r\n [ErrorCode.UNKNOWN]: '알 수 없는 오류가 발생했습니다',\r\n [ErrorCode.INVALID_ARGUMENT]: '잘못된 인자입니다: {0}',\r\n [ErrorCode.NOT_INITIALIZED]: 'SDD 프로젝트가 초기화되지 않았습니다. `sdd init`을 먼저 실행하세요',\r\n\r\n // 파일 시스템 에러\r\n [ErrorCode.FILE_NOT_FOUND]: '파일을 찾을 수 없습니다: {0}',\r\n [ErrorCode.FILE_READ_ERROR]: '파일 읽기 실패: {0}',\r\n [ErrorCode.FILE_WRITE_ERROR]: '파일 쓰기 실패: {0}',\r\n [ErrorCode.DIRECTORY_NOT_FOUND]: '디렉토리를 찾을 수 없습니다: {0}',\r\n [ErrorCode.DIRECTORY_EXISTS]: '디렉토리가 이미 존재합니다: {0}',\r\n\r\n // 스펙 검증 에러\r\n [ErrorCode.SPEC_PARSE_ERROR]: '스펙 파싱 실패: {0}',\r\n [ErrorCode.SPEC_INVALID_FORMAT]: '잘못된 스펙 형식: {0}',\r\n [ErrorCode.SPEC_MISSING_REQUIRED]: '필수 필드 누락: {0}',\r\n [ErrorCode.RFC2119_VIOLATION]: 'RFC 2119 형식 위반: {0}',\r\n [ErrorCode.GWT_INVALID_FORMAT]: 'GIVEN-WHEN-THEN 형식 위반: {0}',\r\n\r\n // Constitution 에러\r\n [ErrorCode.CONSTITUTION_NOT_FOUND]: 'constitution.md를 찾을 수 없습니다',\r\n [ErrorCode.CONSTITUTION_PARSE_ERROR]: 'Constitution 파싱 실패: {0}',\r\n [ErrorCode.CONSTITUTION_VIOLATION]: 'Constitution 원칙 위반: {0}',\r\n [ErrorCode.CONSTITUTION_VERSION_MISMATCH]: 'Constitution 버전 불일치: {0}',\r\n\r\n // 변경 워크플로우 에러\r\n [ErrorCode.PROPOSAL_NOT_FOUND]: '제안서를 찾을 수 없습니다: {0}',\r\n [ErrorCode.PROPOSAL_INVALID]: '잘못된 제안서 형식: {0}',\r\n [ErrorCode.DELTA_CONFLICT]: '델타 충돌: {0}',\r\n [ErrorCode.ARCHIVE_FAILED]: '아카이브 실패: {0}',\r\n\r\n // 분석 에러\r\n [ErrorCode.ANALYSIS_FAILED]: '분석 실패: {0}',\r\n [ErrorCode.INSUFFICIENT_DATA]: '분석에 필요한 데이터 부족: {0}',\r\n};\r\n\r\n/**\r\n * 메시지 템플릿에 인자를 적용\r\n */\r\nexport function formatMessage(code: ErrorCode, ...args: string[]): string {\r\n let message = ErrorMessages[code];\r\n args.forEach((arg, index) => {\r\n message = message.replace(`{${index}}`, arg);\r\n });\r\n return message;\r\n}\r\n","/**\r\n * 에러 기본 클래스\r\n */\r\nimport { ErrorCode, ExitCode } from './codes.js';\r\nimport { formatMessage } from './messages.js';\r\n\r\n/**\r\n * SDD 도구의 기본 에러 클래스\r\n */\r\nexport class SddError extends Error {\r\n readonly code: ErrorCode;\r\n readonly exitCode: ExitCode;\r\n\r\n constructor(\r\n code: ErrorCode,\r\n message?: string,\r\n exitCode: ExitCode = ExitCode.GENERAL_ERROR\r\n ) {\r\n super(message ?? formatMessage(code));\r\n this.name = 'SddError';\r\n this.code = code;\r\n this.exitCode = exitCode;\r\n Error.captureStackTrace?.(this, this.constructor);\r\n }\r\n\r\n /**\r\n * 사용자 친화적 메시지\r\n */\r\n toUserMessage(): string {\r\n return `[${this.code}] ${this.message}`;\r\n }\r\n}\r\n\r\n/**\r\n * 파일 시스템 에러\r\n */\r\nexport class FileSystemError extends SddError {\r\n readonly path: string;\r\n\r\n constructor(code: ErrorCode, path: string) {\r\n super(code, formatMessage(code, path), ExitCode.FILE_SYSTEM_ERROR);\r\n this.name = 'FileSystemError';\r\n this.path = path;\r\n }\r\n}\r\n\r\n/**\r\n * 스펙 검증 에러\r\n */\r\nexport class ValidationError extends SddError {\r\n readonly details: string;\r\n\r\n constructor(code: ErrorCode, details: string) {\r\n super(code, formatMessage(code, details), ExitCode.VALIDATION_FAILED);\r\n this.name = 'ValidationError';\r\n this.details = details;\r\n }\r\n}\r\n\r\n/**\r\n * Constitution 위반 에러\r\n */\r\nexport class ConstitutionError extends SddError {\r\n readonly principle: string;\r\n\r\n constructor(principle: string) {\r\n super(\r\n ErrorCode.CONSTITUTION_VIOLATION,\r\n formatMessage(ErrorCode.CONSTITUTION_VIOLATION, principle),\r\n ExitCode.CONSTITUTION_VIOLATION\r\n );\r\n this.name = 'ConstitutionError';\r\n this.principle = principle;\r\n }\r\n}\r\n\r\n/**\r\n * 사용자 취소 에러\r\n */\r\nexport class UserCancelledError extends SddError {\r\n constructor(message = '사용자가 작업을 취소했습니다') {\r\n super(ErrorCode.UNKNOWN, message, ExitCode.USER_CANCELLED);\r\n this.name = 'UserCancelledError';\r\n }\r\n}\r\n\r\n/**\r\n * 변경 워크플로우 에러\r\n */\r\nexport class ChangeError extends SddError {\r\n constructor(message: string) {\r\n super(ErrorCode.UNKNOWN, message, ExitCode.GENERAL_ERROR);\r\n this.name = 'ChangeError';\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sdd-tool",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Unified Spec-Driven Development CLI - AI-first specification workflow",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -34,20 +34,21 @@
|
|
|
34
34
|
},
|
|
35
35
|
"author": "JakeB-5",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"commander": "^12.1.0",
|
|
38
|
-
"zod": "^3.23.8",
|
|
39
37
|
"chalk": "^5.3.0",
|
|
40
|
-
"
|
|
38
|
+
"chokidar": "^5.0.0",
|
|
39
|
+
"commander": "^12.1.0",
|
|
40
|
+
"gray-matter": "^4.0.3",
|
|
41
|
+
"zod": "^3.23.8"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/node": "^20.17.10",
|
|
44
|
-
"typescript": "^
|
|
45
|
-
"
|
|
46
|
-
"tsup": "^8.3.5",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "^8.18.0",
|
|
46
|
+
"@typescript-eslint/parser": "^8.18.0",
|
|
47
47
|
"@vitest/coverage-v8": "^2.1.8",
|
|
48
48
|
"eslint": "^9.16.0",
|
|
49
|
-
"
|
|
50
|
-
"
|
|
49
|
+
"tsup": "^8.3.5",
|
|
50
|
+
"typescript": "^5.7.2",
|
|
51
|
+
"vitest": "^2.1.8"
|
|
51
52
|
},
|
|
52
53
|
"engines": {
|
|
53
54
|
"node": ">=20.0.0"
|