@nanokajs/core 0.1.3 → 1.0.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/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { D1Database } from '@cloudflare/workers-types';
2
2
  import { BatchItem, BatchResponse } from 'drizzle-orm/batch';
3
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';
4
+ import { F as Field, I as InferFieldType, a as FieldPolicy } from './factories-Cmvx0495.js';
5
+ export { b as FieldModifiers, t } from './factories-Cmvx0495.js';
6
6
  import { Hook } from '@hono/zod-validator';
7
7
  import * as hono from 'hono';
8
8
  import { ValidationTargets, Env, MiddlewareHandler, Hono } from 'hono';
9
9
  import { z } from 'zod';
10
+ import { Env as Env$1, BlankEnv } from 'hono/types';
10
11
 
11
12
  /**
12
13
  * Generic database adapter abstraction for SQLite-compatible databases.
@@ -39,6 +40,14 @@ interface Adapter<TSchema extends Record<string, unknown> = Record<string, never
39
40
  */
40
41
  declare function d1Adapter<TSchema extends Record<string, unknown> = Record<string, never>>(d1: D1Database): Adapter<TSchema>;
41
42
 
43
+ type OpenAPISchemaObject = Record<string, unknown>;
44
+ interface OpenAPIModelComponent {
45
+ create: OpenAPISchemaObject;
46
+ update: OpenAPISchemaObject;
47
+ output: OpenAPISchemaObject;
48
+ }
49
+ type OpenAPIUsage = 'create' | 'update' | 'output';
50
+
42
51
  /**
43
52
  * Options for findMany query.
44
53
  * `limit` is required (no default).
@@ -77,13 +86,84 @@ type RowType<Fields extends Record<string, Field<any, any, any>>> = {
77
86
  [K in keyof Fields]: InferFieldType<Fields[K]>;
78
87
  };
79
88
  /**
80
- * Create input: partial row (most fields optional for insert).
81
- * Phase 1 では `Partial<RowType>` のままとし、必須/任意フィールドの型区別は Phase 2 で扱う。
89
+ * @internal
90
+ * Extracts the policy from a Field's modifiers.
91
+ *
92
+ * Uses `Field<any, { policy: infer P }, any>` rather than a two-step
93
+ * `infer M` + `M extends { policy: infer P }` pattern.
94
+ * The two-step pattern is broken when TypeScript widens `M` to the constraint
95
+ * `FieldModifiers` (which has `policy?: FieldPolicy` as optional), causing
96
+ * `M extends { policy: infer P }` to be true for ALL fields regardless of their
97
+ * actual policy value. Directly matching `{ policy: infer P }` avoids this.
98
+ */
99
+ type PolicyOf<F> = F extends Field<any, {
100
+ policy: infer P extends FieldPolicy;
101
+ }, any> ? P : never;
102
+ /**
103
+ * @internal
104
+ * Computes which field keys should be omitted based on policy and usage.
105
+ * Mirrors the runtime logic in derivePolicyOptions() in schema.ts.
106
+ *
107
+ * NOTE: `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) is used to
108
+ * short-circuit fields with no policy to `never` (do not omit). Without this guard,
109
+ * `never extends 'serverOnly'` evaluates to `true` (vacuously), causing every field
110
+ * without a policy to be incorrectly included in the omit set.
111
+ */
112
+ type PolicyOmitKeys<Fields extends Record<string, Field<any, any, any>>, Usage extends 'input-create' | 'input-update' | 'output'> = {
113
+ [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;
114
+ }[keyof Fields];
115
+ /**
116
+ * @internal
117
+ * Computes which field keys have the serverOnly policy.
118
+ * serverOnly fields are completely excluded from CreateInput
119
+ * (cannot be passed even from library internals — they are server-side only).
120
+ *
121
+ * Uses `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) to short-circuit
122
+ * fields with no policy to `never`. Without this guard, `never extends 'serverOnly'`
123
+ * evaluates to `true` (vacuously), causing every field without a policy to be included.
124
+ */
125
+ type ServerOnlyKeys<Fields extends Record<string, Field<any, any, any>>> = {
126
+ [K in keyof Fields]: [PolicyOf<Fields[K]>] extends [never] ? never : PolicyOf<Fields[K]> extends 'serverOnly' ? K : never;
127
+ }[keyof Fields];
128
+ /**
129
+ * @internal
130
+ * Determines if a field is required for create input.
131
+ * A field is optional if it has a default, is optional, or is readOnly.
132
+ *
133
+ * Uses direct shape matching (`Field<any, { hasDefault: true }, any>`) to avoid
134
+ * the TypeScript infer-widening issue where `infer M` resolves to `FieldModifiers`
135
+ * (the constraint bound) instead of the concrete Mods type, causing `M extends
136
+ * { policy: 'readOnly' }` to be false even for readOnly fields.
137
+ */
138
+ type IsRequired<F extends Field<any, any, any>> = F extends Field<any, {
139
+ hasDefault: true;
140
+ }, any> ? false : F extends Field<any, {
141
+ optional: true;
142
+ }, any> ? false : F extends Field<any, {
143
+ policy: 'readOnly';
144
+ }, any> ? false : true;
145
+ /**
146
+ * Create input with precise types:
147
+ * - `readOnly` fields are optional (library internals can pass them; API callers
148
+ * are excluded via inputSchema — but CreateInput itself keeps them as optional
149
+ * so handlers can supply generated values like `id` or `createdAt`)
150
+ * - fields with `default` are optional
151
+ * - fields marked `optional` are optional
152
+ * - all other fields are required
153
+ * - `serverOnly` fields are completely excluded (cannot be passed even internally)
154
+ * - `writeOnly` fields are included as required (they are input fields by design)
82
155
  */
83
- type CreateInput<Fields extends Record<string, Field<any, any, any>>> = Partial<RowType<Fields>>;
156
+ type CreateInput<Fields extends Record<string, Field<any, any, any>>> = {
157
+ [K in keyof Fields as IsRequired<Fields[K]> extends true ? K extends ServerOnlyKeys<Fields> ? never : K : never]: InferFieldType<Fields[K]>;
158
+ } & {
159
+ [K in keyof Fields as IsRequired<Fields[K]> extends true ? never : K extends ServerOnlyKeys<Fields> ? never : K]?: InferFieldType<Fields[K]>;
160
+ };
161
+ type FieldAccessor<K extends string> = {
162
+ readonly [Key in K]: Key;
163
+ };
84
164
  interface SchemaOptions<K extends string = string> {
85
- readonly pick?: readonly K[];
86
- readonly omit?: readonly K[];
165
+ readonly pick?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[]);
166
+ readonly omit?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[]);
87
167
  readonly partial?: boolean;
