opensoma 0.1.2 → 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.
Files changed (97) hide show
  1. package/dist/package.json +18 -2
  2. package/dist/src/client.d.ts +8 -0
  3. package/dist/src/client.d.ts.map +1 -1
  4. package/dist/src/client.js +123 -21
  5. package/dist/src/client.js.map +1 -1
  6. package/dist/src/commands/auth.d.ts +8 -0
  7. package/dist/src/commands/auth.d.ts.map +1 -1
  8. package/dist/src/commands/auth.js +35 -23
  9. package/dist/src/commands/auth.js.map +1 -1
  10. package/dist/src/commands/dashboard.d.ts.map +1 -1
  11. package/dist/src/commands/dashboard.js +1 -1
  12. package/dist/src/commands/dashboard.js.map +1 -1
  13. package/dist/src/commands/event.d.ts.map +1 -1
  14. package/dist/src/commands/event.js.map +1 -1
  15. package/dist/src/commands/helpers.d.ts.map +1 -1
  16. package/dist/src/commands/helpers.js +12 -2
  17. package/dist/src/commands/helpers.js.map +1 -1
  18. package/dist/src/commands/member.d.ts.map +1 -1
  19. package/dist/src/commands/member.js.map +1 -1
  20. package/dist/src/commands/mentoring.d.ts.map +1 -1
  21. package/dist/src/commands/mentoring.js +14 -5
  22. package/dist/src/commands/mentoring.js.map +1 -1
  23. package/dist/src/commands/notice.d.ts.map +1 -1
  24. package/dist/src/commands/notice.js.map +1 -1
  25. package/dist/src/commands/room.d.ts.map +1 -1
  26. package/dist/src/commands/room.js.map +1 -1
  27. package/dist/src/commands/team.d.ts.map +1 -1
  28. package/dist/src/commands/team.js.map +1 -1
  29. package/dist/src/errors.d.ts +8 -0
  30. package/dist/src/errors.d.ts.map +1 -0
  31. package/dist/src/errors.js +11 -0
  32. package/dist/src/errors.js.map +1 -0
  33. package/dist/src/formatters.d.ts.map +1 -1
  34. package/dist/src/formatters.js +54 -7
  35. package/dist/src/formatters.js.map +1 -1
  36. package/dist/src/http.d.ts +5 -0
  37. package/dist/src/http.d.ts.map +1 -1
  38. package/dist/src/http.js +140 -6
  39. package/dist/src/http.js.map +1 -1
  40. package/dist/src/index.d.ts +1 -0
  41. package/dist/src/index.d.ts.map +1 -1
  42. package/dist/src/index.js +1 -0
  43. package/dist/src/index.js.map +1 -1
  44. package/dist/src/shared/utils/mentoring-params.d.ts.map +1 -1
  45. package/dist/src/shared/utils/mentoring-params.js +4 -1
  46. package/dist/src/shared/utils/mentoring-params.js.map +1 -1
  47. package/dist/src/shared/utils/swmaestro.d.ts.map +1 -1
  48. package/dist/src/shared/utils/swmaestro.js.map +1 -1
  49. package/dist/src/token-extractor.d.ts +12 -0
  50. package/dist/src/token-extractor.d.ts.map +1 -1
  51. package/dist/src/token-extractor.js +83 -18
  52. package/dist/src/token-extractor.js.map +1 -1
  53. package/dist/src/types.d.ts +17 -0
  54. package/dist/src/types.d.ts.map +1 -1
  55. package/dist/src/types.js +6 -0
  56. package/dist/src/types.js.map +1 -1
  57. package/package.json +17 -1
  58. package/src/client.test.ts +112 -12
  59. package/src/client.ts +136 -36
  60. package/src/commands/auth.test.ts +55 -0
  61. package/src/commands/auth.ts +57 -33
  62. package/src/commands/dashboard.ts +5 -6
  63. package/src/commands/event.ts +5 -6
  64. package/src/commands/helpers.ts +21 -4
  65. package/src/commands/member.ts +4 -5
  66. package/src/commands/mentoring.ts +36 -19
  67. package/src/commands/notice.ts +4 -5
  68. package/src/commands/room.ts +4 -5
  69. package/src/commands/team.ts +4 -5
  70. package/src/credential-manager.test.ts +1 -1
  71. package/src/credential-manager.ts +1 -1
  72. package/src/errors.ts +10 -0
  73. package/src/formatters.test.ts +1 -1
  74. package/src/formatters.ts +91 -18
  75. package/src/http.test.ts +43 -7
  76. package/src/http.ts +174 -8
  77. package/src/index.ts +1 -0
  78. package/src/shared/utils/mentoring-params.test.ts +9 -4
  79. package/src/shared/utils/mentoring-params.ts +6 -3
  80. package/src/shared/utils/swmaestro.ts +2 -2
  81. package/src/token-extractor.test.ts +84 -8
  82. package/src/token-extractor.ts +118 -22
  83. package/src/types.test.ts +4 -2
  84. package/src/types.ts +6 -0
  85. package/.claude-plugin/README.md +0 -145
  86. package/.claude-plugin/plugin.json +0 -23
  87. package/.github/workflows/release.yml +0 -86
  88. package/.oxfmtrc.json +0 -9
  89. package/.oxlintrc.json +0 -4
  90. package/AGENTS.md +0 -78
  91. package/README.md +0 -252
  92. package/bun.lock +0 -297
  93. package/bunfig.toml +0 -2
  94. package/e2e/.gitkeep +0 -0
  95. package/skills/opensoma/SKILL.md +0 -345
  96. package/skills/opensoma/references/common-patterns.md +0 -182
  97. package/skills/opensoma/references/output-format.md +0 -130
