Skip to content

Commit 1968a69

Browse files
Merge pull request #98 from Palbahngmiyine/master
SOLAPI Node.js SDK 5.5.4
2 parents 0cd7294 + 0d2b481 commit 1968a69

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+6018
-939
lines changed

.claude/agents/tidy-first.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
name: tidy-first
3+
description: Refactoring specialist applying Kent Beck's Tidy First principles. Proactively invoked when adding new features, implementing functionality, code reviews, and refactoring. Evaluates whether to tidy code BEFORE making behavioral changes. Also responds to Korean prompts (기능 추가, 기능 구현, 새 기능, 리팩토링, 코드 정리, 코드 리뷰).
4+
tools: Read, Grep, Glob, Bash, Edit
5+
model: inherit
6+
---
7+
8+
You are a refactoring specialist focused on Kent Beck's "Tidy First?" principles.
9+
10+
## Language Support
11+
12+
Respond in the same language as the user's prompt:
13+
- If the user writes in Korean, respond in Korean
14+
- If the user writes in English, respond in English
15+
16+
## When to Activate
17+
18+
**Proactively engage when the user wants to:**
19+
- Add a new feature or functionality
20+
- Implement new behavior
21+
- Modify existing features
22+
- Review or refactor code
23+
24+
**Your first task**: Before any behavioral change, analyze the target code area and recommend tidying opportunities that would make the feature implementation easier.
25+
26+
## Core Principles
27+
28+
### The Tidy First? Question
29+
ALWAYS ask this question before adding features:
30+
- Tidy first if: cost of tidying < reduction in future change costs
31+
- Tidying should be a minutes-to-hours activity
32+
- Always separate structural changes from behavioral changes
33+
- Make the change easy, then make the easy change
34+
35+
### Tidying Types
36+
1. **Guard Clauses**: Convert nested conditionals to early returns
37+
2. **Dead Code**: Remove unreachable or unused code
38+
3. **Normalize Symmetries**: Make similar code patterns consistent
39+
4. **Extract Functions**: Break complex logic into focused functions
40+
5. **Readability**: Improve naming and structure
41+
6. **Cohesion Order**: Place related code close together
42+
7. **Explaining Variables**: Add descriptive variables for complex expressions
43+
44+
## Work Process
45+
46+
1. **Analyze**: Read code and identify Tidy First opportunities
47+
2. **Evaluate**: Assess tidying cost vs benefit (determine if tidying is worthwhile)
48+
3. **Verify Tests**: Ensure existing tests pass
49+
4. **Apply**: Apply only one tidying type at a time
50+
5. **Validate**: Re-run tests after changes (`pnpm test`)
51+
6. **Suggest Commit**: Propose commit message in Conventional Commits format
52+
53+
## Project Rules Compliance
54+
55+
Follow this project's code style:
56+
57+
- **Effect Library**: Maintain `Effect.gen`, `pipe`, `Data.TaggedError` style
58+
- **Type Safety**: Never use `any` type - use `unknown` with type guards or Effect Schema
59+
- **Linting**: Follow Biome lint rules (`pnpm lint`)
60+
- **TDD**: Respect Red → Green → Refactor cycle
61+
62+
## Important Principles
63+
64+
- **Keep it small**: Each tidying should take minutes to hours
65+
- **Safety first**: Only make structural changes that don't alter behavior
66+
- **Tests required**: Verify all tests pass after every change
67+
- **Separate commits**: Keep structural and behavioral changes in separate commits
68+
- **Incremental improvement**: Apply only one tidying type at a time
69+
70+
## Commit Message Format
71+
72+
```
73+
refactor: [tidying type] - [change description]
74+
75+
Examples:
76+
refactor: guard clauses - convert nested if statements to early returns
77+
refactor: dead code - remove unused helper function
78+
refactor: extract function - separate complex validation logic into validateInput
79+
```

.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,4 @@ coverage/
5656
# Next.js example build outputs
5757
**/.next/
5858
**/out/
59-
.vercel/
60-
61-
# Claude
62-
CLAUDE.md
59+
.vercel/

