@nanokajs/core 0.1.4 → 1.0.1

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/dist/index.d.ts CHANGED
@@ -1,37 +1,14 @@
1
1
  import { D1Database } from '@cloudflare/workers-types';
2
- import { BatchItem, BatchResponse } from 'drizzle-orm/batch';
3
- import { BaseSQLiteDatabase, SQLiteTable } from 'drizzle-orm/sqlite-core';
4
- import { F as Field, I as InferFieldType } from './factories-CDsk1Hdt.js';
5
- export { a as FieldModifiers, t } from './factories-CDsk1Hdt.js';
2
+ import { A as Adapter } from './types-D2QDVyks.js';
3
+ import { F as Field, I as InferFieldType, a as FieldPolicy } from './factories-Cmvx0495.js';
4
+ export { b as FieldModifiers, t } from './factories-Cmvx0495.js';
6
5
  import { Hook } from '@hono/zod-validator';
6
+ import { SQLiteTable } from 'drizzle-orm/sqlite-core';
7
7
  import * as hono from 'hono';
8
8
  import { ValidationTargets, Env, MiddlewareHandler, Hono } from 'hono';
9
9
  import { z } from 'zod';
10
10
  import { Env as Env$1, BlankEnv } from 'hono/types';
11
-
12
- /**
13
- * Generic database adapter abstraction for SQLite-compatible databases.
14
- *
15
- * Permits implementations over D1, Turso/libSQL, and other SQLite-compatible backends
16
- * without requiring changes to core query path or router.
17
- *
18
- * The `drizzle` property deliberately exposes the raw Drizzle database instance,
19
- * adhering to rule #4 (escape hatch always open).
20
- *
21
- * The `TResultKind` generic is intentionally constrained to `any` to avoid
22
- * coupling adapter implementations to Drizzle's internal result kind type.
23
- */
24
- interface Adapter<TSchema extends Record<string, unknown> = Record<string, never>> {
25
- readonly drizzle: BaseSQLiteDatabase<'async', any, TSchema>;
26
- /**
27
- * Executes multiple Drizzle queries in a single batch.
28
- * Returns results in the same order as the input.
29
- *
30
- * **重要**: 実装は `this` 非依存であること(`nanoka()` 内で thin wrapper として再公開されるため、
31
- * `this` バインディングが失われた状態で呼び出される可能性がある)。
32
- */
33
- batch<U extends BatchItem<'sqlite'>, T extends readonly [U, ...U[]]>(queries: T): Promise<BatchResponse<T>>;
34
- }
11
+ import 'drizzle-orm/batch';
35
12
 
36
13
  /**
37
14
  * D1-specific adapter factory. Wraps Cloudflare D1 binding in the generic
@@ -40,6 +17,67 @@ interface Adapter<TSchema extends Record<string, unknown> = Record<string, never
40
17
  */
41
18
  declare function d1Adapter<TSchema extends Record<string, unknown> = Record<string, never>>(d1: D1Database): Adapter<TSchema>;
42
19
 
