Next.js の独習<その2>

👆 Next.JS のチュートリアルを1つ終えたので、自分のサイトを作ってみる

とりあえず Windows 11 からターミナルを開き、WSLを使って Ubuntu を起動。

PS C:\Users\muzud> wsl --list
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu (既定)
PS C:\Users\muzud> wsl -d Ubuntu

とりあえず、 `/home/ユーザー名/nextjs_practice` というディレクトリーを掘っておく

muzudho@Takahashi-PC:~/nextjs_practice$ cd ~/nextjs_practice
muzudho@Takahashi-PC:~/nextjs_practice$

👆 ディレクトリーを移動しておく

これから作るWebサイトの名前は[ならべる]にしようかと思う。
プロジェクトの名前は `nextjs-naraberu` にしようかと思う。
プロジェクトのスターターキットのようなものを Web サイトの Vercel からダウンロードしようと思う。

👇 以下のコマンドを打鍵する

npx create-next-app@latest nextjs-naraberu --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example" --use-pnpm

👇 作られたディレクトリーへ移動する

muzudho@Takahashi-PC:~/nextjs_practice$ cd nextjs-naraberu
muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$

👇 そのディレクトリーを VSCode で開こうと思う。 VSCode は Ubuntu の中ではなく、WSL の外側のホストの Windows 11 で開かれる

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ code .

ここで、データベースのデータを用意するために Prisma や Drizzle の使い方を知っておいたほうがよいそうだが、知ってないので無視する

開発サーバーをインストールして走らせたい。
👇 以下のコマンドを叩く

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ pnpm i
muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ pnpm dev

👆 これで Ubuntu でサーバーが走る。
ポートの 3000 番をたまたま使ってしまっていたため、代わりに 3001 番でサーバーが立った。

http://localhost:3001 にアクセスする

エグザンプルには CSS ファイルが効いてないとか、いろいろ演習問題が残っているのだった

チャプター2

👇 `/app/layout.tsx` を編集する

※1行目に追加
// HTML に CSS が適用される。 <head> 要素に CSSファイルへのリンクが追加される?
import '@/app/ui/global.css';

この '@/app/ui/global.css' は、 テイルワインド という仕組みらしい。よくわからない。
テイルワインドというのは HTML タグに `className` 属性を付けてスタイルの適用をする独自の方法だと思う

👇 `/app/page.tsx` を編集する

<div
  className="relative w-0 h-0 border-l-[15px] border-r-[15px] border-b-[26px] border-l-transparent border-r-transparent border-b-black"
/>

👆 `<p>` タグが1個あるから、その上に上記の `<div>` タグを挿入する。
微妙に縦位置がずれただけ。
Web ブラウザーで `[Ctrl] + [F5]` を打鍵するとスーパーリロードされて、黒塗りの三角形が表示された。よくわからない

テイルワインドをHTMLに埋め込まず CSS ファイルに外出しする方法などの演習があるので復習しておく

👇 `/app/ui/home.module.css` ファイルを新規作成して、以下のコードを貼り付ける

.shape {
  height: 0;
  width: 0;
  border-bottom: 30px solid black;
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
}

👇 `/app/page.tsx` ファイルを編集する

※追加
import styles from '@/app/ui/home.module.css';

※変更前
          <div
            className="relative w-0 h-0 border-l-[15px] border-r-[15px] border-b-[26px] border-l-transparent border-r-transparent border-b-black"
          />

※変更後
          <div
            className="{styles.shape}"
          />

clsx ライブラリーの使い方の復習

`/app/ui/invoices/status.tsx` ファイルの中で clsx が既に使われている。それを見て使い方を思い出しておく

チャプター3

👆 google フォントを使う例を復習する

👇 `/app/ui/fonts.ts` ファイルを新規作成して、以下のコードを貼り付ける

// グーグル社の Inter と Lusitana という名前のフォントを取り出す
import { Inter, Lusitana } from 'next/font/google';

// ラテンというサブセットをインスタンス化する
export const inter = Inter({ subsets: ['latin'] });
export const lusitana = Lusitana({
    subsets: ['latin'],
    weight: ['400', '700'],
});

👆 Lusitana フォントは太さが `400`, `700` しかないようで、もうひと手間かけている

👇 次に `/app/layout.tsx` ファイルで inter を利用する