88
168
  }
89
169
  /**
@@ -100,16 +180,22 @@ type FieldsToZodShape<Fields extends Record<string, Field<any, any, any>>> = {
100
180
  * Utility to narrow array literal types to union of strings.
101
181
  */
102
182
  type ArrayKeys<A> = A extends readonly (infer U)[] ? U : never;
183
+ /**
184
+ * @internal
185
+ * Resolves pick/omit option type to the array type.
186
+ * Handles both array form and accessor function form.
187
+ */
188
+ type ResolveOptKeys<Opt> = Opt extends readonly string[] ? Opt : Opt extends (f: FieldAccessor<infer _K>) => readonly (infer R)[] ? readonly R[] : never;
103
189
  /**
104
190
  * @internal
105
191
  * Apply pick transformation to a shape.
106
192
  */
107
- type ApplyPickToShape<Shape extends z.ZodRawShape, PickKeys> = PickKeys extends readonly string[] ? Pick<Shape, ArrayKeys<PickKeys> & keyof Shape> : Shape;
193
+ type ApplyPickToShape<Shape extends z.ZodRawShape, PickOpt> = ResolveOptKeys<PickOpt> extends readonly string[] ? Pick<Shape, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof Shape> : Shape;
108
194
  /**
109
195
  * @internal
110
196
  * Apply omit transformation to a shape.
111
197
  */
