@nanokajs/core 1.0.8 → 1.2.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/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to `@nanokajs/core` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.1.0] — 2026-05-04
9
+
10
+ ### Added
11
+
12
+ - Unified migration workflow: `nanoka generate` now automatically runs `drizzle-kit generate` when `drizzle.config.ts` (or `.js` / `.mjs`) is detected in the working directory.
13
+ - `--apply --db <name>` flag: runs the full pipeline (schema generation → `drizzle-kit generate` → `wrangler d1 migrations apply --local`) in one command.
14
+ - `--remote` flag: used with `--apply` to apply migrations remotely instead of locally.
15
+ - `--no-migrate` flag: skips `drizzle-kit generate`, running schema generation only.
16
+ - `--package-manager <pm>` flag: controls how sub-commands are invoked (`npx` default, `pnpm`, `npm`, `yarn`, `bun`).
17
+ - `NanokaConfig.migrate` field: optional config for `drizzleConfig`, `database`, and `packageManager` — can supply `--db` and `--package-manager` defaults via `nanoka.config.ts`.
18
+
8
19
  ## [1.0.2] — 2026-05-03
9
20
 
10
21
  ### Added
package/README.md CHANGED
@@ -133,8 +133,21 @@ Peer dependency ranges: `hono ^4.0.0`, `drizzle-orm ^0.45.0`, `zod ^3.23.0 || ^4
133
133
  })
134
134
  ```
135
135
 
136
- Then:
136
+ **Option A: unified pipeline (recommended)**
137
+ ```bash
138
+ npx nanoka generate --apply --db <DATABASE>
139
+ ```
140
+ When `drizzle.config.ts` is present, `nanoka generate` automatically runs `drizzle-kit generate`. Adding `--apply --db <DATABASE>` also runs `wrangler d1 migrations apply --local`.
141
+
142
+ **Option B: step by step**
143
+ ```bash
144
+ npx nanoka generate # schema generation + drizzle-kit generate (auto when drizzle.config.ts exists)
145
+ npx wrangler d1 migrations apply <DATABASE> --local
146
+ ```
147
+
148
+ **Option C: schema generation only**
137
149
  ```bash
150
+ npx nanoka generate --no-migrate # skips drizzle-kit
138
151
  npx drizzle-kit generate
139
152
  npx wrangler d1 migrations apply <DATABASE> --local
140
153
  ```
package/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import { realpathSync, promises } from 'fs';
3
3
  import { resolve, dirname } from 'path';
4
4
  import { pathToFileURL } from 'url';
5
5
  import { createJiti } from 'jiti';
6
+ import { spawn } from 'child_process';
6
7
 
7
8
  // src/cli/index.ts
8
9
 
@@ -120,25 +121,116 @@ async function loadConfig(configPath) {
120
121
  const mod = await jiti.import(configPath);
121
122
  return mod.default;
122
123
  }
124
+ var D1_DATABASE_NAME_RE = /^[A-Za-z0-9_-]{1,64}$/;
125
+ function validateDbName(db) {
126
+ if (!D1_DATABASE_NAME_RE.test(db)) {
127
+ throw new Error(
128
+ `Invalid D1 database name: "${db}". Only alphanumerics, hyphens, and underscores are allowed (max 64 chars).`
129
+ );
130
+ }
131
+ }
132
+ function resolveRunner(pm) {
133
+ switch (pm) {
134
+ case "pnpm":
135
+ return { cmd: "pnpm", prefix: ["exec"] };
136
+ case "npm":
137
+ return { cmd: "npm", prefix: ["exec"] };
138
+ case "yarn":
139
+ return { cmd: "yarn", prefix: ["dlx"] };
140
+ case "bun":
141
+ return { cmd: "bunx", prefix: [] };
142
+ case "npx":
143
+ return { cmd: "npx", prefix: [] };
144
+ default:
145
+ throw new Error(
146
+ `Unsupported package manager: "${pm}". Use one of: npx, pnpm, npm, yarn, bun.`
147
+ );
148
+ }
149
+ }
150
+ function runProcess(cmd, args, cwd) {
151
+ return new Promise((resolve2, reject) => {
152
+ const child = spawn(cmd, args, { stdio: "inherit", shell: false, cwd });
153
+ child.on("close", (code) => {
154
+ if (code === 0) {
155
+ resolve2();
156
+ } else {
157
+ reject(new Error(`Command '${cmd} ${args.join(" ")}' exited with code ${code}`));
158
+ }
159
+ });
160
+ child.on("error", (err) => {
161
+ reject(new Error(`Failed to spawn '${cmd}': ${err.message}`));
162
+ });
163
+ });
164
+ }
165
+ async function runDrizzleKitGenerate(opts) {
166
+ const { cmd, prefix } = resolveRunner(opts.pm);
167
+ const args = [...prefix, "drizzle-kit", "generate"];
168
+ if (opts.configPath) {
169
+ args.push("--config", opts.configPath);
170
+ }
171
+ await runProcess(cmd, args, opts.cwd);
172
+ }
173
+ async function runWranglerApply(opts) {
174
+ validateDbName(opts.db);
175
+ const { cmd, prefix } = resolveRunner(opts.pm);
176
+ const args = [...prefix, "wrangler", "d1", "migrations", "apply", opts.db];
177
+ args.push(opts.remote ? "--remote" : "--local");
178
+ await runProcess(cmd, args, opts.cwd);
179
+ }
123
180
 
124
181
  // src/cli/index.ts
