@intrig/plugin-react 0.0.1 → 0.0.2-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/index.cjs +4260 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +4235 -0
  4. package/package.json +6 -3
  5. package/.swcrc +0 -29
  6. package/README.md +0 -7
  7. package/eslint.config.mjs +0 -19
  8. package/project.json +0 -29
  9. package/rollup.config.cjs +0 -54
  10. package/rollup.config.mjs +0 -33
  11. package/src/index.ts +0 -2
  12. package/src/lib/code-generator.ts +0 -79
  13. package/src/lib/get-endpoint-documentation.ts +0 -35
  14. package/src/lib/get-schema-documentation.ts +0 -11
  15. package/src/lib/internal-types.ts +0 -15
  16. package/src/lib/plugin-react.ts +0 -22
  17. package/src/lib/templates/context.template.ts +0 -74
  18. package/src/lib/templates/docs/__snapshots__/async-hook.spec.ts.snap +0 -889
  19. package/src/lib/templates/docs/__snapshots__/download-hook.spec.ts.snap +0 -1445
  20. package/src/lib/templates/docs/__snapshots__/react-hook.spec.ts.snap +0 -1371
  21. package/src/lib/templates/docs/__snapshots__/sse-hook.spec.ts.snap +0 -2008
  22. package/src/lib/templates/docs/async-hook.spec.ts +0 -92
  23. package/src/lib/templates/docs/async-hook.ts +0 -226
  24. package/src/lib/templates/docs/download-hook.spec.ts +0 -182
  25. package/src/lib/templates/docs/download-hook.ts +0 -170
  26. package/src/lib/templates/docs/react-hook.spec.ts +0 -97
  27. package/src/lib/templates/docs/react-hook.ts +0 -323
  28. package/src/lib/templates/docs/schema.ts +0 -105
  29. package/src/lib/templates/docs/sse-hook.spec.ts +0 -207
  30. package/src/lib/templates/docs/sse-hook.ts +0 -221
  31. package/src/lib/templates/extra.template.ts +0 -198
  32. package/src/lib/templates/index.template.ts +0 -14
  33. package/src/lib/templates/intrigMiddleware.template.ts +0 -21
  34. package/src/lib/templates/logger.template.ts +0 -67
  35. package/src/lib/templates/media-type-utils.template.ts +0 -191
  36. package/src/lib/templates/network-state.template.ts +0 -702
  37. package/src/lib/templates/packageJson.template.ts +0 -63
  38. package/src/lib/templates/provider/__tests__/provider-templates.spec.ts +0 -209
  39. package/src/lib/templates/provider/axios-config.template.ts +0 -49
  40. package/src/lib/templates/provider/hooks.template.ts +0 -240
  41. package/src/lib/templates/provider/interfaces.template.ts +0 -72
  42. package/src/lib/templates/provider/intrig-provider-stub.template.ts +0 -73
  43. package/src/lib/templates/provider/intrig-provider.template.ts +0 -185
  44. package/src/lib/templates/provider/main.template.ts +0 -48
  45. package/src/lib/templates/provider/reducer.template.ts +0 -50
  46. package/src/lib/templates/provider/status-trap.template.ts +0 -80
  47. package/src/lib/templates/provider.template.ts +0 -698
  48. package/src/lib/templates/source/controller/method/asyncFunctionHook.template.ts +0 -196
  49. package/src/lib/templates/source/controller/method/clientIndex.template.ts +0 -38
  50. package/src/lib/templates/source/controller/method/download.template.ts +0 -256
  51. package/src/lib/templates/source/controller/method/params.template.ts +0 -31
  52. package/src/lib/templates/source/controller/method/requestHook.template.ts +0 -220
  53. package/src/lib/templates/source/type/typeTemplate.ts +0 -257
  54. package/src/lib/templates/swcrc.template.ts +0 -25
  55. package/src/lib/templates/tsconfig.template.ts +0 -37
  56. package/src/lib/templates/type-utils.template.ts +0 -28
  57. package/tsconfig.json +0 -13
  58. package/tsconfig.lib.json +0 -20
