Skip to content
Merged

canary #5534

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ src/

## 開発環境

- **Node.js 20.x**を使用
- **npm 10.x**を使用(Node.js 20 同梱版)
- **Node.js 22.x**を使用
- **npm 10.x**を使用(Node.js 22 同梱版)
- Metro キャッシュ問題が発生した場合のみ`expo start --clear`を実行
- GraphQL codegen には`.env.local`に`GQL_API_URL`が必要

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/bump_version_on_canary_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: "npm"

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/bump_version_on_release_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: "npm"

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: "npm"
- name: Install dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/typecheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: "npm"
- name: Install dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ This handbook defines how automation agents collaborate safely and effectively o

## Tooling & Environment Expectations

- Target **Node.js 20.x** and **npm 10.x**.
- Target **Node.js 22.x** and **npm 10.x**.
- Run `npm install` when dependencies shift; avoid re-locking packages unless instructed.
- Metro cache issues: run `expo start --clear` only when debugging build failures and document the action.
- For native builds, rely on project scripts (`npm run android`, `npm run ios`).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ This app recreates the authentic experience of Japanese train travel by displayi

Before you begin, ensure you have met the following requirements:

- **Node.js 20.x**
- **Node.js 22.x**
- **npm 10.x**
- **React Native development environment** set up
- **Expo CLI** installed globally
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ android {
dimension "environment"
applicationId "me.tinykitten.trainlcd.dev"
versionNameSuffix "-dev"
versionCode 100000304
versionCode 100000305
versionName "10.2.1"
}
prod {
dimension "environment"
versionCode 100000304
versionCode 100000305
versionName "10.2.1"
}
}
Expand Down
5 changes: 3 additions & 2 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default ({ config }: ConfigContext) => ({
},
},
ios: {
buildNumber: '2517',
buildNumber: '2518',
bundleIdentifier:
process.env.EAS_BUILD_PROFILE === 'production'
? 'me.tinykitten.trainlcd'
Expand All @@ -69,7 +69,7 @@ export default ({ config }: ConfigContext) => ({
? 'me.tinykitten.trainlcd'
: 'me.tinykitten.trainlcd.dev',
permissions: [],
versionCode: 100000304,
versionCode: 100000305,
},
owner: 'trainlcd',
});
Expand All @@ -81,3 +81,4 @@ export default ({ config }: ConfigContext) => ({




3 changes: 3 additions & 0 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@
"tuningItemHeaderDelay": "Header animation delay",
"tuningItemHeaderDuration": "Header animation duration",
"tuningItemBottomTransitionDelay": "Bottom transition delay",
"tuningItemTTSVoice": "TTS Voice",
"tuningItemTTSJaVoiceName": "Japanese voice name",
"tuningItemTTSEnVoiceName": "English voice name",
"tuningItemLocationAccuracy": "location accuracy",
"headerDelayTooShortErrorText": "Header animation delay must be greater than the Header animation duration.",
"nanErrorText": "The value must be entered numerically.",
Expand Down
3 changes: 3 additions & 0 deletions assets/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@
"tuningItemHeaderDelay": "ヘッダーアニメーション遅延",
"tuningItemHeaderDuration": "ヘッダーアニメーション時間",
"tuningItemBottomTransitionDelay": "ボトム遷移遅延",
"tuningItemTTSVoice": "TTS ボイス",
"tuningItemTTSJaVoiceName": "日本語ボイス名",
"tuningItemTTSEnVoiceName": "英語ボイス名",
"tuningItemLocationAccuracy": "位置情報の精度",
"headerDelayTooShortErrorText": "ヘッダーアニメーション遅延はヘッダーアニメーション時間より大きい値である必要があります。",
"nanErrorText": "値は数値で入力してください。",
Expand Down
2 changes: 1 addition & 1 deletion docs/bump-version-on-canary-pr.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
## 動作

1. PRのヘッドブランチをチェックアウト
2. npm + Node.js 20 をセットアップ
2. npm + Node.js 22 をセットアップ
3. `npm ci` で依存関係インストール
4. `npm run version:bump -- --no-version-increment` を実行
- アプリのバージョン(`X.Y.Z`)は変更しない
Expand Down
2 changes: 1 addition & 1 deletion functions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ These Cloud Functions provide server-side functionality including:

### Prerequisites

- **Node.js** (version 20)
- **Node.js** (version 22)
- **npm** package manager
- **Firebase CLI** installed globally
- **Firebase project** set up and configured
Expand Down
2 changes: 1 addition & 1 deletion functions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"find-orphaned-tts:prod": "tsx src/cli/find-orphaned-tts.ts --project trainlcd-ea91e --bucket trainlcd-ea91e.firebasestorage.app"
},
"engines": {
"node": "20"
"node": "22"
},
"main": "lib/index.js",
"dependencies": {
Expand Down
57 changes: 36 additions & 21 deletions functions/src/cli/find-orphaned-tts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ function printUsage(): void {
console.error('');
console.error('Options:');
console.error(' --bucket <name> Cloud Storageバケット名(必須)');
console.error(' --project <project-id> Firebaseプロジェクトを指定(必須)');
console.error(
' --project <project-id> Firebaseプロジェクトを指定(必須)'
);
console.error(' --delete 孤立ファイルを確認後に削除');
}

Expand Down Expand Up @@ -54,11 +56,11 @@ function parseArgs(argv: string[]): CliArgs | null {

const PAGE_SIZE = 1000;

async function collectStorageIds(
async function collectStorageFiles(
bucket: Bucket,
prefix: string
): Promise<Set<string>> {
const ids = new Set<string>();
): Promise<Map<string, string[]>> {
const filesById = new Map<string, string[]>();
let pageToken: string | undefined;

do {
Expand All @@ -70,23 +72,24 @@ async function collectStorageIds(
});

for (const file of files) {
const match = file.name.match(
/caches\/tts\/(?:ja|en)\/(.+)\.mp3$/
);
const match = file.name.match(/caches\/tts\/(?:ja|en)\/(.+)\.[^.]+$/);
if (match?.[1]) {
ids.add(match[1]);
const id = match[1];
const existing = filesById.get(id) ?? [];
existing.push(file.name);
filesById.set(id, existing);
}
}

pageToken = (apiResponse as { nextPageToken?: string } | undefined)
?.nextPageToken;
if (pageToken) {
process.stdout.write(`\r ${prefix} ... ${ids.size}件取得済み`);
process.stdout.write(`\r ${prefix} ... ${filesById.size}件取得済み`);
}
} while (pageToken);

process.stdout.write(`\r ${prefix} ... ${ids.size}件 完了\n`);
return ids;
process.stdout.write(`\r ${prefix} ... ${filesById.size}件 完了\n`);
return filesById;
}

async function main(): Promise<void> {
Expand Down Expand Up @@ -118,12 +121,16 @@ async function main(): Promise<void> {

// Storage のファイルIDをページネーションで取得(メモリ節約)
console.log('Storageのファイル一覧を取得中...');
const [jaIds, enIds] = await Promise.all([
collectStorageIds(bucket, 'caches/tts/ja/'),
collectStorageIds(bucket, 'caches/tts/en/'),
const [jaFilesById, enFilesById] = await Promise.all([
collectStorageFiles(bucket, 'caches/tts/ja/'),
collectStorageFiles(bucket, 'caches/tts/en/'),
]);
const jaIds = new Set(jaFilesById.keys());
const enIds = new Set(enFilesById.keys());
const storageIds = new Set([...jaIds, ...enIds]);
console.log(` Storageファイル数: JA=${jaIds.size}, EN=${enIds.size} (ユニークID: ${storageIds.size})`);
console.log(
` Storageファイル数: JA=${jaIds.size}, EN=${enIds.size} (ユニークID: ${storageIds.size})`
);

// 孤立ID = Storage にあるが Firestore にない
const orphanedIds = [...storageIds].filter((id) => !firestoreIds.has(id));
Expand Down Expand Up @@ -167,23 +174,31 @@ async function main(): Promise<void> {
console.log(`削除中: ${id}...`);

const promises: Promise<unknown>[] = [];
if (ja) promises.push(bucket.file(`caches/tts/ja/${id}.mp3`).delete());
if (en) promises.push(bucket.file(`caches/tts/en/${id}.mp3`).delete());
if (ja) {
for (const path of jaFilesById.get(id) ?? []) {
promises.push(bucket.file(path).delete());
}
}
if (en) {
for (const path of enFilesById.get(id) ?? []) {
promises.push(bucket.file(path).delete());
}
}

const results = await Promise.allSettled(promises);
const failed = results.filter((r) => r.status === 'rejected');
if (failed.length > 0) {
for (const f of failed) {
console.warn(
` 削除失敗: ${(f as PromiseRejectedResult).reason}`
);
console.warn(` 削除失敗: ${(f as PromiseRejectedResult).reason}`);
}
} else {
deletedCount++;
}
}

console.log(`\n${deletedCount}/${orphanedFiles.length}件の削除が完了しました。`);
console.log(
`\n${deletedCount}/${orphanedFiles.length}件の削除が完了しました。`
);
}

function confirm(prompt: string): Promise<boolean> {
Expand Down
14 changes: 7 additions & 7 deletions functions/src/cli/find-tts-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function printUsage(): void {
);
console.error(' --exact 部分一致ではなく完全一致で検索');
console.error(
' --delete 検索結果を確認後、FirestoreドキュメントとストレージのMP3を削除'
' --delete 検索結果を確認後、Firestoreドキュメントとストレージ音声を削除'
);
console.error(
' --bucket <name> Cloud Storageバケット名を指定(--delete時は必須)'
Expand Down Expand Up @@ -178,14 +178,12 @@ async function main(): Promise<void> {
}

if (!bucket) {
console.error(
'Error: --delete には --bucket の指定が必要です。'
);
console.error('Error: --delete には --bucket の指定が必要です。');
process.exit(1);
}

const confirmed = await confirm(
`\n上記 ${results.length}件のドキュメントとストレージのMP3ファイルを削除しますか? (y/N): `
`\n上記 ${results.length}件のドキュメントとストレージ音声ファイルを削除しますか? (y/N): `
);
if (!confirmed) {
console.log('削除をキャンセルしました。');
Expand All @@ -197,8 +195,10 @@ async function main(): Promise<void> {
for (const doc of results) {
const data = doc.data();
const id: string = doc.id;
const storagePathJa = `caches/tts/ja/${id}.mp3`;
const storagePathEn = `caches/tts/en/${id}.mp3`;
const storagePathJa =
typeof data.pathJa === 'string' ? data.pathJa : `caches/tts/ja/${id}.mp3`;
const storagePathEn =
typeof data.pathEn === 'string' ? data.pathEn : `caches/tts/en/${id}.mp3`;

console.log(`削除中: ${id}...`);

Expand Down
Loading