112
- type ApplyOmitToShape<Shape extends z.ZodRawShape, OmitKeys> = OmitKeys extends readonly string[] ? Omit<Shape, ArrayKeys<OmitKeys> & keyof Shape> : Shape;
198
+ type ApplyOmitToShape<Shape extends z.ZodRawShape, OmitOpt> = ResolveOptKeys<OmitOpt> extends readonly string[] ? Omit<Shape, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof Shape> : Shape;
113
199
  /**
114
200
  * @internal
115
201
  * Apply partial transformation to a shape.
@@ -117,38 +203,77 @@ type ApplyOmitToShape<Shape extends z.ZodRawShape, OmitKeys> = OmitKeys extends
117
203
  type ApplyPartialToShape<Shape extends z.ZodRawShape> = {
118
204
  [K in keyof Shape]: z.ZodOptional<Shape[K]>;
119
205
  };
206
+ /**
207
+ * @internal
208
+ * Checks if an option value (array or function) is present (i.e. not undefined and not never).
209
+ * Uses distributive conditional to handle union types like `T | undefined`.
210
+ */
211
+ type HasOpt<Opt> = undefined extends Opt ? false : [Opt] extends [never] ? false : true;
120
212
  /**
121
213
  * @internal
122
214
  * Apply pick/omit/partial transformations to a Zod raw shape.
123
215
  * Order: pick → omit → partial
216
+ * Handles both array form and accessor function form for pick/omit.
124
217
  */
125
- type ApplyShape<Shape extends z.ZodRawShape, Opts extends SchemaOptions | undefined> = Opts extends undefined ? Shape : Opts extends {
126
- pick: readonly string[];
127
- } ? Opts extends {
128
- omit: readonly string[];
129
- } ? Opts extends {
218
+ 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 {
130
219
  partial: true;
131
220
  } ? ApplyPartialToShape<ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']>> : ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']> : Opts extends {
132
221
  partial: true;
133
- } ? ApplyPartialToShape<ApplyPickToShape<Shape, Opts['pick']>> : ApplyPickToShape<Shape, Opts['pick']> : Opts extends {
134
- omit: readonly string[];
135
- } ? Opts extends {
222
+ } ? ApplyPartialToShape<ApplyPickToShape<Shape, Opts['pick']>> : ApplyPickToShape<Shape, Opts['pick']> : HasOpt<Opts['omit']> extends true ? Opts extends {
136
223
  partial: true;
137
224
  } ? ApplyPartialToShape<ApplyOmitToShape<Shape, Opts['omit']>> : ApplyOmitToShape<Shape, Opts['omit']> : Opts extends {
138
225
  partial: true;
139
- } ? ApplyPartialToShape<Shape> : Shape;
226
+ } ? ApplyPartialToShape<Shape> : Shape : Shape;
140
227
  /**
141
228
  * @internal
142
229
  * Returns the correct Zod object type after applying pick/omit/partial transformations.
143
230
  */
144
231
  type Apply<Shape extends z.ZodRawShape, Opts extends SchemaOptions | undefined> = z.ZodObject<ApplyShape<Shape, Opts>>;
232
+ /**
233
+ * @internal
234
+ * Apply pick transformation to a TS record type.
235
+ */
236
+ type ApplyPickToRecord<R, PickOpt> = ResolveOptKeys<PickOpt> extends readonly string[] ? Pick<R, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof R> : R;
237
+ /**
238
+ * @internal
239
+ * Apply omit transformation to a TS record type.
240
+ */
241
+ type ApplyOmitToRecord<R, OmitOpt> = ResolveOptKeys<OmitOpt> extends readonly string[] ? Omit<R, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof R> : R;
242
+ /**
243
+ * @internal
244
+ * Apply pick/omit/partial transformations to a TypeScript record type.
245
+ * Mirrors ApplyShape but operates on TS types directly, not Zod shapes.
246
+ * Used for Zod v3/v4 compatible middleware input/output type computation.
247
+ */
248
+ type ApplyToRecord<R, Opts extends SchemaOptions | undefined> = Opts extends SchemaOptions ? HasOpt<Opts['pick']> extends true ? HasOpt<Opts['omit']> extends true ? Opts extends {
249
+ partial: true;
250
+ } ? Partial<ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']>> : ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']> : Opts extends {
251
+ partial: true;
252
+ } ? Partial<ApplyPickToRecord<R, Opts['pick']>> : ApplyPickToRecord<R, Opts['pick']> : HasOpt<Opts['omit']> extends true ? Opts extends {
253
+ partial: true;
254
+ } ? Partial<ApplyOmitToRecord<R, Opts['omit']>> : ApplyOmitToRecord<R, Opts['omit']> : Opts extends {
255
+ partial: true;
256
+ } ? Partial<R> : R : R;
145
257
  /**
146
258
  * @internal
147
259
  * Mirrors @hono/zod-validator's middleware Input type.
148
260
  * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.
149
261
  */