20
+ type OpenAPISchemaObject = Record<string, unknown>;
21
+ interface OpenAPIModelComponent {
22
+ create: OpenAPISchemaObject;
23
+ update: OpenAPISchemaObject;
24
+ output: OpenAPISchemaObject;
25
+ }
26
+ type OpenAPIUsage = 'create' | 'update' | 'output';
27
+ type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
28
+ interface OpenAPIRequestBodySpec {
29
+ readonly description?: string;
30
+ readonly required?: boolean;
31
+ readonly content: {
32
+ readonly 'application/json': {
33
+ readonly schema: OpenAPISchemaObject;
34
+ };
35
+ };
36
+ }
37
+ interface OpenAPIResponseSpec {
38
+ readonly description: string;
39
+ readonly content?: {
40
+ readonly 'application/json': {
41
+ readonly schema: OpenAPISchemaObject;
42
+ };
43
+ };
44
+ }
45
+ interface OpenAPIParamSpec {
46
+ readonly name: string;
47
+ readonly in: 'path' | 'query' | 'header';
48
+ readonly required?: boolean;
49
+ readonly schema: OpenAPISchemaObject;
50
+ readonly description?: string;
51
+ }
52
+ interface OpenAPIRouteMetadata {
53
+ readonly path: string;
54
+ readonly method: HttpMethod;
55
+ readonly operationId?: string;
56
+ readonly summary?: string;
57
+ readonly description?: string;
58
+ readonly tags?: readonly string[];
59
+ readonly requestBody?: OpenAPIRequestBodySpec;
60
+ readonly params?: OpenAPIParamSpec[];
61
+ readonly responses: Record<string, OpenAPIResponseSpec>;
62
+ }
63
+ interface OpenAPISpecOptions {
64
+ readonly info: {
65
+ readonly title: string;
66
+ readonly version: string;
67
+ readonly description?: string;
68
+ };
69
+ readonly servers?: ReadonlyArray<{
70
+ readonly url: string;
71
+ readonly description?: string;
72
+ }>;
73
+ }
74
+ interface OpenAPIDocument {
75
+ readonly openapi: '3.1.0';
76
+ readonly info: OpenAPISpecOptions['info'];
77
+ readonly servers?: OpenAPISpecOptions['servers'];
78
+ readonly paths: Record<string, Record<string, unknown>>;
79
+ }
80
+
43
81
  /**
44
82
  * Options for findMany query.
45
83
  * `limit` is required (no default).
@@ -78,13 +116,84 @@ type RowType<Fields extends Record<string, Field<any, any, any>>> = {
78
116
  [K in keyof Fields]: InferFieldType<Fields[K]>;
79
117
  };
80
118
  /**
81
- * Create input: partial row (most fields optional for insert).
82
- * Phase 1 では `Partial<RowType>` のままとし、必須/任意フィールドの型区別は Phase 2 で扱う。
119
+ * @internal
120
+ * Extracts the policy from a Field's modifiers.
121
+ *
122
+ * Uses `Field<any, { policy: infer P }, any>` rather than a two-step
123
+ * `infer M` + `M extends { policy: infer P }` pattern.
124
+ * The two-step pattern is broken when TypeScript widens `M` to the constraint
125
+ * `FieldModifiers` (which has `policy?: FieldPolicy` as optional), causing
126
+ * `M extends { policy: infer P }` to be true for ALL fields regardless of their
127
+ * actual policy value. Directly matching `{ policy: infer P }` avoids this.
128
+ */
129
+ type PolicyOf<F> = F extends Field<any, {
130
+ policy: infer P extends FieldPolicy;
131
+ }, any> ? P : never;
132
+ /**
133
+ * @internal
134
+ * Computes which field keys should be omitted based on policy and usage.
135
+ * Mirrors the runtime logic in derivePolicyOptions() in schema.ts.
136
+ *
137
+ * NOTE: `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) is used to
138
+ * short-circuit fields with no policy to `never` (do not omit). Without this guard,
139
+ * `never extends 'serverOnly'` evaluates to `true` (vacuously), causing every field
140
+ * without a policy to be incorrectly included in the omit set.
141
+ */
142
+ type PolicyOmitKeys<Fields extends Record<string, Field<any, any, any>>, Usage extends 'input-create' | 'input-update' | 'output'> = {
143
+ [K in keyof Fields]: [PolicyOf<Fields[K]>] extends [never] ? never : PolicyOf<Fields[K]> extends 'serverOnly' ? K : Usage extends 'output' ? PolicyOf<Fields[K]> extends 'writeOnly' ? K : never : Usage extends 'input-create' | 'input-update' ? PolicyOf<Fields[K]> extends 'readOnly' ? K : never : never;
144
+ }[keyof Fields];
145
+ /**
146
+ * @internal
147
+ * Computes which field keys have the serverOnly policy.
148
+ * serverOnly fields are completely excluded from CreateInput
149
+ * (cannot be passed even from library internals — they are server-side only).
150
+ *
151
+ * Uses `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) to short-circuit
152
+ * fields with no policy to `never`. Without this guard, `never extends 'serverOnly'`
153
+ * evaluates to `true` (vacuously), causing every field without a policy to be included.
83
154
  */