@@ -1,97 +0,0 @@
1
- import { reactHookDocs } from './react-hook';
2
-
3
- // The descriptor type is imported in the implementation from "@intrig/plugin-sdk".
4
- // For the test we can just use the plain object shape to avoid tight coupling.
5
-
6
- describe('reactHookDocs', () => {
7
- it('generates markdown that matches snapshot for a simple REST descriptor (no body, no path params)', async () => {
8
- const descriptor = {
9
- id: '1',
10
- name: 'getUser',
11
- type: 'rest' as const,
12
- source: 'demo_api',
13
- path: 'users',
14
- data: {
15
- method: 'GET',
16
- paths: ['/api/users'],
17
- operationId: 'getUser',
18
- // no requestBody
19
- // no variables
20
- },
21
- };
22
-
23
- const result = await reactHookDocs(descriptor as any);
24
-
25
- expect(result.path).toBe('react-hook.md');
26
-
27
- const md = result.content;
28
-
29
- expect(md).toMatchSnapshot();
30
- });
31
-
32
- it('snapshot — request body only (no path params)', async () => {
33
- const descriptor = {
34
- id: '2',
35
- name: 'createUser',
36
- type: 'rest' as const,
37
- source: 'demo_api',
38
- path: 'users',
39
- data: {
40
- method: 'POST',
41
- paths: ['/api/users'],
42
- operationId: 'createUser',
43
- requestBody: 'CreateUserRequest',
44
- // no variables
45
- },
46
- };
47
-
48
- const result = await reactHookDocs(descriptor as any);
49
- expect(result.path).toBe('react-hook.md');
50
- expect(result.content).toMatchSnapshot();
51
- });
52
-
53
- it('snapshot — path params only (no request body)', async () => {
54
- const descriptor = {
55
- id: '3',
56
- name: 'getUserById',
57
- type: 'rest' as const,
58
- source: 'demo_api',
59
- path: 'users/{id}',
60
- data: {
61
- method: 'GET',
62
- paths: ['/api/users/{id}'],
63
- operationId: 'getUserById',
64
- variables: [
65
- { name: 'id', in: 'path', ref: '#/components/schemas/Id' },
66
- ],
67
- },
68
- };
69
-
70
- const result = await reactHookDocs(descriptor as any);
71
- expect(result.path).toBe('react-hook.md');
72
- expect(result.content).toMatchSnapshot();
73
- });
74
-
75
- it('snapshot — request body and path params', async () => {
76
- const descriptor = {
77
- id: '4',
78
- name: 'updateUser',
79
- type: 'rest' as const,
80
- source: 'demo_api',
81
- path: 'users/{id}',
82
- data: {
83
- method: 'PUT',
84
- paths: ['/api/users/{id}'],
85
- operationId: 'updateUser',
86
- requestBody: 'UpdateUserRequest',
87
- variables: [
88
- { name: 'id', in: 'PATH', ref: '#/components/schemas/Id' },
89
- ],
90
- },
91
- };
92
-
93
- const result = await reactHookDocs(descriptor as any);
94
- expect(result.path).toBe('react-hook.md');
95
- expect(result.content).toMatchSnapshot();
96
- });
97
- });
@@ -1,323 +0,0 @@
1
- import { camelCase, mdLiteral, pascalCase, ResourceDescriptor, RestData } from "@intrig/plugin-sdk"
2
-
3
- export function reactHookDocs(descriptor: ResourceDescriptor<RestData>) {
4
- const md = mdLiteral('react-hook.md')
5
-
6
- // ===== Derived names (preserve these) =====
7
- const hasPathParams = (descriptor.data.variables ?? []).some(
8
- (v: any) => v.in?.toUpperCase() === 'PATH',
9
- )
10
-
11
- const actionName = camelCase(descriptor.name) // e.g. getUser
12
- const respVar = `${actionName}Resp` // e.g. getUserResp
13
- const dataVar = `${actionName}Data` // e.g. getUserData
14
- const clearName = `clear${pascalCase(descriptor.name)}` // e.g. clearGetUser
15
-
16
- const requestBodyVar = descriptor.data.requestBody
17
- ? camelCase(descriptor.data.requestBody)
18
- : undefined
19
- const requestBodyType = descriptor.data.requestBody
20
- ? pascalCase(descriptor.data.requestBody)
21
- : undefined
22
-
23
- const paramsVar = hasPathParams ? `${actionName}Params` : undefined // e.g. getUserParams
24
- const paramsType = hasPathParams ? `${pascalCase(descriptor.name)}Params` : undefined // e.g. GetUserParams
25
-
26
- const responseTypeName = `${pascalCase(descriptor.name)}ResponseBody`
27
-
28
- return md`
29
- # Intrig React Hooks — Quick Guide
30
-
31
- ## Copy-paste starter (fast lane)
32
-
33
- ### 1) Hook import
34
- ${"```ts"}
35
- import { use${pascalCase(descriptor.name)} } from '@intrig/react/${descriptor.path}/client';
36
- ${"```"}
37
-
38
- ### 2) Utility guards
39
- ${"```ts"}
40
- import { isPending, isError, isSuccess } from '@intrig/react';
41
- ${"```"}
42
-
43
- ### 3) Hook instance (auto-clear on unmount)
44
- ${"```ts"}
45
- const [${respVar}, ${actionName}] = use${pascalCase(descriptor.name)}({ clearOnUnmount: true });
46
- ${"```"}
47
-
48
- Intrig stateful hooks expose a **NetworkState** plus **actions** to fetch / clear.
49
- Use this when you want a cached, reusable result tied to a global store.
50
-
51
- ---
52
-
53
- ## TL;DR (copy–paste)
54
- ${"```tsx"}
55
- import { use${pascalCase(descriptor.name)} } from '@intrig/react/${descriptor.path}/client';
56
- import { isPending, isError, isSuccess } from '@intrig/react';
57
- import { useEffect, useMemo } from 'react';
58
-
59
- export default function Example() {
60
- const [${respVar}, ${actionName}] = use${pascalCase(descriptor.name)}({ clearOnUnmount: true });
61
-
62
- useEffect(() => {
63
- ${actionName}(${[requestBodyVar, paramsVar ?? '{}'].filter(Boolean).join(', ')});
64
- }, [${[''+actionName, requestBodyVar, paramsVar].filter(Boolean).join(', ')}]);
65
-
66
- const ${dataVar} = useMemo(
67
- () => (isSuccess(${respVar}) ? ${respVar}.data : undefined),
68
- [${respVar}]
69
- );
70
-
71
- if (isPending(${respVar})) return <>Loading…</>;
72
- if (isError(${respVar})) return <>Error: {String(${respVar}.error)}</>;
73
- return <pre>{JSON.stringify(${dataVar}, null, 2)}</pre>;
74
- }
75
- ${"```"}
76
-
77
- ${requestBodyType || paramsType ? `### Optional types (if generated by your build)
78
- ${"```ts"}
79
- ${requestBodyType ? `import type { ${requestBodyType} } from '@intrig/react/${descriptor.source}/components/schemas/${requestBodyType}';
80
- ` : ''}${paramsType ? `import type { ${paramsType} } from '@intrig/react/${descriptor.path}/${pascalCase(descriptor.name)}.params';
81
- ` : ''}// Prefer the concrete response type:
82
- import type { ${responseTypeName} } from '@intrig/react/${descriptor.path}/${pascalCase(descriptor.name)}.response';
83
- ${"```"}
84
- ` : ''}
85
-
86
- ---
87
-
88
- ## Hook API
89
- ${"```ts"}
90
- // Options are consistent across hooks.
91
- type UseHookOptions = {
92
- /** Execute once after mount with provided params/body (if required). */
93
- fetchOnMount?: boolean;
94
- /** Reset the state on unmount (recommended). */
95
- clearOnUnmount?: boolean;
96
- /** Distinguish multiple instances of the same hook. */
97
- key?: string;
98
- /** Initial path params for endpoints that require them. */
99
- params?: ${paramsType ?? 'unknown'};
100
- /** Initial request body (for POST/PUT/etc.). */
101
- body?: ${requestBodyType ?? 'unknown'};
102
- };
103
-
104
- // Prefer concrete types if your build emits them:
105
- // import type { ${responseTypeName} } from '@intrig/react/${descriptor.path}/${pascalCase(descriptor.name)}.response';
106
-
107
- type ${pascalCase(descriptor.name)}Data = ${'typeof '+responseTypeName !== 'undefined' ? responseTypeName : 'unknown'}; // replace with ${responseTypeName} if generated
108
- type ${pascalCase(descriptor.name)}Request = { params?: ${paramsType ?? 'unknown'}; body?: ${requestBodyType ?? 'unknown'}; };
109
-
110
- // Signature (shape shown; concrete generics vary per generated hook)
111
- declare function use${pascalCase(descriptor.name)}(options?: UseHookOptions): [
112
- NetworkState<${pascalCase(descriptor.name)}Data>,
113
- (req: ${pascalCase(descriptor.name)}Request) => void,
114
- () => void
115
- ];
116
- ${"```"}
117
-
118
- ### NetworkState & guards
119
- ${"```ts"}
120
- import { isPending, isError, isSuccess } from '@intrig/react';
121
- ${"```"}
122
-
123
- ---
124
-
125
- ## Conceptual model (Stateful = single source of truth)
126
- - Lives in a shared store keyed by \`key\` + request signature.
127
- - Best for **read** endpoints you want to **reuse** or keep **warm** (lists, details, search).
128
- - Lifecycle helpers:
129
- - \`fetchOnMount\` to kick off automatically.
130
- - \`clearOnUnmount\` to clean up (recommended default).
131
- - \`key\` to isolate multiple independent instances.
132
-
133
- ---
134
-
135
- ## Usage patterns
136
-
137
- ### 1) Controlled (most explicit)
138
- ${"```tsx"}
139
- const [${respVar}, ${actionName}, ${clearName}] = use${pascalCase(descriptor.name)}();
140
-
141
- useEffect(() => {
142
- ${actionName}(${[requestBodyVar, paramsVar ?? '{}'].filter(Boolean).join(', ')});
143
- return ${clearName}; // optional cleanup
144
- }, [${[''+actionName, clearName].join(', ')}]);
145
- ${"```"}
146
-
147
- <details><summary>Description</summary>
148
- <p><strong>Use when</strong> you need explicit control over when a request fires, what params/body it uses, and when to clean up. Ideal for search forms, pagination, conditional fetches.</p>
149
- </details>
150
-
151
- ### 2) Lifecycle-bound (shorthand)
152
- ${"```tsx"}
153
- const [${respVar}] = use${pascalCase(descriptor.name)}({
154
- fetchOnMount: true,
155
- clearOnUnmount: true,
156
- ${requestBodyType ? `body: ${requestBodyVar},` : ''} ${paramsType ? `params: ${paramsVar ?? '{}'},` : 'params: {},'}
157
- });
158
- ${"```"}
159
-
160
- <details><summary>Description</summary>
161
- <p><strong>Use when</strong> the data should follow the component lifecycle: fetch once on mount, reset on unmount.</p>
162
- </details>
163
-
164
- ### 3) Passive observer (render when data arrives)
165
- ${"```tsx"}
166
- const [${respVar}] = use${pascalCase(descriptor.name)}();
167
- return isSuccess(${respVar}) ? <>{String(${respVar}.data)}</> : null;
168
- ${"```"}
169
-
170
- <details><summary>Description</summary>
171
- <p><strong>Use when</strong> another part of the app triggers the fetch and this component only reads the state.</p>
172
- </details>
173
-
174
- ### 4) Keep previous success while refetching (sticky)
175
- ${"```tsx"}
176
- const [${dataVar}, set${pascalCase(descriptor.name)}Data] = useState<any>();
177
- const [${respVar}, ${actionName}] = use${pascalCase(descriptor.name)}();
178
-
179
- useEffect(() => {
180
- if (isSuccess(${respVar})) set${pascalCase(descriptor.name)}Data(${respVar}.data);
181
- }, [${respVar}]);
182
-
183
- return (
184
- <>
185
- {isPending(${respVar}) && ${dataVar} ? <div>Refreshing…</div> : null}
186
- <pre>{JSON.stringify(isSuccess(${respVar}) ? ${respVar}.data : ${dataVar}, null, 2)}</pre>
187
- </>
188
- );
189
- ${"```"}
190
-
191
- <details><summary>Description</summary>
192
- <p><strong>Use when</strong> you want SWR-like UX without flicker.</p>
193
- </details>
194
-
195
- ### 5) Multiple instances of the same hook (isolate with \`key\`)
196
- ${"```tsx"}
197
- const a = use${pascalCase(descriptor.name)}({ key: 'A', fetchOnMount: true, ${paramsType ? `params: ${paramsVar ?? '{}'} ` : 'params: {}'} });
198
- const b = use${pascalCase(descriptor.name)}({ key: 'B', fetchOnMount: true, ${paramsType ? `params: ${paramsVar ?? '{}'} ` : 'params: {}'} });
199
- ${"```"}
200
-
201
- <details><summary>Description</summary>
202
- <p>Use unique keys to prevent state collisions.</p>
203
- </details>
204
-
205
- ---
206
-
207
- ## Before / After mini-migrations
208
-
209
- ### If you mistakenly used Stateful for a simple submit → switch to Async
210
- ${"```diff"}
211
- - const [${respVar}, ${actionName}] = use${pascalCase(descriptor.name)}();
212
- - ${actionName}(${[requestBodyVar, paramsVar ?? '{}'].filter(Boolean).join(', ')});
213
- + const [fn] = use${pascalCase(descriptor.name)}Async();
214
- + await fn(${[requestBodyVar, paramsVar].filter(Boolean).join(', ')});
215
- ${"```"}
216
-
217
- ### If you started with Async but need to read later in another component → Stateful
218
- ${"```diff"}
219
- - const [fn] = use${pascalCase(descriptor.name)}Async();
220
- - const data = await fn(${[requestBodyVar, paramsVar].filter(Boolean).join(', ')});
221
- + const [${respVar}, ${actionName}] = use${pascalCase(descriptor.name)}({ fetchOnMount: true, clearOnUnmount: true, ${paramsType ? `params: ${paramsVar ?? '{}'},` : 'params: {},'} ${requestBodyType ? `body: ${requestBodyVar}` : ''} });
222
- + // read from ${respVar} anywhere with use${pascalCase(descriptor.name)}()
223
- ${"```"}
224
-
225
- ---
226
-
227
- ## Anti-patterns
228
- <details><summary>Don’t use Stateful for field validations or a one-off submit</summary>
229
- Use the Async variant instead: \`const [fn] = use${pascalCase(descriptor.name)}Async()\`.
230
- </details>
231
- <details><summary>Don’t use Async for long-lived lists or detail views</summary>
232
- Use Stateful so other components can read the same data and you can avoid refetch churn.
233
- </details>
234
- <details><summary>Don’t forget required \`params\` when using \`fetchOnMount\`</summary>
235
- Provide \`params\` (and \`body\` if applicable) or switch to the controlled pattern.
236
- </details>
237
- <details><summary>Rendering the same hook twice without a \`key\`</summary>
238
- If they should be independent, add a unique \`key\`.
239
- </details>
240
-
241
- ---
242
-
243
- ## Error & UX guidance
244
- - **Loading:** early return or inline spinner. Prefer **sticky data** to avoid blanking content.
245
- - **Errors:** show a banner or inline errors depending on UX; keep previous good state if possible.
246
- - **Cleanup:** prefer \`clearOnUnmount: true\` as the default.
247
-
248
- ---
249
-
250
- ## Concurrency patterns
251
- - **Refresh:** call the action again; combine with sticky data for smooth UX.
252
- - **Dedupe:** isolate instances with \`key\`.
253
- - **Parallel:** render two keyed instances; don’t share the same key.
254
-
255
- ---
256
-
257
- ## Full examples
258
-
259
- ### Short format (lifecycle-bound)
260
- ${"```tsx"}
261
- import { use${pascalCase(descriptor.name)} } from '@intrig/react/${descriptor.path}/client';
262
- import { isPending, isError, isSuccess } from '@intrig/react';
263
- import { useMemo } from 'react';
264
-
265
- function ShortExample() {
266
- const [${respVar}] = use${pascalCase(descriptor.name)}({
267
- fetchOnMount: true,
268
- clearOnUnmount: true,
269
- ${requestBodyType ? `body: ${requestBodyVar},` : ''} ${paramsType ? `params: ${paramsVar ?? '{}'},` : 'params: {},'}
270
- });
271
-
272
- const ${dataVar} = useMemo(() => (isSuccess(${respVar}) ? ${respVar}.data : undefined), [${respVar}]);
273
-
274
- if (isPending(${respVar})) return <>Loading…</>;
275
- if (isError(${respVar})) return <>Error: {String(${respVar}.error)}</>;
276
- return <pre>{JSON.stringify(${dataVar}, null, 2)}</pre>;
277
- }
278
- ${"```"}
279
-
280
- <details><summary>Description</summary>
281
- <p>Compact lifecycle-bound approach. Great for read-only pages that load once and clean up on unmount.</p>
282
- </details>
283
-
284
- ### Controlled format (explicit actions)
285
- ${"```tsx"}
286
- import { use${pascalCase(descriptor.name)} } from '@intrig/react/${descriptor.path}/client';
287
- import { isPending, isError, isSuccess } from '@intrig/react';
288
- import { useEffect, useMemo } from 'react';
289
-
290
- function ControlledExample() {
291
- const [${respVar}, ${actionName}, ${clearName}] = use${pascalCase(descriptor.name)}();
292
-
293
- useEffect(() => {
294
- ${actionName}(${[requestBodyVar, paramsVar ?? '{}'].filter(Boolean).join(', ')});
295
- return ${clearName};
296
- }, [${[''+actionName, clearName].join(', ')}]);
297
-
298
- const ${dataVar} = useMemo(() => (isSuccess(${respVar}) ? ${respVar}.data : undefined), [${respVar}]);
299
-
300
- if (isPending(${respVar})) return <>Loading…</>;
301
- if (isError(${respVar})) return <>An error occurred: {String(${respVar}.error)}</>;
302
- return <pre>{JSON.stringify(${dataVar}, null, 2)}</pre>;
303
- }
304
- ${"```"}
305
-
306
- ---
307
-
308
- ## Gotchas & Tips
309
- - Prefer **\`clearOnUnmount: true\`** in most components.
310
- - Use **\`key\`** for multiple independent instances.
311
- - Memoize derived values with **\`useMemo\`** to avoid churn.
312
- - Inline indicators keep the rest of the page interactive.
313
-
314
- ---
315
-
316
- ## Reference: State helpers
317
- ${"```ts"}
318
- if (isPending(${respVar})) { /* show spinner */ }
319
- if (isError(${respVar})) { /* show error */ }
320
- if (isSuccess(${respVar})) { /* read ${respVar}.data */ }
321
- ${"```"}
322
- `
323
- }
@@ -1,105 +0,0 @@
1
- import { mdLiteral, ResourceDescriptor, Schema, typescript} from "@intrig/plugin-sdk"
2
- import {openApiSchemaToZod} from '../source/type/typeTemplate.js'
3
- import path from "path";
4
-
5
- /**
6
- * Schema documentation tab builders for React binding.
7
- * We keep a small, composable API similar to other docs templates.
8
- */
9
-
10
- export async function schemaTypescriptDoc(result: ResourceDescriptor<Schema>) {
11
- const md = mdLiteral('schema-typescript.md')
12
- const name = result.data.name
13
- const source = result.source
14
-
15
- const {tsType} = openApiSchemaToZod(result.data.schema);
16
-
17
- const ts = typescript(path.resolve('src', source, 'temp', name, `${name}.ts`))
18
-
19
- const importContent = await ts`
20
- import type { ${name} } from '@intrig/react/${source}/components/schemas/${name}';
21
- `;
22
-
23
- const codeContent = await ts`
24
- export type ${name} = ${tsType};
25
- `
26
-
27
- return md`
28
- # Typescript Type
29
- Use this TypeScript type anywhere you need static typing for this object shape in your app code: component props, function params/returns, reducers, and local state in .ts/.tsx files.
30
-
31
- ## Import
32
- ${'```ts'}
33
- ${importContent}
34
- ${'```'}
35
-
36
- ## Definition
37
- ${'```ts'}
38
- ${codeContent}
39
- ${'```'}
40
- `
41
- }
42
-
43
- export async function schemaJsonSchemaDoc(result: ResourceDescriptor<Schema>) {
44
- const md = mdLiteral('schema-json.md')
45
- const name = result.data.name
46
- const source = result.source
47
-
48
- const ts = typescript(path.resolve('src', source, 'temp', name, `${name}.ts`))
49
-
50
- const importContent = await ts`
51
- import { ${name}_jsonschema } from '@intrig/react/${source}/components/schemas/${name}';
52
- `;
53
-
54
- const codeContent = await ts`
55
- export const ${name}_jsonschema = ${JSON.stringify(result.data.schema, null, 2) ?? "{}"};
56
- `
57
-
58
- return md`
59
- # JSON Schema
60
- Use this JSON Schema with tools that consume JSON Schema: UI form builders (e.g. react-jsonschema-form), validators (AJV, validators in backends), and generators.
61
-
62
- ## Import
63
- ${'```ts'}
64
- ${importContent}
65
- ${'```'}
66
-
67
- ## Definition
68
- ${'```ts'}
69
- ${codeContent}
70
- ${'```'}
71
- `
72
- }
73
-
74
- export async function schemaZodSchemaDoc(result: ResourceDescriptor<Schema>) {
75
- const md = mdLiteral('schema-zod.md')
76
- const name = result.data.name
77
- const source = result.source
78
-
79
- const {zodSchema} = openApiSchemaToZod(result.data.schema);
80
-
81
- const ts = typescript(path.resolve('src', source, 'temp', name, `${name}.ts`))
82
-
83
- const importContent = await ts`
84
- import { ${name}Schema } from '@intrig/react/${source}/components/schemas/${name}';
85
- `;
86
-
87
- const codeContent = await ts`
88
- export const ${name}Schema = ${zodSchema};
89
- `
90
-
91
- return md`
92
- # Zod Schema
93
- Use this Zod schema for runtime validation and parsing: form validation, client/server payload guards, and safe transformations before using or storing data.
94
-
95
- ## Import
96
- ${'```ts'}
97
- ${importContent}
98
- ${'```'}
99
-
100
- ## Definition
101
- ${'```ts'}
102
- ${codeContent}
103
- ${'```'}
104
- `
105
- }