@ir-kit/openapi-ts-orpc 0.1.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.
Files changed (84) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +234 -0
  3. package/dist/config.d.ts +7 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +101 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/generators/client.d.ts +7 -0
  8. package/dist/generators/client.d.ts.map +1 -0
  9. package/dist/generators/client.js +113 -0
  10. package/dist/generators/client.js.map +1 -0
  11. package/dist/generators/contract-validator.d.ts +21 -0
  12. package/dist/generators/contract-validator.d.ts.map +1 -0
  13. package/dist/generators/contract-validator.js +250 -0
  14. package/dist/generators/contract-validator.js.map +1 -0
  15. package/dist/generators/contract.d.ts +9 -0
  16. package/dist/generators/contract.d.ts.map +1 -0
  17. package/dist/generators/contract.js +159 -0
  18. package/dist/generators/contract.js.map +1 -0
  19. package/dist/generators/faker.d.ts +15 -0
  20. package/dist/generators/faker.d.ts.map +1 -0
  21. package/dist/generators/faker.js +61 -0
  22. package/dist/generators/faker.js.map +1 -0
  23. package/dist/generators/handlers/ast.d.ts +65 -0
  24. package/dist/generators/handlers/ast.d.ts.map +1 -0
  25. package/dist/generators/handlers/ast.js +262 -0
  26. package/dist/generators/handlers/ast.js.map +1 -0
  27. package/dist/generators/handlers/index.d.ts +37 -0
  28. package/dist/generators/handlers/index.d.ts.map +1 -0
  29. package/dist/generators/handlers/index.js +48 -0
  30. package/dist/generators/handlers/index.js.map +1 -0
  31. package/dist/generators/index.d.ts +14 -0
  32. package/dist/generators/index.d.ts.map +1 -0
  33. package/dist/generators/index.js +13 -0
  34. package/dist/generators/index.js.map +1 -0
  35. package/dist/generators/router.d.ts +7 -0
  36. package/dist/generators/router.d.ts.map +1 -0
  37. package/dist/generators/router.js +21 -0
  38. package/dist/generators/router.js.map +1 -0
  39. package/dist/generators/server.d.ts +7 -0
  40. package/dist/generators/server.d.ts.map +1 -0
  41. package/dist/generators/server.js +22 -0
  42. package/dist/generators/server.js.map +1 -0
  43. package/dist/generators/tanstack.d.ts +7 -0
  44. package/dist/generators/tanstack.d.ts.map +1 -0
  45. package/dist/generators/tanstack.js +27 -0
  46. package/dist/generators/tanstack.js.map +1 -0
  47. package/dist/generators/types.d.ts +74 -0
  48. package/dist/generators/types.d.ts.map +1 -0
  49. package/dist/generators/types.js +2 -0
  50. package/dist/generators/types.js.map +1 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +3 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/plugin.d.ts +7 -0
  56. package/dist/plugin.d.ts.map +1 -0
  57. package/dist/plugin.js +124 -0
  58. package/dist/plugin.js.map +1 -0
  59. package/dist/router-organizer.d.ts +13 -0
  60. package/dist/router-organizer.d.ts.map +1 -0
  61. package/dist/router-organizer.js +42 -0
  62. package/dist/router-organizer.js.map +1 -0
  63. package/dist/schema/extractor.d.ts +16 -0
  64. package/dist/schema/extractor.d.ts.map +1 -0
  65. package/dist/schema/extractor.js +133 -0
  66. package/dist/schema/extractor.js.map +1 -0
  67. package/dist/schema/index.d.ts +2 -0
  68. package/dist/schema/index.d.ts.map +1 -0
  69. package/dist/schema/index.js +2 -0
  70. package/dist/schema/index.js.map +1 -0
  71. package/dist/symbols/external.d.ts +8 -0
  72. package/dist/symbols/external.d.ts.map +1 -0
  73. package/dist/symbols/external.js +67 -0
  74. package/dist/symbols/external.js.map +1 -0
  75. package/dist/types.d.ts +238 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +2 -0
  78. package/dist/types.js.map +1 -0
  79. package/dist/utils.d.ts +4 -0
  80. package/dist/utils.d.ts.map +1 -0
  81. package/dist/utils.js +13 -0
  82. package/dist/utils.js.map +1 -0
  83. package/docs/typia.md +152 -0
  84. package/package.json +101 -0