84
- type CreateInput<Fields extends Record<string, Field<any, any, any>>> = Partial<RowType<Fields>>;
155
+ type ServerOnlyKeys<Fields extends Record<string, Field<any, any, any>>> = {
156
+ [K in keyof Fields]: [PolicyOf<Fields[K]>] extends [never] ? never : PolicyOf<Fields[K]> extends 'serverOnly' ? K : never;
157
+ }[keyof Fields];
158
+ /**
159
+ * @internal
160
+ * Determines if a field is required for create input.
161
+ * A field is optional if it has a default, is optional, or is readOnly.
162
+ *
163
+ * Uses direct shape matching (`Field<any, { hasDefault: true }, any>`) to avoid
164
+ * the TypeScript infer-widening issue where `infer M` resolves to `FieldModifiers`
165
+ * (the constraint bound) instead of the concrete Mods type, causing `M extends
166
+ * { policy: 'readOnly' }` to be false even for readOnly fields.
167
+ */
168
+ type IsRequired<F extends Field<any, any, any>> = F extends Field<any, {
169
+ hasDefault: true;
170
+ }, any> ? false : F extends Field<any, {
171
+ optional: true;
172
+ }, any> ? false : F extends Field<any, {
173
+ policy: 'readOnly';
174
+ }, any> ? false : true;
175
+ /**
176
+ * Create input with precise types:
177
+ * - `readOnly` fields are optional (library internals can pass them; API callers
178
+ * are excluded via inputSchema — but CreateInput itself keeps them as optional
179
+ * so handlers can supply generated values like `id` or `createdAt`)
180
+ * - fields with `default` are optional
181
+ * - fields marked `optional` are optional
182
+ * - all other fields are required
183
+ * - `serverOnly` fields are completely excluded (cannot be passed even internally)
184
+ * - `writeOnly` fields are included as required (they are input fields by design)
185
+ */
186
+ type CreateInput<Fields extends Record<string, Field<any, any, any>>> = {
187
+ [K in keyof Fields as IsRequired<Fields[K]> extends true ? K extends ServerOnlyKeys<Fields> ? never : K : never]: InferFieldType<Fields[K]>;
188
+ } & {
189
+ [K in keyof Fields as IsRequired<Fields[K]> extends true ? never : K extends ServerOnlyKeys<Fields> ? never : K]?: InferFieldType<Fields[K]>;
190
+ };
191
+ type FieldAccessor<K extends string> = {
192
+ readonly [Key in K]: Key;
193
+ };
85
194
  interface SchemaOptions<K extends string = string> {
86
- readonly pick?: readonly K[];
87
- readonly omit?: readonly K[];
195
+ readonly pick?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[]);
196
+ readonly omit?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[]);
88
197
  readonly partial?: boolean;
89
198
  }
90
199
  /**
@@ -101,16 +210,22 @@ type FieldsToZodShape<Fields extends Record<string, Field<any, any, any>>> = {
101
210
  * Utility to narrow array literal types to union of strings.
102
211
  */
103
212
  type ArrayKeys<A> = A extends readonly (infer U)[] ? U : never;
213
+ /**
214
+ * @internal
215
+ * Resolves pick/omit option type to the array type.
216
+ * Handles both array form and accessor function form.
217
+ */
218
+ type ResolveOptKeys<Opt> = Opt extends readonly string[] ? Opt : Opt extends (f: FieldAccessor<infer _K>) => readonly (infer R)[] ? readonly R[] : never;
104
219
  /**
105
220
  * @internal
106
221
  * Apply pick transformation to a shape.
107
222
  */
108
- type ApplyPickToShape<Shape extends z.ZodRawShape, PickKeys> = PickKeys extends readonly string[] ? Pick<Shape, ArrayKeys<PickKeys> & keyof Shape> : Shape;
223
+ type ApplyPickToShape<Shape extends z.ZodRawShape, PickOpt> = ResolveOptKeys<PickOpt> extends readonly string[] ? Pick<Shape, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof Shape> : Shape;
109
224
  /**
110
225
  * @internal
111
226
  * Apply omit transformation to a shape.
112
227
  */