package/src/types.ts CHANGED
@@ -7,6 +7,11 @@ const DashboardStatusItemSchema = z.object({
7
7
  title: z.string(),
8
8
  url: z.string(),
9
9
  status: z.string(),
10
+ date: z.string().optional(),
11
+ time: z.string().optional(),
12
+ timeEnd: z.string().optional(),
13
+ venue: z.string().optional(),
14
+ type: z.enum(['자유 멘토링', '멘토 특강']).optional(),
10
15
  })
11
16
  const TeamListItemSchema = z.object({
12
17
  name: z.string(),
@@ -127,6 +132,7 @@ export type Pagination = z.infer<typeof PaginationSchema>
127
132
 
128
133
  export const CredentialsSchema = z.object({
129
134
  sessionCookie: z.string(),
135
+ cookies: z.string().optional(),
130
136
  csrfToken: z.string(),
131
137
  username: z.string().optional(),
132
138
  loggedInAt: z.string().optional(),
@@ -1,145 +0,0 @@
1
- # OpenSoma
2
-
3
- SWMaestro MyPage CLI & SDK for AI agents.
4
-
5
- ## Overview
6
-
7
- OpenSoma wraps the SWMaestro MyPage platform (swmaestro.ai) to provide programmatic access to:
8
-
9
- - **Mentoring sessions** - List, create, apply, cancel, and manage mentoring sessions
10
- - **Meeting room reservations** - Reserve rooms at the SWMaestro center
11
- - **Dashboard** - View upcoming events, notices, and personal information
12
- - **Team info** - Access team details and member information
13
- - **Notices** - Read official announcements
14
- - **Events** - Browse and apply for program events
15
-
16
- ## Installation
17
-
18
- ```bash
19
- npm install -g opensoma
20
- ```
21
-
22
- ## Authentication
23
-
24
- ### Browser Session Extraction
25
-
26
- Extract existing session from Chromium-based browsers:
27
-
28
- ```bash
29
- opensoma auth extract
30
- ```
31
-
32
- ### Login with Credentials
33
-
34
- ```bash
35
- opensoma auth login --username <email> --password <password>
36
- ```
37
-
38
- Or use environment variables:
39
-
40
- ```bash
41
- export OPENSOMA_USERNAME=<email>
42
- export OPENSOMA_PASSWORD=<password>
43
- opensoma auth login
44
- ```
45
-
46
- ## Commands
47
-
48
- All commands output JSON. Add `--pretty` for formatted output.
49
-
50
- ### Dashboard
51
-
52
- ```bash
53
- opensoma dashboard show
54
- ```
55
-
56
- ### Mentoring
57
-
58
- ```bash
59
- # List sessions
60
- opensoma mentoring list
61
- opensoma mentoring list --status open --type public
62
-
63
- # Search
64
- opensoma mentoring list --search "keyword"
65
-
66
- # Get details
67
- opensoma mentoring get <id>
68
-
69
- # Create session
70
- opensoma mentoring create \
71
- --title "Title" \
72
- --type public \
73
- --date 2025-01-15 \
74
- --start 14:00 \
75
- --end 16:00 \
76
- --venue "스페이스 A1"
77
-
78
- # Apply to session
79
- opensoma mentoring apply <id>
80
-
81
- # Cancel application
82
- opensoma mentoring cancel --apply-sn <number> --qustnr-sn <number>
83
-
84
- # View history
85
- opensoma mentoring history
86
- ```
87
-
88
- ### Meeting Rooms
89
-
90
- ```bash
91
- # List rooms
92
- opensoma room list --date 2025-01-15
93
-
94
- # Check availability
95
- opensoma room available <roomId> --date 2025-01-15
96
-
97
- # Reserve
98
- opensoma room reserve \
99
- --room A1 \
100
- --date 2025-01-15 \
101
- --slots "14:00,14:30,15:00" \
102
- --title "Team Meeting"
103
- ```
104
-
105
- ### Notices
106
-
107
- ```bash
108
- opensoma notice list
109
- opensoma notice get <id>
110
- ```
111
-
112
- ### Team & Member
113
-
114
- ```bash
115
- opensoma team show
116
- opensoma member show
117
- ```
118
-
119
- ### Events
120
-
121
- ```bash
122
- opensoma event list
123
- opensoma event get <id>
124
- opensoma event apply <id>
125
- ```
126
-
127
- ## SDK
128
-
129
- ```typescript
130
- import { SomaClient } from 'opensoma'
131
-
132
- const client = new SomaClient({
133
- username: process.env.OPENSOMA_USERNAME,
134
- password: process.env.OPENSOMA_PASSWORD,
135
- })
136
- await client.login()
137
-
138
- // Use the SDK
139
- const dashboard = await client.dashboard.get()
140
- const { items } = await client.mentoring.list({ status: 'open' })
141
- ```
142
-
143
- ## License
144
-
145
- MIT
@@ -1,23 +0,0 @@
1
- {
2
- "name": "opensoma",
3
- "version": "0.1.2",
4
- "description": "SWMaestro MyPage CLI & SDK for AI agents - manage mentoring sessions, reserve meeting rooms, view dashboard, team info, notices, and member profiles",
5
- "author": {
6
- "name": "devxoul",
7
- "url": "https://github.com/devxoul"
8
- },
9
- "license": "MIT",
10
- "keywords": [
11
- "swmaestro",
12
- "software-maestro",
13
- "mentoring",
14
- "meeting-room",
15
- "kr",
16
- "korean"
17
- ],
18
- "homepage": "https://github.com/devxoul/opensoma",
19
- "repository": "https://github.com/devxoul/opensoma",
20
- "skills": [
21
- "./skills/opensoma"
22
- ]
23
- }
@@ -1,86 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- workflow_dispatch:
5
- inputs:
6
- version:
7
- description: "Version (x.y.z)"
8
- required: true
9
-
10
- permissions:
11
- contents: write
12
- id-token: write
13
-
14
- jobs:
15
- release:
16
- runs-on: ubuntu-latest
17
-
18
- steps:
19
- - uses: actions/checkout@v4
20
-
21
- - uses: oven-sh/setup-bun@v2
22
- with:
23
- bun-version: latest
24
-
25
- - uses: actions/setup-node@v4
26
- with:
27
- node-version: "22"
28
-
29
- - name: Install dependencies
30
- run: bun install --frozen-lockfile
31
-
32
- - name: Typecheck
33
- run: bun run typecheck
34
-
35
- - name: Lint
36
- run: bun run lint
37
-
38
- - name: Test
39
- run: bun run test
40
-
41
- - name: Build
42
- run: bun run build
43
-
44
- - uses: actions/setup-node@v4
45
- with:
46
- node-version: "24"
47
- registry-url: "https://registry.npmjs.org"
48
-
49
- - name: Bump version
50
- run: |
51
- npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version
52
- bun -e "
53
- const fs = require('fs');
54
- const v = '${{ inputs.version }}';
55
- let readme = fs.readFileSync('README.md', 'utf8');
56
- readme = readme.replace(/opensoma@[\d.]+/g, 'opensoma@' + v);
57
- fs.writeFileSync('README.md', readme);
58
- const pluginJson = JSON.parse(fs.readFileSync('.claude-plugin/plugin.json', 'utf8'));
59
- pluginJson.version = v;
60
- fs.writeFileSync('.claude-plugin/plugin.json', JSON.stringify(pluginJson, null, 2) + '\n');
61
- for (const dir of fs.readdirSync('skills')) {
62
- const p = 'skills/' + dir + '/SKILL.md';
63
- if (fs.existsSync(p)) {
64
- let s = fs.readFileSync(p, 'utf8');
65
- s = s.replace(/^version: .+$/m, 'version: ' + v);
66
- fs.writeFileSync(p, s);
67
- }
68
- }
69
- "
70
-
71
- - name: Commit and tag
72
- run: |
73
- git config user.name "github-actions[bot]"
74
- git config user.email "github-actions[bot]@users.noreply.github.com"
75
- git add package.json README.md skills/*/SKILL.md .claude-plugin/plugin.json
76
- git diff --staged --quiet || git commit -m "${{ inputs.version }}"
77
- git tag "${{ inputs.version }}"
78
- git push origin HEAD --tags
79
-
80
- - name: Publish to npm
81
- run: npm publish --provenance --access public
82
-
83
- - name: Create GitHub Release
84
- run: gh release create "${{ inputs.version }}" --generate-notes
85
- env:
86
- GH_TOKEN: ${{ github.token }}
package/.oxfmtrc.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "$schema": "./node_modules/oxfmt/configuration_schema.json",
3
- "printWidth": 120,
4
- "useTabs": false,
5
- "semi": false,
6
- "singleQuote": true,
7
- "sortImports": {},
8
- "ignorePatterns": ["dist/**", ".github/**", "**/*.md"]
9
- }
package/.oxlintrc.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "$schema": "./node_modules/oxlint/configuration_schema.json",
3
- "ignorePatterns": ["dist/**", ".github/**", "**/*.md"]
4
- }
package/AGENTS.md DELETED
@@ -1,78 +0,0 @@
1
- # AGENTS.md
2
-
3
- ## Project Overview
4
-
5
- SWMaestro MyPage CLI & SDK for AI agents. Wraps the SWMaestro platform (swmaestro.ai) to provide programmatic access to mentoring sessions, meeting room reservations, dashboard, notices, team info, member profiles, and events.
6
-
7
- Runtime: Bun for development, Node.js-compatible output for npm distribution.
8
-
9
- ## Commands
10
-
11
- ```bash
12
- # Install dependencies
13
- bun install
14
-
15
- # Run all unit tests
16
- bun test
17
-
18
- # Type checking
19
- bun run typecheck
20
-
21
- # Lint (oxlint)
22
- bun run lint
23
- bun run lint:fix
24
-
25
- # Format (oxfmt)
26
- bun run format
27
- ```
28
-
29
- Always use `bun` — never `node`, `npm`, `npx`, `yarn`, or `pnpm`. Bun loads `.env` automatically; do not use dotenv.
30
-
31
- ## TypeScript Execution Model
32
-
33
- ### Local Development
34
-
35
- Bun runs TypeScript directly — no compilation step needed.
36
-
37
- - `bin` entry in `package.json` points to `./src/cli.ts`
38
- - CLI entry point uses `#!/usr/bin/env bun` shebang
39
- - Run directly: `bun src/cli.ts`
40
-
41
- ### Production Build (Publish)
42
-
43
- `bun run build` compiles to `dist/` for npm consumers who don't have Bun.
44
-
45
- 1. `tsc` compiles `src/` → `dist/src/` (JS + declarations + source maps)
46
- 2. `tsc-alias` resolves `@/*` path aliases in the compiled output
47
- 3. `scripts/postbuild.ts` replaces `#!/usr/bin/env bun` → `#!/usr/bin/env node` in CLI file
48
- 4. `module` and `main` in `package.json` point to `dist/src/index.js`
49
-
50
- npm consumers run compiled JS via Node.js. The `prepublishOnly` script runs the build, then `scripts/prepublish.ts` rewrites `bin` paths from `./src/*.ts` to `dist/src/*.js`. After publish, `postpublish` restores `package.json` via `git checkout`.
51
-
52
- ### Key Distinction
53
-
54
- | | Local (dev) | Published (npm) |
55
- | ----------- | ----------------- | ------------------------ |
56
- | Runtime | Bun | Node.js |
57
- | Entry files | `src/cli.ts` | `dist/src/cli.js` |
58
- | Shebang | `#!/usr/bin/env bun` | `#!/usr/bin/env node` |
59
- | Compilation | None (Bun runs TS) | `tsc` → `dist/` |
60
-
61
- ## Release
62
-
63
- To publish a new version to npm:
64
-
65
- 1. Bump version in `package.json`
66
- 2. Run `bun run build` to verify the build succeeds
67
- 3. Run `npm publish` (triggers `prepublishOnly` → build + rewrite bin paths, then `postpublish` → restore `package.json`)
68
-
69
- Tags have no `v` prefix.
70
-
71
- ### Version Decision
72
-
73
- When asked to release without a specific version:
74
-
75
- - **Patch** (x.y.Z) — bug fixes, docs, refactors, non-breaking changes
76
- - **Minor** (x.Y.0) — new features, new commands, new options, expanded capabilities
77
-
78
- Decide automatically based on commits since last release. Do not ask the user. Never bump major unless the user explicitly requests it. If the user specifies a version, use it as-is.
package/README.md DELETED
@@ -1,252 +0,0 @@
1
- # opensoma
2
-
3
- 소프트웨어 마에스트로(SWMaestro) 마이페이지 CLI & SDK. 멘토링, 회의실 예약, 공지사항, 행사 등 마이페이지 기능을 커맨드라인과 프로그래밍 방식으로 사용할 수 있습니다.
4
-
5
- AI 에이전트가 SWMaestro 플랫폼과 상호작용할 수 있도록 설계되었습니다. 모든 출력은 JSON 형식입니다.
6
-
7
- > [!TIP]
8
- > Webex도 자동화하고 싶으신가요? [agent-messenger](https://github.com/agent-messenger/agent-messenger)를 사용해 보세요.
9
-
10
- ## 설치
11
-
12
- ```bash
13
- npm install opensoma
14
- ```
15
-
16
- ## 인증
17
-
18
- ### 브라우저 세션 추출
19
-
20
- Chromium 계열 브라우저(Chrome, Edge, Brave, Arc, Vivaldi)에서 swmaestro.ai에 로그인된 세션을 자동으로 추출합니다.
21
-
22
- ```bash
23
- opensoma auth extract
24
- ```
25
-
26
- ### 아이디/비밀번호 로그인
27
-
28
- ```bash
29
- opensoma auth login --username <아이디> --password <비밀번호>
30
- ```
31
-
32
- 환경변수로도 전달 가능합니다:
33
-
34
- ```bash
35
- export OPENSOMA_USERNAME=<아이디>
36
- export OPENSOMA_PASSWORD=<비밀번호>
37
- opensoma auth login
38
- ```
39
-
40
- ### 인증 상태 확인
41
-
42
- ```bash
43
- opensoma auth status
44
- ```
45
-
46
- ### 로그아웃
47
-
48
- ```bash
49
- opensoma auth logout
50
- ```
51
-
52
- 인증 정보는 `~/.config/opensoma/credentials.json`에 저장되며, 파일 권한은 `0600`으로 설정됩니다.
53
-
54
- ## CLI 명령어
55
-
56
- 모든 명령어에 `--pretty` 옵션을 추가하면 JSON 출력을 보기 좋게 포맷합니다.
57
-
58
- ### 대시보드
59
-
60
- ```bash
61
- opensoma dashboard show
62
- ```
63
-
64
- ### 멘토링
65
-
66
- ```bash
67
- # 목록 조회
68
- opensoma mentoring list
69
- opensoma mentoring list --status open --type public --page 2
70
-
71
- # 검색
72
- opensoma mentoring list --search "OpenCode"
73
- opensoma mentoring list --search "author:@me"
74
- opensoma mentoring list --search "author:@me" --status open --type lecture
75
-
76
- # 상세 조회
77
- opensoma mentoring get <id>
78
-
79
- # 멘토링 생성
80
- opensoma mentoring create \
81
- --title "멘토링 제목" \
82
- --type public \
83
- --date 2025-01-15 \
84
- --start 14:00 \
85
- --end 16:00 \
86
- --venue "스페이스 A1"
87
-
88
- # 멘토링 삭제
89
- opensoma mentoring delete <id>
90
-
91
- # 멘토링 신청
92
- opensoma mentoring apply <id>
93
-
94
- # 신청 취소
95
- opensoma mentoring cancel --apply-sn <신청번호> --qustnr-sn <멘토링번호>
96
-
97
- # 신청 내역 조회
98
- opensoma mentoring history
99
- ```
100
-
101
- ### 회의실
102
-
103
- ```bash
104
- # 회의실 목록
105
- opensoma room list
106
- opensoma room list --date 2025-01-15 --room A1
107
-
108
- # 예약 가능 시간 조회
109
- opensoma room available <roomId> --date 2025-01-15
110
-
111
- # 회의실 예약
112
- opensoma room reserve \
113
- --room A1 \
114
- --date 2025-01-15 \
115
- --slots "14:00,14:30,15:00" \
116
- --title "팀 회의"
117
- ```
118
-
119
- ### 공지사항
120
-
121
- ```bash
122
- opensoma notice list
123
- opensoma notice get <id>
124
- ```
125
-
126
- ### 팀
127
-
128
- ```bash
129
- opensoma team show
130
- ```
131
-
132
- ### 회원 정보
133
-
134
- ```bash
135
- opensoma member show
136
- ```
137
-
138
- ### 행사
139
-
140
- ```bash
141
- # 행사 목록
142
- opensoma event list
143
-
144
- # 행사 상세
145
- opensoma event get <id>
146
-
147
- # 행사 신청
148
- opensoma event apply <id>
149
- ```
150
-
151
- ## SDK
152
-
153
- TypeScript/JavaScript에서 프로그래밍 방식으로 사용할 수 있습니다.
154
-
155
- ```typescript
156
- import { SomaClient } from 'opensoma'
157
-
158
- const client = new SomaClient({
159
- username: process.env.OPENSOMA_USERNAME,
160
- password: process.env.OPENSOMA_PASSWORD,
161
- })
162
- await client.login()
163
-
164
- // 대시보드
165
- const dashboard = await client.dashboard.get()
166
-
167
- // 멘토링 목록
168
- const { items, pagination } = await client.mentoring.list({ status: 'open' })
169
-
170
- // 멘토링 상세
171
- const detail = await client.mentoring.get(123)
172
-
173
- // 멘토링 생성
174
- await client.mentoring.create({
175
- title: '멘토링 제목',
176
- type: 'public',
177
- date: '2025-01-15',
178
- startTime: '14:00',
179
- endTime: '16:00',
180
- venue: '스페이스 A1',
181
- })
182
-
183
- // 회의실 목록
184
- const rooms = await client.room.list({ date: '2025-01-15' })
185
-
186
- // 회의실 예약
187
- await client.room.reserve({
188
- roomId: 17,
189
- date: '2025-01-15',
190
- slots: ['14:00', '14:30'],
191
- title: '팀 회의',
192
- })
193
-
194
- // 공지사항
195
- const notices = await client.notice.list()
196
- const notice = await client.notice.get(456)
197
-
198
- // 팀 정보
199
- const team = await client.team.show()
200
-
201
- // 회원 정보
202
- const member = await client.member.show()
203
-
204
- // 행사
205
- const events = await client.event.list()
206
- await client.event.apply(789)
207
- ```
208
-
209
- 세션 쿠키로 직접 인증할 수도 있습니다:
210
-
211
- ```typescript
212
- const client = new SomaClient({
213
- sessionCookie: '<세션쿠키>',
214
- csrfToken: '<CSRF토큰>',
215
- })
216
- ```
217
-
218
- ## 회의실 코드
219
-
220
- | 코드 | 회의실 |
221
- |------|--------|
222
- | A1 | 스페이스 A1 |
223
- | A2 | 스페이스 A2 |
224
- | A3 | 스페이스 A3 |
225
- | A4 | 스페이스 A4 |
226
- | A5 | 스페이스 A5 |
227
- | A6 | 스페이스 A6 |
228
- | A7 | 스페이스 A7 |
229
- | A8 | 스페이스 A8 |
230
-
231
- ## 개발
232
-
233
- ```bash
234
- # 의존성 설치
235
- bun install
236
-
237
- # 테스트
238
- bun test
239
-
240
- # 타입 체크
241
- bun run typecheck
242
-
243
- # 린트
244
- bun run lint
245
-
246
- # 포맷
247
- bun run format
248
- ```
249
-
250
- ## 라이선스
251
-
252
- MIT