Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
14 changes: 13 additions & 1 deletion .github/workflows/sample_firebase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ on:

env:
ACTIONS_INSTALL_COMMAND: pnpm install
ACTIONS_BUILD_COMMAND: pnpm run build
ACTIONS_BUILD_COMMAND: npm run build
ACTIONS_BUILD_DIST: dist
ACTIONS_LOCK_FILE: pnpm-lock.yaml

NEXT_PUBLIC_SITE_ORIGIN: https://example.com
NEXT_PUBLIC_FIREBASE_API_KEY: "XXXXXXXXXXXXXXXXX"
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: "xxxxxxxxxx.firebaseapp.com"
NEXT_PUBLIC_FIREBASE_PROJECT_ID: "xxxxxxxxxx"
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: "xxxxxxxxxx.firebasestorage.app"
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: "000000000000"
NEXT_PUBLIC_FIREBASE_APP_ID: "0:000000000000:xxx:0000000000000000000000"

permissions:
id-token: write
Expand Down Expand Up @@ -45,6 +51,12 @@ jobs:
- name: install dependencies
run: ${{ env.ACTIONS_INSTALL_COMMAND }}

- name: install functions dependencies
run: pnpm install --prefix functions

- name: lint
run: npx eslint --ext .ts,.tsx,.js src

- name: build
run: ${{ env.ACTIONS_BUILD_COMMAND }}

Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ node_modules
.DS_Store
next-env.d.ts
dist
.env.local
*.tsbuildinfo
.env*.local
.firebase
50 changes: 50 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# CLAUDE.md

## モノレポ構成

```
packages/
core/ # Firebase非依存の共通型・ユーティリティ(@hinagata-next/core)
web/ # Next.js Webアプリ(@hinagata-next/web)
functions/ # Firebase Cloud Functions(@hinagata-next/functions)
```

## Import

- `packages/web/` 内のパスエイリアスは `~/`(`packages/web/src/` へのマップ)
- `packages/functions/` 内のパスエイリアスは `~/`(`packages/functions/src/` へのマップ)
- core パッケージへのアクセスは `@hinagata-next/core/common/...` または `@hinagata-next/core/feature/...`
- 相対 import(`./`, `../`)は禁止

## Code style

- Prettier: trailingComma=none, arrowParens=avoid
- コンポーネントは arrow function のみ(`function Foo()` は使わない)

## Styling

- Emotion(`@emotion/styled`, `@emotion/react`)を使う
- Tailwind・CSS Modules は使わない

## Next.js

- `output: "export"`(静的エクスポート)のため SSR 系 API(`cookies()`, `headers()`, Server Actions など)は使えない
- バックエンド処理は Firebase Cloud Functions(`requestAppCallable` で呼ぶ)

## Firestore

- Firestore SDK を直接使わず、必ず `ClientDataStoreAgent`(`~/common/ClientDataStoreAgent`)経由でアクセスする
- スキーマ定義は `@hinagata-next/core/feature/app-data-store-scheme.ts` に `DataStoreScheme` として追加する
- `parse` 関数を scheme に持たせる(`withConverter` は `DataStoreAgent` が内部的に使用)
- 型定義ファイル(`@hinagata-next/core/feature/*.ts`)に対応する `parseXxx` 関数も合わせて定義する
- サブコレクションは `parentCollection` で親 scheme を参照して階層を表現する
- `ClientDataStoreAgent` インスタンスはコンポーネントの外(モジュールレベル)で生成する
- React コンポーネントからのリアルタイム購読は `~/common/database-common-hooks` のフックを使う
- 単一ドキュメント: `useDataStoreSingleItem`
- コレクション: `useDataStoreList`(`QueryFormula<T>[]` でクエリを渡す)
- コレクショングループ: `useDataStoreGroupList`
- エラーハンドリングは `extractFirebaseError`(`~/common/FirebaseErrorParameter`)で `FirebaseErrorParameter` に変換する

## Utilities

- 配列・文字列・日付などの操作は `@hinagata-next/core/common/*-util` に既存関数がないか先に確認する
36 changes: 36 additions & 0 deletions firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"firestore": {
"database": "(default)",
"location": "asia-northeast1",
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": [
{
"source": "packages/functions",
"codebase": "default",
"disallowLegacyRuntimeConfig": true,
"runtime": "nodejs22",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
"*.local"
],
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run make-index",
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
],
"hosting": {
"public": "dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
51 changes: 51 additions & 0 deletions firestore.indexes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
// Example (Standard Edition):
//
// "indexes": [
// {
// "collectionGroup": "widgets",
// "queryScope": "COLLECTION",
// "fields": [
// { "fieldPath": "foo", "arrayConfig": "CONTAINS" },
// { "fieldPath": "bar", "mode": "DESCENDING" }
// ]
// },
//
// "fieldOverrides": [
// {
// "collectionGroup": "widgets",
// "fieldPath": "baz",
// "indexes": [
// { "order": "ASCENDING", "queryScope": "COLLECTION" }
// ]
// },
// ]
// ]
//
// Example (Enterprise Edition):
//
// "indexes": [
// {
// "collectionGroup": "reviews",
// "queryScope": "COLLECTION_GROUP",
// "apiScope": "MONGODB_COMPATIBLE_API",
// "density": "DENSE",
// "multikey": false,
// "fields": [
// { "fieldPath": "baz", "mode": "ASCENDING" }
// ]
// },
// {
// "collectionGroup": "items",
// "queryScope": "COLLECTION_GROUP",
// "apiScope": "MONGODB_COMPATIBLE_API",
// "density": "SPARSE_ANY",
// "multikey": true,
// "fields": [
// { "fieldPath": "baz", "mode": "ASCENDING" }
// ]
// },
// ]
"indexes": [],
"fieldOverrides": []
}
10 changes: 10 additions & 0 deletions firestore.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
rules_version='2'

service cloud.firestore {
match /databases/{database}/documents {
match /profiles/{userId} {
allow read: if true;
allow write: if request.auth.uid == userId;
}
}
}
10 changes: 10 additions & 0 deletions packages/core/src/common/CommonPermission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { parseBoolean, parseObject } from "@hinagata-next/core/common/parser-helper";

type CommonPermission = { valid: boolean };

export const parseCommonPermission = (src: unknown) =>
parseObject<CommonPermission>(src, ({ valid }) => ({
valid: parseBoolean(valid)
}));

export default CommonPermission;
Loading