nuxt-auto-crud 1.9.0 → 1.11.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 CHANGED
@@ -10,14 +10,14 @@ The main objective of this module is to **expose CRUD APIs without the need for
10
10
  You don't need to setup an extra server or database to create an MVP of an application. The Nuxt (Nitro) server and SQLite can save you time and money.
11
11
  And you don't need a separate Strapi or Supabase setup to automate your CRUD process. `nuxt-auto-crud` will help you with that and accelerate your development exponentially.
12
12
 
13
- While we provide a playground with a CMS-like interface, this is primarily to demonstrate the capabilities. You are expected to build your own frontend application to consume these APIs.
13
+ While this module exposes CRUD APIs, you are expected to build your own frontend application to consume them.
14
14
 
15
15
  - [✨ Release Notes](/CHANGELOG.md)
16
16
  - [🎮 Try the Playground](/playground)
17
17
 
18
18
  ## 🚀 CRUD APIs are ready to use without code
19
19
 
20
- Once installed, your database tables automatically become API endpoints:
20
+ Once installed, your database tables' CRUD APIs are exposed in a controlled manner:
21
21
 
22
22
  - `GET /api/:model` - List all records
23
23
  - `POST /api/:model` - Create a new record
@@ -41,7 +41,7 @@ bun run dev
41
41
 
42
42
  **Template Usage Modes:**
43
43
 
