hono-takibi 0.9.9998 → 0.9.9999

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +56 -56
  2. package/dist/index.js +2 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -4,12 +4,6 @@
4
4
 
5
5
  ![img](https://raw.githubusercontent.com/nakita628/hono-takibi/refs/heads/main/assets/img/hono-takibi.png)
6
6
 
7
- ```bash
8
- npm install -D hono-takibi
9
- ```
10
-
11
- ## OpenAPI to Hono Code Generator
12
-
13
7
  **[Hono Takibi](https://www.npmjs.com/package/hono-takibi)** generates type-safe [Hono](https://hono.dev/) code from [OpenAPI](https://www.openapis.org/) / [TypeSpec](https://typespec.io/) specifications.
14
8
 
15
9
  - OpenAPI schemas to [Zod](https://zod.dev/) schemas
@@ -19,6 +13,10 @@ npm install -D hono-takibi
19
13
  - RPC client, mock server, TypeScript types
20
14
  - API reference docs with [hono-cli](https://github.com/honojs/cli) commands
21
15
 
16
+ ```bash
17
+ npm install -D hono-takibi
18
+ ```
19
+
22
20
  ## Quick Start
23
21
 
24
22
  ### CLI
@@ -278,7 +276,7 @@ export default defineConfig({
278
276
  })
279
277
  ```
280
278
 
281
- ### API Reference Docs
279
+ ## API Reference Docs
282
280
 
283
281
  Generate API reference Markdown with [hono-cli](https://github.com/honojs/cli) `hono request` commands:
284
282
 
@@ -314,11 +312,11 @@ import { defineConfig } from 'hono-takibi/config'
314
312
 
315
313
  export default defineConfig({
316
314
  input: 'openapi.yaml',
317
- basePath: '/api',
318
- // format: {}, // oxfmt FormatConfig
319
315
 
320
316
  output: './src/routes.ts', // single-file mode; with template.define, the app entry (required)
317
+ basePath: '/api',
321
318
  readonly: true,
319
+ // format: {}, // oxfmt FormatConfig
322
320
 
323
321
  template: {
324
322
  test: true,
@@ -499,7 +497,11 @@ export default defineConfig({
499
497
  })
500
498
  ```
501
499
 
502
- ## Custom Validation Error Messages
500
+ ## Vendor Extensions (x-\*)
501
+
502
+ hono-takibi reads `x-*` vendor extensions on your OpenAPI / JSON Schema to customize the generated Zod. Each extension maps 1:1 to a Zod feature.
503
+
504
+ ### Custom Validation Error Messages
503
505
 
504
506
  Use `x-*` vendor extensions to attach custom Zod error messages, with **one extension per JSON Schema keyword** (1:1 mapping). The extension name follows the pattern `x-<jsonSchemaKeyword>-message` (e.g. `x-minLength-message`, `x-pattern-message`), plus four generic forms: `x-error-message`, `x-required-message`, `x-const-message`, `x-enum-message`.
505
507
 
@@ -519,8 +521,6 @@ z.string({ error: 'Name must be a string' })
519
521
  .max(50, { error: 'Name must be at most 50 characters' })
520
522
  ```
521
523
 
522
- ### Extension Reference
523
-
524
524
  All custom message extensions follow the `x-<keyword>-message` naming convention and map directly to Zod validator error messages.
525
525
 
526
526
  #### Common (any schema type)
@@ -602,9 +602,9 @@ All custom message extensions follow the `x-<keyword>-message` naming convention
602
602
  | `x-unevaluatedProperties-message` | `unevaluatedProperties` |
603
603
  | `x-unevaluatedItems-message` | `unevaluatedItems` |
604
604
 
605
- ## Behavior Extensions
605
+ ### Behavior Extensions
606
606
 
607
- ### String Pre-validation Transforms
607
+ #### String Pre-validation Transforms
608
608
 
609
609
  | Extension | Generated | Value |
610
610
  | --------------- | ----------------------------- | --------------------------------------- |
@@ -624,7 +624,7 @@ homepage:
624
624
  z.string().trim().pipe(z.url())
625
625
  ```
626
626
 
627
- ### String Validation Checks
627
+ #### String Validation Checks
628
628
 
629
629
  | Extension | Generated | Value |
630
630
  | ------------- | ------------------------ | ------ |
@@ -641,9 +641,9 @@ slug:
641
641
  z.string().lowercase()
642
642
  ```
643
643
 
644
- ### Preprocess (Input Normalization)
644
+ #### Preprocess
645
645
 
646
- #### `x-preprocess`
646
+ **`x-preprocess`**
647
647
 
648
648
  ```yaml
649
649
  username:
@@ -655,9 +655,9 @@ username:
655
655
  z.preprocess((val) => (typeof val === 'string' ? val.trim() : val), z.string())
656
656
  ```
657
657
 
658
- ### Type Coercion
658
+ #### Type Coercion
659
659
 
660
- #### `x-coerce`
660
+ **`x-coerce`**
661
661
 
662
662
  ```yaml
663
663
  asNumber:
@@ -674,7 +674,7 @@ z.coerce.number()
674
674
  z.coerce.date()
675
675
  ```
676
676
 
677
- #### `x-stringbool`
677
+ **`x-stringbool`**
678
678
 
679
679
  ```yaml
680
680
  notify:
@@ -699,27 +699,27 @@ notify:
699
699
  z.stringbool({ truthy: ['yes', 'on'], falsy: ['no', 'off'], case: 'sensitive' })
700
700
  ```
701
701
 
702
- ### Codec (Bidirectional Transform)
702
+ #### Codec
703
703
 
704
- #### `x-codec`
704
+ **`x-codec`**
705
705
 
706
706
  ```yaml
707
707
  updatedAt:
708
708
  type: string
709
709
  format: date-time
710
- x-codec: 'z.codec(z.iso.datetime(), z.date(), { decode: (val) => new Date(val), encode: (val) => val.toISOString() })'
710
+ x-codec: 'z.codec(z.iso.datetime(), z.date(), { decode: (isoString) => new Date(isoString), encode: (date) => date.toISOString() })'
711
711
  ```
712
712
 
713
713
  ```ts
714
714
  z.codec(z.iso.datetime(), z.date(), {
715
- decode: (val) => new Date(val),
716
- encode: (val) => val.toISOString(),
715
+ decode: (isoString) => new Date(isoString),
716
+ encode: (date) => date.toISOString(),
717
717
  })
718
718
  ```
719
719
 
720
- ### Custom Validation
720
+ #### Custom Validation
721
721
 
722
- #### `x-refine`
722
+ **`x-refine`**
723
723
 
724
724
  ```yaml
725
725
  password:
@@ -733,7 +733,7 @@ z.string()
733
733
  .refine((val) => /[A-Z]/.test(val), { message: 'Password must contain an uppercase letter' })
734
734
  ```
735
735
 
736
- #### `x-superRefine`
736
+ **`x-superRefine`**
737
737
 
738
738
  ```yaml
739
739
  normalizedEmail:
@@ -750,9 +750,9 @@ z.email().superRefine((val, ctx) => {
750
750
  })
751
751
  ```
752
752
 
753
- ### Transform & Pipe
753
+ #### Transform & Pipe
754
754
 
755
- #### `x-transform`
755
+ **`x-transform`**
756
756
 
757
757
  ```yaml
758
758
  code:
@@ -764,7 +764,7 @@ code:
764
764
  z.string().transform((val) => val.toUpperCase())
765
765
  ```
766
766
 
767
- #### `x-pipe`
767
+ **`x-pipe`**
768
768
 
769
769
  ```yaml
770
770
  port:
@@ -776,9 +776,9 @@ port:
776
776
  z.string().pipe(z.number().int().positive())
777
777
  ```
778
778
 
779
- ### Default & Fallback Values
779
+ #### Default & Fallback Values
780
780
 
781
- #### `x-prefault`
781
+ **`x-prefault`**
782
782
 
783
783
  ```yaml
784
784
  greeting:
@@ -790,7 +790,7 @@ greeting:
790
790
  z.string().prefault('hello')
791
791
  ```
792
792
 
793
- #### `x-catch`
793
+ **`x-catch`**
794
794
 
795
795
  ```yaml
796
796
  retries:
@@ -802,9 +802,9 @@ retries:
802
802
  z.int().catch(0)
803
803
  ```
804
804
 
805
- ### Immutability
805
+ #### Immutability
806
806
 
807
- #### `x-readonly`
807
+ **`x-readonly`**
808
808
 
809
809
  ```yaml
810
810
  config:
@@ -819,9 +819,9 @@ config:
819
819
  z.object({ name: z.string() }).readonly()
820
820
  ```
821
821
 
822
- ### String Content Checks
822
+ #### String Content Checks
823
823
 
824
- #### `x-startsWith` / `x-endsWith` / `x-includes`
824
+ **`x-startsWith` / `x-endsWith` / `x-includes`**
825
825
 
826
826
  ```yaml
827
827
  url:
@@ -838,7 +838,7 @@ z.string().startsWith('https://').endsWith('.com')
838
838
  z.string().includes('/api/')
839
839
  ```
840
840
 
841
- ### Format-Specific Options
841
+ #### Format-Specific Options
842
842
 
843
843
  ```yaml
844
844
  htmlEmail:
@@ -861,23 +861,23 @@ preciseDatetime:
861
861
  x-isoOffset: true
862
862
  ```
863
863
 
864
- | Extension | Maps to | Values |
865
- | ---------------- | ------------------------------- | -------------------------------- |
866
- | `x-emailPattern` | `z.email({ pattern })` | `html5` / `browser` / `unicode` |
867
- | `x-emailRegex` | `z.email({ pattern: /.../ })` | custom regex string |
868
- | `x-uuidVersion` | `z.uuid({ version })` | `v1` / `v4` / `v6` / `v7` / `v8` |
869
- | `x-urlProtocol` | `z.url({ protocol: /.../ })` | regex string |
870
- | `x-urlHostname` | `z.url({ hostname: /.../ })` | regex string |
871
- | `x-urlNormalize` | `z.url({ normalize })` | `true` / `false` |
872
- | `x-isoPrecision` | `z.iso.datetime({ precision })` | fractional second digits |
873
- | `x-isoOffset` | `z.iso.datetime({ offset })` | `true` / `false` |
874
- | `x-isoLocal` | `z.iso.datetime({ local })` | `true` / `false` |
875
- | `x-macDelimiter` | `z.mac({ delimiter })` | `:` / `-` / `.` |
876
- | `x-jwtAlg` | `z.jwt({ alg })` | `HS256` etc. |
877
- | `x-hashAlg` | `z.hash(alg, ...)` | `sha256` etc. |
878
- | `x-hashEnc` | `z.hash(alg, { enc })` | `hex` / `base64` / `base64url` |
879
-
880
- ## Branded Types
864
+ | Extension | Maps to | Values |
865
+ | ---------------- | ------------------------------- | ----------------------------------------------------- |
866
+ | `x-emailPattern` | `z.email({ pattern })` | `html5` / `rfc5322` / `unicode` |
867
+ | `x-emailRegex` | `z.email({ pattern: /.../ })` | custom regex string |
868
+ | `x-uuidVersion` | `z.uuid({ version })` | `v1` / `v2` / `v3` / `v4` / `v5` / `v6` / `v7` / `v8` |
869
+ | `x-urlProtocol` | `z.url({ protocol: /.../ })` | regex string |
870
+ | `x-urlHostname` | `z.url({ hostname: /.../ })` | regex string |
871
+ | `x-urlNormalize` | `z.url({ normalize })` | `true` / `false` |
872
+ | `x-isoPrecision` | `z.iso.datetime({ precision })` | fractional second digits |
873
+ | `x-isoOffset` | `z.iso.datetime({ offset })` | `true` / `false` |
874
+ | `x-isoLocal` | `z.iso.datetime({ local })` | `true` / `false` |
875
+ | `x-macDelimiter` | `z.mac({ delimiter })` | `:` / `-` / `.` |
876
+ | `x-jwtAlg` | `z.jwt({ alg })` | `HS256` etc. |
877
+ | `x-hashAlg` | `z.hash(alg, ...)` | `sha256` etc. |
878
+ | `x-hashEnc` | `z.hash(alg, { enc })` | `hex` / `base64` / `base64url` |
879
+
880
+ ### Branded Types (x-brand)
881
881
 
882
882
  Use the `x-brand` vendor extension to generate [Zod branded types](https://zod.dev/api?id=branded-types), creating nominal types that are structurally identical but semantically distinct:
883
883
 
package/dist/index.js CHANGED
@@ -88,8 +88,8 @@ async function honoTakibi() {
88
88
  const openAPI = openAPIResult.value;
89
89
  const jobs = makeJob(openAPI, config);
90
90
  const results = await Promise.all(jobs.map((job) => job.run(job.output)));
91
- const failure = results.find((result) => !result.ok);
92
- if (failure) return failure;
91
+ const e = results.find((result) => !result.ok);
92
+ if (e) return e;
93
93
  return {
94
94
  ok: true,
95
95
  value: results.map((result) => result.ok ? result.value : "").filter((v) => v !== "").join("\n")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono-takibi",
3
- "version": "0.9.9998",
3
+ "version": "0.9.9999",
4
4
  "description": "Hono Takibi is a code generator from OpenAPI to @hono/zod-openapi",
5
5
  "keywords": [
6
6
  "hono",