AGENTS.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# SOLAPI SDK for Node.js
2+
3+
**Generated:** 2026-01-21
4+
**Commit:** 9df35df
5+
**Branch:** master
6+
7+
## OVERVIEW
8+
9+
Server-side SDK for SMS/LMS/MMS and Kakao messaging in Korea. Uses Effect library for type-safe functional programming with Data.TaggedError-based error handling.
10+
11+
## STRUCTURE
12+
13+
```
14+
solapi-nodejs/
15+
├── src/
16+
│ ├── index.ts # SolapiMessageService facade (entry point)
17+
│ ├── errors/ # Data.TaggedError types
18+
│ ├── lib/ # Core utilities (fetcher, auth, error handler)
19+
│ ├── models/ # Schemas, requests, responses (see models/AGENTS.md)
20+
│ ├── services/ # Domain services (see services/AGENTS.md)
21+
│ └── types/ # Shared type definitions
22+
├── test/ # Mirrors src/ structure
23+
├── examples/ # Usage examples (excluded from build)
24+
└── debug/ # Debug scripts
25+
```
26+
27+
## WHERE TO LOOK
28+
29+
| Task | Location | Notes |
30+
|------|----------|-------|
31+
| Add new message type | `src/models/base/messages/` | Extend MessageType union |
32+
| Add new service | `src/services/` | Extend DefaultService |
33+
| Add new error type | `src/errors/defaultError.ts` | Extend Data.TaggedError |
34+
| Add utility function | `src/lib/` | Follow Effect patterns |
35+
| Add Kakao BMS type | `src/models/base/kakao/bms/` | Add to BMS_REQUIRED_FIELDS |
36+
| Fix API request issue | `src/lib/defaultFetcher.ts` | HTTP client with retry |
37+
| Understand error flow | `src/lib/effectErrorHandler.ts` | Effect → Promise conversion |
38+
39+
## CONVENTIONS
40+
41+
**Effect Library (MANDATORY)**:
42+
- All errors: `Data.TaggedError` with environment-aware `toString()`
43+
- Async operations: `Effect.gen` + `Effect.tryPromise`, never wrap with try-catch
44+
- Validation: `Effect Schema` with `Schema.filter`, `Schema.transform`
45+
- Error execution: `runSafePromise()` / `runSafeSync()` from effectErrorHandler
46+
47+
**TypeScript**:
48+
- **NEVER use `any`** — use `unknown` + type guards or Effect Schema
49+
- Strict mode enforced (`noUnusedLocals`, `noUnusedParameters`)
50+
- Path aliases: `@models`, `@lib`, `@services`, `@errors`, `@internal-types`
51+
52+
**Testing**:
53+
- Unit: `vitest` with `Schema.decodeUnknownEither()` for validation tests
54+
- E2E: `@effect/vitest` with `it.effect()` and `Effect.gen`
55+
- Run: `pnpm test` / `pnpm test:watch`
56+
57+
## ANTI-PATTERNS
58+
59+
| Pattern | Why Bad | Do Instead |
60+
|---------|---------|------------|
61+
| `any` type | Loses type safety | `unknown` + type guards |
62+
| `as any`, `@ts-ignore` | Suppresses errors | Fix the type issue |
63+
| try-catch around Effect | Loses Effect benefits | Use `Effect.catchTag` |
64+
| Direct `throw new Error()` | Inconsistent error handling | Use `Data.TaggedError` |
65+
| Empty catch blocks | Swallows errors | Handle or propagate |
66+
67+
## COMMANDS
68+
69+
```bash
70+
pnpm dev # Watch mode (tsup)
71+
pnpm build # Lint + build
72+
pnpm lint # Biome check with auto-fix
73+
pnpm test # Run tests once
74+
pnpm test:watch # Watch mode
75+
pnpm docs # Generate TypeDoc
76+
```
77+
78+
## ARCHITECTURE NOTES
79+
80+
**Service Facade Pattern**: `SolapiMessageService` aggregates 7 domain services via `bindServices()` dynamic method binding. All services extend `DefaultService`.
81+
82+
**Error Flow**:
83+
```
84+
API Response
85+
→ defaultFetcher (creates Effect errors)
86+
→ runSafePromise (converts to Promise)
87+
→ toCompatibleError (preserves properties on Error)
88+
→ Consumer
89+
```
90+
91+
**Production vs Development**: Error messages stripped of stack traces and detailed context in production (`process.env.NODE_ENV === 'production'`).
92+
93+
**Retry Logic**: `defaultFetcher.ts` implements 3x retry with exponential backoff for retryable errors (connection refused, reset, 503).

