@su-record/vibe 2.6.53 → 2.7.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/CLAUDE.md +64 -291
- package/README.md +112 -217
- package/dist/cli/collaborator.js +1 -1
- package/dist/cli/commands/info.js +1 -1
- package/dist/cli/setup/GlobalInstaller.d.ts +0 -7
- package/dist/cli/setup/GlobalInstaller.d.ts.map +1 -1
- package/dist/cli/setup/GlobalInstaller.js +4 -23
- package/dist/cli/setup/GlobalInstaller.js.map +1 -1
- package/hooks/scripts/utils.js +13 -27
- package/package.json +4 -4
- package/dist/cli/commands/sync.d.ts +0 -9
- package/dist/cli/commands/sync.d.ts.map +0 -1
- package/dist/cli/commands/sync.js +0 -166
- package/dist/cli/commands/sync.js.map +0 -1
- package/dist/infra/lib/claude-storage.d.ts +0 -12
- package/dist/infra/lib/claude-storage.d.ts.map +0 -1
- package/dist/infra/lib/claude-storage.js +0 -59
- package/dist/infra/lib/claude-storage.js.map +0 -1
- package/dist/infra/lib/gemini-api.d.ts +0 -13
- package/dist/infra/lib/gemini-api.d.ts.map +0 -1
- package/dist/infra/lib/gemini-api.js +0 -13
- package/dist/infra/lib/gemini-api.js.map +0 -1
- package/dist/infra/lib/gemini-constants.d.ts +0 -8
- package/dist/infra/lib/gemini-constants.d.ts.map +0 -1
- package/dist/infra/lib/gemini-constants.js +0 -18
- package/dist/infra/lib/gemini-constants.js.map +0 -1
- package/dist/infra/lib/gemini-oauth.d.ts.map +0 -1
- package/dist/infra/lib/gemini-oauth.js.map +0 -1
- package/dist/infra/lib/gemini-storage.d.ts.map +0 -1
- package/dist/infra/lib/gemini-storage.js.map +0 -1
- package/dist/infra/lib/gpt-api.d.ts +0 -13
- package/dist/infra/lib/gpt-api.d.ts.map +0 -1
- package/dist/infra/lib/gpt-api.js +0 -13
- package/dist/infra/lib/gpt-api.js.map +0 -1
- package/dist/infra/lib/gpt-constants.d.ts +0 -12
- package/dist/infra/lib/gpt-constants.d.ts.map +0 -1
- package/dist/infra/lib/gpt-constants.js +0 -18
- package/dist/infra/lib/gpt-constants.js.map +0 -1
- package/dist/infra/lib/gpt-oauth.d.ts +0 -66
- package/dist/infra/lib/gpt-oauth.d.ts.map +0 -1
- package/dist/infra/lib/gpt-oauth.js +0 -389
- package/dist/infra/lib/gpt-oauth.js.map +0 -1
- package/dist/infra/lib/gpt-storage.d.ts +0 -40
- package/dist/infra/lib/gpt-storage.d.ts.map +0 -1
- package/dist/infra/lib/gpt-storage.js +0 -106
- package/dist/infra/lib/gpt-storage.js.map +0 -1
- package/dist/infra/lib/sync/constants.d.ts +0 -21
- package/dist/infra/lib/sync/constants.d.ts.map +0 -1
- package/dist/infra/lib/sync/constants.js +0 -78
- package/dist/infra/lib/sync/constants.js.map +0 -1
- package/dist/infra/lib/sync/crypto.d.ts +0 -23
- package/dist/infra/lib/sync/crypto.d.ts.map +0 -1
- package/dist/infra/lib/sync/crypto.js +0 -55
- package/dist/infra/lib/sync/crypto.js.map +0 -1
- package/dist/infra/lib/sync/drive.d.ts +0 -22
- package/dist/infra/lib/sync/drive.d.ts.map +0 -1
- package/dist/infra/lib/sync/drive.js +0 -99
- package/dist/infra/lib/sync/drive.js.map +0 -1
- package/dist/infra/lib/sync/index.d.ts +0 -9
- package/dist/infra/lib/sync/index.d.ts.map +0 -1
- package/dist/infra/lib/sync/index.js +0 -9
- package/dist/infra/lib/sync/index.js.map +0 -1
- package/dist/infra/lib/sync/oauth.d.ts +0 -12
- package/dist/infra/lib/sync/oauth.d.ts.map +0 -1
- package/dist/infra/lib/sync/oauth.js +0 -157
- package/dist/infra/lib/sync/oauth.js.map +0 -1
- package/dist/infra/lib/sync/storage.d.ts +0 -21
- package/dist/infra/lib/sync/storage.d.ts.map +0 -1
- package/dist/infra/lib/sync/storage.js +0 -32
- package/dist/infra/lib/sync/storage.js.map +0 -1
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — Google Drive AppData OAuth 상수
|
|
3
|
-
* Google Cloud Console에서 Desktop OAuth 클라이언트 생성 후
|
|
4
|
-
* VIBE_SYNC_GOOGLE_CLIENT_ID 환경변수 또는 ~/.config/vibe/google-oauth-client.json 으로 설정
|
|
5
|
-
*/
|
|
6
|
-
import * as fs from 'node:fs';
|
|
7
|
-
import * as path from 'node:path';
|
|
8
|
-
import * as os from 'node:os';
|
|
9
|
-
export const SYNC_REDIRECT_PORT = 51122;
|
|
10
|
-
export const SYNC_REDIRECT_PATH = '/oauth-callback';
|
|
11
|
-
export const SYNC_REDIRECT_URI = `http://localhost:${SYNC_REDIRECT_PORT}${SYNC_REDIRECT_PATH}`;
|
|
12
|
-
export const SYNC_SCOPES = [
|
|
13
|
-
'https://www.googleapis.com/auth/drive.appdata',
|
|
14
|
-
'https://www.googleapis.com/auth/userinfo.email',
|
|
15
|
-
'https://www.googleapis.com/auth/userinfo.profile',
|
|
16
|
-
'https://www.googleapis.com/auth/gmail.readonly',
|
|
17
|
-
'https://www.googleapis.com/auth/gmail.send',
|
|
18
|
-
'https://www.googleapis.com/auth/drive',
|
|
19
|
-
'https://www.googleapis.com/auth/spreadsheets',
|
|
20
|
-
'https://www.googleapis.com/auth/calendar',
|
|
21
|
-
'https://www.googleapis.com/auth/youtube.readonly',
|
|
22
|
-
];
|
|
23
|
-
export const SYNC_OAUTH_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
|
|
24
|
-
export const SYNC_OAUTH_TOKEN_URL = 'https://oauth2.googleapis.com/token';
|
|
25
|
-
export const SYNC_OAUTH_USERINFO_URL = 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json';
|
|
26
|
-
export const SYNC_DRIVE_APPDATA_FOLDER = 'vibe-sync';
|
|
27
|
-
export const SYNC_FILE_AUTH = 'vibe-auth.enc';
|
|
28
|
-
export const SYNC_FILE_MEMORY = 'vibe-memory.enc';
|
|
29
|
-
export const SYNC_OAUTH_TIMEOUT_MS = 5 * 60 * 1000; // 5분
|
|
30
|
-
/** Cached OAuth client credentials from JSON file */
|
|
31
|
-
let _cachedOAuthClient = null;
|
|
32
|
-
function loadOAuthClientJson() {
|
|
33
|
-
if (_cachedOAuthClient)
|
|
34
|
-
return _cachedOAuthClient;
|
|
35
|
-
const configDir = process.platform === 'win32'
|
|
36
|
-
? path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 'vibe')
|
|
37
|
-
: path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'vibe');
|
|
38
|
-
const jsonPath = path.join(configDir, 'google-oauth-client.json');
|
|
39
|
-
try {
|
|
40
|
-
if (!fs.existsSync(jsonPath))
|
|
41
|
-
return null;
|
|
42
|
-
const raw = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
|
|
43
|
-
const installed = (raw.installed ?? raw.web);
|
|
44
|
-
if (!installed?.client_id)
|
|
45
|
-
return null;
|
|
46
|
-
_cachedOAuthClient = {
|
|
47
|
-
clientId: String(installed.client_id),
|
|
48
|
-
clientSecret: String(installed.client_secret ?? ''),
|
|
49
|
-
};
|
|
50
|
-
return _cachedOAuthClient;
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
export function getSyncClientId() {
|
|
57
|
-
const envId = process.env.VIBE_SYNC_GOOGLE_CLIENT_ID;
|
|
58
|
-
if (envId)
|
|
59
|
-
return envId;
|
|
60
|
-
const fromFile = loadOAuthClientJson();
|
|
61
|
-
if (fromFile)
|
|
62
|
-
return fromFile.clientId;
|
|
63
|
-
throw new Error('Google OAuth client not configured. Set VIBE_SYNC_GOOGLE_CLIENT_ID env var or place google-oauth-client.json in ~/.config/vibe/');
|
|
64
|
-
}
|
|
65
|
-
export function getSyncClientSecret() {
|
|
66
|
-
const envSecret = process.env.VIBE_SYNC_GOOGLE_CLIENT_SECRET;
|
|
67
|
-
if (envSecret)
|
|
68
|
-
return envSecret;
|
|
69
|
-
const fromFile = loadOAuthClientJson();
|
|
70
|
-
return fromFile?.clientSecret ?? '';
|
|
71
|
-
}
|
|
72
|
-
/** Check if OAuth credentials are available (env or JSON file) */
|
|
73
|
-
export function isGoogleOAuthConfigured() {
|
|
74
|
-
if (process.env.VIBE_SYNC_GOOGLE_CLIENT_ID)
|
|
75
|
-
return true;
|
|
76
|
-
return loadOAuthClientJson() !== null;
|
|
77
|
-
}
|
|
78
|
-
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/infra/lib/sync/constants.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — AES-256-GCM 암호화/복호화
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* 랜덤 32바이트 키 생성 (base64 반환)
|
|
6
|
-
*/
|
|
7
|
-
export declare function generateEncryptionKey(): string;
|
|
8
|
-
/**
|
|
9
|
-
* 패스프레이즈로부터 키 유도 (PBKDF2)
|
|
10
|
-
*/
|
|
11
|
-
export declare function deriveKeyFromPassphrase(passphrase: string, salt: Buffer): Buffer;
|
|
12
|
-
/**
|
|
13
|
-
* AES-256-GCM 암호화
|
|
14
|
-
* @param plaintext - 암호화할 데이터
|
|
15
|
-
* @param keyBase64 - base64 인코딩된 32바이트 키 (또는 Buffer)
|
|
16
|
-
* @param optionalSalt - 패스프레이즈 유도 시 사용한 salt (첫 16바이트가 payload 앞에 붙음)
|
|
17
|
-
*/
|
|
18
|
-
export declare function encrypt(plaintext: Buffer, keyBase64: string | Buffer): Buffer;
|
|
19
|
-
/**
|
|
20
|
-
* AES-256-GCM 복호화
|
|
21
|
-
*/
|
|
22
|
-
export declare function decrypt(ciphertext: Buffer, keyBase64: string | Buffer): Buffer;
|
|
23
|
-
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/sync/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAQ7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAU9E"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — AES-256-GCM 암호화/복호화
|
|
3
|
-
*/
|
|
4
|
-
import crypto from 'crypto';
|
|
5
|
-
const ALG = 'aes-256-gcm';
|
|
6
|
-
const IV_LEN = 12;
|
|
7
|
-
const TAG_LEN = 16;
|
|
8
|
-
const KEY_LEN = 32;
|
|
9
|
-
const SALT_LEN = 16;
|
|
10
|
-
const PBKDF2_ITERATIONS = 100_000;
|
|
11
|
-
/**
|
|
12
|
-
* 랜덤 32바이트 키 생성 (base64 반환)
|
|
13
|
-
*/
|
|
14
|
-
export function generateEncryptionKey() {
|
|
15
|
-
return crypto.randomBytes(KEY_LEN).toString('base64');
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* 패스프레이즈로부터 키 유도 (PBKDF2)
|
|
19
|
-
*/
|
|
20
|
-
export function deriveKeyFromPassphrase(passphrase, salt) {
|
|
21
|
-
return crypto.pbkdf2Sync(passphrase, salt, PBKDF2_ITERATIONS, KEY_LEN, 'sha256');
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* AES-256-GCM 암호화
|
|
25
|
-
* @param plaintext - 암호화할 데이터
|
|
26
|
-
* @param keyBase64 - base64 인코딩된 32바이트 키 (또는 Buffer)
|
|
27
|
-
* @param optionalSalt - 패스프레이즈 유도 시 사용한 salt (첫 16바이트가 payload 앞에 붙음)
|
|
28
|
-
*/
|
|
29
|
-
export function encrypt(plaintext, keyBase64) {
|
|
30
|
-
const key = typeof keyBase64 === 'string' ? Buffer.from(keyBase64, 'base64') : keyBase64;
|
|
31
|
-
if (key.length !== KEY_LEN)
|
|
32
|
-
throw new Error('Encryption key must be 32 bytes');
|
|
33
|
-
const iv = crypto.randomBytes(IV_LEN);
|
|
34
|
-
const cipher = crypto.createCipheriv(ALG, key, iv, { authTagLength: TAG_LEN });
|
|
35
|
-
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
36
|
-
const tag = cipher.getAuthTag();
|
|
37
|
-
return Buffer.concat([iv, tag, encrypted]);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* AES-256-GCM 복호화
|
|
41
|
-
*/
|
|
42
|
-
export function decrypt(ciphertext, keyBase64) {
|
|
43
|
-
const key = typeof keyBase64 === 'string' ? Buffer.from(keyBase64, 'base64') : keyBase64;
|
|
44
|
-
if (key.length !== KEY_LEN)
|
|
45
|
-
throw new Error('Decryption key must be 32 bytes');
|
|
46
|
-
if (ciphertext.length < IV_LEN + TAG_LEN)
|
|
47
|
-
throw new Error('Ciphertext too short');
|
|
48
|
-
const iv = ciphertext.subarray(0, IV_LEN);
|
|
49
|
-
const tag = ciphertext.subarray(IV_LEN, IV_LEN + TAG_LEN);
|
|
50
|
-
const data = ciphertext.subarray(IV_LEN + TAG_LEN);
|
|
51
|
-
const decipher = crypto.createDecipheriv(ALG, key, iv, { authTagLength: TAG_LEN });
|
|
52
|
-
decipher.setAuthTag(tag);
|
|
53
|
-
return Buffer.concat([decipher.update(data), decipher.final()]);
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=crypto.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../../src/infra/lib/sync/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,GAAG,GAAG,aAAa,CAAC;AAC1B,MAAM,MAAM,GAAG,EAAE,CAAC;AAClB,MAAM,OAAO,GAAG,EAAE,CAAC;AACnB,MAAM,OAAO,GAAG,EAAE,CAAC;AACnB,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpB,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAElC;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAkB,EAAE,IAAY;IACtE,OAAO,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AACnF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,SAAiB,EAAE,SAA0B;IACnE,MAAM,GAAG,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzF,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC/E,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/E,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,UAAkB,EAAE,SAA0B;IACpE,MAAM,GAAG,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzF,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC/E,IAAI,UAAU,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAClF,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;IACnF,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — Google Drive AppData API (upload/download)
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* AppData 폴더 내 파일 목록 조회 (name으로 필터)
|
|
6
|
-
*/
|
|
7
|
-
export declare function findAppDataFile(name: string): Promise<{
|
|
8
|
-
id: string;
|
|
9
|
-
} | null>;
|
|
10
|
-
/**
|
|
11
|
-
* AppData에 파일 업로드 (없으면 생성, 있으면 PATCH 덮어쓰기)
|
|
12
|
-
*/
|
|
13
|
-
export declare function uploadAppDataFile(name: string, body: Buffer): Promise<void>;
|
|
14
|
-
/**
|
|
15
|
-
* AppData에서 파일 다운로드
|
|
16
|
-
*/
|
|
17
|
-
export declare function downloadAppDataFile(name: string): Promise<Buffer | null>;
|
|
18
|
-
export declare function uploadAuthEnc(data: Buffer): Promise<void>;
|
|
19
|
-
export declare function uploadMemoryEnc(data: Buffer): Promise<void>;
|
|
20
|
-
export declare function downloadAuthEnc(): Promise<Buffer | null>;
|
|
21
|
-
export declare function downloadMemoryEnc(): Promise<Buffer | null>;
|
|
22
|
-
//# sourceMappingURL=drive.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drive.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/sync/drive.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAUlF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CjF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAa9E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/D;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjE;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE9D;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEhE"}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — Google Drive AppData API (upload/download)
|
|
3
|
-
*/
|
|
4
|
-
import { getSyncAccessToken } from './oauth.js';
|
|
5
|
-
import { SYNC_FILE_AUTH, SYNC_FILE_MEMORY } from './constants.js';
|
|
6
|
-
const DRIVE_FILES_URL = 'https://www.googleapis.com/drive/v3/files';
|
|
7
|
-
const DRIVE_UPLOAD_URL = 'https://www.googleapis.com/upload/drive/v3/files';
|
|
8
|
-
async function getAccessToken() {
|
|
9
|
-
return getSyncAccessToken();
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* AppData 폴더 내 파일 목록 조회 (name으로 필터)
|
|
13
|
-
*/
|
|
14
|
-
export async function findAppDataFile(name) {
|
|
15
|
-
const token = await getAccessToken();
|
|
16
|
-
const url = `${DRIVE_FILES_URL}?spaces=appDataFolder&q=${encodeURIComponent("name='" + name + "'")}&fields=files(id,name)`;
|
|
17
|
-
const res = await fetch(url, {
|
|
18
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
19
|
-
});
|
|
20
|
-
if (!res.ok)
|
|
21
|
-
throw new Error(`Drive list failed: ${await res.text()}`);
|
|
22
|
-
const data = (await res.json());
|
|
23
|
-
const file = data.files?.[0];
|
|
24
|
-
return file ? { id: file.id } : null;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* AppData에 파일 업로드 (없으면 생성, 있으면 PATCH 덮어쓰기)
|
|
28
|
-
*/
|
|
29
|
-
export async function uploadAppDataFile(name, body) {
|
|
30
|
-
const token = await getAccessToken();
|
|
31
|
-
const existing = await findAppDataFile(name);
|
|
32
|
-
const metadata = {
|
|
33
|
-
name,
|
|
34
|
-
parents: ['appDataFolder'],
|
|
35
|
-
};
|
|
36
|
-
const boundary = '-------vibe-sync-multipart';
|
|
37
|
-
const metaJson = JSON.stringify(metadata);
|
|
38
|
-
const parts = [
|
|
39
|
-
Buffer.from(`--${boundary}\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n${metaJson}\r\n--${boundary}\r\nContent-Type: application/octet-stream\r\n\r\n`, 'utf8'),
|
|
40
|
-
body,
|
|
41
|
-
Buffer.from(`\r\n--${boundary}--`, 'utf8'),
|
|
42
|
-
];
|
|
43
|
-
const multipartBody = Buffer.concat(parts);
|
|
44
|
-
if (existing) {
|
|
45
|
-
const res = await fetch(`${DRIVE_UPLOAD_URL}/${existing.id}?uploadType=multipart`, {
|
|
46
|
-
method: 'PATCH',
|
|
47
|
-
headers: {
|
|
48
|
-
Authorization: `Bearer ${token}`,
|
|
49
|
-
'Content-Type': `multipart/related; boundary=${boundary}`,
|
|
50
|
-
},
|
|
51
|
-
body: multipartBody,
|
|
52
|
-
});
|
|
53
|
-
if (!res.ok)
|
|
54
|
-
throw new Error(`Drive update failed: ${await res.text()}`);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const res = await fetch(`${DRIVE_UPLOAD_URL}?uploadType=multipart`, {
|
|
58
|
-
method: 'POST',
|
|
59
|
-
headers: {
|
|
60
|
-
Authorization: `Bearer ${token}`,
|
|
61
|
-
'Content-Type': `multipart/related; boundary=${boundary}`,
|
|
62
|
-
},
|
|
63
|
-
body: multipartBody,
|
|
64
|
-
});
|
|
65
|
-
if (!res.ok)
|
|
66
|
-
throw new Error(`Drive upload failed: ${await res.text()}`);
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* AppData에서 파일 다운로드
|
|
70
|
-
*/
|
|
71
|
-
export async function downloadAppDataFile(name) {
|
|
72
|
-
const file = await findAppDataFile(name);
|
|
73
|
-
if (!file)
|
|
74
|
-
return null;
|
|
75
|
-
const token = await getAccessToken();
|
|
76
|
-
const res = await fetch(`${DRIVE_FILES_URL}/${file.id}?alt=media`, {
|
|
77
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
78
|
-
});
|
|
79
|
-
if (!res.ok) {
|
|
80
|
-
if (res.status === 404)
|
|
81
|
-
return null;
|
|
82
|
-
throw new Error(`Drive download failed: ${await res.text()}`);
|
|
83
|
-
}
|
|
84
|
-
const arrayBuffer = await res.arrayBuffer();
|
|
85
|
-
return Buffer.from(arrayBuffer);
|
|
86
|
-
}
|
|
87
|
-
export async function uploadAuthEnc(data) {
|
|
88
|
-
return uploadAppDataFile(SYNC_FILE_AUTH, data);
|
|
89
|
-
}
|
|
90
|
-
export async function uploadMemoryEnc(data) {
|
|
91
|
-
return uploadAppDataFile(SYNC_FILE_MEMORY, data);
|
|
92
|
-
}
|
|
93
|
-
export async function downloadAuthEnc() {
|
|
94
|
-
return downloadAppDataFile(SYNC_FILE_AUTH);
|
|
95
|
-
}
|
|
96
|
-
export async function downloadMemoryEnc() {
|
|
97
|
-
return downloadAppDataFile(SYNC_FILE_MEMORY);
|
|
98
|
-
}
|
|
99
|
-
//# sourceMappingURL=drive.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drive.js","sourceRoot":"","sources":["../../../../src/infra/lib/sync/drive.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — public API
|
|
3
|
-
*/
|
|
4
|
-
export { runSyncLogin, getSyncAccessToken, refreshSyncAccessToken } from './oauth.js';
|
|
5
|
-
export { loadSyncAuth, saveSyncAuth, getSyncAuthPath } from './storage.js';
|
|
6
|
-
export { encrypt, decrypt, generateEncryptionKey } from './crypto.js';
|
|
7
|
-
export { uploadAuthEnc, uploadMemoryEnc, downloadAuthEnc, downloadMemoryEnc, findAppDataFile, } from './drive.js';
|
|
8
|
-
export { SYNC_FILE_AUTH, SYNC_FILE_MEMORY } from './constants.js';
|
|
9
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,aAAa,EACb,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — public API
|
|
3
|
-
*/
|
|
4
|
-
export { runSyncLogin, getSyncAccessToken, refreshSyncAccessToken } from './oauth.js';
|
|
5
|
-
export { loadSyncAuth, saveSyncAuth, getSyncAuthPath } from './storage.js';
|
|
6
|
-
export { encrypt, decrypt, generateEncryptionKey } from './crypto.js';
|
|
7
|
-
export { uploadAuthEnc, uploadMemoryEnc, downloadAuthEnc, downloadMemoryEnc, findAppDataFile, } from './drive.js';
|
|
8
|
-
export { SYNC_FILE_AUTH, SYNC_FILE_MEMORY } from './constants.js';
|
|
9
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/infra/lib/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,aAAa,EACb,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — Google OAuth (drive.appdata) 플로우
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* 로그인 플로우: 브라우저 오픈 → 콜백에서 code 수신 → 토큰 교환 → 저장
|
|
6
|
-
*/
|
|
7
|
-
export declare function runSyncLogin(): Promise<{
|
|
8
|
-
email?: string;
|
|
9
|
-
}>;
|
|
10
|
-
export declare function refreshSyncAccessToken(): Promise<string>;
|
|
11
|
-
export declare function getSyncAccessToken(): Promise<string>;
|
|
12
|
-
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/sync/oauth.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4DH;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoEhE;AAkCD,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC,CAqB9D;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAK1D"}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — Google OAuth (drive.appdata) 플로우
|
|
3
|
-
*/
|
|
4
|
-
import http from 'http';
|
|
5
|
-
import crypto from 'crypto';
|
|
6
|
-
import { exec } from 'child_process';
|
|
7
|
-
import { getSyncClientId, getSyncClientSecret, SYNC_REDIRECT_URI, SYNC_REDIRECT_PATH, SYNC_SCOPES, SYNC_OAUTH_AUTH_URL, SYNC_OAUTH_TOKEN_URL, SYNC_OAUTH_USERINFO_URL, SYNC_OAUTH_TIMEOUT_MS, } from './constants.js';
|
|
8
|
-
import { loadSyncAuth, saveSyncAuth } from './storage.js';
|
|
9
|
-
function generatePKCE() {
|
|
10
|
-
const verifier = crypto.randomBytes(32).toString('base64url');
|
|
11
|
-
const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');
|
|
12
|
-
return { verifier, challenge };
|
|
13
|
-
}
|
|
14
|
-
function encodeState(payload) {
|
|
15
|
-
return Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url');
|
|
16
|
-
}
|
|
17
|
-
function decodeState(state) {
|
|
18
|
-
const normalized = state.replace(/-/g, '+').replace(/_/g, '/');
|
|
19
|
-
const padded = normalized.padEnd(normalized.length + ((4 - (normalized.length % 4)) % 4), '=');
|
|
20
|
-
return JSON.parse(Buffer.from(padded, 'base64').toString('utf8'));
|
|
21
|
-
}
|
|
22
|
-
function openBrowser(url) {
|
|
23
|
-
const platform = process.platform;
|
|
24
|
-
const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'start' : 'xdg-open';
|
|
25
|
-
exec(`${cmd} "${url}"`, (err) => {
|
|
26
|
-
if (err) {
|
|
27
|
-
console.warn('Could not open browser:', err.message);
|
|
28
|
-
console.log('Open this URL manually:', url);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* 로그인 플로우: 브라우저 오픈 → 콜백에서 code 수신 → 토큰 교환 → 저장
|
|
34
|
-
*/
|
|
35
|
-
export async function runSyncLogin() {
|
|
36
|
-
const clientId = getSyncClientId();
|
|
37
|
-
const clientSecret = getSyncClientSecret();
|
|
38
|
-
const pkce = generatePKCE();
|
|
39
|
-
const authUrl = new URL(SYNC_OAUTH_AUTH_URL);
|
|
40
|
-
authUrl.searchParams.set('client_id', clientId);
|
|
41
|
-
authUrl.searchParams.set('response_type', 'code');
|
|
42
|
-
authUrl.searchParams.set('redirect_uri', SYNC_REDIRECT_URI);
|
|
43
|
-
authUrl.searchParams.set('scope', SYNC_SCOPES.join(' '));
|
|
44
|
-
authUrl.searchParams.set('code_challenge', pkce.challenge);
|
|
45
|
-
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
46
|
-
authUrl.searchParams.set('state', encodeState({ verifier: pkce.verifier }));
|
|
47
|
-
authUrl.searchParams.set('access_type', 'offline');
|
|
48
|
-
authUrl.searchParams.set('prompt', 'consent');
|
|
49
|
-
const [code, stateParam] = await new Promise((resolve, reject) => {
|
|
50
|
-
const port = new URL(SYNC_REDIRECT_URI).port;
|
|
51
|
-
const server = http.createServer((req, res) => {
|
|
52
|
-
const url = new URL(req.url ?? '/', `http://localhost`);
|
|
53
|
-
if (url.pathname !== SYNC_REDIRECT_PATH) {
|
|
54
|
-
res.writeHead(404).end();
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const codeParam = url.searchParams.get('code');
|
|
58
|
-
const stateParam = url.searchParams.get('state');
|
|
59
|
-
const errorParam = url.searchParams.get('error');
|
|
60
|
-
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
61
|
-
res.end('<script>window.close()</script><p>로그인 완료. 이 창을 닫아도 됩니다.</p>');
|
|
62
|
-
server.close();
|
|
63
|
-
if (errorParam) {
|
|
64
|
-
reject(new Error(`OAuth error: ${errorParam}`));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
if (!codeParam || !stateParam) {
|
|
68
|
-
reject(new Error('Missing code or state'));
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
resolve([codeParam, stateParam]);
|
|
72
|
-
});
|
|
73
|
-
server.listen(port, () => {
|
|
74
|
-
openBrowser(authUrl.toString());
|
|
75
|
-
});
|
|
76
|
-
setTimeout(() => {
|
|
77
|
-
server.close();
|
|
78
|
-
reject(new Error('OAuth timeout (5 min)'));
|
|
79
|
-
}, SYNC_OAUTH_TIMEOUT_MS);
|
|
80
|
-
});
|
|
81
|
-
const { verifier } = decodeState(stateParam);
|
|
82
|
-
const tokens = await exchangeCodeForTokens(code, verifier, clientId, clientSecret);
|
|
83
|
-
const existing = loadSyncAuth();
|
|
84
|
-
const encryptionKey = existing?.encryptionKey ?? crypto.randomBytes(32).toString('base64');
|
|
85
|
-
const storage = {
|
|
86
|
-
version: 1,
|
|
87
|
-
accessToken: tokens.access_token,
|
|
88
|
-
refreshToken: tokens.refresh_token ?? existing?.refreshToken ?? '',
|
|
89
|
-
expires: Date.now() + tokens.expires_in * 1000 - 60000,
|
|
90
|
-
email: tokens.email,
|
|
91
|
-
encryptionKey,
|
|
92
|
-
};
|
|
93
|
-
saveSyncAuth(storage);
|
|
94
|
-
return { email: tokens.email };
|
|
95
|
-
}
|
|
96
|
-
async function exchangeCodeForTokens(code, verifier, clientId, clientSecret) {
|
|
97
|
-
const body = new URLSearchParams({
|
|
98
|
-
client_id: clientId,
|
|
99
|
-
code,
|
|
100
|
-
grant_type: 'authorization_code',
|
|
101
|
-
redirect_uri: SYNC_REDIRECT_URI,
|
|
102
|
-
code_verifier: verifier,
|
|
103
|
-
});
|
|
104
|
-
if (clientSecret)
|
|
105
|
-
body.set('client_secret', clientSecret);
|
|
106
|
-
const res = await fetch(SYNC_OAUTH_TOKEN_URL, {
|
|
107
|
-
method: 'POST',
|
|
108
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
109
|
-
body: body.toString(),
|
|
110
|
-
});
|
|
111
|
-
if (!res.ok)
|
|
112
|
-
throw new Error(`Token exchange failed: ${await res.text()}`);
|
|
113
|
-
const tokenPayload = (await res.json());
|
|
114
|
-
let email;
|
|
115
|
-
const userRes = await fetch(SYNC_OAUTH_USERINFO_URL, {
|
|
116
|
-
headers: { Authorization: `Bearer ${tokenPayload.access_token}` },
|
|
117
|
-
});
|
|
118
|
-
if (userRes.ok) {
|
|
119
|
-
const user = (await userRes.json());
|
|
120
|
-
email = user.email;
|
|
121
|
-
}
|
|
122
|
-
return { ...tokenPayload, email };
|
|
123
|
-
}
|
|
124
|
-
export async function refreshSyncAccessToken() {
|
|
125
|
-
const auth = loadSyncAuth();
|
|
126
|
-
if (!auth?.refreshToken)
|
|
127
|
-
throw new Error('Not logged in. Run: vibe sync login');
|
|
128
|
-
const clientId = getSyncClientId();
|
|
129
|
-
const clientSecret = getSyncClientSecret();
|
|
130
|
-
const body = new URLSearchParams({
|
|
131
|
-
grant_type: 'refresh_token',
|
|
132
|
-
refresh_token: auth.refreshToken,
|
|
133
|
-
client_id: clientId,
|
|
134
|
-
});
|
|
135
|
-
if (clientSecret)
|
|
136
|
-
body.set('client_secret', clientSecret);
|
|
137
|
-
const res = await fetch(SYNC_OAUTH_TOKEN_URL, {
|
|
138
|
-
method: 'POST',
|
|
139
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
140
|
-
body: body.toString(),
|
|
141
|
-
});
|
|
142
|
-
if (!res.ok)
|
|
143
|
-
throw new Error(`Token refresh failed: ${await res.text()}`);
|
|
144
|
-
const data = (await res.json());
|
|
145
|
-
const expires = Date.now() + data.expires_in * 1000 - 60000;
|
|
146
|
-
saveSyncAuth({ ...auth, accessToken: data.access_token, expires });
|
|
147
|
-
return data.access_token;
|
|
148
|
-
}
|
|
149
|
-
export async function getSyncAccessToken() {
|
|
150
|
-
const auth = loadSyncAuth();
|
|
151
|
-
if (!auth)
|
|
152
|
-
throw new Error('Not logged in. Run: vibe sync login');
|
|
153
|
-
if (auth.expires > Date.now() + 60000)
|
|
154
|
-
return auth.accessToken;
|
|
155
|
-
return refreshSyncAccessToken();
|
|
156
|
-
}
|
|
157
|
-
//# sourceMappingURL=oauth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../../src/infra/lib/sync/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — sync OAuth 토큰 저장/로드 (sync-auth.json)
|
|
3
|
-
*/
|
|
4
|
-
export interface SyncAuthTokens {
|
|
5
|
-
accessToken: string;
|
|
6
|
-
refreshToken: string;
|
|
7
|
-
expires: number;
|
|
8
|
-
email?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface SyncAuthStorage {
|
|
11
|
-
version: number;
|
|
12
|
-
accessToken: string;
|
|
13
|
-
refreshToken: string;
|
|
14
|
-
expires: number;
|
|
15
|
-
email?: string;
|
|
16
|
-
encryptionKey?: string;
|
|
17
|
-
}
|
|
18
|
-
export declare function getSyncAuthPath(): string;
|
|
19
|
-
export declare function loadSyncAuth(): SyncAuthStorage | null;
|
|
20
|
-
export declare function saveSyncAuth(data: SyncAuthStorage): void;
|
|
21
|
-
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/sync/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAQD,wBAAgB,YAAY,IAAI,eAAe,GAAG,IAAI,CASrD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAIxD"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe sync — sync OAuth 토큰 저장/로드 (sync-auth.json)
|
|
3
|
-
*/
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { getGlobalConfigDir } from '../llm/auth/ConfigManager.js';
|
|
7
|
-
export function getSyncAuthPath() {
|
|
8
|
-
return path.join(getGlobalConfigDir(), 'sync-auth.json');
|
|
9
|
-
}
|
|
10
|
-
function ensureDir(dir) {
|
|
11
|
-
if (!fs.existsSync(dir)) {
|
|
12
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
export function loadSyncAuth() {
|
|
16
|
-
try {
|
|
17
|
-
const p = getSyncAuthPath();
|
|
18
|
-
if (!fs.existsSync(p))
|
|
19
|
-
return null;
|
|
20
|
-
const content = fs.readFileSync(p, 'utf-8');
|
|
21
|
-
return JSON.parse(content);
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export function saveSyncAuth(data) {
|
|
28
|
-
const p = getSyncAuthPath();
|
|
29
|
-
ensureDir(path.dirname(p));
|
|
30
|
-
fs.writeFileSync(p, JSON.stringify(data, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=storage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/infra/lib/sync/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAkBlE,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,eAAe,EAAE,CAAC;QAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAqB;IAChD,MAAM,CAAC,GAAG,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACzF,CAAC"}
|