@algocare/react-native-code-push 12.5.0 → 12.6.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 CHANGED
@@ -1,13 +1,260 @@
1
1
  ## @algocare/react-native-code-push
2
2
 
3
- Fork of `code-push-react-native`
3
+ > `react-native-code-push`의 알고케어 커스텀 포크
4
+ > AppCenter 없이 독립적인 CodePush 배포 시스템
4
5
 
5
6
  ```bash
6
7
  npm install @algocare/react-native-code-push
7
8
  ```
8
9
 
9
- You'll have more flexibility and freedom in your deployment strategy.
10
- You can still use CodePush, but become independent of AppCenter's cloud infrastructure.
10
+ ---
11
+
12
+ ## 🚀 빠른 시작 (5분 안에 설정 완료!)
13
+
14
+ ### 1단계: 패키지 설치
15
+
16
+ ```bash
17
+ npm install @algocare/react-native-code-push
18
+ ```
19
+
20
+ ### 2단계: 환경변수 설정
21
+
22
+ #### B2C Home 프로젝트만 (`.env` 파일 사용)
23
+
24
+ `home-device`, `home-mobile` 프로젝트만 `.env` 파일 생성:
25
+
26
+ ```bash
27
+ # AWS 자격 증명
28
+ AWS_ACCESS_KEY_ID=your_aws_access_key_here
29
+ AWS_SECRET_ACCESS_KEY=your_aws_secret_key_here
30
+ AWS_REGION=ap-northeast-2
31
+
32
+ # STG/PRD 환경별 설정
33
+ AWS_S3_BUCKET_STG=your-stg-bucket-name
34
+ AWS_S3_BUCKET_PRD=your-prd-bucket-name
35
+ CDN_URL_STG=https://your-stg-cdn-url.com
36
+ CDN_URL_PRD=https://your-prd-cdn-url.com
37
+ ```
38
+
39
+ ⚠️ **실제 값은 팀 내부에서 공유받으세요!**
40
+
41
+ #### B2B + B2C MVP (Infisical 사용)
42
+
43
+ `user`, `device`, `b2c-device` 프로젝트는 Infisical 사용:
44
+
45
+ ```bash
46
+ # Infisical에서 자동으로 .env 파일 생성
47
+ yarn set:stg # STG 환경변수 로드
48
+ yarn set:prd # PRD 환경변수 로드
49
+ ```
50
+
51
+ Infisical에 이미 모든 환경변수가 설정되어 있습니다.
52
+
53
+ ⚠️ **중요**: `.env` 파일을 `.gitignore`에 추가하세요!
54
+
55
+ ```bash
56
+ echo ".env" >> .gitignore
57
+ ```
58
+
59
+ ### 3단계: package.json에 스크립트 추가
60
+
61
+ ```json
62
+ {
63
+ "scripts": {
64
+ "codepush:release": "sh scripts/codepush.sh release",
65
+ "codepush:release:prd": "sh scripts/codepush.sh release --env=prd",
66
+ "codepush:show": "sh scripts/codepush.sh show",
67
+ "codepush:show:prd": "sh scripts/codepush.sh show --env=prd"
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### 4단계: 배포!
73
+
74
+ ```bash
75
+ # Staging 환경에 배포
76
+ npm run codepush:release
77
+
78
+ # Production 환경에 배포
79
+ npm run codepush:release:prd
80
+ ```
81
+
82
+ **끝!** 더 이상 추가 설정 파일이 필요 없습니다. 🎉
83
+
84
+ ---
85
+
86
+ ## 📱 지원하는 앱
87
+
88
+ | 앱 이름 | 설명 | 플랫폼 | 환경 관리 |
89
+ |---------|------|--------|----------|
90
+ | `user` | B2B 모바일 앱 | iOS, Android | Infisical (STG/PRD) |
91
+ | `device` | B2B 디바이스 앱 | Android | Infisical (STG/PRD) |
92
+ | `b2c-device` | B2C MVP 디바이스 앱 | Android | Infisical (STG/PRD) |
93
+ | `home-device` | B2C Home (상용) 디바이스 앱 | Android | .env 파일 (STG/PRD) |
94
+ | `home-mobile` | B2C Home (상용) 모바일 앱 | iOS, Android | .env 파일 (STG/PRD) |
95
+
96
+ > **모든 앱이 STG/PRD 환경을 구분합니다!**
97
+ > - **B2B + B2C MVP**: Infisical로 환경변수 관리
98
+ > - **B2C Home**: .env 파일로 환경변수 관리
99
+
100
+ ---
101
+
102
+ ## ⚙️ 작동 원리
103
+
104
+ ### 환경 자동 선택
105
+
106
+ 패키지가 자동으로 다음을 수행합니다:
107
+
108
+ 1. `.env` 파일에서 AWS 자격증명 로드
109
+ 2. `-i` 플래그로 환경 구분 (stg/prd)
110
+ 3. 적절한 S3 버킷과 CDN URL 선택
111
+ 4. 번들을 업로드하고 히스토리 관리
112
+
113
+ ### 환경변수 우선순위
114
+
115
+ ```javascript
116
+ // STG 환경
117
+ -i stg → AWS_S3_BUCKET_STG, CDN_URL_STG
118
+
119
+ // PRD 환경
120
+ -i prd → AWS_S3_BUCKET_PRD, CDN_URL_PRD
121
+
122
+ // 레거시 호환성 (옵션)
123
+ AWS_S3_BUCKET, CDN_URL // identifier 없이 사용 가능
124
+ ```
125
+
126
+ ---
127
+
128
+ ## 🔧 상세 설정
129
+
130
+ ### B2C Home 프로젝트 (`.env` 파일)
131
+
132
+ **home-device, home-mobile**
133
+
134
+ `.env` 파일:
135
+ ```bash
136
+ AWS_S3_BUCKET_STG=your-stg-bucket-name
137
+ AWS_S3_BUCKET_PRD=your-prd-bucket-name
138
+ CDN_URL_STG=https://your-stg-cdn-url.com
139
+ CDN_URL_PRD=https://your-prd-cdn-url.com
140
+ ```
141
+
142
+ 사용:
143
+ ```bash
144
+ npm run codepush:release # STG 배포
145
+ npm run codepush:release:prd # PRD 배포
146
+ ```
147
+
148
+ ### B2B + B2C MVP (Infisical)
149
+
150
+ **user, device, b2c-device**
151
+
152
+ ```bash
153
+ # package.json 스크립트
154
+ {
155
+ "scripts": {
156
+ "set:stg": "infisical export --env=stg > .env",
157
+ "set:prd": "infisical export --env=prd > .env",
158
+ "codepush:stg": "yarn set:stg && npx code-push release -i stg",
159
+ "codepush:prd": "yarn set:prd && npx code-push release -i prd"
160
+ }
161
+ }
162
+ ```
163
+
164
+ 사용:
165
+ ```bash
166
+ yarn codepush:stg # STG 배포
167
+ yarn codepush:prd # PRD 배포
168
+ ```
169
+
170
+ ---
171
+
172
+ ## 📝 예제 Scripts
173
+
174
+ ### 기본 배포 스크립트 (`scripts/codepush.sh`)
175
+
176
+ ```bash
177
+ #!/bin/bash
178
+
179
+ ENV="stg"
180
+ COMMAND=""
181
+ ADDITIONAL_ARGS="-a home-mobile -i $ENV"
182
+
183
+ while [[ "$#" -gt 0 ]]; do
184
+ case $1 in
185
+ create|update|show|release) COMMAND="$1";;
186
+ --env=*) ENV="${1#*=}"
187
+ ADDITIONAL_ARGS="-a home-mobile -i $ENV"
188
+ ;;
189
+ *) ADDITIONAL_ARGS="$ADDITIONAL_ARGS $1";;
190
+ esac
191
+ shift
192
+ done
193
+
194
+ if [ "$COMMAND" = "release" ]; then
195
+ npx code-push release $ADDITIONAL_ARGS
196
+ else
197
+ npx code-push $COMMAND-history $ADDITIONAL_ARGS
198
+ fi
199
+ ```
200
+
201
+ ---
202
+
203
+ ## 🆚 기존 방식과의 차이
204
+
205
+ ### ❌ 기존 방식 (복잡함)
206
+
207
+ 1. 프로젝트마다 `code-push.config.js` 파일 생성
208
+ 2. AWS 키 하드코딩 (보안 위험)
209
+ 3. `postinstall` 스크립트로 파일 복사
210
+ 4. 환경별로 다른 설정 파일 관리
211
+
212
+ ### ✅ 새로운 방식 (간단함)
213
+
214
+ 1. `.env` 파일 하나만 생성
215
+ 2. AWS 키 안전하게 관리
216
+ 3. 추가 설정 파일 불필요
217
+ 4. 환경변수로 자동 전환
218
+
219
+ ---
220
+
221
+ ## 🔍 트러블슈팅
222
+
223
+ ### CodePush 실행 시 "AWS credentials not found" 에러
224
+
225
+ **원인**: `.env` 파일이 없거나 환경변수가 설정되지 않음
226
+
227
+ **해결**:
228
+ ```bash
229
+ # .env 파일 확인
230
+ cat .env
231
+
232
+ # 환경변수 설정 확인
233
+ echo $AWS_ACCESS_KEY_ID
234
+ ```
235
+
236
+ ### S3 업로드 실패 (403 Forbidden)
237
+
238
+ **원인**: AWS 자격증명이 잘못되었거나 권한 부족
239
+
240
+ **해결**:
241
+ 1. `.env` 파일의 AWS 키 확인
242
+ 2. IAM 사용자 권한 확인 (S3 PutObject 필요)
243
+
244
+ ### 잘못된 환경에 배포됨
245
+
246
+ **원인**: `-i` 플래그를 잘못 지정
247
+
248
+ **해결**:
249
+ ```bash
250
+ # STG 배포
251
+ npm run codepush:release # -i stg (기본값)
252
+
253
+ # PRD 배포
254
+ npm run codepush:release:prd # -i prd
255
+ ```
256
+
257
+ ---
11
258
 
12
259
  ### Self-host the update bundle file
13
260
 
@@ -10,16 +10,52 @@ const fs = require('fs')
10
10
  const axios = require('axios')
11
11
  require('dotenv').config()
12
12
 
13
+ // CLI 인자에서 identifier 추출 (패키지 버그 workaround)
14
+ function getIdentifierFromArgs() {
15
+ const args = process.argv
16
+ const identifierIndex = args.findIndex(arg => arg === '-i' || arg === '--identifier')
17
+ if (identifierIndex !== -1 && args[identifierIndex + 1]) {
18
+ return args[identifierIndex + 1]
19
+ }
20
+ // --identifier=prd 형태 처리
21
+ const identifierArg = args.find(arg => arg.startsWith('--identifier='))
22
+ if (identifierArg) {
23
+ return identifierArg.split('=')[1]
24
+ }
25
+ return 'stg' // 기본값
26
+ }
27
+
13
28
  const s3Client = new S3Client({
14
- region: process.env.AWS_REGION,
29
+ region: process.env.AWS_REGION || 'ap-northeast-2',
15
30
  credentials: {
16
31
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
17
32
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
18
33
  },
19
34
  })
20
35
 
21
- const BUCKET_NAME = process.env.AWS_S3_BUCKET || 'codepush-bucket'
22
- const CDN_URL = process.env.CDN_URL || `https://${BUCKET_NAME}.s3.amazonaws.com`
36
+ function getBucketName(identifier) {
37
+ // Legacy support: AWS_S3_BUCKET (단일 버킷)
38
+ if (process.env.AWS_S3_BUCKET) {
39
+ return process.env.AWS_S3_BUCKET
40
+ }
41
+
42
+ const actualIdentifier = identifier || getIdentifierFromArgs()
43
+ return actualIdentifier === 'prd'
44
+ ? process.env.AWS_S3_BUCKET_PRD || 'a-algocare-c-prd'
45
+ : process.env.AWS_S3_BUCKET_STG || 'a-algocare-b-stg'
46
+ }
47
+
48
+ function getCDNUrl(identifier) {
49
+ // Legacy support: CDN_URL (단일 CDN)
50
+ if (process.env.CDN_URL) {
51
+ return process.env.CDN_URL
52
+ }
53
+
54
+ const actualIdentifier = identifier || getIdentifierFromArgs()
55
+ return actualIdentifier === 'prd'
56
+ ? process.env.CDN_URL_PRD || 'https://contents.algocare.link'
57
+ : process.env.CDN_URL_STG || 'https://contents-stg.algocare.link'
58
+ }
23
59
 
