hono-crud 0.13.3 → 0.13.4

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 (89) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/README.md +15 -416
  3. package/dist/audit/index.d.ts +2 -2
  4. package/dist/audit/index.js +1 -1
  5. package/dist/auth/index.d.ts +4 -677
  6. package/dist/auth/index.js +1 -1
  7. package/dist/chunk-25YGWSRQ.js +11 -0
  8. package/dist/chunk-3UHAENW7.js +1 -0
  9. package/dist/chunk-6EYS3CNV.js +1 -0
  10. package/dist/chunk-CTU6AAXM.js +1 -0
  11. package/dist/{chunk-QRXEQTNE.js → chunk-DZ3EM3AE.js} +1 -1
  12. package/dist/chunk-NMK4MUR3.js +1 -0
  13. package/dist/chunk-PDHKGPGZ.js +1 -0
  14. package/dist/{chunk-PCPU5A2Q.js → chunk-Q373HVMW.js} +1 -1
  15. package/dist/chunk-RO5IUV4O.js +1 -0
  16. package/dist/chunk-RU3RY5SC.js +1 -0
  17. package/dist/chunk-VTIGDVUR.js +1 -0
  18. package/dist/chunk-YM6W23MT.js +1 -0
  19. package/dist/{emitter-vW4MflrJ.d.ts → emitter-BgVwpiRd.d.ts} +50 -2
  20. package/dist/encryption/index.js +1 -1
  21. package/dist/events/index.d.ts +2 -4
  22. package/dist/events/index.js +1 -1
  23. package/dist/index-_ymQzFJo.d.ts +764 -0
  24. package/dist/index.d.ts +4333 -274
  25. package/dist/index.js +1 -2
  26. package/dist/internal.d.ts +65 -0
  27. package/dist/internal.js +1 -0
  28. package/dist/logging/index.d.ts +2 -2
  29. package/dist/logging/index.js +1 -1
  30. package/dist/serialization/index.d.ts +1 -1
  31. package/dist/serialization/index.js +1 -1
  32. package/dist/storage/index.d.ts +5 -72
  33. package/dist/storage/index.js +1 -1
  34. package/dist/{types-Dfi9RdjS.d.ts → types-38Hj6wN4.d.ts} +2 -2
  35. package/dist/{types-SnlsH9UT.d.ts → types-CpinG1az.d.ts} +1 -1
  36. package/dist/{types-B5wq2iKZ.d.ts → types-DcRAcexC.d.ts} +1 -1
  37. package/dist/versioning/index.d.ts +2 -2
  38. package/dist/versioning/index.js +1 -1
  39. package/package.json +15 -99
  40. package/dist/adapters/drizzle/index.d.ts +0 -1004
  41. package/dist/adapters/drizzle/index.js +0 -1
  42. package/dist/adapters/memory/index.d.ts +0 -373
  43. package/dist/adapters/memory/index.js +0 -1
  44. package/dist/adapters/prisma/index.d.ts +0 -450
  45. package/dist/adapters/prisma/index.js +0 -1
  46. package/dist/bulk-patch-DC4NS656.d.ts +0 -57
  47. package/dist/cache/index.d.ts +0 -488
  48. package/dist/cache/index.js +0 -1
  49. package/dist/chunk-2M5BM4VD.js +0 -1
  50. package/dist/chunk-7DDNX2F2.js +0 -1
  51. package/dist/chunk-7ZUZICKI.js +0 -1
  52. package/dist/chunk-BJTWQHEV.js +0 -0
  53. package/dist/chunk-CCGZ5UPB.js +0 -0
  54. package/dist/chunk-EWKQ6BPV.js +0 -33
  55. package/dist/chunk-FJCWFB5L.js +0 -1
  56. package/dist/chunk-FXIMMYFV.js +0 -1
  57. package/dist/chunk-GBQQ3YQX.js +0 -1
  58. package/dist/chunk-GF2EC5G4.js +0 -1
  59. package/dist/chunk-H3H65KZF.js +0 -1
  60. package/dist/chunk-HRAGVQWS.js +0 -4
  61. package/dist/chunk-IPMPKM4J.js +0 -1
  62. package/dist/chunk-KUFOENSK.js +0 -1
  63. package/dist/chunk-NGUMNUOP.js +0 -1
  64. package/dist/chunk-QXFY6NYI.js +0 -1
  65. package/dist/chunk-R3WESU6C.js +0 -1
  66. package/dist/chunk-SDNXN7M5.js +0 -1
  67. package/dist/chunk-SPICOFUM.js +0 -84
  68. package/dist/chunk-UU7V63VS.js +0 -1
  69. package/dist/chunk-V4YEHNEZ.js +0 -11
  70. package/dist/chunk-XH7DEPW2.js +0 -1
  71. package/dist/chunk-XI7HT5ZM.js +0 -1
  72. package/dist/chunk-ZAVXHUKP.js +0 -1
  73. package/dist/exceptions-BEvDdXFC.d.ts +0 -70
  74. package/dist/health/index.d.ts +0 -103
  75. package/dist/health/index.js +0 -1
  76. package/dist/idempotency/index.d.ts +0 -80
  77. package/dist/idempotency/index.js +0 -1
  78. package/dist/import-Gx0ZUJjI.d.ts +0 -3183
  79. package/dist/index-B1QEfh5v.d.ts +0 -812
  80. package/dist/rate-limit/index.d.ts +0 -386
  81. package/dist/rate-limit/index.js +0 -1
  82. package/dist/route-UXFfftVm.d.ts +0 -94
  83. package/dist/types-BNui1SQl.d.ts +0 -89
  84. package/dist/types-BdRvpp1z.d.ts +0 -141
  85. package/dist/types-Bjef1r9u.d.ts +0 -236
  86. package/dist/types-rJSyOxkJ.d.ts +0 -50
  87. package/dist/ui-CNJUoCg1.d.ts +0 -148
  88. package/dist/ui.d.ts +0 -2
  89. package/dist/ui.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 6c22eaa: Restructure the project into a pnpm-workspaces monorepo. `hono-crud` is now the thin core; the database adapters, documentation UIs, and optional middleware ship as separate installable packages under the `@hono-crud/*` scope:
8
+
9
+ - `@hono-crud/memory`, `@hono-crud/drizzle`, `@hono-crud/prisma` — CRUD adapters (was `hono-crud/adapters/*`)
10
+ - `@hono-crud/swagger`, `@hono-crud/scalar` — documentation UIs (was exported from the `hono-crud` barrel / `hono-crud/ui`)
11
+ - `@hono-crud/cache`, `@hono-crud/rate-limit`, `@hono-crud/idempotency`, `@hono-crud/health` — optional middleware (was `hono-crud/{cache,rate-limit,idempotency,health}`)
12
+
13
+ Breaking: these symbols are no longer re-exported from `hono-crud`; install the corresponding `@hono-crud/*` package and import from it. The unified `createCrudMiddleware`, `HonoCrudEnv`, and `StorageEnv` no longer cover cache/rate-limit/idempotency — compose those packages' own middleware instead. A `hono-crud/internal` entrypoint is available for authoring adapters.
14
+
3
15
  All notable changes to this project will be documented in this file.
4
16
 
5
17
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
@@ -18,15 +30,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
18
30
  %b
19
31
  %b
20
32
  %b
33
+
21
34
  ## [0.8.0] — 2026-05-03
22
35
 
23
36
  ### Added
37
+
24
38
  - `middlewares?: MiddlewareHandler[]` slot on every per-endpoint config in `EndpointsConfig<M>` (`create`, `list`, `read`, `update`, `delete`, `search`, `aggregate`, `restore`, `batchCreate`, `batchUpdate`, `batchDelete`, `batchRestore`, `batchUpsert`, `export`, `import`, `upsert`, `clone`). Middleware listed here runs before the endpoint handler. The existing `RegisterCrudOptions.endpointMiddlewares` continues to work and overrides config-API middlewares for the same verb. Coverage: `tests/per-endpoint-middlewares.test.ts`.
25
39
 
26
40
  ### Fixed
41
+
27
42
  - `HonoOpenAPIHandler.registerRoute` was passing the OpenAPI-style path (`/widgets/{id}`) to `app.use(...)` for per-route middleware. Hono's `use` expects the route-syntax form (`/widgets/:id`), so middleware on dynamic-segment routes (e.g., `delete`, `read`, `update`, `restore`, `clone`) silently never fired. The fix passes the raw path to `app.use(...)` and keeps the OpenAPI conversion only for `createRoute({ path })`. This unblocks both the new config-API `middlewares` slot and the existing `RegisterCrudOptions.endpointMiddlewares` option on `:id` routes.
28
43
 
29
44
  ### Compatibility