113
- type ApplyOmitToShape<Shape extends z.ZodRawShape, OmitKeys> = OmitKeys extends readonly string[] ? Omit<Shape, ArrayKeys<OmitKeys> & keyof Shape> : Shape;
228
+ type ApplyOmitToShape<Shape extends z.ZodRawShape, OmitOpt> = ResolveOptKeys<OmitOpt> extends readonly string[] ? Omit<Shape, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof Shape> : Shape;
114
229
  /**
115
230
  * @internal
116
231
  * Apply partial transformation to a shape.
@@ -118,38 +233,77 @@ type ApplyOmitToShape<Shape extends z.ZodRawShape, OmitKeys> = OmitKeys extends
118
233
  type ApplyPartialToShape<Shape extends z.ZodRawShape> = {
119
234
  [K in keyof Shape]: z.ZodOptional<Shape[K]>;
120
235
  };
236
+ /**
237
+ * @internal
238
+ * Checks if an option value (array or function) is present (i.e. not undefined and not never).
239
+ * Uses distributive conditional to handle union types like `T | undefined`.
240
+ */
241
+ type HasOpt<Opt> = undefined extends Opt ? false : [Opt] extends [never] ? false : true;
121
242
  /**
122
243
  * @internal
123
244
  * Apply pick/omit/partial transformations to a Zod raw shape.
124
245
  * Order: pick → omit → partial
246
+ * Handles both array form and accessor function form for pick/omit.
125
247
  */
126
- type ApplyShape<Shape extends z.ZodRawShape, Opts extends SchemaOptions | undefined> = Opts extends undefined ? Shape : Opts extends {
127
- pick: readonly string[];
128
- } ? Opts extends {
129
- omit: readonly string[];
130
- } ? Opts extends {
248
+ type ApplyShape<Shape extends z.ZodRawShape, Opts extends SchemaOptions | undefined> = Opts extends SchemaOptions ? HasOpt<Opts['pick']> extends true ? HasOpt<Opts['omit']> extends true ? Opts extends {
131
249
  partial: true;
132
250
  } ? ApplyPartialToShape<ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']>> : ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']> : Opts extends {
133
251
  partial: true;
134
- } ? ApplyPartialToShape<ApplyPickToShape<Shape, Opts['pick']>> : ApplyPickToShape<Shape, Opts['pick']> : Opts extends {
135
- omit: readonly string[];
136
- } ? Opts extends {
252
+ } ? ApplyPartialToShape<ApplyPickToShape<Shape, Opts['pick']>> : ApplyPickToShape<Shape, Opts['pick']> : HasOpt<Opts['omit']> extends true ? Opts extends {
137
253
  partial: true;
138
254
  } ? ApplyPartialToShape<ApplyOmitToShape<Shape, Opts['omit']>> : ApplyOmitToShape<Shape, Opts['omit']> : Opts extends {
139
255
  partial: true;
140
- } ? ApplyPartialToShape<Shape> : Shape;
256
+ } ? ApplyPartialToShape<Shape> : Shape : Shape;
141
257
  /**
142
258
  * @internal
143
259
  * Returns the correct Zod object type after applying pick/omit/partial transformations.
144
260
  */
145
261
  type Apply<Shape extends z.ZodRawShape, Opts extends SchemaOptions | undefined> = z.ZodObject<ApplyShape<Shape, Opts>>;
262
+ /**
263
+ * @internal
264
+ * Apply pick transformation to a TS record type.
265
+ */
266
+ type ApplyPickToRecord<R, PickOpt> = ResolveOptKeys<PickOpt> extends readonly string[] ? Pick<R, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof R> : R;
267
+ /**
268
+ * @internal
269
+ * Apply omit transformation to a TS record type.
270
+ */
271
+ type ApplyOmitToRecord<R, OmitOpt> = ResolveOptKeys<OmitOpt> extends readonly string[] ? Omit<R, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof R> : R;
272
+ /**
273
+ * @internal
274
+ * Apply pick/omit/partial transformations to a TypeScript record type.
275
+ * Mirrors ApplyShape but operates on TS types directly, not Zod shapes.
276
+ * Used for Zod v3/v4 compatible middleware input/output type computation.
277
+ */
278
+ type ApplyToRecord<R, Opts extends SchemaOptions | undefined> = Opts extends SchemaOptions ? HasOpt<Opts['pick']> extends true ? HasOpt<Opts['omit']> extends true ? Opts extends {
279
+ partial: true;
280
+ } ? Partial<ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']>> : ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']> : Opts extends {
281
+ partial: true;
282
+ } ? Partial<ApplyPickToRecord<R, Opts['pick']>> : ApplyPickToRecord<R, Opts['pick']> : HasOpt<Opts['omit']> extends true ? Opts extends {
283
+ partial: true;
284
+ } ? Partial<ApplyOmitToRecord<R, Opts['omit']>> : ApplyOmitToRecord<R, Opts['omit']> : Opts extends {
285
+ partial: true;
286
+ } ? Partial<R> : R : R;
146
287
  /**
147
288
  * @internal
148
289
  * Mirrors @hono/zod-validator's middleware Input type.
149
290
  * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.
150
291
  */