24
60
  function historyJsonFileRemotePath(app, platform, binaryVersion) {
25
61
  return `histories/${app}/${platform}/${binaryVersion}.json`
@@ -30,10 +66,19 @@ function bundleFileRemotePath(app, platform, fileName) {
30
66
  }
31
67
 
32
68
  const Config = {
33
- bundleUploader: async (source, app, platform) => {
69
+ bundleUploader: async (source, app, platform, identifier) => {
70
+ const actualIdentifier = identifier || getIdentifierFromArgs()
34
71
  const fileName = source.split('/').pop()
35
72
  const fileContent = fs.readFileSync(source)
36
73
  const remotePath = bundleFileRemotePath(app, platform, fileName)
74
+ const BUCKET_NAME = getBucketName(actualIdentifier)
75
+ const CDN_URL = getCDNUrl(actualIdentifier)
76
+
77
+ console.log(`🔧 S3 업로드 설정:`)
78
+ console.log(` - Identifier: ${actualIdentifier}`)
79
+ console.log(` - Bucket: ${BUCKET_NAME}`)
80
+ console.log(` - Region: ${process.env.AWS_REGION || 'ap-northeast-2'}`)
81
+ console.log(` - Remote Path: ${remotePath}`)
37
82
 
38
83
  try {
39
84
  await s3Client.send(
@@ -55,7 +100,9 @@ const Config = {
55
100
  throw error
56
101
  }
57
102
  },
58
- getReleaseHistory: async (app, targetBinaryVersion, platform) => {
103
+ getReleaseHistory: async (app, targetBinaryVersion, platform, identifier) => {
104
+ const actualIdentifier = identifier || getIdentifierFromArgs()
105
+ const CDN_URL = getCDNUrl(actualIdentifier)
59
106
  const remoteJsonPath = historyJsonFileRemotePath(
60
107
  app,
61
108
  platform,
@@ -69,8 +116,12 @@ const Config = {
69
116
  jsonFilePath,
70
117
  releaseInfo,
71
118
  app,
72
- platform
119
+ platform,
120
+ identifier
73
121
  ) => {
122
+ const actualIdentifier = identifier || getIdentifierFromArgs()
123
+ const BUCKET_NAME = getBucketName(actualIdentifier)
124
+ const CDN_URL = getCDNUrl(actualIdentifier)
74
125
  const fileContent = fs.readFileSync(jsonFilePath, 'utf8')
75
126
  const remoteJsonPath = historyJsonFileRemotePath(
76
127
  app,
@@ -98,7 +149,9 @@ const Config = {
98
149
  throw error
99
150
  }
100
151
  },
101
- getBinaryVersionList: async (app, platform) => {
152
+ getBinaryVersionList: async (app, platform, identifier) => {
153
+ const actualIdentifier = identifier || getIdentifierFromArgs()
154
+ const CDN_URL = getCDNUrl(actualIdentifier)
102
155
  const remoteJsonPath = `histories/${app}/${platform}/list.json`
103
156
  let currentList = {}
104
157
  try {
@@ -113,7 +166,10 @@ const Config = {
113
166
  }
114
167
  return currentList
115
168
  },
116
- setBinaryVersionList: async (targetVersion, jsonFilePath, app, platform) => {
169
+ setBinaryVersionList: async (targetVersion, jsonFilePath, app, platform, identifier) => {
170
+ const actualIdentifier = identifier || getIdentifierFromArgs()
171
+ const BUCKET_NAME = getBucketName(actualIdentifier)
172
+ const CDN_URL = getCDNUrl(actualIdentifier)
117
173
  const remoteJsonPath = `histories/${app}/${platform}/list.json`
118
174
 
119
175
  const currentList = JSON.parse(fs.readFileSync(jsonFilePath, 'utf8'))
@@ -146,7 +202,10 @@ const Config = {
146
202
  throw error
147
203
  }
148
204
  },
149
- removeReleaseHistory: async (app, targetBinaryVersion, platform) => {
205
+ removeReleaseHistory: async (app, targetBinaryVersion, platform, identifier) => {
206
+ const actualIdentifier = identifier || getIdentifierFromArgs()
207
+ const BUCKET_NAME = getBucketName(actualIdentifier)
208
+ const CDN_URL = getCDNUrl(actualIdentifier)
150
209
  const remoteJsonPath = historyJsonFileRemotePath(
151
210
  app,
152
211
  platform,
@@ -7,27 +7,55 @@ import {
7
7
  } from '@algocare/react-native-code-push'
8
8
  import * as fs from 'fs'
9
9
  import axios from 'axios'
10
- import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
10
+ import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3'
11
+ import * as dotenv from 'dotenv'
12
+ dotenv.config()
13
+
14
+ // CLI 인자에서 identifier 추출 (패키지 버그 workaround)
15
+ function getIdentifierFromArgs(): 'stg' | 'prd' {
16
+ const args = process.argv
17
+ const identifierIndex = args.findIndex(arg => arg === '-i' || arg === '--identifier')
18
+ if (identifierIndex !== -1 && args[identifierIndex + 1]) {
19
+ return args[identifierIndex + 1] as 'stg' | 'prd'
20
+ }
21
+ // --identifier=prd 형태 처리
22
+ const identifierArg = args.find(arg => arg.startsWith('--identifier='))
23
+ if (identifierArg) {
24
+ return identifierArg.split('=')[1] as 'stg' | 'prd'
25
+ }
26
+ return 'stg' // 기본값
27
+ }
11
28
 
12
29
  const s3Client = new S3Client({
13
- region: process.env.AWS_REGION,
30
+ region: process.env.AWS_REGION || 'ap-northeast-2',
14
31
  credentials: {
15
32
  accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
16
33
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
17
34
  },
18
35
  })
19
36
 
20
- function getBucketName(identifier: 'stg' | 'prd') {
21
- return identifier === 'prd'
22
- ? process.env.AWS_S3_BUCKET_PRD || 'codepush-bucket'
23
- : process.env.AWS_S3_BUCKET_STG || 'codepush-bucket'
37
+ function getBucketName(identifier?: 'stg' | 'prd') {
38
+ // Legacy support: AWS_S3_BUCKET (단일 버킷)
39
+ if (process.env.AWS_S3_BUCKET) {
40
+ return process.env.AWS_S3_BUCKET
41
+ }
42
+
43
+ const actualIdentifier = identifier || getIdentifierFromArgs()
44
+ return actualIdentifier === 'prd'
45
+ ? process.env.AWS_S3_BUCKET_PRD || 'a-algocare-c-prd'
46
+ : process.env.AWS_S3_BUCKET_STG || 'a-algocare-b-stg'
24
47
  }
25
48
 
26
- function getCDNUrl(identifier: 'stg' | 'prd') {
27
- const BUCKET_NAME = getBucketName(identifier)
28
- return identifier === 'prd'
29
- ? process.env.CDN_URL_PRD || `https://${BUCKET_NAME}.s3.amazonaws.com`
30
- : process.env.CDN_URL_STG || `https://${BUCKET_NAME}.s3.amazonaws.com`
49
+ function getCDNUrl(identifier?: 'stg' | 'prd') {
50
+ // Legacy support: CDN_URL (단일 CDN)
51
+ if (process.env.CDN_URL) {
52
+ return process.env.CDN_URL
53
+ }
54
+
55
+ const actualIdentifier = identifier || getIdentifierFromArgs()
56
+ return actualIdentifier === 'prd'
57
+ ? process.env.CDN_URL_PRD || 'https://contents.algocare.link'
58
+ : process.env.CDN_URL_STG || 'https://contents-stg.algocare.link'
31
59
  }
32
60
 
33
61
  function historyJsonFileRemotePath(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algocare/react-native-code-push",
3
- "version": "12.5.0",
3
+ "version": "12.6.0",
4
4
  "description": "React Native plugin for the CodePush service",
5
5
  "main": "CodePush.js",
6
6
  "typings": "typings/react-native-code-push.d.ts",