45
+
30
46
  - Additive. Existing consumers see no behaviour change other than the bugfix above (middleware that previously was silently dropped on `:id` routes will now run as documented).
31
47
 
32
48
  %b
@@ -47,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
47
63
  %b
48
64
  %b
49
65
  %b
66
+
50
67
  ## [0.1.0] - 2025-01-29
51
68
 
52
69
  ### Added
@@ -67,7 +84,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
67
84
  - Edge runtime support (Cloudflare Workers, Deno, Bun, Node.js)
68
85
 
69
86
  [0.1.0]: https://github.com/ksh-us/hono-crud/releases/tag/v0.1.0
70
-
71
87
  [0.1.1]: https://github.com/ksh-us/hono-crud/compare/v0.0.0...v0.1.1
72
88
  [0.1.2]: https://github.com/ksh-us/hono-crud/compare/v0.1.1...v0.1.2
73
89
  [0.1.3]: https://github.com/ksh-us/hono-crud/compare/v0.1.2...v0.1.3
package/README.md CHANGED
@@ -1,435 +1,34 @@
1
1
  # hono-crud
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/hono-crud.svg)](https://www.npmjs.com/package/hono-crud)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
3
+ CRUD generator for [Hono](https://hono.dev) with Zod validation and OpenAPI generation.
6
4
 
7
- Type-safe CRUD generator for [Hono](https://hono.dev) with Zod validation and automatic OpenAPI documentation.
5
+ Define a model once and register fully-typed Create / Read / Update / Delete / List endpoints. Core also ships auth, logging, events, encryption, serialization, audit, versioning, multi-tenant, and API-versioning helpers. Persistence adapters and docs UIs live in separate `@hono-crud/*` packages.
8
6
 
9
- ## Features
10
-
11
- - **Full CRUD Operations** - Generate Create, Read, Update, Delete, List endpoints with one call
12
- - **OpenAPI/Swagger** - Auto-generated docs with Swagger UI, Scalar, and ReDoc
13
- - **Database Adapters** - Memory (prototyping), Drizzle ORM, and Prisma
14
- - **4 API Patterns** - Class-based, functional, builder, and config-based
15
- - **Zod Validation** - Type-safe request/response validation
16
- - **TypeScript First** - Full type inference and autocompletion
17
- - **Edge Ready** - Works with Cloudflare Workers, Deno, Bun, and Node.js
18
- - **Authentication** - JWT, API Key middleware with role/permission guards
19
- - **Caching** - Response caching with automatic invalidation
20
- - **Rate Limiting** - Fixed/sliding window with tier-based limits
21
- - **Advanced Features** - Soft delete, relations, batch operations, search, versioning, audit logging, and more
22
-
23
- ## Installation
7
+ ## Install
24
8
 
25
9
  ```bash
26
10
  npm install hono-crud hono zod
27
11
  ```
28
12
 
29
- Peer dependencies: `hono >= 4.0.0` and `zod >= 4.0.0` are required.
13
+ You will also want a storage adapter, e.g. `@hono-crud/memory`, `@hono-crud/drizzle`, or `@hono-crud/prisma`.
30
14
 
31
- ## Quick Start
15
+ ## Usage
32
16
 
33
- ```typescript
34
- import { Hono } from 'hono';
17
+ ```ts
35
18
  import { z } from 'zod';
36
- import { fromHono, registerCrud, setupSwaggerUI, defineModel, defineMeta } from 'hono-crud';
37
- import {
38
- MemoryCreateEndpoint,
39
- MemoryReadEndpoint,
40
- MemoryUpdateEndpoint,
41
- MemoryDeleteEndpoint,
42
- MemoryListEndpoint,
43
- } from 'hono-crud/adapters/memory';
44
-
45
- // 1. Define your schema
46
- const UserSchema = z.object({
47
- id: z.uuid(),
48
- email: z.email(),
49
- name: z.string().min(1),
50
- role: z.enum(['admin', 'user']),
51
- });
52
-
53
- // 2. Create model + meta
54
- const UserModel = defineModel({
55
- tableName: 'users',
56
- schema: UserSchema,
57
- primaryKeys: ['id'],
58
- });
59
-
60
- const userMeta = defineMeta({ model: UserModel });
61
-
62
- // 3. Define endpoints
63
- class UserCreate extends MemoryCreateEndpoint {
64
- _meta = userMeta;
65
- schema = { tags: ['Users'], summary: 'Create a user' };
66
- }
19
+ import { fromHono, registerCrud, defineModel, defineMeta } from 'hono-crud';
20
+ import { MemoryCreateEndpoint, MemoryReadEndpoint, MemoryListEndpoint } from '@hono-crud/memory';
67
21
 
68
- class UserList extends MemoryListEndpoint {
69
- _meta = userMeta;
70
- schema = { tags: ['Users'], summary: 'List users' };
71
- filterFields = ['role'];
72
- searchFields = ['name', 'email'];
73
- }
22
+ const UserSchema = z.object({ id: z.string(), name: z.string() });
23
+ const model = defineModel({ schema: UserSchema, primaryKey: 'id' });
24
+ const meta = defineMeta({ tableName: 'users' });
74
25
 
75
- class UserRead extends MemoryReadEndpoint {
76
- _meta = userMeta;
77
- schema = { tags: ['Users'], summary: 'Get a user' };
78
- }
79
-
80
- class UserUpdate extends MemoryUpdateEndpoint {
81
- _meta = userMeta;
82
- schema = { tags: ['Users'], summary: 'Update a user' };
83
- allowedUpdateFields = ['name', 'role'];
84
- }
85
-
86
- class UserDelete extends MemoryDeleteEndpoint {
87
- _meta = userMeta;
88
- schema = { tags: ['Users'], summary: 'Delete a user' };
89
- }
90
-
91
- // 4. Wire it up
92
26
  const app = fromHono(new Hono());
93
-
94
27
  registerCrud(app, '/users', {
95
- create: UserCreate,
96
- list: UserList,
97
- read: UserRead,
98
- update: UserUpdate,
99
- delete: UserDelete,
28
+ model,
29
+ meta,
30
+ endpoints: { create: MemoryCreateEndpoint, read: MemoryReadEndpoint, list: MemoryListEndpoint },
100
31
  });
101
-
102
- // 5. OpenAPI docs
103
- app.doc('/openapi.json', {
104
- openapi: '3.1.0',
105
- info: { title: 'My API', version: '1.0.0' },
106
- });
107
- setupSwaggerUI(app, { docsPath: '/docs', specPath: '/openapi.json' });
108
-
109
- export default app;
110
32
  ```
111
33
 
112
- This generates:
113
-
114
- | Method | Route | Description |
115
- |--------|-------|-------------|
116
- | `POST` | `/users` | Create a user |
117
- | `GET` | `/users` | List users (with filtering, search, pagination) |
118
- | `GET` | `/users/:id` | Get a user by ID |
119
- | `PATCH` | `/users/:id` | Update a user |
120
- | `DELETE` | `/users/:id` | Delete a user |
121
-
122
- ## API Patterns
123
-
124
- hono-crud supports four ways to define endpoints. All produce classes compatible with `registerCrud()` and can be mixed.
125
-
126
- | Pattern | Best For | Style |
127
- |---------|----------|-------|
128
- | **Class-based** | Complex logic, database adapters | `class UserList extends MemoryListEndpoint { ... }` |
129
- | **Functional** | Quick setup | `createList({ meta, filterFields: ['role'] }, MemoryListEndpoint)` |
130
- | **Builder** | Readable chains | `crud(meta).list().filter('role').build(MemoryListEndpoint)` |
131
- | **Config-based** | Declarative, all-in-one | `defineEndpoints({ meta, list: { ... } }, MemoryAdapters)` |
132
-
133
- ```typescript
134
- import { createList, crud, defineEndpoints, MemoryAdapters } from 'hono-crud';
135
-
136
- // Functional
137
- const UserList = createList(
138
- { meta: userMeta, filterFields: ['role'], searchFields: ['name'] },
139
- MemoryListEndpoint
140
- );
141
-
142
- // Builder
143
- const UserList = crud(userMeta)
144
- .list()
145
- .filter('role')
146
- .search('name')
147
- .pagination(20, 100)
148
- .build(MemoryListEndpoint);
149
-
150
- // Config-based (all endpoints at once)
151
- const endpoints = defineEndpoints({
152
- meta: userMeta,
153
- create: { openapi: { tags: ['Users'], summary: 'Create user' } },
154
- list: { filtering: { fields: ['role'] }, search: { fields: ['name'] } },
155
- read: {},
156
- update: { fields: { allowed: ['name', 'role'] } },
157
- delete: {},
158
- }, MemoryAdapters);
159
-
160
- registerCrud(app, '/users', endpoints);
161
- ```
162
-
163
- See [docs/alternative-api-patterns.md](./docs/alternative-api-patterns.md) for the full reference.
164
-
165
- ## Database Adapters
166
-
167
- ### Memory
168
-
169
- Zero-config, perfect for prototyping and tests:
170
-
171
- ```typescript
172
- import { MemoryCreateEndpoint, MemoryListEndpoint /* ... */ } from 'hono-crud/adapters/memory';
173
- ```
174
-
175
- ### Drizzle
176
-
177
- Use `createDrizzleCrud` for minimal boilerplate:
178
-
179
- ```typescript
180
- import { createDrizzleCrud } from 'hono-crud/adapters/drizzle';
181
- import { db } from './db';
182
-
183
- const User = createDrizzleCrud(db, userMeta);
184
-
185
- class UserCreate extends User.Create {
186
- schema = { tags: ['Users'], summary: 'Create user' };
187
- }
188
-
189
- class UserList extends User.List {
190
- schema = { tags: ['Users'], summary: 'List users' };
191
- filterFields = ['role'];
192
- }
193
- ```
194
-
195
- Or set `db` directly on each endpoint class:
196
-
197
- ```typescript
198
- import { DrizzleListEndpoint } from 'hono-crud/adapters/drizzle';
199
-
200
- class UserList extends DrizzleListEndpoint {
201
- _meta = userMeta;
202
- db = drizzleDb;
203
- filterFields = ['role'];
204
- }
205
- ```
206
-
207
- ### Prisma
208
-
209
- ```typescript
210
- import { PrismaListEndpoint } from 'hono-crud/adapters/prisma';
211
-
212
- class UserList extends PrismaListEndpoint {
213
- _meta = userMeta;
214
- prisma = prismaClient;
215
- filterFields = ['role'];
216
- }
217
- ```
218
-
219
- See [docs/database-adapters.md](./docs/database-adapters.md) for complete setup guides.
220
-
221
- ## Authentication
222
-
223
- Built-in JWT and API Key middleware with composable guards:
224
-
225
- ```typescript
226
- import { createJWTMiddleware, requireRoles, requireAuthenticated, anyOf } from 'hono-crud';
227
-
228
- // JWT middleware
229
- app.use('/api/*', createJWTMiddleware({
230
- secret: process.env.JWT_SECRET!,
231
- issuer: 'my-app',
232
- }));
233
-
234
- // Guards on specific endpoints
235
- registerCrud(app, '/users', endpoints, {
236
- middlewares: [requireAuthenticated()],
237
- endpointMiddlewares: {
238
- delete: [requireRoles('admin')],
239
- },
240
- });
241
-
242
- // Composable guards
243
- app.use('/admin/*', anyOf(
244
- requireRoles('admin'),
245
- requireOwnership((ctx) => ctx.req.param('id'))
246
- ));
247
- ```
248
-
249
- See [docs/authentication.md](./docs/authentication.md) for JWT, API Key, guards, and better-auth integration.
250
-
251
- ## Middleware
252
-
253
- ### Caching
254
-
255
- ```typescript
256
- import { withCache, withCacheInvalidation, setCacheStorage, MemoryCacheStorage } from 'hono-crud';
257
-
258
- class UserRead extends withCache(MemoryReadEndpoint) {
259
- _meta = userMeta;
260
- cacheConfig = { ttl: 300, perUser: false };
261
- }
262
- ```
263
-
264
- See [docs/caching.md](./docs/caching.md).
265
-
266
- ### Rate Limiting
267
-
268
- ```typescript
269
- import { createRateLimitMiddleware, setRateLimitStorage, MemoryRateLimitStorage } from 'hono-crud';
270
-
271
- setRateLimitStorage(new MemoryRateLimitStorage());
272
-
273
- app.use('/api/*', createRateLimitMiddleware({
274
- limit: 100,
275
- windowSeconds: 60,
276
- keyStrategy: 'ip',
277
- }));
278
- ```
279
-
280
- See [docs/rate-limiting.md](./docs/rate-limiting.md).
281
-
282
- ### Logging
283
-
284
- ```typescript
285
- import { createLoggingMiddleware, setLoggingStorage, MemoryLoggingStorage } from 'hono-crud';
286
-
287
- setLoggingStorage(new MemoryLoggingStorage());
288
-
289
- app.use('*', createLoggingMiddleware({
290
- redactHeaders: ['authorization', 'cookie'],
291
- redactBodyFields: ['password'],
292
- }));
293
- ```
294
-
295
- See [docs/logging.md](./docs/logging.md).
296
-
297
- ## Response shape
298
-
299
- Every CRUD endpoint defaults to a small, predictable response envelope so consumers always know where to find `result` and `error`:
300
-
301
- ```jsonc
302
- // Success — single item (Create / Read / Update / Restore / Upsert / Clone / …)
303
- { "success": true, "result": { "id": "…", … } }
304
-
305
- // Success — list / search (with pagination metadata)
306
- { "success": true, "result": [ … ], "result_info": { "page": 1, "per_page": 20, … } }
307
-
308
- // Error — produced by `ApiException`s thrown from the endpoint or by
309
- // `createErrorHandler` for everything else
310
- { "success": false, "error": { "code": "NOT_FOUND", "message": "…", "details": … } }
311
- ```
312
-
313
- ### Pluggable envelope (`responseEnvelope`)
314
-
315
- If your house API standard prefers a different shape — RFC 7807 Problem Details, JSON:API `{ data, meta }`, or any custom envelope — pass `responseEnvelope` to `registerCrud`. The two functions are the **final formatting step** before the response body is serialised:
316
-
317
- ```typescript
318
- import { registerCrud, type ResponseEnvelope } from 'hono-crud';
319
-
320
- const envelope: ResponseEnvelope = {
321
- success: (result, info) =>
322
- info ? { data: result, meta: info } : { data: result },
323
- error: (err) => ({
324
- errors: [{ status: err.code, title: err.message, source: err.details }],
325
- }),
326
- };
327
-
328
- registerCrud(app, '/users', endpoints, { responseEnvelope: envelope });
329
- ```
330
-
331
- The `info` argument is the pagination metadata for list/search responses; it's `undefined` for single-item responses, so a single envelope works across the whole CRUD surface.
332
-
333
- ### Composition with `createErrorHandler`
334
-
335
- For errors, the envelope composes with the existing `mappers` chain on `createErrorHandler`. The order is fixed:
336
-
337
- 1. `mappers[]` (and the built-in `zodErrorMapper`) transform the raw `Error` into a structured `ApiException` (`{ code, message, details? }`).
338
- 2. `responseEnvelope.error(...)` wraps that structured object into the final response body.
339
-
340
- ```typescript
341
- import { createErrorHandler, type ErrorMapper } from 'hono-crud';
342
-
343
- const prismaMapper: ErrorMapper = (err) => {
344
- if ((err as { code?: string }).code === 'P2002') {
345
- return new ConflictException('Duplicate key', { /* … */ });
346
- }
347
- };
348
-
349
- app.onError(createErrorHandler({
350
- mappers: [prismaMapper],
351
- // Handler-level default — applies to errors that propagate to onError
352
- // (i.e. anything that's not already an ApiException). Per-route envelope
353
- // set via `registerCrud({ responseEnvelope })` always wins.
354
- responseEnvelope: envelope,
355
- }));
356
- ```
357
-
358
- This split lets you keep your domain-error mappers (Prisma codes, Drizzle constraint violations, …) unchanged and layer a custom shape on top — no response-rewriting middleware required.
359
-
360
- When `responseEnvelope` is omitted (the default), the response body is byte-identical to pre-0.10.0 — existing consumers see no behaviour change.
361
-
362
- ## Advanced Features
363
-
364
- - **Soft Delete & Restore** - `softDelete: true` in model, `?withDeleted=true`, restore endpoint
365
- - **Relations** - `hasOne`, `hasMany`, `belongsTo` with `?include=posts,profile`
366
- - **Nested Writes** - Create/update related records in a single request
367
- - **Batch Operations** - Batch create, update, delete, restore, upsert
368
- - **Upsert** - Create or update by unique keys
369
- - **Versioning** - Record version history with rollback
370
- - **Audit Logging** - Track who changed what and when
371
- - **Full-Text Search** - Weighted search with highlighting
372
- - **Aggregation** - Sum, count, avg, min, max with grouping
373
- - **Export/Import** - CSV and JSON export/import
374
- - **Computed Fields** - Virtual fields calculated on read
375
- - **Field Selection** - `?fields=id,name,email`
376
- - **Events & Webhooks** - Event emitter with webhook delivery
377
- - **Encryption** - Field-level encryption with Web Crypto API
378
- - **Idempotency** - Idempotency key middleware for safe retries
379
- - **Multi-Tenancy** - Tenant isolation via header, path, query, or JWT
380
- - **Health Checks** - Liveness and readiness endpoints
381
- - **Error Handling** - Typed exceptions with custom error handlers
382
-
383
- See [docs/advanced-features.md](./docs/advanced-features.md) for examples of every feature.
384
-
385
- ### Subpath Imports
386
-
387
- Every advanced feature is also exposed as a tree-shakeable subpath, so apps that only need one feature can import it directly without pulling in the rest of the library:
388
-
389
- ```typescript
390
- import { multiTenant } from 'hono-crud/multi-tenant';
391
- import { createAuditLogger, MemoryAuditLogStorage } from 'hono-crud/audit';
392
- import { VersionManager, MemoryVersioningStorage } from 'hono-crud/versioning';
393
- import { CrudEventEmitter, registerWebhooks } from 'hono-crud/events';
394
- import { idempotency, MemoryIdempotencyStorage } from 'hono-crud/idempotency';
395
- import { createHealthEndpoints } from 'hono-crud/health';
396
- import { encryptFields, decryptFields, StaticKeyProvider } from 'hono-crud/encryption';
397
- import { applyProfile, type SerializationProfile } from 'hono-crud/serialization';
398
- import { apiVersion, getApiVersion } from 'hono-crud/api-version';
399
- ```
400
-
401
- The same symbols remain available from `'hono-crud'` for convenience.
402
-
403
- ## API Documentation
404
-
405
- ```typescript
406
- import { setupSwaggerUI, setupReDoc, setupScalar } from 'hono-crud';
407
-
408
- // OpenAPI spec
409
- app.doc('/openapi.json', {
410
- openapi: '3.1.0',
411
- info: { title: 'My API', version: '1.0.0' },
412
- });
413
-
414
- // Documentation UIs
415
- setupSwaggerUI(app, { docsPath: '/docs', specPath: '/openapi.json' });
416
- setupReDoc(app, { redocPath: '/redoc', specPath: '/openapi.json' });
417
- setupScalar(app, '/reference', { specUrl: '/openapi.json' });
418
- ```
419
-
420
- ## Examples
421
-
422
- See the [examples/](./examples) directory for complete working applications:
423
-
424
- - [Memory Adapter](./examples/memory) - Basic CRUD, alternative APIs, comprehensive features
425
- - [Drizzle + PostgreSQL](./examples/drizzle) - Schema, relations, filtering, batch operations
426
- - [Prisma + PostgreSQL](./examples/prisma) - Schema, relations, filtering, batch operations
427
-
428
- ## Requirements
429
-
430
- - Node.js >= 20
431
- - TypeScript >= 5.0
432
-
433
- ## License
434
-
435
- [MIT](./LICENSE) - Kauan Guesser
34
+ See the [repository README](https://github.com/kshdotdev/hono-crud) for the full guide.
@@ -1,8 +1,8 @@
1
1
  import { Context, Env } from 'hono';
2
- import { A as AuditConfig, c as AuditLogEntry, d as AuditAction } from '../types-Dfi9RdjS.js';
2
+ import { A as AuditConfig, a as AuditLogEntry, b as AuditAction } from '../types-38Hj6wN4.js';
3
3
  import { S as StorageRegistry } from '../registry-PNJjvSvm.js';
4
4
  import 'zod';
5
- import '../types-B5wq2iKZ.js';
5
+ import '../types-DcRAcexC.js';
6
6
  import '../types-BAcN7U0B.js';
7
7
  import '@hono/zod-openapi';
8
8
 
@@ -1 +1 @@
1
- export{e as AuditLogger,a as MemoryAuditLogStorage,b as auditStorageRegistry,f as createAuditLogger,d as getAuditStorage,c as setAuditStorage}from'../chunk-FJCWFB5L.js';import'../chunk-KUFOENSK.js';import'../chunk-GBQQ3YQX.js';import'../chunk-MDHMZPXK.js';import'../chunk-VJRDAVID.js';
1
+ export{e as AuditLogger,a as MemoryAuditLogStorage,b as auditStorageRegistry,f as createAuditLogger,d as getAuditStorage,c as setAuditStorage}from'../chunk-CTU6AAXM.js';import'../chunk-RU3RY5SC.js';import'../chunk-MDHMZPXK.js';import'../chunk-VJRDAVID.js';