Skip to content

Commit

Permalink
Merge branch 'edge'
Browse files Browse the repository at this point in the history
  • Loading branch information
TimMikeladze committed Dec 3, 2023
2 parents 35f3559 + 84fb352 commit 4d88db3
Show file tree
Hide file tree
Showing 55 changed files with 6,051 additions and 4,508 deletions.
10 changes: 4 additions & 6 deletions .env.template
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
MINIO_PORT="9000"
MINIO_SSL="false"
MINIO_SECRET_KEY="password"
MINIO_ACCESS_KEY="root"
MINIO_ENDPOINT="localhost"
MINIO_REGION="us-west-1"
S3_SECRET_KEY="password"
S3_ACCESS_KEY="root"
S3_ENDPOINT="http://localhost:9000"
S3_REGION="us-west-1"
PG_DB="postgres"
PG_CONNECTION_STRING="postgresql://postgres:postgres@localhost:5432"
13 changes: 4 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ jobs:
run-ci:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MINIO_REGION: us-west-1
MINIO_SSL: false
MINIO_PORT: 9000
MINIO_ACCESS_KEY: root
MINIO_SECRET_KEY: password
MINIO_ENDPOINT: localhost
S3_REGION: us-west-1
S3_ACCESS_KEY: root
S3_SECRET_KEY: password
S3_ENDPOINT: http://localhost:9000
PG_CONNECTION_STRING: postgres://postgres:password@localhost:5432
PG_DB: postgres

Expand Down Expand Up @@ -54,9 +52,6 @@ jobs:
- name: Run tests
run: yarn test:ci

- name: Build storybook
run: yarn build-storybook

- name: Build package
run: yarn build

Expand Down
69 changes: 43 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# 🗃️ next-upload

A turn-key solution for integrating Next.js with signed & secure file-uploads to an S3 compliant storage service such as R2, AWS, or Minio.
A turn-key solution for integrating Next.js with signed & secure file-uploads to an S3 compliant storage service such as R2, AWS, or Minio. Generates signed URLs for uploading files directly to your storage service and optionally integrates with your database to store additional metadata about your files.

