From 53cf1c0aeea81931d13031ed6072ffe6312ae825 Mon Sep 17 00:00:00 2001 From: yamashita-kenngo Date: Sat, 1 Jun 2024 11:07:58 +0900 Subject: [PATCH] chore: format --- app/src/index.tsx | 62 ++++--- app/src/pages/403.test.tsx | 32 ++-- app/src/pages/403.tsx | 33 ++-- app/src/pages/account/addAccount.test.tsx | 40 ++--- app/src/pages/account/addAccount.tsx | 138 +++++++++------ app/src/pages/dashboard.test.tsx | 28 +-- app/src/pages/dashboard.tsx | 121 ++++++------- app/src/pages/login.test.tsx | 32 ++-- app/src/pages/login.tsx | 161 ++++++++++------- app/src/pages/tenant/addTenant.test.tsx | 44 ++--- app/src/pages/tenant/addTenant.tsx | 178 +++++++++++-------- app/src/schema/account.ts | 44 ++--- app/src/schema/tenant.ts | 26 +-- app/src/service/auth.ts | 58 ++++--- app/src/service/firebase.ts | 20 +-- app/src/service/firestore.test.ts | 59 ++++--- app/src/service/firestore.ts | 201 ++++++++++++++-------- 17 files changed, 741 insertions(+), 536 deletions(-) diff --git a/app/src/index.tsx b/app/src/index.tsx index 8e65722..2741859 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -1,37 +1,45 @@ -import { render } from 'solid-js/web'; -import { Router, Route } from '@solidjs/router'; +import { render } from "solid-js/web"; +import { Router, Route } from "@solidjs/router"; import "./index.css"; -import Login from './pages/login'; -import Dashboard from './pages/dashboard'; -import Page403 from './pages/403'; -import AddAccount from './pages/account/addAccount'; -import AddTenant from './pages/tenant/addTenant'; -import { isVerifiedAccount } from './service/auth'; +import Login from "./pages/login"; +import Dashboard from "./pages/dashboard"; +import Page403 from "./pages/403"; +import AddAccount from "./pages/account/addAccount"; +import AddTenant from "./pages/tenant/addTenant"; +import { isVerifiedAccount } from "./service/auth"; -const root = document.getElementById('root'); +const root = document.getElementById("root"); if (import.meta.env.DEV && !(root instanceof HTMLElement)) { - throw new Error( - 'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?', - ); + throw new Error( + "Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?", + ); } render( - () => ( - - - await checkAuth()} /> - - - await checkAuth()} /> - - ), - document.getElementById('root')!, -) + () => ( + + + await checkAuth()} + /> + + + await checkAuth()} + /> + + ), + document.getElementById("root")!, +); async function checkAuth() { - if (! await isVerifiedAccount()) { - window.location.href = '/403'; - } -} \ No newline at end of file + if (!(await isVerifiedAccount())) { + window.location.href = "/403"; + } +} diff --git a/app/src/pages/403.test.tsx b/app/src/pages/403.test.tsx index e9bcdd6..8abd7e0 100644 --- a/app/src/pages/403.test.tsx +++ b/app/src/pages/403.test.tsx @@ -1,33 +1,35 @@ import { suite } from "uvu"; import * as assert from "uvu/assert"; -import { render, fireEvent, waitFor } from '@solidjs/testing-library'; -import { isInDocument, hasStyle } from 'solid-dom-testing'; +import { render, fireEvent, waitFor } from "@solidjs/testing-library"; +import { isInDocument, hasStyle } from "solid-dom-testing"; import Page403 from "./403"; -const test = suite>(''); +const test = suite>(""); test.before.each((context) => { - const returnValue = render(() => ); - Object.getOwnPropertyNames(returnValue).forEach((name) => { - // @ts-expect-error - context[name] = returnValue[name]; - }); + const returnValue = render(() => ); + Object.getOwnPropertyNames(returnValue).forEach((name) => { + // @ts-expect-error + context[name] = returnValue[name]; + }); }); test.after.each(({ unmount }) => unmount()); -test('page render 403 title', ({ getByText }) => { - assert.ok(isInDocument(getByText('403 Forbidden'))); +test("page render 403 title", ({ getByText }) => { + assert.ok(isInDocument(getByText("403 Forbidden"))); }); -test('page render 403 message', ({ getByText }) => { - assert.ok(isInDocument(getByText('You are not allowed to access this page.'))); +test("page render 403 message", ({ getByText }) => { + assert.ok( + isInDocument(getByText("You are not allowed to access this page.")), + ); }); -test('page render 403 contact message', ({ getByText }) => { - assert.ok(isInDocument(getByText('Please contact the administrator.'))); +test("page render 403 contact message", ({ getByText }) => { + assert.ok(isInDocument(getByText("Please contact the administrator."))); }); -test.run(); \ No newline at end of file +test.run(); diff --git a/app/src/pages/403.tsx b/app/src/pages/403.tsx index 50a0cf6..9a13f2d 100644 --- a/app/src/pages/403.tsx +++ b/app/src/pages/403.tsx @@ -1,18 +1,19 @@ const Page403 = () => { - return ( + return ( + // tailwindcss + // use class not use className +
+

403 Forbidden

+
+
+

+ You are not allowed to access this page. +

+

Please contact the administrator.

+
+
+
+ ); +}; - // tailwindcss - // use class not use className -
-

403 Forbidden

-
-
-

You are not allowed to access this page.

-

Please contact the administrator.

-
-
-
- ); -} - -export default Page403; \ No newline at end of file +export default Page403; diff --git a/app/src/pages/account/addAccount.test.tsx b/app/src/pages/account/addAccount.test.tsx index 22f2b69..6b349d0 100644 --- a/app/src/pages/account/addAccount.test.tsx +++ b/app/src/pages/account/addAccount.test.tsx @@ -1,41 +1,41 @@ import { suite } from "uvu"; import * as assert from "uvu/assert"; -import { render, fireEvent, waitFor } from '@solidjs/testing-library'; -import { isInDocument, hasStyle } from 'solid-dom-testing'; +import { render, fireEvent, waitFor } from "@solidjs/testing-library"; +import { isInDocument, hasStyle } from "solid-dom-testing"; -import AddAccount from './addAccount'; +import AddAccount from "./addAccount"; -const test = suite>(''); +const test = suite>(""); test.before.each((context) => { - const returnValue = render(() => ); - Object.getOwnPropertyNames(returnValue).forEach((name) => { - // @ts-expect-error - context[name] = returnValue[name]; - }); + const returnValue = render(() => ); + Object.getOwnPropertyNames(returnValue).forEach((name) => { + // @ts-expect-error + context[name] = returnValue[name]; + }); }); test.after.each(({ unmount }) => unmount()); -test('form render name input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('Name'))); +test("form render name input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("Name"))); }); -test('form render email input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('Email'))); +test("form render email input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("Email"))); }); -test('form render role select', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('Role'))); +test("form render role select", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("Role"))); }); -test('form render add account button', ({ getByText }) => { - assert.ok(isInDocument(getByText('Register Account'))); +test("form render add account button", ({ getByText }) => { + assert.ok(isInDocument(getByText("Register Account"))); }); -test('form render reset button', ({ getByText }) => { - assert.ok(isInDocument(getByText('Reset'))); +test("form render reset button", ({ getByText }) => { + assert.ok(isInDocument(getByText("Reset"))); }); -test.run(); \ No newline at end of file +test.run(); diff --git a/app/src/pages/account/addAccount.tsx b/app/src/pages/account/addAccount.tsx index fea3848..f88c309 100644 --- a/app/src/pages/account/addAccount.tsx +++ b/app/src/pages/account/addAccount.tsx @@ -1,61 +1,89 @@ import { Account } from "../../schema/account"; const AddAccount = () => { - // tailwindcssのクラス名 - // solidjsではclassではなくclassNameを使う + // tailwindcssのクラス名 + // solidjsではclassではなくclassNameを使う - // テナントアカウントの追加フォーム - // baseAccountObjのプロパティを入力するフォーム + // テナントアカウントの追加フォーム + // baseAccountObjのプロパティを入力するフォーム - // ログインユーザーのアカウント情報から取得する - // id uid - // email - // name - // createdAt - // updatedAt + // ログインユーザーのアカウント情報から取得する + // id uid + // email + // name + // createdAt + // updatedAt - // テナントアカウントの追加フォーム - return ( -
-
-
-
-

Add Account

-
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
- ); -} + // テナントアカウントの追加フォーム + return ( +
+
+
+
+

Add Account

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ ); +}; -export default AddAccount; \ No newline at end of file +export default AddAccount; diff --git a/app/src/pages/dashboard.test.tsx b/app/src/pages/dashboard.test.tsx index 1a5030e..dda541d 100644 --- a/app/src/pages/dashboard.test.tsx +++ b/app/src/pages/dashboard.test.tsx @@ -1,29 +1,29 @@ import { suite } from "uvu"; import * as assert from "uvu/assert"; -import { render, fireEvent, waitFor } from '@solidjs/testing-library'; -import { isInDocument, hasStyle } from 'solid-dom-testing'; +import { render, fireEvent, waitFor } from "@solidjs/testing-library"; +import { isInDocument, hasStyle } from "solid-dom-testing"; -import Dashboard from './dashboard'; +import Dashboard from "./dashboard"; -const test = suite>(''); +const test = suite>(""); test.before.each((context) => { - const returnValue = render(() => ); - Object.getOwnPropertyNames(returnValue).forEach((name) => { - // @ts-expect-error - context[name] = returnValue[name]; - }); + const returnValue = render(() => ); + Object.getOwnPropertyNames(returnValue).forEach((name) => { + // @ts-expect-error + context[name] = returnValue[name]; + }); }); test.after.each(({ unmount }) => unmount()); -test('page render dashboard title', ({ getByText }) => { - assert.ok(isInDocument(getByText('Dashboard'))); +test("page render dashboard title", ({ getByText }) => { + assert.ok(isInDocument(getByText("Dashboard"))); }); -test('page render dashboard message', ({ getByText }) => { - assert.ok(isInDocument(getByText('Welcome to your dashboard!'))); +test("page render dashboard message", ({ getByText }) => { + assert.ok(isInDocument(getByText("Welcome to your dashboard!"))); }); -test.run(); \ No newline at end of file +test.run(); diff --git a/app/src/pages/dashboard.tsx b/app/src/pages/dashboard.tsx index 98dc3d1..f46425f 100644 --- a/app/src/pages/dashboard.tsx +++ b/app/src/pages/dashboard.tsx @@ -1,67 +1,72 @@ - import { getCurrentUser } from "../service/auth"; import { QueryObj, getDocumentsWithQuery } from "../service/firestore"; import { DocumentData } from "firebase/firestore"; - const Dashboard = () => { - return ( -
-
-
-

Dashboard

-
-
- {/* pulldown menu select */} - - -
-
-
-
-
-
-
-
-

Welcome to your dashboard!

- - Register Tenant - -
-
-
-
-
- ); -} + return ( +
+
+
+

+ Dashboard +

+
+
+ {/* pulldown menu select */} + + +
+
+
+
+
+
+
+
+

+ Welcome to your dashboard! +

+ + Register Tenant + +
+
+
+
+
+ ); +}; export default Dashboard; async function getAccountInfo(): Promise { - const user = await getCurrentUser(); - const uid = user?.uid; - const collectionName = 'accounts'; - const queryObj: QueryObj = { - field: 'uid', - operator: '==', - value: uid - }; - const result = await getDocumentsWithQuery(collectionName, queryObj); - if (result instanceof Error) { - return null; - } - if (result.length === 0) { - return null; - } - if (result.length > 1) { - return null; - } - return result[0]; -} \ No newline at end of file + const user = await getCurrentUser(); + const uid = user?.uid; + const collectionName = "accounts"; + const queryObj: QueryObj = { + field: "uid", + operator: "==", + value: uid, + }; + const result = await getDocumentsWithQuery(collectionName, queryObj); + if (result instanceof Error) { + return null; + } + if (result.length === 0) { + return null; + } + if (result.length > 1) { + return null; + } + return result[0]; +} diff --git a/app/src/pages/login.test.tsx b/app/src/pages/login.test.tsx index 8f91392..d3fcdf0 100644 --- a/app/src/pages/login.test.tsx +++ b/app/src/pages/login.test.tsx @@ -1,33 +1,33 @@ import { suite } from "uvu"; import * as assert from "uvu/assert"; -import { render, fireEvent, waitFor } from '@solidjs/testing-library'; -import { isInDocument, hasStyle } from 'solid-dom-testing'; +import { render, fireEvent, waitFor } from "@solidjs/testing-library"; +import { isInDocument, hasStyle } from "solid-dom-testing"; -import Login from './login'; +import Login from "./login"; -const test = suite>(''); +const test = suite>(""); test.before.each((context) => { - const returnValue = render(() => ); - Object.getOwnPropertyNames(returnValue).forEach((name) => { - // @ts-expect-error - context[name] = returnValue[name]; - }); + const returnValue = render(() => ); + Object.getOwnPropertyNames(returnValue).forEach((name) => { + // @ts-expect-error + context[name] = returnValue[name]; + }); }); test.after.each(({ unmount }) => unmount()); -test('form render email input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('Email address'))); +test("form render email input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("Email address"))); }); -test('form render password input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('Password'))); +test("form render password input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("Password"))); }); -test('form render sign in button', ({ getByText }) => { - assert.ok(isInDocument(getByText('Sign in'))); +test("form render sign in button", ({ getByText }) => { + assert.ok(isInDocument(getByText("Sign in"))); }); -test.run(); \ No newline at end of file +test.run(); diff --git a/app/src/pages/login.tsx b/app/src/pages/login.tsx index 959f0d2..2a6c1e3 100644 --- a/app/src/pages/login.tsx +++ b/app/src/pages/login.tsx @@ -1,72 +1,113 @@ -import { createSignal } from 'solid-js'; -import { signIn } from '../service/auth'; +import { createSignal } from "solid-js"; +import { signIn } from "../service/auth"; const Login = () => { - const [email, setEmail] = createSignal(''); - const [password, setPassword] = createSignal(''); + const [email, setEmail] = createSignal(""); + const [password, setPassword] = createSignal(""); - const validateEmail = (email: string) => { - const re = /\S+@\S+\.\S+/; - return re.test(email); - } + const validateEmail = (email: string) => { + const re = /\S+@\S+\.\S+/; + return re.test(email); + }; - const validatePassword = (password: string) => { - return password.length >= 8; - } + const validatePassword = (password: string) => { + return password.length >= 8; + }; - const handleEmailChange = (e: Event) => { - const target = e.target as HTMLInputElement; - setEmail(target.value); - } + const handleEmailChange = (e: Event) => { + const target = e.target as HTMLInputElement; + setEmail(target.value); + }; - const handlePasswordChange = (e: Event) => { - const target = e.target as HTMLInputElement; - setPassword(target.value); - } + const handlePasswordChange = (e: Event) => { + const target = e.target as HTMLInputElement; + setPassword(target.value); + }; - const handleLogin = async () => { - const userCredential = await signIn(email(), password()); - if (userCredential instanceof Error) { - window.alert(userCredential.message); - } else { - window.location.href = '/dashboard'; - } - } + const handleLogin = async () => { + const userCredential = await signIn(email(), password()); + if (userCredential instanceof Error) { + window.alert(userCredential.message); + } else { + window.location.href = "/dashboard"; + } + }; + return ( +
+
+
+ +
+ handleEmailChange(e)} + /> +
+
- return ( -
- -
- -
- handleEmailChange(e)} /> -
-
+
+
+ + +
+
+ handlePasswordChange(e)} + /> +
+
-
-
- - -
-
- handlePasswordChange(e)} /> -
-
+
+ +
+ -
- -
- +

+ Not a member? + + Start a 90 day free trial + +

+
+ ); +}; -

