release: v6.0.0 — Effect 기반 대규모 마이그레이션 및 BMS 지원#153
Open
Palbahngmiyine wants to merge 74 commits intomasterfrom
Open
release: v6.0.0 — Effect 기반 대규모 마이그레이션 및 BMS 지원#153Palbahngmiyine wants to merge 74 commits intomasterfrom
Palbahngmiyine wants to merge 74 commits intomasterfrom
Conversation
BREAKING CHANGE: 전체 API를 Effect 라이브러리 기반으로 마이그레이션 - 모든 타입과 스키마를 외부로 export - Data.TaggedError 기반 에러 처리 통일 - Effect.gen + Effect.tryPromise 비동기 처리 - Effect Schema 기반 입력 검증 - runSafePromise()/runSafeSync() Promise 변환 유틸 도입 - authenticator를 Effect.try로 래핑 - finalize Defect 방지 및 Kakao 입력 검증 - 테스트 환경변수 SOLAPI_ 접두사 통일 - effectErrorHandler, schemaUtils, getGroupsRequest, getMessagesRequest 테스트 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SOLAPI Node.js SDK 6.0.0-beta
- versioning-strategy: prerelease 추가 (6.0.0-beta.0 형식 생성) - package.json version을 5.5.4로 복원 (manifest와 일치, release-please가 bump) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: beta release-please versioning-strategy 및 버전 복원
release-please config schema의 올바른 속성명은 "versioning"이다. "versioning-strategy"는 존재하지 않는 속성으로 무시되어 prerelease 버전(6.0.0-beta.0)이 생성되지 않았다. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: release-please versioning 속성명 수정 (beta)
"beta"로 설정하면 첫 버전이 6.0.0-beta(카운터 없음)로 생성된다. "beta.0"으로 설정하면 6.0.0-beta.0부터 시작하고, 이후 bump 시 beta.1, beta.2로 시리얼하게 증가한다. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: prerelease-type beta.0으로 변경 — 시리얼 넘버링 (beta)
…omponents--solapi chore(beta): release solapi 6.0.0-beta.0
release-please가 package.json 업데이트 시 포맷을 변경하여 biome check(lint:ci)에서 포맷 에러가 발생한다. package.json은 release-please가 관리하므로 formatter 대상에서 제외. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: biome formatter에서 package.json 제외
upstream/beta 동기화 시 보존 대상 파일 복원: - agents: barrel-checker, effect-reviewer, tidy-first - skills: create-model, gen-e2e-test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v6.0.0 Effect 전환에서 남아있던 레거시 패턴을 모두 제거: - Message, KakaoOption, RcsOption dead class 제거 (호출처 없음) - MessageType, AdditionalBody, RcsOptionRequest 수동 타입을 Schema 파생 타입으로 교체 - defaultFetcher의 try-catch를 Effect.try 파이프라인으로 변환 - barrel export 개선: VariableValidationError value export, 누락 schema 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- JSON.parse("null") 시 null.errorCode TypeError 방지 (null guard 추가)
- parseServerErrorBody 순수 함수 추출로 에러 결정 로직 명확화
- makeError 팩토리로 ServerError 생성 코드 중복 제거
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- res.json() 대신 res.text() + JSON.parse로 변경하여 파싱 실패 처리 - null, 비객체 JSON, 다른 스키마 JSON에 대한 null guard 추가 - genericError fallback으로 "undefined: undefined" 에러 메시지 방지 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…egacy-cleanup refactor: 레거시 클래스/수동 타입 제거 및 Effect Schema 전면 전환
- defaultFetcher.ts: Effect.flatMap 내 try-catch를 Effect.try로 전환, throw new Error 제거, isErrorResponse 타입 가드로 as Partial<ErrorResponse> 단언 대체 - defaultError.ts: 미사용 deprecated ApiError alias 제거, isErrorResponse 타입 가드 추가 - index.ts/messageService.ts: sendOne 메소드 삭제 - kakaoOption.ts: as Record<string, unknown> 단언을 keyof BaseBmsSchemaType으로 대체 - defaultService.ts: 내부 전용 타입 불필요 export 제거 - stringDateTrasnfer.ts → stringDateTransfer.ts 파일명 오타 수정 및 전체 import 경로 반영 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- isErrorResponse: 빈 문자열 거부 추가 (기존 truthy 체크 동작 보존), 단일 cast로 간소화 - handleClientErrorResponse: SyntaxError 구분 추가 (parseServerErrorBody와 일관) - defaultFetcher: toMessage/makeParseError 헬퍼 추출로 반복 제거, 불필요 nested pipe 제거 - isErrorResponse 단위 테스트 19건 추가 (null, undefined, 원시값, 빈 문자열 등) - examples/: 삭제된 sendOne/sendOneFuture → send로 전환 (6개 파일) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- singleMessageSendingRequestSchema, SingleMessageSendingRequestSchema 제거 (sendOne 전용) - singleMessageSentResponseSchema, SingleMessageSentResponse 제거 (sendOne 전용) - barrel export (requests/index.ts, responses/index.ts)에서 해당 항목 제거 - 미사용 messageTypeSchema import 정리 (messageResponses.ts) - sendMessage.test.ts에서 삭제된 스키마 테스트 3건 제거 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ns-cleanup refactor: CLAUDE.md 원칙 위반 정리 및 dead code 제거
- 미사용 default export 제거 (fileToBase64, defaultFetcher) - 빈 섹션 주석 제거 (models/index.ts, responses/index.ts) - effectErrorHandler 타입 가드 개선: 필드별 as 어설션 → Record 통합 - bmsCommerce NumberOrNumericString 타입 어설션 Why 주석 보강 - deprecated v5 alias 7개 제거 (KakaoAlimtalkTemplateInterface 등) - bindServices 동적 프로토타입 순회 → 32개 메서드 명시적 .bind() 전환 - Writable<T> 헬퍼 타입 및 DefaultService import 제거 - 타입 어설션 7개 제거 (as unknown as, as never, as Record 등) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CLAUDE.md/AGENTS.md: bindServices() 참조를 명시적 .bind()로 업데이트 - effectErrorHandler 테스트: non-string _tag, message 없는 tagged defect 케이스 추가 - solapiMessageService 테스트: 32개 메서드 전체 바인딩 검증 테스트 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…de-md-violations refactor: dead code 제거, deprecated alias 정리, bindServices 명시적 바인딩 전환
- @effect/language-service 설치 및 tsconfig.json plugin 설정 - as 캐스팅 제거: isTaggedDefect 타입 가드 도입, isErrorResponse in 연산자 narrowing - DRY: DefaultService에 getWithQuery 헬퍼 추출, 6개 서비스 메서드 간소화 - Effect.gen → Effect.flatMap 전환: uploadFile, reserveGroup, addMessagesToGroup - Effect LSP diagnostic 반영: Schema.decodeUnknown + mapError, Effect.void, yieldable error 직접 yield Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rvice-optimization refactor: Effect Language Service 도입 및 타입 안전성·DRY 개선
operatorTypeSchema, dateOperatorTypeSchema, kakaoOptionRequestSchema 등 프로젝트 내부·외부 어디에서도 참조되지 않는 타입/스키마 export를 정리하고, 유일한 export가 모두 dead인 kakaoOptionRequest.ts 파일을 삭제합니다. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
refactor: 미사용 export 및 dead file 제거
npm Trusted Publishers OIDC token exchange requires npm CLI 11.5.1+. Node 18 ships npm 10.8.2 which lacks OIDC support, causing E404 on publish despite provenance signing succeeding (Sigstore is separate). Node 24 ships npm 11.x+ with native OIDC support. Only the publish job is changed — test/lint jobs remain on Node 18 for SDK compatibility. Also restore --provenance --access public flags per OIDC project conventions (astral-sh/ruff, Effect-TS/effect). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): use Node 24 for npm Trusted Publishers OIDC support
Re-trigger release-please after deleting solapi-v6.0.0-beta.1 release and tag. The updated release.yml (Node 24, npm 11.x+) will handle OIDC Trusted Publishers authentication. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ci: trigger beta release with Node 24 OIDC publish
…omponents--solapi chore(beta): release solapi 6.0.0-beta.2
- Remove unused runSafeSync from effectErrorHandler (dead code) - Unify path aliases to domain-specific form (@/ -> @errors, @models) - Add @errors/* path to tsconfig to match documented alias scheme - Extract retryable error detection helper in defaultFetcher - Adopt ParseResult TreeFormatter/ArrayFormatter in decodeWithBadRequest - Remove redundant WHAT/section comments; keep TSDoc and WHY-only Verified with pnpm lint, pnpm test (277/277), pnpm build, and @effect/language-service diagnostics (0 errors / 0 warnings / 88 files). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
refactor: remove dead code and align with effect best practices
Refactor commit 0042ae6 는 release-please 기본 설정상 user-facing commit(feat/fix/perf/deps)이 아니라 release PR 이 자동 생성되지 않았습니다. Effect ParseResult 포맷터 도입과 runSafeSync 내부 심볼 제거가 포함되어 있어 beta release 로 배포합니다. Release-As: 6.0.0-beta.3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore: trigger beta release for refactor changes (6.0.0-beta.3)
sendOne/sendOneFuture 메서드는 이미 제거되어 `send`로 통합되었으므로 "send 메소드로도 동일하게 사용가능" 주석 문구는 의미가 사라졌습니다. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docs(examples): drop stale sendOne note from send_sms comment
Member
Author
There was a problem hiding this comment.
Code Review
This pull request executes a comprehensive migration of the SDK to the Effect library, introducing functional programming patterns and schema-based validation. The SolapiMessageService facade was refactored to use explicit method binding, and all domain services and internal utilities were converted to Effect pipelines. Additionally, legacy class-based models were replaced with Effect Schema definitions, and the test suite was expanded to cover these new patterns. Feedback from the review suggests ensuring compatibility for error.cause in older Node.js 16 environments and recommends utilizing Effect Schema for response parsing instead of type assertions to improve runtime safety.
Comment on lines
+32
to
+40
| const isRetryableNetworkError = (error: Error): boolean => { | ||
| const cause = error.cause; | ||
| const causeCode = | ||
| cause && typeof cause === 'object' && 'code' in cause | ||
| ? String(cause.code) | ||
| : ''; | ||
| const message = `${error.message} ${causeCode}`.toLowerCase(); | ||
| return RETRYABLE_ERROR_KEYWORDS.some(keyword => message.includes(keyword)); | ||
| }; |
Comment on lines
+66
to
+67
| const parsed: unknown = JSON.parse(responseText); | ||
| return parsed as R; |
- getBalance 응답에 lowBalanceAlert, minimumCash, rechargeTo, deposit 등 실서버에 존재하는 필드를 반영해 스키마 확장 - getStatistics, getGroups, getGroup, getBlacks, getBlockGroups, getKakaoChannel, getKakaoAlimtalkTemplate(s) 응답의 드리프트(nullable, 누락 필드, Record→Array 등) 정합화 - MessageTypeRecord에 rcs_itpl/ltpl, fax, voice, bms_* 신규 메시지 타입 추가 - 조회 응답 전용 storedMessageSchema 신설해 발송용 messageSchema와 분리 - DefaultService.requestEffect/getWithQuery에 responseSchema 주입 경로 마련하고, decodeServerResponse 헬퍼 추가로 서버 응답을 런타임 검증해 드리프트 즉시 감지 - 15개 조회 서비스 메서드에 해당 스키마 연결 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
첫 페이지 호출 시 서버가 startKey를 null 또는 미포함으로 반환하는데 getKakaoChannelsResponseSchema와 getKakaoAlimtalkTemplatesResponseSchema의 startKey가 required string으로 남아 있어 런타임 검증이 실패하는 회귀를 수정. 다른 list 응답들과 동일하게 NullishOr로 정렬. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 전용 ResponseSchemaMismatchError 도입 — 2xx에서 발생하는 스키마 불일치를 ServerError(200)으로 래핑하던 문제를 분리해 5xx 재시도/알림 분기 오염 방지 - validationErrors(ArrayFormatter) 및 responseBody 보존으로 운영 환경에서도 드리프트 경로 재현 가능 - decodeServerResponse에 onExcessProperty:'preserve' 적용 — 부분 스키마가 서버의 미선언 필드를 strip 해버려 소비자 응답에서 silent data loss가 발생하던 문제 수정 - storedMessageSchema의 autoTypeDetect/replacement/voiceReplied/ unavailableSenderNumber를 Schema.transform으로 boolean 정규화 - responseSchema 제네릭을 Schema.Schema<R, I, never>로 타이트닝 — 요구사항 채널이 오염되지 않도록 강제 - decodeServerResponse 8개 유닛 테스트 추가 (fixture 기반 회귀 방어) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- booleanOrZeroOne을 Schema.transformOrFail로 엄격화해 2/-1/NaN 같은 drift 입력을 silent true로 coerce하지 않고 ResponseSchemaMismatchError로 전파 - stringifyResponseBody가 circular/BigInt로 JSON 실패 시 undefined로 정보 소실하던 동작을 '[unserializable: reason] toStringTag' 메타데이터로 보완 - ResponseSchemaMismatchError.toString()의 production 경로에서 url과 validationErrors를 유지(responseBody만 민감 페이로드라 계속 숨김) - 엣지 케이스 유닛 테스트 추가: boolean transform 거부값, 순환참조 responseBody Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ure fields Codex 2차 리뷰 발견 사항 반영: - countForChargeSchema에 rcs_itpl/ltpl, fax, voice, bms_* 13개 필드 추가 — messageTypeRecordSchema 확장과 비대칭하여 신규 메시지 타입을 가진 그룹 조회가 ResponseSchemaMismatchError로 실패하던 문제 수정 (getGroups/getGroup 회귀 방어) - storedMessageSchema의 unavailableSenderNumber/faxPageCount/voiceDuration/ voiceReplied를 NullishOr로 완화 — non-FAX/non-VOICE 메시지 행에서 null로 내려오는 경우 전체 응답 decode 실패하던 문제 수정 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Error Codex 3차 리뷰 P2: production에서 ResponseSchemaMismatchError의 responseBody 필드에 원본 응답이 유지되어, toString() 가드와 무관하게 Sentry 등 에러 리포터가 enumerable 필드를 직렬화하면서 PII가 누출될 수 있었음. ServerError와 동일하게 creation 단계에서 production이면 undefined로 제외. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tion silent-failure-hunter 4차 후속: - ParseResult.ArrayFormatter/TreeFormatter는 실패 메시지에 원본 값(전화번호 등)을 그대로 문자열로 삽입하므로, production에서는 validationErrors 엔트리를 `path: [_tag]` 형태로 축약하고 message는 issue 개수 요약으로 대체 - getMessages 등 조회 API는 to/from 등을 query string에 실으므로 production에서 url의 query 부분을 '?[redacted]'로 마스킹 - 테스트 fixture를 확장해 실제 전화번호 문자열이 message/validationErrors/url 어디에도 포함되지 않음을 명시적으로 검증 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
silent-failure-hunter 5차: - NODE_ENV 가드를 safe-by-default로 반전 — staging/unset 등 비정형 환경에서도 redact를 기본 적용하고, development/test만 verbose 모드 - redactUrlForProduction이 URL fragment(#...)를 먼저 strip 하도록 보완해 fragment 내부 쿼리 문자열 또한 redact 경로에 포함 - ResponseSchemaMismatchError.toString()에서 이중 가드 제거 — creation 시점에 이미 필드가 redact된 상태라 단순히 보유 값만 렌더링 - 테스트 시나리오를 'production' → 'staging'으로 교체해 새로운 가드 범위 검증 Codex 4차에서 지적된 BadRequestError/ClientError/ServerError/NetworkError의 동일 PII 누출 패턴은 request/transport 계층 전반의 정책 변경을 요구하므로 이 PR 범위에서 분리 — 별도 후속 작업으로 처리 권장 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
silent-failure-hunter/Codex 5차: - NODE_ENV gate를 .trim().toLowerCase()로 정규화해 Windows PowerShell 등에서 'Development' 같은 변형도 verbose 모드로 인식 - redactUrlForProduction을 URL 객체 기반으로 전환해 query string뿐 아니라 fragment/userinfo(user:password@)까지 함께 redact - ResponseSchemaMismatchError.toString()에 defense-in-depth 가드 복원 — 클래스가 public이라 외부에서 직접 생성될 경우에도 production 경로에서 responseBody가 유출되지 않도록 한다 - storedMessageSchema의 옵션 객체(kakao/rcs/naver/fax/voice)와 배열 필드 (replacements/log/queues)를 Record/Array of Unknown으로 강화해 최소한의 구조 계약(object or array)이 타입 수준에서 유지되도록 함 - 테스트: NODE_ENV를 table-driven으로 확장해 production/staging/undefined/빈 문자열 모두 redact 되고 development/test만 verbose 되는 계약, 대소문자/공백 정규화 동작, userinfo/fragment redact 동작까지 커버 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ypeRecord Codex 최종 P2: statusCode 값 타입이 generic Record<string, number>로 바뀌면서 statusCode[code].sms/lms 같은 타입-narrowed 접근이 깨지던 회귀 복원. 서버가 실제 일부 필드만 내려주는 sparse 응답임을 고려해, messageTypeRecordSchema를 Schema.partial로 감싼 partialMessageTypeRecordSchema를 신설하고 dayPeriod.statusCode value에 사용. 타입 정보는 유지하면서도 한두 필드만 있는 응답도 통과한다. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dation-beta fix(responses): sync query API schemas and add runtime response validation
…omponents--solapi chore(beta): release solapi 6.0.0-beta.3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
beta브랜치에 누적된 v6.0.0 변경사항을master(stable)로 승격합니다. npmlatest태그 릴리스 대상입니다.5.5.4→ beta6.0.0-beta.26.0.0(stable)⚠ BREAKING CHANGES
Data.TaggedError기반 에러 처리 통일Effect.gen+Effect.tryPromise비동기 처리runSafePromise()/runSafeSync()Promise 변환 유틸 도입Features
ClientError/ServerError클래스 도입으로 에러 분류 명확화AGENTS.md) 및 Effect 가이드라인 정비Bug Fixes
handleClientErrorResponse/handleServerErrorResponsenull/비정형 JSON 방어codenullable, 앱버튼 링크 필수 처리restore default message schema export— BMS 어설션 유지로 downstream 빌드 실패 방지expect.assertions()추가로 false-green 방지CI / Release Automation
release-please--branches--beta--components--solapi) 체계화Docs / Examples
sendOne/sendOneFuture메서드 제거 및send단일 메서드로 통합 (docs(examples): drop stale sendOne note from send_sms comment #152)Test plan
pnpm build성공(타입 체크 포함) 이력 확인@effect/language-servicediagnostics: 0 errors / 0 warnings6.0.0PR 자동 생성하는지 확인latest태그로6.0.0배포 후 설치/임포트 smoke testReferences
solapi-v6.0.0-beta.2CHANGELOG.md(beta 브랜치 기준)🤖 Generated with Claude Code