@dloizides/orval-preset 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/index.d.mts +244 -0
- package/dist/index.d.ts +244 -0
- package/dist/index.js +236 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +225 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +78 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@dloizides/orval-preset` are documented here.
|
|
4
|
+
|
|
5
|
+
## [1.0.0] - 2026-06-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Initial extraction from the duplicated Orval setup in `erevna-web` and
|
|
10
|
+
`katalogos-web` (task #196).
|
|
11
|
+
- `defineOrvalConfig({ swaggerDir, outDir, mutatorPath, prettier? })` — builds
|
|
12
|
+
the shared 6-API Orval config (onlineMenu / identity / questioner / content /
|
|
13
|
+
payment / notification) from app-supplied paths.
|
|
14
|
+
- The 6 mutators (`customInstance`, `identityInstance`, `questionerInstance`,
|
|
15
|
+
`contentInstance`, `notificationInstance`, `paymentInstance`) plus the runtime
|
|
16
|
+
registry (`registerMutators` / `getMutator`).
|
|
17
|
+
- `createHttpClient(httpService, opts)` — the axios-bridge factory, with the
|
|
18
|
+
transport injected as a port (`HttpServicePort`) so the package imports no
|
|
19
|
+
product or concrete http layer. Whitespace-normalized vs the per-app copies;
|
|
20
|
+
behaviour-identical.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 dloizides
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @dloizides/orval-preset
|
|
2
|
+
|
|
3
|
+
Shared [Orval](https://orval.dev) generation setup for the dloizides.com SaaS
|
|
4
|
+
frontends (`erevna-web` + `katalogos-web`).
|
|
5
|
+
|
|
6
|
+
Both apps generate React Query hooks from the **same six OpenAPI services**
|
|
7
|
+
(onlineMenu / identity / questioner / content / notification / payment) with a
|
|
8
|
+
byte-for-byte identical config, mutator registry, and axios-bridge http client.
|
|
9
|
+
This package owns that shared shape. Each app keeps only its own
|
|
10
|
+
`swagger/*.json` inputs, output paths, and the generated client dirs.
|
|
11
|
+
|
|
12
|
+
## Surface
|
|
13
|
+
|
|
14
|
+
| Export | When | Purpose |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| `defineOrvalConfig(opts)` | build-time | Builds the 6-API Orval config from app paths. |
|
|
17
|
+
| `customInstance`, `identityInstance`, `questionerInstance`, `contentInstance`, `notificationInstance`, `paymentInstance` | runtime | The mutators referenced by the generated hooks; they delegate to the registry. |
|
|
18
|
+
| `registerMutators` / `getMutator` | runtime | The registry the app populates at startup with the real http clients. |
|
|
19
|
+
| `createHttpClient(httpService, opts)` | runtime | Axios-bridge factory; the app injects its own `httpService` transport (port). |
|
|
20
|
+
|
|
21
|
+
## Build-time: `orval.config.js`
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
const { defineOrvalConfig } = require('@dloizides/orval-preset');
|
|
25
|
+
|
|
26
|
+
module.exports = defineOrvalConfig({
|
|
27
|
+
swaggerDir: './src/server/swagger',
|
|
28
|
+
outDir: './src/server/autoGeneratedHooks',
|
|
29
|
+
mutatorPath: './src/server/mutators',
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`mutatorPath` is the directory the generated hooks import their mutator from.
|
|
34
|
+
Keep a thin local shim at that path that re-exports from this package, so the
|
|
35
|
+
generated import paths stay stable across regenerations:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// src/server/mutators/onlineMenuMutator.ts
|
|
39
|
+
export { customInstance, customInstance as default } from '@dloizides/orval-preset';
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Runtime: registration + http client
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// src/server/httpClient.ts
|
|
46
|
+
import { createHttpClient } from '@dloizides/orval-preset';
|
|
47
|
+
import * as httpService from '../lib/httpService';
|
|
48
|
+
import { BFF_API_BASE } from './bffRoutes';
|
|
49
|
+
|
|
50
|
+
export const customInstance = createHttpClient(httpService, {
|
|
51
|
+
baseURL: BFF_API_BASE.menus,
|
|
52
|
+
withCredentials: true,
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// app entry point
|
|
58
|
+
import { registerMutators } from '@dloizides/orval-preset';
|
|
59
|
+
import { customInstance } from './server/httpClient';
|
|
60
|
+
// …the other five httpClient* files…
|
|
61
|
+
|
|
62
|
+
registerMutators({ customInstance /* , … */ });
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The `httpService` port must expose `get` / `post` / `postForm` / `put` /
|
|
66
|
+
`patch` / `deleteMethod` (the surface the apps' axios bridge already provides).
|
|
67
|
+
|
|
68
|
+
## Why a port, not a baked-in axios
|
|
69
|
+
|
|
70
|
+
`createHttpClient` takes the transport as an argument so the package never
|
|
71
|
+
imports a product, a realm, or a concrete axios instance. The app's UI axios
|
|
72
|
+
(`@dloizides/bff-web-client`) and this mutator transport remain separate
|
|
73
|
+
instances by design; unifying them is a future optimization.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orval config factory shared by erevna-web and katalogos-web.
|
|
3
|
+
*
|
|
4
|
+
* Both apps generate React Query hooks from the SAME six OpenAPI services
|
|
5
|
+
* (onlineMenu / identity / questioner / content / notification / payment) with
|
|
6
|
+
* an identical `tags-split` + per-service-mutator setup. This factory owns that
|
|
7
|
+
* shared shape; each app supplies only its own paths via {@link DefineOrvalConfigOptions}.
|
|
8
|
+
*
|
|
9
|
+
* The return value is a plain Orval config object (the same thing
|
|
10
|
+
* `defineConfig(...)` returns), so the app's `orval.config.js` becomes:
|
|
11
|
+
*
|
|
12
|
+
* ```js
|
|
13
|
+
* const { defineOrvalConfig } = require('@dloizides/orval-preset');
|
|
14
|
+
* module.exports = defineOrvalConfig({
|
|
15
|
+
* swaggerDir: './src/server/swagger',
|
|
16
|
+
* outDir: './src/server/autoGeneratedHooks',
|
|
17
|
+
* mutatorPath: './src/server/mutators',
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
interface DefineOrvalConfigOptions {
|
|
22
|
+
/** Directory holding the per-service swagger JSON inputs (app-owned). */
|
|
23
|
+
swaggerDir: string;
|
|
24
|
+
/** Directory the generated client dirs are written to (app-owned, gitignored). */
|
|
25
|
+
outDir: string;
|
|
26
|
+
/** Directory holding the mutator files orval points generated hooks at (app-owned shims). */
|
|
27
|
+
mutatorPath: string;
|
|
28
|
+
/** Optional prettier override (defaults to true, matching the legacy config). */
|
|
29
|
+
prettier?: boolean;
|
|
30
|
+
}
|
|
31
|
+
interface OrvalMutatorOverride {
|
|
32
|
+
path: string;
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
interface OrvalHookCommand {
|
|
36
|
+
command: string;
|
|
37
|
+
}
|
|
38
|
+
interface OrvalApiEntry {
|
|
39
|
+
input: {
|
|
40
|
+
target: string;
|
|
41
|
+
validation: boolean;
|
|
42
|
+
};
|
|
43
|
+
output: {
|
|
44
|
+
target: string;
|
|
45
|
+
client: 'react-query';
|
|
46
|
+
mode: 'tags-split';
|
|
47
|
+
clean: boolean;
|
|
48
|
+
prettier: boolean;
|
|
49
|
+
schemas: string;
|
|
50
|
+
override: {
|
|
51
|
+
mutator: OrvalMutatorOverride;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
hooks: {
|
|
55
|
+
afterAllFilesWrite: OrvalHookCommand[];
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
type OrvalConfig = Record<string, OrvalApiEntry>;
|
|
59
|
+
/**
|
|
60
|
+
* Builds the shared 6-API Orval config object from app-supplied paths.
|
|
61
|
+
*/
|
|
62
|
+
declare function defineOrvalConfig(options: DefineOrvalConfigOptions): OrvalConfig;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Runtime registry for HTTP client implementations.
|
|
66
|
+
*
|
|
67
|
+
* This registry allows the app to register the real http client implementations
|
|
68
|
+
* at startup, which the generated Orval hooks will then use at runtime.
|
|
69
|
+
*
|
|
70
|
+
* Usage in app entry point (e.g., App.tsx):
|
|
71
|
+
* ```typescript
|
|
72
|
+
* import { registerMutators } from '@dloizides/orval-preset';
|
|
73
|
+
* import { customInstance } from './server/httpClient';
|
|
74
|
+
* import { identityInstance } from './server/httpClientIdentity';
|
|
75
|
+
* import { questionerInstance } from './server/httpClientQuestioner';
|
|
76
|
+
* import { contentInstance } from './server/httpClientContent';
|
|
77
|
+
* import { notificationInstance } from './server/httpClientNotification';
|
|
78
|
+
* import { paymentInstance } from './server/httpClientPayment';
|
|
79
|
+
*
|
|
80
|
+
* registerMutators({
|
|
81
|
+
* customInstance,
|
|
82
|
+
* identityInstance,
|
|
83
|
+
* questionerInstance,
|
|
84
|
+
* contentInstance,
|
|
85
|
+
* notificationInstance,
|
|
86
|
+
* paymentInstance,
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
interface OrvalRequest<Req = unknown, Qry = unknown> {
|
|
91
|
+
url: string;
|
|
92
|
+
method?: string;
|
|
93
|
+
data?: Req | FormData;
|
|
94
|
+
params?: Qry;
|
|
95
|
+
signal?: AbortSignal;
|
|
96
|
+
headers?: Record<string, string>;
|
|
97
|
+
}
|
|
98
|
+
type OrvalMutator = <TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>) => Promise<TResp>;
|
|
99
|
+
interface MutatorRegistry {
|
|
100
|
+
customInstance?: OrvalMutator;
|
|
101
|
+
identityInstance?: OrvalMutator;
|
|
102
|
+
questionerInstance?: OrvalMutator;
|
|
103
|
+
contentInstance?: OrvalMutator;
|
|
104
|
+
notificationInstance?: OrvalMutator;
|
|
105
|
+
paymentInstance?: OrvalMutator;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Register the real HTTP client implementations.
|
|
109
|
+
* Call this once at app startup before any API hooks are used.
|
|
110
|
+
*/
|
|
111
|
+
declare function registerMutators(mutators: Partial<MutatorRegistry>): void;
|
|
112
|
+
/**
|
|
113
|
+
* Get a registered mutator by name.
|
|
114
|
+
* @throws Error if the mutator has not been registered.
|
|
115
|
+
*/
|
|
116
|
+
declare function getMutator(name: keyof MutatorRegistry): OrvalMutator;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* OnlineMenu API mutator for Orval code generation.
|
|
120
|
+
*
|
|
121
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
122
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
123
|
+
* the real HTTP client from the registry.
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* HTTP client for OnlineMenu API.
|
|
128
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
129
|
+
*/
|
|
130
|
+
declare function customInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Identity API mutator for Orval code generation.
|
|
134
|
+
*
|
|
135
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
136
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
137
|
+
* the real HTTP client from the registry.
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* HTTP client for Identity API.
|
|
142
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
143
|
+
*/
|
|
144
|
+
declare function identityInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Questioner API mutator for Orval code generation.
|
|
148
|
+
*
|
|
149
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
150
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
151
|
+
* the real HTTP client from the registry.
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* HTTP client for Questioner API.
|
|
156
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
157
|
+
*/
|
|
158
|
+
declare function questionerInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Content API mutator for Orval code generation.
|
|
162
|
+
*
|
|
163
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
164
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
165
|
+
* the real HTTP client from the registry.
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* HTTP client for Content API.
|
|
170
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
171
|
+
*/
|
|
172
|
+
declare function contentInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Notification API mutator for Orval code generation.
|
|
176
|
+
*
|
|
177
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
178
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
179
|
+
* the real HTTP client from the registry.
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* HTTP client for Notification API.
|
|
184
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
185
|
+
*/
|
|
186
|
+
declare function notificationInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Payment API mutator for Orval code generation.
|
|
190
|
+
*
|
|
191
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
192
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
193
|
+
* the real HTTP client from the registry.
|
|
194
|
+
*/
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* HTTP client for Payment API.
|
|
198
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
199
|
+
*/
|
|
200
|
+
declare function paymentInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Request options passed to the injected httpService methods.
|
|
204
|
+
*
|
|
205
|
+
* This is the contract the consuming app's `httpService` must accept. The
|
|
206
|
+
* package never imports a concrete axios/http layer — the app supplies it as
|
|
207
|
+
* a port (see `HttpServicePort`), keeping this factory product-agnostic.
|
|
208
|
+
*/
|
|
209
|
+
interface HttpRequestOptions {
|
|
210
|
+
withCredentials?: boolean;
|
|
211
|
+
baseURL?: string;
|
|
212
|
+
signal?: AbortSignal;
|
|
213
|
+
headers?: Record<string, string>;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* The HTTP transport port the consuming app injects. Mirrors the method
|
|
217
|
+
* surface the app's `httpService` already exposes (axios bridge).
|
|
218
|
+
*
|
|
219
|
+
* The package always supplies the base {@link HttpRequestOptions} shape, so an
|
|
220
|
+
* app whose `httpService` accepts a *wider* options type (extra optional fields)
|
|
221
|
+
* can be adapted to this port without type assertions.
|
|
222
|
+
*/
|
|
223
|
+
interface HttpServicePort {
|
|
224
|
+
get<TQry, TResp>(endpoint: string, params: TQry, opts: HttpRequestOptions): Promise<TResp>;
|
|
225
|
+
post<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
226
|
+
postForm<TResp>(endpoint: string, data: FormData, opts: HttpRequestOptions): Promise<TResp>;
|
|
227
|
+
put<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
228
|
+
patch<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
229
|
+
deleteMethod<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
230
|
+
}
|
|
231
|
+
interface HttpClientOptions {
|
|
232
|
+
baseURL?: string;
|
|
233
|
+
withCredentials?: boolean;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Creates an HTTP client instance for Orval-generated hooks.
|
|
237
|
+
*
|
|
238
|
+
* @param http - The app's httpService transport (injected port).
|
|
239
|
+
* @param clientOptions - Configuration options for the client (baseURL, auth settings).
|
|
240
|
+
* @returns An async function that handles HTTP requests.
|
|
241
|
+
*/
|
|
242
|
+
declare function createHttpClient(http: HttpServicePort, clientOptions?: HttpClientOptions): OrvalMutator;
|
|
243
|
+
|
|
244
|
+
export { type DefineOrvalConfigOptions, type HttpRequestOptions, type HttpServicePort, type OrvalConfig, type OrvalMutator, type OrvalRequest, contentInstance, createHttpClient, customInstance, defineOrvalConfig, getMutator, identityInstance, notificationInstance, paymentInstance, questionerInstance, registerMutators };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orval config factory shared by erevna-web and katalogos-web.
|
|
3
|
+
*
|
|
4
|
+
* Both apps generate React Query hooks from the SAME six OpenAPI services
|
|
5
|
+
* (onlineMenu / identity / questioner / content / notification / payment) with
|
|
6
|
+
* an identical `tags-split` + per-service-mutator setup. This factory owns that
|
|
7
|
+
* shared shape; each app supplies only its own paths via {@link DefineOrvalConfigOptions}.
|
|
8
|
+
*
|
|
9
|
+
* The return value is a plain Orval config object (the same thing
|
|
10
|
+
* `defineConfig(...)` returns), so the app's `orval.config.js` becomes:
|
|
11
|
+
*
|
|
12
|
+
* ```js
|
|
13
|
+
* const { defineOrvalConfig } = require('@dloizides/orval-preset');
|
|
14
|
+
* module.exports = defineOrvalConfig({
|
|
15
|
+
* swaggerDir: './src/server/swagger',
|
|
16
|
+
* outDir: './src/server/autoGeneratedHooks',
|
|
17
|
+
* mutatorPath: './src/server/mutators',
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
interface DefineOrvalConfigOptions {
|
|
22
|
+
/** Directory holding the per-service swagger JSON inputs (app-owned). */
|
|
23
|
+
swaggerDir: string;
|
|
24
|
+
/** Directory the generated client dirs are written to (app-owned, gitignored). */
|
|
25
|
+
outDir: string;
|
|
26
|
+
/** Directory holding the mutator files orval points generated hooks at (app-owned shims). */
|
|
27
|
+
mutatorPath: string;
|
|
28
|
+
/** Optional prettier override (defaults to true, matching the legacy config). */
|
|
29
|
+
prettier?: boolean;
|
|
30
|
+
}
|
|
31
|
+
interface OrvalMutatorOverride {
|
|
32
|
+
path: string;
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
interface OrvalHookCommand {
|
|
36
|
+
command: string;
|
|
37
|
+
}
|
|
38
|
+
interface OrvalApiEntry {
|
|
39
|
+
input: {
|
|
40
|
+
target: string;
|
|
41
|
+
validation: boolean;
|
|
42
|
+
};
|
|
43
|
+
output: {
|
|
44
|
+
target: string;
|
|
45
|
+
client: 'react-query';
|
|
46
|
+
mode: 'tags-split';
|
|
47
|
+
clean: boolean;
|
|
48
|
+
prettier: boolean;
|
|
49
|
+
schemas: string;
|
|
50
|
+
override: {
|
|
51
|
+
mutator: OrvalMutatorOverride;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
hooks: {
|
|
55
|
+
afterAllFilesWrite: OrvalHookCommand[];
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
type OrvalConfig = Record<string, OrvalApiEntry>;
|
|
59
|
+
/**
|
|
60
|
+
* Builds the shared 6-API Orval config object from app-supplied paths.
|
|
61
|
+
*/
|
|
62
|
+
declare function defineOrvalConfig(options: DefineOrvalConfigOptions): OrvalConfig;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Runtime registry for HTTP client implementations.
|
|
66
|
+
*
|
|
67
|
+
* This registry allows the app to register the real http client implementations
|
|
68
|
+
* at startup, which the generated Orval hooks will then use at runtime.
|
|
69
|
+
*
|
|
70
|
+
* Usage in app entry point (e.g., App.tsx):
|
|
71
|
+
* ```typescript
|
|
72
|
+
* import { registerMutators } from '@dloizides/orval-preset';
|
|
73
|
+
* import { customInstance } from './server/httpClient';
|
|
74
|
+
* import { identityInstance } from './server/httpClientIdentity';
|
|
75
|
+
* import { questionerInstance } from './server/httpClientQuestioner';
|
|
76
|
+
* import { contentInstance } from './server/httpClientContent';
|
|
77
|
+
* import { notificationInstance } from './server/httpClientNotification';
|
|
78
|
+
* import { paymentInstance } from './server/httpClientPayment';
|
|
79
|
+
*
|
|
80
|
+
* registerMutators({
|
|
81
|
+
* customInstance,
|
|
82
|
+
* identityInstance,
|
|
83
|
+
* questionerInstance,
|
|
84
|
+
* contentInstance,
|
|
85
|
+
* notificationInstance,
|
|
86
|
+
* paymentInstance,
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
interface OrvalRequest<Req = unknown, Qry = unknown> {
|
|
91
|
+
url: string;
|
|
92
|
+
method?: string;
|
|
93
|
+
data?: Req | FormData;
|
|
94
|
+
params?: Qry;
|
|
95
|
+
signal?: AbortSignal;
|
|
96
|
+
headers?: Record<string, string>;
|
|
97
|
+
}
|
|
98
|
+
type OrvalMutator = <TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>) => Promise<TResp>;
|
|
99
|
+
interface MutatorRegistry {
|
|
100
|
+
customInstance?: OrvalMutator;
|
|
101
|
+
identityInstance?: OrvalMutator;
|
|
102
|
+
questionerInstance?: OrvalMutator;
|
|
103
|
+
contentInstance?: OrvalMutator;
|
|
104
|
+
notificationInstance?: OrvalMutator;
|
|
105
|
+
paymentInstance?: OrvalMutator;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Register the real HTTP client implementations.
|
|
109
|
+
* Call this once at app startup before any API hooks are used.
|
|
110
|
+
*/
|
|
111
|
+
declare function registerMutators(mutators: Partial<MutatorRegistry>): void;
|
|
112
|
+
/**
|
|
113
|
+
* Get a registered mutator by name.
|
|
114
|
+
* @throws Error if the mutator has not been registered.
|
|
115
|
+
*/
|
|
116
|
+
declare function getMutator(name: keyof MutatorRegistry): OrvalMutator;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* OnlineMenu API mutator for Orval code generation.
|
|
120
|
+
*
|
|
121
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
122
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
123
|
+
* the real HTTP client from the registry.
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* HTTP client for OnlineMenu API.
|
|
128
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
129
|
+
*/
|
|
130
|
+
declare function customInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Identity API mutator for Orval code generation.
|
|
134
|
+
*
|
|
135
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
136
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
137
|
+
* the real HTTP client from the registry.
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* HTTP client for Identity API.
|
|
142
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
143
|
+
*/
|
|
144
|
+
declare function identityInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Questioner API mutator for Orval code generation.
|
|
148
|
+
*
|
|
149
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
150
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
151
|
+
* the real HTTP client from the registry.
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* HTTP client for Questioner API.
|
|
156
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
157
|
+
*/
|
|
158
|
+
declare function questionerInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Content API mutator for Orval code generation.
|
|
162
|
+
*
|
|
163
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
164
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
165
|
+
* the real HTTP client from the registry.
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* HTTP client for Content API.
|
|
170
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
171
|
+
*/
|
|
172
|
+
declare function contentInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Notification API mutator for Orval code generation.
|
|
176
|
+
*
|
|
177
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
178
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
179
|
+
* the real HTTP client from the registry.
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* HTTP client for Notification API.
|
|
184
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
185
|
+
*/
|
|
186
|
+
declare function notificationInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Payment API mutator for Orval code generation.
|
|
190
|
+
*
|
|
191
|
+
* This file has no Expo dependencies at the module level, allowing Orval
|
|
192
|
+
* to load it in Node.js during code generation. At runtime, it retrieves
|
|
193
|
+
* the real HTTP client from the registry.
|
|
194
|
+
*/
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* HTTP client for Payment API.
|
|
198
|
+
* At runtime, delegates to the real implementation registered via registerMutators().
|
|
199
|
+
*/
|
|
200
|
+
declare function paymentInstance<TResp = unknown, TReq = unknown, TQry = unknown>(opts: OrvalRequest<TReq, TQry>): Promise<TResp>;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Request options passed to the injected httpService methods.
|
|
204
|
+
*
|
|
205
|
+
* This is the contract the consuming app's `httpService` must accept. The
|
|
206
|
+
* package never imports a concrete axios/http layer — the app supplies it as
|
|
207
|
+
* a port (see `HttpServicePort`), keeping this factory product-agnostic.
|
|
208
|
+
*/
|
|
209
|
+
interface HttpRequestOptions {
|
|
210
|
+
withCredentials?: boolean;
|
|
211
|
+
baseURL?: string;
|
|
212
|
+
signal?: AbortSignal;
|
|
213
|
+
headers?: Record<string, string>;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* The HTTP transport port the consuming app injects. Mirrors the method
|
|
217
|
+
* surface the app's `httpService` already exposes (axios bridge).
|
|
218
|
+
*
|
|
219
|
+
* The package always supplies the base {@link HttpRequestOptions} shape, so an
|
|
220
|
+
* app whose `httpService` accepts a *wider* options type (extra optional fields)
|
|
221
|
+
* can be adapted to this port without type assertions.
|
|
222
|
+
*/
|
|
223
|
+
interface HttpServicePort {
|
|
224
|
+
get<TQry, TResp>(endpoint: string, params: TQry, opts: HttpRequestOptions): Promise<TResp>;
|
|
225
|
+
post<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
226
|
+
postForm<TResp>(endpoint: string, data: FormData, opts: HttpRequestOptions): Promise<TResp>;
|
|
227
|
+
put<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
228
|
+
patch<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
229
|
+
deleteMethod<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;
|
|
230
|
+
}
|
|
231
|
+
interface HttpClientOptions {
|
|
232
|
+
baseURL?: string;
|
|
233
|
+
withCredentials?: boolean;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Creates an HTTP client instance for Orval-generated hooks.
|
|
237
|
+
*
|
|
238
|
+
* @param http - The app's httpService transport (injected port).
|
|
239
|
+
* @param clientOptions - Configuration options for the client (baseURL, auth settings).
|
|
240
|
+
* @returns An async function that handles HTTP requests.
|
|
241
|
+
*/
|
|
242
|
+
declare function createHttpClient(http: HttpServicePort, clientOptions?: HttpClientOptions): OrvalMutator;
|
|
243
|
+
|
|
244
|
+
export { type DefineOrvalConfigOptions, type HttpRequestOptions, type HttpServicePort, type OrvalConfig, type OrvalMutator, type OrvalRequest, contentInstance, createHttpClient, customInstance, defineOrvalConfig, getMutator, identityInstance, notificationInstance, paymentInstance, questionerInstance, registerMutators };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/defineOrvalConfig.ts
|
|
4
|
+
var API_DESCRIPTORS = [
|
|
5
|
+
{
|
|
6
|
+
key: "onlineMenuApi",
|
|
7
|
+
slug: "onlinemenu",
|
|
8
|
+
mutatorFile: "onlineMenuMutator",
|
|
9
|
+
mutatorName: "customInstance",
|
|
10
|
+
label: "OnlineMenuSaaS"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
key: "identityApi",
|
|
14
|
+
slug: "identity",
|
|
15
|
+
mutatorFile: "identityMutator",
|
|
16
|
+
mutatorName: "identityInstance",
|
|
17
|
+
label: "IdentityService"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
key: "questionerApi",
|
|
21
|
+
slug: "questioner",
|
|
22
|
+
mutatorFile: "questionerMutator",
|
|
23
|
+
mutatorName: "questionerInstance",
|
|
24
|
+
label: "QuestionerService"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
key: "contentApi",
|
|
28
|
+
slug: "content",
|
|
29
|
+
mutatorFile: "contentMutator",
|
|
30
|
+
mutatorName: "contentInstance",
|
|
31
|
+
label: "ContentService"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
key: "paymentApi",
|
|
35
|
+
slug: "payment",
|
|
36
|
+
mutatorFile: "paymentMutator",
|
|
37
|
+
mutatorName: "paymentInstance",
|
|
38
|
+
label: "PaymentService"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "notificationApi",
|
|
42
|
+
slug: "notification",
|
|
43
|
+
mutatorFile: "notificationMutator",
|
|
44
|
+
mutatorName: "notificationInstance",
|
|
45
|
+
label: "NotificationService"
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
function stripTrailingSlashes(value) {
|
|
49
|
+
let end = value.length;
|
|
50
|
+
while (end > 0 && value[end - 1] === "/") {
|
|
51
|
+
end -= 1;
|
|
52
|
+
}
|
|
53
|
+
return value.slice(0, end);
|
|
54
|
+
}
|
|
55
|
+
function joinPath(base, segment) {
|
|
56
|
+
return `${stripTrailingSlashes(base)}/${segment}`;
|
|
57
|
+
}
|
|
58
|
+
function buildApiEntry(descriptor, options) {
|
|
59
|
+
const generatedDir = joinPath(options.outDir, descriptor.slug);
|
|
60
|
+
return {
|
|
61
|
+
input: {
|
|
62
|
+
target: joinPath(options.swaggerDir, `${descriptor.slug}.json`),
|
|
63
|
+
validation: false
|
|
64
|
+
},
|
|
65
|
+
output: {
|
|
66
|
+
target: joinPath(generatedDir, "index.ts"),
|
|
67
|
+
client: "react-query",
|
|
68
|
+
mode: "tags-split",
|
|
69
|
+
clean: true,
|
|
70
|
+
prettier: options.prettier,
|
|
71
|
+
schemas: joinPath(generatedDir, "models"),
|
|
72
|
+
override: {
|
|
73
|
+
mutator: {
|
|
74
|
+
path: joinPath(options.mutatorPath, `${descriptor.mutatorFile}.ts`),
|
|
75
|
+
name: descriptor.mutatorName
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
hooks: {
|
|
80
|
+
afterAllFilesWrite: [
|
|
81
|
+
{ command: `npx prettier --write ${generatedDir}` },
|
|
82
|
+
{ command: `echo "\u2705 Orval: ${descriptor.label} hooks generated"` }
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function defineOrvalConfig(options) {
|
|
88
|
+
const resolved = {
|
|
89
|
+
swaggerDir: options.swaggerDir,
|
|
90
|
+
outDir: options.outDir,
|
|
91
|
+
mutatorPath: options.mutatorPath,
|
|
92
|
+
prettier: options.prettier ?? true
|
|
93
|
+
};
|
|
94
|
+
const config = {};
|
|
95
|
+
for (const descriptor of API_DESCRIPTORS) {
|
|
96
|
+
config[descriptor.key] = buildApiEntry(descriptor, resolved);
|
|
97
|
+
}
|
|
98
|
+
return config;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/mutators/registry.ts
|
|
102
|
+
var registry = {};
|
|
103
|
+
function registerMutators(mutators) {
|
|
104
|
+
if (mutators.customInstance) {
|
|
105
|
+
registry.customInstance = mutators.customInstance;
|
|
106
|
+
}
|
|
107
|
+
if (mutators.identityInstance) {
|
|
108
|
+
registry.identityInstance = mutators.identityInstance;
|
|
109
|
+
}
|
|
110
|
+
if (mutators.questionerInstance) {
|
|
111
|
+
registry.questionerInstance = mutators.questionerInstance;
|
|
112
|
+
}
|
|
113
|
+
if (mutators.contentInstance) {
|
|
114
|
+
registry.contentInstance = mutators.contentInstance;
|
|
115
|
+
}
|
|
116
|
+
if (mutators.notificationInstance) {
|
|
117
|
+
registry.notificationInstance = mutators.notificationInstance;
|
|
118
|
+
}
|
|
119
|
+
if (mutators.paymentInstance) {
|
|
120
|
+
registry.paymentInstance = mutators.paymentInstance;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function getMutator(name) {
|
|
124
|
+
const mutator = registry[name];
|
|
125
|
+
if (!mutator) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
`HTTP client '${name}' not registered. Call registerMutators() at app startup.`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return mutator;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/mutators/onlineMenuMutator.ts
|
|
134
|
+
async function customInstance(opts) {
|
|
135
|
+
const realMutator = getMutator("customInstance");
|
|
136
|
+
return realMutator(opts);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/mutators/identityMutator.ts
|
|
140
|
+
async function identityInstance(opts) {
|
|
141
|
+
const realMutator = getMutator("identityInstance");
|
|
142
|
+
return realMutator(opts);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/mutators/questionerMutator.ts
|
|
146
|
+
async function questionerInstance(opts) {
|
|
147
|
+
const realMutator = getMutator("questionerInstance");
|
|
148
|
+
return realMutator(opts);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/mutators/contentMutator.ts
|
|
152
|
+
async function contentInstance(opts) {
|
|
153
|
+
const realMutator = getMutator("contentInstance");
|
|
154
|
+
return realMutator(opts);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/mutators/notificationMutator.ts
|
|
158
|
+
async function notificationInstance(opts) {
|
|
159
|
+
const realMutator = getMutator("notificationInstance");
|
|
160
|
+
return realMutator(opts);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/mutators/paymentMutator.ts
|
|
164
|
+
async function paymentInstance(opts) {
|
|
165
|
+
const realMutator = getMutator("paymentInstance");
|
|
166
|
+
return realMutator(opts);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/createHttpClient.ts
|
|
170
|
+
function createRequestOptions(opts, clientOptions) {
|
|
171
|
+
return {
|
|
172
|
+
withCredentials: clientOptions.withCredentials ?? true,
|
|
173
|
+
baseURL: clientOptions.baseURL,
|
|
174
|
+
signal: opts.signal,
|
|
175
|
+
headers: opts.headers
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
async function handleGet(http, endpoint, params, reqOpts) {
|
|
179
|
+
return http.get(endpoint, params, reqOpts);
|
|
180
|
+
}
|
|
181
|
+
async function handlePost(http, endpoint, data, reqOpts) {
|
|
182
|
+
if (typeof FormData !== "undefined" && data instanceof FormData) {
|
|
183
|
+
return http.postForm(endpoint, data, reqOpts);
|
|
184
|
+
}
|
|
185
|
+
const payload = data;
|
|
186
|
+
return http.post(endpoint, payload, reqOpts);
|
|
187
|
+
}
|
|
188
|
+
async function handlePut(http, endpoint, data, reqOpts) {
|
|
189
|
+
return http.put(endpoint, data, reqOpts);
|
|
190
|
+
}
|
|
191
|
+
async function handlePatch(http, endpoint, data, reqOpts) {
|
|
192
|
+
return http.patch(endpoint, data, reqOpts);
|
|
193
|
+
}
|
|
194
|
+
async function handleDelete(http, endpoint, data, reqOpts) {
|
|
195
|
+
return http.deleteMethod(endpoint, data, reqOpts);
|
|
196
|
+
}
|
|
197
|
+
function createHttpClient(http, clientOptions = {}) {
|
|
198
|
+
return async (opts) => {
|
|
199
|
+
const { url, method = "GET", data, params } = opts;
|
|
200
|
+
const m = method.toUpperCase();
|
|
201
|
+
const endpoint = url;
|
|
202
|
+
const reqOpts = createRequestOptions(opts, clientOptions);
|
|
203
|
+
if (m === "GET") {
|
|
204
|
+
return handleGet(http, endpoint, params, reqOpts);
|
|
205
|
+
}
|
|
206
|
+
if (m === "POST") {
|
|
207
|
+
return handlePost(http, endpoint, data, reqOpts);
|
|
208
|
+
}
|
|
209
|
+
if (m === "PUT") {
|
|
210
|
+
const putData = data instanceof FormData ? void 0 : data;
|
|
211
|
+
return handlePut(http, endpoint, putData, reqOpts);
|
|
212
|
+
}
|
|
213
|
+
if (m === "PATCH") {
|
|
214
|
+
const patchData = data instanceof FormData ? void 0 : data;
|
|
215
|
+
return handlePatch(http, endpoint, patchData, reqOpts);
|
|
216
|
+
}
|
|
217
|
+
if (m === "DELETE") {
|
|
218
|
+
const deleteData = data instanceof FormData ? void 0 : data;
|
|
219
|
+
return handleDelete(http, endpoint, deleteData, reqOpts);
|
|
220
|
+
}
|
|
221
|
+
return handlePost(http, endpoint, data, reqOpts);
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
exports.contentInstance = contentInstance;
|
|
226
|
+
exports.createHttpClient = createHttpClient;
|
|
227
|
+
exports.customInstance = customInstance;
|
|
228
|
+
exports.defineOrvalConfig = defineOrvalConfig;
|
|
229
|
+
exports.getMutator = getMutator;
|
|
230
|
+
exports.identityInstance = identityInstance;
|
|
231
|
+
exports.notificationInstance = notificationInstance;
|
|
232
|
+
exports.paymentInstance = paymentInstance;
|
|
233
|
+
exports.questionerInstance = questionerInstance;
|
|
234
|
+
exports.registerMutators = registerMutators;
|
|
235
|
+
//# sourceMappingURL=index.js.map
|
|
236
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/defineOrvalConfig.ts","../src/mutators/registry.ts","../src/mutators/onlineMenuMutator.ts","../src/mutators/identityMutator.ts","../src/mutators/questionerMutator.ts","../src/mutators/contentMutator.ts","../src/mutators/notificationMutator.ts","../src/mutators/paymentMutator.ts","../src/createHttpClient.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Orval config factory shared by erevna-web and katalogos-web.\n *\n * Both apps generate React Query hooks from the SAME six OpenAPI services\n * (onlineMenu / identity / questioner / content / notification / payment) with\n * an identical `tags-split` + per-service-mutator setup. This factory owns that\n * shared shape; each app supplies only its own paths via {@link DefineOrvalConfigOptions}.\n *\n * The return value is a plain Orval config object (the same thing\n * `defineConfig(...)` returns), so the app's `orval.config.js` becomes:\n *\n * ```js\n * const { defineOrvalConfig } = require('@dloizides/orval-preset');\n * module.exports = defineOrvalConfig({\n * swaggerDir: './src/server/swagger',\n * outDir: './src/server/autoGeneratedHooks',\n * mutatorPath: './src/server/mutators',\n * });\n * ```\n */\n\nexport interface DefineOrvalConfigOptions {\n /** Directory holding the per-service swagger JSON inputs (app-owned). */\n swaggerDir: string;\n /** Directory the generated client dirs are written to (app-owned, gitignored). */\n outDir: string;\n /** Directory holding the mutator files orval points generated hooks at (app-owned shims). */\n mutatorPath: string;\n /** Optional prettier override (defaults to true, matching the legacy config). */\n prettier?: boolean;\n}\n\ninterface OrvalMutatorOverride {\n path: string;\n name: string;\n}\n\ninterface OrvalHookCommand {\n command: string;\n}\n\ninterface OrvalApiEntry {\n input: {\n target: string;\n validation: boolean;\n };\n output: {\n target: string;\n client: 'react-query';\n mode: 'tags-split';\n clean: boolean;\n prettier: boolean;\n schemas: string;\n override: {\n mutator: OrvalMutatorOverride;\n };\n };\n hooks: {\n afterAllFilesWrite: OrvalHookCommand[];\n };\n}\n\nexport type OrvalConfig = Record<string, OrvalApiEntry>;\n\ninterface ApiDescriptor {\n /** Orval config key (e.g. `onlineMenuApi`). */\n key: string;\n /** Swagger file basename without extension + the generated dir name (e.g. `onlinemenu`). */\n slug: string;\n /** Mutator file basename without extension (e.g. `onlineMenuMutator`). */\n mutatorFile: string;\n /** Exported mutator function name (e.g. `customInstance`). */\n mutatorName: string;\n /** Human label used in the generated success echo. */\n label: string;\n}\n\n// The six services both apps generate, in the legacy config's order.\nconst API_DESCRIPTORS: readonly ApiDescriptor[] = [\n {\n key: 'onlineMenuApi',\n slug: 'onlinemenu',\n mutatorFile: 'onlineMenuMutator',\n mutatorName: 'customInstance',\n label: 'OnlineMenuSaaS',\n },\n {\n key: 'identityApi',\n slug: 'identity',\n mutatorFile: 'identityMutator',\n mutatorName: 'identityInstance',\n label: 'IdentityService',\n },\n {\n key: 'questionerApi',\n slug: 'questioner',\n mutatorFile: 'questionerMutator',\n mutatorName: 'questionerInstance',\n label: 'QuestionerService',\n },\n {\n key: 'contentApi',\n slug: 'content',\n mutatorFile: 'contentMutator',\n mutatorName: 'contentInstance',\n label: 'ContentService',\n },\n {\n key: 'paymentApi',\n slug: 'payment',\n mutatorFile: 'paymentMutator',\n mutatorName: 'paymentInstance',\n label: 'PaymentService',\n },\n {\n key: 'notificationApi',\n slug: 'notification',\n mutatorFile: 'notificationMutator',\n mutatorName: 'notificationInstance',\n label: 'NotificationService',\n },\n];\n\n/** Strips trailing forward slashes without a backtracking-prone regex. */\nfunction stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === '/') {\n end -= 1;\n }\n return value.slice(0, end);\n}\n\n/**\n * Joins a base dir to a segment with a single forward slash. The base may carry\n * a trailing slash (app paths often do); segments are always clean slugs/files.\n */\nfunction joinPath(base: string, segment: string): string {\n return `${stripTrailingSlashes(base)}/${segment}`;\n}\n\nfunction buildApiEntry(\n descriptor: ApiDescriptor,\n options: Required<Pick<DefineOrvalConfigOptions, 'swaggerDir' | 'outDir' | 'mutatorPath' | 'prettier'>>,\n): OrvalApiEntry {\n const generatedDir = joinPath(options.outDir, descriptor.slug);\n return {\n input: {\n target: joinPath(options.swaggerDir, `${descriptor.slug}.json`),\n validation: false,\n },\n output: {\n target: joinPath(generatedDir, 'index.ts'),\n client: 'react-query',\n mode: 'tags-split',\n clean: true,\n prettier: options.prettier,\n schemas: joinPath(generatedDir, 'models'),\n override: {\n mutator: {\n path: joinPath(options.mutatorPath, `${descriptor.mutatorFile}.ts`),\n name: descriptor.mutatorName,\n },\n },\n },\n hooks: {\n afterAllFilesWrite: [\n { command: `npx prettier --write ${generatedDir}` },\n { command: `echo \"✅ Orval: ${descriptor.label} hooks generated\"` },\n ],\n },\n };\n}\n\n/**\n * Builds the shared 6-API Orval config object from app-supplied paths.\n */\nexport function defineOrvalConfig(options: DefineOrvalConfigOptions): OrvalConfig {\n const resolved = {\n swaggerDir: options.swaggerDir,\n outDir: options.outDir,\n mutatorPath: options.mutatorPath,\n prettier: options.prettier ?? true,\n };\n\n const config: OrvalConfig = {};\n for (const descriptor of API_DESCRIPTORS) {\n config[descriptor.key] = buildApiEntry(descriptor, resolved);\n }\n return config;\n}\n","/**\n * Runtime registry for HTTP client implementations.\n *\n * This registry allows the app to register the real http client implementations\n * at startup, which the generated Orval hooks will then use at runtime.\n *\n * Usage in app entry point (e.g., App.tsx):\n * ```typescript\n * import { registerMutators } from '@dloizides/orval-preset';\n * import { customInstance } from './server/httpClient';\n * import { identityInstance } from './server/httpClientIdentity';\n * import { questionerInstance } from './server/httpClientQuestioner';\n * import { contentInstance } from './server/httpClientContent';\n * import { notificationInstance } from './server/httpClientNotification';\n * import { paymentInstance } from './server/httpClientPayment';\n *\n * registerMutators({\n * customInstance,\n * identityInstance,\n * questionerInstance,\n * contentInstance,\n * notificationInstance,\n * paymentInstance,\n * });\n * ```\n */\n\nexport interface OrvalRequest<Req = unknown, Qry = unknown> {\n url: string;\n method?: string;\n data?: Req | FormData;\n params?: Qry;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport type OrvalMutator = <TResp = unknown, TReq = unknown, TQry = unknown>(\n opts: OrvalRequest<TReq, TQry>,\n) => Promise<TResp>;\n\ninterface MutatorRegistry {\n customInstance?: OrvalMutator;\n identityInstance?: OrvalMutator;\n questionerInstance?: OrvalMutator;\n contentInstance?: OrvalMutator;\n notificationInstance?: OrvalMutator;\n paymentInstance?: OrvalMutator;\n}\n\n// Global registry - populated at app startup\nconst registry: MutatorRegistry = {};\n\n/**\n * Register the real HTTP client implementations.\n * Call this once at app startup before any API hooks are used.\n */\nexport function registerMutators(mutators: Partial<MutatorRegistry>): void {\n if (mutators.customInstance) {\n registry.customInstance = mutators.customInstance;\n }\n if (mutators.identityInstance) {\n registry.identityInstance = mutators.identityInstance;\n }\n if (mutators.questionerInstance) {\n registry.questionerInstance = mutators.questionerInstance;\n }\n if (mutators.contentInstance) {\n registry.contentInstance = mutators.contentInstance;\n }\n if (mutators.notificationInstance) {\n registry.notificationInstance = mutators.notificationInstance;\n }\n if (mutators.paymentInstance) {\n registry.paymentInstance = mutators.paymentInstance;\n }\n}\n\n/**\n * Get a registered mutator by name.\n * @throws Error if the mutator has not been registered.\n */\nexport function getMutator(name: keyof MutatorRegistry): OrvalMutator {\n const mutator = registry[name];\n if (!mutator) {\n throw new Error(\n `HTTP client '${name}' not registered. Call registerMutators() at app startup.`,\n );\n }\n\n return mutator;\n}\n","/**\n * OnlineMenu API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for OnlineMenu API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function customInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('customInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default customInstance;\n","/**\n * Identity API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Identity API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function identityInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('identityInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default identityInstance;\n","/**\n * Questioner API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Questioner API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function questionerInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('questionerInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default questionerInstance;\n","/**\n * Content API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Content API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function contentInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('contentInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default contentInstance;\n","/**\n * Notification API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Notification API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function notificationInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('notificationInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default notificationInstance;\n","/**\n * Payment API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Payment API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function paymentInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('paymentInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default paymentInstance;\n","import type { OrvalRequest, OrvalMutator } from './mutators/registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * Request options passed to the injected httpService methods.\n *\n * This is the contract the consuming app's `httpService` must accept. The\n * package never imports a concrete axios/http layer — the app supplies it as\n * a port (see `HttpServicePort`), keeping this factory product-agnostic.\n */\nexport interface HttpRequestOptions {\n withCredentials?: boolean;\n baseURL?: string;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\n/**\n * The HTTP transport port the consuming app injects. Mirrors the method\n * surface the app's `httpService` already exposes (axios bridge).\n *\n * The package always supplies the base {@link HttpRequestOptions} shape, so an\n * app whose `httpService` accepts a *wider* options type (extra optional fields)\n * can be adapted to this port without type assertions.\n */\nexport interface HttpServicePort {\n get<TQry, TResp>(endpoint: string, params: TQry, opts: HttpRequestOptions): Promise<TResp>;\n post<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n postForm<TResp>(endpoint: string, data: FormData, opts: HttpRequestOptions): Promise<TResp>;\n put<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n patch<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n deleteMethod<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n}\n\ninterface HttpClientOptions {\n baseURL?: string;\n withCredentials?: boolean;\n}\n\n/**\n * Creates request options with common defaults.\n *\n * `withCredentials` is always on — the BFF session cookie must travel with\n * every same-origin API call. There is no `withToken`: the SPA holds no\n * token, the BFF attaches the `Bearer` server-side.\n */\nfunction createRequestOptions(\n opts: OrvalRequest,\n clientOptions: HttpClientOptions,\n): HttpRequestOptions {\n return {\n withCredentials: clientOptions.withCredentials ?? true,\n baseURL: clientOptions.baseURL,\n signal: opts.signal,\n headers: opts.headers,\n };\n}\n\n/**\n * Handles GET requests.\n */\nasync function handleGet<TResp, TQry>(\n http: HttpServicePort,\n endpoint: string,\n params: TQry,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.get<TQry, TResp>(endpoint, params, reqOpts);\n}\n\n/**\n * Handles POST requests, including FormData.\n */\nasync function handlePost<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | FormData | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n if (typeof FormData !== 'undefined' && data instanceof FormData) {\n return http.postForm<TResp>(endpoint, data, reqOpts);\n }\n\n // FormData was handled above, so `data` is TReq | undefined here. We cast\n // rather than re-test (the re-test would be a dead, uncoverable branch).\n const payload = data as TReq | undefined;\n return http.post<TReq | undefined, TResp>(endpoint, payload, reqOpts);\n}\n\n/**\n * Handles PUT requests.\n */\nasync function handlePut<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.put<TReq | undefined, TResp>(endpoint, data, reqOpts);\n}\n\n/**\n * Handles PATCH requests.\n */\nasync function handlePatch<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.patch<TReq | undefined, TResp>(endpoint, data, reqOpts);\n}\n\n/**\n * Handles DELETE requests.\n */\nasync function handleDelete<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.deleteMethod<TReq | undefined, TResp>(endpoint, data, reqOpts);\n}\n\n/**\n * Creates an HTTP client instance for Orval-generated hooks.\n *\n * @param http - The app's httpService transport (injected port).\n * @param clientOptions - Configuration options for the client (baseURL, auth settings).\n * @returns An async function that handles HTTP requests.\n */\nexport function createHttpClient(\n http: HttpServicePort,\n clientOptions: HttpClientOptions = {},\n): OrvalMutator {\n return async <TResp = unknown, TReq = unknown, TQry = unknown>(\n opts: OrvalRequest<TReq, TQry>,\n ): Promise<TResp> => {\n const { url, method = 'GET', data, params } = opts;\n const m = method.toUpperCase();\n const endpoint = url;\n const reqOpts = createRequestOptions(opts, clientOptions);\n\n if (m === 'GET') {\n return handleGet<TResp, TQry | undefined>(http, endpoint, params, reqOpts);\n }\n\n if (m === 'POST') {\n return handlePost<TResp, TReq>(http, endpoint, data, reqOpts);\n }\n\n if (m === 'PUT') {\n // data could be TReq | FormData | undefined, but PUT doesn't use FormData\n const putData: TReq | undefined = data instanceof FormData ? undefined : data;\n return handlePut<TResp, TReq>(http, endpoint, putData, reqOpts);\n }\n\n if (m === 'PATCH') {\n const patchData: TReq | undefined = data instanceof FormData ? undefined : data;\n return handlePatch<TResp, TReq>(http, endpoint, patchData, reqOpts);\n }\n\n if (m === 'DELETE') {\n const deleteData: TReq | undefined = data instanceof FormData ? undefined : data;\n return handleDelete<TResp, TReq>(http, endpoint, deleteData, reqOpts);\n }\n\n // Fallback to POST for unsupported methods\n return handlePost<TResp, TReq>(http, endpoint, data, reqOpts);\n };\n}\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// src/defineOrvalConfig.ts
|
|
2
|
+
var API_DESCRIPTORS = [
|
|
3
|
+
{
|
|
4
|
+
key: "onlineMenuApi",
|
|
5
|
+
slug: "onlinemenu",
|
|
6
|
+
mutatorFile: "onlineMenuMutator",
|
|
7
|
+
mutatorName: "customInstance",
|
|
8
|
+
label: "OnlineMenuSaaS"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
key: "identityApi",
|
|
12
|
+
slug: "identity",
|
|
13
|
+
mutatorFile: "identityMutator",
|
|
14
|
+
mutatorName: "identityInstance",
|
|
15
|
+
label: "IdentityService"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
key: "questionerApi",
|
|
19
|
+
slug: "questioner",
|
|
20
|
+
mutatorFile: "questionerMutator",
|
|
21
|
+
mutatorName: "questionerInstance",
|
|
22
|
+
label: "QuestionerService"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
key: "contentApi",
|
|
26
|
+
slug: "content",
|
|
27
|
+
mutatorFile: "contentMutator",
|
|
28
|
+
mutatorName: "contentInstance",
|
|
29
|
+
label: "ContentService"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
key: "paymentApi",
|
|
33
|
+
slug: "payment",
|
|
34
|
+
mutatorFile: "paymentMutator",
|
|
35
|
+
mutatorName: "paymentInstance",
|
|
36
|
+
label: "PaymentService"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: "notificationApi",
|
|
40
|
+
slug: "notification",
|
|
41
|
+
mutatorFile: "notificationMutator",
|
|
42
|
+
mutatorName: "notificationInstance",
|
|
43
|
+
label: "NotificationService"
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
function stripTrailingSlashes(value) {
|
|
47
|
+
let end = value.length;
|
|
48
|
+
while (end > 0 && value[end - 1] === "/") {
|
|
49
|
+
end -= 1;
|
|
50
|
+
}
|
|
51
|
+
return value.slice(0, end);
|
|
52
|
+
}
|
|
53
|
+
function joinPath(base, segment) {
|
|
54
|
+
return `${stripTrailingSlashes(base)}/${segment}`;
|
|
55
|
+
}
|
|
56
|
+
function buildApiEntry(descriptor, options) {
|
|
57
|
+
const generatedDir = joinPath(options.outDir, descriptor.slug);
|
|
58
|
+
return {
|
|
59
|
+
input: {
|
|
60
|
+
target: joinPath(options.swaggerDir, `${descriptor.slug}.json`),
|
|
61
|
+
validation: false
|
|
62
|
+
},
|
|
63
|
+
output: {
|
|
64
|
+
target: joinPath(generatedDir, "index.ts"),
|
|
65
|
+
client: "react-query",
|
|
66
|
+
mode: "tags-split",
|
|
67
|
+
clean: true,
|
|
68
|
+
prettier: options.prettier,
|
|
69
|
+
schemas: joinPath(generatedDir, "models"),
|
|
70
|
+
override: {
|
|
71
|
+
mutator: {
|
|
72
|
+
path: joinPath(options.mutatorPath, `${descriptor.mutatorFile}.ts`),
|
|
73
|
+
name: descriptor.mutatorName
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
hooks: {
|
|
78
|
+
afterAllFilesWrite: [
|
|
79
|
+
{ command: `npx prettier --write ${generatedDir}` },
|
|
80
|
+
{ command: `echo "\u2705 Orval: ${descriptor.label} hooks generated"` }
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function defineOrvalConfig(options) {
|
|
86
|
+
const resolved = {
|
|
87
|
+
swaggerDir: options.swaggerDir,
|
|
88
|
+
outDir: options.outDir,
|
|
89
|
+
mutatorPath: options.mutatorPath,
|
|
90
|
+
prettier: options.prettier ?? true
|
|
91
|
+
};
|
|
92
|
+
const config = {};
|
|
93
|
+
for (const descriptor of API_DESCRIPTORS) {
|
|
94
|
+
config[descriptor.key] = buildApiEntry(descriptor, resolved);
|
|
95
|
+
}
|
|
96
|
+
return config;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/mutators/registry.ts
|
|
100
|
+
var registry = {};
|
|
101
|
+
function registerMutators(mutators) {
|
|
102
|
+
if (mutators.customInstance) {
|
|
103
|
+
registry.customInstance = mutators.customInstance;
|
|
104
|
+
}
|
|
105
|
+
if (mutators.identityInstance) {
|
|
106
|
+
registry.identityInstance = mutators.identityInstance;
|
|
107
|
+
}
|
|
108
|
+
if (mutators.questionerInstance) {
|
|
109
|
+
registry.questionerInstance = mutators.questionerInstance;
|
|
110
|
+
}
|
|
111
|
+
if (mutators.contentInstance) {
|
|
112
|
+
registry.contentInstance = mutators.contentInstance;
|
|
113
|
+
}
|
|
114
|
+
if (mutators.notificationInstance) {
|
|
115
|
+
registry.notificationInstance = mutators.notificationInstance;
|
|
116
|
+
}
|
|
117
|
+
if (mutators.paymentInstance) {
|
|
118
|
+
registry.paymentInstance = mutators.paymentInstance;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function getMutator(name) {
|
|
122
|
+
const mutator = registry[name];
|
|
123
|
+
if (!mutator) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`HTTP client '${name}' not registered. Call registerMutators() at app startup.`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return mutator;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/mutators/onlineMenuMutator.ts
|
|
132
|
+
async function customInstance(opts) {
|
|
133
|
+
const realMutator = getMutator("customInstance");
|
|
134
|
+
return realMutator(opts);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/mutators/identityMutator.ts
|
|
138
|
+
async function identityInstance(opts) {
|
|
139
|
+
const realMutator = getMutator("identityInstance");
|
|
140
|
+
return realMutator(opts);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/mutators/questionerMutator.ts
|
|
144
|
+
async function questionerInstance(opts) {
|
|
145
|
+
const realMutator = getMutator("questionerInstance");
|
|
146
|
+
return realMutator(opts);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/mutators/contentMutator.ts
|
|
150
|
+
async function contentInstance(opts) {
|
|
151
|
+
const realMutator = getMutator("contentInstance");
|
|
152
|
+
return realMutator(opts);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/mutators/notificationMutator.ts
|
|
156
|
+
async function notificationInstance(opts) {
|
|
157
|
+
const realMutator = getMutator("notificationInstance");
|
|
158
|
+
return realMutator(opts);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/mutators/paymentMutator.ts
|
|
162
|
+
async function paymentInstance(opts) {
|
|
163
|
+
const realMutator = getMutator("paymentInstance");
|
|
164
|
+
return realMutator(opts);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/createHttpClient.ts
|
|
168
|
+
function createRequestOptions(opts, clientOptions) {
|
|
169
|
+
return {
|
|
170
|
+
withCredentials: clientOptions.withCredentials ?? true,
|
|
171
|
+
baseURL: clientOptions.baseURL,
|
|
172
|
+
signal: opts.signal,
|
|
173
|
+
headers: opts.headers
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async function handleGet(http, endpoint, params, reqOpts) {
|
|
177
|
+
return http.get(endpoint, params, reqOpts);
|
|
178
|
+
}
|
|
179
|
+
async function handlePost(http, endpoint, data, reqOpts) {
|
|
180
|
+
if (typeof FormData !== "undefined" && data instanceof FormData) {
|
|
181
|
+
return http.postForm(endpoint, data, reqOpts);
|
|
182
|
+
}
|
|
183
|
+
const payload = data;
|
|
184
|
+
return http.post(endpoint, payload, reqOpts);
|
|
185
|
+
}
|
|
186
|
+
async function handlePut(http, endpoint, data, reqOpts) {
|
|
187
|
+
return http.put(endpoint, data, reqOpts);
|
|
188
|
+
}
|
|
189
|
+
async function handlePatch(http, endpoint, data, reqOpts) {
|
|
190
|
+
return http.patch(endpoint, data, reqOpts);
|
|
191
|
+
}
|
|
192
|
+
async function handleDelete(http, endpoint, data, reqOpts) {
|
|
193
|
+
return http.deleteMethod(endpoint, data, reqOpts);
|
|
194
|
+
}
|
|
195
|
+
function createHttpClient(http, clientOptions = {}) {
|
|
196
|
+
return async (opts) => {
|
|
197
|
+
const { url, method = "GET", data, params } = opts;
|
|
198
|
+
const m = method.toUpperCase();
|
|
199
|
+
const endpoint = url;
|
|
200
|
+
const reqOpts = createRequestOptions(opts, clientOptions);
|
|
201
|
+
if (m === "GET") {
|
|
202
|
+
return handleGet(http, endpoint, params, reqOpts);
|
|
203
|
+
}
|
|
204
|
+
if (m === "POST") {
|
|
205
|
+
return handlePost(http, endpoint, data, reqOpts);
|
|
206
|
+
}
|
|
207
|
+
if (m === "PUT") {
|
|
208
|
+
const putData = data instanceof FormData ? void 0 : data;
|
|
209
|
+
return handlePut(http, endpoint, putData, reqOpts);
|
|
210
|
+
}
|
|
211
|
+
if (m === "PATCH") {
|
|
212
|
+
const patchData = data instanceof FormData ? void 0 : data;
|
|
213
|
+
return handlePatch(http, endpoint, patchData, reqOpts);
|
|
214
|
+
}
|
|
215
|
+
if (m === "DELETE") {
|
|
216
|
+
const deleteData = data instanceof FormData ? void 0 : data;
|
|
217
|
+
return handleDelete(http, endpoint, deleteData, reqOpts);
|
|
218
|
+
}
|
|
219
|
+
return handlePost(http, endpoint, data, reqOpts);
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export { contentInstance, createHttpClient, customInstance, defineOrvalConfig, getMutator, identityInstance, notificationInstance, paymentInstance, questionerInstance, registerMutators };
|
|
224
|
+
//# sourceMappingURL=index.mjs.map
|
|
225
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/defineOrvalConfig.ts","../src/mutators/registry.ts","../src/mutators/onlineMenuMutator.ts","../src/mutators/identityMutator.ts","../src/mutators/questionerMutator.ts","../src/mutators/contentMutator.ts","../src/mutators/notificationMutator.ts","../src/mutators/paymentMutator.ts","../src/createHttpClient.ts"],"names":[],"mappings":";AA8EA,IAAM,eAAA,GAA4C;AAAA,EAChD;AAAA,IACE,GAAA,EAAK,eAAA;AAAA,IACL,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EAAa,mBAAA;AAAA,IACb,WAAA,EAAa,gBAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,GAAA,EAAK,aAAA;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,iBAAA;AAAA,IACb,WAAA,EAAa,kBAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,GAAA,EAAK,eAAA;AAAA,IACL,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EAAa,mBAAA;AAAA,IACb,WAAA,EAAa,oBAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,GAAA,EAAK,YAAA;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,gBAAA;AAAA,IACb,WAAA,EAAa,iBAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,GAAA,EAAK,YAAA;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,gBAAA;AAAA,IACb,WAAA,EAAa,iBAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,GAAA,EAAK,iBAAA;AAAA,IACL,IAAA,EAAM,cAAA;AAAA,IACN,WAAA,EAAa,qBAAA;AAAA,IACb,WAAA,EAAa,sBAAA;AAAA,IACb,KAAA,EAAO;AAAA;AAEX,CAAA;AAGA,SAAS,qBAAqB,KAAA,EAAuB;AACnD,EAAA,IAAI,MAAM,KAAA,CAAM,MAAA;AAChB,EAAA,OAAO,MAAM,CAAA,IAAK,KAAA,CAAM,GAAA,GAAM,CAAC,MAAM,GAAA,EAAK;AACxC,IAAA,GAAA,IAAO,CAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AAC3B;AAMA,SAAS,QAAA,CAAS,MAAc,OAAA,EAAyB;AACvD,EAAA,OAAO,CAAA,EAAG,oBAAA,CAAqB,IAAI,CAAC,IAAI,OAAO,CAAA,CAAA;AACjD;AAEA,SAAS,aAAA,CACP,YACA,OAAA,EACe;AACf,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,WAAW,IAAI,CAAA;AAC7D,EAAA,OAAO;AAAA,IACL,KAAA,EAAO;AAAA,MACL,QAAQ,QAAA,CAAS,OAAA,CAAQ,YAAY,CAAA,EAAG,UAAA,CAAW,IAAI,CAAA,KAAA,CAAO,CAAA;AAAA,MAC9D,UAAA,EAAY;AAAA,KACd;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,MAAA,EAAQ,QAAA,CAAS,YAAA,EAAc,UAAU,CAAA;AAAA,MACzC,MAAA,EAAQ,aAAA;AAAA,MACR,IAAA,EAAM,YAAA;AAAA,MACN,KAAA,EAAO,IAAA;AAAA,MACP,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,OAAA,EAAS,QAAA,CAAS,YAAA,EAAc,QAAQ,CAAA;AAAA,MACxC,QAAA,EAAU;AAAA,QACR,OAAA,EAAS;AAAA,UACP,MAAM,QAAA,CAAS,OAAA,CAAQ,aAAa,CAAA,EAAG,UAAA,CAAW,WAAW,CAAA,GAAA,CAAK,CAAA;AAAA,UAClE,MAAM,UAAA,CAAW;AAAA;AACnB;AACF,KACF;AAAA,IACA,KAAA,EAAO;AAAA,MACL,kBAAA,EAAoB;AAAA,QAClB,EAAE,OAAA,EAAS,CAAA,qBAAA,EAAwB,YAAY,CAAA,CAAA,EAAG;AAAA,QAClD,EAAE,OAAA,EAAS,CAAA,oBAAA,EAAkB,UAAA,CAAW,KAAK,CAAA,iBAAA,CAAA;AAAoB;AACnE;AACF,GACF;AACF;AAKO,SAAS,kBAAkB,OAAA,EAAgD;AAChF,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,aAAa,OAAA,CAAQ,WAAA;AAAA,IACrB,QAAA,EAAU,QAAQ,QAAA,IAAY;AAAA,GAChC;AAEA,EAAA,MAAM,SAAsB,EAAC;AAC7B,EAAA,KAAA,MAAW,cAAc,eAAA,EAAiB;AACxC,IAAA,MAAA,CAAO,UAAA,CAAW,GAAG,CAAA,GAAI,aAAA,CAAc,YAAY,QAAQ,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,MAAA;AACT;;;AC3IA,IAAM,WAA4B,EAAC;AAM5B,SAAS,iBAAiB,QAAA,EAA0C;AACzE,EAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,IAAA,QAAA,CAAS,iBAAiB,QAAA,CAAS,cAAA;AAAA,EACrC;AACA,EAAA,IAAI,SAAS,gBAAA,EAAkB;AAC7B,IAAA,QAAA,CAAS,mBAAmB,QAAA,CAAS,gBAAA;AAAA,EACvC;AACA,EAAA,IAAI,SAAS,kBAAA,EAAoB;AAC/B,IAAA,QAAA,CAAS,qBAAqB,QAAA,CAAS,kBAAA;AAAA,EACzC;AACA,EAAA,IAAI,SAAS,eAAA,EAAiB;AAC5B,IAAA,QAAA,CAAS,kBAAkB,QAAA,CAAS,eAAA;AAAA,EACtC;AACA,EAAA,IAAI,SAAS,oBAAA,EAAsB;AACjC,IAAA,QAAA,CAAS,uBAAuB,QAAA,CAAS,oBAAA;AAAA,EAC3C;AACA,EAAA,IAAI,SAAS,eAAA,EAAiB;AAC5B,IAAA,QAAA,CAAS,kBAAkB,QAAA,CAAS,eAAA;AAAA,EACtC;AACF;AAMO,SAAS,WAAW,IAAA,EAA2C;AACpE,EAAA,MAAM,OAAA,GAAU,SAAS,IAAI,CAAA;AAC7B,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,IAAI,CAAA,yDAAA;AAAA,KACtB;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;;;AC3EA,eAAsB,eAKpB,IAAA,EACgB;AAChB,EAAA,MAAM,WAAA,GAAc,WAAW,gBAAgB,CAAA;AAC/C,EAAA,OAAO,YAA+B,IAAI,CAAA;AAC5C;;;ACTA,eAAsB,iBAKpB,IAAA,EACgB;AAChB,EAAA,MAAM,WAAA,GAAc,WAAW,kBAAkB,CAAA;AACjD,EAAA,OAAO,YAA+B,IAAI,CAAA;AAC5C;;;ACTA,eAAsB,mBAKpB,IAAA,EACgB;AAChB,EAAA,MAAM,WAAA,GAAc,WAAW,oBAAoB,CAAA;AACnD,EAAA,OAAO,YAA+B,IAAI,CAAA;AAC5C;;;ACTA,eAAsB,gBAKpB,IAAA,EACgB;AAChB,EAAA,MAAM,WAAA,GAAc,WAAW,iBAAiB,CAAA;AAChD,EAAA,OAAO,YAA+B,IAAI,CAAA;AAC5C;;;ACTA,eAAsB,qBAKpB,IAAA,EACgB;AAChB,EAAA,MAAM,WAAA,GAAc,WAAW,sBAAsB,CAAA;AACrD,EAAA,OAAO,YAA+B,IAAI,CAAA;AAC5C;;;ACTA,eAAsB,gBAKpB,IAAA,EACgB;AAChB,EAAA,MAAM,WAAA,GAAc,WAAW,iBAAiB,CAAA;AAChD,EAAA,OAAO,YAA+B,IAAI,CAAA;AAC5C;;;ACuBA,SAAS,oBAAA,CACP,MACA,aAAA,EACoB;AACpB,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,cAAc,eAAA,IAAmB,IAAA;AAAA,IAClD,SAAS,aAAA,CAAc,OAAA;AAAA,IACvB,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,SAAS,IAAA,CAAK;AAAA,GAChB;AACF;AAKA,eAAe,SAAA,CACb,IAAA,EACA,QAAA,EACA,MAAA,EACA,OAAA,EACgB;AAChB,EAAA,OAAO,IAAA,CAAK,GAAA,CAAiB,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AACxD;AAKA,eAAe,UAAA,CACb,IAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACgB;AAChB,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,IAAA,YAAgB,QAAA,EAAU;AAC/D,IAAA,OAAO,IAAA,CAAK,QAAA,CAAgB,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AAAA,EACrD;AAIA,EAAA,MAAM,OAAA,GAAU,IAAA;AAChB,EAAA,OAAO,IAAA,CAAK,IAAA,CAA8B,QAAA,EAAU,OAAA,EAAS,OAAO,CAAA;AACtE;AAKA,eAAe,SAAA,CACb,IAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACgB;AAChB,EAAA,OAAO,IAAA,CAAK,GAAA,CAA6B,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AAClE;AAKA,eAAe,WAAA,CACb,IAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACgB;AAChB,EAAA,OAAO,IAAA,CAAK,KAAA,CAA+B,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACpE;AAKA,eAAe,YAAA,CACb,IAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACgB;AAChB,EAAA,OAAO,IAAA,CAAK,YAAA,CAAsC,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AAC3E;AASO,SAAS,gBAAA,CACd,IAAA,EACA,aAAA,GAAmC,EAAC,EACtB;AACd,EAAA,OAAO,OACL,IAAA,KACmB;AACnB,IAAA,MAAM,EAAE,GAAA,EAAK,MAAA,GAAS,KAAA,EAAO,IAAA,EAAM,QAAO,GAAI,IAAA;AAC9C,IAAA,MAAM,CAAA,GAAI,OAAO,WAAA,EAAY;AAC7B,IAAA,MAAM,QAAA,GAAW,GAAA;AACjB,IAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,IAAA,EAAM,aAAa,CAAA;AAExD,IAAA,IAAI,MAAM,KAAA,EAAO;AACf,MAAA,OAAO,SAAA,CAAmC,IAAA,EAAM,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AAAA,IAC3E;AAEA,IAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,MAAA,OAAO,UAAA,CAAwB,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAI,MAAM,KAAA,EAAO;AAEf,MAAA,MAAM,OAAA,GAA4B,IAAA,YAAgB,QAAA,GAAW,MAAA,GAAY,IAAA;AACzE,MAAA,OAAO,SAAA,CAAuB,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,OAAO,CAAA;AAAA,IAChE;AAEA,IAAA,IAAI,MAAM,OAAA,EAAS;AACjB,MAAA,MAAM,SAAA,GAA8B,IAAA,YAAgB,QAAA,GAAW,MAAA,GAAY,IAAA;AAC3E,MAAA,OAAO,WAAA,CAAyB,IAAA,EAAM,QAAA,EAAU,SAAA,EAAW,OAAO,CAAA;AAAA,IACpE;AAEA,IAAA,IAAI,MAAM,QAAA,EAAU;AAClB,MAAA,MAAM,UAAA,GAA+B,IAAA,YAAgB,QAAA,GAAW,MAAA,GAAY,IAAA;AAC5E,MAAA,OAAO,YAAA,CAA0B,IAAA,EAAM,QAAA,EAAU,UAAA,EAAY,OAAO,CAAA;AAAA,IACtE;AAGA,IAAA,OAAO,UAAA,CAAwB,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AAAA,EAC9D,CAAA;AACF","file":"index.mjs","sourcesContent":["/**\n * Orval config factory shared by erevna-web and katalogos-web.\n *\n * Both apps generate React Query hooks from the SAME six OpenAPI services\n * (onlineMenu / identity / questioner / content / notification / payment) with\n * an identical `tags-split` + per-service-mutator setup. This factory owns that\n * shared shape; each app supplies only its own paths via {@link DefineOrvalConfigOptions}.\n *\n * The return value is a plain Orval config object (the same thing\n * `defineConfig(...)` returns), so the app's `orval.config.js` becomes:\n *\n * ```js\n * const { defineOrvalConfig } = require('@dloizides/orval-preset');\n * module.exports = defineOrvalConfig({\n * swaggerDir: './src/server/swagger',\n * outDir: './src/server/autoGeneratedHooks',\n * mutatorPath: './src/server/mutators',\n * });\n * ```\n */\n\nexport interface DefineOrvalConfigOptions {\n /** Directory holding the per-service swagger JSON inputs (app-owned). */\n swaggerDir: string;\n /** Directory the generated client dirs are written to (app-owned, gitignored). */\n outDir: string;\n /** Directory holding the mutator files orval points generated hooks at (app-owned shims). */\n mutatorPath: string;\n /** Optional prettier override (defaults to true, matching the legacy config). */\n prettier?: boolean;\n}\n\ninterface OrvalMutatorOverride {\n path: string;\n name: string;\n}\n\ninterface OrvalHookCommand {\n command: string;\n}\n\ninterface OrvalApiEntry {\n input: {\n target: string;\n validation: boolean;\n };\n output: {\n target: string;\n client: 'react-query';\n mode: 'tags-split';\n clean: boolean;\n prettier: boolean;\n schemas: string;\n override: {\n mutator: OrvalMutatorOverride;\n };\n };\n hooks: {\n afterAllFilesWrite: OrvalHookCommand[];\n };\n}\n\nexport type OrvalConfig = Record<string, OrvalApiEntry>;\n\ninterface ApiDescriptor {\n /** Orval config key (e.g. `onlineMenuApi`). */\n key: string;\n /** Swagger file basename without extension + the generated dir name (e.g. `onlinemenu`). */\n slug: string;\n /** Mutator file basename without extension (e.g. `onlineMenuMutator`). */\n mutatorFile: string;\n /** Exported mutator function name (e.g. `customInstance`). */\n mutatorName: string;\n /** Human label used in the generated success echo. */\n label: string;\n}\n\n// The six services both apps generate, in the legacy config's order.\nconst API_DESCRIPTORS: readonly ApiDescriptor[] = [\n {\n key: 'onlineMenuApi',\n slug: 'onlinemenu',\n mutatorFile: 'onlineMenuMutator',\n mutatorName: 'customInstance',\n label: 'OnlineMenuSaaS',\n },\n {\n key: 'identityApi',\n slug: 'identity',\n mutatorFile: 'identityMutator',\n mutatorName: 'identityInstance',\n label: 'IdentityService',\n },\n {\n key: 'questionerApi',\n slug: 'questioner',\n mutatorFile: 'questionerMutator',\n mutatorName: 'questionerInstance',\n label: 'QuestionerService',\n },\n {\n key: 'contentApi',\n slug: 'content',\n mutatorFile: 'contentMutator',\n mutatorName: 'contentInstance',\n label: 'ContentService',\n },\n {\n key: 'paymentApi',\n slug: 'payment',\n mutatorFile: 'paymentMutator',\n mutatorName: 'paymentInstance',\n label: 'PaymentService',\n },\n {\n key: 'notificationApi',\n slug: 'notification',\n mutatorFile: 'notificationMutator',\n mutatorName: 'notificationInstance',\n label: 'NotificationService',\n },\n];\n\n/** Strips trailing forward slashes without a backtracking-prone regex. */\nfunction stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === '/') {\n end -= 1;\n }\n return value.slice(0, end);\n}\n\n/**\n * Joins a base dir to a segment with a single forward slash. The base may carry\n * a trailing slash (app paths often do); segments are always clean slugs/files.\n */\nfunction joinPath(base: string, segment: string): string {\n return `${stripTrailingSlashes(base)}/${segment}`;\n}\n\nfunction buildApiEntry(\n descriptor: ApiDescriptor,\n options: Required<Pick<DefineOrvalConfigOptions, 'swaggerDir' | 'outDir' | 'mutatorPath' | 'prettier'>>,\n): OrvalApiEntry {\n const generatedDir = joinPath(options.outDir, descriptor.slug);\n return {\n input: {\n target: joinPath(options.swaggerDir, `${descriptor.slug}.json`),\n validation: false,\n },\n output: {\n target: joinPath(generatedDir, 'index.ts'),\n client: 'react-query',\n mode: 'tags-split',\n clean: true,\n prettier: options.prettier,\n schemas: joinPath(generatedDir, 'models'),\n override: {\n mutator: {\n path: joinPath(options.mutatorPath, `${descriptor.mutatorFile}.ts`),\n name: descriptor.mutatorName,\n },\n },\n },\n hooks: {\n afterAllFilesWrite: [\n { command: `npx prettier --write ${generatedDir}` },\n { command: `echo \"✅ Orval: ${descriptor.label} hooks generated\"` },\n ],\n },\n };\n}\n\n/**\n * Builds the shared 6-API Orval config object from app-supplied paths.\n */\nexport function defineOrvalConfig(options: DefineOrvalConfigOptions): OrvalConfig {\n const resolved = {\n swaggerDir: options.swaggerDir,\n outDir: options.outDir,\n mutatorPath: options.mutatorPath,\n prettier: options.prettier ?? true,\n };\n\n const config: OrvalConfig = {};\n for (const descriptor of API_DESCRIPTORS) {\n config[descriptor.key] = buildApiEntry(descriptor, resolved);\n }\n return config;\n}\n","/**\n * Runtime registry for HTTP client implementations.\n *\n * This registry allows the app to register the real http client implementations\n * at startup, which the generated Orval hooks will then use at runtime.\n *\n * Usage in app entry point (e.g., App.tsx):\n * ```typescript\n * import { registerMutators } from '@dloizides/orval-preset';\n * import { customInstance } from './server/httpClient';\n * import { identityInstance } from './server/httpClientIdentity';\n * import { questionerInstance } from './server/httpClientQuestioner';\n * import { contentInstance } from './server/httpClientContent';\n * import { notificationInstance } from './server/httpClientNotification';\n * import { paymentInstance } from './server/httpClientPayment';\n *\n * registerMutators({\n * customInstance,\n * identityInstance,\n * questionerInstance,\n * contentInstance,\n * notificationInstance,\n * paymentInstance,\n * });\n * ```\n */\n\nexport interface OrvalRequest<Req = unknown, Qry = unknown> {\n url: string;\n method?: string;\n data?: Req | FormData;\n params?: Qry;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport type OrvalMutator = <TResp = unknown, TReq = unknown, TQry = unknown>(\n opts: OrvalRequest<TReq, TQry>,\n) => Promise<TResp>;\n\ninterface MutatorRegistry {\n customInstance?: OrvalMutator;\n identityInstance?: OrvalMutator;\n questionerInstance?: OrvalMutator;\n contentInstance?: OrvalMutator;\n notificationInstance?: OrvalMutator;\n paymentInstance?: OrvalMutator;\n}\n\n// Global registry - populated at app startup\nconst registry: MutatorRegistry = {};\n\n/**\n * Register the real HTTP client implementations.\n * Call this once at app startup before any API hooks are used.\n */\nexport function registerMutators(mutators: Partial<MutatorRegistry>): void {\n if (mutators.customInstance) {\n registry.customInstance = mutators.customInstance;\n }\n if (mutators.identityInstance) {\n registry.identityInstance = mutators.identityInstance;\n }\n if (mutators.questionerInstance) {\n registry.questionerInstance = mutators.questionerInstance;\n }\n if (mutators.contentInstance) {\n registry.contentInstance = mutators.contentInstance;\n }\n if (mutators.notificationInstance) {\n registry.notificationInstance = mutators.notificationInstance;\n }\n if (mutators.paymentInstance) {\n registry.paymentInstance = mutators.paymentInstance;\n }\n}\n\n/**\n * Get a registered mutator by name.\n * @throws Error if the mutator has not been registered.\n */\nexport function getMutator(name: keyof MutatorRegistry): OrvalMutator {\n const mutator = registry[name];\n if (!mutator) {\n throw new Error(\n `HTTP client '${name}' not registered. Call registerMutators() at app startup.`,\n );\n }\n\n return mutator;\n}\n","/**\n * OnlineMenu API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for OnlineMenu API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function customInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('customInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default customInstance;\n","/**\n * Identity API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Identity API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function identityInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('identityInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default identityInstance;\n","/**\n * Questioner API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Questioner API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function questionerInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('questionerInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default questionerInstance;\n","/**\n * Content API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Content API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function contentInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('contentInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default contentInstance;\n","/**\n * Notification API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Notification API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function notificationInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('notificationInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default notificationInstance;\n","/**\n * Payment API mutator for Orval code generation.\n *\n * This file has no Expo dependencies at the module level, allowing Orval\n * to load it in Node.js during code generation. At runtime, it retrieves\n * the real HTTP client from the registry.\n */\nimport { getMutator, type OrvalRequest, type OrvalMutator } from './registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * HTTP client for Payment API.\n * At runtime, delegates to the real implementation registered via registerMutators().\n */\nexport async function paymentInstance<\n TResp = unknown,\n TReq = unknown,\n TQry = unknown,\n>(\n opts: OrvalRequest<TReq, TQry>,\n): Promise<TResp> {\n const realMutator = getMutator('paymentInstance');\n return realMutator<TResp, TReq, TQry>(opts);\n}\n\nexport default paymentInstance;\n","import type { OrvalRequest, OrvalMutator } from './mutators/registry';\n\nexport type { OrvalRequest, OrvalMutator };\n\n/**\n * Request options passed to the injected httpService methods.\n *\n * This is the contract the consuming app's `httpService` must accept. The\n * package never imports a concrete axios/http layer — the app supplies it as\n * a port (see `HttpServicePort`), keeping this factory product-agnostic.\n */\nexport interface HttpRequestOptions {\n withCredentials?: boolean;\n baseURL?: string;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\n/**\n * The HTTP transport port the consuming app injects. Mirrors the method\n * surface the app's `httpService` already exposes (axios bridge).\n *\n * The package always supplies the base {@link HttpRequestOptions} shape, so an\n * app whose `httpService` accepts a *wider* options type (extra optional fields)\n * can be adapted to this port without type assertions.\n */\nexport interface HttpServicePort {\n get<TQry, TResp>(endpoint: string, params: TQry, opts: HttpRequestOptions): Promise<TResp>;\n post<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n postForm<TResp>(endpoint: string, data: FormData, opts: HttpRequestOptions): Promise<TResp>;\n put<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n patch<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n deleteMethod<TReq, TResp>(endpoint: string, data: TReq, opts: HttpRequestOptions): Promise<TResp>;\n}\n\ninterface HttpClientOptions {\n baseURL?: string;\n withCredentials?: boolean;\n}\n\n/**\n * Creates request options with common defaults.\n *\n * `withCredentials` is always on — the BFF session cookie must travel with\n * every same-origin API call. There is no `withToken`: the SPA holds no\n * token, the BFF attaches the `Bearer` server-side.\n */\nfunction createRequestOptions(\n opts: OrvalRequest,\n clientOptions: HttpClientOptions,\n): HttpRequestOptions {\n return {\n withCredentials: clientOptions.withCredentials ?? true,\n baseURL: clientOptions.baseURL,\n signal: opts.signal,\n headers: opts.headers,\n };\n}\n\n/**\n * Handles GET requests.\n */\nasync function handleGet<TResp, TQry>(\n http: HttpServicePort,\n endpoint: string,\n params: TQry,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.get<TQry, TResp>(endpoint, params, reqOpts);\n}\n\n/**\n * Handles POST requests, including FormData.\n */\nasync function handlePost<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | FormData | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n if (typeof FormData !== 'undefined' && data instanceof FormData) {\n return http.postForm<TResp>(endpoint, data, reqOpts);\n }\n\n // FormData was handled above, so `data` is TReq | undefined here. We cast\n // rather than re-test (the re-test would be a dead, uncoverable branch).\n const payload = data as TReq | undefined;\n return http.post<TReq | undefined, TResp>(endpoint, payload, reqOpts);\n}\n\n/**\n * Handles PUT requests.\n */\nasync function handlePut<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.put<TReq | undefined, TResp>(endpoint, data, reqOpts);\n}\n\n/**\n * Handles PATCH requests.\n */\nasync function handlePatch<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.patch<TReq | undefined, TResp>(endpoint, data, reqOpts);\n}\n\n/**\n * Handles DELETE requests.\n */\nasync function handleDelete<TResp, TReq>(\n http: HttpServicePort,\n endpoint: string,\n data: TReq | undefined,\n reqOpts: HttpRequestOptions,\n): Promise<TResp> {\n return http.deleteMethod<TReq | undefined, TResp>(endpoint, data, reqOpts);\n}\n\n/**\n * Creates an HTTP client instance for Orval-generated hooks.\n *\n * @param http - The app's httpService transport (injected port).\n * @param clientOptions - Configuration options for the client (baseURL, auth settings).\n * @returns An async function that handles HTTP requests.\n */\nexport function createHttpClient(\n http: HttpServicePort,\n clientOptions: HttpClientOptions = {},\n): OrvalMutator {\n return async <TResp = unknown, TReq = unknown, TQry = unknown>(\n opts: OrvalRequest<TReq, TQry>,\n ): Promise<TResp> => {\n const { url, method = 'GET', data, params } = opts;\n const m = method.toUpperCase();\n const endpoint = url;\n const reqOpts = createRequestOptions(opts, clientOptions);\n\n if (m === 'GET') {\n return handleGet<TResp, TQry | undefined>(http, endpoint, params, reqOpts);\n }\n\n if (m === 'POST') {\n return handlePost<TResp, TReq>(http, endpoint, data, reqOpts);\n }\n\n if (m === 'PUT') {\n // data could be TReq | FormData | undefined, but PUT doesn't use FormData\n const putData: TReq | undefined = data instanceof FormData ? undefined : data;\n return handlePut<TResp, TReq>(http, endpoint, putData, reqOpts);\n }\n\n if (m === 'PATCH') {\n const patchData: TReq | undefined = data instanceof FormData ? undefined : data;\n return handlePatch<TResp, TReq>(http, endpoint, patchData, reqOpts);\n }\n\n if (m === 'DELETE') {\n const deleteData: TReq | undefined = data instanceof FormData ? undefined : data;\n return handleDelete<TResp, TReq>(http, endpoint, deleteData, reqOpts);\n }\n\n // Fallback to POST for unsupported methods\n return handlePost<TResp, TReq>(http, endpoint, data, reqOpts);\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dloizides/orval-preset",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Shared Orval generation setup for the dloizides.com SaaS frontends: a 6-API config factory (defineOrvalConfig), the per-service mutator registry, and the axios-bridge createHttpClient factory (transport injected as a port). Owned shape erevna-web and katalogos-web shared byte-for-byte; never imports a product.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"orval",
|
|
7
|
+
"react-query",
|
|
8
|
+
"openapi",
|
|
9
|
+
"codegen",
|
|
10
|
+
"mutator",
|
|
11
|
+
"dloizides"
|
|
12
|
+
],
|
|
13
|
+
"author": "dloizides",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/openmindednewby/orval-preset.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/openmindednewby/orval-preset#readme",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/openmindednewby/orval-preset/issues"
|
|
22
|
+
},
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"module": "./dist/index.mjs",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"import": {
|
|
33
|
+
"types": "./dist/index.d.mts",
|
|
34
|
+
"default": "./dist/index.mjs"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md",
|
|
41
|
+
"CHANGELOG.md"
|
|
42
|
+
],
|
|
43
|
+
"sideEffects": false,
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18.0.0"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "rimraf dist && tsup",
|
|
49
|
+
"build:watch": "tsup --watch",
|
|
50
|
+
"test": "jest",
|
|
51
|
+
"test:watch": "jest --watch",
|
|
52
|
+
"test:coverage": "jest --coverage",
|
|
53
|
+
"lint": "eslint src --ext .ts",
|
|
54
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
55
|
+
"typecheck": "tsc --noEmit",
|
|
56
|
+
"clean": "rimraf dist",
|
|
57
|
+
"security:audit": "npm audit --audit-level=high",
|
|
58
|
+
"deps:outdated": "npm outdated || exit 0",
|
|
59
|
+
"deps:unused": "npx depcheck --ignores \"@types/jest,@types/node,rimraf\"",
|
|
60
|
+
"deps:licenses": "npx license-checker --onlyAllow \"MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause;0BSD;Unlicense;CC0-1.0\"",
|
|
61
|
+
"deps:health": "npm run deps:outdated && npm run deps:unused",
|
|
62
|
+
"prepublishOnly": "npm run clean && npm run build && npm run test"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/jest": "^29.5.0",
|
|
66
|
+
"@types/node": "^20.19.32",
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
68
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
69
|
+
"eslint": "^8.57.0",
|
|
70
|
+
"eslint-plugin-sonarjs": "^4.0.3",
|
|
71
|
+
"jest": "^29.7.0",
|
|
72
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
73
|
+
"rimraf": "^5.0.0",
|
|
74
|
+
"ts-jest": "^29.1.0",
|
|
75
|
+
"tsup": "^8.0.0",
|
|
76
|
+
"typescript": "^5.4.0"
|
|
77
|
+
}
|
|
78
|
+
}
|