※追加
// Inter フォントと Lusitana フォントのインスタンス
import { inter, lusitana } from '@/app/ui/fonts';

※変更前
<body>{children}</body>

※変更後
<body className={`${inter.className} antialiased`}>{children}</body>

👇 `/app/page.tsx` を編集する

※追加
import { lusitana } from '@/app/ui/fonts';

※変更前
          <p className={`text-xl text-gray-800 md:text-3xl md:leading-normal`}>

※変更後
          <p className={`text-xl text-gray-800 md:text-3xl md:leading-normal ${lusitana.className} antialiased`}>

ここで フォントを変えることはできた

デスクトップ用PC画面と、モバイル画面で、表示する画像を変更する

👇 `/app/page.tsx` を編集する

※追加
import Image from 'next/image';

          {/* Add Hero Images Here */}
          <Image
            src="/hero-desktop.png"
            width={1000}
            height={760}
            className="hidden md:block"
            alt="Screenshots of the dashboard project showing desktop version"
          />
          <Image
            src="/hero-mobile.png"
            width={560}
            height={620}
            className="block md:hidden"
            alt="Screenshot of the dashboard project showing mobile version"
          />

👆 デスクトップPCと、モバイルで画像が切り替わるという仕組みだ

Git Hub のリポジトリを用意する

ここで、 Git Hub のリポジトリを用意していないことを思い出した。
あとのチャプターでやることだが、便利なので先にやっておく

👆 VSCode のツールバーに Git の印(Source Control)のボタンがあるのでクリック。
続けて `Initialize Repository` ボタンをクリック。
`nextjs-narabu` ディレクトリーへのパスが出てくるので、そのままクリック。

`Unsafe` という文字が見えるが、今はエグザンプルで練習しているだけで個人情報をアップロードすることもないだろうから そのまま `Manage Unsafe Repositiories` ボタンをクリック。

`nextjs-narabu` ディレクトリーをもう1回選ぶ。
すると ローカルのリポジトリにコミットしたり、
クラウドへプッシュ(アップロード)するファイルの一覧が出てくる

ツリー表示の `Changes` を右クリックして `Stage All Changes` をクリック。
テキストボックスに `復習` とか適当に文字を入れて `Commit` ボタンを作る

これで ローカルPCのリポジトリにコミット完了。
これをクラウドに上げて公開するために `Publish Branch` ボタンをクリック。
続けて `Publish to GitHub public repository` をクリック。これでOk

Vercel にもリポジトリを作って、Git Hub から自動デプロイされるようにしておく

👆 やり方を忘れたので、チャプター6を再確認する

Vercel のアカウントで Webサイトを開き、 `Import Git Repository` と書かれたページを開いたが、 `nextjs-naraberu` リポジトリーが見えない。

よくわからないので `Configure GitHub App` ボタンを押してみる。
二要素認証の画面に飛んだので 認証を進める

リポジトリーの選択で `nextjs-naraberu` を追加する。
これで Vercel の Webサイトから `nextjs-naraberu` リポジトリーを選択できるようになった。
`nextjs-naraberu` リポジトリーを選択して `Import` ボタンをクリック

`Configure Project` と書かれたページが出てくる。
プロジェクト名の欄に `nextjs-naraberu` と入力されているのを確認して
`Deploy` ボタンをクリックする

これで Vercel Webサイトに、GitHub の `nextjs-naraberu` リポジトリーが自動デプロイされる仕組みが整った

https://nextjs-naraberu-bhcg4dd0v-muzudhos-projects.vercel.app/

👆 これで、 naraberu の Webサイトが公開されているはず

Vercel で公開した Web サイトのドメインを変更したい

👆 `http://~.vercel.app/` というドメインを、自分が所有しているドメインに変更したい

👇 以下のような CNAMEレコードを登録すればいいらしい

Type CNAME
Name sample
Value cname.vercel-dns.com

👆 CNAME が何なのかわからないので調べる

CNAME の設定では、レンタルサーバーの方の設定を、変更するのらしい。
レンタルサーバー側で CNAME を設定できない場合は、 Value-Domain や さくらVPS などの方で設定できるらしい

cname naraberu nextjs-naraberu-bhcg4dd0v-muzudhos-projects.vercel.app.

👆 例えば こんな感じで設定すればいいのか? 最後にピリオドが付いてる?