@@ -0,0 +1,238 @@
1
+ import type { DefinePlugin, NamingConfig, NamingRule, Plugin } from "@hey-api/shared";
2
+ /**
3
+ * Handler generation mode.
4
+ * - 'stub': Throws `ORPCError('NOT_IMPLEMENTED')` (default).
5
+ * - 'faker': Returns faker-generated mock data matching the response schema.
6
+ * - 'proxy': Forwards the request through the generated OpenAPI client.
7
+ */
8
+ export type HandlerMode = "stub" | "faker" | "proxy";
9
+ /**
10
+ * Faker-specific handler options (only apply when `mode: 'faker'`).
11
+ */
12
+ export type FakerHandlerConfig = {
13
+ /**
14
+ * Respect schema constraints (`minimum`/`maximum`, `minLength`/`maxLength`,
15
+ * `minItems`/`maxItems`) when generating values.
16
+ * @default true
17
+ */
18
+ respectConstraints?: boolean;
19
+ /**
20
+ * Map field names to faker method paths. Keys are case/separator-insensitive
21
+ * (`email`, `Email`, `user_email`, `userEmail` all normalize the same).
22
+ * Values must be valid faker methods callable with zero arguments.
23
+ * @example { email: "internet.email", firstName: "person.firstName" }
24
+ */
25
+ fieldNameHints?: import("@ir-kit/openapi-ts-faker/core").FieldNameHints;
26
+ /**
27
+ * Map OpenAPI `format` strings to faker method paths. Merged with the
28
+ * shipped defaults (`uuid`, `email`, `date-time`, `uri`, ...).
29
+ */
30
+ formatMapping?: import("@ir-kit/openapi-ts-faker/core").FormatMapping;
31
+ };
32
+ /**
33
+ * Proxy-specific handler options (only apply when `mode: 'proxy'`).
34
+ */
35
+ export type ProxyHandlerConfig = {
36
+ /**
37
+ * Override the client import used in proxy handlers.
38
+ * By default, a client instance is generated from the OpenAPI client.
39
+ * @example { name: 'apiClient', from: '#/lib/client' }
40
+ */
41
+ clientImport?: {
42
+ /** The exported name to use (e.g. `'apiClient'`). */
43
+ name: string;
44
+ /** The module to import it from (e.g. `'#/lib/client'`). */
45
+ from: string;
46
+ };
47
+ };
48
+ export type ServerConfig = {
49
+ /**
50
+ * Generate server.gen.ts — the `os = implement(router)` helper used to
51
+ * type-safely implement each procedure in your backend.
52
+ * @default false
53
+ */
54
+ implementation?: boolean;
55
+ /**
56
+ * Scaffold handler files under `handlersDir`.
57
+ * - New files are created with `throw new ORPCError('NOT_IMPLEMENTED')` stubs.
58
+ * - Existing files are patched: only procedures absent from the file are appended.
59
+ * Files are never wiped; set to `false` to disable entirely.
60
+ * @default true when `implementation` is true
61
+ */
62
+ handlers?: boolean | {
63
+ /**
64
+ * Directory to write handler files into.
65
+ * Resolved relative to `process.cwd()`.
66
+ * @default 'src/handlers'
67
+ */
68
+ dir?: string;
69
+ /**
70
+ * Path alias prefix used when importing `server.gen` inside handler files.
71
+ * When set (e.g. `'#/'`), the import becomes `#/generated/.../server.gen`.
72
+ * When omitted, a relative path is used instead.
73
+ * @example '#/'
74
+ */
75
+ importAlias?: string;
76
+ /**
77
+ * Override the implementer used in generated handler stubs.
78
+ * By default stubs import `os` from the generated `server.gen` file.
79
+ * Use this to import a wrapper like `publicOs` from your own `procedures` module instead.
80
+ * @example { name: 'publicOs', from: '#/procedures' }
81
+ */
82
+ implementer?: {
83
+ /** The exported name to use (e.g. `'publicOs'`). */
84
+ name: string;
85
+ /** The module to import it from (e.g. `'#/procedures'`). */
86
+ from: string;
87
+ };
88
+ /**
89
+ * Handler body generation mode.
90
+ * - 'stub': Throws `ORPCError('NOT_IMPLEMENTED')` (default).
91
+ * - 'faker': Returns faker-generated mock data matching the response schema.
92
+ * - 'proxy': Forwards the request through the generated OpenAPI client.
93
+ * @default 'stub'
94
+ */
95
+ mode?: HandlerMode;
96
+ /**
97
+ * When `true`, existing handler files are completely rewritten on every
98
+ * codegen run instead of only patching in missing procedures.
99
+ * Useful when switching modes (e.g. from stub to proxy) on an existing codebase.
100
+ * @default false
101
+ */
102
+ override?: boolean;
103
+ /**
104
+ * Faker-specific options. Only used when `mode: 'faker'`.
105
+ */
106
+ faker?: FakerHandlerConfig;
107
+ /**
108
+ * Proxy-specific options. Only used when `mode: 'proxy'`.
109
+ */
110
+ proxy?: ProxyHandlerConfig;
111
+ };
112
+ };
113
+ export type ClientConfig = {
114
+ /**
115
+ * Generate an HTTP client using the native oRPC RPC protocol.
116
+ * @default false
117
+ */
118
+ rpc?: boolean;
119
+ /**
120
+ * Generate a WebSocket client using the native oRPC RPC protocol.
121
+ * @default false
122
+ */
123
+ websocket?: boolean;
124
+ /**
125
+ * Generate a MessagePort client (Web Workers, iframes).
126
+ * @default false
127
+ */
128
+ messageport?: boolean;
129
+ /**
130
+ * Generate an OpenAPI-compatible REST client.
131
+ * Use this when the server exposes standard REST endpoints.
132
+ * @default false
133
+ */
134
+ openapi?: boolean;
135
+ /**
136
+ * Generate TanStack Query utilities (useQuery, useMutation, etc.).
137
+ * Wraps any of the above clients.
138
+ * @default false
139
+ */
140
+ tanstack?: boolean;
141
+ };
142
+ export type ClientType = keyof ClientConfig;
143
+ export type UserConfig = Plugin.Hooks & Plugin.UserExports & {
144
+ name: "@ir-kit/orpc";
145
+ /**
146
+ * Server-side generation options.
147
+ * Controls what backend files are produced.
148
+ * Contracts and router are always generated regardless of this setting.
149
+ * @example { implementation: true }
150
+ */
151
+ server?: ServerConfig;
152
+ /**
153
+ * Client-side generation options.
154
+ * Each key enables a specific client transport or utility.
155
+ * @example { rpc: true, tanstack: true }
156
+ * @example { openapi: true }
157
+ */
158
+ client?: ClientConfig;
159
+ /**
160
+ * Generate JSDoc comments on contract constants from OpenAPI summary/description.
161
+ * @default true
162
+ */
163
+ comments?: boolean;
164
+ /**
165
+ * Router grouping strategy.
166
+ * - 'tags' (default): Group by OpenAPI tags
167
+ * - 'paths': Group by REST path structure
168
+ * - 'flat': No grouping, all procedures at root level
169
+ * @default 'tags'
170
+ */
171
+ group?: "tags" | "paths" | "flat" | "operationId";
172
+ /**
173
+ * Contract input structure mode.
174
+ * - 'compact' (default): Flat merged schema (path + body for mutations, path + query for reads)
175
+ * - 'detailed': Explicit { path, query, headers, body } structure
176
+ * @default 'compact'
177
+ */
178
+ mode?: "detailed" | "compact";
179
+ /**
180
+ * Validator configuration for contract input/output schemas.
181
+ * Accepts a plugin name or an object with separate input/output validators.
182
+ * Set to `false` to disable validation.
183
+ * @default "zod"
184
+ * @example "zod"
185
+ * @example { input: "zod", output: false }
186
+ * @example { input: "typia", output: "typia" }
187
+ */
188
+ validator?: string | false | {
189
+ input?: string | false;
190
+ output?: string | false;
191
+ };
192
+ /**
193
+ * Naming rules for generated code.
194
+ * Each key accepts a casing string (e.g. 'camelCase') or a full NamingConfig.
195
+ */
196
+ naming?: {
197
+ /** Naming for contract constants (e.g. "GetUserContract"). @default { casing: 'PascalCase' } */
198
+ contract?: NamingRule;
199
+ /** Naming for router/procedure keys (e.g. "getUser"). @default { casing: 'camelCase' } */
200
+ operation?: NamingRule;
201
+ };
202
+ };
203
+ export type Config = Plugin.Hooks & Plugin.Exports & {
204
+ name: "@ir-kit/orpc";
205
+ server: Required<Omit<ServerConfig, "handlers">> & {
206
+ handlers: false | {
207
+ dir: string;
208
+ importAlias?: string;
209
+ implementer?: {
210
+ name: string;
211
+ from: string;
212
+ };
213
+ mode: HandlerMode;
214
+ override: boolean;
215
+ faker?: FakerHandlerConfig;
216
+ proxy?: ProxyHandlerConfig;
217
+ };
218
+ };
219
+ client: Required<ClientConfig>;
220
+ comments: boolean;
221
+ group: "tags" | "paths" | "flat" | "operationId";
222
+ mode: "detailed" | "compact";
223
+ naming: {
224
+ contract: NamingConfig;
225
+ operation: NamingConfig;
226
+ };
227
+ validator: {
228
+ input: string | false;
229
+ output: string | false;
230
+ };
231
+ };
232
+ export type ORPCPlugin = DefinePlugin<UserConfig, Config>;
233
+ declare module "@hey-api/openapi-ts" {
234
+ interface PluginConfigMap {
235
+ "@ir-kit/orpc": ORPCPlugin["Types"];
236
+ }
237
+ }
238
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { type NamingConfig } from "@hey-api/shared";
2
+ export declare function contractName(operationId: string, config?: NamingConfig): string;
3
+ export declare function operationName(name: string, config?: NamingConfig): string;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AASjE,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,YAAY,GACpB,MAAM,CAER;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAEzE"}
package/dist/utils.js ADDED
@@ -0,0 +1,13 @@
1
+ import { applyNaming } from "@hey-api/shared";
2
+ const DEFAULT_CONTRACT_NAMING = { casing: "PascalCase" };
3
+ const DEFAULT_OPERATION_NAMING = { casing: "camelCase" };
4
+ function sanitize(name) {
5
+ return name.replace(/[^\w]/g, "");
6
+ }
7
+ export function contractName(operationId, config) {
8
+ return sanitize(applyNaming(operationId, config ?? DEFAULT_CONTRACT_NAMING));
9
+ }
10
+ export function operationName(name, config) {
11
+ return sanitize(applyNaming(name, config ?? DEFAULT_OPERATION_NAMING));
12
+ }
13
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAqB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,uBAAuB,GAAiB,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AACvE,MAAM,wBAAwB,GAAiB,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AAEvE,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,WAAmB,EACnB,MAAqB;IAErB,OAAO,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,IAAI,uBAAuB,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,MAAqB;IAC/D,OAAO,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,IAAI,wBAAwB,CAAC,CAAC,CAAC;AACzE,CAAC"}
package/docs/typia.md ADDED
@@ -0,0 +1,152 @@
1
+ # Typia Integration
2
+
3
+ Instead of Zod, you can use [Typia](https://typia.io/) for runtime validation.
4
+ Typia generates validators at compile-time from TypeScript types — no schema
5
+ duplication.
6
+
7
+ Integration is via the [`@ir-kit/openapi-ts-typia`](https://github.com/ir-kit/ir-kit/tree/main/packages/openapi/plugins/typia)
8
+ companion plugin. This oRPC plugin consumes it through the standard
9
+ validator API, the same way it consumes `zod`, `valibot`, or `arktype`.
10
+
11
+ ## How it works
12
+
13
+ With `validator: '@ir-kit/openapi-ts-typia'`, the typia plugin emits
14
+ one `typia.createValidate<T>()` per operation plus a bulk
15
+ `typia.json.schemas<[...]>()` call whose result is indexed by
16
+ operation. The oRPC plugin references those symbols directly on each
17
+ contract's `.input()` / `.output()` / `.errors()`.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ bun add -d @ir-kit/openapi-ts-typia
23
+ bun add typia @standard-schema/spec
24
+ bun add -d @ryoppippi/unplugin-typia
25
+ ```
26
+
27
+ Typia requires a compiler transform to work. Use `unplugin-typia` for
28
+ your bundler.
29
+
30
+ `@standard-schema/spec` is already a runtime dep of typia; pnpm's strict
31
+ mode hides transitives, so generated code's `import type { StandardSchemaV1 }`
32
+ requires you list it as a direct install.
33
+
34
+ ## Build setup
35
+
36
+ ### tsdown / rolldown
37
+
38
+ ```typescript
39
+ // tsdown.config.ts
40
+ import { defineConfig } from 'tsdown'
41
+ import UnpluginTypia from '@ryoppippi/unplugin-typia/rolldown'
42
+
43
+ export default defineConfig({
44
+ entry: ['src/server.ts'],
45
+ format: 'esm',
46
+ outDir: 'dist',
47
+ plugins: [UnpluginTypia()],
48
+ })
49
+ ```
50
+
51
+ ### Vite
52
+
53
+ ```typescript
54
+ // vite.config.ts
55
+ import UnpluginTypia from '@ryoppippi/unplugin-typia/vite'
56
+
57
+ export default { plugins: [UnpluginTypia()] }
58
+ ```
59
+
60
+ ## openapi-ts config
61
+
62
+ ```typescript
63
+ import { defineConfig } from '@hey-api/openapi-ts';
64
+ import { defineConfig as defineORPCConfig } from '@ir-kit/openapi-ts-orpc';
65
+ import {
66
+ defineConfig as defineTypiaConfig,
67
+ typiaTypeTransformer,
68
+ } from '@ir-kit/openapi-ts-typia';
69
+
70
+ export default defineConfig({
71
+ input: 'openapi.json',
72
+ output: { path: './src/generated' },
73
+ plugins: [
74
+ '@hey-api/typescript',
75
+ {
76
+ name: '@hey-api/transformers',
77
+ typeTransformers: [typiaTypeTransformer],
78
+ },
79
+ defineTypiaConfig(),
80
+ defineORPCConfig({
81
+ validator: '@ir-kit/openapi-ts-typia',
82
+ // ... rest of your config
83
+ }),
84
+ ],
85
+ });
86
+ ```
87
+
88
+ `typiaTypeTransformer` annotates generated TypeScript types with typia
89
+ constraint tags (see [table below](#what-the-transformer-does)) so the
90
+ emitted `createValidate<T>()` calls enforce those constraints.
91
+
92
+ ## OpenAPI spec generation
93
+
94
+ The typia plugin emits a plain JSON Schema twin per operation alongside
95
+ each validator:
96
+
97
+ ```ts
98
+ export const tGetUserData: StandardSchemaV1<...> = createValidate<...>();
99
+ export const tGetUserDataJsonSchema = typiaSchemas.schemas[0];
100
+ ```
101
+
102
+ For oRPC's OpenAPI generator, write a small `ConditionalSchemaConverter`
103
+ that pairs the validator with its twin and registers both with
104
+ `SmartCoercionPlugin`:
105
+
106
+ ```typescript
107
+ import { createTypiaConverter } from './lib/typia-converter'
108
+ import { ZodToJsonSchemaConverter } from '@orpc/zod'
109
+
110
+ new SmartCoercionPlugin({
111
+ schemaConverters: [
112
+ new ZodToJsonSchemaConverter(),
113
+ createTypiaConverter(),
114
+ ],
115
+ })
116
+ ```
117
+
118
+ The converter is a thin wrapper — it detects validators produced by
119
+ typia (via `'~standard'.vendor === 'typia'`) and returns the companion
120
+ JSON Schema symbol by naming convention (`${validatorName}JsonSchema`).
121
+
122
+ ## What the transformer does
123
+
124
+ `typiaTypeTransformer` annotates TypeScript types with Typia constraint
125
+ tags derived from your OpenAPI schema:
126
+
127
+ | OpenAPI constraint | Typia tag |
128
+ |---|---|
129
+ | `minLength` / `maxLength` | `MinLength<N>` / `MaxLength<N>` |
130
+ | `pattern` | `Pattern<"...">` |
131
+ | `format` | `Format<"...">` |
132
+ | `minimum` / `maximum` | `Minimum<N>` / `Maximum<N>` |
133
+ | `exclusiveMinimum` / `exclusiveMaximum` | `ExclusiveMinimum<N>` / `ExclusiveMaximum<N>` |
134
+ | `multipleOf` | `MultipleOf<N>` |
135
+ | `minItems` / `maxItems` | `MinItems<N>` / `MaxItems<N>` |
136
+ | `uniqueItems` | `UniqueItems` |
137
+ | integer `format` (int32, int64, …) | `Type<"int32">` etc. |
138
+
139
+ ## Error responses
140
+
141
+ 4xx/5xx responses get per-status validators. Generated contracts wire
142
+ them automatically:
143
+
144
+ ```ts
145
+ export const GetUserContract = oc.route({...})
146
+ .input(tGetUserData)
147
+ .output(tGetUserResponse)
148
+ .errors({
149
+ 404: { data: tGetUserResponseError404 },
150
+ 500: { data: tGetUserResponseError500 },
151
+ });
152
+ ```
package/package.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "name": "@ir-kit/openapi-ts-orpc",
3
+ "version": "0.1.0",
4
+ "description": "oRPC plugin for @hey-api/openapi-ts - Generate type-safe RPC clients and servers from OpenAPI specs",
5
+ "keywords": [
6
+ "openapi",
7
+ "openapi-ts",
8
+ "orpc",
9
+ "rpc",
10
+ "typescript",
11
+ "codegen",
12
+ "type-safe",
13
+ "plugin"
14
+ ],
15
+ "homepage": "https://github.com/ir-kit/ir-kit/tree/main/packages/openapi/plugins/orpc",
16
+ "bugs": {
17
+ "url": "https://github.com/ir-kit/ir-kit/issues"
18
+ },
19
+ "license": "MIT",
20
+ "author": {
21
+ "name": "Ahmed Rowaihi",
22
+ "email": "ahmedrowaihi@gmail.com"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/ir-kit/ir-kit.git",
27
+ "directory": "packages/openapi/plugins/orpc"
28
+ },
29
+ "type": "module",
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/index.js",
36
+ "require": "./dist/index.js"
37
+ },
38
+ "./package.json": "./package.json"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "docs",
43
+ "README.md",
44
+ "LICENSE.md"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public",
48
+ "provenance": true
49
+ },
50
+ "peerDependencies": {
51
+ "@faker-js/faker": "^10.0.0 || ^9.0.0 || ^8.0.0",
52
+ "@hey-api/codegen-core": ">=0.7.0",
53
+ "@hey-api/openapi-ts": ">=0.95.0",
54
+ "@hey-api/shared": ">=0.3.0",
55
+ "@ir-kit/openapi-ts-faker": ">=0.1.0",
56
+ "@orpc/client": "^1.13",
57
+ "@orpc/contract": "^1.13",
58
+ "@orpc/openapi": "^1.13",
59
+ "@orpc/openapi-client": "^1.13",
60
+ "@orpc/server": "^1.13",
61
+ "@orpc/tanstack-query": "^1.13",
62
+ "@orpc/zod": "^1.13"
63
+ },
64
+ "peerDependenciesMeta": {
65
+ "@ir-kit/openapi-ts-faker": {
66
+ "optional": true
67
+ },
68
+ "@faker-js/faker": {
69
+ "optional": true
70
+ },
71
+ "@orpc/zod": {
72
+ "optional": true
73
+ }
74
+ },
75
+ "devDependencies": {
76
+ "@faker-js/faker": "^10.4.0",
77
+ "@hey-api/codegen-core": "^0.8.1",
78
+ "@hey-api/openapi-ts": "^0.97.0",
79
+ "@hey-api/shared": "^0.4.2",
80
+ "@orpc/client": "^1.14.0",
81
+ "@orpc/contract": "^1.13.14",
82
+ "@orpc/openapi": "^1.13.14",
83
+ "@orpc/openapi-client": "^1.14.0",
84
+ "@orpc/server": "^1.14.0",
85
+ "@orpc/tanstack-query": "^1.14.0",
86
+ "@orpc/zod": "^1.13",
87
+ "@ryoppippi/unplugin-typia": "^2.6.5",
88
+ "@types/node": "^22",
89
+ "ts-patch": "^3.3.0",
90
+ "@ir-kit/openapi-ts-faker": "0.1.0",
91
+ "@ir-kit/tsconfig": "0.0.0"
92
+ },
93
+ "engines": {
94
+ "node": ">=20.19.0"
95
+ },
96
+ "scripts": {
97
+ "build": "tsc",
98
+ "dev": "tsc --watch",
99
+ "typecheck": "tsc --noEmit"
100
+ }
101
+ }