Check out this [example](https://github.com/TimMikeladze/next-upload/tree/master/examples/next-upload-example) of a Next.js codebase showcasing an advanced implementation of `next-upload`.
Check out this [example](https://github.com/TimMikeladze/next-upload/tree/master/examples/next-upload-example) of a Next.js codebase showcasing an advanced implementation of `next-upload` with different storage services and databases.

> 🚧 Under active development. Expect breaking changes until v1.0.0.
Expand All @@ -26,12 +26,15 @@ First let's create a `NextUploadConfig` that defines how to connect to a storage

```tsx
export const config: NextUploadConfig = {
maxSize: '10mb',
maxSize: '1mb',
bucket: NextUpload.bucketFromEnv('my-project-name'),
client: {
endPoint: `s3.us-west-1.amazonaws.com`,
region: `us-west-1`,
secretKey: process.env.AWS_SECRET,
accessKey: process.env.AWS_KEY,
region: 'us-west-1',
endpoint: 'https://s3.us-west-1.amazonaws.com',
credentials: {
secretAccessKey: process.env.S3_SECRET_KEY,
accessKeyId: process.env.S3_ACCESS_KEY,
},
},
};
```
Expand All @@ -52,6 +55,9 @@ const nup = new NextUpload(config);
export const POST = (request: NextRequest) => nup.handler(request);

export const dynamic = 'force-dynamic';

// Optionally, if your application supports it you can run next-upload in the Edge runtime.
export const runtime = 'edge';
```

At this point you can import helper functions from `next-upload/client` to send files to your storage service in one line of code.
Expand Down Expand Up @@ -110,19 +116,19 @@ Works with any [keyv](https://github.com/jaredwray/) enabled store. This include

**src/app/upload/nup.ts**
```tsx
import { KeyvStore, NextUpload } from 'next-upload';
import { config } from './config';
import { NextRequest } from 'next/server';
import Keyv from 'keyv';
import { nextUploadConfig } from '@/app/upload/config';
import KeyvPostgres from '@keyv/postgres';
import Keyv from 'keyv';
import { NextUpload } from 'next-upload';
import { NextUploadKeyvStore } from 'next-upload/store/keyv';

export const nup = new NextUpload(
config,
new KeyvStore(
nextUploadConfig,
new NextUploadKeyvStore(
new Keyv({
namespace: NextUpload.namespaceFromEnv(),
namespace: NextUpload.namespaceFromEnv('my-project-name'),
store: new KeyvPostgres({
uri: process.env.PG_CONNECTION_STRING + '/' + process.env.PG_DB,
uri: `${process.env.PG_CONNECTION_STRING}/${process.env.PG_DB}`,
}),
})
)
Expand All @@ -133,27 +139,31 @@ export const nup = new NextUpload(

Works with a [Drizzle](https://github.com/drizzle-team/drizzle-orm) enabled database. This is a great option if you are already using Drizzle in your application and want tighter integration with your database schema. It also provides a more performant option for high volume reads/writes to your asset store.

#### 🐘 DrizzlePgStore - Postgres
#### 🐘 NextUploadDrizzlePgStore

**Note:** You must import and reexport `drizzlePgAssetsTable` from your Drizzle schema file as part of the database migration process to setup the asset store table.
The following Postgres clients are directly supported. Other Postgres clients most likely will work but may raise TypeScript errors during initialization of the `NextUploadDrizzlePgStore` instance.

- [Postgres.JS](https://orm.drizzle.team/docs/quick-postgresql/postgresjs)
- [node-postgres](https://orm.drizzle.team/docs/quick-postgresql/node-postgres)
- [Neon](https://orm.drizzle.team/docs/quick-postgresql/neon)

**src/db/schema.ts**
```tsx
export { drizzlePgAssetsTable } from 'next-upload';
export { nextUploadAssetsTable } from 'next-upload/store/drizzle/postgres-js';
```

**src/app/upload/nup.ts**
```tsx
import { DrizzlePgStore, NextUpload } from 'next-upload';
import { config } from './config';
import { NextRequest } from 'next/server';
import { nextUploadConfig } from '@/app/nextUploadConfig';
import { getDbPostgresJs } from '@/drizzle/getDbPostgresJs';
import { NextUpload } from 'next-upload';
import { NextUploadDrizzlePgStore } from 'next-upload/store/drizzle/postgres-js';

export const nup = new NextUpload(
config,
async () => new DrizzlePgStore(
await getDb(); // however you get your drizzle instance
)
nextUploadConfig,
new NextUploadDrizzlePgStore(getDbPostgresJs())
);

```

### 🔗 Getting an Asset Url
Expand Down Expand Up @@ -252,6 +262,7 @@ Consider setting up a cron job to run this function on a regular basis.
- [getBucket](#gear-getbucket)
- [getClient](#gear-getclient)
- [init](#gear-init)
- [bucketExists](#gear-bucketexists)
- [generatePresignedPostPolicy](#gear-generatepresignedpostpolicy)
- [pruneAssets](#gear-pruneassets)
- [verifyAsset](#gear-verifyasset)
Expand Down Expand Up @@ -310,14 +321,20 @@ Consider setting up a cron job to run this function on a regular basis.

| Method | Type |
| ---------- | ---------- |
| `getClient` | `() => Client` |
| `getClient` | `() => S3` |

#### :gear: init

| Method | Type |
| ---------- | ---------- |
| `init` | `() => Promise<void>` |

#### :gear: bucketExists

| Method | Type |
| ---------- | ---------- |
| `bucketExists` | `() => Promise<boolean>` |

#### :gear: generatePresignedPostPolicy

| Method | Type |
Expand Down
10 changes: 4 additions & 6 deletions environment.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
MINIO_ACCESS_KEY: string;
MINIO_ENDPOINT: string;
MINIO_PORT: string;
MINIO_REGION: string;
MINIO_SECRET_KEY: string;
MINIO_SSL?: 'true' | undefined;
S3_ACCESS_KEY: string;
S3_ENDPOINT: string;
S3_REGION: string;
S3_SECRET_KEY: string;
PG_CONNECTION_STRING: string;
PG_DB: string;
}
Expand Down
13 changes: 5 additions & 8 deletions examples/next-upload-example/.env.template
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
MINIO_PORT="9000"
MINIO_SSL="false"
MINIO_SECRET_KEY="password"
MINIO_ACCESS_KEY="root"
MINIO_ENDPOINT="localhost"
MINIO_REGION="us-west-1"
S3_SECRET_KEY="password"
S3_ACCESS_KEY="root"
S3_ENDPOINT="http://localhost:9000"
S3_REGION="us-west-1"
PG_DB="postgres"
PG_CONNECTION_STRING="postgresql://postgres:postgres@localhost:5432"
NEXT_PUBLIC_MAX_SIZE="1mb"
CRON_KEY="password"
NEXT_PUBLIC_MAX_SIZE="1mb"
10 changes: 4 additions & 6 deletions examples/next-upload-example/environment.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
MINIO_ACCESS_KEY: string;
MINIO_ENDPOINT: string;
MINIO_PORT: string;
MINIO_REGION: string;
MINIO_SECRET_KEY: string;
MINIO_SSL?: 'true' | undefined;
S3_ACCESS_KEY: string;
S3_ENDPOINT: string;
S3_REGION: string;
S3_SECRET_KEY: string;
PG_DB: string;
PG_CONNECTION_STRING: string;
NEXT_PUBLIC_MAX_SIZE: string | undefined;
Expand Down
37 changes: 24 additions & 13 deletions examples/next-upload-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,42 @@
"private": true,
"scripts": {
"dev": "next dev",
"build": "node vercel.js && next build",
"build": "next build",
"start": "next start",
"lint": "next lint",
"link:self": "yarn yalc link next-upload && yarn link next-upload"
"link:self": "yarn yalc link next-upload && yarn link next-upload",
"migrate:generate": "drizzle-kit generate:pg --out src/drizzle/migrations --schema src/drizzle/schema.ts",
"migrate": "yarn ts src/drizzle/migrate",
"ts": "node node_modules/.bin/ts-node -r tsconfig-paths/register -O '{\"module\": \"commonjs\", \"moduleResolution\": \"classic\", \"resolveJsonModule\": false }' --transpile-only --project ./tsconfig.json"
},
"dependencies": {
"@keyv/postgres": "^1.4.8",
"@types/node": "20.4.5",
"@types/react": "18.2.17",
"@types/react-dom": "18.2.7",
"@keyv/postgres": "^1.4.9",
"@neondatabase/serverless": "^0.6.0",
"@types/node": "20.10.2",
"@types/react": "18.2.40",
"@types/react-dom": "18.2.17",
"bytes": "^3.1.2",
"eslint": "8.46.0",
"eslint-config-next": "13.4.12",
"keyv": "^4.5.3",
"next": "13.4.12",
"next-upload": "^0.0.28",
"drizzle-orm": "^0.29.1",
"eslint": "8.55.0",
"eslint-config-next": "14.0.3",
"keyv": "^4.5.4",
"next": "14.0.3",
"next-upload": "0.0.29",
"postgres": "^3.4.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-dropzone": "^14.2.3",
"react-hot-toast": "^2.4.1",
"typescript": "5.1.6"
"typescript": "5.3.2"
},
"devDependencies": {
"@types/bytes": "^3.1.1",
"@types/bytes": "^3.1.4",
"@types/pg": "^8.10.9",
"dotenv": "^16.3.1",
"drizzle-kit": "^0.20.6",
"pg": "^8.11.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"yalc": "^1.0.0-pre.53"
}
}
21 changes: 0 additions & 21 deletions examples/next-upload-example/src/app/cron/route.ts

This file was deleted.

2 changes: 1 addition & 1 deletion examples/next-upload-example/src/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
:root {
--max-width: 1100px;
--max-width: 600px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
Expand Down
15 changes: 15 additions & 0 deletions examples/next-upload-example/src/app/nextUploadConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { type NextUploadConfig } from 'next-upload/client';
import { NextUpload } from 'next-upload';

export const nextUploadConfig: NextUploadConfig = {
maxSize: process.env.NEXT_PUBLIC_MAX_SIZE || '1mb',
bucket: NextUpload.bucketFromEnv('next-upload-example'),
client: {
region: process.env.S3_REGION,
endpoint: process.env.S3_ENDPOINT,
credentials: {
secretAccessKey: process.env.S3_SECRET_KEY,
accessKeyId: process.env.S3_ACCESS_KEY,
},
},
};
4 changes: 3 additions & 1 deletion examples/next-upload-example/src/app/page.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
}

.builtBy {
font-size: 0.7rem;
font-size: 0.8rem;
font-weight: bold;
text-align: left;
display: flex;
Expand All @@ -39,6 +39,8 @@

.example {
margin: 1rem 0rem;
max-width: var(--max-width);
width: 100%;
}

.divider {
Expand Down
25 changes: 22 additions & 3 deletions examples/next-upload-example/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default async function Home() {
<ExampleInstallCommand textToCopy={textToCopy} />
<div className={styles.builtBy}>
<div className={styles.row}>
Leave a star on
Read the docs on
<a
href="https://github.com/TimMikeladze/next-upload"
target="_blank"
Expand All @@ -30,9 +30,28 @@ export default async function Home() {

<div className={styles.divider} />
<div className={styles.example}>
<FileUpload />
<FileUpload
api="/upload/basic"
title="Basic upload (without database )"
/>
<FileUpload api="/upload/keyv" title="Upload with Keyv store" />
<FileUpload
api="/upload/drizzle-postgres-js"
title="Upload with Drizzle Postgres.js store"
/>
<FileUpload
api="/upload/drizzle-node-postgres"
title="Upload with Drizzle Node-Postgres store"
/>
<FileUpload
api="/upload/edge"
title="Edge upload (without database ) "
/>
<FileUpload
api="/upload/edge-with-drizzle-neon"
title="Edge upload with Drizzle Neon Serverless Postgres store "
/>
</div>
<div className={styles.divider} />
</main>
);
}
Loading

0 comments on commit 4d88db3

Please sign in to comment.