150
262
  type HasUndefined<T> = undefined extends T ? true : false;
151
- type ValidatorInput<Target extends keyof ValidationTargets, Schema extends z.ZodType<any, z.ZodTypeDef, any>, In = z.input<Schema>, Out = z.output<Schema>> = {
263
+ /**
264
+ * @internal
265
+ * Hono middleware input/output type for validator middleware.
266
+ * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.
267
+ *
268
+ * WARNING (Zod 4): `z.input<ZodTypeAny>` resolves to `unknown` in Zod 4, making
269
+ * `c.req.valid(target)` return `unknown` if `In`/`Out` are left as defaults.
270
+ * When using this type directly (outside of `ModelValidatorReturn`), always pass
271
+ * explicit `In` and `Out` type arguments — do NOT rely on the defaults.
272
+ *
273
+ * Internal usages in this file (ModelValidatorReturn and preset overloads) already
274
+ * pass `In`/`Out` explicitly via `ApplyToRecord` or `Omit<RowType<Fields>, ...>`.
275
+ */
276
+ type ValidatorInput<Target extends keyof ValidationTargets, Schema extends z.ZodTypeAny, In = z.input<Schema>, Out = z.output<Schema>> = {
152
277
  in: HasUndefined<In> extends true ? {
153
278
  [K in Target]?: (In extends ValidationTargets[K] ? In : {
154
279
  [K2 in keyof In]?: ValidationTargets[K][K2] | undefined;
@@ -166,8 +291,11 @@ type ValidatorInput<Target extends keyof ValidationTargets, Schema extends z.Zod
166
291
  * @internal
167
292
  * Type-safe Hono middleware handler return for Model.validator().
168
293
  * Provides proper type narrowing for c.req.valid(target).
294
+ *
295
+ * Uses RowType<Fields> directly for input/output type computation
296
+ * to ensure Zod v3/v4 compatibility (z.input<ZodTypeAny> returns unknown in Zod v4).
169
297
  */
170
- 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>>>;
298
+ 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>>>;
171
299
 
172
300
  /**
173
301
  * Represents a database model with type-safe schema derivation and CRUD operations.
@@ -184,22 +312,60 @@ interface Model<Fields extends Record<string, Field<any, any, any>>> {
184
312
  * const CreateSchema = User.schema({ omit: ['passwordHash'] })
185
313
  * const UpdateSchema = User.schema({ partial: true, pick: ['name', 'email'] })
186
314
  */
187
- schema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(opts?: Opts): Apply<FieldsToZodShape<Fields>, Opts>;
315
+ schema<Opts extends SchemaOptions<keyof Fields & string> | undefined>(opts?: Opts): Apply<FieldsToZodShape<Fields>, Opts>;
188
316
  /**
189
317
  * Returns a Hono middleware validator derived from this model's schema.
190
318
  * Integrates with @hono/zod-validator to validate request inputs.
191
319
  * The optional `hook` argument is passed through to @hono/zod-validator.
192
320
  *
321
+ * Accepts a preset ('create' | 'update') as second argument to use inputSchema.
322
+ * When a preset is used, the return type is a MiddlewareHandler (loosely typed in Phase 2A).
323
+ * Precise type narrowing for preset is deferred to Phase 2B M2.3.
324
+ *
193
325
  * @example
326
+ * app.post('/users', User.validator('json', 'create'), c => {
327
+ * const body = c.req.valid('json')
328
+ * })
194
329
  * app.post('/users', User.validator('json', { omit: ['passwordHash'] }), c => {
195
330
  * const body = c.req.valid('json')
196
331
  * })
197
- * // With hook for hardened error responses:
332
+ * // With hook:
198
333
  * app.post('/users', User.validator('json', opts, (result, c) => {
199
334
  * if (!result.success) return c.json({ error: 'Invalid request' }, 400)
200
335
  * }), handler)
201
336
  */
202
- 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>;
337
+ 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>>>;
338
+ 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>>>>;
339
+ 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>;
340
+ /**
341
+ * Returns a Zod schema for API input, with policy-based field exclusions applied.
342
+ * - 'create': serverOnly and readOnly fields are excluded
343
+ * - 'update': same exclusions + all fields become optional (partial: true)
344
+ *
345
+ * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.
346
+ */
347
+ 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>>;
348
+ 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 ? {
349
+ partial: true;
350
+ } : Opts & {
351
+ partial: true;
352
+ }>>;
353
+ inputSchema(usage: 'create' | 'update', opts?: SchemaOptions<keyof Fields & string>): z.ZodObject<z.ZodRawShape>;
354
+ /**
355
+ * Returns a Zod schema for API output, with policy-based field exclusions applied.
356
+ * - serverOnly and writeOnly fields are excluded
357
+ * - readOnly fields remain present
358
+ *
359
+ * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.
360
+ */
361
+ outputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(opts?: Opts): z.ZodObject<ApplyShape<Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'output'> & string>, Opts>>;
362
+ /**
363
+ * Parses a DB row through outputSchema and returns the safe response object.
364
+ * Equivalent to `User.outputSchema().parse(row)`.
365
+ */
366
+ toResponse(row: RowType<Fields>): unknown;
367
+ toOpenAPIComponent(): OpenAPIModelComponent;
368
+ toOpenAPISchema(usage: OpenAPIUsage): OpenAPISchemaObject;
203
369
  /**
204
370
  * Fetches multiple rows with pagination and optional ordering.
205
371
  * `limit` is required (no default) to prevent accidental unbounded queries.
@@ -285,8 +451,25 @@ interface NanokaModel<Fields extends Record<string, Field<any, any, any>>> {
285
451
  /**
286
452
  * Returns a Hono middleware validator for this model.
287
453
  * The optional `hook` argument is passed through to @hono/zod-validator.
454
+ * Accepts a preset ('create' | 'update') as second argument to use inputSchema.
455
+ */
456
+ 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>>>;
457
+ 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>>>>;
458
+ 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>;
459
+ /**
460
+ * Returns a Zod schema for API input, with policy-based field exclusions applied.
461
+ */
462
+ inputSchema(usage: 'create' | 'update', opts?: SchemaOptions<keyof Fields & string>): z.ZodObject<z.ZodRawShape>;
463
+ /**
464
+ * Returns a Zod schema for API output, with policy-based field exclusions applied.
465
+ */
466
+ outputSchema(opts?: SchemaOptions<keyof Fields & string>): z.ZodObject<z.ZodRawShape>;
467
+ /**
468
+ * Parses a DB row through outputSchema and returns the safe response object.
288
469
  */
289
- validator<Target extends keyof hono.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>;
470
+ toResponse(row: RowType<Fields>): unknown;
471
+ toOpenAPIComponent(): OpenAPIModelComponent;
472
+ toOpenAPISchema(usage: OpenAPIUsage): OpenAPISchemaObject;
290
473
  /**
291
474
  * Fetches multiple rows with pagination and optional ordering.
292
475
  * `limit` is required (no default) to prevent accidental unbounded queries.
@@ -318,7 +501,7 @@ interface NanokaModel<Fields extends Record<string, Field<any, any, any>>> {
318
501
  * Nanoka application: a Hono instance extended with model registration,
319
502
  * adapter binding, and escape hatches for raw Drizzle and batch operations.
320
503
  */
321
- interface Nanoka extends Hono {
504
+ interface Nanoka<E extends Env$1 = BlankEnv> extends Hono<E> {
322
505
  /**
323
506
  * Raw Drizzle database instance (escape hatch per rule #4).
324
507
  * Exposes the full Drizzle API for advanced queries.
@@ -361,6 +544,6 @@ interface Nanoka extends Hono {
361
544
  * }
362
545
  * }
363
546
  */
364
- declare function nanoka(adapter: Adapter): Nanoka;
547
+ declare function nanoka<E extends Env$1 = BlankEnv>(adapter: Adapter): Nanoka<E>;
365
548
 
366
- 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 };
549
+ export { type Adapter, type CreateInput, Field, FieldPolicy, type FindManyOptions, type IdOrWhere, InferFieldType, type Model, type Nanoka, type NanokaModel, type OpenAPIModelComponent, type OpenAPISchemaObject, type OpenAPIUsage, type OrderBy, type RowType, type SchemaOptions, type Where, d1Adapter, defineModel, nanoka };