@xrift/cli 0.1.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/CONTRIBUTING.md +231 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +16 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +16 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/upload.d.ts +4 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +20 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +16 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/__tests__/api.test.d.ts +2 -0
- package/dist/lib/__tests__/api.test.d.ts.map +1 -0
- package/dist/lib/__tests__/api.test.js +23 -0
- package/dist/lib/__tests__/api.test.js.map +1 -0
- package/dist/lib/__tests__/config.test.d.ts +2 -0
- package/dist/lib/__tests__/config.test.d.ts.map +1 -0
- package/dist/lib/__tests__/config.test.js +36 -0
- package/dist/lib/__tests__/config.test.js.map +1 -0
- package/dist/lib/__tests__/project-config.test.d.ts +2 -0
- package/dist/lib/__tests__/project-config.test.d.ts.map +1 -0
- package/dist/lib/__tests__/project-config.test.js +108 -0
- package/dist/lib/__tests__/project-config.test.js.map +1 -0
- package/dist/lib/api.d.ts +15 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +54 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/auth.d.ts +13 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +205 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/config.d.ts +26 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +68 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +17 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +23 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/project-config.d.ts +22 -0
- package/dist/lib/project-config.d.ts.map +1 -0
- package/dist/lib/project-config.js +95 -0
- package/dist/lib/project-config.js.map +1 -0
- package/dist/lib/upload.d.ts +5 -0
- package/dist/lib/upload.d.ts.map +1 -0
- package/dist/lib/upload.js +159 -0
- package/dist/lib/upload.js.map +1 -0
- package/dist/types/index.d.ts +37 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { loadProjectConfig, loadWorldMetadata, saveWorldMetadata, scanDirectory, validateDistDir, } from '../project-config.js';
|
|
6
|
+
describe('project-config', () => {
|
|
7
|
+
let testDir;
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
// テスト用の一時ディレクトリを作成
|
|
10
|
+
testDir = path.join(os.tmpdir(), `xrift-project-test-${Date.now()}`);
|
|
11
|
+
await fs.mkdir(testDir, { recursive: true });
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
// テスト用ディレクトリを削除
|
|
15
|
+
try {
|
|
16
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
// 削除失敗は無視
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
describe('loadProjectConfig', () => {
|
|
23
|
+
it('正しい設定ファイルを読み込める', async () => {
|
|
24
|
+
const config = {
|
|
25
|
+
world: {
|
|
26
|
+
distDir: './dist',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
await fs.writeFile(path.join(testDir, 'xrift.json'), JSON.stringify(config, null, 2));
|
|
30
|
+
const loaded = await loadProjectConfig(testDir);
|
|
31
|
+
expect(loaded).toEqual(config);
|
|
32
|
+
});
|
|
33
|
+
it('設定ファイルが存在しない場合はエラー', async () => {
|
|
34
|
+
await expect(loadProjectConfig(testDir)).rejects.toThrow('プロジェクト設定ファイルが見つかりません');
|
|
35
|
+
});
|
|
36
|
+
it('distDir が設定されていない場合はエラー', async () => {
|
|
37
|
+
const invalidConfig = { world: {} };
|
|
38
|
+
await fs.writeFile(path.join(testDir, 'xrift.json'), JSON.stringify(invalidConfig, null, 2));
|
|
39
|
+
await expect(loadProjectConfig(testDir)).rejects.toThrow('world.distDir が設定されていません');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('loadWorldMetadata と saveWorldMetadata', () => {
|
|
43
|
+
it('ワールドメタデータを保存して読み込める', async () => {
|
|
44
|
+
const metadata = {
|
|
45
|
+
id: 'world_123',
|
|
46
|
+
createdAt: '2025-01-15T10:00:00Z',
|
|
47
|
+
lastUploadedAt: '2025-01-15T12:00:00Z',
|
|
48
|
+
};
|
|
49
|
+
await saveWorldMetadata(metadata, testDir);
|
|
50
|
+
const loaded = await loadWorldMetadata(testDir);
|
|
51
|
+
expect(loaded).toEqual(metadata);
|
|
52
|
+
});
|
|
53
|
+
it('メタデータが存在しない場合は null を返す', async () => {
|
|
54
|
+
const loaded = await loadWorldMetadata(testDir);
|
|
55
|
+
expect(loaded).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
it('.xrift ディレクトリが自動作成される', async () => {
|
|
58
|
+
const metadata = {
|
|
59
|
+
id: 'world_456',
|
|
60
|
+
createdAt: '2025-01-16T10:00:00Z',
|
|
61
|
+
lastUploadedAt: '2025-01-16T10:00:00Z',
|
|
62
|
+
};
|
|
63
|
+
await saveWorldMetadata(metadata, testDir);
|
|
64
|
+
const metaDir = path.join(testDir, '.xrift');
|
|
65
|
+
const stat = await fs.stat(metaDir);
|
|
66
|
+
expect(stat.isDirectory()).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('scanDirectory', () => {
|
|
70
|
+
it('ディレクトリ内のファイルを再帰的にスキャンできる', async () => {
|
|
71
|
+
// テスト用のファイル構造を作成
|
|
72
|
+
const distDir = path.join(testDir, 'dist');
|
|
73
|
+
await fs.mkdir(distDir, { recursive: true });
|
|
74
|
+
await fs.mkdir(path.join(distDir, 'textures'), { recursive: true });
|
|
75
|
+
await fs.writeFile(path.join(distDir, 'world.glb'), 'test');
|
|
76
|
+
await fs.writeFile(path.join(distDir, 'config.json'), '{}');
|
|
77
|
+
await fs.writeFile(path.join(distDir, 'textures', 'texture1.png'), 'test');
|
|
78
|
+
const files = await scanDirectory(distDir);
|
|
79
|
+
expect(files).toHaveLength(3);
|
|
80
|
+
expect(files).toContain(path.join(distDir, 'world.glb'));
|
|
81
|
+
expect(files).toContain(path.join(distDir, 'config.json'));
|
|
82
|
+
expect(files).toContain(path.join(distDir, 'textures', 'texture1.png'));
|
|
83
|
+
});
|
|
84
|
+
it('空のディレクトリの場合は空配列を返す', async () => {
|
|
85
|
+
const emptyDir = path.join(testDir, 'empty');
|
|
86
|
+
await fs.mkdir(emptyDir, { recursive: true });
|
|
87
|
+
const files = await scanDirectory(emptyDir);
|
|
88
|
+
expect(files).toEqual([]);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('validateDistDir', () => {
|
|
92
|
+
it('存在するディレクトリの場合は成功', async () => {
|
|
93
|
+
const distDir = path.join(testDir, 'dist');
|
|
94
|
+
await fs.mkdir(distDir, { recursive: true });
|
|
95
|
+
await expect(validateDistDir(distDir)).resolves.not.toThrow();
|
|
96
|
+
});
|
|
97
|
+
it('存在しないディレクトリの場合はエラー', async () => {
|
|
98
|
+
const nonExistentDir = path.join(testDir, 'does-not-exist');
|
|
99
|
+
await expect(validateDistDir(nonExistentDir)).rejects.toThrow('distディレクトリが見つかりません');
|
|
100
|
+
});
|
|
101
|
+
it('ファイルの場合はエラー', async () => {
|
|
102
|
+
const filePath = path.join(testDir, 'not-a-directory');
|
|
103
|
+
await fs.writeFile(filePath, 'test');
|
|
104
|
+
await expect(validateDistDir(filePath)).rejects.toThrow('はディレクトリではありません');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=project-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-config.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/project-config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type AxiosInstance } from 'axios';
|
|
2
|
+
import type { VerifyTokenResponse } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* API クライアントのインスタンスを作成
|
|
5
|
+
*/
|
|
6
|
+
export declare function createApiClient(token?: string): AxiosInstance;
|
|
7
|
+
/**
|
|
8
|
+
* トークンを検証
|
|
9
|
+
*/
|
|
10
|
+
export declare function verifyToken(token: string): Promise<VerifyTokenResponse>;
|
|
11
|
+
/**
|
|
12
|
+
* 認証済みAPIクライアントを取得
|
|
13
|
+
*/
|
|
14
|
+
export declare function getAuthenticatedClient(): Promise<AxiosInstance>;
|
|
15
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,CAc7D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAe7E;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,aAAa,CAAC,CAcrE"}
|
package/dist/lib/api.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { API_BASE_URL, AUTH_VERIFY_PATH } from './constants.js';
|
|
3
|
+
import { getToken } from './config.js';
|
|
4
|
+
/**
|
|
5
|
+
* API クライアントのインスタンスを作成
|
|
6
|
+
*/
|
|
7
|
+
export function createApiClient(token) {
|
|
8
|
+
const headers = {
|
|
9
|
+
'Content-Type': 'application/json',
|
|
10
|
+
};
|
|
11
|
+
if (token) {
|
|
12
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
13
|
+
}
|
|
14
|
+
return axios.create({
|
|
15
|
+
baseURL: API_BASE_URL,
|
|
16
|
+
headers,
|
|
17
|
+
timeout: 30000,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* トークンを検証
|
|
22
|
+
*/
|
|
23
|
+
export async function verifyToken(token) {
|
|
24
|
+
const client = createApiClient(token);
|
|
25
|
+
try {
|
|
26
|
+
const response = await client.get(AUTH_VERIFY_PATH);
|
|
27
|
+
return response.data;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (axios.isAxiosError(error)) {
|
|
31
|
+
if (error.response?.status === 401) {
|
|
32
|
+
return { valid: false };
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`トークンの検証に失敗しました: ${error.message}`);
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 認証済みAPIクライアントを取得
|
|
41
|
+
*/
|
|
42
|
+
export async function getAuthenticatedClient() {
|
|
43
|
+
const token = await getToken();
|
|
44
|
+
if (!token) {
|
|
45
|
+
throw new Error('ログインが必要です。`xrift login` を実行してください。');
|
|
46
|
+
}
|
|
47
|
+
// トークンの有効性を確認
|
|
48
|
+
const verification = await verifyToken(token);
|
|
49
|
+
if (!verification.valid) {
|
|
50
|
+
throw new Error('トークンが無効です。再度ログインしてください。');
|
|
51
|
+
}
|
|
52
|
+
return createApiClient(token);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC;QAClB,OAAO,EAAE,YAAY;QACrB,OAAO;QACP,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAa;IAC7C,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAsB,gBAAgB,CAAC,CAAC;QACzE,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAC1B,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAE/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,cAAc;IACd,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;IAC9C,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ログイン処理
|
|
3
|
+
*/
|
|
4
|
+
export declare function login(): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* ログアウト処理
|
|
7
|
+
*/
|
|
8
|
+
export declare function logout(): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* 現在のユーザー情報を表示
|
|
11
|
+
*/
|
|
12
|
+
export declare function whoami(): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAqBA;;GAEG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA8J3C;AAED;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAU5C;AAED;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAmC5C"}
|
package/dist/lib/auth.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import open from 'open';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { API_BASE_URL, AUTH_LOGIN_PATH, CALLBACK_PORT, CALLBACK_PATH, } from './constants.js';
|
|
7
|
+
import { saveAuthConfig, deleteAuthConfig, getToken } from './config.js';
|
|
8
|
+
import { verifyToken } from './api.js';
|
|
9
|
+
/**
|
|
10
|
+
* ランダムなstateパラメータを生成(CSRF対策)
|
|
11
|
+
*/
|
|
12
|
+
function generateState() {
|
|
13
|
+
return crypto.randomBytes(32).toString('hex');
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* ログイン処理
|
|
17
|
+
*/
|
|
18
|
+
export async function login() {
|
|
19
|
+
const state = generateState();
|
|
20
|
+
const callbackUrl = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
21
|
+
const loginUrl = `${API_BASE_URL}${AUTH_LOGIN_PATH}?callback=${encodeURIComponent(callbackUrl)}&state=${state}`;
|
|
22
|
+
console.log(chalk.blue('ブラウザで認証を行います...'));
|
|
23
|
+
console.log(chalk.gray(`認証URL: ${loginUrl}`));
|
|
24
|
+
// Callback serverを起動
|
|
25
|
+
const spinner = ora('認証を待機中...').start();
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const server = http.createServer(async (req, res) => {
|
|
28
|
+
if (!req.url?.startsWith(CALLBACK_PATH)) {
|
|
29
|
+
res.writeHead(404);
|
|
30
|
+
res.end('Not Found');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
|
|
35
|
+
const token = url.searchParams.get('token');
|
|
36
|
+
const returnedState = url.searchParams.get('state');
|
|
37
|
+
// CSRF対策: stateパラメータを検証
|
|
38
|
+
if (returnedState !== state) {
|
|
39
|
+
throw new Error('不正なstateパラメータです');
|
|
40
|
+
}
|
|
41
|
+
if (!token) {
|
|
42
|
+
throw new Error('トークンが取得できませんでした');
|
|
43
|
+
}
|
|
44
|
+
// トークンを検証
|
|
45
|
+
const verification = await verifyToken(token);
|
|
46
|
+
if (!verification.valid) {
|
|
47
|
+
throw new Error('無効なトークンです');
|
|
48
|
+
}
|
|
49
|
+
// トークンを保存
|
|
50
|
+
await saveAuthConfig({ token });
|
|
51
|
+
// 成功レスポンス
|
|
52
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
53
|
+
res.end(`
|
|
54
|
+
<!DOCTYPE html>
|
|
55
|
+
<html>
|
|
56
|
+
<head>
|
|
57
|
+
<meta charset="utf-8">
|
|
58
|
+
<title>XRift CLI - ログイン成功</title>
|
|
59
|
+
<style>
|
|
60
|
+
body {
|
|
61
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
62
|
+
display: flex;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
align-items: center;
|
|
65
|
+
height: 100vh;
|
|
66
|
+
margin: 0;
|
|
67
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
68
|
+
}
|
|
69
|
+
.container {
|
|
70
|
+
background: white;
|
|
71
|
+
padding: 3rem;
|
|
72
|
+
border-radius: 1rem;
|
|
73
|
+
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
|
74
|
+
text-align: center;
|
|
75
|
+
}
|
|
76
|
+
h1 { color: #667eea; margin-bottom: 1rem; }
|
|
77
|
+
p { color: #666; margin: 0.5rem 0; }
|
|
78
|
+
</style>
|
|
79
|
+
</head>
|
|
80
|
+
<body>
|
|
81
|
+
<div class="container">
|
|
82
|
+
<h1>✅ ログイン成功</h1>
|
|
83
|
+
<p>XRift CLI へのログインに成功しました!</p>
|
|
84
|
+
<p>このウィンドウを閉じて、ターミナルに戻ってください。</p>
|
|
85
|
+
</div>
|
|
86
|
+
</body>
|
|
87
|
+
</html>
|
|
88
|
+
`);
|
|
89
|
+
spinner.succeed(chalk.green('✅ ログインに成功しました'));
|
|
90
|
+
if (verification.username) {
|
|
91
|
+
console.log(chalk.gray(`ログイン中: ${verification.username}`));
|
|
92
|
+
}
|
|
93
|
+
server.close();
|
|
94
|
+
resolve();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
spinner.fail(chalk.red('❌ ログインに失敗しました'));
|
|
98
|
+
if (error instanceof Error) {
|
|
99
|
+
console.error(chalk.red(error.message));
|
|
100
|
+
}
|
|
101
|
+
// エラーレスポンス
|
|
102
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
103
|
+
res.end(`
|
|
104
|
+
<!DOCTYPE html>
|
|
105
|
+
<html>
|
|
106
|
+
<head>
|
|
107
|
+
<meta charset="utf-8">
|
|
108
|
+
<title>XRift CLI - ログイン失敗</title>
|
|
109
|
+
<style>
|
|
110
|
+
body {
|
|
111
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
112
|
+
display: flex;
|
|
113
|
+
justify-content: center;
|
|
114
|
+
align-items: center;
|
|
115
|
+
height: 100vh;
|
|
116
|
+
margin: 0;
|
|
117
|
+
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
|
118
|
+
}
|
|
119
|
+
.container {
|
|
120
|
+
background: white;
|
|
121
|
+
padding: 3rem;
|
|
122
|
+
border-radius: 1rem;
|
|
123
|
+
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
|
124
|
+
text-align: center;
|
|
125
|
+
}
|
|
126
|
+
h1 { color: #f5576c; margin-bottom: 1rem; }
|
|
127
|
+
p { color: #666; margin: 0.5rem 0; }
|
|
128
|
+
</style>
|
|
129
|
+
</head>
|
|
130
|
+
<body>
|
|
131
|
+
<div class="container">
|
|
132
|
+
<h1>❌ ログイン失敗</h1>
|
|
133
|
+
<p>認証に失敗しました。</p>
|
|
134
|
+
<p>ターミナルに戻り、もう一度お試しください。</p>
|
|
135
|
+
</div>
|
|
136
|
+
</body>
|
|
137
|
+
</html>
|
|
138
|
+
`);
|
|
139
|
+
server.close();
|
|
140
|
+
reject(error);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
server.listen(CALLBACK_PORT, () => {
|
|
144
|
+
// ブラウザを開く
|
|
145
|
+
open(loginUrl).catch(() => {
|
|
146
|
+
spinner.warn('ブラウザを自動で開けませんでした');
|
|
147
|
+
console.log(chalk.yellow('\n以下のURLをブラウザで開いてください:'));
|
|
148
|
+
console.log(chalk.blue(loginUrl));
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
// タイムアウト設定(5分)
|
|
152
|
+
setTimeout(() => {
|
|
153
|
+
spinner.fail(chalk.red('認証がタイムアウトしました'));
|
|
154
|
+
server.close();
|
|
155
|
+
reject(new Error('認証がタイムアウトしました'));
|
|
156
|
+
}, 5 * 60 * 1000);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* ログアウト処理
|
|
161
|
+
*/
|
|
162
|
+
export async function logout() {
|
|
163
|
+
const token = await getToken();
|
|
164
|
+
if (!token) {
|
|
165
|
+
console.log(chalk.yellow('ログインしていません'));
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
await deleteAuthConfig();
|
|
169
|
+
console.log(chalk.green('✅ ログアウトしました'));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 現在のユーザー情報を表示
|
|
173
|
+
*/
|
|
174
|
+
export async function whoami() {
|
|
175
|
+
const token = await getToken();
|
|
176
|
+
if (!token) {
|
|
177
|
+
console.log(chalk.yellow('ログインしていません'));
|
|
178
|
+
console.log(chalk.gray('`xrift login` を実行してログインしてください'));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const spinner = ora('ユーザー情報を取得中...').start();
|
|
182
|
+
try {
|
|
183
|
+
const verification = await verifyToken(token);
|
|
184
|
+
if (!verification.valid) {
|
|
185
|
+
spinner.fail(chalk.red('トークンが無効です'));
|
|
186
|
+
console.log(chalk.gray('再度ログインしてください: `xrift login`'));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
spinner.succeed(chalk.green('ログイン中'));
|
|
190
|
+
if (verification.username) {
|
|
191
|
+
console.log(chalk.blue('ユーザー名:'), verification.username);
|
|
192
|
+
}
|
|
193
|
+
if (verification.email) {
|
|
194
|
+
console.log(chalk.blue('メール:'), verification.email);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
spinner.fail(chalk.red('ユーザー情報の取得に失敗しました'));
|
|
199
|
+
if (error instanceof Error) {
|
|
200
|
+
console.error(chalk.red(error.message));
|
|
201
|
+
}
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AuthConfig } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* 設定ディレクトリを確保
|
|
4
|
+
*/
|
|
5
|
+
export declare function ensureConfigDir(): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* 認証設定を保存
|
|
8
|
+
*/
|
|
9
|
+
export declare function saveAuthConfig(config: AuthConfig): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* 認証設定を読み込み
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadAuthConfig(): Promise<AuthConfig | null>;
|
|
14
|
+
/**
|
|
15
|
+
* 認証設定を削除
|
|
16
|
+
*/
|
|
17
|
+
export declare function deleteAuthConfig(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* トークンを取得
|
|
20
|
+
*/
|
|
21
|
+
export declare function getToken(): Promise<string | null>;
|
|
22
|
+
/**
|
|
23
|
+
* トークンの有効性を確認
|
|
24
|
+
*/
|
|
25
|
+
export declare function isTokenValid(config: AuthConfig): boolean;
|
|
26
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAMrD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAOtE;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAQjE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAMxD"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { CONFIG_DIR, AUTH_CONFIG_FILE } from './constants.js';
|
|
3
|
+
/**
|
|
4
|
+
* 設定ディレクトリを確保
|
|
5
|
+
*/
|
|
6
|
+
export async function ensureConfigDir() {
|
|
7
|
+
try {
|
|
8
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
throw new Error(`設定ディレクトリの作成に失敗しました: ${CONFIG_DIR}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 認証設定を保存
|
|
16
|
+
*/
|
|
17
|
+
export async function saveAuthConfig(config) {
|
|
18
|
+
await ensureConfigDir();
|
|
19
|
+
try {
|
|
20
|
+
await fs.writeFile(AUTH_CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw new Error(`認証設定の保存に失敗しました: ${AUTH_CONFIG_FILE}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 認証設定を読み込み
|
|
28
|
+
*/
|
|
29
|
+
export async function loadAuthConfig() {
|
|
30
|
+
try {
|
|
31
|
+
const data = await fs.readFile(AUTH_CONFIG_FILE, 'utf-8');
|
|
32
|
+
return JSON.parse(data);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
// ファイルが存在しない場合はnullを返す
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 認証設定を削除
|
|
41
|
+
*/
|
|
42
|
+
export async function deleteAuthConfig() {
|
|
43
|
+
try {
|
|
44
|
+
await fs.unlink(AUTH_CONFIG_FILE);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
// ファイルが存在しない場合は無視
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* トークンを取得
|
|
52
|
+
*/
|
|
53
|
+
export async function getToken() {
|
|
54
|
+
const config = await loadAuthConfig();
|
|
55
|
+
return config?.token || null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* トークンの有効性を確認
|
|
59
|
+
*/
|
|
60
|
+
export function isTokenValid(config) {
|
|
61
|
+
if (!config.token)
|
|
62
|
+
return false;
|
|
63
|
+
if (!config.expiresAt)
|
|
64
|
+
return true; // expiresAtがない場合は有効とみなす
|
|
65
|
+
const expiresAt = new Date(config.expiresAt);
|
|
66
|
+
return expiresAt > new Date();
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG9D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAkB;IACrD,MAAM,eAAe,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,mBAAmB,gBAAgB,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uBAAuB;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,kBAAkB;IACpB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;IACtC,OAAO,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC,CAAC,wBAAwB;IAE5D,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC7C,OAAO,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XRift CLI Constants
|
|
3
|
+
*/
|
|
4
|
+
export declare const API_BASE_URL: string;
|
|
5
|
+
export declare const AUTH_LOGIN_PATH = "/cli-login";
|
|
6
|
+
export declare const AUTH_VERIFY_PATH = "/api/auth/verify";
|
|
7
|
+
export declare const CALLBACK_PORT = 3000;
|
|
8
|
+
export declare const CALLBACK_PATH = "/callback";
|
|
9
|
+
export declare const CONFIG_DIR: string;
|
|
10
|
+
export declare const AUTH_CONFIG_FILE: string;
|
|
11
|
+
export declare const PROJECT_CONFIG_FILE = "xrift.json";
|
|
12
|
+
export declare const PROJECT_META_DIR = ".xrift";
|
|
13
|
+
export declare const WORLD_META_FILE = "world.json";
|
|
14
|
+
export declare const WORLD_CREATE_PATH = "/api/worlds";
|
|
15
|
+
export declare const WORLD_UPDATE_PATH = "/api/worlds";
|
|
16
|
+
export declare const WORLD_UPLOAD_URL_PATH = "/api/worlds";
|
|
17
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAGA;;GAEG;AAGH,eAAO,MAAM,YAAY,QAAmD,CAAC;AAG7E,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,eAAO,MAAM,aAAa,OAAO,CAAC;AAClC,eAAO,MAAM,aAAa,cAAc,CAAC;AAGzC,eAAO,MAAM,UAAU,QAAoC,CAAC;AAC5D,eAAO,MAAM,gBAAgB,QAAuC,CAAC;AACrE,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAChD,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,eAAe,eAAe,CAAC;AAG5C,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,qBAAqB,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
/**
|
|
4
|
+
* XRift CLI Constants
|
|
5
|
+
*/
|
|
6
|
+
// API Base URL
|
|
7
|
+
export const API_BASE_URL = process.env.XRIFT_API_URL || 'https://xrift.com';
|
|
8
|
+
// Authentication
|
|
9
|
+
export const AUTH_LOGIN_PATH = '/cli-login';
|
|
10
|
+
export const AUTH_VERIFY_PATH = '/api/auth/verify';
|
|
11
|
+
export const CALLBACK_PORT = 3000;
|
|
12
|
+
export const CALLBACK_PATH = '/callback';
|
|
13
|
+
// Config file paths
|
|
14
|
+
export const CONFIG_DIR = path.join(os.homedir(), '.xrift');
|
|
15
|
+
export const AUTH_CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
16
|
+
export const PROJECT_CONFIG_FILE = 'xrift.json';
|
|
17
|
+
export const PROJECT_META_DIR = '.xrift';
|
|
18
|
+
export const WORLD_META_FILE = 'world.json';
|
|
19
|
+
// World API endpoints
|
|
20
|
+
export const WORLD_CREATE_PATH = '/api/worlds';
|
|
21
|
+
export const WORLD_UPDATE_PATH = '/api/worlds';
|
|
22
|
+
export const WORLD_UPLOAD_URL_PATH = '/api/worlds';
|
|
23
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB;;GAEG;AAEH,eAAe;AACf,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,mBAAmB,CAAC;AAE7E,iBAAiB;AACjB,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAC5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AACnD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AAEzC,oBAAoB;AACpB,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAChD,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AACzC,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAE5C,sBAAsB;AACtB,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAC/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { XriftConfig, WorldMetadata } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* プロジェクト設定ファイル (xrift.json) を読み込み
|
|
4
|
+
*/
|
|
5
|
+
export declare function loadProjectConfig(cwd?: string): Promise<XriftConfig>;
|
|
6
|
+
/**
|
|
7
|
+
* ワールドメタデータを読み込み
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadWorldMetadata(cwd?: string): Promise<WorldMetadata | null>;
|
|
10
|
+
/**
|
|
11
|
+
* ワールドメタデータを保存
|
|
12
|
+
*/
|
|
13
|
+
export declare function saveWorldMetadata(metadata: WorldMetadata, cwd?: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* ディレクトリ内のファイルを再帰的にスキャン
|
|
16
|
+
*/
|
|
17
|
+
export declare function scanDirectory(dirPath: string): Promise<string[]>;
|
|
18
|
+
/**
|
|
19
|
+
* distディレクトリの検証
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateDistDir(distDir: string): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=project-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-config.d.ts","sourceRoot":"","sources":["../../src/lib/project-config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEpE;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CAsBzF;AAWD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAY/B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,aAAa,EACvB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBtE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYpE"}
|