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.
Files changed (31) hide show
  1. package/README.md +189 -90
  2. package/dist/module.d.mts +49 -1
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +24 -1
  5. package/dist/runtime/server/api/[model]/[id].delete.d.ts +1 -1
  6. package/dist/runtime/server/api/[model]/[id].delete.js +20 -2
  7. package/dist/runtime/server/api/[model]/[id].get.d.ts +1 -1
  8. package/dist/runtime/server/api/[model]/[id].get.js +21 -4
  9. package/dist/runtime/server/api/[model]/[id].patch.d.ts +1 -1
  10. package/dist/runtime/server/api/[model]/[id].patch.js +29 -5
  11. package/dist/runtime/server/api/[model]/index.get.js +25 -4
  12. package/dist/runtime/server/api/[model]/index.post.d.ts +1 -1
  13. package/dist/runtime/server/api/[model]/index.post.js +23 -8
  14. package/dist/runtime/server/utils/auth.d.ts +2 -0
  15. package/dist/runtime/server/utils/auth.js +39 -0
  16. package/dist/runtime/server/utils/config.d.ts +2 -0
  17. package/dist/runtime/server/utils/config.js +4 -0
  18. package/dist/runtime/server/utils/jwt.d.ts +2 -0
  19. package/dist/runtime/server/utils/jwt.js +19 -0
  20. package/dist/runtime/server/utils/modelMapper.d.ts +31 -0
  21. package/dist/runtime/server/utils/modelMapper.js +38 -0
  22. package/package.json +20 -10
  23. package/src/runtime/server/api/[model]/[id].delete.ts +29 -3
  24. package/src/runtime/server/api/[model]/[id].get.ts +29 -5
  25. package/src/runtime/server/api/[model]/[id].patch.ts +40 -9
  26. package/src/runtime/server/api/[model]/index.get.ts +33 -5
  27. package/src/runtime/server/api/[model]/index.post.ts +32 -15
  28. package/src/runtime/server/utils/auth.ts +55 -0
  29. package/src/runtime/server/utils/config.ts +6 -0
  30. package/src/runtime/server/utils/jwt.ts +23 -0
  31. 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
- Auto-generate RESTful CRUD APIs for your Nuxt app based solely on your database schema. No configuration needed!
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
- ## Features
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
- - 🔄 **Auto-Detection** - Automatically detects all tables from your Drizzle schema
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
- ## 📦 Quick Setup
22
+ ### New Project (Recommended)
23
23
 
24
- ### 1. Install the module
24
+ Start a new project with everything pre-configured using our template:
25
25
 
26
26
  ```bash
27
- bun add nuxt-auto-crud
28
- # or
29
- npm install nuxt-auto-crud
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. Add to your Nuxt config
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: ["@nuxthub/core", "nuxt-auto-crud"],
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: "server/database/schema", // default value
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
- ### 3. Define your database schema
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 "drizzle-orm/sqlite-core";
54
-
55
- export const users = sqliteTable("users", {
56
- id: integer("id").primaryKey({ autoIncrement: true }),
57
- name: text("name").notNull(),
58
- email: text("email").notNull().unique(),
59
- bio: text("bio"),
60
- createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
61
- () => new Date()
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
- export const posts = sqliteTable("posts", {
66
- id: integer("id").primaryKey({ autoIncrement: true }),
67
- title: text("title").notNull(),
68
- content: text("content").notNull(),
69
- published: integer("published", { mode: "boolean" }).default(false),
70
- authorId: integer("author_id").references(() => users.id),
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: "John Doe",
116
- email: "john@example.com",
117
- bio: "Software developer",
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
- ## ⚙️ Configuration
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
- - NuxtHub (for database functionality)
180
- - Drizzle ORM
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-auto-crud",
3
3
  "configKey": "autoCrud",
4
- "version": "1.2.2",
4
+ "version": "1.4.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
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<any>>;
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
- return deletedRecord;
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<any>>;
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, getModelSingularName } from "../../utils/modelMapper.js";
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: `${singularName} not found`
26
+ message: "Record not found"
14
27
  });
15
28
  }
16
- return record;
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<any>>;
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 updateData = filterUpdatableFields(model, body);
10
- const record = await useDrizzle().update(table).set(updateData).where(eq(table.id, Number(id))).returning().get();
11
- return record;
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 records = await useDrizzle().select().from(table).all();
8
- return records;
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<any>>;
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Record<string, unknown>>>;
2
2
  export default _default;