mirror of
https://github.com/vercel/next-learn.git
synced 2026-07-08 06:28:41 +00:00
Move from @vercel/postgres to postgres (provider-agnostic) (#989)
* Postgres * fix * fix * prettier-fix --------- Co-authored-by: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com>
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
'use server';
|
||||
|
||||
import { z } from 'zod';
|
||||
import { sql } from '@vercel/postgres';
|
||||
import postgres from 'postgres';
|
||||
import { revalidatePath } from 'next/cache';
|
||||
import { redirect } from 'next/navigation';
|
||||
import { signIn } from '@/auth';
|
||||
import { AuthError } from 'next-auth';
|
||||
|
||||
const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });
|
||||
|
||||
const FormSchema = z.object({
|
||||
id: z.string(),
|
||||
customerId: z.string({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { sql } from '@vercel/postgres';
|
||||
import postgres from 'postgres';
|
||||
import {
|
||||
CustomerField,
|
||||
CustomersTableType,
|
||||
@@ -9,6 +9,8 @@ import {
|
||||
} from './definitions';
|
||||
import { formatCurrency } from './utils';
|
||||
|
||||
const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });
|
||||
|
||||
export async function fetchRevenue() {
|
||||
try {
|
||||
// Artificially delay a response for demo purposes.
|
||||
@@ -17,11 +19,11 @@ export async function fetchRevenue() {
|
||||
// console.log('Fetching revenue data...');
|
||||
// await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||
|
||||
const data = await sql<Revenue>`SELECT * FROM revenue`;
|
||||
const data = await sql<Revenue[]>`SELECT * FROM revenue`;
|
||||
|
||||
// console.log('Data fetch completed after 3 seconds.');
|
||||
|
||||
return data.rows;
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Database Error:', error);
|
||||
throw new Error('Failed to fetch revenue data.');
|
||||
@@ -30,14 +32,14 @@ export async function fetchRevenue() {
|
||||
|
||||
export async function fetchLatestInvoices() {
|
||||
try {
|
||||
const data = await sql<LatestInvoiceRaw>`
|
||||
const data = await sql<LatestInvoiceRaw[]>`
|
||||
SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id
|
||||
FROM invoices
|
||||
JOIN customers ON invoices.customer_id = customers.id
|
||||
ORDER BY invoices.date DESC
|
||||
LIMIT 5`;
|
||||
|
||||
const latestInvoices = data.rows.map((invoice) => ({
|
||||
const latestInvoices = data.map((invoice) => ({
|
||||
...invoice,
|
||||
amount: formatCurrency(invoice.amount),
|
||||
}));
|
||||
@@ -66,10 +68,10 @@ export async function fetchCardData() {
|
||||
invoiceStatusPromise,
|
||||
]);
|
||||
|
||||
const numberOfInvoices = Number(data[0].rows[0].count ?? '0');
|
||||
const numberOfCustomers = Number(data[1].rows[0].count ?? '0');
|
||||
const totalPaidInvoices = formatCurrency(data[2].rows[0].paid ?? '0');
|
||||
const totalPendingInvoices = formatCurrency(data[2].rows[0].pending ?? '0');
|
||||
const numberOfInvoices = Number(data[0].count ?? '0');
|
||||
const numberOfCustomers = Number(data[1].count ?? '0');
|
||||
const totalPaidInvoices = formatCurrency(data[2][0].paid ?? '0');
|
||||
const totalPendingInvoices = formatCurrency(data[2][0].pending ?? '0');
|
||||
|
||||
return {
|
||||
numberOfCustomers,
|
||||
@@ -91,7 +93,7 @@ export async function fetchFilteredInvoices(
|
||||
const offset = (currentPage - 1) * ITEMS_PER_PAGE;
|
||||
|
||||
try {
|
||||
const invoices = await sql<InvoicesTable>`
|
||||
const invoices = await sql<InvoicesTable[]>`
|
||||
SELECT
|
||||
invoices.id,
|
||||
invoices.amount,
|
||||
@@ -112,7 +114,7 @@ export async function fetchFilteredInvoices(
|
||||
LIMIT ${ITEMS_PER_PAGE} OFFSET ${offset}
|
||||
`;
|
||||
|
||||
return invoices.rows;
|
||||
return invoices;
|
||||
} catch (error) {
|
||||
console.error('Database Error:', error);
|
||||
throw new Error('Failed to fetch invoices.');
|
||||
@@ -121,7 +123,7 @@ export async function fetchFilteredInvoices(
|
||||
|
||||
export async function fetchInvoicesPages(query: string) {
|
||||
try {
|
||||
const count = await sql`SELECT COUNT(*)
|
||||
const data = await sql`SELECT COUNT(*)
|
||||
FROM invoices
|
||||
JOIN customers ON invoices.customer_id = customers.id
|
||||
WHERE
|
||||
@@ -132,7 +134,7 @@ export async function fetchInvoicesPages(query: string) {
|
||||
invoices.status ILIKE ${`%${query}%`}
|
||||
`;
|
||||
|
||||
const totalPages = Math.ceil(Number(count.rows[0].count) / ITEMS_PER_PAGE);
|
||||
const totalPages = Math.ceil(Number(data[0].count) / ITEMS_PER_PAGE);
|
||||
return totalPages;
|
||||
} catch (error) {
|
||||
console.error('Database Error:', error);
|
||||
@@ -142,7 +144,7 @@ export async function fetchInvoicesPages(query: string) {
|
||||
|
||||
export async function fetchInvoiceById(id: string) {
|
||||
try {
|
||||
const data = await sql<InvoiceForm>`
|
||||
const data = await sql<InvoiceForm[]>`
|
||||
SELECT
|
||||
invoices.id,
|
||||
invoices.customer_id,
|
||||
@@ -152,7 +154,7 @@ export async function fetchInvoiceById(id: string) {
|
||||
WHERE invoices.id = ${id};
|
||||
`;
|
||||
|
||||
const invoice = data.rows.map((invoice) => ({
|
||||
const invoice = data.map((invoice) => ({
|
||||
...invoice,
|
||||
// Convert amount from cents to dollars
|
||||
amount: invoice.amount / 100,
|
||||
@@ -167,7 +169,7 @@ export async function fetchInvoiceById(id: string) {
|
||||
|
||||
export async function fetchCustomers() {
|
||||
try {
|
||||
const data = await sql<CustomerField>`
|
||||
const customers = await sql<CustomerField[]>`
|
||||
SELECT
|
||||
id,
|
||||
name
|
||||
@@ -175,7 +177,6 @@ export async function fetchCustomers() {
|
||||
ORDER BY name ASC
|
||||
`;
|
||||
|
||||
const customers = data.rows;
|
||||
return customers;
|
||||
} catch (err) {
|
||||
console.error('Database Error:', err);
|
||||
@@ -185,7 +186,7 @@ export async function fetchCustomers() {
|
||||
|
||||
export async function fetchFilteredCustomers(query: string) {
|
||||
try {
|
||||
const data = await sql<CustomersTableType>`
|
||||
const data = await sql<CustomersTableType[]>`
|
||||
SELECT
|
||||
customers.id,
|
||||
customers.name,
|
||||
@@ -203,7 +204,7 @@ export async function fetchFilteredCustomers(query: string) {
|
||||
ORDER BY customers.name ASC
|
||||
`;
|
||||
|
||||
const customers = data.rows.map((customer) => ({
|
||||
const customers = data.map((customer) => ({
|
||||
...customer,
|
||||
total_pending: formatCurrency(customer.total_pending),
|
||||
total_paid: formatCurrency(customer.total_paid),
|
||||
|
||||
@@ -1,122 +1,117 @@
|
||||
// import bcrypt from 'bcrypt';
|
||||
// import { db } from '@vercel/postgres';
|
||||
// import { invoices, customers, revenue, users } from '../lib/placeholder-data';
|
||||
import bcrypt from 'bcrypt';
|
||||
import postgres from 'postgres';
|
||||
import { invoices, customers, revenue, users } from '../lib/placeholder-data';
|
||||
|
||||
// const client = await db.connect();
|
||||
const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });
|
||||
|
||||
// async function seedUsers() {
|
||||
// await client.sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
|
||||
// await client.sql`
|
||||
// CREATE TABLE IF NOT EXISTS users (
|
||||
// id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
// name VARCHAR(255) NOT NULL,
|
||||
// email TEXT NOT NULL UNIQUE,
|
||||
// password TEXT NOT NULL
|
||||
// );
|
||||
// `;
|
||||
async function seedUsers() {
|
||||
await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
|
||||
await sql`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
// const insertedUsers = await Promise.all(
|
||||
// users.map(async (user) => {
|
||||
// const hashedPassword = await bcrypt.hash(user.password, 10);
|
||||
// return client.sql`
|
||||
// INSERT INTO users (id, name, email, password)
|
||||
// VALUES (${user.id}, ${user.name}, ${user.email}, ${hashedPassword})
|
||||
// ON CONFLICT (id) DO NOTHING;
|
||||
// `;
|
||||
// }),
|
||||
// );
|
||||
const insertedUsers = await Promise.all(
|
||||
users.map(async (user) => {
|
||||
const hashedPassword = await bcrypt.hash(user.password, 10);
|
||||
return sql`
|
||||
INSERT INTO users (id, name, email, password)
|
||||
VALUES (${user.id}, ${user.name}, ${user.email}, ${hashedPassword})
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
`;
|
||||
}),
|
||||
);
|
||||
|
||||
// return insertedUsers;
|
||||
// }
|
||||
return insertedUsers;
|
||||
}
|
||||
|
||||
// async function seedInvoices() {
|
||||
// await client.sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
|
||||
async function seedInvoices() {
|
||||
await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
|
||||
|
||||
// await client.sql`
|
||||
// CREATE TABLE IF NOT EXISTS invoices (
|
||||
// id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
// customer_id UUID NOT NULL,
|
||||
// amount INT NOT NULL,
|
||||
// status VARCHAR(255) NOT NULL,
|
||||
// date DATE NOT NULL
|
||||
// );
|
||||
// `;
|
||||
await sql`
|
||||
CREATE TABLE IF NOT EXISTS invoices (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
customer_id UUID NOT NULL,
|
||||
amount INT NOT NULL,
|
||||
status VARCHAR(255) NOT NULL,
|
||||
date DATE NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
// const insertedInvoices = await Promise.all(
|
||||
// invoices.map(
|
||||
// (invoice) => client.sql`
|
||||
// INSERT INTO invoices (customer_id, amount, status, date)
|
||||
// VALUES (${invoice.customer_id}, ${invoice.amount}, ${invoice.status}, ${invoice.date})
|
||||
// ON CONFLICT (id) DO NOTHING;
|
||||
// `,
|
||||
// ),
|
||||
// );
|
||||
const insertedInvoices = await Promise.all(
|
||||
invoices.map(
|
||||
(invoice) => sql`
|
||||
INSERT INTO invoices (customer_id, amount, status, date)
|
||||
VALUES (${invoice.customer_id}, ${invoice.amount}, ${invoice.status}, ${invoice.date})
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
`,
|
||||
),
|
||||
);
|
||||
|
||||
// return insertedInvoices;
|
||||
// }
|
||||
return insertedInvoices;
|
||||
}
|
||||
|
||||
// async function seedCustomers() {
|
||||
// await client.sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
|
||||
async function seedCustomers() {
|
||||
await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
|
||||
|
||||
// await client.sql`
|
||||
// CREATE TABLE IF NOT EXISTS customers (
|
||||
// id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
// name VARCHAR(255) NOT NULL,
|
||||
// email VARCHAR(255) NOT NULL,
|
||||
// image_url VARCHAR(255) NOT NULL
|
||||
// );
|
||||
// `;
|
||||
await sql`
|
||||
CREATE TABLE IF NOT EXISTS customers (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
image_url VARCHAR(255) NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
// const insertedCustomers = await Promise.all(
|
||||
// customers.map(
|
||||
// (customer) => client.sql`
|
||||
// INSERT INTO customers (id, name, email, image_url)
|
||||
// VALUES (${customer.id}, ${customer.name}, ${customer.email}, ${customer.image_url})
|
||||
// ON CONFLICT (id) DO NOTHING;
|
||||
// `,
|
||||
// ),
|
||||
// );
|
||||
const insertedCustomers = await Promise.all(
|
||||
customers.map(
|
||||
(customer) => sql`
|
||||
INSERT INTO customers (id, name, email, image_url)
|
||||
VALUES (${customer.id}, ${customer.name}, ${customer.email}, ${customer.image_url})
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
`,
|
||||
),
|
||||
);
|
||||
|
||||
// return insertedCustomers;
|
||||
// }
|
||||
return insertedCustomers;
|
||||
}
|
||||
|
||||
// async function seedRevenue() {
|
||||
// await client.sql`
|
||||
// CREATE TABLE IF NOT EXISTS revenue (
|
||||
// month VARCHAR(4) NOT NULL UNIQUE,
|
||||
// revenue INT NOT NULL
|
||||
// );
|
||||
// `;
|
||||
async function seedRevenue() {
|
||||
await sql`
|
||||
CREATE TABLE IF NOT EXISTS revenue (
|
||||
month VARCHAR(4) NOT NULL UNIQUE,
|
||||
revenue INT NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
// const insertedRevenue = await Promise.all(
|
||||
// revenue.map(
|
||||
// (rev) => client.sql`
|
||||
// INSERT INTO revenue (month, revenue)
|
||||
// VALUES (${rev.month}, ${rev.revenue})
|
||||
// ON CONFLICT (month) DO NOTHING;
|
||||
// `,
|
||||
// ),
|
||||
// );
|
||||
const insertedRevenue = await Promise.all(
|
||||
revenue.map(
|
||||
(rev) => sql`
|
||||
INSERT INTO revenue (month, revenue)
|
||||
VALUES (${rev.month}, ${rev.revenue})
|
||||
ON CONFLICT (month) DO NOTHING;
|
||||
`,
|
||||
),
|
||||
);
|
||||
|
||||
// return insertedRevenue;
|
||||
// }
|
||||
return insertedRevenue;
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
return Response.json({
|
||||
message:
|
||||
'Uncomment this file and remove this line. You can delete this file when you are finished.',
|
||||
});
|
||||
// try {
|
||||
// await client.sql`BEGIN`;
|
||||
// await seedUsers();
|
||||
// await seedCustomers();
|
||||
// await seedInvoices();
|
||||
// await seedRevenue();
|
||||
// await client.sql`COMMIT`;
|
||||
try {
|
||||
const result = await sql.begin((sql) => [
|
||||
seedUsers(),
|
||||
seedCustomers(),
|
||||
seedInvoices(),
|
||||
seedRevenue(),
|
||||
]);
|
||||
|
||||
// return Response.json({ message: 'Database seeded successfully' });
|
||||
// } catch (error) {
|
||||
// await client.sql`ROLLBACK`;
|
||||
// return Response.json({ error }, { status: 500 });
|
||||
// }
|
||||
return Response.json({ message: 'Database seeded successfully' });
|
||||
} catch (error) {
|
||||
return Response.json({ error }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user