http://naraberu.warabenture.com/

👆 これで 自分のドメインから naraberu Webサーバーへアクセスできるようになったが、何やらエラーが出ているようだ

404: NOT_FOUND
Code: DEPLOYMENT_NOT_FOUND
ID: kix1::t8jqn-1723353685343-b759d7d8e1b0

This deployment cannot be found. For more information and troubleshooting, see our documentation.

👆 Vercel 側の `.env` ファイルが未設定なのだろうか、これはあとで見てみる

Vercel に PostgreSQL サーバーを立てる

👆 とりあえず Vercel のダッシュボードを開けてみる

`nextjs-naraberu` のプロジェクトを開く

メインメニューの `Storage` を開く

ドロップダウンリストから `Postgres` を選択して `CreateDatabase` をクリック

`Browse Storage` というポップアップが出てくるから `Postgres` をクリック。続けて `Continue` ボタンをクリック

なにか警告が出てくる

Create Postgres Database

You have reached the limit of Postgres Databases on this plan.

Personal Accounts are limited to 1 active Postgres Database at a time.
To create additional Postgres Databases, upgrade your plan to Pro or remove an existing Postgres Database.

Learn more

[Go Back]    [Upgrade your plan]

👆 どうも、 Postgres サーバーはもう立ててるから、もっと Postgres サーバーを立てたかったらプランをアップデートしろということらしい。なんてこった

調べていくと 月20ドルの pro プランへの誘いだった。
日本円で毎月3000円払ってデプロイを楽するのと、
毎月3000円を払わずに自力でデプロイするのと、どっちがいいだろうか?
年間3万6千円

さくらインターネットで さくらVPSを年間いくらかで借りて Ubuntu を入れて 自力でデプロイしたらどうだろうか? これはあとで考えよう

Vercel は使わない方向で復習

VSCode に戻る

👇 `.env.example` ファイルを開く

# Copy from .env.local on the Vercel dashboard
# https://nextjs.org/learn/dashboard-app/setting-up-your-database#create-a-postgres-database
POSTGRES_URL=
POSTGRES_PRISMA_URL=
POSTGRES_URL_NON_POOLING=
POSTGRES_USER=
POSTGRES_HOST=
POSTGRES_PASSWORD=
POSTGRES_DATABASE=

# `openssl rand -base64 32`
AUTH_SECRET=
AUTH_URL=http://localhost:3000/api/auth

Vercel に Postgres をインストールしたわけではないので、
このファイルを設定する方法が分からない。
postgres をローカルの Ubuntu にインストールする方法を調べるか?

(独自調べ)postgres を Ubuntu にインストールする

👆 root のパスワードを設定しておくこと。
root にパスワードがかかってるかどうかは

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-dashboard$ sudo su - 
[sudo] password for muzudho:

とでも打てば分かる。 `[Ctrl] + [C]` で抜ける

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-dashboard$ sudo apt update

👆 サーバーのローカル・パッケージ・インデックスを更新する

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-dashboard$ sudo apt install postgresql postgresql-contrib

👆 `postgresql` と `postgresql-contrib` をインストールする。
これで postgres のインストールは Ok

postgres の起動

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-dashboard$ sudo service postgresql start

👆 打鍵しても、見た目は、起動したかどうか分かんない

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-dashboard$ sudo service postgresql status

👆 起動しているかどうか確認する

postgres のための設定

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-dashboard$ sudo -u postgres psql
[sudo] password for muzudho:
could not change directory to "/home/muzudho/nextjs_practice/nextjs-dashboard": Permission denied
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=#

👆 postgres にデフォルトで追加されている postgres ユーザーでログインしようとしたら、パーミッション設定でエラー。 Linux に慣れてないとつらい。 `[Ctrl] + [Z]` で抜ける

👆 エラーを調べてみる

👆 エラーメッセージは出ているが、無視していいのか?

ubuntu のユーザーに、データベースにアクセスする権限を与える

postgres=# CREATE ROLE muzudho LOGIN CREATEDB;
CREATE ROLE

👆 自分は muzudho ユーザーなんで、とりあえず muzudho というロールを作り、 muzudho ロールに LOGIN(ログインできる権限)と、 CREATEDB(データベースを作れる権限)を付ける

