Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 15 additions & 0 deletions .github/snippets/pr-preview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Every pull request publishes a preview package via [pkg.pr.new](https://pkg.pr.new), so you can install and test changes before they are merged.

```bash
# npm
npm install https://pkg.pr.new/@websideproject/nuxt-auto-api@<pr-number>
npm install https://pkg.pr.new/@websideproject/nuxt-auto-admin@<pr-number>

# pnpm
pnpm add https://pkg.pr.new/@websideproject/nuxt-auto-api@<pr-number>
pnpm add https://pkg.pr.new/@websideproject/nuxt-auto-admin@<pr-number>

# bun
bun add https://pkg.pr.new/@websideproject/nuxt-auto-api@<pr-number>
bun add https://pkg.pr.new/@websideproject/nuxt-auto-admin@<pr-number>
```
5 changes: 4 additions & 1 deletion .github/workflows/autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ jobs:
- name: Lint code
run: bun run lint:fix

- name: Update README
run: bun run automd

- uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27
with:
commit-message: 'chore: apply automated lint fixes'
commit-message: 'chore: apply automated fixes'
38 changes: 19 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,22 @@ jobs:
- name: Test
run: bun run test

publish:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
needs: [build, lint, typecheck, test]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Prepare
run: bun run dev:prepare
- name: Build modules
run: bun run build
- name: Publish
run: bunx pkg-pr-new publish --compact --no-template './packages/nuxt-auto-api' './packages/nuxt-auto-admin'
# publish:
# runs-on: ubuntu-latest
# if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
# needs: [build, lint, typecheck, test]
# steps:
# - uses: actions/checkout@v4
# with:
# fetch-depth: 0
# - uses: oven-sh/setup-bun@v2
# with:
# bun-version: latest
# - name: Install dependencies
# run: bun install --frozen-lockfile
# - name: Prepare
# run: bun run dev:prepare
# - name: Build modules
# run: bun run build
# - name: Publish
# run: bunx pkg-pr-new publish --compact --no-template './packages/nuxt-auto-api' './packages/nuxt-auto-admin'
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ bun add -D @websideproject/nuxt-auto-api @websideproject/nuxt-auto-admin

📖 **[Full Documentation →](https://github.com/websideproject/nuxt-auto)**

## 🔍 PR Previews

<!-- automd:file src=".github/snippets/pr-preview.md" -->

Every pull request publishes a preview package via [pkg.pr.new](https://pkg.pr.new), so you can install and test changes before they are merged.

```bash
# npm
npm install https://pkg.pr.new/@websideproject/nuxt-auto-api@<pr-number>
npm install https://pkg.pr.new/@websideproject/nuxt-auto-admin@<pr-number>

# pnpm
pnpm add https://pkg.pr.new/@websideproject/nuxt-auto-api@<pr-number>
pnpm add https://pkg.pr.new/@websideproject/nuxt-auto-admin@<pr-number>

# bun
bun add https://pkg.pr.new/@websideproject/nuxt-auto-api@<pr-number>
bun add https://pkg.pr.new/@websideproject/nuxt-auto-admin@<pr-number>
```

<!-- /automd -->

## 🤝 Contributing

<!-- automd:file src=".github/snippets/contributing.md" -->
Expand Down
34 changes: 34 additions & 0 deletions apps/benchmark/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FROM node:20-slim

WORKDIR /workspace

# Copy the package
COPY packages/nuxt-auto-api ./packages/nuxt-auto-api

# Build the package
WORKDIR /workspace/packages/nuxt-auto-api
RUN npm install
RUN npm run prepack

# Copy the app
COPY benchmark/app /workspace/benchmark/app

WORKDIR /workspace/benchmark/app

# Install dependencies
RUN npm install

# Build the application
RUN npm run build

# Expose port
EXPOSE 3000

# Set environment variables
ENV HOST=0.0.0.0
ENV PORT=3000
ENV NODE_ENV=production

# Run seed and then start the server
# using jiti to execute the typescript seed file directly
CMD mkdir -p .data && npm run db:push && npx jiti ./server/database/seed.ts && node .output/server/index.mjs
42 changes: 42 additions & 0 deletions apps/benchmark/Dockerfile.bun
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
FROM oven/bun:1

WORKDIR /workspace

# Install build dependencies for better-sqlite3
RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*

# Copy the package
COPY packages/nuxt-auto-api ./packages/nuxt-auto-api

# Remove better-sqlite3 from package dependencies to avoid build
WORKDIR /workspace/packages/nuxt-auto-api
RUN sed -i '/better-sqlite3/d' package.json
RUN bun install
RUN bun run prepack

# Copy the app
COPY benchmark/app /workspace/benchmark/app

WORKDIR /workspace/benchmark/app

# Remove better-sqlite3 and swap db.ts
RUN sed -i '/better-sqlite3/d' package.json
RUN cp server/database/db.bun.ts server/database/db.ts

# Install dependencies
RUN bun install

# Build the application
ENV NITRO_PRESET=bun
RUN bun run build

# Expose port
EXPOSE 3000

# Set environment variables
ENV HOST=0.0.0.0
ENV PORT=3000
ENV NODE_ENV=production

# Run migrations, seed and then start the server
CMD mkdir -p .data && bun run ./server/database/init-bun.ts && bun run ./server/database/seed.ts && bun run .output/server/index.mjs
26 changes: 26 additions & 0 deletions apps/benchmark/Dockerfile.fastify
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM node:20-slim

WORKDIR /workspace/benchmark/fastify-app

# Copy package.json
COPY benchmark/fastify-app/package.json .

# Install dependencies
RUN npm install

# Copy source
COPY benchmark/fastify-app .

# Build
RUN npm run build

# Expose port
EXPOSE 3000

# Set environment variables
ENV HOST=0.0.0.0
ENV PORT=3000
ENV NODE_ENV=production

# Run migrations (create .data dir first), seed and start
CMD mkdir -p .data && npx drizzle-kit push && npx tsx src/database/seed.ts && npm start
17 changes: 17 additions & 0 deletions apps/benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Benchmark

This directory contains a benchmark for `nuxt-auto-api` vs manual handlers.

## Usage

1. Build and run with Docker Compose:
```bash
docker compose up --build
```

2. View k6 results in the console.

## Structure

- `app`: A minimal Nuxt app using `nuxt-auto-api` and manual handlers.
- `k6`: k6 load testing scripts.
10 changes: 10 additions & 0 deletions apps/benchmark/app/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from 'drizzle-kit'

export default defineConfig({
schema: './server/database/schema.ts',
out: './drizzle',
dialect: 'sqlite',
dbCredentials: {
url: '.data/db.sqlite',
},
})
84 changes: 84 additions & 0 deletions apps/benchmark/app/modules/base/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type { ResourceAuthConfig } from 'nuxt-auto-api/runtime/types'

/**
* Authorization configuration for core playground resources
*/

// Users resource
export const usersAuth: ResourceAuthConfig = {
permissions: {
// Anyone can read users
read: () => true,
// Only admins can create users
create: 'admin',
// Users can update themselves, admins can update anyone
update: (context) => {
if (context.permissions.includes('admin')) return true
if (context.user && context.params.id === String(context.user.id)) return true
return false
},
// Only admins can delete users
delete: 'admin',
},
// Object-level check: users can only see/edit themselves unless they're admin
objectLevel: async (object, context) => {
if (context.permissions.includes('admin')) return true
// Convert both to string for comparison since IDs might be different types
if (context.user && String(object.id) === String(context.user.id)) return true
return false
},
// Field-level permissions
fields: {
// Only the user themselves or admins can see the email
email: {
read: (context) => {
if (context.permissions.includes('admin')) return true
if (context.user && context.params.id === String(context.user.id)) return true
return false
},
},
// Only admins can change role
role: {
write: 'admin',
},
},
}

// Posts resource - object-level authorization demo
export const postsAuth: ResourceAuthConfig = {
permissions: {
// Anyone can read posts
read: () => true,
// Authenticated users can create posts
create: (context) => !!context.user,
// Authenticated users can update (but object-level auth will restrict to own posts)
update: (context) => !!context.user,
// Authenticated users can delete (but object-level auth will restrict to own posts)
delete: (context) => !!context.user,
},
// Object-level: users can only edit their own posts unless they're admin
objectLevel: async (object, context) => {
// Allow reading all posts
if (context.operation === 'get' || context.operation === 'list') return true

// Admins can do anything
if (context.user?.role === 'admin') return true

// For update/delete, must be the owner
if (context.operation === 'update' || context.operation === 'delete') {
return context.user && String(object.userId) === String(context.user.id)
}

return false
},
}

// Comments resource
export const commentsAuth: ResourceAuthConfig = {
permissions: {
read: () => true,
create: (context) => !!context.user,
update: (context) => !!context.user,
delete: ['admin', 'editor'],
},
}
43 changes: 43 additions & 0 deletions apps/benchmark/app/modules/base/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { defineNuxtModule, createResolver } from '@nuxt/kit'
import { createModuleImport } from '@websideproject/nuxt-auto-api'

/**
* Base module for playground - registers core resources (users, posts, comments)
* This demonstrates how a main app can register its resources via hooks
*/
export default defineNuxtModule({
meta: {
name: 'playground-base',
configKey: 'playgroundBase',
},

setup(_options, nuxt) {
const resolver = createResolver(import.meta.url)

// Register resources at BUILD TIME via hook
nuxt.hook('autoApi:registerSchema', (registry) => {
// Register users
registry.register('users', {
schema: createModuleImport(resolver.resolve('../../server/database/schema'), 'users'),
authorization: createModuleImport(resolver.resolve('./auth'), 'usersAuth'),
validation: createModuleImport(resolver.resolve('../../server/validation/users'), 'usersValidation'),
hiddenFields: ['password', 'apiKey'], // Hide sensitive fields from all API responses
})

// Register posts
registry.register('posts', {
schema: createModuleImport(resolver.resolve('../../server/database/schema'), 'posts'),
authorization: createModuleImport(resolver.resolve('./auth'), 'postsAuth'),
validation: createModuleImport(resolver.resolve('../../server/validation/posts'), 'postsValidation'),
})

// Register comments
registry.register('comments', {
schema: createModuleImport(resolver.resolve('../../server/database/schema'), 'comments'),
authorization: createModuleImport(resolver.resolve('./auth'), 'commentsAuth'),
})

console.log('[playground-base] Registered 3 core resources at build time')
})
},
})
27 changes: 27 additions & 0 deletions apps/benchmark/app/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export default defineNuxtConfig({
modules: [
'@websideproject/nuxt-auto-api',
'./modules/base',
],

autoApi: {
prefix: '/api',
database: {
client: 'better-sqlite3'
},
pagination: {
default: 'offset',
defaultLimit: 20,
maxLimit: 100
}
},

compatibilityDate: '2025-01-15',

// Ensure we can import from server/database
nitro: {
imports: {
dirs: ['./server/database']
}
}
})
Loading
Loading