182
+ async function findDrizzleConfig(cwd) {
183
+ const candidates = ["drizzle.config.ts", "drizzle.config.js", "drizzle.config.mjs"];
184
+ for (const name of candidates) {
185
+ try {
186
+ await promises.access(resolve(cwd, name));
187
+ return resolve(cwd, name);
188
+ } catch {
189
+ }
190
+ }
191
+ return void 0;
192
+ }
125
193
  async function main(args) {
126
194
  try {
127
195
  if (args.length === 0 || args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
128
- console.log("Usage: nanoka generate [--config <path>] [--output <path>]");
196
+ console.log(
197
+ "Usage: nanoka generate [--config <path>] [--output <path>] [--no-migrate] [--apply --db <name>] [--remote] [--package-manager <pm>]"
198
+ );
129
199
  console.log("");
130
200
  console.log("Options:");
131
- console.log(" --config <path> Path to nanoka.config.ts (default: ./nanoka.config.ts)");
132
- console.log(" --output <path> Output file path (overrides config.output)");
201
+ console.log(
202
+ " --config <path> Path to nanoka.config.ts (default: ./nanoka.config.ts)"
203
+ );
204
+ console.log(" --output <path> Output file path (overrides config.output)");
205
+ console.log(" --no-migrate Skip drizzle-kit generate (schema generation only)");
206
+ console.log(
207
+ " --apply Run wrangler d1 migrations apply after drizzle-kit generate"
208
+ );
209
+ console.log(
210
+ " --db <name> D1 database name for wrangler (required with --apply)"
211
+ );
212
+ console.log(
213
+ " --remote Apply migrations to remote instead of local (used with --apply)"
214
+ );
215
+ console.log(
216
+ " --package-manager <pm> Package manager to use: npx (default), pnpm, npm, yarn, bun"
217
+ );
133
218
  return 0;
134
219
  }
135
220
  if (args[0] !== "generate") {
136
221
  console.error(`Error: unknown command '${args[0]}'`);
137
- console.error("Usage: nanoka generate [--config <path>] [--output <path>]");
222
+ console.error(
223
+ "Usage: nanoka generate [--config <path>] [--output <path>] [--no-migrate] [--apply --db <name>] [--remote] [--package-manager <pm>]"
224
+ );
138
225
  return 1;
139
226
  }
140
227
  let configPath = "./nanoka.config.ts";
141
228
  let outputPath;
229
+ let noMigrate = false;
230
+ let apply = false;
231
+ let dbName;
232
+ let remote = false;
233
+ let packageManager = "npx";
142
234
  let i = 1;
143
235
  while (i < args.length) {
144
236
  if (args[i] === "--config" && i + 1 < args.length) {
@@ -149,19 +241,76 @@ async function main(args) {
149
241
  const next = args[i + 1];
150
242
  if (next !== void 0) outputPath = next;
151
243
  i += 2;
244
+ } else if (args[i] === "--no-migrate") {
245
+ noMigrate = true;
246
+ i += 1;
247
+ } else if (args[i] === "--apply") {
248
+ apply = true;
249
+ i += 1;
250
+ } else if (args[i] === "--db" && i + 1 < args.length) {
251
+ const next = args[i + 1];
252
+ if (next !== void 0) dbName = next;
253
+ i += 2;
254
+ } else if (args[i] === "--remote") {
255
+ remote = true;
256
+ i += 1;
257
+ } else if (args[i] === "--package-manager" && i + 1 < args.length) {
258
+ const next = args[i + 1];
259
+ if (next !== void 0) {
260
+ const validPms = ["npx", "pnpm", "npm", "yarn", "bun"];
261
+ if (!validPms.includes(next)) {
262
+ console.error(
263
+ `Error: unsupported package manager '${next}'. Use one of: ${validPms.join(", ")}`
264
+ );
265
+ return 1;
266
+ }
267
+ packageManager = next;
268
+ }
269
+ i += 2;
152
270
  } else {
153
271
  console.error(`Error: unknown option '${args[i]}'`);
154
272
  return 1;
155
273
  }
156
274
  }
157
- const absoluteConfigPath = resolve(process.cwd(), configPath);
275
+ const cwd = process.cwd();
276
+ const absoluteConfigPath = resolve(cwd, configPath);
158
277
  const config = await loadConfig(absoluteConfigPath);
159
278
  const finalOutputPath = outputPath ?? config.output ?? "./drizzle/schema.ts";
160
- const absoluteOutputPath = resolve(process.cwd(), finalOutputPath);
279
+ const absoluteOutputPath = resolve(cwd, finalOutputPath);
161
280
  const schema = generateDrizzleSchema(config.models);
162
281
  await promises.mkdir(dirname(absoluteOutputPath), { recursive: true });
163
282
  await promises.writeFile(absoluteOutputPath, schema, "utf-8");
164
283
  console.log(`\u2713 Generated ${absoluteOutputPath}`);
284
+ if (!noMigrate) {
285
+ const drizzleConfigPath = config.migrate?.drizzleConfig !== void 0 ? resolve(cwd, config.migrate.drizzleConfig) : await findDrizzleConfig(cwd);
286
+ if (drizzleConfigPath !== void 0) {
287
+ const pm = config.migrate?.packageManager ?? packageManager;
288
+ console.log("Running drizzle-kit generate...");
289
+ await runDrizzleKitGenerate({ cwd, configPath: drizzleConfigPath, pm });
290
+ console.log("\u2713 drizzle-kit generate completed");
291
+ } else {
292
+ console.log("No drizzle.config.ts found, skipping drizzle-kit generate");
293
+ }
294
+ }
295
+ if (apply) {
296
+ const resolvedDb = dbName ?? config.migrate?.database;
297
+ if (resolvedDb === void 0) {
298
+ console.error(
299
+ "Error: --db <name> \u3092\u6307\u5B9A\u3059\u308B\u304B nanoka.config.ts \u306E migrate.database \u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"
300
+ );
301
+ return 1;
302
+ }
303
+ try {
304
+ validateDbName(resolvedDb);
305
+ } catch (err) {
306
+ console.error(`Error: ${err instanceof Error ? err.message : err}`);
307
+ return 1;
308
+ }
309
+ const pm = config.migrate?.packageManager ?? packageManager;
310
+ console.log(`Running wrangler d1 migrations apply ${resolvedDb}...`);
311
+ await runWranglerApply({ cwd, db: resolvedDb, remote, pm });
312
+ console.log("\u2713 wrangler d1 migrations apply completed");
313
+ }
165
314
  return 0;
166
315
  } catch (error) {
167
316
  if (error instanceof Error) {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/codegen/render-field.ts","../src/codegen/generate.ts","../src/cli/load-config.ts","../src/cli/index.ts"],"names":["fs"],"mappings":"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","file":"cli.js","sourcesContent":["import type { Field } from '../field'\n\nexport function renderField(fieldName: string, field: Field<any, any, any>): string {\n const lines: string[] = []\n\n const kind = field.kind\n let colType: string\n\n if (kind === 'string' || kind === 'uuid') {\n colType = `text('${fieldName}')`\n } else if (kind === 'number') {\n colType = `real('${fieldName}')`\n } else if (kind === 'integer') {\n colType = `integer('${fieldName}')`\n } else if (kind === 'boolean') {\n colType = `integer('${fieldName}', { mode: 'boolean' })`\n } else if (kind === 'timestamp') {\n colType = `integer('${fieldName}', { mode: 'timestamp_ms' })`\n } else if (kind === 'json') {\n colType = `text('${fieldName}', { mode: 'json' }).$type<unknown>()`\n } else {\n throw new Error(`Unknown field kind: ${kind}`)\n }\n\n let column = colType\n\n if (field.modifiers.primary) {\n column += '.primaryKey()'\n }\n\n if (!field.modifiers.optional) {\n column += '.notNull()'\n }\n\n if (field.modifiers.unique) {\n column += '.unique()'\n }\n\n if (field.modifiers.hasDefault) {\n const defaultValue = field.modifiers.defaultValue\n if (typeof defaultValue === 'function') {\n console.warn(\n `[nanoka] Warning: field \"${fieldName}\" has a function default. Default clause will be omitted. ` +\n `Use Drizzle's $defaultFn() or .onUpdateCurrent() in your custom schema if needed.`,\n )\n } else {\n const serializedValue = JSON.stringify(defaultValue)\n column += `.default(${serializedValue})`\n }\n }\n\n lines.push(` ${fieldName}: ${column},`)\n return lines.join('\\n')\n}\n","import { renderField } from './render-field'\nimport type { ModelDef } from './types'\n\nconst USED_DRIZZLE_IMPORTS = {\n text: false,\n integer: false,\n real: false,\n sqliteTable: false,\n}\n\nfunction detectImports(\n models: readonly ModelDef[],\n): Record<keyof typeof USED_DRIZZLE_IMPORTS, boolean> {\n const imports = { ...USED_DRIZZLE_IMPORTS }\n\n for (const model of models) {\n for (const field of Object.values(model.fields)) {\n const kind = field.kind\n\n if (kind === 'string' || kind === 'uuid' || kind === 'json') {\n imports.text = true\n } else if (kind === 'number') {\n imports.real = true\n } else if (kind === 'integer' || kind === 'boolean' || kind === 'timestamp') {\n imports.integer = true\n }\n }\n\n if (Object.values(model.fields).length > 0) {\n imports.sqliteTable = true\n }\n }\n\n return imports\n}\n\nfunction buildImportStatement(imports: Record<keyof typeof USED_DRIZZLE_IMPORTS, boolean>): string {\n const used: string[] = []\n\n if (imports.integer) used.push('integer')\n if (imports.real) used.push('real')\n if (imports.sqliteTable) used.push('sqliteTable')\n if (imports.text) used.push('text')\n\n if (used.length === 0) {\n return \"import { sqliteTable } from 'drizzle-orm/sqlite-core'\"\n }\n\n return `import { ${used.join(', ')} } from 'drizzle-orm/sqlite-core'`\n}\n\nexport function generateDrizzleSchema(models: readonly ModelDef[]): string {\n const imports = detectImports(models)\n const importStatement = buildImportStatement(imports)\n\n const lines: string[] = [\n '// AUTO-GENERATED by `nanoka generate`. DO NOT EDIT BY HAND.',\n '// To regenerate: `npx nanoka generate`',\n importStatement,\n '',\n ]\n\n for (const model of models) {\n const fieldLines: string[] = []\n\n for (const [fieldName, field] of Object.entries(model.fields)) {\n fieldLines.push(renderField(fieldName, field))\n }\n\n const fieldsStr = fieldLines.length > 0 ? fieldLines.join('\\n') : ''\n const tableContent = fieldsStr ? `{\\n${fieldsStr}\\n}` : '{}'\n\n lines.push(`export const ${model.name} = sqliteTable('${model.name}', ${tableContent})`)\n lines.push('')\n }\n\n // Remove trailing empty line and add single newline at EOF\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop()\n }\n\n return `${lines.join('\\n')}\\n`\n}\n","import { createJiti } from 'jiti'\nimport type { NanokaConfig } from '../codegen/types'\n\nexport async function loadConfig(configPath: string): Promise<NanokaConfig> {\n const jiti = createJiti(import.meta.url, { interopDefault: true })\n const mod = await jiti.import<{ default: NanokaConfig }>(configPath)\n return mod.default\n}\n","import { promises as fs, realpathSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { generateDrizzleSchema } from '../codegen/generate'\nimport { loadConfig } from './load-config'\n\nasync function main(args: string[]): Promise<number> {\n try {\n if (args.length === 0 || args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {\n console.log('Usage: nanoka generate [--config <path>] [--output <path>]')\n console.log('')\n console.log('Options:')\n console.log(' --config <path> Path to nanoka.config.ts (default: ./nanoka.config.ts)')\n console.log(' --output <path> Output file path (overrides config.output)')\n return 0\n }\n\n if (args[0] !== 'generate') {\n console.error(`Error: unknown command '${args[0]}'`)\n console.error('Usage: nanoka generate [--config <path>] [--output <path>]')\n return 1\n }\n\n let configPath: string = './nanoka.config.ts'\n let outputPath: string | undefined\n\n let i = 1\n while (i < args.length) {\n if (args[i] === '--config' && i + 1 < args.length) {\n const next = args[i + 1]\n if (next !== undefined) configPath = next\n i += 2\n } else if (args[i] === '--output' && i + 1 < args.length) {\n const next = args[i + 1]\n if (next !== undefined) outputPath = next\n i += 2\n } else {\n console.error(`Error: unknown option '${args[i]}'`)\n return 1\n }\n }\n\n const absoluteConfigPath = resolve(process.cwd(), configPath)\n const config = await loadConfig(absoluteConfigPath)\n\n const finalOutputPath = outputPath ?? config.output ?? './drizzle/schema.ts'\n const absoluteOutputPath = resolve(process.cwd(), finalOutputPath)\n\n const schema = generateDrizzleSchema(config.models)\n\n await fs.mkdir(dirname(absoluteOutputPath), { recursive: true })\n await fs.writeFile(absoluteOutputPath, schema, 'utf-8')\n\n console.log(`✓ Generated ${absoluteOutputPath}`)\n return 0\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`)\n } else {\n console.error('Unknown error:', error)\n }\n return 1\n }\n}\n\n// Entry-point detection: compare realpath-resolved argv[1] (which may be a\n// symlink under pnpm/npm bin shims) with this module's URL. A naive\n// `file://${argv[1]}` comparison fails whenever the package is installed via\n// pnpm because node_modules entries are symlinks into the .pnpm store while\n// import.meta.url is always the resolved path.\nfunction isCliEntrypoint(): boolean {\n const argv1 = process.argv[1]\n if (!argv1) return false\n try {\n return pathToFileURL(realpathSync(argv1)).href === import.meta.url\n } catch {\n return false\n }\n}\n\nif (isCliEntrypoint()) {\n main(process.argv.slice(2)).then((code) => {\n process.exit(code)\n })\n}\n\nexport { main }\n"]}
1
+ {"version":3,"sources":["../src/codegen/render-field.ts","../src/codegen/generate.ts","../src/cli/load-config.ts","../src/cli/run.ts","../src/cli/index.ts"],"names":["resolve","fs"],"mappings":"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","file":"cli.js","sourcesContent":["import type { Field } from '../field'\n\nexport function renderField(fieldName: string, field: Field<any, any, any>): string {\n const lines: string[] = []\n\n const kind = field.kind\n let colType: string\n\n if (kind === 'string' || kind === 'uuid') {\n colType = `text('${fieldName}')`\n } else if (kind === 'number') {\n colType = `real('${fieldName}')`\n } else if (kind === 'integer') {\n colType = `integer('${fieldName}')`\n } else if (kind === 'boolean') {\n colType = `integer('${fieldName}', { mode: 'boolean' })`\n } else if (kind === 'timestamp') {\n colType = `integer('${fieldName}', { mode: 'timestamp_ms' })`\n } else if (kind === 'json') {\n colType = `text('${fieldName}', { mode: 'json' }).$type<unknown>()`\n } else {\n throw new Error(`Unknown field kind: ${kind}`)\n }\n\n let column = colType\n\n if (field.modifiers.primary) {\n column += '.primaryKey()'\n }\n\n if (!field.modifiers.optional) {\n column += '.notNull()'\n }\n\n if (field.modifiers.unique) {\n column += '.unique()'\n }\n\n if (field.modifiers.hasDefault) {\n const defaultValue = field.modifiers.defaultValue\n if (typeof defaultValue === 'function') {\n console.warn(\n `[nanoka] Warning: field \"${fieldName}\" has a function default. Default clause will be omitted. ` +\n `Use Drizzle's $defaultFn() or .onUpdateCurrent() in your custom schema if needed.`,\n )\n } else {\n const serializedValue = JSON.stringify(defaultValue)\n column += `.default(${serializedValue})`\n }\n }\n\n lines.push(` ${fieldName}: ${column},`)\n return lines.join('\\n')\n}\n","import { renderField } from './render-field'\nimport type { ModelDef } from './types'\n\nconst USED_DRIZZLE_IMPORTS = {\n text: false,\n integer: false,\n real: false,\n sqliteTable: false,\n}\n\nfunction detectImports(\n models: readonly ModelDef[],\n): Record<keyof typeof USED_DRIZZLE_IMPORTS, boolean> {\n const imports = { ...USED_DRIZZLE_IMPORTS }\n\n for (const model of models) {\n for (const field of Object.values(model.fields)) {\n const kind = field.kind\n\n if (kind === 'string' || kind === 'uuid' || kind === 'json') {\n imports.text = true\n } else if (kind === 'number') {\n imports.real = true\n } else if (kind === 'integer' || kind === 'boolean' || kind === 'timestamp') {\n imports.integer = true\n }\n }\n\n if (Object.values(model.fields).length > 0) {\n imports.sqliteTable = true\n }\n }\n\n return imports\n}\n\nfunction buildImportStatement(imports: Record<keyof typeof USED_DRIZZLE_IMPORTS, boolean>): string {\n const used: string[] = []\n\n if (imports.integer) used.push('integer')\n if (imports.real) used.push('real')\n if (imports.sqliteTable) used.push('sqliteTable')\n if (imports.text) used.push('text')\n\n if (used.length === 0) {\n return \"import { sqliteTable } from 'drizzle-orm/sqlite-core'\"\n }\n\n return `import { ${used.join(', ')} } from 'drizzle-orm/sqlite-core'`\n}\n\nexport function generateDrizzleSchema(models: readonly ModelDef[]): string {\n const imports = detectImports(models)\n const importStatement = buildImportStatement(imports)\n\n const lines: string[] = [\n '// AUTO-GENERATED by `nanoka generate`. DO NOT EDIT BY HAND.',\n '// To regenerate: `npx nanoka generate`',\n importStatement,\n '',\n ]\n\n for (const model of models) {\n const fieldLines: string[] = []\n\n for (const [fieldName, field] of Object.entries(model.fields)) {\n fieldLines.push(renderField(fieldName, field))\n }\n\n const fieldsStr = fieldLines.length > 0 ? fieldLines.join('\\n') : ''\n const tableContent = fieldsStr ? `{\\n${fieldsStr}\\n}` : '{}'\n\n lines.push(`export const ${model.name} = sqliteTable('${model.name}', ${tableContent})`)\n lines.push('')\n }\n\n // Remove trailing empty line and add single newline at EOF\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop()\n }\n\n return `${lines.join('\\n')}\\n`\n}\n","import { createJiti } from 'jiti'\nimport type { NanokaConfig } from '../codegen/types'\n\nexport async function loadConfig(configPath: string): Promise<NanokaConfig> {\n const jiti = createJiti(import.meta.url, { interopDefault: true })\n const mod = await jiti.import<{ default: NanokaConfig }>(configPath)\n return mod.default\n}\n","import { spawn } from 'node:child_process'\n\nconst D1_DATABASE_NAME_RE = /^[A-Za-z0-9_-]{1,64}$/\n\nexport function validateDbName(db: string): void {\n if (!D1_DATABASE_NAME_RE.test(db)) {\n throw new Error(\n `Invalid D1 database name: \"${db}\". Only alphanumerics, hyphens, and underscores are allowed (max 64 chars).`,\n )\n }\n}\n\nfunction resolveRunner(pm: string): { cmd: string; prefix: string[] } {\n switch (pm) {\n case 'pnpm':\n return { cmd: 'pnpm', prefix: ['exec'] }\n case 'npm':\n return { cmd: 'npm', prefix: ['exec'] }\n case 'yarn':\n return { cmd: 'yarn', prefix: ['dlx'] }\n case 'bun':\n return { cmd: 'bunx', prefix: [] }\n case 'npx':\n return { cmd: 'npx', prefix: [] }\n default:\n throw new Error(\n `Unsupported package manager: \"${pm}\". Use one of: npx, pnpm, npm, yarn, bun.`,\n )\n }\n}\n\nfunction runProcess(cmd: string, args: string[], cwd: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd, args, { stdio: 'inherit', shell: false, cwd })\n child.on('close', (code) => {\n if (code === 0) {\n resolve()\n } else {\n reject(new Error(`Command '${cmd} ${args.join(' ')}' exited with code ${code}`))\n }\n })\n child.on('error', (err) => {\n reject(new Error(`Failed to spawn '${cmd}': ${err.message}`))\n })\n })\n}\n\nexport async function runDrizzleKitGenerate(opts: {\n cwd: string\n configPath?: string\n pm: string\n}): Promise<void> {\n const { cmd, prefix } = resolveRunner(opts.pm)\n const args = [...prefix, 'drizzle-kit', 'generate']\n if (opts.configPath) {\n args.push('--config', opts.configPath)\n }\n await runProcess(cmd, args, opts.cwd)\n}\n\nexport async function runWranglerApply(opts: {\n cwd: string\n db: string\n remote: boolean\n pm: string\n}): Promise<void> {\n validateDbName(opts.db)\n const { cmd, prefix } = resolveRunner(opts.pm)\n const args = [...prefix, 'wrangler', 'd1', 'migrations', 'apply', opts.db]\n args.push(opts.remote ? '--remote' : '--local')\n await runProcess(cmd, args, opts.cwd)\n}\n","import { promises as fs, realpathSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { generateDrizzleSchema } from '../codegen/generate'\nimport { loadConfig } from './load-config'\nimport { runDrizzleKitGenerate, runWranglerApply, validateDbName } from './run'\n\nasync function findDrizzleConfig(cwd: string): Promise<string | undefined> {\n const candidates = ['drizzle.config.ts', 'drizzle.config.js', 'drizzle.config.mjs']\n for (const name of candidates) {\n try {\n await fs.access(resolve(cwd, name))\n return resolve(cwd, name)\n } catch {\n // not found, try next\n }\n }\n return undefined\n}\n\nasync function main(args: string[]): Promise<number> {\n try {\n if (args.length === 0 || args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {\n console.log(\n 'Usage: nanoka generate [--config <path>] [--output <path>] [--no-migrate] [--apply --db <name>] [--remote] [--package-manager <pm>]',\n )\n console.log('')\n console.log('Options:')\n console.log(\n ' --config <path> Path to nanoka.config.ts (default: ./nanoka.config.ts)',\n )\n console.log(' --output <path> Output file path (overrides config.output)')\n console.log(' --no-migrate Skip drizzle-kit generate (schema generation only)')\n console.log(\n ' --apply Run wrangler d1 migrations apply after drizzle-kit generate',\n )\n console.log(\n ' --db <name> D1 database name for wrangler (required with --apply)',\n )\n console.log(\n ' --remote Apply migrations to remote instead of local (used with --apply)',\n )\n console.log(\n ' --package-manager <pm> Package manager to use: npx (default), pnpm, npm, yarn, bun',\n )\n return 0\n }\n\n if (args[0] !== 'generate') {\n console.error(`Error: unknown command '${args[0]}'`)\n console.error(\n 'Usage: nanoka generate [--config <path>] [--output <path>] [--no-migrate] [--apply --db <name>] [--remote] [--package-manager <pm>]',\n )\n return 1\n }\n\n let configPath: string = './nanoka.config.ts'\n let outputPath: string | undefined\n let noMigrate = false\n let apply = false\n let dbName: string | undefined\n let remote = false\n let packageManager: string = 'npx'\n\n let i = 1\n while (i < args.length) {\n if (args[i] === '--config' && i + 1 < args.length) {\n const next = args[i + 1]\n if (next !== undefined) configPath = next\n i += 2\n } else if (args[i] === '--output' && i + 1 < args.length) {\n const next = args[i + 1]\n if (next !== undefined) outputPath = next\n i += 2\n } else if (args[i] === '--no-migrate') {\n noMigrate = true\n i += 1\n } else if (args[i] === '--apply') {\n apply = true\n i += 1\n } else if (args[i] === '--db' && i + 1 < args.length) {\n const next = args[i + 1]\n if (next !== undefined) dbName = next\n i += 2\n } else if (args[i] === '--remote') {\n remote = true\n i += 1\n } else if (args[i] === '--package-manager' && i + 1 < args.length) {\n const next = args[i + 1]\n if (next !== undefined) {\n const validPms = ['npx', 'pnpm', 'npm', 'yarn', 'bun']\n if (!validPms.includes(next)) {\n console.error(\n `Error: unsupported package manager '${next}'. Use one of: ${validPms.join(', ')}`,\n )\n return 1\n }\n packageManager = next\n }\n i += 2\n } else {\n console.error(`Error: unknown option '${args[i]}'`)\n return 1\n }\n }\n\n const cwd = process.cwd()\n const absoluteConfigPath = resolve(cwd, configPath)\n const config = await loadConfig(absoluteConfigPath)\n\n const finalOutputPath = outputPath ?? config.output ?? './drizzle/schema.ts'\n const absoluteOutputPath = resolve(cwd, finalOutputPath)\n\n const schema = generateDrizzleSchema(config.models)\n\n await fs.mkdir(dirname(absoluteOutputPath), { recursive: true })\n await fs.writeFile(absoluteOutputPath, schema, 'utf-8')\n\n console.log(`✓ Generated ${absoluteOutputPath}`)\n\n if (!noMigrate) {\n const drizzleConfigPath =\n config.migrate?.drizzleConfig !== undefined\n ? resolve(cwd, config.migrate.drizzleConfig)\n : await findDrizzleConfig(cwd)\n\n if (drizzleConfigPath !== undefined) {\n const pm = config.migrate?.packageManager ?? packageManager\n console.log('Running drizzle-kit generate...')\n await runDrizzleKitGenerate({ cwd, configPath: drizzleConfigPath, pm })\n console.log('✓ drizzle-kit generate completed')\n } else {\n console.log('No drizzle.config.ts found, skipping drizzle-kit generate')\n }\n }\n\n if (apply) {\n const resolvedDb = dbName ?? config.migrate?.database\n if (resolvedDb === undefined) {\n console.error(\n 'Error: --db <name> を指定するか nanoka.config.ts の migrate.database に設定してください',\n )\n return 1\n }\n try {\n validateDbName(resolvedDb)\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : err}`)\n return 1\n }\n\n const pm = config.migrate?.packageManager ?? packageManager\n console.log(`Running wrangler d1 migrations apply ${resolvedDb}...`)\n await runWranglerApply({ cwd, db: resolvedDb, remote, pm })\n console.log('✓ wrangler d1 migrations apply completed')\n }\n\n return 0\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`)\n } else {\n console.error('Unknown error:', error)\n }\n return 1\n }\n}\n\n// Entry-point detection: compare realpath-resolved argv[1] (which may be a\n// symlink under pnpm/npm bin shims) with this module's URL. A naive\n// `file://${argv[1]}` comparison fails whenever the package is installed via\n// pnpm because node_modules entries are symlinks into the .pnpm store while\n// import.meta.url is always the resolved path.\nfunction isCliEntrypoint(): boolean {\n const argv1 = process.argv[1]\n if (!argv1) return false\n try {\n return pathToFileURL(realpathSync(argv1)).href === import.meta.url\n } catch {\n return false\n }\n}\n\nif (isCliEntrypoint()) {\n main(process.argv.slice(2)).then((code) => {\n process.exit(code)\n })\n}\n\nexport { main }\n"]}
package/dist/config.d.ts CHANGED
@@ -10,6 +10,11 @@ interface ModelDef {
10
10
  interface NanokaConfig {
11
11
  readonly output?: string | undefined;
12
12
  readonly models: readonly ModelDef[];
13
+ readonly migrate?: {
14
+ readonly drizzleConfig?: string;
15
+ readonly database?: string;
16
+ readonly packageManager?: 'npx' | 'pnpm' | 'npm' | 'yarn' | 'bun';
17
+ };
13
18
  }
14
19
 
15
20
  declare function defineConfig(config: NanokaConfig): NanokaConfig;
package/dist/index.d.ts CHANGED
@@ -7,7 +7,8 @@ import { SQLiteTableWithColumns, AnySQLiteColumn } 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
- import { Env as Env$1, BlankEnv } from 'hono/types';
10
+ import * as hono_types from 'hono/types';
11
+ import { Env as Env$1, BlankEnv, H, HandlerInterface } from 'hono/types';
11
12
  import 'drizzle-orm/batch';
12
13
 
13
14
  /**
@@ -60,6 +61,7 @@ interface OpenAPIRouteMetadata {
60
61
  readonly params?: OpenAPIParamSpec[];
61
62
  readonly responses: Record<string, OpenAPIResponseSpec>;
62
63
  }
64
+ type RouteOpenAPIMetadata = Omit<OpenAPIRouteMetadata, 'path' | 'method'>;
63
65
  interface OpenAPISpecOptions {
64
66
  readonly info: {
65
67
  readonly title: string;
@@ -545,6 +547,13 @@ interface NanokaModel<Fields extends Record<string, Field<any, any, any>>> {
545
547
  readonly deleted: number;
546
548
  }>;
547
549
  }
550
+ /**
551
+ * Inline OpenAPI metadata option accepted as the second argument to
552
+ * app.get/post/put/patch/delete when registering a route with OpenAPI.
553
+ */
554
+ interface RouteOpenAPIOption {
555
+ readonly openapi: RouteOpenAPIMetadata;
556
+ }
548
557
  /**
549
558
  * Nanoka application: a Hono instance extended with model registration,
550
559
  * adapter binding, and escape hatches for raw Drizzle and batch operations.
@@ -580,6 +589,11 @@ interface Nanoka<E extends Env$1 = BlankEnv> extends Hono<E> {
580
589
  * Builds the full OpenAPI 3.1 document from all registered openapi() metadata.
581
590
  */
582
591
  generateOpenAPISpec(options: OpenAPISpecOptions): OpenAPIDocument;
592
+ get: ((path: string, meta: RouteOpenAPIOption, ...handlers: H[]) => this) & HandlerInterface<E, 'get', hono_types.BlankSchema, '/'>;
593
+ post: ((path: string, meta: RouteOpenAPIOption, ...handlers: H[]) => this) & HandlerInterface<E, 'post', hono_types.BlankSchema, '/'>;
594
+ put: ((path: string, meta: RouteOpenAPIOption, ...handlers: H[]) => this) & HandlerInterface<E, 'put', hono_types.BlankSchema, '/'>;
595
+ patch: ((path: string, meta: RouteOpenAPIOption, ...handlers: H[]) => this) & HandlerInterface<E, 'patch', hono_types.BlankSchema, '/'>;
596
+ delete: ((path: string, meta: RouteOpenAPIOption, ...handlers: H[]) => this) & HandlerInterface<E, 'delete', hono_types.BlankSchema, '/'>;
583
597
  }
584
598
 
585
599
  /**
@@ -603,4 +617,4 @@ interface Nanoka<E extends Env$1 = BlankEnv> extends Hono<E> {
603
617
  */
604
618
  declare function nanoka<E extends Env$1 = BlankEnv>(adapter: Adapter): Nanoka<E>;
605
619
 
606
- 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 };
620
+ 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 RouteOpenAPIMetadata, type RouteOpenAPIOption, type RowType, type SchemaOptions, type Where, d1Adapter, defineModel, nanoka, swaggerUI };
package/dist/index.js CHANGED
@@ -627,6 +627,20 @@ function nanoka(adapter) {
627
627
  return app;
628
628
  };
629
629
  app.generateOpenAPISpec = (options) => buildOpenAPIDocument(openapiRoutes, options);
630
+ function wrapWithOpenAPI(method) {
631
+ const original = app[method].bind(app);
632
+ app[method] = (path, second, ...rest) => {
633
+ if (second !== null && typeof second === "object" && !Array.isArray(second) && typeof second.openapi === "object") {
634
+ const { openapi } = second;
635
+ openapiRoutes.push({ ...openapi, path, method });
636
+ return original(path, ...rest);
637
+ }
638
+ return original(path, second, ...rest);
639
+ };
640
+ }
641
+ for (const method of ["get", "post", "put", "patch", "delete"]) {
642
+ wrapWithOpenAPI(method);
643
+ }
630
644
  app.model = function model(name, fields) {
631
645
  const inner = defineModel(name, fields);
632
646
  return {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter/d1.ts","../src/model/types.ts","../src/model/schema.ts","../src/openapi/generate.ts","../src/model/crud.ts","../src/model/table.ts","../src/model/define.ts","../src/openapi/route.ts","../src/openapi/swagger-ui.ts","../src/router/nanoka.ts"],"names":["partial","combinedOmit"],"mappings":"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","file":"index.js","sourcesContent":["import type { D1Database } from '@cloudflare/workers-types'\nimport { drizzle } from 'drizzle-orm/d1'\nimport type { Adapter } from './types'\n\n/**\n * D1-specific adapter factory. Wraps Cloudflare D1 binding in the generic\n * Adapter abstraction, enabling the core query path and router to remain\n * implementation-agnostic.\n */\nexport function d1Adapter<TSchema extends Record<string, unknown> = Record<string, never>>(\n d1: D1Database,\n): Adapter<TSchema> {\n // drizzle-orm/d1's drizzle() returns DrizzleD1Database which embeds D1-specific\n // result types. We cast to BaseSQLiteDatabase via the Adapter interface to keep\n // the D1 dependency local to this file (see CLAUDE.md rule #3). Consumers receive\n // the typed Adapter interface, so this `any` is intentionally local.\n //\n // Note: drizzle-orm/d1 internally stores the D1 binding in db.$client. When\n // handling multiple D1 bindings, call d1Adapter() fresh for each binding rather\n // than caching the return value across binding switches.\n // biome-ignore lint/suspicious/noExplicitAny: intentional - Drizzle returns complex union type\n const db = drizzle(d1) as any\n\n return {\n drizzle: db,\n batch: (queries) => db.batch(queries),\n }\n}\n","import type { Hook } from '@hono/zod-validator'\nimport type { AnySQLiteColumn, SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'\nimport type { Env, MiddlewareHandler, ValidationTargets } from 'hono'\nimport type { z } from 'zod'\nimport type { Adapter } from '../adapter/types'\nimport type { Field, FieldPolicy, InferFieldType } from '../field/types'\nimport type { OpenAPIModelComponent, OpenAPISchemaObject, OpenAPIUsage } from '../openapi/types'\n\n/**\n * Options for findMany query.\n * `limit` is required (no default).\n * `offset` defaults to 0 if omitted.\n * `orderBy` is optional for column ordering.\n */\nexport interface FindManyOptions<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> {\n readonly limit: number\n readonly offset?: number\n readonly orderBy?: OrderBy<Fields>\n}\n\n/**\n * Order-by specification: single field, or field with direction, or array of multiple.\n */\nexport type OrderBy<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> =\n | (keyof Fields & string)\n | { readonly column: keyof Fields & string; readonly direction?: 'asc' | 'desc' }\n | ReadonlyArray<\n | (keyof Fields & string)\n | { readonly column: keyof Fields & string; readonly direction?: 'asc' | 'desc' }\n >\n\n/**\n * Where clause object: each key is a field name, each value is the desired equality.\n */\nexport type Where<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n readonly [K in keyof Fields]?: InferFieldType<Fields[K]>\n}\n\n/**\n * Identifier or Where clause: can be a primary key value or a Where object.\n */\nexport type IdOrWhere<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = string | number | Where<Fields>\n\n/**\n * Row type: full record type from fields.\n */\nexport type RowType<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n [K in keyof Fields]: InferFieldType<Fields[K]>\n}\n\n/**\n * Drizzle table type with columns typed to match the model's Fields.\n * Allows type-safe column access via Model.table.fieldName.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\nexport type ModelTable<Fields extends Record<string, Field<any, any, any>>> =\n SQLiteTableWithColumns<{\n name: string\n schema: undefined\n columns: { [K in keyof Fields]: AnySQLiteColumn }\n dialect: 'sqlite'\n }>\n\n/**\n * @internal\n * Extracts the policy from a Field's modifiers.\n *\n * Uses `Field<any, { policy: infer P }, any>` rather than a two-step\n * `infer M` + `M extends { policy: infer P }` pattern.\n * The two-step pattern is broken when TypeScript widens `M` to the constraint\n * `FieldModifiers` (which has `policy?: FieldPolicy` as optional), causing\n * `M extends { policy: infer P }` to be true for ALL fields regardless of their\n * actual policy value. Directly matching `{ policy: infer P }` avoids this.\n */\ntype PolicyOf<F> =\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { policy: infer P extends FieldPolicy }, any> ? P : never\n\n/**\n * @internal\n * Computes which field keys should be omitted based on policy and usage.\n * Mirrors the runtime logic in derivePolicyOptions() in schema.ts.\n *\n * NOTE: `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) is used to\n * short-circuit fields with no policy to `never` (do not omit). Without this guard,\n * `never extends 'serverOnly'` evaluates to `true` (vacuously), causing every field\n * without a policy to be incorrectly included in the omit set.\n */\nexport type PolicyOmitKeys<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n Usage extends 'input-create' | 'input-update' | 'output',\n> = {\n [K in keyof Fields]: [PolicyOf<Fields[K]>] extends [never]\n ? never\n : PolicyOf<Fields[K]> extends 'serverOnly'\n ? K\n : Usage extends 'output'\n ? PolicyOf<Fields[K]> extends 'writeOnly'\n ? K\n : never\n : Usage extends 'input-create' | 'input-update'\n ? PolicyOf<Fields[K]> extends 'readOnly'\n ? K\n : never\n : never\n}[keyof Fields]\n\n/**\n * @internal\n * Computes which field keys have the serverOnly policy.\n * serverOnly fields are completely excluded from CreateInput\n * (cannot be passed even from library internals — they are server-side only).\n *\n * Uses `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) to short-circuit\n * fields with no policy to `never`. Without this guard, `never extends 'serverOnly'`\n * evaluates to `true` (vacuously), causing every field without a policy to be included.\n */\ntype ServerOnlyKeys<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n [K in keyof Fields]: [PolicyOf<Fields[K]>] extends [never]\n ? never\n : PolicyOf<Fields[K]> extends 'serverOnly'\n ? K\n : never\n}[keyof Fields]\n\n/**\n * @internal\n * Determines if a field is required for create input.\n * A field is optional if it has a default, is optional, or is readOnly.\n *\n * Uses direct shape matching (`Field<any, { hasDefault: true }, any>`) to avoid\n * the TypeScript infer-widening issue where `infer M` resolves to `FieldModifiers`\n * (the constraint bound) instead of the concrete Mods type, causing `M extends\n * { policy: 'readOnly' }` to be false even for readOnly fields.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\ntype IsRequired<F extends Field<any, any, any>> =\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { hasDefault: true }, any>\n ? false\n : // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { optional: true }, any>\n ? false\n : // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { policy: 'readOnly' }, any>\n ? false\n : true\n\n/**\n * Create input with precise types:\n * - `readOnly` fields are optional (library internals can pass them; API callers\n * are excluded via inputSchema — but CreateInput itself keeps them as optional\n * so handlers can supply generated values like `id` or `createdAt`)\n * - fields with `default` are optional\n * - fields marked `optional` are optional\n * - all other fields are required\n * - `serverOnly` fields are completely excluded (cannot be passed even internally)\n * - `writeOnly` fields are included as required (they are input fields by design)\n */\nexport type CreateInput<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n [K in keyof Fields as IsRequired<Fields[K]> extends true\n ? K extends ServerOnlyKeys<Fields>\n ? never\n : K\n : never]: InferFieldType<Fields[K]>\n} & {\n [K in keyof Fields as IsRequired<Fields[K]> extends true\n ? never\n : K extends ServerOnlyKeys<Fields>\n ? never\n : K]?: InferFieldType<Fields[K]>\n}\n\nexport type FieldAccessor<K extends string> = { readonly [Key in K]: Key }\n\nexport interface SchemaOptions<K extends string = string> {\n readonly pick?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[])\n readonly omit?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[])\n readonly partial?: boolean\n}\n\n/**\n * @internal\n * Resolves pick/omit option to string array using the accessor when it's a function.\n */\nexport function resolveSchemaOptionKeys<K extends string>(\n opt: readonly K[] | ((f: FieldAccessor<K>) => readonly K[]) | undefined,\n accessor: FieldAccessor<K>,\n): readonly K[] | undefined {\n if (opt === undefined) return undefined\n if (typeof opt === 'function') return opt(accessor)\n return opt\n}\n\n/**\n * @internal\n * Builds a frozen field accessor object for use in schema/validator options.\n * Each key maps to itself, providing typo detection at type level.\n */\nexport function buildFieldAccessor<Fields extends Record<string, unknown>>(\n fields: Fields,\n): { readonly [K in keyof Fields]: K } {\n const acc: Record<string, string> = {}\n for (const k of Object.keys(fields)) acc[k] = k\n return Object.freeze(acc) as { readonly [K in keyof Fields]: K }\n}\n\n/**\n * @internal\n * Extracts a Zod shape from fields for the Apply type.\n * Each field's zodBase becomes a property in the shape.\n * Indexed access ensures concrete Zod types are preserved (not `any`).\n */\nexport type FieldsToZodShape<\n Fields extends Record<\n string,\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Field<any, any, any>\n >,\n> = {\n [K in keyof Fields]: Fields[K]['zodBase']\n}\n\n/**\n * @internal\n * Utility to narrow array literal types to union of strings.\n */\ntype ArrayKeys<A> = A extends readonly (infer U)[] ? U : never\n\n/**\n * @internal\n * Resolves pick/omit option type to the array type.\n * Handles both array form and accessor function form.\n */\ntype ResolveOptKeys<Opt> = Opt extends readonly string[]\n ? Opt\n : Opt extends (f: FieldAccessor<infer _K>) => readonly (infer R)[]\n ? readonly R[]\n : never\n\n/**\n * @internal\n * Apply pick transformation to a shape.\n */\ntype ApplyPickToShape<Shape extends z.ZodRawShape, PickOpt> =\n ResolveOptKeys<PickOpt> extends readonly string[]\n ? Pick<Shape, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof Shape>\n : Shape\n\n/**\n * @internal\n * Apply omit transformation to a shape.\n */\ntype ApplyOmitToShape<Shape extends z.ZodRawShape, OmitOpt> =\n ResolveOptKeys<OmitOpt> extends readonly string[]\n ? Omit<Shape, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof Shape>\n : Shape\n\n/**\n * @internal\n * Apply partial transformation to a shape.\n */\ntype ApplyPartialToShape<Shape extends z.ZodRawShape> = {\n [K in keyof Shape]: z.ZodOptional<Shape[K]>\n}\n\n/**\n * @internal\n * Checks if an option value (array or function) is present (i.e. not undefined and not never).\n * Uses distributive conditional to handle union types like `T | undefined`.\n */\ntype HasOpt<Opt> = undefined extends Opt ? false : [Opt] extends [never] ? false : true\n\n/**\n * @internal\n * Apply pick/omit/partial transformations to a Zod raw shape.\n * Order: pick → omit → partial\n * Handles both array form and accessor function form for pick/omit.\n */\ntype ApplyShape<\n Shape extends z.ZodRawShape,\n Opts extends SchemaOptions | undefined,\n> = Opts extends SchemaOptions\n ? HasOpt<Opts['pick']> extends true\n ? HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? ApplyPartialToShape<ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']>>\n : ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']>\n : Opts extends { partial: true }\n ? ApplyPartialToShape<ApplyPickToShape<Shape, Opts['pick']>>\n : ApplyPickToShape<Shape, Opts['pick']>\n : HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? ApplyPartialToShape<ApplyOmitToShape<Shape, Opts['omit']>>\n : ApplyOmitToShape<Shape, Opts['omit']>\n : Opts extends { partial: true }\n ? ApplyPartialToShape<Shape>\n : Shape\n : Shape\n\n/**\n * @internal\n * Returns the correct Zod object type after applying pick/omit/partial transformations.\n */\nexport type Apply<\n Shape extends z.ZodRawShape,\n Opts extends SchemaOptions | undefined,\n> = z.ZodObject<ApplyShape<Shape, Opts>>\n\n/**\n * @internal\n * Apply pick transformation to a TS record type.\n */\ntype ApplyPickToRecord<R, PickOpt> =\n ResolveOptKeys<PickOpt> extends readonly string[]\n ? Pick<R, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof R>\n : R\n\n/**\n * @internal\n * Apply omit transformation to a TS record type.\n */\ntype ApplyOmitToRecord<R, OmitOpt> =\n ResolveOptKeys<OmitOpt> extends readonly string[]\n ? Omit<R, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof R>\n : R\n\n/**\n * @internal\n * Apply pick/omit/partial transformations to a TypeScript record type.\n * Mirrors ApplyShape but operates on TS types directly, not Zod shapes.\n * Used for Zod v3/v4 compatible middleware input/output type computation.\n */\ntype ApplyToRecord<R, Opts extends SchemaOptions | undefined> = Opts extends SchemaOptions\n ? HasOpt<Opts['pick']> extends true\n ? HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? Partial<ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']>>\n : ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']>\n : Opts extends { partial: true }\n ? Partial<ApplyPickToRecord<R, Opts['pick']>>\n : ApplyPickToRecord<R, Opts['pick']>\n : HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? Partial<ApplyOmitToRecord<R, Opts['omit']>>\n : ApplyOmitToRecord<R, Opts['omit']>\n : Opts extends { partial: true }\n ? Partial<R>\n : R\n : R\n\n/**\n * @internal\n * Mirrors @hono/zod-validator's middleware Input type.\n * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.\n */\ntype HasUndefined<T> = undefined extends T ? true : false\n\n/**\n * @internal\n * Hono middleware input/output type for validator middleware.\n * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.\n *\n * WARNING (Zod 4): `z.input<ZodTypeAny>` resolves to `unknown` in Zod 4, making\n * `c.req.valid(target)` return `unknown` if `In`/`Out` are left as defaults.\n * When using this type directly (outside of `ModelValidatorReturn`), always pass\n * explicit `In` and `Out` type arguments — do NOT rely on the defaults.\n *\n * Internal usages in this file (ModelValidatorReturn and preset overloads) already\n * pass `In`/`Out` explicitly via `ApplyToRecord` or `Omit<RowType<Fields>, ...>`.\n */\nexport type ValidatorInput<\n Target extends keyof ValidationTargets,\n Schema extends z.ZodTypeAny,\n In = z.input<Schema>,\n Out = z.output<Schema>,\n> = {\n in: HasUndefined<In> extends true\n ? {\n [K in Target]?:\n | (In extends ValidationTargets[K]\n ? In\n : { [K2 in keyof In]?: ValidationTargets[K][K2] | undefined })\n | undefined\n }\n : {\n [K in Target]: In extends ValidationTargets[K]\n ? In\n : { [K2 in keyof In]: ValidationTargets[K][K2] }\n }\n out: { [K in Target]: Out }\n}\n\n/**\n * @internal\n * Type-safe Hono middleware handler return for Model.validator().\n * Provides proper type narrowing for c.req.valid(target).\n *\n * Uses RowType<Fields> directly for input/output type computation\n * to ensure Zod v3/v4 compatibility (z.input<ZodTypeAny> returns unknown in Zod v4).\n */\nexport type ModelValidatorReturn<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n Target extends keyof ValidationTargets,\n Opts extends SchemaOptions<keyof Fields & string> | undefined,\n> = MiddlewareHandler<\n any,\n string,\n ValidatorInput<\n Target,\n Apply<FieldsToZodShape<Fields>, Opts>,\n ApplyToRecord<RowType<Fields>, Opts>,\n ApplyToRecord<RowType<Fields>, Opts>\n >\n>\n\n/**\n * Hook type for Model.validator() third argument.\n * Re-exported from @hono/zod-validator for convenience.\n */\nexport type { Hook }\n\n/**\n * Represents a database model with type-safe schema derivation and CRUD operations.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for the generic Field constraint\nexport interface Model<Fields extends Record<string, Field<any, any, any>>> {\n readonly fields: Fields\n readonly tableName: string\n readonly table: ModelTable<Fields>\n\n /**\n * Returns a Zod schema derived from this model's fields.\n * Supports pick, omit, and partial transformations.\n *\n * @example\n * const CreateSchema = User.schema({ omit: ['passwordHash'] })\n * const UpdateSchema = User.schema({ partial: true, pick: ['name', 'email'] })\n */\n schema<Opts extends SchemaOptions<keyof Fields & string> | undefined>(\n opts?: Opts,\n ): Apply<FieldsToZodShape<Fields>, Opts>\n\n /**\n * Returns a Hono middleware validator derived from this model's schema.\n * Integrates with @hono/zod-validator to validate request inputs.\n * The optional `hook` argument is passed through to @hono/zod-validator.\n *\n * Accepts a preset ('create' | 'update') as second argument to use inputSchema.\n * When a preset is used, the return type is a MiddlewareHandler (loosely typed in Phase 2A).\n * Precise type narrowing for preset is deferred to Phase 2B M2.3.\n *\n * @example\n * app.post('/users', User.validator('json', 'create'), c => {\n * const body = c.req.valid('json')\n * })\n * app.post('/users', User.validator('json', { omit: ['passwordHash'] }), c => {\n * const body = c.req.valid('json')\n * })\n * // With hook:\n * app.post('/users', User.validator('json', opts, (result, c) => {\n * if (!result.success) return c.json({ error: 'Invalid request' }, 400)\n * }), handler)\n */\n validator<Target extends keyof ValidationTargets, E extends Env = Env, P extends string = string>(\n target: Target,\n preset: 'create',\n hook?: Hook<\n Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>,\n E,\n P,\n Target\n >,\n ): MiddlewareHandler<\n E,\n P,\n ValidatorInput<\n Target,\n z.ZodObject<z.ZodRawShape>,\n Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>,\n Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>\n >\n >\n validator<Target extends keyof ValidationTargets, E extends Env = Env, P extends string = string>(\n target: Target,\n preset: 'update',\n hook?: Hook<\n Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>,\n E,\n P,\n Target\n >,\n ): MiddlewareHandler<\n E,\n P,\n ValidatorInput<\n Target,\n z.ZodObject<z.ZodRawShape>,\n Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>,\n Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>\n >\n >\n validator<\n Target extends keyof ValidationTargets,\n Opts extends SchemaOptions<keyof Fields & string> | undefined,\n E extends Env = Env,\n P extends string = string,\n >(\n target: Target,\n opts?: Opts,\n hook?: Hook<z.output<Apply<FieldsToZodShape<Fields>, Opts>>, E, P, Target>,\n ): ModelValidatorReturn<Fields, Target, Opts>\n\n /**\n * Returns a Zod schema for API input, with policy-based field exclusions applied.\n * - 'create': serverOnly and readOnly fields are excluded\n * - 'update': same exclusions + all fields become optional (partial: true)\n *\n * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.\n */\n inputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(\n usage: 'create',\n opts?: Opts,\n ): z.ZodObject<\n ApplyShape<\n Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>,\n Opts\n >\n >\n inputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(\n usage: 'update',\n opts?: Opts,\n ): z.ZodObject<\n ApplyShape<\n Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>,\n Opts extends undefined ? { partial: true } : Opts & { partial: true }\n >\n >\n inputSchema(\n usage: 'create' | 'update',\n opts?: SchemaOptions<keyof Fields & string>,\n ): z.ZodObject<z.ZodRawShape>\n\n /**\n * Returns a Zod schema for API output, with policy-based field exclusions applied.\n * - serverOnly and writeOnly fields are excluded\n * - readOnly fields remain present\n *\n * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.\n */\n outputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(\n opts?: Opts,\n ): z.ZodObject<\n ApplyShape<Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'output'> & string>, Opts>\n >\n\n /**\n * Parses a DB row through outputSchema and returns the safe response object.\n * Equivalent to `User.outputSchema().parse(row)`.\n */\n toResponse(row: RowType<Fields>): unknown\n\n toOpenAPIComponent(): OpenAPIModelComponent\n\n toOpenAPISchema(usage: OpenAPIUsage): OpenAPISchemaObject\n\n /**\n * Fetches multiple rows with pagination and optional ordering.\n * `limit` is required (no default) to prevent accidental unbounded queries.\n * Offset defaults to 0 if omitted.\n *\n * @example\n * const users = await User.findMany(adapter, { limit: 20 })\n * const page2 = await User.findMany(adapter, { limit: 20, offset: 20 })\n * const sorted = await User.findMany(adapter, { limit: 10, orderBy: 'name' })\n */\n findMany(adapter: Adapter, options: FindManyOptions<Fields>): Promise<RowType<Fields>[]>\n\n /**\n * Fetches a single row by primary key or where clause.\n * Returns null if not found.\n *\n * @example\n * const user = await User.findOne(adapter, id)\n * const byEmail = await User.findOne(adapter, { email: 'john@example.com' })\n */\n findOne(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<RowType<Fields> | null>\n\n /**\n * Creates a new row and returns the created record.\n *\n * @example\n * const user = await User.create(adapter, { name: 'John', email: 'john@example.com' })\n */\n create(adapter: Adapter, data: CreateInput<Fields>): Promise<RowType<Fields>>\n\n /**\n * Updates rows matching the given id or where clause.\n * Returns the updated row(s), or null if no rows matched.\n *\n * @example\n * const updated = await User.update(adapter, id, { name: 'Jane' })\n * const byEmail = await User.update(adapter, { email: '...' }, { name: 'Jane' })\n */\n update(\n adapter: Adapter,\n idOrWhere: IdOrWhere<Fields>,\n data: Partial<RowType<Fields>>,\n ): Promise<RowType<Fields> | null>\n\n /**\n * Deletes rows matching the given id or where clause.\n * Returns the number of deleted rows.\n *\n * @example\n * const result = await User.delete(adapter, id)\n * console.log(result.deleted) // number\n */\n delete(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<{ readonly deleted: number }>\n}\n","import { z } from 'zod'\nimport type { Field } from '../field/types'\nimport { type FieldAccessor, resolveSchemaOptionKeys, type SchemaOptions } from './types'\n\ntype PolicyUsage = 'input-create' | 'input-update' | 'output'\n\n/**\n * Returns field names that are security-critical and must always be omitted from API schemas.\n * Currently only serverOnly fields. These cannot be overridden by user pick/omit.\n */\nfunction computeForcedOmit(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling\n fields: Record<string, Field<any, any, any>>,\n): string[] {\n const omit: string[] = []\n for (const [key, field] of Object.entries(fields)) {\n if (field.modifiers.policy === 'serverOnly') {\n omit.push(key)\n }\n }\n return omit\n}\n\n/**\n * Returns field names to omit based on UX-oriented policy (writeOnly / readOnly).\n * These can be overridden when user explicitly provides pick.\n *\n * Policy mapping:\n * - `writeOnly`: omitted from output only. For input targets (input-create, input-update),\n * writeOnly fields are NOT omitted — they are intentionally part of the input (e.g. password).\n * - `readOnly`: omitted from input targets (input-create, input-update) only. Remains in output.\n *\n * The asymmetry is by design: writeOnly means \"accepted on write, hidden on read\";\n * readOnly means \"visible on read, rejected on write\".\n */\nfunction computeOptionalOmit(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling\n fields: Record<string, Field<any, any, any>>,\n target: PolicyUsage,\n): string[] {\n const omit: string[] = []\n for (const [key, field] of Object.entries(fields)) {\n const policy = field.modifiers.policy\n if (!policy) continue\n if (policy === 'writeOnly' && target === 'output') {\n omit.push(key)\n } else if (policy === 'readOnly' && (target === 'input-create' || target === 'input-update')) {\n omit.push(key)\n }\n }\n return omit\n}\n\n/**\n * Merges policy-derived omit with user-provided SchemaOptions.\n *\n * serverOnly fields are always omitted regardless of user pick/omit (security invariant).\n * writeOnly / readOnly are UX-oriented and can be overridden when user provides pick.\n * For 'input-update', partial defaults to true unless user specifies otherwise.\n */\nexport function derivePolicyOptions(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling\n fields: Record<string, Field<any, any, any>>,\n usage: PolicyUsage,\n userOpts?: SchemaOptions,\n // biome-ignore lint/suspicious/noExplicitAny: accessor is a plain object with string keys\n accessor?: FieldAccessor<any>,\n): SchemaOptions {\n const forced = computeForcedOmit(fields)\n const optional = computeOptionalOmit(fields, usage)\n\n const acc = accessor ?? ({} as FieldAccessor<string>)\n const resolvedPick = resolveSchemaOptionKeys(userOpts?.pick, acc)\n const resolvedOmit = resolveSchemaOptionKeys(userOpts?.omit, acc)\n\n if (resolvedPick !== undefined) {\n const partial = usage === 'input-update' ? (userOpts?.partial ?? true) : userOpts?.partial\n // serverOnly fields are stripped from pick even if user explicitly listed them\n const sanitizedPick = Array.from(resolvedPick).filter((k) => !forced.includes(k))\n // Combine forced omit with user-provided omit to preserve both constraints\n const combinedOmit = [...new Set([...forced, ...(resolvedOmit ?? [])])]\n return {\n ...userOpts,\n pick: sanitizedPick,\n ...(combinedOmit.length > 0 ? { omit: combinedOmit } : {}),\n partial,\n }\n }\n\n const combinedOmit = [...new Set([...forced, ...optional, ...(resolvedOmit ?? [])])]\n const partial =\n usage === 'input-update' ? (userOpts?.partial ?? true) : (userOpts?.partial ?? undefined)\n\n return {\n ...(userOpts ?? {}),\n pick: undefined,\n ...(combinedOmit.length > 0 ? { omit: combinedOmit } : {}),\n ...(partial !== undefined ? { partial } : {}),\n }\n}\n\n/**\n * Builds a Zod object schema from a fields definition.\n * Returns a ZodObject with all fields required and present.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling and Zod shape\nexport function buildBaseObject(fields: Record<string, Field<any, any, any>>): z.ZodObject<any> {\n // biome-ignore lint/suspicious/noExplicitAny: Record key-value pairs have any type for shape\n const shape: Record<string, any> = {}\n for (const [key, field] of Object.entries(fields)) {\n shape[key] = field.zodBase\n }\n return z.object(shape)\n}\n\n/**\n * Applies pick, omit, and partial transformations to a Zod object schema.\n * Order: pick → omit → partial\n *\n * Returns the transformed schema, cast to Apply<Shape, Opts> at the call site.\n */\nexport function applySchemaOptions(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Zod shape operations\n baseSchema: z.ZodObject<any>,\n opts: SchemaOptions | undefined,\n // biome-ignore lint/suspicious/noExplicitAny: accessor is a plain object with string keys\n accessor?: FieldAccessor<any>,\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for return type\n): z.ZodObject<any> {\n if (!opts) {\n return baseSchema\n }\n\n const acc = accessor ?? ({} as FieldAccessor<string>)\n const resolvedPick = resolveSchemaOptionKeys(opts.pick, acc)\n const resolvedOmit = resolveSchemaOptionKeys(opts.omit, acc)\n\n let schema = baseSchema\n\n // Apply pick\n if (resolvedPick !== undefined) {\n const pickArray = Array.from(resolvedPick)\n schema = schema.pick(\n // biome-ignore lint/suspicious/noExplicitAny: Zod API\n Object.fromEntries(pickArray.map((k) => [k, true])) as any,\n )\n }\n\n // Apply omit\n if (resolvedOmit !== undefined) {\n const omitArray = Array.from(resolvedOmit)\n schema = schema.omit(\n // biome-ignore lint/suspicious/noExplicitAny: Zod API\n Object.fromEntries(omitArray.map((k) => [k, true])) as any,\n )\n }\n\n // Apply partial\n // `partial: false` を渡してもこの条件で何もしない。スキーマは required のまま。\n if (opts.partial === true) {\n schema = schema.partial()\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Cast to Apply type at call site\n return schema as any\n}\n","import type { Field } from '../field/types'\nimport { applySchemaOptions, buildBaseObject, derivePolicyOptions } from '../model/schema'\nimport type { SchemaOptions } from '../model/types'\nimport type { OpenAPIModelComponent, OpenAPISchemaObject, OpenAPIUsage } from './types'\n\n// biome-ignore lint/suspicious/noExplicitAny: OpenAPI generation accepts any concrete field builder.\ntype AnyField = Field<any, any, any>\ntype FieldsRecord = Record<string, AnyField>\n\ninterface OpenAPIOptions {\n readonly opts?: SchemaOptions\n readonly strict?: boolean\n}\n\nexport function toOpenAPIComponent(\n fields: FieldsRecord,\n opts?: OpenAPIOptions,\n): OpenAPIModelComponent {\n return {\n create: toOpenAPISchema(fields, 'create', opts),\n update: toOpenAPISchema(fields, 'update', opts),\n output: toOpenAPISchema(fields, 'output', opts),\n }\n}\n\nexport function toOpenAPISchema(\n fields: FieldsRecord,\n usage: OpenAPIUsage,\n opts?: OpenAPIOptions,\n): OpenAPISchemaObject {\n const policyUsage =\n usage === 'create' ? 'input-create' : usage === 'update' ? 'input-update' : 'output'\n const merged = derivePolicyOptions(fields, policyUsage, opts?.opts)\n const schema = applySchemaOptions(buildBaseObject(fields), merged)\n const shape = getZodObjectShape(schema)\n const properties: Record<string, OpenAPISchemaObject> = {}\n const required: string[] = []\n\n for (const [key, zodSchema] of Object.entries(shape)) {\n const field = fields[key]\n if (field === undefined) continue\n\n properties[key] = fieldToOpenAPISchema(field, opts?.strict)\n if (field.modifiers.policy === 'writeOnly' && (usage === 'create' || usage === 'update')) {\n properties[key].writeOnly = true\n }\n if (field.modifiers.policy === 'readOnly' && usage === 'output') {\n properties[key].readOnly = true\n }\n if (usage !== 'update' && isRequiredZodSchema(zodSchema)) {\n required.push(key)\n }\n }\n\n return {\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n }\n}\n\nfunction fieldToOpenAPISchema(field: AnyField, strict = false): OpenAPISchemaObject {\n const schema: OpenAPISchemaObject =\n field.kind === 'json'\n ? zodToOpenAPISchema(field.zodBase, strict)\n : field.kind === 'string'\n ? { type: 'string' }\n : field.kind === 'uuid'\n ? { type: 'string', format: 'uuid' }\n : field.kind === 'number'\n ? { type: 'number' }\n : field.kind === 'integer'\n ? { type: 'integer' }\n : field.kind === 'boolean'\n ? { type: 'boolean' }\n : field.kind === 'timestamp'\n ? { type: 'string', format: 'date-time' }\n : {}\n\n if (field.modifiers.format === 'email') {\n schema.format = 'email'\n }\n if (field.modifiers.min !== undefined) {\n if (field.kind === 'string' || field.kind === 'uuid') {\n schema.minLength = field.modifiers.min\n } else {\n schema.minimum = field.modifiers.min\n }\n }\n if (field.modifiers.max !== undefined) {\n if (field.kind === 'string' || field.kind === 'uuid') {\n schema.maxLength = field.modifiers.max\n } else {\n schema.maximum = field.modifiers.max\n }\n }\n\n if (field.modifiers.optional) {\n schema.nullable = true\n }\n\n return schema\n}\n\nfunction zodToOpenAPISchema(schema: unknown, strict = false): OpenAPISchemaObject {\n const def = getZodDef(schema)\n if (def === undefined) return {}\n\n const typeName = getZodTypeName(def)\n\n if (typeName === 'ZodOptional' || typeName === 'optional') {\n return zodToOpenAPISchema(def.innerType, strict)\n }\n if (typeName === 'ZodDefault' || typeName === 'default') {\n return zodToOpenAPISchema(def.innerType, strict)\n }\n if (typeName === 'ZodNullable' || typeName === 'nullable') {\n return { ...zodToOpenAPISchema(def.innerType, strict), nullable: true }\n }\n\n if (typeName === 'ZodObject' || typeName === 'object') {\n const shape = getZodObjectShape(schema)\n const properties: Record<string, OpenAPISchemaObject> = {}\n const required: string[] = []\n\n for (const [key, childSchema] of Object.entries(shape)) {\n properties[key] = zodToOpenAPISchema(childSchema, strict)\n if (isRequiredZodSchema(childSchema)) {\n required.push(key)\n }\n }\n\n return {\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n }\n }\n\n if (typeName === 'ZodString' || typeName === 'string') {\n return applyStringChecks({ type: 'string' }, def)\n }\n\n if (typeName === 'ZodNumber' || typeName === 'number') {\n return applyNumberChecks({ type: hasIntegerCheck(def) ? 'integer' : 'number' }, def)\n }\n\n if (typeName === 'ZodBoolean' || typeName === 'boolean') {\n return { type: 'boolean' }\n }\n\n if (typeName === 'ZodArray' || typeName === 'array') {\n const itemSchema = def.element ?? def.type\n return {\n type: 'array',\n items: zodToOpenAPISchema(itemSchema, strict),\n }\n }\n\n if (typeName === 'ZodRecord' || typeName === 'record') {\n return {\n type: 'object',\n additionalProperties: zodToOpenAPISchema(def.valueType, strict),\n }\n }\n\n if (typeName === 'ZodUnknown' || typeName === 'unknown') {\n return {}\n }\n\n if (strict) {\n throw new Error(`Unsupported Zod type for strict OpenAPI generation: ${typeName ?? 'unknown'}`)\n }\n return {\n 'x-nanoka-zod-unsupported': true,\n ...(typeName ? { 'x-nanoka-zod-type': typeName } : {}),\n }\n}\n\nfunction getZodObjectShape(schema: unknown): Record<string, unknown> {\n if (\n typeof schema === 'object' &&\n schema !== null &&\n 'shape' in schema &&\n typeof schema.shape === 'object' &&\n schema.shape !== null\n ) {\n return schema.shape as Record<string, unknown>\n }\n\n if (\n typeof schema === 'object' &&\n schema !== null &&\n '_def' in schema &&\n typeof schema._def === 'object' &&\n schema._def !== null &&\n 'shape' in schema._def\n ) {\n const shape = schema._def.shape\n return (typeof shape === 'function' ? shape() : shape) as Record<string, unknown>\n }\n\n return {}\n}\n\nfunction isRequiredZodSchema(schema: unknown): boolean {\n const def = getZodDef(schema)\n if (def === undefined) {\n return true\n }\n\n const typeName = getZodTypeName(def)\n return (\n typeName !== 'ZodOptional' &&\n typeName !== 'optional' &&\n typeName !== 'ZodDefault' &&\n typeName !== 'default'\n )\n}\n\nfunction getZodDef(schema: unknown): Record<string, unknown> | undefined {\n if (\n typeof schema === 'object' &&\n schema !== null &&\n '_def' in schema &&\n typeof schema._def === 'object' &&\n schema._def !== null\n ) {\n return schema._def as Record<string, unknown>\n }\n\n return undefined\n}\n\nfunction getZodTypeName(def: Record<string, unknown>): string | undefined {\n return typeof def.typeName === 'string'\n ? def.typeName\n : typeof def.type === 'string'\n ? def.type\n : undefined\n}\n\nfunction applyStringChecks(\n schema: OpenAPISchemaObject,\n def: Record<string, unknown>,\n): OpenAPISchemaObject {\n for (const check of getZodChecks(def)) {\n const checkDef = getZodCheckDef(check)\n if (checkDef.kind === 'email' || checkDef.format === 'email') {\n schema.format = 'email'\n }\n if (checkDef.kind === 'min' && typeof checkDef.value === 'number') {\n schema.minLength = checkDef.value\n }\n if (checkDef.kind === 'max' && typeof checkDef.value === 'number') {\n schema.maxLength = checkDef.value\n }\n if (checkDef.check === 'min_length' && typeof checkDef.minimum === 'number') {\n schema.minLength = checkDef.minimum\n }\n if (checkDef.check === 'max_length' && typeof checkDef.maximum === 'number') {\n schema.maxLength = checkDef.maximum\n }\n }\n\n return schema\n}\n\nfunction applyNumberChecks(\n schema: OpenAPISchemaObject,\n def: Record<string, unknown>,\n): OpenAPISchemaObject {\n for (const check of getZodChecks(def)) {\n const checkDef = getZodCheckDef(check)\n if (checkDef.kind === 'min' && typeof checkDef.value === 'number') {\n schema.minimum = checkDef.value\n }\n if (checkDef.kind === 'max' && typeof checkDef.value === 'number') {\n schema.maximum = checkDef.value\n }\n if (\n (checkDef.check === 'greater_than' || checkDef.check === 'number_format') &&\n typeof checkDef.minimum === 'number'\n ) {\n schema.minimum = checkDef.minimum\n }\n if (\n (checkDef.check === 'less_than' || checkDef.check === 'number_format') &&\n typeof checkDef.maximum === 'number'\n ) {\n schema.maximum = checkDef.maximum\n }\n }\n\n return schema\n}\n\nfunction hasIntegerCheck(def: Record<string, unknown>): boolean {\n return getZodChecks(def).some((check) => {\n const checkDef = getZodCheckDef(check)\n return (\n checkDef.kind === 'int' ||\n checkDef.format === 'safeint' ||\n checkDef.format === 'int32' ||\n checkDef.format === 'int64'\n )\n })\n}\n\nfunction getZodChecks(def: Record<string, unknown>): readonly unknown[] {\n return Array.isArray(def.checks) ? def.checks : []\n}\n\nfunction getZodCheckDef(check: unknown): Record<string, unknown> {\n if (typeof check !== 'object' || check === null) {\n return {}\n }\n if (\n '_zod' in check &&\n typeof check._zod === 'object' &&\n check._zod !== null &&\n 'def' in check._zod &&\n typeof check._zod.def === 'object' &&\n check._zod.def !== null\n ) {\n return check._zod.def as Record<string, unknown>\n }\n\n return check as Record<string, unknown>\n}\n","import { and, asc, desc, eq } from 'drizzle-orm'\nimport type { SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'\nimport { HTTPException } from 'hono/http-exception'\nimport type { Adapter } from '../adapter/types'\nimport type { Field } from '../field/types'\nimport type { CreateInput, IdOrWhere, OrderBy, RowType, Where } from './types'\n\nconst MAX_LIMIT = 100\n\n/**\n * Validates and guards limit/offset parameters.\n * @internal\n */\nfunction guardLimit(limit: unknown): number {\n if (!Number.isInteger(limit)) {\n throw new HTTPException(400, { message: 'limit must be an integer' })\n }\n const n = limit as number\n if (n < 0) {\n throw new HTTPException(400, { message: 'limit must be >= 0' })\n }\n if (n > MAX_LIMIT) {\n throw new HTTPException(400, { message: `limit must be <= ${MAX_LIMIT}` })\n }\n return n\n}\n\nfunction guardOffset(offset: unknown): number {\n if (!Number.isInteger(offset)) {\n throw new HTTPException(400, { message: 'offset must be an integer' })\n }\n const n = offset as number\n if (n < 0) {\n throw new HTTPException(400, { message: 'offset must be >= 0' })\n }\n return n\n}\n\n/**\n * Finds the primary key field from fields record.\n * @internal\n */\nfunction findPrimaryKey(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n fields: Record<string, Field<any, any, any>>,\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n): [string, Field<any, any, any>] | null {\n let pkKey: string | undefined\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n let pkField: Field<any, any, any> | undefined\n let pkCount = 0\n\n for (const [key, field] of Object.entries(fields)) {\n if (field.modifiers.primary === true) {\n pkCount++\n if (pkCount === 1) {\n pkKey = key\n pkField = field\n }\n }\n }\n\n if (pkCount === 0) {\n return null\n }\n if (pkCount > 1) {\n throw new HTTPException(500, { message: 'model has multiple primary keys' })\n }\n if (pkKey === undefined || pkField === undefined) {\n return null\n }\n\n return [pkKey, pkField]\n}\n\n/**\n * Constructs a Drizzle where clause from an object.\n * All entries are combined with AND.\n * @internal\n */\nfunction buildWhereClause(\n table: SQLiteTableWithColumns<any>,\n fields: Record<string, Field<any, any, any>>,\n where: Where<Record<string, any>>,\n): ReturnType<typeof and> | null {\n const conditions: ReturnType<typeof eq>[] = []\n\n for (const [key, value] of Object.entries(where)) {\n // Multi-layered guard against identifier injection\n if (!Object.hasOwn(fields, key)) {\n throw new HTTPException(400, { message: 'invalid field in where clause' })\n }\n if (!Object.hasOwn(table, key)) {\n throw new HTTPException(400, { message: 'invalid column in table' })\n }\n // biome-ignore lint/suspicious/noExplicitAny: table column access is runtime-guarded by hasOwn\n const col = (table as unknown as Record<string, any>)[key]\n conditions.push(eq(col, value))\n }\n\n if (conditions.length === 0) {\n return null\n }\n if (conditions.length === 1) {\n return conditions[0]\n }\n return and(...conditions)\n}\n\n/**\n * Fetches multiple rows with limit, offset, and optional ordering.\n * @internal\n */\nexport async function findManyImpl<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n _fields: Fields,\n options: {\n limit: unknown\n offset?: unknown\n orderBy?: OrderBy<Fields>\n },\n): Promise<RowType<Fields>[]> {\n const limit = guardLimit(options.limit)\n const offset = options.offset !== undefined ? guardOffset(options.offset) : 0\n\n // biome-ignore lint/suspicious/noExplicitAny: drizzle query builder type narrowing\n let query: any = adapter.drizzle.select().from(table).limit(limit).offset(offset)\n\n // Apply ordering\n if (options.orderBy !== undefined) {\n const orderByList = Array.isArray(options.orderBy) ? options.orderBy : [options.orderBy]\n\n for (const orderByItem of orderByList) {\n let column: string\n let direction: 'asc' | 'desc' = 'asc'\n\n if (typeof orderByItem === 'string') {\n column = orderByItem\n } else if (\n typeof orderByItem === 'object' &&\n orderByItem !== null &&\n 'column' in orderByItem\n ) {\n column = orderByItem.column\n if (orderByItem.direction) {\n direction = orderByItem.direction\n }\n } else {\n throw new HTTPException(400, { message: 'invalid orderBy format' })\n }\n\n // Runtime guard against identifier injection\n if (!Object.hasOwn(table, column)) {\n throw new HTTPException(400, { message: 'invalid field in orderBy' })\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: table column access is runtime-guarded by hasOwn\n const col = (table as unknown as Record<string, any>)[column]\n query = query.orderBy(direction === 'asc' ? asc(col) : desc(col))\n }\n }\n\n const rows = await query\n return rows\n}\n\n/**\n * Fetches a single row by primary key or where clause.\n * @internal\n */\nexport async function findOneImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n fields: Fields,\n idOrWhere: IdOrWhere<Fields>,\n): Promise<RowType<Fields> | null> {\n let where: Where<Fields> | null = null\n\n if (typeof idOrWhere === 'string' || typeof idOrWhere === 'number') {\n // PK mode\n const pk = findPrimaryKey(fields)\n if (!pk) {\n throw new HTTPException(500, { message: 'model has no primary key' })\n }\n where = { [pk[0]]: idOrWhere } as Where<Fields>\n } else {\n where = idOrWhere as Where<Fields>\n }\n\n const whereClause = buildWhereClause(table, fields, where)\n if (!whereClause) {\n throw new HTTPException(400, { message: 'where clause must not be empty' })\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: drizzle query type\n const rows = await (adapter.drizzle.select().from(table).where(whereClause).limit(1) as any)\n return rows.length > 0 ? rows[0] : null\n}\n\n/**\n * Creates a new row and returns the created record.\n * @internal\n */\nexport async function createImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n data: CreateInput<Fields>,\n): Promise<RowType<Fields>> {\n const rows = await (adapter.drizzle\n .insert(table)\n .values(data as any)\n .returning() as any)\n return rows[0]\n}\n\n/**\n * Updates rows matching the given id or where clause.\n * @internal\n */\nexport async function updateImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n fields: Fields,\n idOrWhere: IdOrWhere<Fields>,\n data: Partial<RowType<Fields>>,\n): Promise<RowType<Fields> | null> {\n let where: Where<Fields> | null = null\n\n if (typeof idOrWhere === 'string' || typeof idOrWhere === 'number') {\n // PK mode\n const pk = findPrimaryKey(fields)\n if (!pk) {\n throw new HTTPException(500, { message: 'model has no primary key' })\n }\n where = { [pk[0]]: idOrWhere } as Where<Fields>\n } else {\n where = idOrWhere as Where<Fields>\n }\n\n const whereClause = buildWhereClause(table, fields, where)\n if (!whereClause) {\n throw new HTTPException(400, { message: 'where clause must not be empty' })\n }\n\n const rows = await (adapter.drizzle\n .update(table)\n .set(data as any)\n .where(whereClause)\n .returning() as any)\n return rows.length > 0 ? rows[0] : null\n}\n\n/**\n * Deletes rows matching the given id or where clause.\n * @internal\n */\nexport async function deleteImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n fields: Fields,\n idOrWhere: IdOrWhere<Fields>,\n): Promise<{ readonly deleted: number }> {\n let where: Where<Fields> | null = null\n\n if (typeof idOrWhere === 'string' || typeof idOrWhere === 'number') {\n // PK mode\n const pk = findPrimaryKey(fields)\n if (!pk) {\n throw new HTTPException(500, { message: 'model has no primary key' })\n }\n where = { [pk[0]]: idOrWhere } as Where<Fields>\n } else {\n where = idOrWhere as Where<Fields>\n }\n\n const whereClause = buildWhereClause(table, fields, where)\n if (!whereClause) {\n throw new HTTPException(400, { message: 'where clause must not be empty' })\n }\n\n const result = await adapter.drizzle.delete(table).where(whereClause).returning()\n return { deleted: result.length }\n}\n","import { type AnySQLiteColumn, type SQLiteTableWithColumns, sqliteTable } from 'drizzle-orm/sqlite-core'\nimport type { Field } from '../field/types'\n\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\ntype ModelTable<Fields extends Record<string, Field<any, any, any>>> = SQLiteTableWithColumns<{\n name: string\n schema: undefined\n columns: { [K in keyof Fields]: AnySQLiteColumn }\n dialect: 'sqlite'\n}>\n\n/**\n * Constructs a Drizzle SQLiteTable from a tableName and fields.\n * Each field is converted to a Drizzle column via field.drizzleColumn(key).\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\nexport function buildTable<Fields extends Record<string, Field<any, any, any>>>(\n tableName: string,\n fields: Fields,\n): ModelTable<Fields> {\n const columns: Record<string, any> = {}\n for (const [key, field] of Object.entries(fields)) {\n columns[key] = field.drizzleColumn(key)\n }\n return sqliteTable(tableName, columns) as unknown as ModelTable<Fields>\n}\n","import { type Hook, zValidator } from '@hono/zod-validator'\nimport type { Env, ValidationTargets } from 'hono'\nimport type { z } from 'zod'\nimport type { Adapter } from '../adapter/types'\nimport type { Field } from '../field/types'\nimport { toOpenAPIComponent, toOpenAPISchema } from '../openapi/generate'\nimport type { OpenAPIUsage } from '../openapi/types'\nimport { createImpl, deleteImpl, findManyImpl, findOneImpl, updateImpl } from './crud'\nimport { applySchemaOptions, buildBaseObject, derivePolicyOptions } from './schema'\nimport { buildTable } from './table'\nimport type {\n Apply,\n CreateInput,\n FieldsToZodShape,\n FindManyOptions,\n IdOrWhere,\n Model,\n RowType,\n SchemaOptions,\n} from './types'\nimport { buildFieldAccessor } from './types'\n\n/**\n * Creates a Model instance from a tableName and fields definition.\n * The model supports deriving Zod schemas, Hono validators, and CRUD operations.\n *\n * @example\n * const User = defineModel('users', {\n * id: t.uuid().primary(),\n * name: t.string(),\n * email: t.string().email(),\n * passwordHash: t.string(),\n * })\n *\n * const CreateSchema = User.schema({ omit: ['passwordHash'] })\n * const users = await User.findMany(adapter, { limit: 20 })\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field constraint\nexport function defineModel<Fields extends Record<string, Field<any, any, any>>>(\n tableName: string,\n fields: Fields,\n): Model<Fields> {\n const table = buildTable(tableName, fields)\n const accessor = buildFieldAccessor(fields)\n\n return {\n fields,\n tableName,\n table,\n\n schema<Opts extends SchemaOptions<keyof Fields & string> | undefined>(\n opts?: Opts,\n ): Apply<FieldsToZodShape<Fields>, Opts> {\n const baseSchema = buildBaseObject(fields)\n const schema = applySchemaOptions(baseSchema, opts, accessor)\n // biome-ignore lint/suspicious/noExplicitAny: Zod .pick()/.omit() return type narrowing requires cast at boundary\n return schema as any\n },\n\n validator(\n target: keyof ValidationTargets,\n optsOrPreset?: 'create' | 'update' | SchemaOptions<keyof Fields & string>,\n // biome-ignore lint/suspicious/noExplicitAny: Hook<T> is contravariant in T; any is required to bridge overload implementations\n hook?: Hook<any, Env, string, keyof ValidationTargets>,\n ) {\n let schema: z.ZodTypeAny\n if (optsOrPreset === 'create' || optsOrPreset === 'update') {\n schema = this.inputSchema(optsOrPreset)\n } else {\n schema = this.schema(optsOrPreset as SchemaOptions<keyof Fields & string>)\n }\n // biome-ignore lint/suspicious/noExplicitAny: zValidator return type cast required at overload boundary\n return zValidator(target, schema, hook) as any\n },\n\n inputSchema(\n usage: 'create' | 'update',\n opts?: SchemaOptions<keyof Fields & string>,\n // biome-ignore lint/suspicious/noExplicitAny: precise return type is enforced by Model<Fields> overload signatures\n ): any {\n const merged = derivePolicyOptions(\n fields,\n usage === 'create' ? 'input-create' : 'input-update',\n opts,\n accessor,\n )\n const baseSchema = buildBaseObject(fields)\n return applySchemaOptions(baseSchema, merged)\n },\n\n outputSchema(\n opts?: SchemaOptions<keyof Fields & string>,\n // biome-ignore lint/suspicious/noExplicitAny: precise return type is enforced by Model<Fields> overload signatures\n ): any {\n const merged = derivePolicyOptions(fields, 'output', opts, accessor)\n const baseSchema = buildBaseObject(fields)\n return applySchemaOptions(baseSchema, merged)\n },\n\n toResponse(row: RowType<Fields>): unknown {\n return this.outputSchema().parse(row)\n },\n\n toOpenAPIComponent() {\n return toOpenAPIComponent(fields)\n },\n\n toOpenAPISchema(usage: OpenAPIUsage) {\n return toOpenAPISchema(fields, usage)\n },\n\n findMany(adapter: Adapter, options: FindManyOptions<Fields>): Promise<RowType<Fields>[]> {\n return findManyImpl(adapter, table, fields, options)\n },\n\n findOne(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<RowType<Fields> | null> {\n return findOneImpl(adapter, table, fields, idOrWhere)\n },\n\n create(adapter: Adapter, data: CreateInput<Fields>): Promise<RowType<Fields>> {\n return createImpl(adapter, table, data)\n },\n\n update(\n adapter: Adapter,\n idOrWhere: IdOrWhere<Fields>,\n data: Partial<RowType<Fields>>,\n ): Promise<RowType<Fields> | null> {\n return updateImpl(adapter, table, fields, idOrWhere, data)\n },\n\n delete(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<{ readonly deleted: number }> {\n return deleteImpl(adapter, table, fields, idOrWhere)\n },\n }\n}\n","import type { OpenAPIDocument, OpenAPIRouteMetadata, OpenAPISpecOptions } from './types'\n\nfunction honoPathToOpenAPI(path: string): string {\n return path.replace(/:([^/]+)/g, '{$1}')\n}\n\nexport function buildOpenAPIDocument(\n routes: readonly OpenAPIRouteMetadata[],\n options: OpenAPISpecOptions,\n): OpenAPIDocument {\n const paths: Record<string, Record<string, unknown>> = {}\n\n for (const route of routes) {\n const openAPIPath = honoPathToOpenAPI(route.path)\n if (!paths[openAPIPath]) {\n paths[openAPIPath] = {}\n }\n\n const operation: Record<string, unknown> = {}\n if (route.operationId) operation.operationId = route.operationId\n if (route.summary) operation.summary = route.summary\n if (route.description) operation.description = route.description\n if (route.tags) operation.tags = route.tags\n\n const parameters: unknown[] = []\n const pathParams = [...route.path.matchAll(/:([^/]+)/g)].map((m) => m[1])\n for (const param of pathParams) {\n const alreadyDefined = route.params?.some((p) => p.name === param && p.in === 'path')\n if (!alreadyDefined) {\n parameters.push({ name: param, in: 'path', required: true, schema: { type: 'string' } })\n }\n }\n if (route.params) {\n parameters.push(...route.params)\n }\n if (parameters.length > 0) operation.parameters = parameters\n\n if (route.requestBody) operation.requestBody = route.requestBody\n operation.responses = route.responses\n\n paths[openAPIPath][route.method] = operation\n }\n\n const doc: OpenAPIDocument = {\n openapi: '3.1.0',\n info: options.info,\n ...(options.servers ? { servers: options.servers } : {}),\n paths,\n }\n\n return doc\n}\n","import type { MiddlewareHandler } from 'hono'\n\nexport interface SwaggerUIOptions {\n readonly url: string\n readonly title?: string\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nexport function swaggerUI(options: SwaggerUIOptions): MiddlewareHandler {\n const title = escapeHtml(options.title ?? 'API Documentation')\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <title>${title}</title>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui.css\" />\n</head>\n<body>\n <div id=\"swagger-ui\"></div>\n <script src=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js\"></script>\n <script>\n SwaggerUIBundle({\n url: ${JSON.stringify(options.url)},\n dom_id: '#swagger-ui',\n presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],\n layout: 'BaseLayout',\n })\n </script>\n</body>\n</html>`\n\n return async (c) => {\n return c.html(html)\n }\n}\n","import { Hono } from 'hono'\nimport type { BlankEnv, Env } from 'hono/types'\nimport type { Adapter } from '../adapter/types'\nimport type { Field } from '../field/types'\nimport { defineModel } from '../model/define'\nimport { buildOpenAPIDocument } from '../openapi/route'\nimport type { OpenAPIRouteMetadata } from '../openapi/types'\nimport type { Nanoka, NanokaModel } from './types'\n\n/**\n * Creates a Nanoka application instance with the given database adapter.\n *\n * @param adapter - The database adapter (e.g., d1Adapter(env.DB))\n * @returns A Nanoka application (Hono extended with model(), db, and batch)\n *\n * @example\n * export default {\n * fetch(req: Request, env: Env, ctx: ExecutionContext) {\n * const app = nanoka(d1Adapter(env.DB))\n * const User = app.model('users', { id, name, email, passwordHash })\n * app.get('/users', async (c) => {\n * const users = await User.findMany({ limit: 20 })\n * return c.json(users)\n * })\n * return app.fetch(req, env, ctx)\n * }\n * }\n */\nexport function nanoka<E extends Env = BlankEnv>(adapter: Adapter): Nanoka<E> {\n const app = new Hono<E>() as Nanoka<E>\n const openapiRoutes: OpenAPIRouteMetadata[] = []\n\n Object.defineProperty(app, 'db', {\n get: () => adapter.drizzle,\n enumerable: true,\n })\n\n app.batch = ((queries: Parameters<Adapter['batch']>[0]) =>\n adapter.batch(queries)) as unknown as Adapter['batch']\n\n app.openapi = (metadata: OpenAPIRouteMetadata) => {\n openapiRoutes.push(metadata)\n return app\n }\n\n app.generateOpenAPISpec = (options) => buildOpenAPIDocument(openapiRoutes, options)\n\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field generic constraint\n app.model = function model<Fields extends Record<string, Field<any, any, any>>>(\n name: string,\n fields: Fields,\n ): NanokaModel<Fields> {\n const inner = defineModel(name, fields)\n\n return {\n fields: inner.fields,\n tableName: inner.tableName,\n table: inner.table,\n\n schema: (opts) => inner.schema(opts),\n\n validator: (\n ...args: [\n keyof import('hono').ValidationTargets,\n ('create' | 'update' | import('../model/types').SchemaOptions<keyof Fields & string>)?,\n import('@hono/zod-validator').Hook<\n // biome-ignore lint/suspicious/noExplicitAny: Hook<T> is contravariant in T; any is required to bridge overload implementations\n any,\n import('hono').Env,\n string,\n keyof import('hono').ValidationTargets\n >?,\n ]\n ) => {\n // `NanokaModel` interface の overload 定義 (router/types.ts) で type safety は担保する。\n // 実装は inner.validator に委譲するだけで、型は interface 側の overload に従う。\n // biome-ignore lint/suspicious/noExplicitAny: NanokaModel interface overloads provide type safety\n return (inner.validator as (...a: typeof args) => any)(...args)\n },\n\n inputSchema: (usage, opts) => inner.inputSchema(usage, opts),\n\n outputSchema: (opts) => inner.outputSchema(opts),\n\n toResponse: (row) => inner.toResponse(row),\n\n toOpenAPIComponent: () => inner.toOpenAPIComponent(),\n\n toOpenAPISchema: (usage) => inner.toOpenAPISchema(usage),\n\n findMany: (options) => inner.findMany(adapter, options),\n\n findOne: (idOrWhere) => inner.findOne(adapter, idOrWhere),\n\n create: (data) => inner.create(adapter, data),\n\n update: (idOrWhere, data) => inner.update(adapter, idOrWhere, data),\n\n delete: (idOrWhere) => inner.delete(adapter, idOrWhere),\n }\n }\n\n return app\n}\n"]}
1
+ {"version":3,"sources":["../src/adapter/d1.ts","../src/model/types.ts","../src/model/schema.ts","../src/openapi/generate.ts","../src/model/crud.ts","../src/model/table.ts","../src/model/define.ts","../src/openapi/route.ts","../src/openapi/swagger-ui.ts","../src/router/nanoka.ts"],"names":["partial","combinedOmit"],"mappings":"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","file":"index.js","sourcesContent":["import type { D1Database } from '@cloudflare/workers-types'\nimport { drizzle } from 'drizzle-orm/d1'\nimport type { Adapter } from './types'\n\n/**\n * D1-specific adapter factory. Wraps Cloudflare D1 binding in the generic\n * Adapter abstraction, enabling the core query path and router to remain\n * implementation-agnostic.\n */\nexport function d1Adapter<TSchema extends Record<string, unknown> = Record<string, never>>(\n d1: D1Database,\n): Adapter<TSchema> {\n // drizzle-orm/d1's drizzle() returns DrizzleD1Database which embeds D1-specific\n // result types. We cast to BaseSQLiteDatabase via the Adapter interface to keep\n // the D1 dependency local to this file (see CLAUDE.md rule #3). Consumers receive\n // the typed Adapter interface, so this `any` is intentionally local.\n //\n // Note: drizzle-orm/d1 internally stores the D1 binding in db.$client. When\n // handling multiple D1 bindings, call d1Adapter() fresh for each binding rather\n // than caching the return value across binding switches.\n // biome-ignore lint/suspicious/noExplicitAny: intentional - Drizzle returns complex union type\n const db = drizzle(d1) as any\n\n return {\n drizzle: db,\n batch: (queries) => db.batch(queries),\n }\n}\n","import type { Hook } from '@hono/zod-validator'\nimport type { AnySQLiteColumn, SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'\nimport type { Env, MiddlewareHandler, ValidationTargets } from 'hono'\nimport type { z } from 'zod'\nimport type { Adapter } from '../adapter/types'\nimport type { Field, FieldPolicy, InferFieldType } from '../field/types'\nimport type { OpenAPIModelComponent, OpenAPISchemaObject, OpenAPIUsage } from '../openapi/types'\n\n/**\n * Options for findMany query.\n * `limit` is required (no default).\n * `offset` defaults to 0 if omitted.\n * `orderBy` is optional for column ordering.\n */\nexport interface FindManyOptions<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> {\n readonly limit: number\n readonly offset?: number\n readonly orderBy?: OrderBy<Fields>\n}\n\n/**\n * Order-by specification: single field, or field with direction, or array of multiple.\n */\nexport type OrderBy<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> =\n | (keyof Fields & string)\n | { readonly column: keyof Fields & string; readonly direction?: 'asc' | 'desc' }\n | ReadonlyArray<\n | (keyof Fields & string)\n | { readonly column: keyof Fields & string; readonly direction?: 'asc' | 'desc' }\n >\n\n/**\n * Where clause object: each key is a field name, each value is the desired equality.\n */\nexport type Where<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n readonly [K in keyof Fields]?: InferFieldType<Fields[K]>\n}\n\n/**\n * Identifier or Where clause: can be a primary key value or a Where object.\n */\nexport type IdOrWhere<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = string | number | Where<Fields>\n\n/**\n * Row type: full record type from fields.\n */\nexport type RowType<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n [K in keyof Fields]: InferFieldType<Fields[K]>\n}\n\n/**\n * Drizzle table type with columns typed to match the model's Fields.\n * Allows type-safe column access via Model.table.fieldName.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\nexport type ModelTable<Fields extends Record<string, Field<any, any, any>>> =\n SQLiteTableWithColumns<{\n name: string\n schema: undefined\n columns: { [K in keyof Fields]: AnySQLiteColumn }\n dialect: 'sqlite'\n }>\n\n/**\n * @internal\n * Extracts the policy from a Field's modifiers.\n *\n * Uses `Field<any, { policy: infer P }, any>` rather than a two-step\n * `infer M` + `M extends { policy: infer P }` pattern.\n * The two-step pattern is broken when TypeScript widens `M` to the constraint\n * `FieldModifiers` (which has `policy?: FieldPolicy` as optional), causing\n * `M extends { policy: infer P }` to be true for ALL fields regardless of their\n * actual policy value. Directly matching `{ policy: infer P }` avoids this.\n */\ntype PolicyOf<F> =\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { policy: infer P extends FieldPolicy }, any> ? P : never\n\n/**\n * @internal\n * Computes which field keys should be omitted based on policy and usage.\n * Mirrors the runtime logic in derivePolicyOptions() in schema.ts.\n *\n * NOTE: `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) is used to\n * short-circuit fields with no policy to `never` (do not omit). Without this guard,\n * `never extends 'serverOnly'` evaluates to `true` (vacuously), causing every field\n * without a policy to be incorrectly included in the omit set.\n */\nexport type PolicyOmitKeys<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n Usage extends 'input-create' | 'input-update' | 'output',\n> = {\n [K in keyof Fields]: [PolicyOf<Fields[K]>] extends [never]\n ? never\n : PolicyOf<Fields[K]> extends 'serverOnly'\n ? K\n : Usage extends 'output'\n ? PolicyOf<Fields[K]> extends 'writeOnly'\n ? K\n : never\n : Usage extends 'input-create' | 'input-update'\n ? PolicyOf<Fields[K]> extends 'readOnly'\n ? K\n : never\n : never\n}[keyof Fields]\n\n/**\n * @internal\n * Computes which field keys have the serverOnly policy.\n * serverOnly fields are completely excluded from CreateInput\n * (cannot be passed even from library internals — they are server-side only).\n *\n * Uses `[PolicyOf<Fields[K]>] extends [never]` (non-distributive form) to short-circuit\n * fields with no policy to `never`. Without this guard, `never extends 'serverOnly'`\n * evaluates to `true` (vacuously), causing every field without a policy to be included.\n */\ntype ServerOnlyKeys<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n [K in keyof Fields]: [PolicyOf<Fields[K]>] extends [never]\n ? never\n : PolicyOf<Fields[K]> extends 'serverOnly'\n ? K\n : never\n}[keyof Fields]\n\n/**\n * @internal\n * Determines if a field is required for create input.\n * A field is optional if it has a default, is optional, or is readOnly.\n *\n * Uses direct shape matching (`Field<any, { hasDefault: true }, any>`) to avoid\n * the TypeScript infer-widening issue where `infer M` resolves to `FieldModifiers`\n * (the constraint bound) instead of the concrete Mods type, causing `M extends\n * { policy: 'readOnly' }` to be false even for readOnly fields.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\ntype IsRequired<F extends Field<any, any, any>> =\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { hasDefault: true }, any>\n ? false\n : // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { optional: true }, any>\n ? false\n : // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n F extends Field<any, { policy: 'readOnly' }, any>\n ? false\n : true\n\n/**\n * Create input with precise types:\n * - `readOnly` fields are optional (library internals can pass them; API callers\n * are excluded via inputSchema — but CreateInput itself keeps them as optional\n * so handlers can supply generated values like `id` or `createdAt`)\n * - fields with `default` are optional\n * - fields marked `optional` are optional\n * - all other fields are required\n * - `serverOnly` fields are completely excluded (cannot be passed even internally)\n * - `writeOnly` fields are included as required (they are input fields by design)\n */\nexport type CreateInput<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n> = {\n [K in keyof Fields as IsRequired<Fields[K]> extends true\n ? K extends ServerOnlyKeys<Fields>\n ? never\n : K\n : never]: InferFieldType<Fields[K]>\n} & {\n [K in keyof Fields as IsRequired<Fields[K]> extends true\n ? never\n : K extends ServerOnlyKeys<Fields>\n ? never\n : K]?: InferFieldType<Fields[K]>\n}\n\nexport type FieldAccessor<K extends string> = { readonly [Key in K]: Key }\n\nexport interface SchemaOptions<K extends string = string> {\n readonly pick?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[])\n readonly omit?: readonly K[] | ((f: FieldAccessor<K>) => readonly K[])\n readonly partial?: boolean\n}\n\n/**\n * @internal\n * Resolves pick/omit option to string array using the accessor when it's a function.\n */\nexport function resolveSchemaOptionKeys<K extends string>(\n opt: readonly K[] | ((f: FieldAccessor<K>) => readonly K[]) | undefined,\n accessor: FieldAccessor<K>,\n): readonly K[] | undefined {\n if (opt === undefined) return undefined\n if (typeof opt === 'function') return opt(accessor)\n return opt\n}\n\n/**\n * @internal\n * Builds a frozen field accessor object for use in schema/validator options.\n * Each key maps to itself, providing typo detection at type level.\n */\nexport function buildFieldAccessor<Fields extends Record<string, unknown>>(\n fields: Fields,\n): { readonly [K in keyof Fields]: K } {\n const acc: Record<string, string> = {}\n for (const k of Object.keys(fields)) acc[k] = k\n return Object.freeze(acc) as { readonly [K in keyof Fields]: K }\n}\n\n/**\n * @internal\n * Extracts a Zod shape from fields for the Apply type.\n * Each field's zodBase becomes a property in the shape.\n * Indexed access ensures concrete Zod types are preserved (not `any`).\n */\nexport type FieldsToZodShape<\n Fields extends Record<\n string,\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Field<any, any, any>\n >,\n> = {\n [K in keyof Fields]: Fields[K]['zodBase']\n}\n\n/**\n * @internal\n * Utility to narrow array literal types to union of strings.\n */\ntype ArrayKeys<A> = A extends readonly (infer U)[] ? U : never\n\n/**\n * @internal\n * Resolves pick/omit option type to the array type.\n * Handles both array form and accessor function form.\n */\ntype ResolveOptKeys<Opt> = Opt extends readonly string[]\n ? Opt\n : Opt extends (f: FieldAccessor<infer _K>) => readonly (infer R)[]\n ? readonly R[]\n : never\n\n/**\n * @internal\n * Apply pick transformation to a shape.\n */\ntype ApplyPickToShape<Shape extends z.ZodRawShape, PickOpt> =\n ResolveOptKeys<PickOpt> extends readonly string[]\n ? Pick<Shape, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof Shape>\n : Shape\n\n/**\n * @internal\n * Apply omit transformation to a shape.\n */\ntype ApplyOmitToShape<Shape extends z.ZodRawShape, OmitOpt> =\n ResolveOptKeys<OmitOpt> extends readonly string[]\n ? Omit<Shape, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof Shape>\n : Shape\n\n/**\n * @internal\n * Apply partial transformation to a shape.\n */\ntype ApplyPartialToShape<Shape extends z.ZodRawShape> = {\n [K in keyof Shape]: z.ZodOptional<Shape[K]>\n}\n\n/**\n * @internal\n * Checks if an option value (array or function) is present (i.e. not undefined and not never).\n * Uses distributive conditional to handle union types like `T | undefined`.\n */\ntype HasOpt<Opt> = undefined extends Opt ? false : [Opt] extends [never] ? false : true\n\n/**\n * @internal\n * Apply pick/omit/partial transformations to a Zod raw shape.\n * Order: pick → omit → partial\n * Handles both array form and accessor function form for pick/omit.\n */\ntype ApplyShape<\n Shape extends z.ZodRawShape,\n Opts extends SchemaOptions | undefined,\n> = Opts extends SchemaOptions\n ? HasOpt<Opts['pick']> extends true\n ? HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? ApplyPartialToShape<ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']>>\n : ApplyOmitToShape<ApplyPickToShape<Shape, Opts['pick']>, Opts['omit']>\n : Opts extends { partial: true }\n ? ApplyPartialToShape<ApplyPickToShape<Shape, Opts['pick']>>\n : ApplyPickToShape<Shape, Opts['pick']>\n : HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? ApplyPartialToShape<ApplyOmitToShape<Shape, Opts['omit']>>\n : ApplyOmitToShape<Shape, Opts['omit']>\n : Opts extends { partial: true }\n ? ApplyPartialToShape<Shape>\n : Shape\n : Shape\n\n/**\n * @internal\n * Returns the correct Zod object type after applying pick/omit/partial transformations.\n */\nexport type Apply<\n Shape extends z.ZodRawShape,\n Opts extends SchemaOptions | undefined,\n> = z.ZodObject<ApplyShape<Shape, Opts>>\n\n/**\n * @internal\n * Apply pick transformation to a TS record type.\n */\ntype ApplyPickToRecord<R, PickOpt> =\n ResolveOptKeys<PickOpt> extends readonly string[]\n ? Pick<R, ArrayKeys<ResolveOptKeys<PickOpt>> & keyof R>\n : R\n\n/**\n * @internal\n * Apply omit transformation to a TS record type.\n */\ntype ApplyOmitToRecord<R, OmitOpt> =\n ResolveOptKeys<OmitOpt> extends readonly string[]\n ? Omit<R, ArrayKeys<ResolveOptKeys<OmitOpt>> & keyof R>\n : R\n\n/**\n * @internal\n * Apply pick/omit/partial transformations to a TypeScript record type.\n * Mirrors ApplyShape but operates on TS types directly, not Zod shapes.\n * Used for Zod v3/v4 compatible middleware input/output type computation.\n */\ntype ApplyToRecord<R, Opts extends SchemaOptions | undefined> = Opts extends SchemaOptions\n ? HasOpt<Opts['pick']> extends true\n ? HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? Partial<ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']>>\n : ApplyOmitToRecord<ApplyPickToRecord<R, Opts['pick']>, Opts['omit']>\n : Opts extends { partial: true }\n ? Partial<ApplyPickToRecord<R, Opts['pick']>>\n : ApplyPickToRecord<R, Opts['pick']>\n : HasOpt<Opts['omit']> extends true\n ? Opts extends { partial: true }\n ? Partial<ApplyOmitToRecord<R, Opts['omit']>>\n : ApplyOmitToRecord<R, Opts['omit']>\n : Opts extends { partial: true }\n ? Partial<R>\n : R\n : R\n\n/**\n * @internal\n * Mirrors @hono/zod-validator's middleware Input type.\n * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.\n */\ntype HasUndefined<T> = undefined extends T ? true : false\n\n/**\n * @internal\n * Hono middleware input/output type for validator middleware.\n * Aligned with @hono/zod-validator@0.4.x; revisit on version bump.\n *\n * WARNING (Zod 4): `z.input<ZodTypeAny>` resolves to `unknown` in Zod 4, making\n * `c.req.valid(target)` return `unknown` if `In`/`Out` are left as defaults.\n * When using this type directly (outside of `ModelValidatorReturn`), always pass\n * explicit `In` and `Out` type arguments — do NOT rely on the defaults.\n *\n * Internal usages in this file (ModelValidatorReturn and preset overloads) already\n * pass `In`/`Out` explicitly via `ApplyToRecord` or `Omit<RowType<Fields>, ...>`.\n */\nexport type ValidatorInput<\n Target extends keyof ValidationTargets,\n Schema extends z.ZodTypeAny,\n In = z.input<Schema>,\n Out = z.output<Schema>,\n> = {\n in: HasUndefined<In> extends true\n ? {\n [K in Target]?:\n | (In extends ValidationTargets[K]\n ? In\n : { [K2 in keyof In]?: ValidationTargets[K][K2] | undefined })\n | undefined\n }\n : {\n [K in Target]: In extends ValidationTargets[K]\n ? In\n : { [K2 in keyof In]: ValidationTargets[K][K2] }\n }\n out: { [K in Target]: Out }\n}\n\n/**\n * @internal\n * Type-safe Hono middleware handler return for Model.validator().\n * Provides proper type narrowing for c.req.valid(target).\n *\n * Uses RowType<Fields> directly for input/output type computation\n * to ensure Zod v3/v4 compatibility (z.input<ZodTypeAny> returns unknown in Zod v4).\n */\nexport type ModelValidatorReturn<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n Target extends keyof ValidationTargets,\n Opts extends SchemaOptions<keyof Fields & string> | undefined,\n> = MiddlewareHandler<\n any,\n string,\n ValidatorInput<\n Target,\n Apply<FieldsToZodShape<Fields>, Opts>,\n ApplyToRecord<RowType<Fields>, Opts>,\n ApplyToRecord<RowType<Fields>, Opts>\n >\n>\n\n/**\n * Hook type for Model.validator() third argument.\n * Re-exported from @hono/zod-validator for convenience.\n */\nexport type { Hook }\n\n/**\n * Represents a database model with type-safe schema derivation and CRUD operations.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for the generic Field constraint\nexport interface Model<Fields extends Record<string, Field<any, any, any>>> {\n readonly fields: Fields\n readonly tableName: string\n readonly table: ModelTable<Fields>\n\n /**\n * Returns a Zod schema derived from this model's fields.\n * Supports pick, omit, and partial transformations.\n *\n * @example\n * const CreateSchema = User.schema({ omit: ['passwordHash'] })\n * const UpdateSchema = User.schema({ partial: true, pick: ['name', 'email'] })\n */\n schema<Opts extends SchemaOptions<keyof Fields & string> | undefined>(\n opts?: Opts,\n ): Apply<FieldsToZodShape<Fields>, Opts>\n\n /**\n * Returns a Hono middleware validator derived from this model's schema.\n * Integrates with @hono/zod-validator to validate request inputs.\n * The optional `hook` argument is passed through to @hono/zod-validator.\n *\n * Accepts a preset ('create' | 'update') as second argument to use inputSchema.\n * When a preset is used, the return type is a MiddlewareHandler (loosely typed in Phase 2A).\n * Precise type narrowing for preset is deferred to Phase 2B M2.3.\n *\n * @example\n * app.post('/users', User.validator('json', 'create'), c => {\n * const body = c.req.valid('json')\n * })\n * app.post('/users', User.validator('json', { omit: ['passwordHash'] }), c => {\n * const body = c.req.valid('json')\n * })\n * // With hook:\n * app.post('/users', User.validator('json', opts, (result, c) => {\n * if (!result.success) return c.json({ error: 'Invalid request' }, 400)\n * }), handler)\n */\n validator<Target extends keyof ValidationTargets, E extends Env = Env, P extends string = string>(\n target: Target,\n preset: 'create',\n hook?: Hook<\n Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>,\n E,\n P,\n Target\n >,\n ): MiddlewareHandler<\n E,\n P,\n ValidatorInput<\n Target,\n z.ZodObject<z.ZodRawShape>,\n Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>,\n Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>\n >\n >\n validator<Target extends keyof ValidationTargets, E extends Env = Env, P extends string = string>(\n target: Target,\n preset: 'update',\n hook?: Hook<\n Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>,\n E,\n P,\n Target\n >,\n ): MiddlewareHandler<\n E,\n P,\n ValidatorInput<\n Target,\n z.ZodObject<z.ZodRawShape>,\n Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>,\n Partial<Omit<RowType<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>>\n >\n >\n validator<\n Target extends keyof ValidationTargets,\n Opts extends SchemaOptions<keyof Fields & string> | undefined,\n E extends Env = Env,\n P extends string = string,\n >(\n target: Target,\n opts?: Opts,\n hook?: Hook<z.output<Apply<FieldsToZodShape<Fields>, Opts>>, E, P, Target>,\n ): ModelValidatorReturn<Fields, Target, Opts>\n\n /**\n * Returns a Zod schema for API input, with policy-based field exclusions applied.\n * - 'create': serverOnly and readOnly fields are excluded\n * - 'update': same exclusions + all fields become optional (partial: true)\n *\n * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.\n */\n inputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(\n usage: 'create',\n opts?: Opts,\n ): z.ZodObject<\n ApplyShape<\n Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'input-create'> & string>,\n Opts\n >\n >\n inputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(\n usage: 'update',\n opts?: Opts,\n ): z.ZodObject<\n ApplyShape<\n Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'input-update'> & string>,\n Opts extends undefined ? { partial: true } : Opts & { partial: true }\n >\n >\n inputSchema(\n usage: 'create' | 'update',\n opts?: SchemaOptions<keyof Fields & string>,\n ): z.ZodObject<z.ZodRawShape>\n\n /**\n * Returns a Zod schema for API output, with policy-based field exclusions applied.\n * - serverOnly and writeOnly fields are excluded\n * - readOnly fields remain present\n *\n * The return type precisely reflects policy-derived omissions using PolicyOmitKeys.\n */\n outputSchema<Opts extends SchemaOptions<keyof Fields & string> | undefined = undefined>(\n opts?: Opts,\n ): z.ZodObject<\n ApplyShape<Omit<FieldsToZodShape<Fields>, PolicyOmitKeys<Fields, 'output'> & string>, Opts>\n >\n\n /**\n * Parses a DB row through outputSchema and returns the safe response object.\n * Equivalent to `User.outputSchema().parse(row)`.\n */\n toResponse(row: RowType<Fields>): unknown\n\n toOpenAPIComponent(): OpenAPIModelComponent\n\n toOpenAPISchema(usage: OpenAPIUsage): OpenAPISchemaObject\n\n /**\n * Fetches multiple rows with pagination and optional ordering.\n * `limit` is required (no default) to prevent accidental unbounded queries.\n * Offset defaults to 0 if omitted.\n *\n * @example\n * const users = await User.findMany(adapter, { limit: 20 })\n * const page2 = await User.findMany(adapter, { limit: 20, offset: 20 })\n * const sorted = await User.findMany(adapter, { limit: 10, orderBy: 'name' })\n */\n findMany(adapter: Adapter, options: FindManyOptions<Fields>): Promise<RowType<Fields>[]>\n\n /**\n * Fetches a single row by primary key or where clause.\n * Returns null if not found.\n *\n * @example\n * const user = await User.findOne(adapter, id)\n * const byEmail = await User.findOne(adapter, { email: 'john@example.com' })\n */\n findOne(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<RowType<Fields> | null>\n\n /**\n * Creates a new row and returns the created record.\n *\n * @example\n * const user = await User.create(adapter, { name: 'John', email: 'john@example.com' })\n */\n create(adapter: Adapter, data: CreateInput<Fields>): Promise<RowType<Fields>>\n\n /**\n * Updates rows matching the given id or where clause.\n * Returns the updated row(s), or null if no rows matched.\n *\n * @example\n * const updated = await User.update(adapter, id, { name: 'Jane' })\n * const byEmail = await User.update(adapter, { email: '...' }, { name: 'Jane' })\n */\n update(\n adapter: Adapter,\n idOrWhere: IdOrWhere<Fields>,\n data: Partial<RowType<Fields>>,\n ): Promise<RowType<Fields> | null>\n\n /**\n * Deletes rows matching the given id or where clause.\n * Returns the number of deleted rows.\n *\n * @example\n * const result = await User.delete(adapter, id)\n * console.log(result.deleted) // number\n */\n delete(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<{ readonly deleted: number }>\n}\n","import { z } from 'zod'\nimport type { Field } from '../field/types'\nimport { type FieldAccessor, resolveSchemaOptionKeys, type SchemaOptions } from './types'\n\ntype PolicyUsage = 'input-create' | 'input-update' | 'output'\n\n/**\n * Returns field names that are security-critical and must always be omitted from API schemas.\n * Currently only serverOnly fields. These cannot be overridden by user pick/omit.\n */\nfunction computeForcedOmit(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling\n fields: Record<string, Field<any, any, any>>,\n): string[] {\n const omit: string[] = []\n for (const [key, field] of Object.entries(fields)) {\n if (field.modifiers.policy === 'serverOnly') {\n omit.push(key)\n }\n }\n return omit\n}\n\n/**\n * Returns field names to omit based on UX-oriented policy (writeOnly / readOnly).\n * These can be overridden when user explicitly provides pick.\n *\n * Policy mapping:\n * - `writeOnly`: omitted from output only. For input targets (input-create, input-update),\n * writeOnly fields are NOT omitted — they are intentionally part of the input (e.g. password).\n * - `readOnly`: omitted from input targets (input-create, input-update) only. Remains in output.\n *\n * The asymmetry is by design: writeOnly means \"accepted on write, hidden on read\";\n * readOnly means \"visible on read, rejected on write\".\n */\nfunction computeOptionalOmit(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling\n fields: Record<string, Field<any, any, any>>,\n target: PolicyUsage,\n): string[] {\n const omit: string[] = []\n for (const [key, field] of Object.entries(fields)) {\n const policy = field.modifiers.policy\n if (!policy) continue\n if (policy === 'writeOnly' && target === 'output') {\n omit.push(key)\n } else if (policy === 'readOnly' && (target === 'input-create' || target === 'input-update')) {\n omit.push(key)\n }\n }\n return omit\n}\n\n/**\n * Merges policy-derived omit with user-provided SchemaOptions.\n *\n * serverOnly fields are always omitted regardless of user pick/omit (security invariant).\n * writeOnly / readOnly are UX-oriented and can be overridden when user provides pick.\n * For 'input-update', partial defaults to true unless user specifies otherwise.\n */\nexport function derivePolicyOptions(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling\n fields: Record<string, Field<any, any, any>>,\n usage: PolicyUsage,\n userOpts?: SchemaOptions,\n // biome-ignore lint/suspicious/noExplicitAny: accessor is a plain object with string keys\n accessor?: FieldAccessor<any>,\n): SchemaOptions {\n const forced = computeForcedOmit(fields)\n const optional = computeOptionalOmit(fields, usage)\n\n const acc = accessor ?? ({} as FieldAccessor<string>)\n const resolvedPick = resolveSchemaOptionKeys(userOpts?.pick, acc)\n const resolvedOmit = resolveSchemaOptionKeys(userOpts?.omit, acc)\n\n if (resolvedPick !== undefined) {\n const partial = usage === 'input-update' ? (userOpts?.partial ?? true) : userOpts?.partial\n // serverOnly fields are stripped from pick even if user explicitly listed them\n const sanitizedPick = Array.from(resolvedPick).filter((k) => !forced.includes(k))\n // Combine forced omit with user-provided omit to preserve both constraints\n const combinedOmit = [...new Set([...forced, ...(resolvedOmit ?? [])])]\n return {\n ...userOpts,\n pick: sanitizedPick,\n ...(combinedOmit.length > 0 ? { omit: combinedOmit } : {}),\n partial,\n }\n }\n\n const combinedOmit = [...new Set([...forced, ...optional, ...(resolvedOmit ?? [])])]\n const partial =\n usage === 'input-update' ? (userOpts?.partial ?? true) : (userOpts?.partial ?? undefined)\n\n return {\n ...(userOpts ?? {}),\n pick: undefined,\n ...(combinedOmit.length > 0 ? { omit: combinedOmit } : {}),\n ...(partial !== undefined ? { partial } : {}),\n }\n}\n\n/**\n * Builds a Zod object schema from a fields definition.\n * Returns a ZodObject with all fields required and present.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field handling and Zod shape\nexport function buildBaseObject(fields: Record<string, Field<any, any, any>>): z.ZodObject<any> {\n // biome-ignore lint/suspicious/noExplicitAny: Record key-value pairs have any type for shape\n const shape: Record<string, any> = {}\n for (const [key, field] of Object.entries(fields)) {\n shape[key] = field.zodBase\n }\n return z.object(shape)\n}\n\n/**\n * Applies pick, omit, and partial transformations to a Zod object schema.\n * Order: pick → omit → partial\n *\n * Returns the transformed schema, cast to Apply<Shape, Opts> at the call site.\n */\nexport function applySchemaOptions(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Zod shape operations\n baseSchema: z.ZodObject<any>,\n opts: SchemaOptions | undefined,\n // biome-ignore lint/suspicious/noExplicitAny: accessor is a plain object with string keys\n accessor?: FieldAccessor<any>,\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for return type\n): z.ZodObject<any> {\n if (!opts) {\n return baseSchema\n }\n\n const acc = accessor ?? ({} as FieldAccessor<string>)\n const resolvedPick = resolveSchemaOptionKeys(opts.pick, acc)\n const resolvedOmit = resolveSchemaOptionKeys(opts.omit, acc)\n\n let schema = baseSchema\n\n // Apply pick\n if (resolvedPick !== undefined) {\n const pickArray = Array.from(resolvedPick)\n schema = schema.pick(\n // biome-ignore lint/suspicious/noExplicitAny: Zod API\n Object.fromEntries(pickArray.map((k) => [k, true])) as any,\n )\n }\n\n // Apply omit\n if (resolvedOmit !== undefined) {\n const omitArray = Array.from(resolvedOmit)\n schema = schema.omit(\n // biome-ignore lint/suspicious/noExplicitAny: Zod API\n Object.fromEntries(omitArray.map((k) => [k, true])) as any,\n )\n }\n\n // Apply partial\n // `partial: false` を渡してもこの条件で何もしない。スキーマは required のまま。\n if (opts.partial === true) {\n schema = schema.partial()\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Cast to Apply type at call site\n return schema as any\n}\n","import type { Field } from '../field/types'\nimport { applySchemaOptions, buildBaseObject, derivePolicyOptions } from '../model/schema'\nimport type { SchemaOptions } from '../model/types'\nimport type { OpenAPIModelComponent, OpenAPISchemaObject, OpenAPIUsage } from './types'\n\n// biome-ignore lint/suspicious/noExplicitAny: OpenAPI generation accepts any concrete field builder.\ntype AnyField = Field<any, any, any>\ntype FieldsRecord = Record<string, AnyField>\n\ninterface OpenAPIOptions {\n readonly opts?: SchemaOptions\n readonly strict?: boolean\n}\n\nexport function toOpenAPIComponent(\n fields: FieldsRecord,\n opts?: OpenAPIOptions,\n): OpenAPIModelComponent {\n return {\n create: toOpenAPISchema(fields, 'create', opts),\n update: toOpenAPISchema(fields, 'update', opts),\n output: toOpenAPISchema(fields, 'output', opts),\n }\n}\n\nexport function toOpenAPISchema(\n fields: FieldsRecord,\n usage: OpenAPIUsage,\n opts?: OpenAPIOptions,\n): OpenAPISchemaObject {\n const policyUsage =\n usage === 'create' ? 'input-create' : usage === 'update' ? 'input-update' : 'output'\n const merged = derivePolicyOptions(fields, policyUsage, opts?.opts)\n const schema = applySchemaOptions(buildBaseObject(fields), merged)\n const shape = getZodObjectShape(schema)\n const properties: Record<string, OpenAPISchemaObject> = {}\n const required: string[] = []\n\n for (const [key, zodSchema] of Object.entries(shape)) {\n const field = fields[key]\n if (field === undefined) continue\n\n properties[key] = fieldToOpenAPISchema(field, opts?.strict)\n if (field.modifiers.policy === 'writeOnly' && (usage === 'create' || usage === 'update')) {\n properties[key].writeOnly = true\n }\n if (field.modifiers.policy === 'readOnly' && usage === 'output') {\n properties[key].readOnly = true\n }\n if (usage !== 'update' && isRequiredZodSchema(zodSchema)) {\n required.push(key)\n }\n }\n\n return {\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n }\n}\n\nfunction fieldToOpenAPISchema(field: AnyField, strict = false): OpenAPISchemaObject {\n const schema: OpenAPISchemaObject =\n field.kind === 'json'\n ? zodToOpenAPISchema(field.zodBase, strict)\n : field.kind === 'string'\n ? { type: 'string' }\n : field.kind === 'uuid'\n ? { type: 'string', format: 'uuid' }\n : field.kind === 'number'\n ? { type: 'number' }\n : field.kind === 'integer'\n ? { type: 'integer' }\n : field.kind === 'boolean'\n ? { type: 'boolean' }\n : field.kind === 'timestamp'\n ? { type: 'string', format: 'date-time' }\n : {}\n\n if (field.modifiers.format === 'email') {\n schema.format = 'email'\n }\n if (field.modifiers.min !== undefined) {\n if (field.kind === 'string' || field.kind === 'uuid') {\n schema.minLength = field.modifiers.min\n } else {\n schema.minimum = field.modifiers.min\n }\n }\n if (field.modifiers.max !== undefined) {\n if (field.kind === 'string' || field.kind === 'uuid') {\n schema.maxLength = field.modifiers.max\n } else {\n schema.maximum = field.modifiers.max\n }\n }\n\n if (field.modifiers.optional) {\n schema.nullable = true\n }\n\n return schema\n}\n\nfunction zodToOpenAPISchema(schema: unknown, strict = false): OpenAPISchemaObject {\n const def = getZodDef(schema)\n if (def === undefined) return {}\n\n const typeName = getZodTypeName(def)\n\n if (typeName === 'ZodOptional' || typeName === 'optional') {\n return zodToOpenAPISchema(def.innerType, strict)\n }\n if (typeName === 'ZodDefault' || typeName === 'default') {\n return zodToOpenAPISchema(def.innerType, strict)\n }\n if (typeName === 'ZodNullable' || typeName === 'nullable') {\n return { ...zodToOpenAPISchema(def.innerType, strict), nullable: true }\n }\n\n if (typeName === 'ZodObject' || typeName === 'object') {\n const shape = getZodObjectShape(schema)\n const properties: Record<string, OpenAPISchemaObject> = {}\n const required: string[] = []\n\n for (const [key, childSchema] of Object.entries(shape)) {\n properties[key] = zodToOpenAPISchema(childSchema, strict)\n if (isRequiredZodSchema(childSchema)) {\n required.push(key)\n }\n }\n\n return {\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n }\n }\n\n if (typeName === 'ZodString' || typeName === 'string') {\n return applyStringChecks({ type: 'string' }, def)\n }\n\n if (typeName === 'ZodNumber' || typeName === 'number') {\n return applyNumberChecks({ type: hasIntegerCheck(def) ? 'integer' : 'number' }, def)\n }\n\n if (typeName === 'ZodBoolean' || typeName === 'boolean') {\n return { type: 'boolean' }\n }\n\n if (typeName === 'ZodArray' || typeName === 'array') {\n const itemSchema = def.element ?? def.type\n return {\n type: 'array',\n items: zodToOpenAPISchema(itemSchema, strict),\n }\n }\n\n if (typeName === 'ZodRecord' || typeName === 'record') {\n return {\n type: 'object',\n additionalProperties: zodToOpenAPISchema(def.valueType, strict),\n }\n }\n\n if (typeName === 'ZodUnknown' || typeName === 'unknown') {\n return {}\n }\n\n if (strict) {\n throw new Error(`Unsupported Zod type for strict OpenAPI generation: ${typeName ?? 'unknown'}`)\n }\n return {\n 'x-nanoka-zod-unsupported': true,\n ...(typeName ? { 'x-nanoka-zod-type': typeName } : {}),\n }\n}\n\nfunction getZodObjectShape(schema: unknown): Record<string, unknown> {\n if (\n typeof schema === 'object' &&\n schema !== null &&\n 'shape' in schema &&\n typeof schema.shape === 'object' &&\n schema.shape !== null\n ) {\n return schema.shape as Record<string, unknown>\n }\n\n if (\n typeof schema === 'object' &&\n schema !== null &&\n '_def' in schema &&\n typeof schema._def === 'object' &&\n schema._def !== null &&\n 'shape' in schema._def\n ) {\n const shape = schema._def.shape\n return (typeof shape === 'function' ? shape() : shape) as Record<string, unknown>\n }\n\n return {}\n}\n\nfunction isRequiredZodSchema(schema: unknown): boolean {\n const def = getZodDef(schema)\n if (def === undefined) {\n return true\n }\n\n const typeName = getZodTypeName(def)\n return (\n typeName !== 'ZodOptional' &&\n typeName !== 'optional' &&\n typeName !== 'ZodDefault' &&\n typeName !== 'default'\n )\n}\n\nfunction getZodDef(schema: unknown): Record<string, unknown> | undefined {\n if (\n typeof schema === 'object' &&\n schema !== null &&\n '_def' in schema &&\n typeof schema._def === 'object' &&\n schema._def !== null\n ) {\n return schema._def as Record<string, unknown>\n }\n\n return undefined\n}\n\nfunction getZodTypeName(def: Record<string, unknown>): string | undefined {\n return typeof def.typeName === 'string'\n ? def.typeName\n : typeof def.type === 'string'\n ? def.type\n : undefined\n}\n\nfunction applyStringChecks(\n schema: OpenAPISchemaObject,\n def: Record<string, unknown>,\n): OpenAPISchemaObject {\n for (const check of getZodChecks(def)) {\n const checkDef = getZodCheckDef(check)\n if (checkDef.kind === 'email' || checkDef.format === 'email') {\n schema.format = 'email'\n }\n if (checkDef.kind === 'min' && typeof checkDef.value === 'number') {\n schema.minLength = checkDef.value\n }\n if (checkDef.kind === 'max' && typeof checkDef.value === 'number') {\n schema.maxLength = checkDef.value\n }\n if (checkDef.check === 'min_length' && typeof checkDef.minimum === 'number') {\n schema.minLength = checkDef.minimum\n }\n if (checkDef.check === 'max_length' && typeof checkDef.maximum === 'number') {\n schema.maxLength = checkDef.maximum\n }\n }\n\n return schema\n}\n\nfunction applyNumberChecks(\n schema: OpenAPISchemaObject,\n def: Record<string, unknown>,\n): OpenAPISchemaObject {\n for (const check of getZodChecks(def)) {\n const checkDef = getZodCheckDef(check)\n if (checkDef.kind === 'min' && typeof checkDef.value === 'number') {\n schema.minimum = checkDef.value\n }\n if (checkDef.kind === 'max' && typeof checkDef.value === 'number') {\n schema.maximum = checkDef.value\n }\n if (\n (checkDef.check === 'greater_than' || checkDef.check === 'number_format') &&\n typeof checkDef.minimum === 'number'\n ) {\n schema.minimum = checkDef.minimum\n }\n if (\n (checkDef.check === 'less_than' || checkDef.check === 'number_format') &&\n typeof checkDef.maximum === 'number'\n ) {\n schema.maximum = checkDef.maximum\n }\n }\n\n return schema\n}\n\nfunction hasIntegerCheck(def: Record<string, unknown>): boolean {\n return getZodChecks(def).some((check) => {\n const checkDef = getZodCheckDef(check)\n return (\n checkDef.kind === 'int' ||\n checkDef.format === 'safeint' ||\n checkDef.format === 'int32' ||\n checkDef.format === 'int64'\n )\n })\n}\n\nfunction getZodChecks(def: Record<string, unknown>): readonly unknown[] {\n return Array.isArray(def.checks) ? def.checks : []\n}\n\nfunction getZodCheckDef(check: unknown): Record<string, unknown> {\n if (typeof check !== 'object' || check === null) {\n return {}\n }\n if (\n '_zod' in check &&\n typeof check._zod === 'object' &&\n check._zod !== null &&\n 'def' in check._zod &&\n typeof check._zod.def === 'object' &&\n check._zod.def !== null\n ) {\n return check._zod.def as Record<string, unknown>\n }\n\n return check as Record<string, unknown>\n}\n","import { and, asc, desc, eq } from 'drizzle-orm'\nimport type { SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'\nimport { HTTPException } from 'hono/http-exception'\nimport type { Adapter } from '../adapter/types'\nimport type { Field } from '../field/types'\nimport type { CreateInput, IdOrWhere, OrderBy, RowType, Where } from './types'\n\nconst MAX_LIMIT = 100\n\n/**\n * Validates and guards limit/offset parameters.\n * @internal\n */\nfunction guardLimit(limit: unknown): number {\n if (!Number.isInteger(limit)) {\n throw new HTTPException(400, { message: 'limit must be an integer' })\n }\n const n = limit as number\n if (n < 0) {\n throw new HTTPException(400, { message: 'limit must be >= 0' })\n }\n if (n > MAX_LIMIT) {\n throw new HTTPException(400, { message: `limit must be <= ${MAX_LIMIT}` })\n }\n return n\n}\n\nfunction guardOffset(offset: unknown): number {\n if (!Number.isInteger(offset)) {\n throw new HTTPException(400, { message: 'offset must be an integer' })\n }\n const n = offset as number\n if (n < 0) {\n throw new HTTPException(400, { message: 'offset must be >= 0' })\n }\n return n\n}\n\n/**\n * Finds the primary key field from fields record.\n * @internal\n */\nfunction findPrimaryKey(\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n fields: Record<string, Field<any, any, any>>,\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n): [string, Field<any, any, any>] | null {\n let pkKey: string | undefined\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n let pkField: Field<any, any, any> | undefined\n let pkCount = 0\n\n for (const [key, field] of Object.entries(fields)) {\n if (field.modifiers.primary === true) {\n pkCount++\n if (pkCount === 1) {\n pkKey = key\n pkField = field\n }\n }\n }\n\n if (pkCount === 0) {\n return null\n }\n if (pkCount > 1) {\n throw new HTTPException(500, { message: 'model has multiple primary keys' })\n }\n if (pkKey === undefined || pkField === undefined) {\n return null\n }\n\n return [pkKey, pkField]\n}\n\n/**\n * Constructs a Drizzle where clause from an object.\n * All entries are combined with AND.\n * @internal\n */\nfunction buildWhereClause(\n table: SQLiteTableWithColumns<any>,\n fields: Record<string, Field<any, any, any>>,\n where: Where<Record<string, any>>,\n): ReturnType<typeof and> | null {\n const conditions: ReturnType<typeof eq>[] = []\n\n for (const [key, value] of Object.entries(where)) {\n // Multi-layered guard against identifier injection\n if (!Object.hasOwn(fields, key)) {\n throw new HTTPException(400, { message: 'invalid field in where clause' })\n }\n if (!Object.hasOwn(table, key)) {\n throw new HTTPException(400, { message: 'invalid column in table' })\n }\n // biome-ignore lint/suspicious/noExplicitAny: table column access is runtime-guarded by hasOwn\n const col = (table as unknown as Record<string, any>)[key]\n conditions.push(eq(col, value))\n }\n\n if (conditions.length === 0) {\n return null\n }\n if (conditions.length === 1) {\n return conditions[0]\n }\n return and(...conditions)\n}\n\n/**\n * Fetches multiple rows with limit, offset, and optional ordering.\n * @internal\n */\nexport async function findManyImpl<\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\n Fields extends Record<string, Field<any, any, any>>,\n>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n _fields: Fields,\n options: {\n limit: unknown\n offset?: unknown\n orderBy?: OrderBy<Fields>\n },\n): Promise<RowType<Fields>[]> {\n const limit = guardLimit(options.limit)\n const offset = options.offset !== undefined ? guardOffset(options.offset) : 0\n\n // biome-ignore lint/suspicious/noExplicitAny: drizzle query builder type narrowing\n let query: any = adapter.drizzle.select().from(table).limit(limit).offset(offset)\n\n // Apply ordering\n if (options.orderBy !== undefined) {\n const orderByList = Array.isArray(options.orderBy) ? options.orderBy : [options.orderBy]\n\n for (const orderByItem of orderByList) {\n let column: string\n let direction: 'asc' | 'desc' = 'asc'\n\n if (typeof orderByItem === 'string') {\n column = orderByItem\n } else if (\n typeof orderByItem === 'object' &&\n orderByItem !== null &&\n 'column' in orderByItem\n ) {\n column = orderByItem.column\n if (orderByItem.direction) {\n direction = orderByItem.direction\n }\n } else {\n throw new HTTPException(400, { message: 'invalid orderBy format' })\n }\n\n // Runtime guard against identifier injection\n if (!Object.hasOwn(table, column)) {\n throw new HTTPException(400, { message: 'invalid field in orderBy' })\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: table column access is runtime-guarded by hasOwn\n const col = (table as unknown as Record<string, any>)[column]\n query = query.orderBy(direction === 'asc' ? asc(col) : desc(col))\n }\n }\n\n const rows = await query\n return rows\n}\n\n/**\n * Fetches a single row by primary key or where clause.\n * @internal\n */\nexport async function findOneImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n fields: Fields,\n idOrWhere: IdOrWhere<Fields>,\n): Promise<RowType<Fields> | null> {\n let where: Where<Fields> | null = null\n\n if (typeof idOrWhere === 'string' || typeof idOrWhere === 'number') {\n // PK mode\n const pk = findPrimaryKey(fields)\n if (!pk) {\n throw new HTTPException(500, { message: 'model has no primary key' })\n }\n where = { [pk[0]]: idOrWhere } as Where<Fields>\n } else {\n where = idOrWhere as Where<Fields>\n }\n\n const whereClause = buildWhereClause(table, fields, where)\n if (!whereClause) {\n throw new HTTPException(400, { message: 'where clause must not be empty' })\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: drizzle query type\n const rows = await (adapter.drizzle.select().from(table).where(whereClause).limit(1) as any)\n return rows.length > 0 ? rows[0] : null\n}\n\n/**\n * Creates a new row and returns the created record.\n * @internal\n */\nexport async function createImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n data: CreateInput<Fields>,\n): Promise<RowType<Fields>> {\n const rows = await (adapter.drizzle\n .insert(table)\n .values(data as any)\n .returning() as any)\n return rows[0]\n}\n\n/**\n * Updates rows matching the given id or where clause.\n * @internal\n */\nexport async function updateImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n fields: Fields,\n idOrWhere: IdOrWhere<Fields>,\n data: Partial<RowType<Fields>>,\n): Promise<RowType<Fields> | null> {\n let where: Where<Fields> | null = null\n\n if (typeof idOrWhere === 'string' || typeof idOrWhere === 'number') {\n // PK mode\n const pk = findPrimaryKey(fields)\n if (!pk) {\n throw new HTTPException(500, { message: 'model has no primary key' })\n }\n where = { [pk[0]]: idOrWhere } as Where<Fields>\n } else {\n where = idOrWhere as Where<Fields>\n }\n\n const whereClause = buildWhereClause(table, fields, where)\n if (!whereClause) {\n throw new HTTPException(400, { message: 'where clause must not be empty' })\n }\n\n const rows = await (adapter.drizzle\n .update(table)\n .set(data as any)\n .where(whereClause)\n .returning() as any)\n return rows.length > 0 ? rows[0] : null\n}\n\n/**\n * Deletes rows matching the given id or where clause.\n * @internal\n */\nexport async function deleteImpl<Fields extends Record<string, Field<any, any, any>>>(\n adapter: Adapter,\n table: SQLiteTableWithColumns<any>,\n fields: Fields,\n idOrWhere: IdOrWhere<Fields>,\n): Promise<{ readonly deleted: number }> {\n let where: Where<Fields> | null = null\n\n if (typeof idOrWhere === 'string' || typeof idOrWhere === 'number') {\n // PK mode\n const pk = findPrimaryKey(fields)\n if (!pk) {\n throw new HTTPException(500, { message: 'model has no primary key' })\n }\n where = { [pk[0]]: idOrWhere } as Where<Fields>\n } else {\n where = idOrWhere as Where<Fields>\n }\n\n const whereClause = buildWhereClause(table, fields, where)\n if (!whereClause) {\n throw new HTTPException(400, { message: 'where clause must not be empty' })\n }\n\n const result = await adapter.drizzle.delete(table).where(whereClause).returning()\n return { deleted: result.length }\n}\n","import {\n type AnySQLiteColumn,\n type SQLiteTableWithColumns,\n sqliteTable,\n} from 'drizzle-orm/sqlite-core'\nimport type { Field } from '../field/types'\n\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\ntype ModelTable<Fields extends Record<string, Field<any, any, any>>> = SQLiteTableWithColumns<{\n name: string\n schema: undefined\n columns: { [K in keyof Fields]: AnySQLiteColumn }\n dialect: 'sqlite'\n}>\n\n/**\n * Constructs a Drizzle SQLiteTable from a tableName and fields.\n * Each field is converted to a Drizzle column via field.drizzleColumn(key).\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field constraint\nexport function buildTable<Fields extends Record<string, Field<any, any, any>>>(\n tableName: string,\n fields: Fields,\n): ModelTable<Fields> {\n const columns: Record<string, any> = {}\n for (const [key, field] of Object.entries(fields)) {\n columns[key] = field.drizzleColumn(key)\n }\n return sqliteTable(tableName, columns) as unknown as ModelTable<Fields>\n}\n","import { type Hook, zValidator } from '@hono/zod-validator'\nimport type { Env, ValidationTargets } from 'hono'\nimport type { z } from 'zod'\nimport type { Adapter } from '../adapter/types'\nimport type { Field } from '../field/types'\nimport { toOpenAPIComponent, toOpenAPISchema } from '../openapi/generate'\nimport type { OpenAPIUsage } from '../openapi/types'\nimport { createImpl, deleteImpl, findManyImpl, findOneImpl, updateImpl } from './crud'\nimport { applySchemaOptions, buildBaseObject, derivePolicyOptions } from './schema'\nimport { buildTable } from './table'\nimport type {\n Apply,\n CreateInput,\n FieldsToZodShape,\n FindManyOptions,\n IdOrWhere,\n Model,\n RowType,\n SchemaOptions,\n} from './types'\nimport { buildFieldAccessor } from './types'\n\n/**\n * Creates a Model instance from a tableName and fields definition.\n * The model supports deriving Zod schemas, Hono validators, and CRUD operations.\n *\n * @example\n * const User = defineModel('users', {\n * id: t.uuid().primary(),\n * name: t.string(),\n * email: t.string().email(),\n * passwordHash: t.string(),\n * })\n *\n * const CreateSchema = User.schema({ omit: ['passwordHash'] })\n * const users = await User.findMany(adapter, { limit: 20 })\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is necessary for generic Field constraint\nexport function defineModel<Fields extends Record<string, Field<any, any, any>>>(\n tableName: string,\n fields: Fields,\n): Model<Fields> {\n const table = buildTable(tableName, fields)\n const accessor = buildFieldAccessor(fields)\n\n return {\n fields,\n tableName,\n table,\n\n schema<Opts extends SchemaOptions<keyof Fields & string> | undefined>(\n opts?: Opts,\n ): Apply<FieldsToZodShape<Fields>, Opts> {\n const baseSchema = buildBaseObject(fields)\n const schema = applySchemaOptions(baseSchema, opts, accessor)\n // biome-ignore lint/suspicious/noExplicitAny: Zod .pick()/.omit() return type narrowing requires cast at boundary\n return schema as any\n },\n\n validator(\n target: keyof ValidationTargets,\n optsOrPreset?: 'create' | 'update' | SchemaOptions<keyof Fields & string>,\n // biome-ignore lint/suspicious/noExplicitAny: Hook<T> is contravariant in T; any is required to bridge overload implementations\n hook?: Hook<any, Env, string, keyof ValidationTargets>,\n ) {\n let schema: z.ZodTypeAny\n if (optsOrPreset === 'create' || optsOrPreset === 'update') {\n schema = this.inputSchema(optsOrPreset)\n } else {\n schema = this.schema(optsOrPreset as SchemaOptions<keyof Fields & string>)\n }\n // biome-ignore lint/suspicious/noExplicitAny: zValidator return type cast required at overload boundary\n return zValidator(target, schema, hook) as any\n },\n\n inputSchema(\n usage: 'create' | 'update',\n opts?: SchemaOptions<keyof Fields & string>,\n // biome-ignore lint/suspicious/noExplicitAny: precise return type is enforced by Model<Fields> overload signatures\n ): any {\n const merged = derivePolicyOptions(\n fields,\n usage === 'create' ? 'input-create' : 'input-update',\n opts,\n accessor,\n )\n const baseSchema = buildBaseObject(fields)\n return applySchemaOptions(baseSchema, merged)\n },\n\n outputSchema(\n opts?: SchemaOptions<keyof Fields & string>,\n // biome-ignore lint/suspicious/noExplicitAny: precise return type is enforced by Model<Fields> overload signatures\n ): any {\n const merged = derivePolicyOptions(fields, 'output', opts, accessor)\n const baseSchema = buildBaseObject(fields)\n return applySchemaOptions(baseSchema, merged)\n },\n\n toResponse(row: RowType<Fields>): unknown {\n return this.outputSchema().parse(row)\n },\n\n toOpenAPIComponent() {\n return toOpenAPIComponent(fields)\n },\n\n toOpenAPISchema(usage: OpenAPIUsage) {\n return toOpenAPISchema(fields, usage)\n },\n\n findMany(adapter: Adapter, options: FindManyOptions<Fields>): Promise<RowType<Fields>[]> {\n return findManyImpl(adapter, table, fields, options)\n },\n\n findOne(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<RowType<Fields> | null> {\n return findOneImpl(adapter, table, fields, idOrWhere)\n },\n\n create(adapter: Adapter, data: CreateInput<Fields>): Promise<RowType<Fields>> {\n return createImpl(adapter, table, data)\n },\n\n update(\n adapter: Adapter,\n idOrWhere: IdOrWhere<Fields>,\n data: Partial<RowType<Fields>>,\n ): Promise<RowType<Fields> | null> {\n return updateImpl(adapter, table, fields, idOrWhere, data)\n },\n\n delete(adapter: Adapter, idOrWhere: IdOrWhere<Fields>): Promise<{ readonly deleted: number }> {\n return deleteImpl(adapter, table, fields, idOrWhere)\n },\n }\n}\n","import type { OpenAPIDocument, OpenAPIRouteMetadata, OpenAPISpecOptions } from './types'\n\nfunction honoPathToOpenAPI(path: string): string {\n return path.replace(/:([^/]+)/g, '{$1}')\n}\n\nexport function buildOpenAPIDocument(\n routes: readonly OpenAPIRouteMetadata[],\n options: OpenAPISpecOptions,\n): OpenAPIDocument {\n const paths: Record<string, Record<string, unknown>> = {}\n\n for (const route of routes) {\n const openAPIPath = honoPathToOpenAPI(route.path)\n if (!paths[openAPIPath]) {\n paths[openAPIPath] = {}\n }\n\n const operation: Record<string, unknown> = {}\n if (route.operationId) operation.operationId = route.operationId\n if (route.summary) operation.summary = route.summary\n if (route.description) operation.description = route.description\n if (route.tags) operation.tags = route.tags\n\n const parameters: unknown[] = []\n const pathParams = [...route.path.matchAll(/:([^/]+)/g)].map((m) => m[1])\n for (const param of pathParams) {\n const alreadyDefined = route.params?.some((p) => p.name === param && p.in === 'path')\n if (!alreadyDefined) {\n parameters.push({ name: param, in: 'path', required: true, schema: { type: 'string' } })\n }\n }\n if (route.params) {\n parameters.push(...route.params)\n }\n if (parameters.length > 0) operation.parameters = parameters\n\n if (route.requestBody) operation.requestBody = route.requestBody\n operation.responses = route.responses\n\n paths[openAPIPath][route.method] = operation\n }\n\n const doc: OpenAPIDocument = {\n openapi: '3.1.0',\n info: options.info,\n ...(options.servers ? { servers: options.servers } : {}),\n paths,\n }\n\n return doc\n}\n","import type { MiddlewareHandler } from 'hono'\n\nexport interface SwaggerUIOptions {\n readonly url: string\n readonly title?: string\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nexport function swaggerUI(options: SwaggerUIOptions): MiddlewareHandler {\n const title = escapeHtml(options.title ?? 'API Documentation')\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <title>${title}</title>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui.css\" />\n</head>\n<body>\n <div id=\"swagger-ui\"></div>\n <script src=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js\"></script>\n <script>\n SwaggerUIBundle({\n url: ${JSON.stringify(options.url)},\n dom_id: '#swagger-ui',\n presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],\n layout: 'BaseLayout',\n })\n </script>\n</body>\n</html>`\n\n return async (c) => {\n return c.html(html)\n }\n}\n","import { Hono } from 'hono'\nimport type { BlankEnv, Env, H } from 'hono/types'\nimport type { Adapter } from '../adapter/types'\nimport type { Field } from '../field/types'\nimport { defineModel } from '../model/define'\nimport { buildOpenAPIDocument } from '../openapi/route'\nimport type { HttpMethod, OpenAPIRouteMetadata } from '../openapi/types'\nimport type { Nanoka, NanokaModel, RouteOpenAPIOption } from './types'\n\n/**\n * Creates a Nanoka application instance with the given database adapter.\n *\n * @param adapter - The database adapter (e.g., d1Adapter(env.DB))\n * @returns A Nanoka application (Hono extended with model(), db, and batch)\n *\n * @example\n * export default {\n * fetch(req: Request, env: Env, ctx: ExecutionContext) {\n * const app = nanoka(d1Adapter(env.DB))\n * const User = app.model('users', { id, name, email, passwordHash })\n * app.get('/users', async (c) => {\n * const users = await User.findMany({ limit: 20 })\n * return c.json(users)\n * })\n * return app.fetch(req, env, ctx)\n * }\n * }\n */\nexport function nanoka<E extends Env = BlankEnv>(adapter: Adapter): Nanoka<E> {\n const app = new Hono<E>() as Nanoka<E>\n const openapiRoutes: OpenAPIRouteMetadata[] = []\n\n Object.defineProperty(app, 'db', {\n get: () => adapter.drizzle,\n enumerable: true,\n })\n\n app.batch = ((queries: Parameters<Adapter['batch']>[0]) =>\n adapter.batch(queries)) as unknown as Adapter['batch']\n\n app.openapi = (metadata: OpenAPIRouteMetadata) => {\n openapiRoutes.push(metadata)\n return app\n }\n\n app.generateOpenAPISpec = (options) => buildOpenAPIDocument(openapiRoutes, options)\n\n function wrapWithOpenAPI(method: HttpMethod) {\n // biome-ignore lint/suspicious/noExplicitAny: original Hono method is typed as HandlerInterface which needs any at call site\n const original = (app as any)[method].bind(app)\n // biome-ignore lint/suspicious/noExplicitAny: overload bridge — type safety is provided by the Nanoka interface overload\n ;(app as any)[method] = (path: string, second: RouteOpenAPIOption | H, ...rest: H[]) => {\n if (\n second !== null &&\n typeof second === 'object' &&\n !Array.isArray(second) &&\n typeof (second as RouteOpenAPIOption).openapi === 'object'\n ) {\n const { openapi } = second as RouteOpenAPIOption\n openapiRoutes.push({ ...openapi, path, method })\n return original(path, ...rest)\n }\n return original(path, second, ...rest)\n }\n }\n\n for (const method of ['get', 'post', 'put', 'patch', 'delete'] as const) {\n wrapWithOpenAPI(method)\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: any is necessary for Field generic constraint\n app.model = function model<Fields extends Record<string, Field<any, any, any>>>(\n name: string,\n fields: Fields,\n ): NanokaModel<Fields> {\n const inner = defineModel(name, fields)\n\n return {\n fields: inner.fields,\n tableName: inner.tableName,\n table: inner.table,\n\n schema: (opts) => inner.schema(opts),\n\n validator: (\n ...args: [\n keyof import('hono').ValidationTargets,\n ('create' | 'update' | import('../model/types').SchemaOptions<keyof Fields & string>)?,\n import('@hono/zod-validator').Hook<\n // biome-ignore lint/suspicious/noExplicitAny: Hook<T> is contravariant in T; any is required to bridge overload implementations\n any,\n import('hono').Env,\n string,\n keyof import('hono').ValidationTargets\n >?,\n ]\n ) => {\n // `NanokaModel` interface の overload 定義 (router/types.ts) で type safety は担保する。\n // 実装は inner.validator に委譲するだけで、型は interface 側の overload に従う。\n // biome-ignore lint/suspicious/noExplicitAny: NanokaModel interface overloads provide type safety\n return (inner.validator as (...a: typeof args) => any)(...args)\n },\n\n inputSchema: (usage, opts) => inner.inputSchema(usage, opts),\n\n outputSchema: (opts) => inner.outputSchema(opts),\n\n toResponse: (row) => inner.toResponse(row),\n\n toOpenAPIComponent: () => inner.toOpenAPIComponent(),\n\n toOpenAPISchema: (usage) => inner.toOpenAPISchema(usage),\n\n findMany: (options) => inner.findMany(adapter, options),\n\n findOne: (idOrWhere) => inner.findOne(adapter, idOrWhere),\n\n create: (data) => inner.create(adapter, data),\n\n update: (idOrWhere, data) => inner.update(adapter, idOrWhere, data),\n\n delete: (idOrWhere) => inner.delete(adapter, idOrWhere),\n }\n }\n\n return app\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanokajs/core",
3
- "version": "1.0.8",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "description": "Thin wrapper over Hono + Drizzle + Zod for Cloudflare Workers + D1. 80% automatic, 20% explicit.",
6
6
  "author": "Eiichiro Iriguchi <eiichiro_iriguchi@a-1ro.dev>",