44
- 1. **Fullstack App**: The template includes the `nuxt-auto-crud` module, providing both the backend APIs and the frontend UI.
44
+ 1. **Fullstack App**: The template includes the `nuxt-auto-crud` module, providing both the backend APIs and the frontend UI. [Watch Demo](https://youtu.be/M9-koXmhB9k)
45
45
  2. **Frontend Only**: You can use the template just for the frontend. In this case, you don't need to install the module in the frontend app. Instead, you would install `nuxt-auto-crud` in a separate backend setup (e.g., another Nuxt project acting as the API).
46
46
 
47
47
  Detailed instructions can be found in [https://auto-crud.clifland.in/](https://auto-crud.clifland.in/)
@@ -78,8 +78,13 @@ export default defineNuxtConfig({
78
78
  },
79
79
 
80
80
  autoCrud: {
81
- schemaPath: 'server/database/schema', // default value
82
- auth: false, // Disable auth by default for easy testing
81
+ schemaPath: 'server/database/schema',
82
+ // auth: false,
83
+ auth: {
84
+ type: 'session', // for Normal Authentication with nuxt-auth-utils
85
+ authentication: true,
86
+ authorization: true,
87
+ },
83
88
  },
84
89
  })
85
90
  ```
@@ -147,9 +152,6 @@ export const users = sqliteTable('users', {
147
152
  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
148
153
  })
149
154
  ```
150
-
151
- > **Note:** The `organization.ts` and `cms.ts` files you might see in the playground are just examples and are commented out by default. You should implement a robust schema tailored to your production needs.
152
-
153
155
  #### Run the project
154
156
 
155
157
  ```bash
@@ -158,7 +160,45 @@ bun db:generate
158
160
  bun run dev
159
161
  ```
160
162
 
161
- That's it! 🎉 Your CRUD APIs are now available at `/api/users`.
163
+ That's it! 🎉 Your CRUD APIs are now available at `/api/users`.
164
+
165
+
166
+ #### Adding New Schemas
167
+
168
+ To add a new table (e.g., `posts`), simply create a new file in your schema directory:
169
+
170
+ ```typescript
171
+ // server/database/schema/posts.ts
172
+ import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
173
+ import { users } from './users'
174
+
175
+ export const posts = sqliteTable('posts', {
176
+ id: integer('id').primaryKey({ autoIncrement: true }),
177
+ title: text('title').notNull(),
178
+ content: text('content').notNull(),
179
+ authorId: integer('author_id').references(() => users.id),
180
+ createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
181
+ })
182
+ ```
183
+
184
+ Then, ensure it is exported in your `server/database/schema/index.ts` (if you are using an index file) or that your `drizzle.config.ts` is pointing to the correct location.
185
+
186
+ ```typescript
187
+ // server/database/schema/index.ts
188
+ export * from './users'
189
+ export * from './posts'
190
+ ```
191
+
192
+ After adding the file, run the generation script:
193
+
194
+ ```bash
195
+ bun db:generate
196
+ ```
197
+
198
+ The new API endpoints (e.g., `/api/posts`) will be automatically available. [Watch Demo](https://youtu.be/7gW0KW1KtN0)
199
+
200
+
201
+ > **Note:** The `organization.ts` and `cms.ts` files you might see in the playground are just examples and are commented out by default. You should implement a robust schema tailored to your production needs.
162
202
 
163
203
  ### 3. Backend-only App (API Mode)
164
204
 
@@ -166,18 +206,42 @@ If you are using Nuxt as a backend for a separate client application (e.g., mobi
166
206
 
167
207
  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.
168
208
 
169
- ```ts
209
+ ```typescript
210
+ // nuxt.config.ts
170
211
  export default defineNuxtConfig({
171
212
  modules: ['nuxt-auto-crud'],
172
213
  autoCrud: {
173
- auth: false // APIs are public (or handled by your own middleware)
174
- }
214
+ schemaPath: 'server/database/schema',
215
+ // auth: false, // Uncomment this line for testing APIs without auth
216
+ auth: {
217
+ type: 'jwt', // for app providing backend apis only
218
+ authentication: true,
219
+ authorization: true,
220
+ jwtSecret: process.env.NUXT_JWT_SECRET || 'test-secret-key-123',
221
+ },
222
+ },
223
+ })
224
+ ```
225
+
226
+ **Note:** Remember to add your `NUXT_JWT_SECRET` in `.env`.
227
+
228
+ You should also configure `drizzle.config.ts` correctly:
229
+
230
+ ```typescript
231
+ // drizzle.config.ts
232
+ import { defineConfig } from 'drizzle-kit'
233
+
234
+ export default defineConfig({
235
+ dialect: 'sqlite',
236
+ schema: './server/database/schema/index.ts',
237
+ out: './server/database/migrations',
238
+ tablesFilter: ['!_hub_migrations'],
175
239
  })
176
240
  ```
177
241
 
178
242
  ## 🔐 Authentication Configuration
179
243
 
180
- The module supports `auth: false` by default, which exposes all LCRUD APIs. You can enable authentication and authorization as needed.
244
+ The module enables authentication by default. To test APIs without authentication, you can set `auth: false`.
181
245
 
182
246
  ### Session Auth (Default)
183
247
 
@@ -301,22 +365,28 @@ const updated = await $fetch("/api/users/1", {
301
365
  ```typescript
302
366
  await $fetch("/api/users/1", {
303
367
  method: "DELETE",
304
- headers: {
305
- // If auth is enabled
306
- Authorization: 'Bearer ...'
307
- }
308
368
  });
309
369
  ```
310
370
 
371
+ > **Note:** If authentication is enabled (default):
372
+ > - **Fullstack App:** The module integrates with `nuxt-auth-utils`, so session cookies are handled automatically.
373
+ > - **Backend-only App:** You must include the `Authorization: Bearer <token>` header in your requests.
374
+
311
375
  ## Configuration
312
376
 
313
377
  ### Module Options
314
378
 
315
379
  ```typescript
380
+
316
381
  export default defineNuxtConfig({
317
382
  autoCrud: {
318
383
  // Path to your database schema file (relative to project root)
319
384
  schemaPath: "server/database/schema", // default
385
+
386
+ // Authentication configuration (see "Authentication Configuration" section)
387
+ auth: {
388
+ // ...
389
+ }
320
390
  },
321
391
  });
322
392
  ```
@@ -328,6 +398,8 @@ By default, the following fields are protected from updates:
328
398
  - `id`
329
399
  - `createdAt`
330
400
  - `created_at`
401
+ - `updatedAt`
402
+ - `updated_at`
331
403
 
332
404
  You can customize updatable fields in your schema by modifying the `modelMapper.ts` utility.
333
405
 
@@ -347,6 +419,16 @@ You can customize hidden fields by modifying the `modelMapper.ts` utility.
347
419
  - Drizzle ORM (SQLite)
348
420
  - NuxtHub (Recommended) or [Custom SQLite Setup](./custom-setup.md)
349
421
 
422
+ ## 🔗 Other Helpful Links
423
+
424
+ - **Template:** [https://github.com/clifordpereira/nuxt-auto-crud_template](https://github.com/clifordpereira/nuxt-auto-crud_template)
425
+ - **Docs:** [https://auto-crud.clifland.in/](https://auto-crud.clifland.in/)
426
+ - **Repo:** [https://github.com/clifordpereira/nuxt-auto-crud](https://github.com/clifordpereira/nuxt-auto-crud)
427
+ - **YouTube:** [https://youtu.be/M9-koXmhB9k](https://youtu.be/M9-koXmhB9k)
428
+ - **YouTube 2:** [https://youtu.be/7gW0KW1KtN0](https://youtu.be/7gW0KW1KtN0)
429
+ - **npm:** [https://www.npmjs.com/package/nuxt-auto-crud](https://www.npmjs.com/package/nuxt-auto-crud)
430
+ - **Discuss:** [https://discord.gg/hGgyEaGu](https://discord.gg/hGgyEaGu)
431
+
350
432
  ## 🤝 Contributing
351
433
 
352
434
  Contributions are welcome! Please check out the [contribution guide](/CONTRIBUTING.md).
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-auto-crud",
3
3
  "configKey": "autoCrud",
4
- "version": "1.9.0",
4
+ "version": "1.11.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -4,7 +4,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
4
4
  name: string;
5
5
  type: string;
6
6
  required: any;
7
- selectOptions: undefined;
7
+ selectOptions: string[] | undefined;
8
8
  }[];
9
9
  }>>;
10
10
  export default _default;
@@ -4,7 +4,7 @@ export declare function drizzleTableToFields(table: any, resourceName: string):
4
4
  name: string;
5
5
  type: string;
6
6
  required: any;
7
- selectOptions: undefined;
7
+ selectOptions: string[] | undefined;
8
8
  }[];
9
9
  };
10
10
  export declare function getRelations(): Promise<Record<string, Record<string, string>>>;
@@ -15,6 +15,6 @@ export declare function getSchema(tableName: string): Promise<{
15
15
  name: string;
16
16
  type: string;
17
17
  required: any;
18
- selectOptions: undefined;
18
+ selectOptions: string[] | undefined;
19
19
  }[];
20
20
  } | undefined>;
@@ -8,8 +8,12 @@ export function drizzleTableToFields(table, resourceName) {
8
8
  const column = col;
9
9
  const isRequired = column.notNull;
10
10
  let type = "string";
11
- const selectOptions = void 0;
12
- if (column.dataType === "number" || column.columnType === "SQLiteInteger" || column.columnType === "SQLiteReal") {
11
+ let selectOptions = void 0;
12
+ const enumValues = column.enumValues || column.config?.enumValues;
13
+ if (enumValues) {
14
+ type = "enum";
15
+ selectOptions = enumValues;
16
+ } else if (column.dataType === "number" || column.columnType === "SQLiteInteger" || column.columnType === "SQLiteReal") {
13
17
  type = "number";
14
18
  if (column.name.endsWith("_at") || column.name.endsWith("At")) {
15
19
  type = "date";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auto-crud",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "Exposes RESTful CRUD APIs for your Nuxt app based solely on your database migrations.",
5
5
  "author": "Cliford Pereira",
6
6
  "license": "MIT",
@@ -12,10 +12,17 @@ export function drizzleTableToFields(table: any, resourceName: string) {
12
12
  const column = col as any
13
13
  const isRequired = column.notNull
14
14
  let type = 'string'
15
- const selectOptions: string[] | undefined = undefined
15
+ let selectOptions: string[] | undefined = undefined
16
16
 
17
+ // Check for enum values (Drizzle stores them in enumValues or config.enumValues)
18
+ const enumValues = column.enumValues || column.config?.enumValues
19
+
20
+ if (enumValues) {
21
+ type = 'enum'
22
+ selectOptions = enumValues
23
+ }
17
24
  // Map Drizzle types to frontend types
18
- if (column.dataType === 'number' || column.columnType === 'SQLiteInteger' || column.columnType === 'SQLiteReal') {
25
+ else if (column.dataType === 'number' || column.columnType === 'SQLiteInteger' || column.columnType === 'SQLiteReal') {
19
26
  type = 'number'
20
27
  // Check if it is a timestamp
21
28
  if (column.name.endsWith('_at') || column.name.endsWith('At')) {