- Not a member? - Start a 90 day free trial -

-
- ); -} - -export default Login; \ No newline at end of file +export default Login; diff --git a/app/src/pages/tenant/addTenant.test.tsx b/app/src/pages/tenant/addTenant.test.tsx index 709cc66..cce82eb 100644 --- a/app/src/pages/tenant/addTenant.test.tsx +++ b/app/src/pages/tenant/addTenant.test.tsx @@ -1,45 +1,45 @@ import { suite } from "uvu"; import * as assert from "uvu/assert"; -import { render, fireEvent, waitFor } from '@solidjs/testing-library'; -import { isInDocument, hasStyle } from 'solid-dom-testing'; +import { render, fireEvent, waitFor } from "@solidjs/testing-library"; +import { isInDocument, hasStyle } from "solid-dom-testing"; -import AddTenant from './addTenant'; +import AddTenant from "./addTenant"; -const test = suite>(''); +const test = suite>(""); test.before.each((context) => { - const returnValue = render(() => ); - Object.getOwnPropertyNames(returnValue).forEach((name) => { - // @ts-expect-error - context[name] = returnValue[name]; - }); + const returnValue = render(() => ); + Object.getOwnPropertyNames(returnValue).forEach((name) => { + // @ts-expect-error + context[name] = returnValue[name]; + }); }); test.after.each(({ unmount }) => unmount()); -test('form render name input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('Name'))); +test("form render name input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("Name"))); }); -test('form render city input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('City'))); +test("form render city input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("City"))); }); -test('form render area input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('Area'))); +test("form render area input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("Area"))); }); -test('form render members input', ({ getByLabelText }) => { - assert.ok(isInDocument(getByLabelText('How Many Members'))); +test("form render members input", ({ getByLabelText }) => { + assert.ok(isInDocument(getByLabelText("How Many Members"))); }); -test('form render add tenant button', ({ getByText }) => { - assert.ok(isInDocument(getByText('Register Tenant'))); +test("form render add tenant button", ({ getByText }) => { + assert.ok(isInDocument(getByText("Register Tenant"))); }); -test('form render reset button', ({ getByText }) => { - assert.ok(isInDocument(getByText('Reset'))); +test("form render reset button", ({ getByText }) => { + assert.ok(isInDocument(getByText("Reset"))); }); -test.run(); \ No newline at end of file +test.run(); diff --git a/app/src/pages/tenant/addTenant.tsx b/app/src/pages/tenant/addTenant.tsx index d87b12f..d4484c6 100644 --- a/app/src/pages/tenant/addTenant.tsx +++ b/app/src/pages/tenant/addTenant.tsx @@ -1,70 +1,112 @@ const AddTenant = () => { - return ( -
-
-
-

Add Tenant

-
-
- - -
-
-
-
-
-
-
-
-

Add Tenant

-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
-
- ); -} + return ( +
+
+
+

+ Add Tenant +

+
+
+ + +
+
+
+
+
+
+
+
+

Add Tenant

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+ ); +}; -export default AddTenant; \ No newline at end of file +export default AddTenant; diff --git a/app/src/schema/account.ts b/app/src/schema/account.ts index 137b953..8217e39 100644 --- a/app/src/schema/account.ts +++ b/app/src/schema/account.ts @@ -4,56 +4,56 @@ アカウントの種類によってスキーマを分ける */ -import { z } from 'zod'; +import { z } from "zod"; // アカウントの基本情報 // 全てのアカウントに共通する情報 const baseAccountObj = z.object({ - id: z.string(), - email: z.string(), - name: z.string(), - createdAt: z.string().optional(), - updatedAt: z.string().optional(), + id: z.string(), + email: z.string(), + name: z.string(), + createdAt: z.string().optional(), + updatedAt: z.string().optional(), }); // テナントアカウント // 地域地縁組織(自治会や町内会など)に紐づくアカウント const tenantAccountObj = baseAccountObj.extend({ - type: z.literal('tenant'), - tenantId: z.string(), - role: z.literal('admin'), + type: z.literal("tenant"), + tenantId: z.string(), + role: z.literal("admin"), }); // サポートアカウント // 自治体職員など中間支援組織に紐づくアカウント // プロダクトのサポート(CS)を担当するアカウント const supportAccountObj = baseAccountObj.extend({ - type: z.literal('support'), - role: z.literal('readOnly'), - invitedBy: z.string(), + type: z.literal("support"), + role: z.literal("readOnly"), + invitedBy: z.string(), }); // システム管理者アカウント // システムの管理者に紐づくアカウント const adminAccountObj = baseAccountObj.extend({ - type: z.literal('admin'), - role: z.literal('admin'), + type: z.literal("admin"), + role: z.literal("admin"), }); // 住民アカウント // 住民に紐づくアカウント const residentAccountObj = baseAccountObj.extend({ - type: z.literal('resident'), - role: z.literal('readOnly'), - tenantId: z.string(), + type: z.literal("resident"), + role: z.literal("readOnly"), + tenantId: z.string(), }); // アカウントのスキーマ const accountObj = z.union([ - tenantAccountObj, - supportAccountObj, - adminAccountObj, - residentAccountObj, + tenantAccountObj, + supportAccountObj, + adminAccountObj, + residentAccountObj, ]); -export type Account = z.infer; \ No newline at end of file +export type Account = z.infer; diff --git a/app/src/schema/tenant.ts b/app/src/schema/tenant.ts index c4047d2..f25e92c 100644 --- a/app/src/schema/tenant.ts +++ b/app/src/schema/tenant.ts @@ -2,21 +2,21 @@ 地域地縁組織(自治会や町内会など)を表すスキーマ プロダクト内では、地域地縁組織はテナントとして扱う */ -import { z } from 'zod'; +import { z } from "zod"; const tenantObj = z.object({ - id: z.string(), - name: z.string(), - city: z.string(), - area: z.string(), - members: z.number(), - productIds: z.array(z.string()).optional(), - createdBy: z.string().optional(), - createdAt: z.string().optional(), - updatedAt: z.string().optional(), - isConfirmed: z.boolean().optional(), - confirmedBy: z.string().optional(), - confirmedAt: z.string().optional(), + id: z.string(), + name: z.string(), + city: z.string(), + area: z.string(), + members: z.number(), + productIds: z.array(z.string()).optional(), + createdBy: z.string().optional(), + createdAt: z.string().optional(), + updatedAt: z.string().optional(), + isConfirmed: z.boolean().optional(), + confirmedBy: z.string().optional(), + confirmedAt: z.string().optional(), }); export type Tenant = z.infer; diff --git a/app/src/service/auth.ts b/app/src/service/auth.ts index a630a6c..5d17345 100644 --- a/app/src/service/auth.ts +++ b/app/src/service/auth.ts @@ -1,4 +1,11 @@ -import { getAuth, signInWithEmailAndPassword, signOut, onAuthStateChanged, UserCredential, User } from "firebase/auth"; +import { + getAuth, + signInWithEmailAndPassword, + signOut, + onAuthStateChanged, + UserCredential, + User, +} from "firebase/auth"; import { firebaseApp } from "./firebase"; /* @@ -9,30 +16,37 @@ import { firebaseApp } from "./firebase"; const auth = getAuth(firebaseApp); // Sign in with email and password -export async function signIn(email: string, password: string):Promise { - const userCredential = await signInWithEmailAndPassword(auth, email, password).catch((error) => { - return new Error("Email or password is incorrect"); - }); - return userCredential; +export async function signIn( + email: string, + password: string, +): Promise { + const userCredential = await signInWithEmailAndPassword( + auth, + email, + password, + ).catch((error) => { + return new Error("Email or password is incorrect"); + }); + return userCredential; } // check if user is signed in -export async function isVerifiedAccount():Promise { - return new Promise((resolve) => { - onAuthStateChanged(auth, (user) => { - if (user) { - resolve(true); - } else { - resolve(false); - } - }); - }); +export async function isVerifiedAccount(): Promise { + return new Promise((resolve) => { + onAuthStateChanged(auth, (user) => { + if (user) { + resolve(true); + } else { + resolve(false); + } + }); + }); } -export async function getCurrentUser():Promise { - return new Promise((resolve) => { - onAuthStateChanged(auth, (user) => { - resolve(user); - }); - }); +export async function getCurrentUser(): Promise { + return new Promise((resolve) => { + onAuthStateChanged(auth, (user) => { + resolve(user); + }); + }); } diff --git a/app/src/service/firebase.ts b/app/src/service/firebase.ts index 590c903..9c4f5e7 100644 --- a/app/src/service/firebase.ts +++ b/app/src/service/firebase.ts @@ -1,14 +1,14 @@ -import { initializeApp } from 'firebase/app'; +import { initializeApp } from "firebase/app"; // replace with your own firebase config object const devfirebaseConfig = { - apiKey: "AIzaSyAFUVOZFSMY3ry4-OKvXrqrb-MnhqPaK1A", - authDomain: "autonomy-tegata-dev.firebaseapp.com", - projectId: "autonomy-tegata-dev", - storageBucket: "autonomy-tegata-dev.appspot.com", - messagingSenderId: "860829179517", - appId: "1:860829179517:web:0c3947200d448056f85b14", - measurementId: "G-813EBFYV1Q" -} + apiKey: "AIzaSyAFUVOZFSMY3ry4-OKvXrqrb-MnhqPaK1A", + authDomain: "autonomy-tegata-dev.firebaseapp.com", + projectId: "autonomy-tegata-dev", + storageBucket: "autonomy-tegata-dev.appspot.com", + messagingSenderId: "860829179517", + appId: "1:860829179517:web:0c3947200d448056f85b14", + measurementId: "G-813EBFYV1Q", +}; -export const firebaseApp = initializeApp(devfirebaseConfig); \ No newline at end of file +export const firebaseApp = initializeApp(devfirebaseConfig); diff --git a/app/src/service/firestore.test.ts b/app/src/service/firestore.test.ts index 9a3a625..50d210a 100644 --- a/app/src/service/firestore.test.ts +++ b/app/src/service/firestore.test.ts @@ -1,7 +1,10 @@ -import { test} from "uvu"; +import { test } from "uvu"; import * as assert from "uvu/assert"; import fs from "node:fs"; -import { initializeTestEnvironment, RulesTestEnvironment } from '@firebase/rules-unit-testing'; +import { + initializeTestEnvironment, + RulesTestEnvironment, +} from "@firebase/rules-unit-testing"; import { getAllDocumentsWithCollectionName } from "./firestore"; import type { Firestore } from "firebase/firestore"; @@ -10,34 +13,36 @@ import type { Firestore } from "firebase/firestore"; // before running the tests let testEnv: RulesTestEnvironment | null = null; -test.before.each(async() => { - testEnv = await initializeTestEnvironment({ - projectId: "test-project", - firestore: { - rules: fs.readFileSync("/home/yamashita/tegata/firestore.rules", "utf8"), - host: "localhost", - port: 8080 - } - }); - }); - -test.after.each(async() => { - await testEnv?.cleanup(); +test.before.each(async () => { + testEnv = await initializeTestEnvironment({ + projectId: "test-project", + firestore: { + rules: fs.readFileSync("/home/yamashita/tegata/firestore.rules", "utf8"), + host: "localhost", + port: 8080, + }, + }); }); -test("getAllDocumentsWithCollectionName", async() => { - const user = testEnv?.authenticatedContext("test-user"); - const firestore = user?.firestore() as unknown as Firestore; - const collectionName = "users"; - if (!firestore) { - throw new Error("Firestore is not initialized"); - } - const result = await getAllDocumentsWithCollectionName(firestore, collectionName); - if (result instanceof Error) { - throw result; - } - assert.is(result.length, 0); +test.after.each(async () => { + await testEnv?.cleanup(); }); +test("getAllDocumentsWithCollectionName", async () => { + const user = testEnv?.authenticatedContext("test-user"); + const firestore = user?.firestore() as unknown as Firestore; + const collectionName = "users"; + if (!firestore) { + throw new Error("Firestore is not initialized"); + } + const result = await getAllDocumentsWithCollectionName( + firestore, + collectionName, + ); + if (result instanceof Error) { + throw result; + } + assert.is(result.length, 0); +}); test.run(); diff --git a/app/src/service/firestore.ts b/app/src/service/firestore.ts index fb04977..efd29fa 100644 --- a/app/src/service/firestore.ts +++ b/app/src/service/firestore.ts @@ -1,5 +1,23 @@ -import { firebaseApp } from './firebase'; -import { CollectionReference, DocumentData, Firestore, query, Query, addDoc, collection, collectionGroup, deleteDoc, doc, getDoc, getFirestore, setDoc, updateDoc, getDocs, where, QuerySnapshot } from 'firebase/firestore'; +import { firebaseApp } from "./firebase"; +import { + CollectionReference, + DocumentData, + Firestore, + query, + Query, + addDoc, + collection, + collectionGroup, + deleteDoc, + doc, + getDoc, + getFirestore, + setDoc, + updateDoc, + getDocs, + where, + QuerySnapshot, +} from "firebase/firestore"; export const firestore: Firestore = getFirestore(firebaseApp); @@ -8,90 +26,131 @@ firebaseはcollectionとdocumentの概念を持っている https://firebase.google.com/docs/reference/js/firestore_ */ -function getCollection(db: Firestore, collectionName: string): CollectionReference { - return collection(db, collectionName); +function getCollection( + db: Firestore, + collectionName: string, +): CollectionReference { + return collection(db, collectionName); } -export async function getAllDocumentsWithCollectionName(db: Firestore, collectionName: string):Promise{ - const collectionRef = getCollection(db, collectionName); - try { - const documents: DocumentData[] = []; - const querySnapshot = await getDocs(collectionRef); - for (const doc of querySnapshot.docs) { - documents.push(doc.data()); - } - return documents; - } catch (error) { - return new Error('Error getting documents: ' + error); - } - } +export async function getAllDocumentsWithCollectionName( + db: Firestore, + collectionName: string, +): Promise { + const collectionRef = getCollection(db, collectionName); + try { + const documents: DocumentData[] = []; + const querySnapshot = await getDocs(collectionRef); + for (const doc of querySnapshot.docs) { + documents.push(doc.data()); + } + return documents; + } catch (error) { + return new Error("Error getting documents: " + error); + } +} // 新しいドキュメントを任意のIDで追加する -export async function addNewDocument(db: Firestore, collectionName: string, data: DocumentData):Promise { - const collectionRef = getCollection(db, collectionName); - return setDoc(doc(collectionRef, data.id), data).then(() => { - return null; - }).catch((error) => { - return new Error('Error adding document: ' + error); - }); +export async function addNewDocument( + db: Firestore, + collectionName: string, + data: DocumentData, +): Promise { + const collectionRef = getCollection(db, collectionName); + return setDoc(doc(collectionRef, data.id), data) + .then(() => { + return null; + }) + .catch((error) => { + return new Error("Error adding document: " + error); + }); } // autoIdを使って新しいドキュメントを追加する -export async function addNewDocumentWithAutoId(db: Firestore, collectionName: string, data: DocumentData):Promise { - const collectionRef = getCollection(db, collectionName); - return addDoc(collectionRef, data).then(() => { - return null; - }).catch((error) => { - return new Error('Error adding document: ' + error); - }); +export async function addNewDocumentWithAutoId( + db: Firestore, + collectionName: string, + data: DocumentData, +): Promise { + const collectionRef = getCollection(db, collectionName); + return addDoc(collectionRef, data) + .then(() => { + return null; + }) + .catch((error) => { + return new Error("Error adding document: " + error); + }); } -export async function getDocumentById(db: Firestore, collectionName: string, documentId: string):Promise { - const documentRef = doc(db, collectionName, documentId); - const documentSnapshot = await getDoc(documentRef); - if (documentSnapshot.exists()) { - return documentSnapshot.data(); - } else { - return null; - } +export async function getDocumentById( + db: Firestore, + collectionName: string, + documentId: string, +): Promise { + const documentRef = doc(db, collectionName, documentId); + const documentSnapshot = await getDoc(documentRef); + if (documentSnapshot.exists()) { + return documentSnapshot.data(); + } else { + return null; + } } -export async function updateDocument(db: Firestore, collectionName: string, documentId: string, data: DocumentData):Promise { - const documentRef = doc(db, collectionName, documentId); - return updateDoc(documentRef, data).then(() => { - return null; - }).catch((error) => { - return new Error('Error updating document: ' + error); - }); +export async function updateDocument( + db: Firestore, + collectionName: string, + documentId: string, + data: DocumentData, +): Promise { + const documentRef = doc(db, collectionName, documentId); + return updateDoc(documentRef, data) + .then(() => { + return null; + }) + .catch((error) => { + return new Error("Error updating document: " + error); + }); } -export async function deleteDocument(db: Firestore, collectionName: string, documentId: string):Promise { - const documentRef = doc(db, collectionName, documentId); - return deleteDoc(documentRef).then(() => { - return null; - }).catch((error) => { - return new Error('Error deleting document: ' + error); - }); +export async function deleteDocument( + db: Firestore, + collectionName: string, + documentId: string, +): Promise { + const documentRef = doc(db, collectionName, documentId); + return deleteDoc(documentRef) + .then(() => { + return null; + }) + .catch((error) => { + return new Error("Error deleting document: " + error); + }); } export type QueryObj = { - field: string, - operator: "==", - value: unknown, -} + field: string; + operator: "=="; + value: unknown; +}; -export async function getDocumentsWithQuery(db: Firestore, collectionName: string, queryObj: QueryObj):Promise { - const collectionRef = collection(db, collectionName); - const q = query(collectionRef, where(queryObj.field, queryObj.operator, queryObj.value)); - try { - const querySnapshot = await getDocs(q); - const documents: DocumentData[] = []; - for (const doc of querySnapshot.docs) { - documents.push(doc.data()); - } - return documents; - } - catch (error) { - return new Error(`Error getting documents: ${error}`); - } +export async function getDocumentsWithQuery( + db: Firestore, + collectionName: string, + queryObj: QueryObj, +): Promise { + const collectionRef = collection(db, collectionName); + const q = query( + collectionRef, + where(queryObj.field, queryObj.operator, queryObj.value), + ); + try { + const querySnapshot = await getDocs(q); + const documents: DocumentData[] = []; + for (const doc of querySnapshot.docs) { + documents.push(doc.data()); + } + return documents; + } catch (error) { + return new Error(`Error getting documents: ${error}`); + } }