※注意:ここは、新規ユーザーの muzudho を作るのではなく、デフォルト・ユーザーの postgres に LOGIN 権限を与えろ、ということだったのかもしれない

\q

👆 ポストグレスを終了するコマンド

psql -d postgres

👆 postgres ユーザーでポストグレスにログイン

これでポストグレスは使える状態になった。Ok

しかし このあと どうすればいいか分からない。
prisma でも覚えるか?

Prisma

👆 練習してきた

👇 Prisma CLI のインストール

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ npm install prisma --save-dev

👆 結構時間がかかる。なんでだろう

👇 Prisma CLI の初期設定(データベースに Postgres を使う場合)

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ npx prisma init --datasource-provider postgresql

👇 ディレクトリーの中に `prisma` フォルダーができている

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ ls
README.md  next-env.d.ts    node_modules  pnpm-lock.yaml     prisma  tailwind.config.ts
app        next.config.mjs  package.json  postcss.config.js  public  tsconfig.json

👇 VSCode で `/nextjs-naraberu/prisma/schema.prisma` ファイルの中身を見てみる

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

👆 このファイルに データベース・スキーマを記述していく

👇 Next.JS の Dashboard チュートリアルには `/app/lib/definitions.ts` ファイルの中に Java Script でテーブル定義がある

// This file contains type definitions for your data.
// It describes the shape of the data, and what data type each property should accept.
// For simplicity of teaching, we're manually defining these types.
// However, these types are generated automatically if you're using an ORM such as Prisma.
export type User = {
  id: string;
  name: string;
  email: string;
  password: string;
};

export type Customer = {
  id: string;
  name: string;
  email: string;
  image_url: string;
};

export type Invoice = {
  id: string;
  customer_id: string;
  amount: number;
  date: string;
  // In TypeScript, this is called a string union type.
  // It means that the "status" property can only be one of the two strings: 'pending' or 'paid'.
  status: 'pending' | 'paid';
};

export type Revenue = {
  month: string;
  revenue: number;
};

export type LatestInvoice = {
  id: string;
  name: string;
  image_url: string;
  email: string;
  amount: string;
};

// The database returns a number for amount, but we later format it to a string with the formatCurrency function
export type LatestInvoiceRaw = Omit<LatestInvoice, 'amount'> & {
  amount: number;
};

export type InvoicesTable = {
  id: string;
  customer_id: string;
  name: string;
  email: string;
  image_url: string;
  date: string;
  amount: number;
  status: 'pending' | 'paid';
};

export type CustomersTableType = {
  id: string;
  name: string;
  email: string;
  image_url: string;
  total_invoices: number;
  total_pending: number;
  total_paid: number;
};

export type FormattedCustomersTable = {
  id: string;
  name: string;
  email: string;
  image_url: string;
  total_invoices: number;
  total_pending: string;
  total_paid: string;
};

export type CustomerField = {
  id: string;
  name: string;
};

export type InvoiceForm = {
  id: string;
  customer_id: string;
  amount: number;
  status: 'pending' | 'paid';
};

👆👇 これを元に `/nextjs-naraberu/prisma/schema.prisma` ファイルにテーブル定義を追加する練習をする

// この Web サイトの利用者
model User {
  id       String     @unique // ふつう Int 型にする。 @id @default(autoincrement())
  name     String
  email    String
  password String
}

// 消費者
model Customer {
  id        String     @unique // ふつう Int 型にする。 @id @default(autoincrement())
  name      String
  email     String
  image_url String
}

// 支払い状況 "pending" or "paid"
enum CustomerStatus {
  PENDING
  PAID
}

// 請求書
model Invoice {
  id            String     @unique // ふつう Int 型にする。 @id @default(autoincrement())
  customer_id   String
  amount        Int       // 金額
  data          String
  Status        CustomerStatus
}

// 収益
model Revenue {
  id        Int     @id @default(autoincrement())   // ユニークな列が1つは必要?
  month     String
  revenue   Int
}

// 最新の請求書
model LatestInvoice {
  id        String     @unique // ふつう Int 型にする。 @id @default(autoincrement())
  name      String
  image_url String
  email     String
  amount    String
}

// FIXME この行をどう変換すればいいか分からない
// // The database returns a number for amount, but we later format it to a string with the formatCurrency function
// export type LatestInvoiceRaw = Omit<LatestInvoice, 'amount'> & {
//   amount: number;
// };

