nuxt-auto-crud 1.2.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +189 -90
- package/dist/module.d.mts +49 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +24 -1
- package/dist/runtime/server/api/[model]/[id].delete.d.ts +1 -1
- package/dist/runtime/server/api/[model]/[id].delete.js +20 -2
- package/dist/runtime/server/api/[model]/[id].get.d.ts +1 -1
- package/dist/runtime/server/api/[model]/[id].get.js +21 -4
- package/dist/runtime/server/api/[model]/[id].patch.d.ts +1 -1
- package/dist/runtime/server/api/[model]/[id].patch.js +29 -5
- package/dist/runtime/server/api/[model]/index.get.js +25 -4
- package/dist/runtime/server/api/[model]/index.post.d.ts +1 -1
- package/dist/runtime/server/api/[model]/index.post.js +23 -8
- package/dist/runtime/server/utils/auth.d.ts +2 -0
- package/dist/runtime/server/utils/auth.js +39 -0
- package/dist/runtime/server/utils/config.d.ts +2 -0
- package/dist/runtime/server/utils/config.js +4 -0
- package/dist/runtime/server/utils/jwt.d.ts +2 -0
- package/dist/runtime/server/utils/jwt.js +19 -0
- package/dist/runtime/server/utils/modelMapper.d.ts +31 -0
- package/dist/runtime/server/utils/modelMapper.js +38 -0
- package/package.json +20 -10
- package/src/runtime/server/api/[model]/[id].delete.ts +29 -3
- package/src/runtime/server/api/[model]/[id].get.ts +29 -5
- package/src/runtime/server/api/[model]/[id].patch.ts +40 -9
- package/src/runtime/server/api/[model]/index.get.ts +33 -5
- package/src/runtime/server/api/[model]/index.post.ts +32 -15
- package/src/runtime/server/utils/auth.ts +55 -0
- package/src/runtime/server/utils/config.ts +6 -0
- package/src/runtime/server/utils/jwt.ts +23 -0
- package/src/runtime/server/utils/modelMapper.ts +83 -0
package/README.md
CHANGED
|
@@ -1,77 +1,153 @@
|
|
|
1
1
|
# Nuxt Auto CRUD
|
|
2
2
|
|
|
3
|
-
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
-
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
-
[![License][license-src]][license-href]
|
|
6
|
-
[![Nuxt][nuxt-src]][nuxt-href]
|
|
7
3
|
|
|
8
|
-
|
|
4
|
+
|
|
5
|
+
> **Note:** This module is currently in its alpha stage. However, you can use it to accelerate MVP development. It has not been tested thoroughly enough for production use; only happy-path testing is performed for each release.
|
|
6
|
+
|
|
7
|
+
Auto-generate RESTful CRUD APIs for your **Nuxt** application based solely on your database schema. Minimal configuration required.
|
|
9
8
|
|
|
10
9
|
- [✨ Release Notes](/CHANGELOG.md)
|
|
11
10
|
- [🎮 Try the Playground](/playground)
|
|
12
11
|
|
|
13
|
-
##
|
|
12
|
+
## 🚀 CRUD APIs are ready to use without code
|
|
13
|
+
|
|
14
|
+
- `GET /api/:model` - List all records
|
|
15
|
+
- `POST /api/:model` - Create a new record
|
|
16
|
+
- `GET /api/:model/:id` - Get record by ID
|
|
17
|
+
- `PATCH /api/:model/:id` - Update record
|
|
18
|
+
- `DELETE /api/:model/:id` - Delete record
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
- 🚀 **Zero Configuration** - Just define your schema, APIs are generated automatically
|
|
17
|
-
- 🛡️ **Protected Fields** - Automatically protects `id` and `createdAt` fields from updates
|
|
18
|
-
- 📝 **Full CRUD** - Complete Create, Read, Update, Delete operations out of the box
|
|
19
|
-
- 🎯 **Type-Safe** - Fully typed with TypeScript support
|
|
20
|
-
- 🔌 **Works with NuxtHub** - Seamlessly integrates with NuxtHub database
|
|
20
|
+
## 📦 How to install
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
### New Project (Recommended)
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Start a new project with everything pre-configured using our template:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
npx nuxi init -t gh:clifordpereira/nuxt-auto-crud_template <project-name>
|
|
28
|
+
cd <project-name>
|
|
29
|
+
bun install
|
|
30
|
+
bun db:generate
|
|
31
|
+
bun run dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Detailed instructions can be found in [https://auto-crud.clifland.in/](https://auto-crud.clifland.in/)
|
|
35
|
+
|
|
36
|
+
### Add User
|
|
37
|
+
Open Nuxt DevTools (bottom-middle icon) > `...` menu > **Database** icon to add users.
|
|
38
|
+
> **Note:** If the users table doesn't appear, restart the server (`Ctrl + C` and `bun run dev`).
|
|
39
|
+
|
|
40
|
+
That's it! You can now access the APIs:
|
|
41
|
+
|
|
42
|
+
### Test API
|
|
43
|
+
Visit [http://localhost:3000/api/users](http://localhost:3000/api/users).
|
|
44
|
+
|
|
45
|
+
### Existing Project
|
|
46
|
+
|
|
47
|
+
If you want to add `nuxt-auto-crud` to an existing project, follow these steps:
|
|
48
|
+
|
|
49
|
+
> **Note:** These instructions assume you are using NuxtHub. If you are using a custom SQLite setup (e.g. better-sqlite3, Turso), please see [Custom Setup](./custom-setup.md).
|
|
50
|
+
|
|
51
|
+
### 1. Install dependencies
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Install module and required dependencies
|
|
55
|
+
npm install nuxt-auto-crud @nuxthub/core@latest drizzle-orm
|
|
56
|
+
npm install --save-dev wrangler drizzle-kit
|
|
57
|
+
|
|
58
|
+
# Or using bun
|
|
59
|
+
bun add nuxt-auto-crud @nuxthub/core@latest drizzle-orm
|
|
60
|
+
bun add --dev wrangler drizzle-kit
|
|
30
61
|
```
|
|
31
62
|
|
|
32
|
-
### 2.
|
|
63
|
+
### 2. Configure Nuxt
|
|
64
|
+
|
|
65
|
+
Add the modules to your `nuxt.config.ts`:
|
|
33
66
|
|
|
34
67
|
```typescript
|
|
35
68
|
// nuxt.config.ts
|
|
36
69
|
export default defineNuxtConfig({
|
|
37
|
-
modules: [
|
|
70
|
+
modules: ['@nuxthub/core', 'nuxt-auto-crud'],
|
|
38
71
|
|
|
39
72
|
hub: {
|
|
40
73
|
database: true,
|
|
41
74
|
},
|
|
42
75
|
|
|
43
76
|
autoCrud: {
|
|
44
|
-
schemaPath:
|
|
77
|
+
schemaPath: 'server/database/schema', // default value
|
|
45
78
|
},
|
|
46
|
-
})
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 3. Configure Drizzle
|
|
83
|
+
|
|
84
|
+
Add the generation script to your `package.json`:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"scripts": {
|
|
89
|
+
"db:generate": "drizzle-kit generate"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Create `drizzle.config.ts` in your project root:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// drizzle.config.ts
|
|
98
|
+
import { defineConfig } from 'drizzle-kit'
|
|
99
|
+
|
|
100
|
+
export default defineConfig({
|
|
101
|
+
dialect: 'sqlite',
|
|
102
|
+
schema: './server/database/schema.ts',
|
|
103
|
+
out: './server/database/migrations'
|
|
104
|
+
})
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 4. Setup Database Connection
|
|
108
|
+
|
|
109
|
+
Create `server/utils/drizzle.ts` to export the database instance:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// server/utils/drizzle.ts
|
|
113
|
+
import { drizzle } from 'drizzle-orm/d1'
|
|
114
|
+
export { sql, eq, and, or } from 'drizzle-orm'
|
|
115
|
+
|
|
116
|
+
import * as schema from '../database/schema'
|
|
117
|
+
|
|
118
|
+
export const tables = schema
|
|
119
|
+
|
|
120
|
+
export function useDrizzle() {
|
|
121
|
+
return drizzle(hubDatabase(), { schema })
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type User = typeof schema.users.$inferSelect
|
|
47
125
|
```
|
|
48
126
|
|
|
49
|
-
###
|
|
127
|
+
### 5. Define your database schema
|
|
128
|
+
|
|
129
|
+
Create `server/database/schema.ts`:
|
|
50
130
|
|
|
51
131
|
```typescript
|
|
52
132
|
// server/database/schema.ts
|
|
53
|
-
import { sqliteTable, text, integer } from
|
|
54
|
-
|
|
55
|
-
export const users = sqliteTable(
|
|
56
|
-
id: integer(
|
|
57
|
-
name: text(
|
|
58
|
-
email: text(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
133
|
+
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
|
|
134
|
+
|
|
135
|
+
export const users = sqliteTable('users', {
|
|
136
|
+
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
137
|
+
name: text('name').notNull(),
|
|
138
|
+
email: text('email').notNull().unique(),
|
|
139
|
+
password: text('password').notNull(),
|
|
140
|
+
avatar: text('avatar').notNull(),
|
|
141
|
+
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
|
|
142
|
+
})
|
|
143
|
+
```
|
|
64
144
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
|
|
72
|
-
() => new Date()
|
|
73
|
-
),
|
|
74
|
-
});
|
|
145
|
+
### 6. Run the project
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
cd <project-name>
|
|
149
|
+
bun db:generate
|
|
150
|
+
bun run dev
|
|
75
151
|
```
|
|
76
152
|
|
|
77
153
|
That's it! 🎉 Your CRUD APIs are now available:
|
|
@@ -93,12 +169,13 @@ Want to see it in action? Clone this repo and try the playground:
|
|
|
93
169
|
git clone https://github.com/clifordpereira/nuxt-auto-crud.git
|
|
94
170
|
cd nuxt-auto-crud
|
|
95
171
|
|
|
96
|
-
# Install dependencies
|
|
172
|
+
# Install dependencies (parent folder)
|
|
97
173
|
bun install
|
|
98
174
|
|
|
99
|
-
# Run the playground
|
|
100
|
-
cd playground
|
|
175
|
+
# Run the playground (fullstack with auth)
|
|
176
|
+
cd playground-fullstack
|
|
101
177
|
bun install
|
|
178
|
+
bun db:generate
|
|
102
179
|
bun run dev
|
|
103
180
|
```
|
|
104
181
|
|
|
@@ -112,9 +189,9 @@ The playground includes a sample schema with users, posts, and comments tables,
|
|
|
112
189
|
const user = await $fetch("/api/users", {
|
|
113
190
|
method: "POST",
|
|
114
191
|
body: {
|
|
115
|
-
name: "
|
|
116
|
-
email: "
|
|
117
|
-
bio: "
|
|
192
|
+
name: "Cliford Pereira",
|
|
193
|
+
email: "clifordpereira@gmail.com",
|
|
194
|
+
bio: "Full-Stack Developer",
|
|
118
195
|
},
|
|
119
196
|
});
|
|
120
197
|
```
|
|
@@ -150,7 +227,57 @@ await $fetch("/api/users/1", {
|
|
|
150
227
|
});
|
|
151
228
|
```
|
|
152
229
|
|
|
153
|
-
##
|
|
230
|
+
## Use Cases
|
|
231
|
+
|
|
232
|
+
### 1. Full-stack App (with Auth)
|
|
233
|
+
|
|
234
|
+
If you are building a full-stack Nuxt application, you can easily integrate `nuxt-auth-utils` and `nuxt-authorization` to secure your auto-generated APIs.
|
|
235
|
+
|
|
236
|
+
First, install the modules:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npx nuxi@latest module add auth-utils
|
|
240
|
+
npm install nuxt-authorization
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Then, configure `nuxt-auto-crud` in your `nuxt.config.ts`:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
export default defineNuxtConfig({
|
|
247
|
+
modules: [
|
|
248
|
+
'nuxt-auto-crud',
|
|
249
|
+
'nuxt-auth-utils'
|
|
250
|
+
],
|
|
251
|
+
autoCrud: {
|
|
252
|
+
auth: {
|
|
253
|
+
enabled: true, // Enables requireUserSession() check
|
|
254
|
+
authorization: true // Enables authorize(model, action) check
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
When `authorization` is enabled, the module will call `authorize(model, action)` where action is one of: `create`, `read`, `update`, `delete`.
|
|
261
|
+
|
|
262
|
+
### 2. Backend-only App (API Mode)
|
|
263
|
+
|
|
264
|
+
If you are using Nuxt as a backend for a separate client application (e.g., mobile app, SPA), you can use this module to quickly generate REST APIs.
|
|
265
|
+
|
|
266
|
+
In this case, you might handle authentication differently (e.g., validating tokens in middleware) or disable the built-in auth checks if you have a global auth middleware.
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
export default defineNuxtConfig({
|
|
270
|
+
modules: ['nuxt-auto-crud'],
|
|
271
|
+
autoCrud: {
|
|
272
|
+
auth: {
|
|
273
|
+
enabled: false, // Default
|
|
274
|
+
authorization: false // Default
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
})
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Configuration
|
|
154
281
|
|
|
155
282
|
### Module Options
|
|
156
283
|
|
|
@@ -173,45 +300,26 @@ By default, the following fields are protected from updates:
|
|
|
173
300
|
|
|
174
301
|
You can customize updatable fields in your schema by modifying the `modelMapper.ts` utility.
|
|
175
302
|
|
|
303
|
+
### Hidden Fields
|
|
304
|
+
|
|
305
|
+
By default, the following fields are hidden from API responses for security:
|
|
306
|
+
|
|
307
|
+
- `password`
|
|
308
|
+
- `secret`
|
|
309
|
+
- `token`
|
|
310
|
+
|
|
311
|
+
You can customize hidden fields by modifying the `modelMapper.ts` utility.
|
|
312
|
+
|
|
176
313
|
## 🔧 Requirements
|
|
177
314
|
|
|
178
315
|
- Nuxt 3 or 4
|
|
179
|
-
-
|
|
180
|
-
-
|
|
316
|
+
- Drizzle ORM (SQLite)
|
|
317
|
+
- NuxtHub (Recommended) or [Custom SQLite Setup](./custom-setup.md)
|
|
181
318
|
|
|
182
319
|
## 🤝 Contributing
|
|
183
320
|
|
|
184
321
|
Contributions are welcome! Please check out the [contribution guide](/CONTRIBUTING.md).
|
|
185
322
|
|
|
186
|
-
<details>
|
|
187
|
-
<summary>Local development</summary>
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
# Install dependencies
|
|
191
|
-
bun install
|
|
192
|
-
|
|
193
|
-
# Generate type stubs
|
|
194
|
-
bun run dev:prepare
|
|
195
|
-
|
|
196
|
-
# Develop with the playground
|
|
197
|
-
bun run dev
|
|
198
|
-
|
|
199
|
-
# Build the playground
|
|
200
|
-
bun run dev:build
|
|
201
|
-
|
|
202
|
-
# Run ESLint
|
|
203
|
-
bun run lint
|
|
204
|
-
|
|
205
|
-
# Run Vitest
|
|
206
|
-
bun run test
|
|
207
|
-
bun run test:watch
|
|
208
|
-
|
|
209
|
-
# Release new version
|
|
210
|
-
bun run release
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
</details>
|
|
214
|
-
|
|
215
323
|
## 📝 License
|
|
216
324
|
|
|
217
325
|
[MIT License](./LICENSE)
|
|
@@ -220,13 +328,4 @@ Contributions are welcome! Please check out the [contribution guide](/CONTRIBUTI
|
|
|
220
328
|
|
|
221
329
|
Made with ❤️ by [Cliford Pereira](https://github.com/clifordpereira)
|
|
222
330
|
|
|
223
|
-
<!-- Badges -->
|
|
224
331
|
|
|
225
|
-
[npm-version-src]: https://img.shields.io/npm/v/nuxt-auto-crud/latest.svg?style=flat&colorA=020420&colorB=00DC82
|
|
226
|
-
[npm-version-href]: https://npmjs.com/package/nuxt-auto-crud
|
|
227
|
-
[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-auto-crud.svg?style=flat&colorA=020420&colorB=00DC82
|
|
228
|
-
[npm-downloads-href]: https://npm.chart.dev/nuxt-auto-crud
|
|
229
|
-
[license-src]: https://img.shields.io/npm/l/nuxt-auto-crud.svg?style=flat&colorA=020420&colorB=00DC82
|
|
230
|
-
[license-href]: https://npmjs.com/package/nuxt-auto-crud
|
|
231
|
-
[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
|
|
232
|
-
[nuxt-href]: https://nuxt.com
|
package/dist/module.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
|
|
3
3
|
interface ModuleOptions {
|
|
4
|
-
/**
|
|
5
4
|
/**
|
|
6
5
|
* Path to the database schema file
|
|
7
6
|
* @default 'server/database/schema'
|
|
@@ -12,6 +11,55 @@ interface ModuleOptions {
|
|
|
12
11
|
* @default 'server/utils/drizzle'
|
|
13
12
|
*/
|
|
14
13
|
drizzlePath?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Authentication configuration
|
|
16
|
+
*/
|
|
17
|
+
auth?: {
|
|
18
|
+
/**
|
|
19
|
+
* Authentication type
|
|
20
|
+
* @default 'session'
|
|
21
|
+
*/
|
|
22
|
+
type?: 'session' | 'jwt';
|
|
23
|
+
/**
|
|
24
|
+
* JWT Secret (required if type is 'jwt')
|
|
25
|
+
*/
|
|
26
|
+
jwtSecret?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Enable authentication checks (requires nuxt-auth-utils for session)
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
enabled: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Enable authorization checks (requires nuxt-authorization)
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
authorization?: boolean;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Resource-specific configuration
|
|
40
|
+
* Define public access and column visibility
|
|
41
|
+
*/
|
|
42
|
+
resources?: {
|
|
43
|
+
[modelName: string]: {
|
|
44
|
+
/**
|
|
45
|
+
* Actions allowed without authentication
|
|
46
|
+
* true = all actions
|
|
47
|
+
* array = specific actions ('list', 'create', 'read', 'update', 'delete')
|
|
48
|
+
*/
|
|
49
|
+
public?: boolean | ('list' | 'create' | 'read' | 'update' | 'delete')[];
|
|
50
|
+
/**
|
|
51
|
+
* Columns to return for unauthenticated requests
|
|
52
|
+
* If not specified, all columns (except hidden ones) are returned
|
|
53
|
+
*/
|
|
54
|
+
publicColumns?: string[];
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
declare module '@nuxt/schema' {
|
|
60
|
+
interface RuntimeConfig {
|
|
61
|
+
autoCrud: ModuleOptions;
|
|
62
|
+
}
|
|
15
63
|
}
|
|
16
64
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
17
65
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -9,7 +9,7 @@ const module$1 = defineNuxtModule({
|
|
|
9
9
|
schemaPath: "server/database/schema",
|
|
10
10
|
drizzlePath: "server/utils/drizzle"
|
|
11
11
|
},
|
|
12
|
-
setup(options, nuxt) {
|
|
12
|
+
async setup(options, nuxt) {
|
|
13
13
|
const resolver = createResolver(import.meta.url);
|
|
14
14
|
const schemaPath = resolver.resolve(
|
|
15
15
|
nuxt.options.rootDir,
|
|
@@ -21,6 +21,29 @@ const module$1 = defineNuxtModule({
|
|
|
21
21
|
options.drizzlePath
|
|
22
22
|
);
|
|
23
23
|
nuxt.options.alias["#site/drizzle"] = drizzlePath;
|
|
24
|
+
nuxt.options.alias["#authorization"] = nuxt.options.alias["#authorization"] || "nuxt-authorization/utils";
|
|
25
|
+
const { loadConfig } = await import('c12');
|
|
26
|
+
const { config: externalConfig } = await loadConfig({
|
|
27
|
+
name: "autocrud",
|
|
28
|
+
cwd: nuxt.options.rootDir
|
|
29
|
+
});
|
|
30
|
+
const mergedAuth = {
|
|
31
|
+
...externalConfig?.auth,
|
|
32
|
+
...options.auth
|
|
33
|
+
};
|
|
34
|
+
const mergedResources = {
|
|
35
|
+
...externalConfig?.resources,
|
|
36
|
+
...options.resources
|
|
37
|
+
};
|
|
38
|
+
nuxt.options.runtimeConfig.autoCrud = {
|
|
39
|
+
auth: {
|
|
40
|
+
enabled: mergedAuth.enabled ?? false,
|
|
41
|
+
authorization: mergedAuth.authorization ?? false,
|
|
42
|
+
type: mergedAuth.type ?? "session",
|
|
43
|
+
jwtSecret: mergedAuth.jwtSecret
|
|
44
|
+
},
|
|
45
|
+
resources: mergedResources || {}
|
|
46
|
+
};
|
|
24
47
|
const apiDir = resolver.resolve("./runtime/server/api");
|
|
25
48
|
addServerHandler({
|
|
26
49
|
route: "/api/:model",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Record<string, unknown>>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { eventHandler, getRouterParams, createError } from "h3";
|
|
2
2
|
import { eq } from "drizzle-orm";
|
|
3
|
-
import { getTableForModel, getModelSingularName } from "../../utils/modelMapper.js";
|
|
3
|
+
import { getTableForModel, getModelSingularName, filterHiddenFields, filterPublicColumns } from "../../utils/modelMapper.js";
|
|
4
4
|
import { useDrizzle } from "#site/drizzle";
|
|
5
|
+
import { useAutoCrudConfig } from "../../utils/config.js";
|
|
6
|
+
import { checkAdminAccess } from "../../utils/auth.js";
|
|
5
7
|
export default eventHandler(async (event) => {
|
|
8
|
+
const { resources } = useAutoCrudConfig();
|
|
6
9
|
const { model, id } = getRouterParams(event);
|
|
10
|
+
const isAdmin = await checkAdminAccess(event, model, "delete");
|
|
11
|
+
if (!isAdmin) {
|
|
12
|
+
const resourceConfig = resources?.[model];
|
|
13
|
+
const isPublic = resourceConfig?.public === true || Array.isArray(resourceConfig?.public) && resourceConfig.public.includes("delete");
|
|
14
|
+
if (!isPublic) {
|
|
15
|
+
throw createError({
|
|
16
|
+
statusCode: 401,
|
|
17
|
+
message: "Unauthorized"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
7
21
|
const table = getTableForModel(model);
|
|
8
22
|
const singularName = getModelSingularName(model);
|
|
9
23
|
const deletedRecord = await useDrizzle().delete(table).where(eq(table.id, Number(id))).returning().get();
|
|
@@ -13,5 +27,9 @@ export default eventHandler(async (event) => {
|
|
|
13
27
|
message: `${singularName} not found`
|
|
14
28
|
});
|
|
15
29
|
}
|
|
16
|
-
|
|
30
|
+
if (isAdmin) {
|
|
31
|
+
return filterHiddenFields(model, deletedRecord);
|
|
32
|
+
} else {
|
|
33
|
+
return filterPublicColumns(model, deletedRecord);
|
|
34
|
+
}
|
|
17
35
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Record<string, unknown>>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
import { eventHandler, getRouterParams, createError } from "h3";
|
|
2
2
|
import { eq } from "drizzle-orm";
|
|
3
|
-
import { getTableForModel,
|
|
3
|
+
import { getTableForModel, filterHiddenFields, filterPublicColumns } from "../../utils/modelMapper.js";
|
|
4
4
|
import { useDrizzle } from "#site/drizzle";
|
|
5
|
+
import { useAutoCrudConfig } from "../../utils/config.js";
|
|
6
|
+
import { checkAdminAccess } from "../../utils/auth.js";
|
|
5
7
|
export default eventHandler(async (event) => {
|
|
8
|
+
const { resources } = useAutoCrudConfig();
|
|
6
9
|
const { model, id } = getRouterParams(event);
|
|
10
|
+
const isAdmin = await checkAdminAccess(event, model, "read");
|
|
11
|
+
if (!isAdmin) {
|
|
12
|
+
const resourceConfig = resources?.[model];
|
|
13
|
+
const isPublic = resourceConfig?.public === true || Array.isArray(resourceConfig?.public) && resourceConfig.public.includes("read");
|
|
14
|
+
if (!isPublic) {
|
|
15
|
+
throw createError({
|
|
16
|
+
statusCode: 401,
|
|
17
|
+
message: "Unauthorized"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
7
21
|
const table = getTableForModel(model);
|
|
8
|
-
const singularName = getModelSingularName(model);
|
|
9
22
|
const record = await useDrizzle().select().from(table).where(eq(table.id, Number(id))).get();
|
|
10
23
|
if (!record) {
|
|
11
24
|
throw createError({
|
|
12
25
|
statusCode: 404,
|
|
13
|
-
message:
|
|
26
|
+
message: "Record not found"
|
|
14
27
|
});
|
|
15
28
|
}
|
|
16
|
-
|
|
29
|
+
if (isAdmin) {
|
|
30
|
+
return filterHiddenFields(model, record);
|
|
31
|
+
} else {
|
|
32
|
+
return filterPublicColumns(model, record);
|
|
33
|
+
}
|
|
17
34
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Record<string, unknown>>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,12 +1,36 @@
|
|
|
1
|
-
import { eventHandler, getRouterParams, readBody } from "h3";
|
|
1
|
+
import { eventHandler, getRouterParams, readBody, createError } from "h3";
|
|
2
2
|
import { eq } from "drizzle-orm";
|
|
3
|
-
import { getTableForModel, filterUpdatableFields } from "../../utils/modelMapper.js";
|
|
3
|
+
import { getTableForModel, filterUpdatableFields, filterHiddenFields, filterPublicColumns } from "../../utils/modelMapper.js";
|
|
4
4
|
import { useDrizzle } from "#site/drizzle";
|
|
5
|
+
import { useAutoCrudConfig } from "../../utils/config.js";
|
|
6
|
+
import { checkAdminAccess } from "../../utils/auth.js";
|
|
5
7
|
export default eventHandler(async (event) => {
|
|
8
|
+
const { resources } = useAutoCrudConfig();
|
|
6
9
|
const { model, id } = getRouterParams(event);
|
|
10
|
+
const isAdmin = await checkAdminAccess(event, model, "update");
|
|
11
|
+
if (!isAdmin) {
|
|
12
|
+
const resourceConfig = resources?.[model];
|
|
13
|
+
const isPublic = resourceConfig?.public === true || Array.isArray(resourceConfig?.public) && resourceConfig.public.includes("update");
|
|
14
|
+
if (!isPublic) {
|
|
15
|
+
throw createError({
|
|
16
|
+
statusCode: 401,
|
|
17
|
+
message: "Unauthorized"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
7
21
|
const table = getTableForModel(model);
|
|
8
22
|
const body = await readBody(event);
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
23
|
+
const payload = filterUpdatableFields(model, body);
|
|
24
|
+
const updatedRecord = await useDrizzle().update(table).set(payload).where(eq(table.id, Number(id))).returning().get();
|
|
25
|
+
if (!updatedRecord) {
|
|
26
|
+
throw createError({
|
|
27
|
+
statusCode: 404,
|
|
28
|
+
message: "Record not found"
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (isAdmin) {
|
|
32
|
+
return filterHiddenFields(model, updatedRecord);
|
|
33
|
+
} else {
|
|
34
|
+
return filterPublicColumns(model, updatedRecord);
|
|
35
|
+
}
|
|
12
36
|
});
|
|
@@ -1,9 +1,30 @@
|
|
|
1
|
-
import { eventHandler, getRouterParams } from "h3";
|
|
2
|
-
import { getTableForModel } from "../../utils/modelMapper.js";
|
|
1
|
+
import { eventHandler, getRouterParams, createError } from "h3";
|
|
2
|
+
import { getTableForModel, filterHiddenFields, filterPublicColumns } from "../../utils/modelMapper.js";
|
|
3
3
|
import { useDrizzle } from "#site/drizzle";
|
|
4
|
+
import { useAutoCrudConfig } from "../../utils/config.js";
|
|
5
|
+
import { checkAdminAccess } from "../../utils/auth.js";
|
|
4
6
|
export default eventHandler(async (event) => {
|
|
7
|
+
console.log("[GET] Request received", event.path);
|
|
8
|
+
const { resources } = useAutoCrudConfig();
|
|
5
9
|
const { model } = getRouterParams(event);
|
|
10
|
+
const isAdmin = await checkAdminAccess(event, model, "list");
|
|
11
|
+
if (!isAdmin) {
|
|
12
|
+
const resourceConfig = resources?.[model];
|
|
13
|
+
const isPublic = resourceConfig?.public === true || Array.isArray(resourceConfig?.public) && resourceConfig.public.includes("list");
|
|
14
|
+
if (!isPublic) {
|
|
15
|
+
throw createError({
|
|
16
|
+
statusCode: 401,
|
|
17
|
+
message: "Unauthorized"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
6
21
|
const table = getTableForModel(model);
|
|
7
|
-
const
|
|
8
|
-
return
|
|
22
|
+
const results = await useDrizzle().select().from(table).all();
|
|
23
|
+
return results.map((item) => {
|
|
24
|
+
if (isAdmin) {
|
|
25
|
+
return filterHiddenFields(model, item);
|
|
26
|
+
} else {
|
|
27
|
+
return filterPublicColumns(model, item);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
9
30
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Record<string, unknown>>>;
|
|
2
2
|
export default _default;
|