@intrig/plugin-react 0.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/.swcrc +29 -0
- package/README.md +7 -0
- package/eslint.config.mjs +19 -0
- package/package.json +25 -0
- package/project.json +29 -0
- package/rollup.config.cjs +54 -0
- package/rollup.config.mjs +33 -0
- package/src/index.ts +2 -0
- package/src/lib/code-generator.ts +79 -0
- package/src/lib/get-endpoint-documentation.ts +35 -0
- package/src/lib/get-schema-documentation.ts +11 -0
- package/src/lib/internal-types.ts +15 -0
- package/src/lib/plugin-react.ts +22 -0
- package/src/lib/templates/context.template.ts +74 -0
- package/src/lib/templates/docs/__snapshots__/async-hook.spec.ts.snap +889 -0
- package/src/lib/templates/docs/__snapshots__/download-hook.spec.ts.snap +1445 -0
- package/src/lib/templates/docs/__snapshots__/react-hook.spec.ts.snap +1371 -0
- package/src/lib/templates/docs/__snapshots__/sse-hook.spec.ts.snap +2008 -0
- package/src/lib/templates/docs/async-hook.spec.ts +92 -0
- package/src/lib/templates/docs/async-hook.ts +226 -0
- package/src/lib/templates/docs/download-hook.spec.ts +182 -0
- package/src/lib/templates/docs/download-hook.ts +170 -0
- package/src/lib/templates/docs/react-hook.spec.ts +97 -0
- package/src/lib/templates/docs/react-hook.ts +323 -0
- package/src/lib/templates/docs/schema.ts +105 -0
- package/src/lib/templates/docs/sse-hook.spec.ts +207 -0
- package/src/lib/templates/docs/sse-hook.ts +221 -0
- package/src/lib/templates/extra.template.ts +198 -0
- package/src/lib/templates/index.template.ts +14 -0
- package/src/lib/templates/intrigMiddleware.template.ts +21 -0
- package/src/lib/templates/logger.template.ts +67 -0
- package/src/lib/templates/media-type-utils.template.ts +191 -0
- package/src/lib/templates/network-state.template.ts +702 -0
- package/src/lib/templates/packageJson.template.ts +63 -0
- package/src/lib/templates/provider/__tests__/provider-templates.spec.ts +209 -0
- package/src/lib/templates/provider/axios-config.template.ts +49 -0
- package/src/lib/templates/provider/hooks.template.ts +240 -0
- package/src/lib/templates/provider/interfaces.template.ts +72 -0
- package/src/lib/templates/provider/intrig-provider-stub.template.ts +73 -0
- package/src/lib/templates/provider/intrig-provider.template.ts +185 -0
- package/src/lib/templates/provider/main.template.ts +48 -0
- package/src/lib/templates/provider/reducer.template.ts +50 -0
- package/src/lib/templates/provider/status-trap.template.ts +80 -0
- package/src/lib/templates/provider.template.ts +698 -0
- package/src/lib/templates/source/controller/method/asyncFunctionHook.template.ts +196 -0
- package/src/lib/templates/source/controller/method/clientIndex.template.ts +38 -0
- package/src/lib/templates/source/controller/method/download.template.ts +256 -0
- package/src/lib/templates/source/controller/method/params.template.ts +31 -0
- package/src/lib/templates/source/controller/method/requestHook.template.ts +220 -0
- package/src/lib/templates/source/type/typeTemplate.ts +257 -0
- package/src/lib/templates/swcrc.template.ts +25 -0
- package/src/lib/templates/tsconfig.template.ts +37 -0
- package/src/lib/templates/type-utils.template.ts +28 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +20 -0
|
@@ -0,0 +1,889 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`reactAsyncFunctionHookDocs > snapshot — path params only (no request body) 1`] = `
|
|
4
|
+
"# Intrig Async Hooks — Quick Guide
|
|
5
|
+
|
|
6
|
+
## Copy-paste starter (fast lane)
|
|
7
|
+
|
|
8
|
+
### 1) Hook import
|
|
9
|
+
|
|
10
|
+
\`\`\`ts
|
|
11
|
+
import { useVerifyUserByIdAsync } from "@intrig/react/users/{id}/client";
|
|
12
|
+
\`\`\`
|
|
13
|
+
|
|
14
|
+
### 2) Create an instance
|
|
15
|
+
|
|
16
|
+
\`\`\`ts
|
|
17
|
+
const [verifyUserById, abortVerifyUserById] = useVerifyUserByIdAsync();
|
|
18
|
+
\`\`\`
|
|
19
|
+
|
|
20
|
+
### 3) Call it (awaitable)
|
|
21
|
+
|
|
22
|
+
\`\`\`ts
|
|
23
|
+
// body?, params? — pass what your endpoint needs (order: body, params)
|
|
24
|
+
await verifyUserById(verifyUserByIdParams);
|
|
25
|
+
\`\`\`
|
|
26
|
+
|
|
27
|
+
Async hooks are for one-off, low-friction calls (e.g., validations, submissions). They return an **awaitable function** plus an **abort** function. No NetworkState.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## TL;DR (copy–paste)
|
|
32
|
+
|
|
33
|
+
\`\`\`tsx
|
|
34
|
+
import { useVerifyUserByIdAsync } from "@intrig/react/users/{id}/client";
|
|
35
|
+
import { useCallback, useEffect } from "react";
|
|
36
|
+
|
|
37
|
+
export default function Example() {
|
|
38
|
+
const [verifyUserById, abortVerifyUserById] = useVerifyUserByIdAsync();
|
|
39
|
+
|
|
40
|
+
const run = useCallback(async () => {
|
|
41
|
+
try {
|
|
42
|
+
const result = await verifyUserById(verifyUserByIdParams);
|
|
43
|
+
// do something with result
|
|
44
|
+
console.log(result);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
// request failed or was aborted
|
|
47
|
+
console.error(e);
|
|
48
|
+
}
|
|
49
|
+
}, [verifyUserById]);
|
|
50
|
+
|
|
51
|
+
// Optional: abort on unmount
|
|
52
|
+
useEffect(() => abortVerifyUserById, [abortVerifyUserById]);
|
|
53
|
+
|
|
54
|
+
return <button onClick={run}>Call</button>;
|
|
55
|
+
}
|
|
56
|
+
\`\`\`
|
|
57
|
+
|
|
58
|
+
### Optional types (if generated by your build)
|
|
59
|
+
|
|
60
|
+
\`\`\`ts
|
|
61
|
+
import type { VerifyUserByIdParams } from "@intrig/react/users/{id}/VerifyUserById.params";
|
|
62
|
+
import type { VerifyUserByIdResponseBody } from "@intrig/react/users/{id}/VerifyUserById.response";
|
|
63
|
+
\`\`\`
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Hook API
|
|
68
|
+
|
|
69
|
+
\`\`\`ts
|
|
70
|
+
// Prefer concrete types if your build emits them:
|
|
71
|
+
// import type { VerifyUserByIdResponseBody } from '@intrig/react/users/{id}/VerifyUserById.response';
|
|
72
|
+
// import type { VerifyUserByIdParams } from '@intrig/react/users/{id}/VerifyUserById.params';
|
|
73
|
+
|
|
74
|
+
type VerifyUserByIdData = unknown; // replace with VerifyUserByIdResponseBody if generated
|
|
75
|
+
type VerifyUserByIdRequest = {
|
|
76
|
+
body?: unknown;
|
|
77
|
+
params?: VerifyUserByIdParams;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Signature (shape shown; return type depends on your endpoint)
|
|
81
|
+
declare function useVerifyUserByIdAsync(): [
|
|
82
|
+
(
|
|
83
|
+
body?: VerifyUserByIdRequest["body"],
|
|
84
|
+
params?: VerifyUserByIdRequest["params"],
|
|
85
|
+
) => Promise<VerifyUserByIdData>,
|
|
86
|
+
() => void, // abort
|
|
87
|
+
];
|
|
88
|
+
\`\`\`
|
|
89
|
+
|
|
90
|
+
### Why async hooks?
|
|
91
|
+
|
|
92
|
+
- **No state machine:** just \`await\` the result.
|
|
93
|
+
- **Great for validations & submits:** uniqueness checks, field-level checks, updates.
|
|
94
|
+
- **Abortable:** cancel in-flight work on demand.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Usage Patterns
|
|
99
|
+
|
|
100
|
+
### 1) Simple try/catch (recommended)
|
|
101
|
+
|
|
102
|
+
\`\`\`tsx
|
|
103
|
+
const [verifyUserById] = useVerifyUserByIdAsync();
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const res = await verifyUserById(verifyUserByIdParams);
|
|
107
|
+
// use res
|
|
108
|
+
} catch (e) {
|
|
109
|
+
// network error or abort
|
|
110
|
+
}
|
|
111
|
+
\`\`\`
|
|
112
|
+
|
|
113
|
+
<details><summary>Description</summary>
|
|
114
|
+
<p><strong>Use when</strong> you just need the value or an error. Ideal for validators, uniqueness checks, or quick lookups.</p>
|
|
115
|
+
</details>
|
|
116
|
+
|
|
117
|
+
### 2) Abort on unmount (safe cleanup)
|
|
118
|
+
|
|
119
|
+
\`\`\`tsx
|
|
120
|
+
const [verifyUserById, abortVerifyUserById] = useVerifyUserByIdAsync();
|
|
121
|
+
|
|
122
|
+
useEffect(() => abortVerifyUserById, [abortVerifyUserById]);
|
|
123
|
+
\`\`\`
|
|
124
|
+
|
|
125
|
+
<details><summary>Description</summary>
|
|
126
|
+
<p><strong>Use when</strong> the component may unmount while a request is in-flight (route changes, conditional UI).</p>
|
|
127
|
+
</details>
|
|
128
|
+
|
|
129
|
+
### 3) Debounced validation (e.g., on input change)
|
|
130
|
+
|
|
131
|
+
\`\`\`tsx
|
|
132
|
+
const [verifyUserById, abortVerifyUserById] = useVerifyUserByIdAsync();
|
|
133
|
+
|
|
134
|
+
const onChange = useMemo(() => {
|
|
135
|
+
let t: any;
|
|
136
|
+
return (value: string) => {
|
|
137
|
+
clearTimeout(t);
|
|
138
|
+
t = setTimeout(async () => {
|
|
139
|
+
try {
|
|
140
|
+
// Optionally abort before firing a new request
|
|
141
|
+
abortVerifyUserById();
|
|
142
|
+
await verifyUserById(/* body from value */, verifyUserByIdParams);
|
|
143
|
+
} catch {}
|
|
144
|
+
}, 250);
|
|
145
|
+
};
|
|
146
|
+
}, [verifyUserById, abortVerifyUserById]);
|
|
147
|
+
\`\`\`
|
|
148
|
+
|
|
149
|
+
<details><summary>Description</summary>
|
|
150
|
+
<p><strong>Use when</strong> validating as the user types. Debounce to reduce chatter; consider <code>abortVerifyUserById()</code> before firing a new call.</p>
|
|
151
|
+
</details>
|
|
152
|
+
|
|
153
|
+
### 4) Guard against races (latest-only)
|
|
154
|
+
|
|
155
|
+
\`\`\`tsx
|
|
156
|
+
const [verifyUserById, abortVerifyUserById] = useVerifyUserByIdAsync();
|
|
157
|
+
|
|
158
|
+
const latestOnly = async () => {
|
|
159
|
+
abortVerifyUserById();
|
|
160
|
+
return verifyUserById(verifyUserByIdParams);
|
|
161
|
+
};
|
|
162
|
+
\`\`\`
|
|
163
|
+
|
|
164
|
+
<details><summary>Description</summary>
|
|
165
|
+
<p><strong>Use when</strong> only the most recent call should win (search suggestions, live filters).</p>
|
|
166
|
+
</details>
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Full example
|
|
171
|
+
|
|
172
|
+
\`\`\`tsx
|
|
173
|
+
import { useVerifyUserByIdAsync } from "@intrig/react/users/{id}/client";
|
|
174
|
+
import { useCallback } from "react";
|
|
175
|
+
|
|
176
|
+
function MyComponent() {
|
|
177
|
+
const [verifyUserById, abortVerifyUserById] = useVerifyUserByIdAsync();
|
|
178
|
+
|
|
179
|
+
const run = useCallback(async () => {
|
|
180
|
+
try {
|
|
181
|
+
const data = await verifyUserById(verifyUserByIdParams);
|
|
182
|
+
alert(JSON.stringify(data));
|
|
183
|
+
} catch (e) {
|
|
184
|
+
console.error("Call failed/aborted", e);
|
|
185
|
+
}
|
|
186
|
+
}, [verifyUserById]);
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<>
|
|
190
|
+
<button onClick={run}>Call remote</button>
|
|
191
|
+
<button onClick={abortVerifyUserById}>Abort</button>
|
|
192
|
+
</>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
\`\`\`
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Gotchas & Tips
|
|
200
|
+
|
|
201
|
+
- **No \`NetworkState\`:** async hooks return a Promise, not a state machine.
|
|
202
|
+
- **Abort:** always available; call it to cancel the latest in-flight request.
|
|
203
|
+
- **Errors:** wrap calls with \`try/catch\` to handle network failures or abort errors.
|
|
204
|
+
- **Debounce & throttle:** combine with timers to cut down chatter for typeahead/validators.
|
|
205
|
+
- **Types:** prefer generated \`VerifyUserByIdResponseBody\` and \`VerifyUserByIdParams\` if your build emits them.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Reference: Minimal cheat sheet
|
|
210
|
+
|
|
211
|
+
\`\`\`ts
|
|
212
|
+
const [fn, abort] = useVerifyUserByIdAsync();
|
|
213
|
+
await fn(verifyUserByIdParams);
|
|
214
|
+
abort(); // optional
|
|
215
|
+
\`\`\`
|
|
216
|
+
"
|
|
217
|
+
`;
|
|
218
|
+
|
|
219
|
+
exports[`reactAsyncFunctionHookDocs > snapshot — request body and path params 1`] = `
|
|
220
|
+
"# Intrig Async Hooks — Quick Guide
|
|
221
|
+
|
|
222
|
+
## Copy-paste starter (fast lane)
|
|
223
|
+
|
|
224
|
+
### 1) Hook import
|
|
225
|
+
|
|
226
|
+
\`\`\`ts
|
|
227
|
+
import { useRecalculateUserScoreAsync } from "@intrig/react/users/{id}/client";
|
|
228
|
+
\`\`\`
|
|
229
|
+
|
|
230
|
+
### 2) Create an instance
|
|
231
|
+
|
|
232
|
+
\`\`\`ts
|
|
233
|
+
const [recalculateUserScore, abortRecalculateUserScore] =
|
|
234
|
+
useRecalculateUserScoreAsync();
|
|
235
|
+
\`\`\`
|
|
236
|
+
|
|
237
|
+
### 3) Call it (awaitable)
|
|
238
|
+
|
|
239
|
+
\`\`\`ts
|
|
240
|
+
// body?, params? — pass what your endpoint needs (order: body, params)
|
|
241
|
+
await recalculateUserScore(
|
|
242
|
+
recalculateUserScoreRequest,
|
|
243
|
+
recalculateUserScoreParams,
|
|
244
|
+
);
|
|
245
|
+
\`\`\`
|
|
246
|
+
|
|
247
|
+
Async hooks are for one-off, low-friction calls (e.g., validations, submissions). They return an **awaitable function** plus an **abort** function. No NetworkState.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## TL;DR (copy–paste)
|
|
252
|
+
|
|
253
|
+
\`\`\`tsx
|
|
254
|
+
import { useRecalculateUserScoreAsync } from "@intrig/react/users/{id}/client";
|
|
255
|
+
import { useCallback, useEffect } from "react";
|
|
256
|
+
|
|
257
|
+
export default function Example() {
|
|
258
|
+
const [recalculateUserScore, abortRecalculateUserScore] =
|
|
259
|
+
useRecalculateUserScoreAsync();
|
|
260
|
+
|
|
261
|
+
const run = useCallback(async () => {
|
|
262
|
+
try {
|
|
263
|
+
const result = await recalculateUserScore(
|
|
264
|
+
recalculateUserScoreRequest,
|
|
265
|
+
recalculateUserScoreParams,
|
|
266
|
+
);
|
|
267
|
+
// do something with result
|
|
268
|
+
console.log(result);
|
|
269
|
+
} catch (e) {
|
|
270
|
+
// request failed or was aborted
|
|
271
|
+
console.error(e);
|
|
272
|
+
}
|
|
273
|
+
}, [recalculateUserScore]);
|
|
274
|
+
|
|
275
|
+
// Optional: abort on unmount
|
|
276
|
+
useEffect(() => abortRecalculateUserScore, [abortRecalculateUserScore]);
|
|
277
|
+
|
|
278
|
+
return <button onClick={run}>Call</button>;
|
|
279
|
+
}
|
|
280
|
+
\`\`\`
|
|
281
|
+
|
|
282
|
+
### Optional types (if generated by your build)
|
|
283
|
+
|
|
284
|
+
\`\`\`ts
|
|
285
|
+
import type { RecalculateUserScoreRequest } from "@intrig/react/demo_api/components/schemas/RecalculateUserScoreRequest";
|
|
286
|
+
import type { RecalculateUserScoreParams } from "@intrig/react/users/{id}/RecalculateUserScore.params";
|
|
287
|
+
import type { RecalculateUserScoreResponseBody } from "@intrig/react/users/{id}/RecalculateUserScore.response";
|
|
288
|
+
\`\`\`
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Hook API
|
|
293
|
+
|
|
294
|
+
\`\`\`ts
|
|
295
|
+
// Prefer concrete types if your build emits them:
|
|
296
|
+
// import type { RecalculateUserScoreResponseBody } from '@intrig/react/users/{id}/RecalculateUserScore.response';
|
|
297
|
+
// import type { RecalculateUserScoreParams } from '@intrig/react/users/{id}/RecalculateUserScore.params';
|
|
298
|
+
|
|
299
|
+
type RecalculateUserScoreData = unknown; // replace with RecalculateUserScoreResponseBody if generated
|
|
300
|
+
type RecalculateUserScoreRequest = {
|
|
301
|
+
body?: RecalculateUserScoreRequest;
|
|
302
|
+
params?: RecalculateUserScoreParams;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// Signature (shape shown; return type depends on your endpoint)
|
|
306
|
+
declare function useRecalculateUserScoreAsync(): [
|
|
307
|
+
(
|
|
308
|
+
body?: RecalculateUserScoreRequest["body"],
|
|
309
|
+
params?: RecalculateUserScoreRequest["params"],
|
|
310
|
+
) => Promise<RecalculateUserScoreData>,
|
|
311
|
+
() => void, // abort
|
|
312
|
+
];
|
|
313
|
+
\`\`\`
|
|
314
|
+
|
|
315
|
+
### Why async hooks?
|
|
316
|
+
|
|
317
|
+
- **No state machine:** just \`await\` the result.
|
|
318
|
+
- **Great for validations & submits:** uniqueness checks, field-level checks, updates.
|
|
319
|
+
- **Abortable:** cancel in-flight work on demand.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Usage Patterns
|
|
324
|
+
|
|
325
|
+
### 1) Simple try/catch (recommended)
|
|
326
|
+
|
|
327
|
+
\`\`\`tsx
|
|
328
|
+
const [recalculateUserScore] = useRecalculateUserScoreAsync();
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
const res = await recalculateUserScore(
|
|
332
|
+
recalculateUserScoreRequest,
|
|
333
|
+
recalculateUserScoreParams,
|
|
334
|
+
);
|
|
335
|
+
// use res
|
|
336
|
+
} catch (e) {
|
|
337
|
+
// network error or abort
|
|
338
|
+
}
|
|
339
|
+
\`\`\`
|
|
340
|
+
|
|
341
|
+
<details><summary>Description</summary>
|
|
342
|
+
<p><strong>Use when</strong> you just need the value or an error. Ideal for validators, uniqueness checks, or quick lookups.</p>
|
|
343
|
+
</details>
|
|
344
|
+
|
|
345
|
+
### 2) Abort on unmount (safe cleanup)
|
|
346
|
+
|
|
347
|
+
\`\`\`tsx
|
|
348
|
+
const [recalculateUserScore, abortRecalculateUserScore] =
|
|
349
|
+
useRecalculateUserScoreAsync();
|
|
350
|
+
|
|
351
|
+
useEffect(() => abortRecalculateUserScore, [abortRecalculateUserScore]);
|
|
352
|
+
\`\`\`
|
|
353
|
+
|
|
354
|
+
<details><summary>Description</summary>
|
|
355
|
+
<p><strong>Use when</strong> the component may unmount while a request is in-flight (route changes, conditional UI).</p>
|
|
356
|
+
</details>
|
|
357
|
+
|
|
358
|
+
### 3) Debounced validation (e.g., on input change)
|
|
359
|
+
|
|
360
|
+
\`\`\`tsx
|
|
361
|
+
const [recalculateUserScore, abortRecalculateUserScore] =
|
|
362
|
+
useRecalculateUserScoreAsync();
|
|
363
|
+
|
|
364
|
+
const onChange = useMemo(() => {
|
|
365
|
+
let t: any;
|
|
366
|
+
return (recalculateUserScoreRequest: RecalculateUserScoreRequest) => {
|
|
367
|
+
clearTimeout(t);
|
|
368
|
+
t = setTimeout(async () => {
|
|
369
|
+
try {
|
|
370
|
+
// Optionally abort before firing a new request
|
|
371
|
+
abortRecalculateUserScore();
|
|
372
|
+
await recalculateUserScore(
|
|
373
|
+
recalculateUserScoreRequest,
|
|
374
|
+
recalculateUserScoreParams,
|
|
375
|
+
);
|
|
376
|
+
} catch {}
|
|
377
|
+
}, 250);
|
|
378
|
+
};
|
|
379
|
+
}, [recalculateUserScore, abortRecalculateUserScore]);
|
|
380
|
+
\`\`\`
|
|
381
|
+
|
|
382
|
+
<details><summary>Description</summary>
|
|
383
|
+
<p><strong>Use when</strong> validating as the user types. Debounce to reduce chatter; consider <code>abortRecalculateUserScore()</code> before firing a new call.</p>
|
|
384
|
+
</details>
|
|
385
|
+
|
|
386
|
+
### 4) Guard against races (latest-only)
|
|
387
|
+
|
|
388
|
+
\`\`\`tsx
|
|
389
|
+
const [recalculateUserScore, abortRecalculateUserScore] =
|
|
390
|
+
useRecalculateUserScoreAsync();
|
|
391
|
+
|
|
392
|
+
const latestOnly = async () => {
|
|
393
|
+
abortRecalculateUserScore();
|
|
394
|
+
return recalculateUserScore(
|
|
395
|
+
recalculateUserScoreRequest,
|
|
396
|
+
recalculateUserScoreParams,
|
|
397
|
+
);
|
|
398
|
+
};
|
|
399
|
+
\`\`\`
|
|
400
|
+
|
|
401
|
+
<details><summary>Description</summary>
|
|
402
|
+
<p><strong>Use when</strong> only the most recent call should win (search suggestions, live filters).</p>
|
|
403
|
+
</details>
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Full example
|
|
408
|
+
|
|
409
|
+
\`\`\`tsx
|
|
410
|
+
import { useRecalculateUserScoreAsync } from "@intrig/react/users/{id}/client";
|
|
411
|
+
import { useCallback } from "react";
|
|
412
|
+
|
|
413
|
+
function MyComponent() {
|
|
414
|
+
const [recalculateUserScore, abortRecalculateUserScore] =
|
|
415
|
+
useRecalculateUserScoreAsync();
|
|
416
|
+
|
|
417
|
+
const run = useCallback(async () => {
|
|
418
|
+
try {
|
|
419
|
+
const data = await recalculateUserScore(
|
|
420
|
+
recalculateUserScoreRequest,
|
|
421
|
+
recalculateUserScoreParams,
|
|
422
|
+
);
|
|
423
|
+
alert(JSON.stringify(data));
|
|
424
|
+
} catch (e) {
|
|
425
|
+
console.error("Call failed/aborted", e);
|
|
426
|
+
}
|
|
427
|
+
}, [recalculateUserScore]);
|
|
428
|
+
|
|
429
|
+
return (
|
|
430
|
+
<>
|
|
431
|
+
<button onClick={run}>Call remote</button>
|
|
432
|
+
<button onClick={abortRecalculateUserScore}>Abort</button>
|
|
433
|
+
</>
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
\`\`\`
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## Gotchas & Tips
|
|
441
|
+
|
|
442
|
+
- **No \`NetworkState\`:** async hooks return a Promise, not a state machine.
|
|
443
|
+
- **Abort:** always available; call it to cancel the latest in-flight request.
|
|
444
|
+
- **Errors:** wrap calls with \`try/catch\` to handle network failures or abort errors.
|
|
445
|
+
- **Debounce & throttle:** combine with timers to cut down chatter for typeahead/validators.
|
|
446
|
+
- **Types:** prefer generated \`RecalculateUserScoreResponseBody\` and \`RecalculateUserScoreParams\` if your build emits them.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## Reference: Minimal cheat sheet
|
|
451
|
+
|
|
452
|
+
\`\`\`ts
|
|
453
|
+
const [fn, abort] = useRecalculateUserScoreAsync();
|
|
454
|
+
await fn(recalculateUserScoreRequest, recalculateUserScoreParams);
|
|
455
|
+
abort(); // optional
|
|
456
|
+
\`\`\`
|
|
457
|
+
"
|
|
458
|
+
`;
|
|
459
|
+
|
|
460
|
+
exports[`reactAsyncFunctionHookDocs > snapshot — request body only (no path params) 1`] = `
|
|
461
|
+
"# Intrig Async Hooks — Quick Guide
|
|
462
|
+
|
|
463
|
+
## Copy-paste starter (fast lane)
|
|
464
|
+
|
|
465
|
+
### 1) Hook import
|
|
466
|
+
|
|
467
|
+
\`\`\`ts
|
|
468
|
+
import { useCheckPasswordStrengthAsync } from "@intrig/react/security/client";
|
|
469
|
+
\`\`\`
|
|
470
|
+
|
|
471
|
+
### 2) Create an instance
|
|
472
|
+
|
|
473
|
+
\`\`\`ts
|
|
474
|
+
const [checkPasswordStrength, abortCheckPasswordStrength] =
|
|
475
|
+
useCheckPasswordStrengthAsync();
|
|
476
|
+
\`\`\`
|
|
477
|
+
|
|
478
|
+
### 3) Call it (awaitable)
|
|
479
|
+
|
|
480
|
+
\`\`\`ts
|
|
481
|
+
// body?, params? — pass what your endpoint needs (order: body, params)
|
|
482
|
+
await checkPasswordStrength(checkPasswordStrengthRequest);
|
|
483
|
+
\`\`\`
|
|
484
|
+
|
|
485
|
+
Async hooks are for one-off, low-friction calls (e.g., validations, submissions). They return an **awaitable function** plus an **abort** function. No NetworkState.
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## TL;DR (copy–paste)
|
|
490
|
+
|
|
491
|
+
\`\`\`tsx
|
|
492
|
+
import { useCheckPasswordStrengthAsync } from "@intrig/react/security/client";
|
|
493
|
+
import { useCallback, useEffect } from "react";
|
|
494
|
+
|
|
495
|
+
export default function Example() {
|
|
496
|
+
const [checkPasswordStrength, abortCheckPasswordStrength] =
|
|
497
|
+
useCheckPasswordStrengthAsync();
|
|
498
|
+
|
|
499
|
+
const run = useCallback(async () => {
|
|
500
|
+
try {
|
|
501
|
+
const result = await checkPasswordStrength(checkPasswordStrengthRequest);
|
|
502
|
+
// do something with result
|
|
503
|
+
console.log(result);
|
|
504
|
+
} catch (e) {
|
|
505
|
+
// request failed or was aborted
|
|
506
|
+
console.error(e);
|
|
507
|
+
}
|
|
508
|
+
}, [checkPasswordStrength]);
|
|
509
|
+
|
|
510
|
+
// Optional: abort on unmount
|
|
511
|
+
useEffect(() => abortCheckPasswordStrength, [abortCheckPasswordStrength]);
|
|
512
|
+
|
|
513
|
+
return <button onClick={run}>Call</button>;
|
|
514
|
+
}
|
|
515
|
+
\`\`\`
|
|
516
|
+
|
|
517
|
+
### Optional types (if generated by your build)
|
|
518
|
+
|
|
519
|
+
\`\`\`ts
|
|
520
|
+
import type { CheckPasswordStrengthRequest } from "@intrig/react/demo_api/components/schemas/CheckPasswordStrengthRequest";
|
|
521
|
+
import type { CheckPasswordStrengthResponseBody } from "@intrig/react/security/CheckPasswordStrength.response";
|
|
522
|
+
\`\`\`
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## Hook API
|
|
527
|
+
|
|
528
|
+
\`\`\`ts
|
|
529
|
+
// Prefer concrete types if your build emits them:
|
|
530
|
+
// import type { CheckPasswordStrengthResponseBody } from '@intrig/react/security/CheckPasswordStrength.response';
|
|
531
|
+
//
|
|
532
|
+
|
|
533
|
+
type CheckPasswordStrengthData = unknown; // replace with CheckPasswordStrengthResponseBody if generated
|
|
534
|
+
type CheckPasswordStrengthRequest = {
|
|
535
|
+
body?: CheckPasswordStrengthRequest;
|
|
536
|
+
params?: unknown;
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// Signature (shape shown; return type depends on your endpoint)
|
|
540
|
+
declare function useCheckPasswordStrengthAsync(): [
|
|
541
|
+
(
|
|
542
|
+
body?: CheckPasswordStrengthRequest["body"],
|
|
543
|
+
params?: CheckPasswordStrengthRequest["params"],
|
|
544
|
+
) => Promise<CheckPasswordStrengthData>,
|
|
545
|
+
() => void, // abort
|
|
546
|
+
];
|
|
547
|
+
\`\`\`
|
|
548
|
+
|
|
549
|
+
### Why async hooks?
|
|
550
|
+
|
|
551
|
+
- **No state machine:** just \`await\` the result.
|
|
552
|
+
- **Great for validations & submits:** uniqueness checks, field-level checks, updates.
|
|
553
|
+
- **Abortable:** cancel in-flight work on demand.
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## Usage Patterns
|
|
558
|
+
|
|
559
|
+
### 1) Simple try/catch (recommended)
|
|
560
|
+
|
|
561
|
+
\`\`\`tsx
|
|
562
|
+
const [checkPasswordStrength] = useCheckPasswordStrengthAsync();
|
|
563
|
+
|
|
564
|
+
try {
|
|
565
|
+
const res = await checkPasswordStrength(checkPasswordStrengthRequest);
|
|
566
|
+
// use res
|
|
567
|
+
} catch (e) {
|
|
568
|
+
// network error or abort
|
|
569
|
+
}
|
|
570
|
+
\`\`\`
|
|
571
|
+
|
|
572
|
+
<details><summary>Description</summary>
|
|
573
|
+
<p><strong>Use when</strong> you just need the value or an error. Ideal for validators, uniqueness checks, or quick lookups.</p>
|
|
574
|
+
</details>
|
|
575
|
+
|
|
576
|
+
### 2) Abort on unmount (safe cleanup)
|
|
577
|
+
|
|
578
|
+
\`\`\`tsx
|
|
579
|
+
const [checkPasswordStrength, abortCheckPasswordStrength] =
|
|
580
|
+
useCheckPasswordStrengthAsync();
|
|
581
|
+
|
|
582
|
+
useEffect(() => abortCheckPasswordStrength, [abortCheckPasswordStrength]);
|
|
583
|
+
\`\`\`
|
|
584
|
+
|
|
585
|
+
<details><summary>Description</summary>
|
|
586
|
+
<p><strong>Use when</strong> the component may unmount while a request is in-flight (route changes, conditional UI).</p>
|
|
587
|
+
</details>
|
|
588
|
+
|
|
589
|
+
### 3) Debounced validation (e.g., on input change)
|
|
590
|
+
|
|
591
|
+
\`\`\`tsx
|
|
592
|
+
const [checkPasswordStrength, abortCheckPasswordStrength] =
|
|
593
|
+
useCheckPasswordStrengthAsync();
|
|
594
|
+
|
|
595
|
+
const onChange = useMemo(() => {
|
|
596
|
+
let t: any;
|
|
597
|
+
return (checkPasswordStrengthRequest: CheckPasswordStrengthRequest) => {
|
|
598
|
+
clearTimeout(t);
|
|
599
|
+
t = setTimeout(async () => {
|
|
600
|
+
try {
|
|
601
|
+
// Optionally abort before firing a new request
|
|
602
|
+
abortCheckPasswordStrength();
|
|
603
|
+
await checkPasswordStrength(checkPasswordStrengthRequest /* params? */);
|
|
604
|
+
} catch {}
|
|
605
|
+
}, 250);
|
|
606
|
+
};
|
|
607
|
+
}, [checkPasswordStrength, abortCheckPasswordStrength]);
|
|
608
|
+
\`\`\`
|
|
609
|
+
|
|
610
|
+
<details><summary>Description</summary>
|
|
611
|
+
<p><strong>Use when</strong> validating as the user types. Debounce to reduce chatter; consider <code>abortCheckPasswordStrength()</code> before firing a new call.</p>
|
|
612
|
+
</details>
|
|
613
|
+
|
|
614
|
+
### 4) Guard against races (latest-only)
|
|
615
|
+
|
|
616
|
+
\`\`\`tsx
|
|
617
|
+
const [checkPasswordStrength, abortCheckPasswordStrength] =
|
|
618
|
+
useCheckPasswordStrengthAsync();
|
|
619
|
+
|
|
620
|
+
const latestOnly = async () => {
|
|
621
|
+
abortCheckPasswordStrength();
|
|
622
|
+
return checkPasswordStrength(checkPasswordStrengthRequest);
|
|
623
|
+
};
|
|
624
|
+
\`\`\`
|
|
625
|
+
|
|
626
|
+
<details><summary>Description</summary>
|
|
627
|
+
<p><strong>Use when</strong> only the most recent call should win (search suggestions, live filters).</p>
|
|
628
|
+
</details>
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
## Full example
|
|
633
|
+
|
|
634
|
+
\`\`\`tsx
|
|
635
|
+
import { useCheckPasswordStrengthAsync } from "@intrig/react/security/client";
|
|
636
|
+
import { useCallback } from "react";
|
|
637
|
+
|
|
638
|
+
function MyComponent() {
|
|
639
|
+
const [checkPasswordStrength, abortCheckPasswordStrength] =
|
|
640
|
+
useCheckPasswordStrengthAsync();
|
|
641
|
+
|
|
642
|
+
const run = useCallback(async () => {
|
|
643
|
+
try {
|
|
644
|
+
const data = await checkPasswordStrength(checkPasswordStrengthRequest);
|
|
645
|
+
alert(JSON.stringify(data));
|
|
646
|
+
} catch (e) {
|
|
647
|
+
console.error("Call failed/aborted", e);
|
|
648
|
+
}
|
|
649
|
+
}, [checkPasswordStrength]);
|
|
650
|
+
|
|
651
|
+
return (
|
|
652
|
+
<>
|
|
653
|
+
<button onClick={run}>Call remote</button>
|
|
654
|
+
<button onClick={abortCheckPasswordStrength}>Abort</button>
|
|
655
|
+
</>
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
\`\`\`
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## Gotchas & Tips
|
|
663
|
+
|
|
664
|
+
- **No \`NetworkState\`:** async hooks return a Promise, not a state machine.
|
|
665
|
+
- **Abort:** always available; call it to cancel the latest in-flight request.
|
|
666
|
+
- **Errors:** wrap calls with \`try/catch\` to handle network failures or abort errors.
|
|
667
|
+
- **Debounce & throttle:** combine with timers to cut down chatter for typeahead/validators.
|
|
668
|
+
- **Types:** prefer generated \`CheckPasswordStrengthResponseBody\` and \`...Params\` if your build emits them.
|
|
669
|
+
|
|
670
|
+
---
|
|
671
|
+
|
|
672
|
+
## Reference: Minimal cheat sheet
|
|
673
|
+
|
|
674
|
+
\`\`\`ts
|
|
675
|
+
const [fn, abort] = useCheckPasswordStrengthAsync();
|
|
676
|
+
await fn(checkPasswordStrengthRequest);
|
|
677
|
+
abort(); // optional
|
|
678
|
+
\`\`\`
|
|
679
|
+
"
|
|
680
|
+
`;
|
|
681
|
+
|
|
682
|
+
exports[`reactAsyncFunctionHookDocs > snapshot — simple REST descriptor (no body, no path params) 1`] = `
|
|
683
|
+
"# Intrig Async Hooks — Quick Guide
|
|
684
|
+
|
|
685
|
+
## Copy-paste starter (fast lane)
|
|
686
|
+
|
|
687
|
+
### 1) Hook import
|
|
688
|
+
|
|
689
|
+
\`\`\`ts
|
|
690
|
+
import { useValidateUsernameAsync } from "@intrig/react/users/client";
|
|
691
|
+
\`\`\`
|
|
692
|
+
|
|
693
|
+
### 2) Create an instance
|
|
694
|
+
|
|
695
|
+
\`\`\`ts
|
|
696
|
+
const [validateUsername, abortValidateUsername] = useValidateUsernameAsync();
|
|
697
|
+
\`\`\`
|
|
698
|
+
|
|
699
|
+
### 3) Call it (awaitable)
|
|
700
|
+
|
|
701
|
+
\`\`\`ts
|
|
702
|
+
// body?, params? — pass what your endpoint needs (order: body, params)
|
|
703
|
+
await validateUsername();
|
|
704
|
+
\`\`\`
|
|
705
|
+
|
|
706
|
+
Async hooks are for one-off, low-friction calls (e.g., validations, submissions). They return an **awaitable function** plus an **abort** function. No NetworkState.
|
|
707
|
+
|
|
708
|
+
---
|
|
709
|
+
|
|
710
|
+
## TL;DR (copy–paste)
|
|
711
|
+
|
|
712
|
+
\`\`\`tsx
|
|
713
|
+
import { useValidateUsernameAsync } from "@intrig/react/users/client";
|
|
714
|
+
import { useCallback, useEffect } from "react";
|
|
715
|
+
|
|
716
|
+
export default function Example() {
|
|
717
|
+
const [validateUsername, abortValidateUsername] = useValidateUsernameAsync();
|
|
718
|
+
|
|
719
|
+
const run = useCallback(async () => {
|
|
720
|
+
try {
|
|
721
|
+
const result = await validateUsername();
|
|
722
|
+
// do something with result
|
|
723
|
+
console.log(result);
|
|
724
|
+
} catch (e) {
|
|
725
|
+
// request failed or was aborted
|
|
726
|
+
console.error(e);
|
|
727
|
+
}
|
|
728
|
+
}, [validateUsername]);
|
|
729
|
+
|
|
730
|
+
// Optional: abort on unmount
|
|
731
|
+
useEffect(() => abortValidateUsername, [abortValidateUsername]);
|
|
732
|
+
|
|
733
|
+
return <button onClick={run}>Call</button>;
|
|
734
|
+
}
|
|
735
|
+
\`\`\`
|
|
736
|
+
|
|
737
|
+
---
|
|
738
|
+
|
|
739
|
+
## Hook API
|
|
740
|
+
|
|
741
|
+
\`\`\`ts
|
|
742
|
+
// Prefer concrete types if your build emits them:
|
|
743
|
+
// import type { ValidateUsernameResponseBody } from '@intrig/react/users/ValidateUsername.response';
|
|
744
|
+
//
|
|
745
|
+
|
|
746
|
+
type ValidateUsernameData = unknown; // replace with ValidateUsernameResponseBody if generated
|
|
747
|
+
type ValidateUsernameRequest = {
|
|
748
|
+
body?: unknown;
|
|
749
|
+
params?: unknown;
|
|
750
|
+
};
|
|
751
|
+
|
|
752
|
+
// Signature (shape shown; return type depends on your endpoint)
|
|
753
|
+
declare function useValidateUsernameAsync(): [
|
|
754
|
+
(
|
|
755
|
+
body?: ValidateUsernameRequest["body"],
|
|
756
|
+
params?: ValidateUsernameRequest["params"],
|
|
757
|
+
) => Promise<ValidateUsernameData>,
|
|
758
|
+
() => void, // abort
|
|
759
|
+
];
|
|
760
|
+
\`\`\`
|
|
761
|
+
|
|
762
|
+
### Why async hooks?
|
|
763
|
+
|
|
764
|
+
- **No state machine:** just \`await\` the result.
|
|
765
|
+
- **Great for validations & submits:** uniqueness checks, field-level checks, updates.
|
|
766
|
+
- **Abortable:** cancel in-flight work on demand.
|
|
767
|
+
|
|
768
|
+
---
|
|
769
|
+
|
|
770
|
+
## Usage Patterns
|
|
771
|
+
|
|
772
|
+
### 1) Simple try/catch (recommended)
|
|
773
|
+
|
|
774
|
+
\`\`\`tsx
|
|
775
|
+
const [validateUsername] = useValidateUsernameAsync();
|
|
776
|
+
|
|
777
|
+
try {
|
|
778
|
+
const res = await validateUsername();
|
|
779
|
+
// use res
|
|
780
|
+
} catch (e) {
|
|
781
|
+
// network error or abort
|
|
782
|
+
}
|
|
783
|
+
\`\`\`
|
|
784
|
+
|
|
785
|
+
<details><summary>Description</summary>
|
|
786
|
+
<p><strong>Use when</strong> you just need the value or an error. Ideal for validators, uniqueness checks, or quick lookups.</p>
|
|
787
|
+
</details>
|
|
788
|
+
|
|
789
|
+
### 2) Abort on unmount (safe cleanup)
|
|
790
|
+
|
|
791
|
+
\`\`\`tsx
|
|
792
|
+
const [validateUsername, abortValidateUsername] = useValidateUsernameAsync();
|
|
793
|
+
|
|
794
|
+
useEffect(() => abortValidateUsername, [abortValidateUsername]);
|
|
795
|
+
\`\`\`
|
|
796
|
+
|
|
797
|
+
<details><summary>Description</summary>
|
|
798
|
+
<p><strong>Use when</strong> the component may unmount while a request is in-flight (route changes, conditional UI).</p>
|
|
799
|
+
</details>
|
|
800
|
+
|
|
801
|
+
### 3) Debounced validation (e.g., on input change)
|
|
802
|
+
|
|
803
|
+
\`\`\`tsx
|
|
804
|
+
const [validateUsername, abortValidateUsername] = useValidateUsernameAsync();
|
|
805
|
+
|
|
806
|
+
const onChange = useMemo(() => {
|
|
807
|
+
let t: any;
|
|
808
|
+
return (value: string) => {
|
|
809
|
+
clearTimeout(t);
|
|
810
|
+
t = setTimeout(async () => {
|
|
811
|
+
try {
|
|
812
|
+
// Optionally abort before firing a new request
|
|
813
|
+
abortValidateUsername();
|
|
814
|
+
await validateUsername(/* body from value */, /* params? */);
|
|
815
|
+
} catch {}
|
|
816
|
+
}, 250);
|
|
817
|
+
};
|
|
818
|
+
}, [validateUsername, abortValidateUsername]);
|
|
819
|
+
\`\`\`
|
|
820
|
+
|
|
821
|
+
<details><summary>Description</summary>
|
|
822
|
+
<p><strong>Use when</strong> validating as the user types. Debounce to reduce chatter; consider <code>abortValidateUsername()</code> before firing a new call.</p>
|
|
823
|
+
</details>
|
|
824
|
+
|
|
825
|
+
### 4) Guard against races (latest-only)
|
|
826
|
+
|
|
827
|
+
\`\`\`tsx
|
|
828
|
+
const [validateUsername, abortValidateUsername] = useValidateUsernameAsync();
|
|
829
|
+
|
|
830
|
+
const latestOnly = async () => {
|
|
831
|
+
abortValidateUsername();
|
|
832
|
+
return validateUsername();
|
|
833
|
+
};
|
|
834
|
+
\`\`\`
|
|
835
|
+
|
|
836
|
+
<details><summary>Description</summary>
|
|
837
|
+
<p><strong>Use when</strong> only the most recent call should win (search suggestions, live filters).</p>
|
|
838
|
+
</details>
|
|
839
|
+
|
|
840
|
+
---
|
|
841
|
+
|
|
842
|
+
## Full example
|
|
843
|
+
|
|
844
|
+
\`\`\`tsx
|
|
845
|
+
import { useValidateUsernameAsync } from "@intrig/react/users/client";
|
|
846
|
+
import { useCallback } from "react";
|
|
847
|
+
|
|
848
|
+
function MyComponent() {
|
|
849
|
+
const [validateUsername, abortValidateUsername] = useValidateUsernameAsync();
|
|
850
|
+
|
|
851
|
+
const run = useCallback(async () => {
|
|
852
|
+
try {
|
|
853
|
+
const data = await validateUsername();
|
|
854
|
+
alert(JSON.stringify(data));
|
|
855
|
+
} catch (e) {
|
|
856
|
+
console.error("Call failed/aborted", e);
|
|
857
|
+
}
|
|
858
|
+
}, [validateUsername]);
|
|
859
|
+
|
|
860
|
+
return (
|
|
861
|
+
<>
|
|
862
|
+
<button onClick={run}>Call remote</button>
|
|
863
|
+
<button onClick={abortValidateUsername}>Abort</button>
|
|
864
|
+
</>
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
\`\`\`
|
|
868
|
+
|
|
869
|
+
---
|
|
870
|
+
|
|
871
|
+
## Gotchas & Tips
|
|
872
|
+
|
|
873
|
+
- **No \`NetworkState\`:** async hooks return a Promise, not a state machine.
|
|
874
|
+
- **Abort:** always available; call it to cancel the latest in-flight request.
|
|
875
|
+
- **Errors:** wrap calls with \`try/catch\` to handle network failures or abort errors.
|
|
876
|
+
- **Debounce & throttle:** combine with timers to cut down chatter for typeahead/validators.
|
|
877
|
+
- **Types:** prefer generated \`ValidateUsernameResponseBody\` and \`...Params\` if your build emits them.
|
|
878
|
+
|
|
879
|
+
---
|
|
880
|
+
|
|
881
|
+
## Reference: Minimal cheat sheet
|
|
882
|
+
|
|
883
|
+
\`\`\`ts
|
|
884
|
+
const [fn, abort] = useValidateUsernameAsync();
|
|
885
|
+
await fn();
|
|
886
|
+
abort(); // optional
|
|
887
|
+
\`\`\`
|
|
888
|
+
"
|
|
889
|
+
`;
|