model InvoicesTable {
  id            String     @unique // ふつう Int 型にする。 @id @default(autoincrement())
  customer_id   String
  name          String
  email         String
  image_url     String
  data          String
  amount        String
  Status        CustomerStatus
}

👆 これでいいのかどうか分からないが とりあえず書いた

👇 以下のコマンドを打鍵する

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "mydb", schema "public" at "localhost:5432"

Error: P1000: Authentication failed against database server at `localhost`, the provided database credentials for `johndoe` are not valid.

Please make sure to provide valid database credentials for the database server at `localhost`.

👆 何かエラーが出た

`johndoe` って誰だ? 検索すると …

👇 `.env` ファイル

# This was inserted by `prisma init`:
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema

# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings

DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"

👆 行が増えている? これは データベース接続文字列 では?

👇 データベース接続文字列を下記のように変更

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"

👇 以下のコマンドを打鍵する

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "mydb", schema "public" at "localhost:5432"

Error: P1000: Authentication failed against database server at `localhost`, the provided database credentials for `postgres` are not valid.

Please make sure to provide valid database credentials for the database server at `localhost`.

👆 postgres ユーザーには データベースの資格情報が足りない?
muzudho ユーザーはパスワードが分からない。
どのユーザーで接続する?

postgres が起動していないのでは?

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ sudo service postgresql status
[sudo] password for muzudho:
● postgresql.service - PostgreSQL RDBMS
     Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sun 2024-08-11 16:48:42 JST; 20h ago
    Process: 433009 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
   Main PID: 433009 (code=exited, status=0/SUCCESS)

Aug 11 16:48:42 Takahashi-PC systemd[1]: Starting PostgreSQL RDBMS...
Aug 11 16:48:42 Takahashi-PC systemd[1]: Finished PostgreSQL RDBMS.

👆 起動はしている? このあと 結果は変わらず

👇 ポストグレスにログインできるか試してみる

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=>

👆 ログインできてる。パスワードも無しで?

`-d` はデータベース名を指定するオプションだそうだ。
`[Ctrl] + [Z]` で終了

じゃあ ユーザー名やパスワードはどうなってる?

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -U postgres
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  Peer authentication failed for user "postgres"

👆 `postgres` というユーザーは未登録?

👆 ポストグレスには ユーザーという概念がなく、代わりに ロールという概念がある?

👇 もう一回 登録しているロールを確認

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=> \du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 muzudho   | Create DB                                                  | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=>

👆 `muzudho` も `postgres` もロールとして作ってある

👆 パスワードは省略できるのか?
パスワードを省略してもエラー

👆 エラーメッセージの `P1000` を調べてみる

Error codes
Common
P1000
"Authentication failed against database server at {database_host}, the provided database credentials for {database_user} are not valid. Please make sure to provide valid database credentials for the database server at {database_host}."

👆 わからない

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=>
postgres=> SELECT usename AS role_name,
  CASE
     WHEN usesuper AND usecreatedb THEN
           CAST('superuser, create database' AS pg_catalog.text)
     WHEN usesuper THEN
            CAST('superuser' AS pg_catalog.text)
     WHEN usecreatedb THEN
            CAST('create database' AS pg_catalog.text)
     ELSE
            CAST('' AS pg_catalog.text)
  END role_attributes
FROM pg_catalog.pg_user
ORDER BY role_name desc;
 role_name |      role_attributes
-----------+----------------------------
 postgres  | superuser, create database
 muzudho   | create database
(2 rows)

postgres=>

👆 知ってる人に聞いてみると、ロールは、デフォルトでログインできないらしい。

👆 `CREATE USER` コマンドはデフォルトでログイン権限を付けるそうだ

CREATE ROLE <user> WITH LOGIN PASSWORD 'password';
または
CREATE USER <user> WITH PASSWORD 'password';

👆 ロールを作るときに ログイン権限とパスワードを一緒に付ける必要があったそうだ。
既存のロールに対して `CREATE ROLE` コマンドを使って ログイン権限とパスワードを追加してみる

postgres=> CREATE ROLE muzudho WITH LOGIN PASSWORD 'password'
postgres=>