CLAUDE.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
SOLAPI SDK for Node.js - A server-side SDK for sending SMS, LMS, MMS, and Kakao messages (Alimtalk/Friendtalk) in Korea. Compatible with SOLAPI family services (CoolSMS, etc).
8+
9+
## Commands
10+
11+
```bash
12+
# Development
13+
pnpm dev # Watch mode with tsup
14+
pnpm build # Lint + build (production)
15+
pnpm lint # Biome check with auto-fix
16+
17+
# Testing
18+
pnpm test # Run all tests once
19+
pnpm test:watch # Watch mode
20+
pnpm vitest run <path> # Run specific test file
21+
22+
# Documentation
23+
pnpm docs # Generate TypeDoc documentation
24+
```
25+
26+
## Architecture
27+
28+
### Entry Point & Service Facade
29+
`SolapiMessageService` (src/index.ts) is the main SDK entry point. It aggregates all domain services and exposes their methods via delegation pattern using `bindServices()`.
30+
31+
### Service Layer
32+
All services extend `DefaultService` (src/services/defaultService.ts) which provides:
33+
- Base URL configuration (https://api.solapi.com)
34+
- Authentication handling via `AuthenticationParameter`
35+
- HTTP request abstraction via `defaultFetcher`
36+
37+
Domain services:
38+
- `MessageService` / `GroupService` - Message sending and group management
39+
- `KakaoChannelService` / `KakaoTemplateService` - Kakao Alimtalk integration
40+
- `CashService` - Balance inquiries
41+
- `IamService` - Block lists and 080 rejection management
42+
- `StorageService` - File uploads (images, documents)
43+
44+
### Effect Library Integration
45+
This project uses the **Effect** library for functional programming and type-safe error handling:
46+
47+
- All errors extend `Data.TaggedError` with environment-aware `toString()` methods
48+
- Use `Effect.gen` for complex business logic
49+
- Use `pipe` with `Effect.flatMap` for data transformation chains
50+
- Schema validation via Effect Schema for runtime type safety
51+
- Convert Effect to Promise using `runSafePromise` for API compatibility
52+
53+
### Path Aliases
54+
```
55+
@models → src/models
56+
@lib → src/lib
57+
@services → src/services
58+
@errors → src/errors
59+
@internal-types → src/types
60+
@ → src
61+
```
62+
63+
## Code Style Requirements
64+
65+
### TypeScript
66+
- **Never use `any` type** - use `unknown` with type guards, union types, or Effect Schema
67+
- Prefer functional programming style with Effect library
68+
- Run lint after writing code
69+
70+
### TDD Approach
71+
- Follow Red → Green → Refactor cycle
72+
- Separate structural changes from behavioral changes in commits
73+
- Only commit when all tests pass
74+
75+
### Error Handling
76+
- Define errors as Effect Data types (`Data.TaggedError`)
77+
- Provide concise messages in production, detailed in development
78+
- Use structured logging with environment-specific verbosity
79+
80+
## Sub-Agents
81+
82+
### tidy-first
83+
Refactoring specialist applying Kent Beck's "Tidy First?" principles.
84+
85+
**Auto-invocation conditions**:
86+
- Adding new features or functionality
87+
- Implementing new behavior
88+
- Code review requests
89+
- Refactoring tasks
90+
91+
**Core principles**:
92+
- Always separate structural changes from behavioral changes
93+
- Make small, reversible changes only (minutes to hours)
94+
- Maintain test coverage
95+
96+
**Tidying types**: Guard Clauses, Dead Code removal, Pattern normalization, Function extraction, Readability improvements
97+
98+
Works alongside the TDD Approach section's "Separate structural changes from behavioral changes" principle.

biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.3.7/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
33
"vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false },
44
"files": {
55
"ignoreUnknown": false,
36.6 KB
Loading
45.4 KB
Loading

examples/javascript/common/src/kakao/send/send_bms.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
/**
2-
* 카카오 브랜드 메시지 발송 예제
3-
* 현재 targeting 타입 중 M, N의 경우는 카카오 측에서 인허가된 채널만 사용하실 수 있습니다.
2+
* 카카오 브랜드 메시지(템플릿 기반) 발송 예제
3+
* 이 파일은 templateId를 사용한 템플릿 기반 BMS 발송 예제입니다.
4+
*
5+
* BMS 자유형(템플릿 없이 직접 메시지 구성) 예제는 아래 파일들을 참고하세요:
6+
* - send_bms_free_text.js: TEXT 타입 (텍스트 전용)
7+
* - send_bms_free_text_with_buttons.js: TEXT 타입 + 버튼
8+
* - send_bms_free_image.js: IMAGE 타입 (이미지 포함)
9+
* - send_bms_free_image_with_buttons.js: IMAGE 타입 + 버튼
10+
* - send_bms_free_wide.js: WIDE 타입 (와이드 이미지)
11+
* - send_bms_free_wide_item_list.js: WIDE_ITEM_LIST 타입 (와이드 아이템 리스트)
12+
* - send_bms_free_commerce.js: COMMERCE 타입 (상품 메시지)
13+
* - send_bms_free_carousel_feed.js: CAROUSEL_FEED 타입 (캐러셀 피드)
14+
* - send_bms_free_carousel_commerce.js: CAROUSEL_COMMERCE 타입 (캐러셀 커머스)
15+
* - send_bms_free_premium_video.js: PREMIUM_VIDEO 타입 (프리미엄 비디오)
16+
*
17+
* targeting 타입 중 M, N의 경우는 카카오 측에서 인허가된 채널만 사용하실 수 있습니다.
418
* 그 외의 모든 채널은 I 타입만 사용 가능합니다.
519
*/
620
const {SolapiMessageService} = require('solapi');

0 commit comments

Comments
 (0)