151
292
  type HasUndefined<T> = undefined extends T ? true : false;
152
- type ValidatorInput<Target extends keyof ValidationTargets, Schema extends z.ZodType<any, z.ZodTypeDef, any>, In = z.input<Schema>, Out = z.output<Schema>> = {
293
+ /**
294
+ * @internal
295
+ * Hono middleware input/output type for validator middleware.
296
+ * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.
297
+ *
298
+ * WARNING (Zod 4): `z.input<ZodTypeAny>` resolves to `unknown` in Zod 4, making
299
+ * `c.req.valid(target)` return `unknown` if `In`/`Out` are left as defaults.
300
+ * When using this type directly (outside of `ModelValidatorReturn`), always pass
301
+ * explicit `In` and `Out` type arguments — do NOT rely on the defaults.
302
+ *
303
+ * Internal usages in this file (ModelValidatorReturn and preset overloads) already
304
+ * pass `In`/`Out` explicitly via `ApplyToRecord` or `Omit<RowType<Fields>, ...>`.
305
+ */
306
+ type ValidatorInput<Target extends keyof ValidationTargets, Schema extends z.ZodTypeAny, In = z.input<Schema>, Out = z.output<Schema>> = {
153
307
  in: HasUndefined<In> extends true ? {
154
308
  [K in Target]?: (In extends ValidationTargets[K] ? In : {
155
309
  [K2 in keyof In]?: ValidationTargets[K][K2] | undefined;
@@ -167,8 +321,11 @@ type ValidatorInput<Target extends keyof ValidationTargets, Schema extends z.Zod
167
321
  * @internal
168
322
  * Type-safe Hono middleware handler return for Model.validator().
169
323
  * Provides proper type narrowing for c.req.valid(target).
324
+ *
325
+ * Uses RowType<Fields> directly for input/output type computation
326
+ * to ensure Zod v3/v4 compatibility (z.input<ZodTypeAny> returns unknown in Zod v4).
170
327
  */
171
- type ModelValidatorReturn<Fields extends Record<string, Field<any, any, any>>, Target extends keyof ValidationTargets, Opts extends SchemaOptions<keyof Fields & string> | undefined> = MiddlewareHandler<any, string, ValidatorInput<Target, Apply<FieldsToZodShape<Fields>, Opts>>>;
328
+ type ModelValidatorReturn<Fields extends Record<string, Field<any, any, any>>, Target extends keyof ValidationTargets, Opts extends SchemaOptions<keyof Fields & string> | undefined> = MiddlewareHandler<any, string, ValidatorInput<Target, Apply<FieldsToZodShape<Fields>, Opts>, ApplyToRecord<RowType<Fields>, Opts>, ApplyToRecord<RowType<Fields>, Opts>>>;
172
329
 
173
330
  /**
174
331
  * Represents a database model with type-safe schema derivation and CRUD operations.
@@ -185,22 +342,60 @@ interface Model<Fields extends Record<string, Field<any, any, any>>> {
185
342
  * const CreateSchema = User.schema({ omit: ['passwordHash'] })
186
343
  * const UpdateSchema = User.schema({ partial: true, pick: ['name', 'email'] })
187
344
  */
188
- schema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(opts?: Opts): Apply<FieldsToZodShape<Fields>, Opts>;
345
+ schema<Opts extends SchemaOptions<keyof Fields & string> | undefined>(opts?: Opts): Apply<FieldsToZodShape<Fields>, Opts>;
189
346
  /**
190
347
  * Returns a Hono middleware validator derived from this model's schema.
191
348
  * Integrates with @hono/zod-validator to validate request inputs.
192
349
  * The optional `hook` argument is passed through to @hono/zod-validator.
193
350
  *
351
+ * Accepts a preset ('create' | 'update') as second argument to use inputSchema.
352
+ * When a preset is used, the return type is a MiddlewareHandler (loosely typed in Phase 2A).
353
+ * Precise type narrowing for preset is deferred to Phase 2B M2.3.
354
+ *
194
355
  * @example
356
+ * app.post('/users', User.validator('json', 'create'), c => {
357
+ * const body = c.req.valid('json')
358
+ * })
195
359
  * app.post('/users', User.validator('json', { omit: ['passwordHash'] }), c => {
196
360
  * const body = c.req.valid('json')
197
361
  * })
198
- * // With hook for hardened error responses:
362
+ * // With hook:
199
363
  * app.post('/users', User.validator('json', opts, (result, c) => {
200
364
  * if (!result.success) return c.json({ error: 'Invalid request' }, 400)
201
365
  * }), handler)
202
366
  */
203
- validator<Target extends keyof ValidationTargets, Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined, E extends Env = Env, P extends string = string>(target: Target, opts?: Opts, hook?: Hook<z.output<Apply<FieldsToZodShape<Fields>, Opts>>, E, P, Target>): ModelValidatorReturn<Fields, Target, Opts>;
367
+ validator<Target extends keyof ValidationTargets, E extends Env = Env, P extends string = string>(target: Target, preset: 'create', hook?: Hook<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>, E, P, Target>): MiddlewareHandler<E, P, ValidatorInput<Target, z.ZodObject<z.ZodRawShape>, Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>, Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>>>;
368
+ validator<Target extends keyof ValidationTargets, E extends Env = Env, P extends string = string>(target: Target, preset: 'update', hook?: Hook<Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>, E, P, Target>): MiddlewareHandler<E, P, ValidatorInput<Target, z.ZodObject<z.ZodRawShape>, Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>, Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>>>;
369
+ validator<Target extends keyof ValidationTargets, Opts extends SchemaOptions<keyof Fields & string> | undefined, E extends Env = Env, P extends string = string>(target: Target, opts?: Opts, hook?: Hook<z.output<Apply<FieldsToZodShape<Fields>, Opts>>, E, P, Target>): ModelValidatorReturn<Fields, Target, Opts>;
370
+ /**
371
+ * Returns a Zod schema for API input, with policy-based field exclusions applied.
372
+ * - 'create': serverOnly and readOnly fields are excluded
373
+ * - 'update': same exclusions + all fields become optional (partial: true)
374
+ *
375
+ * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.
376
+ */
377
+ inputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(usage: 'create', opts?: Opts): z.ZodObject<ApplyShape<Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>, Opts>>;
378
+ inputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(usage: 'update', opts?: Opts): z.ZodObject<ApplyShape<Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>, Opts extends undefined ? {
379
+ partial: true;
380
+ } : Opts & {
381
+ partial: true;
382
+ }>>;
383
+ inputSchema(usage: 'create' | 'update', opts?: SchemaOptions<keyof Fields & string>): z.ZodObject<z.ZodRawShape>;
384
+ /**
385
+ * Returns a Zod schema for API output, with policy-based field exclusions applied.
386
+ * - serverOnly and writeOnly fields are excluded
387
+ * - readOnly fields remain present
388
+ *
389
+ * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.
390
+ */
391
+ outputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(opts?: Opts): z.ZodObject<ApplyShape<Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'output'> & string>, Opts>>;
392
+ /**
393
+ * Parses a DB row through outputSchema and returns the safe response object.
394
+ * Equivalent to `User.outputSchema().parse(row)`.
395
+ */
396
+ toResponse(row: RowType<Fields>): unknown;
397
+ toOpenAPIComponent(): OpenAPIModelComponent;
398
+ toOpenAPISchema(usage: OpenAPIUsage): OpenAPISchemaObject;
204
399
  /**
205
400
  * Fetches multiple rows with pagination and optional ordering.
206
401
  * `limit` is required (no default) to prevent accidental unbounded queries.
@@ -250,6 +445,12 @@ interface Model<Fields extends Record<string, Field<any, any, any>>> {
250
445
  }>;
251
446
  }
252
447
 
448
+ interface SwaggerUIOptions {
449
+ readonly url: string;
450
+ readonly title?: string;
451
+ }
452
+ declare function swaggerUI(options: SwaggerUIOptions): MiddlewareHandler;
453
+
253
454
  /**
254
455
  * Creates a Model instance from a tableName and fields definition.
255
456
  * The model supports deriving Zod schemas, Hono validators, and CRUD operations.
@@ -286,8 +487,25 @@ interface NanokaModel<Fields extends Record<string, Field<any, any, any>>> {
286
487
  /**
287
488
  * Returns a Hono middleware validator for this model.
288
489
  * The optional `hook` argument is passed through to @hono/zod-validator.
490
+ * Accepts a preset ('create' | 'update') as second argument to use inputSchema.
289
491
  */
492
+ validator<Target extends keyof hono.ValidationTargets, E extends Env$1 = Env$1, P extends string = string>(target: Target, preset: 'create', hook?: Hook<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>, E, P, Target>): MiddlewareHandler<E, P, ValidatorInput<Target, z.ZodObject<z.ZodRawShape>, Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>, Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>>>;
493
+ validator<Target extends keyof hono.ValidationTargets, E extends Env$1 = Env$1, P extends string = string>(target: Target, preset: 'update', hook?: Hook<Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>, E, P, Target>): MiddlewareHandler<E, P, ValidatorInput<Target, z.ZodObject<z.ZodRawShape>, Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>, Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>>>;
290
494
  validator<Target extends keyof hono.ValidationTargets, Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined, E extends Env$1 = Env$1, P extends string = string>(target: Target, opts?: Opts, hook?: Hook<z.output<Apply<FieldsToZodShape<Fields>, Opts>>, E, P, Target>): ModelValidatorReturn<Fields, Target, Opts>;
495
+ /**
496
+ * Returns a Zod schema for API input, with policy-based field exclusions applied.
497
+ */
498
+ inputSchema(usage: 'create' | 'update', opts?: SchemaOptions<keyof Fields & string>): z.ZodObject<z.ZodRawShape>;
499
+ /**
500
+ * Returns a Zod schema for API output, with policy-based field exclusions applied.
501
+ */
502
+ outputSchema(opts?: SchemaOptions<keyof Fields & string>): z.ZodObject<z.ZodRawShape>;
503
+ /**
504
+ * Parses a DB row through outputSchema and returns the safe response object.
505
+ */
506
+ toResponse(row: RowType<Fields>): unknown;
507
+ toOpenAPIComponent(): OpenAPIModelComponent;
508
+ toOpenAPISchema(usage: OpenAPIUsage): OpenAPISchemaObject;
291
509
  /**
292
510
  * Fetches multiple rows with pagination and optional ordering.
293
511
  * `limit` is required (no default) to prevent accidental unbounded queries.
@@ -341,6 +559,15 @@ interface Nanoka<E extends Env$1 = BlankEnv> extends Hono<E> {
341
559
  * const users = await User.findMany({ limit: 20 })
342
560
  */
343
561
  model<Fields extends Record<string, Field<any, any, any>>>(name: string, fields: Fields): NanokaModel<Fields>;
562
+ /**
563
+ * Registers OpenAPI metadata for a route.
564
+ * Does NOT register the actual Hono handler — call app.get/post/... separately.
565
+ */
566
+ openapi(metadata: OpenAPIRouteMetadata): this;
567
+ /**
568
+ * Builds the full OpenAPI 3.1 document from all registered openapi() metadata.
569
+ */
570
+ generateOpenAPISpec(options: OpenAPISpecOptions): OpenAPIDocument;
344
571
  }
345
572
 
346
573
  /**
@@ -364,4 +591,4 @@ interface Nanoka<E extends Env$1 = BlankEnv> extends Hono<E> {
364
591
  */
365
592
  declare function nanoka<E extends Env$1 = BlankEnv>(adapter: Adapter): Nanoka<E>;
366
593
 
367
- export { type Adapter, type CreateInput, Field, type FindManyOptions, type IdOrWhere, InferFieldType, type Model, type Nanoka, type NanokaModel, type OrderBy, type RowType, type SchemaOptions, type Where, d1Adapter, defineModel, nanoka };
594
+ export { Adapter, type CreateInput, Field, FieldPolicy, type FindManyOptions, type HttpMethod, type IdOrWhere, InferFieldType, type Model, type Nanoka, type NanokaModel, type OpenAPIDocument, type OpenAPIModelComponent, type OpenAPIParamSpec, type OpenAPIRequestBodySpec, type OpenAPIResponseSpec, type OpenAPIRouteMetadata, type OpenAPISchemaObject, type OpenAPISpecOptions, type OpenAPIUsage, type OrderBy, type RowType, type SchemaOptions, type Where, d1Adapter, defineModel, nanoka, swaggerUI };