`[Ctrl] + [Z]` で抜ける

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=> SELECT usename AS role_name,
  CASE
     WHEN usesuper AND usecreatedb THEN
           CAST('superuser, create database' AS pg_catalog.text)
     WHEN usesuper THEN
            CAST('superuser' AS pg_catalog.text)
     WHEN usecreatedb THEN
            CAST('create database' AS pg_catalog.text)
     ELSE
            CAST('' AS pg_catalog.text)
  END role_attributes
FROM pg_catalog.pg_user
ORDER BY role_name desc;
 role_name |      role_attributes
-----------+----------------------------
 postgres  | superuser, create database
 muzudho   | create database
(2 rows)

postgres=>

👆 muzudho にログイン権限付いてない

postgres=> CREATE ROLE muzudho WITH LOGIN PASSWORD 'password';

👆 末尾にセミコロンを付けてみる

ERROR:  permission denied to create role

👆 ロールを付ける権限がない?

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -U postgres
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  Peer authentication failed for user "postgres"

👆 postgres ユーザーもログインできない

パスワードなしで入れるオプションがあるらしい。 `pg_hba.conf` というファイルがどこかにある?

`/usr/local/pgsql/data/pg_hba.conf` というファイルがある?

`/usr/local/pgsql` ディレクトリーがない

知ってる人に聞いてみると、もし `*.tar.gz` を公式からダウンロードしてきて展開してソースから prefix なしで configure した場合は `/usr/local` の下にディレクトリーがあるかもしれないが、 `sudo apt` などのパッケージマネージャーを使った場合はどこにあるかは ディストリビューションによるらしい

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=> SHOW hba_file;
ERROR:  must be superuser or a member of pg_read_all_settings to examine "hba_file"
postgres=>

👆 スーパーユーザーではないため、場所が見れないようだ

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -t -P format=unaligned -c 'show hba_file';
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  database "muzudho" does not exist

👆 これもダメ

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ ps aux  | grep 'postgres *-D'
postgres  432991  0.0  0.3 215760 30232 ?        Ss   Aug11   0:02 /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf

👆 `config_file=/etc/postgresql/14/main/postgresql.conf` か?

muzudho@Takahashi-PC:/etc/postgresql/14/main$ ls
conf.d  environment  pg_ctl.conf  pg_hba.conf  pg_ident.conf  postgresql.conf  start.conf

👆 `pg_hba.conf` ファイルがあった

muzudho@Takahashi-PC:/etc/postgresql/14/main$ code .
muzudho@Takahashi-PC:/etc/postgresql/14/main$ ll
total 68
drwxr-xr-x 3 postgres postgres  4096 Aug 11 16:48 ./
drwxr-xr-x 3 postgres postgres  4096 Aug 11 16:48 ../
drwxr-xr-x 2 postgres postgres  4096 Aug 11 16:48 conf.d/
-rw-r--r-- 1 postgres postgres   315 Aug 11 16:48 environment
-rw-r--r-- 1 postgres postgres   143 Aug 11 16:48 pg_ctl.conf
-rw-r----- 1 postgres postgres  5002 Aug 11 16:48 pg_hba.conf
-rw-r----- 1 postgres postgres  1636 Aug 11 16:48 pg_ident.conf
-rw-r--r-- 1 postgres postgres 29030 Aug 11 16:48 postgresql.conf
-rw-r--r-- 1 postgres postgres   317 Aug 11 16:48 start.conf
muzudho@Takahashi-PC:/etc/postgresql/14/main$ vi pg_hba.conf

[9]+  Stopped                 vi pg_hba.conf
muzudho@Takahashi-PC:/etc/postgresql/14/main$

👆 パーミッションで `pg_hba.conf` を開くことを拒否されてしまう

muzudho@Takahashi-PC:/etc/postgresql/14/main$ sudo vi pg_hba.conf

👆 `sudo` を付けるとファイルを開けることができた

👇 `/etc/postgresql/14/main/pg_hba.conf` ファイル

# DO NOT DISABLE!
# If you change this first entry you will need to make sure that the
# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            scram-sha-256
# IPv6 local connections:
host    all             all             ::1/128                 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            scram-sha-256
host    replication     all             ::1/128                 scram-sha-256

👆 これをどうすれば postgres ユーザーでデータベースにログインするときにパスワードを入力しなくていいようにできるだろうか?

わからん

👆 Postgres のデフォルト・ユーザーにパスワードは付いていないそうだ。
あとからパスワードを付けることはできるか?

👇 postgres ユーザーでログインする

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ sudo -u postgres psql
[sudo] password for muzudho:
could not change directory to "/home/muzudho/nextjs_practice/nextjs-naraberu": Permission denied
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=#

👆 変わらず パーミッション拒否のエラーが出ている

`[Ctrl] + [Z]` で抜ける

👇 コマンドを打鍵

sudo nano /etc/postgresql/14/main/pg_hba.conf
# Database administrative login by Unix domain socket
local   all             postgres                                peer

👆 この行があるから Ok

やりなおし

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ sudo -u postgres psql
could not change directory to "/home/muzudho/nextjs_practice/nextjs-naraberu": Permission denied
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=# ALTER USER postgres PASSWORD 'パスワード';
ALTER ROLE

👆 これで、パスワードの付いていない postgres ユーザーにパスワードを付けた

👇 `/nextjs-naraberu/.env` ファイル

DATABASE_URL="postgresql://postgres:パスワード@localhost:5432/mydb?schema=public"

👆 ユーザー名とパスワードを編集

👇 以下のコマンドを打鍵する

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "mydb", schema "public" at "localhost:5432"

PostgreSQL database mydb created at localhost:5432

Applying migration `20240812121618_init`

The following migration(s) have been created and applied from new schema changes:

migrations/
  └─ 20240812121618_init/
    └─ migration.sql

Your database is now in sync with your schema.

Running generate... (Use --skip-generate to skip the generators)

✔ Generated Prisma Client (v5.18.0) to ./node_modules/.pnpm/@prisma+client@5.18.0_prisma@5.18.0/node_modules/@prisma/cli
ent in 84ms

👆 ようやく コマンドが通った

👆 話しを戻す

👇 デフォルトの `postgres` ユーザーでデータベースにログインする

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres

これでデータベースを操作できるはず

postgres=> select schemaname, tablename, tableowner from pg_tables;

👆 テーブル一覧を表示。 `/nextjs-naraberu/prisma/schema.prisma` ファイルで設定したテーブルは入ってない

とりあえず 次へ進む

チャプター4

👇 `app/dashboard/page.tsx` ファイルを新規作成し、以下のコードを貼り付ける

export default function Page() {
    return <p>Dashboard Page</p>;
}

👇 サーバーが止まっていたので再起動

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ pnpm dev

http://localhost:3000/dashboard へアクセス。Webブラウザのクライアント領域全体に `Dashboard Page` という文字だけ表示されている

複数ページに跨るナビゲーションを作る

👇 `/app/dashboard/layout.tsx` ファイルを新規作成する。以下のコードを貼り付ける

import SideNav from '@/app/ui/dashboard/sidenav';
 
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
      <div className="w-full flex-none md:w-64">
        {/* サイド・ナビゲーション */}
        <SideNav />
      </div>
      {/* メイン領域 */}
      <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
    </div>
  );
}

👆 これでサイド・メニュー(サイド・ナビゲーション)が付く

チャプター5

👇 `/app/ui/dashboard/nav-links.tsx` ファイルに以下のコードを追加

import Link from 'next/link';
'use client';
import { usePathname } from 'next/navigation';
import clsx from 'clsx';
export default function NavLinks() {
  const pathname = usePathname();
  // ...
}
※変更前
          <a
            key={link.name}
            href={link.href}
            className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
          >

※変更後
          <a
            key={link.name}
            href={link.href}
            className={clsx(
              'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
              {
                'bg-sky-100 text-blue-600': pathname === link.href,
              },
            )}
          >

👆 これでエラーが出るので …

^C
muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ pnpm dev

👆 サーバーを止めて、またサーバーを起動。Web ブラウザー上で `[Ctrl] + [F5]` キーを打鍵してスーパーリロード。これで アクティブ・リンクが表示された

チャプター6

データベースをシードする

Prisma を使ってやったが、テーブルが作られていない?

PS C:\Users\muzud> wsl -d Ubuntu
muzudho@Takahashi-PC:/mnt/c/Users/muzud$ cd ~/nextjs_practice/nextjs-naraberu
muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=>

👇 データベースの一覧

postgres=> \list
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges
-----------+----------+----------+---------+---------+-----------------------
 mydb      | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
(4 rows)

postgres=>

👇 テーブルの一覧

postgres=> \dt
Did not find any relations.
postgres=>

👆 テーブルが作られていない

postgres=> \q

👆 抜ける

(独習)Prisma Migrate を使ってみる

👇 以下のコマンドで、スキーマ通りのテーブルが作られるそうだ

muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "mydb", schema "public" at "localhost:5432"

Already in sync, no schema change or pending migration was found.

✔ Generated Prisma Client (v5.18.0) to ./node_modules/.pnpm/@prisma+client@5.18.0_prisma@5.18.0/node_modules/@prisma/cli
ent in 89ms
muzudho@Takahashi-PC:~/nextjs_practice/nextjs-naraberu$ psql -d postgres
psql (14.12 (Ubuntu 14.12-0ubuntu0.22.04.1))
Type "help" for help.

postgres=> \dt
Did not find any relations.
postgres=>

👆 やっぱり テーブルは作られていない

👇 マイグレーション用の SQL ファイルが自動生成されていた
`/nextjs-naraberu/prisma/migrations/20240812121618_init/migration.sql` ファイル

-- CreateEnum
CREATE TYPE "CustomerStatus" AS ENUM ('PENDING', 'PAID');

-- CreateTable
CREATE TABLE "User" (
    "id" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "email" TEXT NOT NULL,
    "password" TEXT NOT NULL
);

-- CreateTable
CREATE TABLE "Customer" (
    "id" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "email" TEXT NOT NULL,
    "image_url" TEXT NOT NULL
);

-- CreateTable
CREATE TABLE "Invoice" (
    "id" TEXT NOT NULL,
    "customer_id" TEXT NOT NULL,
    "amount" INTEGER NOT NULL,
    "data" TEXT NOT NULL,
    "Status" "CustomerStatus" NOT NULL
);

-- CreateTable
CREATE TABLE "Revenue" (
    "id" SERIAL NOT NULL,
    "month" TEXT NOT NULL,
    "revenue" INTEGER NOT NULL,

    CONSTRAINT "Revenue_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "LatestInvoice" (
    "id" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "image_url" TEXT NOT NULL,
    "email" TEXT NOT NULL,
    "amount" TEXT NOT NULL
);

-- CreateTable
CREATE TABLE "InvoicesTable" (
    "id" TEXT NOT NULL,
    "customer_id" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "email" TEXT NOT NULL,
    "image_url" TEXT NOT NULL,
    "data" TEXT NOT NULL,
    "amount" TEXT NOT NULL,
    "Status" "CustomerStatus" NOT NULL
);

-- CreateIndex
CREATE UNIQUE INDEX "User_id_key" ON "User"("id");

-- CreateIndex
CREATE UNIQUE INDEX "Customer_id_key" ON "Customer"("id");

-- CreateIndex
CREATE UNIQUE INDEX "Invoice_id_key" ON "Invoice"("id");

-- CreateIndex
CREATE UNIQUE INDEX "LatestInvoice_id_key" ON "LatestInvoice"("id");

-- CreateIndex
CREATE UNIQUE INDEX "InvoicesTable_id_key" ON "InvoicesTable"("id");

👆 この SQL が実行されれば、テーブルが作られるだろうことは分かる。
ポストグレスで `*.sql` ファイルを実行する方法を調べる

👆 方法は2通りあるそうだ

postgres=> \i prisma/migrations/20240812121618_init/migration.sql
CREATE TYPE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
postgres=>
postgres=> \dt
            List of relations
 Schema |     Name      | Type  |  Owner
--------+---------------+-------+---------
 public | Customer      | table | muzudho
 public | Invoice       | table | muzudho
 public | InvoicesTable | table | muzudho
 public | LatestInvoice | table | muzudho
 public | Revenue       | table | muzudho
 public | User          | table | muzudho
(6 rows)

postgres=>

👆 テーブルが作られた。 Owner が muzudho で良かったかどうか分からない

SQLite と Postgres は違うのか、 `/nextjs-naraberu/prisma/dev.db` のようなファイルは作成されてない

このあとは Type Script の中に SQL をベタ書きしていいのか、
Prisma を使った方がいいのか、どうなんだろうか?


この記事が気に入ったらサポートをしてみませんか?