@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.
- package/dist/index.cjs +4260 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4235 -0
- package/package.json +6 -3
- package/.swcrc +0 -29
- package/README.md +0 -7
- package/eslint.config.mjs +0 -19
- package/project.json +0 -29
- package/rollup.config.cjs +0 -54
- package/rollup.config.mjs +0 -33
- package/src/index.ts +0 -2
- package/src/lib/code-generator.ts +0 -79
- package/src/lib/get-endpoint-documentation.ts +0 -35
- package/src/lib/get-schema-documentation.ts +0 -11
- package/src/lib/internal-types.ts +0 -15
- package/src/lib/plugin-react.ts +0 -22
- package/src/lib/templates/context.template.ts +0 -74
- package/src/lib/templates/docs/__snapshots__/async-hook.spec.ts.snap +0 -889
- package/src/lib/templates/docs/__snapshots__/download-hook.spec.ts.snap +0 -1445
- package/src/lib/templates/docs/__snapshots__/react-hook.spec.ts.snap +0 -1371
- package/src/lib/templates/docs/__snapshots__/sse-hook.spec.ts.snap +0 -2008
- package/src/lib/templates/docs/async-hook.spec.ts +0 -92
- package/src/lib/templates/docs/async-hook.ts +0 -226
- package/src/lib/templates/docs/download-hook.spec.ts +0 -182
- package/src/lib/templates/docs/download-hook.ts +0 -170
- package/src/lib/templates/docs/react-hook.spec.ts +0 -97
- package/src/lib/templates/docs/react-hook.ts +0 -323
- package/src/lib/templates/docs/schema.ts +0 -105
- package/src/lib/templates/docs/sse-hook.spec.ts +0 -207
- package/src/lib/templates/docs/sse-hook.ts +0 -221
- package/src/lib/templates/extra.template.ts +0 -198
- package/src/lib/templates/index.template.ts +0 -14
- package/src/lib/templates/intrigMiddleware.template.ts +0 -21
- package/src/lib/templates/logger.template.ts +0 -67
- package/src/lib/templates/media-type-utils.template.ts +0 -191
- package/src/lib/templates/network-state.template.ts +0 -702
- package/src/lib/templates/packageJson.template.ts +0 -63
- package/src/lib/templates/provider/__tests__/provider-templates.spec.ts +0 -209
- package/src/lib/templates/provider/axios-config.template.ts +0 -49
- package/src/lib/templates/provider/hooks.template.ts +0 -240
- package/src/lib/templates/provider/interfaces.template.ts +0 -72
- package/src/lib/templates/provider/intrig-provider-stub.template.ts +0 -73
- package/src/lib/templates/provider/intrig-provider.template.ts +0 -185
- package/src/lib/templates/provider/main.template.ts +0 -48
- package/src/lib/templates/provider/reducer.template.ts +0 -50
- package/src/lib/templates/provider/status-trap.template.ts +0 -80
- package/src/lib/templates/provider.template.ts +0 -698
- package/src/lib/templates/source/controller/method/asyncFunctionHook.template.ts +0 -196
- package/src/lib/templates/source/controller/method/clientIndex.template.ts +0 -38
- package/src/lib/templates/source/controller/method/download.template.ts +0 -256
- package/src/lib/templates/source/controller/method/params.template.ts +0 -31
- package/src/lib/templates/source/controller/method/requestHook.template.ts +0 -220
- package/src/lib/templates/source/type/typeTemplate.ts +0 -257
- package/src/lib/templates/swcrc.template.ts +0 -25
- package/src/lib/templates/tsconfig.template.ts +0 -37
- package/src/lib/templates/type-utils.template.ts +0 -28
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -20
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
camelCase,
|
|
3
|
-
generatePostfix,
|
|
4
|
-
pascalCase, ResourceDescriptor, RestData,
|
|
5
|
-
typescript,
|
|
6
|
-
Variable
|
|
7
|
-
} from "@intrig/plugin-sdk";
|
|
8
|
-
import * as path from 'path';
|
|
9
|
-
import {InternalGeneratorContext} from "../../../../internal-types.js";
|
|
10
|
-
|
|
11
|
-
function extractHookShapeAndOptionsShape(response: string | undefined, requestBody: string | undefined, imports: Set<string>) {
|
|
12
|
-
if (response) {
|
|
13
|
-
if (requestBody) {
|
|
14
|
-
imports.add(`import { BinaryFunctionHook, BinaryHookOptions } from "@intrig/react"`);
|
|
15
|
-
return {
|
|
16
|
-
hookShape: `BinaryFunctionHook<Params, RequestBody, Response>`,
|
|
17
|
-
optionsShape: `BinaryHookOptions<Params, RequestBody>`
|
|
18
|
-
};
|
|
19
|
-
} else {
|
|
20
|
-
imports.add(`import { UnaryFunctionHook, UnaryHookOptions } from "@intrig/react"`);
|
|
21
|
-
return {
|
|
22
|
-
hookShape: `UnaryFunctionHook<Params, Response>`,
|
|
23
|
-
optionsShape: `UnaryHookOptions<Params>`
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
} else {
|
|
27
|
-
if (requestBody) {
|
|
28
|
-
imports.add(`import { BinaryProduceHook, BinaryHookOptions } from "@intrig/react"`);
|
|
29
|
-
return {
|
|
30
|
-
hookShape: `BinaryProduceHook<Params, RequestBody>`,
|
|
31
|
-
optionsShape: `BinaryHookOptions<Params, RequestBody>`
|
|
32
|
-
};
|
|
33
|
-
} else {
|
|
34
|
-
imports.add(`import { UnaryProduceHook, UnaryHookOptions } from "@intrig/react"`);
|
|
35
|
-
return {
|
|
36
|
-
hookShape: `UnaryProduceHook<Params>`,
|
|
37
|
-
optionsShape: `UnaryHookOptions<Params>`
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function extractParamDeconstruction(variables: Variable[], requestBody?: string) {
|
|
44
|
-
const isParamMandatory = variables?.some(a => a.in === 'path') || false;
|
|
45
|
-
|
|
46
|
-
if (requestBody) {
|
|
47
|
-
if (isParamMandatory) {
|
|
48
|
-
return {
|
|
49
|
-
paramExpression: 'data, p',
|
|
50
|
-
paramType: 'data: RequestBody, params: Params'
|
|
51
|
-
}
|
|
52
|
-
} else {
|
|
53
|
-
return {
|
|
54
|
-
paramExpression: 'data, p = {}',
|
|
55
|
-
paramType: 'data: RequestBody, params?: Params'
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
if (isParamMandatory) {
|
|
60
|
-
return {
|
|
61
|
-
paramExpression: 'p',
|
|
62
|
-
paramType: 'params: Params'
|
|
63
|
-
}
|
|
64
|
-
} else {
|
|
65
|
-
return {
|
|
66
|
-
paramExpression: 'p = {}',
|
|
67
|
-
paramType: 'params?: Params'
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function extractErrorParams(errorTypes: string[]) {
|
|
74
|
-
switch (errorTypes.length) {
|
|
75
|
-
case 0:
|
|
76
|
-
return `
|
|
77
|
-
export type _ErrorType = any
|
|
78
|
-
const errorSchema = z.any()`
|
|
79
|
-
case 1:
|
|
80
|
-
return `
|
|
81
|
-
export type _ErrorType = ${errorTypes[0]}
|
|
82
|
-
const errorSchema = ${errorTypes[0]}Schema`
|
|
83
|
-
default:
|
|
84
|
-
return `
|
|
85
|
-
export type _ErrorType = ${errorTypes.join(' | ')}
|
|
86
|
-
const errorSchema = z.union([${errorTypes.map(a => `${a}Schema`).join(', ')}])`
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export async function requestHookTemplate({source,
|
|
91
|
-
data: {
|
|
92
|
-
paths,
|
|
93
|
-
operationId,
|
|
94
|
-
response,
|
|
95
|
-
requestUrl,
|
|
96
|
-
variables,
|
|
97
|
-
requestBody,
|
|
98
|
-
contentType,
|
|
99
|
-
responseType,
|
|
100
|
-
errorResponses,
|
|
101
|
-
method
|
|
102
|
-
}
|
|
103
|
-
}: ResourceDescriptor<RestData>, ctx: InternalGeneratorContext) {
|
|
104
|
-
const postfix = ctx.potentiallyConflictingDescriptors.includes(operationId) ? generatePostfix(contentType, responseType) : ''
|
|
105
|
-
const ts = typescript(path.resolve('src', source, ...paths, camelCase(operationId), `use${pascalCase(operationId)}${postfix}.ts`))
|
|
106
|
-
ctx.getCounter(source)?.inc("Stateful Hooks")
|
|
107
|
-
|
|
108
|
-
const modifiedRequestUrl = `${requestUrl?.replace(/\{/g, "${")}`
|
|
109
|
-
|
|
110
|
-
const imports = new Set<string>();
|
|
111
|
-
imports.add(`import { z } from 'zod'`)
|
|
112
|
-
imports.add(`import { useCallback, useEffect } from 'react'`)
|
|
113
|
-
imports.add(`import {useNetworkState, NetworkState, DispatchState, error, successfulDispatch, validationError, encode, requestValidationError} from "@intrig/react"`)
|
|
114
|
-
|
|
115
|
-
const { hookShape, optionsShape } = extractHookShapeAndOptionsShape(response, requestBody, imports);
|
|
116
|
-
|
|
117
|
-
const { paramExpression, paramType } = extractParamDeconstruction(variables ?? [], requestBody);
|
|
118
|
-
|
|
119
|
-
if (requestBody) {
|
|
120
|
-
imports.add(`import { ${requestBody} as RequestBody, ${requestBody}Schema as requestBodySchema } from "@intrig/react/${source}/components/schemas/${requestBody}"`)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (response) {
|
|
124
|
-
imports.add(`import { ${response} as Response, ${response}Schema as schema } from "@intrig/react/${source}/components/schemas/${response}"`)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
imports.add(`import {${pascalCase(operationId)}Params as Params} from './${pascalCase(operationId)}.params'`)
|
|
128
|
-
|
|
129
|
-
const errorTypes = [...new Set(Object.values(errorResponses ?? {}).map(a => a.response))]
|
|
130
|
-
errorTypes.forEach(ref => imports.add(`import {${ref}, ${ref}Schema } from "@intrig/react/${source}/components/schemas/${ref}"`))
|
|
131
|
-
|
|
132
|
-
const paramExplode = [
|
|
133
|
-
...variables?.filter(a => a.in === "path").map(a => a.name) ?? [],
|
|
134
|
-
"...params"
|
|
135
|
-
].join(",")
|
|
136
|
-
|
|
137
|
-
const finalRequestBodyBlock = requestBody ? `,data: encode(data, "${contentType}", requestBodySchema)` : ''
|
|
138
|
-
|
|
139
|
-
function responseTypePart() {
|
|
140
|
-
switch (responseType) {
|
|
141
|
-
case "application/octet-stream":
|
|
142
|
-
return `responseType: 'blob', adapter: 'fetch',`;
|
|
143
|
-
case "text/event-stream":
|
|
144
|
-
return `responseType: 'stream', adapter: 'fetch',`;
|
|
145
|
-
}
|
|
146
|
-
return ''
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return ts`
|
|
150
|
-
${[...imports].join('\n')}
|
|
151
|
-
|
|
152
|
-
${!response ? `
|
|
153
|
-
type Response = any;
|
|
154
|
-
const schema = z.any();
|
|
155
|
-
` : ''}
|
|
156
|
-
|
|
157
|
-
${extractErrorParams(errorTypes.map(a => a as string))}
|
|
158
|
-
|
|
159
|
-
const operation = "${method.toUpperCase()} ${requestUrl}| ${contentType} -> ${responseType}"
|
|
160
|
-
const source = "${source}"
|
|
161
|
-
|
|
162
|
-
function use${pascalCase(operationId)}Hook(options: ${optionsShape} = {}): [NetworkState<Response>, (${paramType}) => DispatchState<any>, () => void] {
|
|
163
|
-
const [state, dispatch, clear, dispatchState] = useNetworkState<Response>({
|
|
164
|
-
key: options?.key ?? 'default',
|
|
165
|
-
operation,
|
|
166
|
-
source,
|
|
167
|
-
schema,
|
|
168
|
-
errorSchema
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const doExecute = useCallback<(${paramType}) => DispatchState<any>>((${paramExpression}) => {
|
|
172
|
-
const { ${paramExplode}} = p
|
|
173
|
-
|
|
174
|
-
${requestBody ? `
|
|
175
|
-
const validationResult = requestBodySchema.safeParse(data);
|
|
176
|
-
if (!validationResult.success) {
|
|
177
|
-
dispatchState(error(requestValidationError(validationResult.error)));
|
|
178
|
-
return validationError(validationResult.error.errors);
|
|
179
|
-
}
|
|
180
|
-
` : ``}
|
|
181
|
-
|
|
182
|
-
dispatch({
|
|
183
|
-
method: '${method}',
|
|
184
|
-
url: \`${modifiedRequestUrl}\`,
|
|
185
|
-
headers: {
|
|
186
|
-
${contentType ? `"Content-Type": "${contentType}",` : ''}
|
|
187
|
-
},
|
|
188
|
-
params,
|
|
189
|
-
key: \`${"${source}: ${operation}"}\`,
|
|
190
|
-
source: '${source}'
|
|
191
|
-
${requestBody ? finalRequestBodyBlock : ''},
|
|
192
|
-
${(responseTypePart())}
|
|
193
|
-
})
|
|
194
|
-
return successfulDispatch();
|
|
195
|
-
}, [dispatch])
|
|
196
|
-
|
|
197
|
-
useEffect(() => {
|
|
198
|
-
if (options.fetchOnMount) {
|
|
199
|
-
doExecute(${[requestBody ? `options.body!` : undefined, "options.params!"].filter(a => a).join(",")});
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return () => {
|
|
203
|
-
if (options.clearOnUnmount) {
|
|
204
|
-
clear();
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}, [])
|
|
208
|
-
|
|
209
|
-
return [
|
|
210
|
-
state,
|
|
211
|
-
doExecute,
|
|
212
|
-
clear
|
|
213
|
-
]
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
use${pascalCase(operationId)}Hook.key = \`${"${source}: ${operation}"}\`
|
|
217
|
-
|
|
218
|
-
export const use${pascalCase(operationId)}: ${hookShape} = use${pascalCase(operationId)}Hook;
|
|
219
|
-
`
|
|
220
|
-
}
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
import { OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
-
import {jsonLiteral, ResourceDescriptor, Schema, typescript} from "@intrig/plugin-sdk";
|
|
3
|
-
import * as path from 'path'
|
|
4
|
-
|
|
5
|
-
export interface SchemaConversionResult {
|
|
6
|
-
tsType: string;
|
|
7
|
-
zodSchema: string;
|
|
8
|
-
imports: Set<string>;
|
|
9
|
-
optional?: boolean;
|
|
10
|
-
binaryish?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function typeTemplate(descriptor: ResourceDescriptor<Schema>) {
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
data: {
|
|
17
|
-
schema,
|
|
18
|
-
name: typeName
|
|
19
|
-
},
|
|
20
|
-
source
|
|
21
|
-
} = descriptor;
|
|
22
|
-
|
|
23
|
-
const {imports, zodSchema, tsType} = openApiSchemaToZod(schema);
|
|
24
|
-
|
|
25
|
-
const ts = typescript(path.resolve('src', source, 'components', 'schemas', `${typeName}.ts`));
|
|
26
|
-
|
|
27
|
-
const simpleType = (await jsonLiteral('')`${JSON.stringify(schema)}`).content;
|
|
28
|
-
|
|
29
|
-
const transport =
|
|
30
|
-
schema.type === 'string' && (schema as any).format === 'binary'
|
|
31
|
-
? 'binary'
|
|
32
|
-
: 'json';
|
|
33
|
-
|
|
34
|
-
return ts`
|
|
35
|
-
import { z } from 'zod'
|
|
36
|
-
|
|
37
|
-
${[...imports].join('\n')}
|
|
38
|
-
|
|
39
|
-
//--- Zod Schemas ---//
|
|
40
|
-
|
|
41
|
-
export const ${typeName}Schema = ${zodSchema}
|
|
42
|
-
|
|
43
|
-
//--- Typescript Type ---//
|
|
44
|
-
|
|
45
|
-
export type ${typeName} = ${tsType}
|
|
46
|
-
|
|
47
|
-
//--- JSON Schema ---//
|
|
48
|
-
|
|
49
|
-
export const ${typeName}_jsonschema = ${JSON.stringify(schema) ?? "{}"}
|
|
50
|
-
|
|
51
|
-
//--- Simple Type ---//
|
|
52
|
-
/*[${simpleType}]*/
|
|
53
|
-
|
|
54
|
-
// Transport hint for clients ("binary" => use arraybuffer/blob)
|
|
55
|
-
export const ${typeName}_transport = '${transport}' as const;
|
|
56
|
-
`
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function isRef(schema: OpenAPIV3_1.SchemaObject | OpenAPIV3_1.ReferenceObject): schema is OpenAPIV3_1.ReferenceObject {
|
|
60
|
-
return '$ref' in (schema ?? {});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Helper function to convert OpenAPI schema types to TypeScript types and Zod schemas
|
|
64
|
-
export function openApiSchemaToZod(schema: OpenAPIV3_1.SchemaObject, imports: Set<string> = new Set()): SchemaConversionResult {
|
|
65
|
-
if (!schema) {
|
|
66
|
-
return { tsType: 'any', zodSchema: 'z.any()', imports: new Set() };
|
|
67
|
-
}
|
|
68
|
-
if (isRef(schema)) {
|
|
69
|
-
return handleRefSchema(schema.$ref, imports);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (!schema.type) {
|
|
73
|
-
if ('properties' in schema) {
|
|
74
|
-
schema.type = 'object';
|
|
75
|
-
} else if ('items' in schema) {
|
|
76
|
-
schema.type = 'array' as any;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
switch (schema.type) {
|
|
81
|
-
case 'string':
|
|
82
|
-
return handleStringSchema(schema);
|
|
83
|
-
case 'number':
|
|
84
|
-
return handleNumberSchema(schema);
|
|
85
|
-
case 'integer':
|
|
86
|
-
return handleIntegerSchema(schema);
|
|
87
|
-
case 'boolean':
|
|
88
|
-
return handleBooleanSchema();
|
|
89
|
-
case 'array':
|
|
90
|
-
return handleArraySchema(schema, imports);
|
|
91
|
-
case 'object':
|
|
92
|
-
return handleObjectSchema(schema, imports);
|
|
93
|
-
default:
|
|
94
|
-
return handleComplexSchema(schema, imports);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function handleRefSchema(ref: string, imports: Set<string>): SchemaConversionResult {
|
|
99
|
-
const refParts = ref.split('/');
|
|
100
|
-
const refName = refParts[refParts.length - 1];
|
|
101
|
-
imports.add(`import { ${refName}, ${refName}Schema } from './${refName}';`);
|
|
102
|
-
return { tsType: refName, zodSchema: `z.lazy(() => ${refName}Schema)`, imports };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function handleStringSchema(schema: OpenAPIV3_1.SchemaObject): SchemaConversionResult {
|
|
106
|
-
const imports = new Set<string>();
|
|
107
|
-
let binaryish = false;
|
|
108
|
-
if (schema.enum) {
|
|
109
|
-
const enumValues = schema.enum.map(value => `'${value}'`).join(' | ');
|
|
110
|
-
const zodEnum = `z.enum([${schema.enum.map(value => `'${value}'`).join(', ')}])`;
|
|
111
|
-
return { tsType: enumValues, zodSchema: zodEnum , imports: new Set() };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
let zodSchema = 'z.string()';
|
|
115
|
-
let tsType = 'string';
|
|
116
|
-
|
|
117
|
-
if (schema.format === 'date' && !schema.pattern) {
|
|
118
|
-
tsType = 'Date';
|
|
119
|
-
zodSchema = 'z.coerce.date()';
|
|
120
|
-
zodSchema += `.transform((val) => {
|
|
121
|
-
const parsedDate = new Date(val);
|
|
122
|
-
if (isNaN(parsedDate.getTime())) {
|
|
123
|
-
throw new Error('Invalid date format');
|
|
124
|
-
}
|
|
125
|
-
return parsedDate;
|
|
126
|
-
})`;
|
|
127
|
-
} else if (schema.format === 'time') {
|
|
128
|
-
zodSchema = 'z.string()';
|
|
129
|
-
if (schema.pattern) {
|
|
130
|
-
zodSchema += `.regex(new RegExp('${schema.pattern}'))`;
|
|
131
|
-
}
|
|
132
|
-
} else if (schema.format === 'date-time' && !schema.pattern) {
|
|
133
|
-
tsType = 'Date';
|
|
134
|
-
zodSchema = 'z.coerce.date()';
|
|
135
|
-
zodSchema += `.transform((val) => {
|
|
136
|
-
const parsedDateTime = new Date(val);
|
|
137
|
-
if (isNaN(parsedDateTime.getTime())) {
|
|
138
|
-
throw new Error('Invalid date-time format');
|
|
139
|
-
}
|
|
140
|
-
return parsedDateTime;
|
|
141
|
-
})`;
|
|
142
|
-
} else if (schema.format === 'binary') {
|
|
143
|
-
tsType = 'BinaryData';
|
|
144
|
-
zodSchema = 'BinaryDataSchema';
|
|
145
|
-
imports.add(`import { BinaryData, BinaryDataSchema } from '@intrig/react/type-utils'`);
|
|
146
|
-
binaryish = true;
|
|
147
|
-
} else if (schema.format === 'byte') {
|
|
148
|
-
tsType = 'Uint8Array';
|
|
149
|
-
zodSchema = 'z.string().transform((val) => base64ToUint8Array(val))';
|
|
150
|
-
imports.add(`import { base64ToUint8Array } from '@intrig/react/type-utils'`);
|
|
151
|
-
binaryish = true;
|
|
152
|
-
} else if (schema.format === 'email') {
|
|
153
|
-
zodSchema = 'z.string().email()';
|
|
154
|
-
} else if (schema.format === 'uuid') {
|
|
155
|
-
zodSchema = 'z.string().uuid()';
|
|
156
|
-
} else if (schema.format === 'uri') {
|
|
157
|
-
zodSchema = 'z.string().url()';
|
|
158
|
-
} else if (schema.format === 'hostname') {
|
|
159
|
-
zodSchema = 'z.string()'; // Zod does not have a direct hostname validator
|
|
160
|
-
} else if (schema.format === 'ipv4') {
|
|
161
|
-
zodSchema = 'z.string().regex(/^((25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)$/)';
|
|
162
|
-
} else if (schema.format === 'ipv6') {
|
|
163
|
-
zodSchema = 'z.string().regex(/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6}|:)|::(ffff(:0{1,4}){0,1}:)?((25[0-5]|(2[0-4]|1[0-9]|[0-9])\\.){3}(25[0-5]|(2[0-4]|1[0-9]|[0-9]))))$/)';
|
|
164
|
-
} else {
|
|
165
|
-
if (schema.minLength !== undefined) zodSchema += `.min(${schema.minLength})`;
|
|
166
|
-
if (schema.maxLength !== undefined) zodSchema += `.max(${schema.maxLength})`;
|
|
167
|
-
if (schema.pattern !== undefined) zodSchema += `.regex(new RegExp('${schema.pattern}'))`;
|
|
168
|
-
}
|
|
169
|
-
return { tsType, zodSchema, imports, binaryish };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function handleNumberSchema(schema: OpenAPIV3_1.SchemaObject): SchemaConversionResult {
|
|
173
|
-
let zodSchema = 'z.number()';
|
|
174
|
-
if (schema.minimum !== undefined) zodSchema += `.min(${schema.minimum})`;
|
|
175
|
-
if (schema.maximum !== undefined) zodSchema += `.max(${schema.maximum})`;
|
|
176
|
-
return { tsType: 'number', zodSchema, imports: new Set() };
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function handleIntegerSchema(schema: OpenAPIV3_1.SchemaObject): SchemaConversionResult {
|
|
180
|
-
let zodSchema = 'z.number().int()';
|
|
181
|
-
if (schema.minimum !== undefined) zodSchema += `.min(${schema.minimum})`;
|
|
182
|
-
if (schema.maximum !== undefined) zodSchema += `.max(${schema.maximum})`;
|
|
183
|
-
return { tsType: 'number', zodSchema, imports: new Set() };
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function handleBooleanSchema(): SchemaConversionResult {
|
|
187
|
-
const zodSchema = 'z.boolean()';
|
|
188
|
-
return { tsType: 'boolean', zodSchema, imports: new Set() };
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function handleArraySchema(schema: OpenAPIV3_1.ArraySchemaObject, imports: Set<string>): SchemaConversionResult {
|
|
192
|
-
if (!schema.items) {
|
|
193
|
-
throw new Error('Array schema must have an items property');
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const {
|
|
197
|
-
tsType,
|
|
198
|
-
zodSchema: itemZodSchema,
|
|
199
|
-
imports: itemImports,
|
|
200
|
-
binaryish
|
|
201
|
-
} = openApiSchemaToZod(schema.items as OpenAPIV3_1.SchemaObject, imports);
|
|
202
|
-
|
|
203
|
-
let zodSchema = binaryish ?
|
|
204
|
-
`z.array(${itemZodSchema})`:
|
|
205
|
-
`(z.preprocess((raw) => (Array.isArray(raw) ? raw : [raw]), z.array(${itemZodSchema})) as z.ZodType<${tsType}[], z.ZodTypeDef, ${tsType}[]>)`;
|
|
206
|
-
if (schema.minItems !== undefined) zodSchema += `.min(${schema.minItems})`;
|
|
207
|
-
if (schema.maxItems !== undefined) zodSchema += `.max(${schema.maxItems})`;
|
|
208
|
-
return {tsType: `(${tsType})[]`, zodSchema, imports: new Set([...imports, ...itemImports])};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function handleObjectSchema(schema: OpenAPIV3_1.SchemaObject, imports: Set<string>): SchemaConversionResult {
|
|
212
|
-
const updatedRequiredFields = schema.required || [];
|
|
213
|
-
if (schema.properties) {
|
|
214
|
-
const propertiesTs = Object.entries(schema.properties).map(([key, value]) => {
|
|
215
|
-
const { tsType, optional } = openApiSchemaToZod(value as OpenAPIV3_1.SchemaObject);
|
|
216
|
-
const isRequired = !optional && updatedRequiredFields.includes(key);
|
|
217
|
-
return `${key}${isRequired ? '' : '?'}: ${tsType} ${isRequired ? '' : ' | null'};`;
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
const propertiesZod = Object.entries(schema.properties).map(([key, value]) => {
|
|
221
|
-
const { zodSchema, imports: propImports } = openApiSchemaToZod(value as OpenAPIV3_1.SchemaObject);
|
|
222
|
-
imports = new Set([...imports, ...propImports]);
|
|
223
|
-
const isRequired = updatedRequiredFields.includes(key);
|
|
224
|
-
return `${key}: ${isRequired ? zodSchema : zodSchema.includes('.optional().nullable()') ? zodSchema : zodSchema + '.optional().nullable()'}`;
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
return {
|
|
228
|
-
tsType: `{ ${propertiesTs.join(' ')} }`,
|
|
229
|
-
zodSchema: `z.object({ ${propertiesZod.join(', ')} })`,
|
|
230
|
-
imports,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
return { tsType: 'any', zodSchema: 'z.any()', imports: new Set(), optional: true };
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function handleComplexSchema(schema: OpenAPIV3_1.SchemaObject, imports: Set<string>): SchemaConversionResult {
|
|
237
|
-
if (schema.oneOf) {
|
|
238
|
-
const options = schema.oneOf.map(subSchema => openApiSchemaToZod(subSchema as OpenAPIV3_1.SchemaObject));
|
|
239
|
-
const zodSchemas = options.map(option => option.zodSchema);
|
|
240
|
-
const tsTypes = options.map(option => option.tsType);
|
|
241
|
-
return { tsType: tsTypes.join(' | '), zodSchema: `z.union([${zodSchemas.join(', ')}])`, imports: new Set([...imports, ...options.flatMap(option => Array.from(option.imports))]) };
|
|
242
|
-
}
|
|
243
|
-
if (schema.anyOf) {
|
|
244
|
-
const options = schema.anyOf.map(subSchema => openApiSchemaToZod(subSchema as OpenAPIV3_1.SchemaObject));
|
|
245
|
-
const zodSchemas = options.map(option => option.zodSchema);
|
|
246
|
-
const tsTypes = options.map(option => option.tsType);
|
|
247
|
-
return { tsType: tsTypes.join(' | '), zodSchema: `z.union([${zodSchemas.join(', ')}])`, imports: new Set([...imports, ...options.flatMap(option => Array.from(option.imports))]) };
|
|
248
|
-
}
|
|
249
|
-
if (schema.allOf) {
|
|
250
|
-
const options = schema.allOf.map(subSchema => openApiSchemaToZod(subSchema as OpenAPIV3_1.SchemaObject));
|
|
251
|
-
const zodSchemas = options.map(option => option.zodSchema);
|
|
252
|
-
const tsTypes = options.map(option => option.tsType);
|
|
253
|
-
if (zodSchemas.length === 1) return { tsType: tsTypes.join(' & '), zodSchema: zodSchemas[0], imports: new Set([...imports, ...options.flatMap(option => Array.from(option.imports))]) };
|
|
254
|
-
return { tsType: tsTypes.join(' & '), zodSchema: `z.intersection(${zodSchemas.join(', ')})`, imports: new Set([...imports, ...options.flatMap(option => Array.from(option.imports))]) };
|
|
255
|
-
}
|
|
256
|
-
return { tsType: 'any', zodSchema: 'z.any()', imports };
|
|
257
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import {jsonLiteral} from "@intrig/plugin-sdk";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
|
|
4
|
-
export function reactSwcrcTemplate() {
|
|
5
|
-
const json = jsonLiteral(path.resolve('.swcrc'))
|
|
6
|
-
return json`
|
|
7
|
-
{
|
|
8
|
-
"jsc": {
|
|
9
|
-
"parser": {
|
|
10
|
-
"syntax": "typescript",
|
|
11
|
-
"decorators": false,
|
|
12
|
-
"dynamicImport": true
|
|
13
|
-
},
|
|
14
|
-
"target": "es2022",
|
|
15
|
-
"externalHelpers": false
|
|
16
|
-
},
|
|
17
|
-
"module": {
|
|
18
|
-
"type": "es6",
|
|
19
|
-
"noInterop": false
|
|
20
|
-
},
|
|
21
|
-
"sourceMaps": true,
|
|
22
|
-
"exclude": ["../../node_modules"]
|
|
23
|
-
}
|
|
24
|
-
`
|
|
25
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {jsonLiteral} from "@intrig/plugin-sdk";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
|
|
4
|
-
export function reactTsConfigTemplate() {
|
|
5
|
-
const json = jsonLiteral(path.resolve('tsconfig.json'))
|
|
6
|
-
return json`
|
|
7
|
-
{
|
|
8
|
-
"compilerOptions": {
|
|
9
|
-
"target": "es2020",
|
|
10
|
-
"module": "ESNext",
|
|
11
|
-
"declaration": true,
|
|
12
|
-
"outDir": "./dist",
|
|
13
|
-
"strict": true,
|
|
14
|
-
"esModuleInterop": true,
|
|
15
|
-
"noImplicitAny": false,
|
|
16
|
-
"moduleResolution": "node",
|
|
17
|
-
"baseUrl": "./",
|
|
18
|
-
"paths": {
|
|
19
|
-
"@intrig/react": [
|
|
20
|
-
"./src"
|
|
21
|
-
],
|
|
22
|
-
"@intrig/react/*": [
|
|
23
|
-
"./src/*"
|
|
24
|
-
],
|
|
25
|
-
"intrig-hook": ["src/config/intrig"]
|
|
26
|
-
},
|
|
27
|
-
"jsx": "react-jsx",
|
|
28
|
-
"skipLibCheck": true
|
|
29
|
-
},
|
|
30
|
-
"exclude": [
|
|
31
|
-
"node_modules",
|
|
32
|
-
"../../node_modules",
|
|
33
|
-
"**/__tests__/*"
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
`
|
|
37
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {typescript} from "@intrig/plugin-sdk";
|
|
2
|
-
import path from "path";
|
|
3
|
-
|
|
4
|
-
export function typeUtilsTemplate() {
|
|
5
|
-
const ts = typescript(path.resolve('src', 'type-utils.ts'))
|
|
6
|
-
|
|
7
|
-
return ts`import { z } from 'zod';
|
|
8
|
-
|
|
9
|
-
export type BinaryData = Blob;
|
|
10
|
-
export const BinaryDataSchema: z.ZodType<BinaryData> = z.instanceof(Blob);
|
|
11
|
-
|
|
12
|
-
// Base64 helpers (browser + Node compatible; no Buffer required)
|
|
13
|
-
export function base64ToUint8Array(b64: string): Uint8Array {
|
|
14
|
-
if (typeof atob === 'function') {
|
|
15
|
-
// Browser
|
|
16
|
-
const bin = atob(b64);
|
|
17
|
-
const bytes = new Uint8Array(bin.length);
|
|
18
|
-
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
|
19
|
-
return bytes;
|
|
20
|
-
} else {
|
|
21
|
-
// Node
|
|
22
|
-
const buf = Buffer.from(b64, 'base64');
|
|
23
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
`
|
|
28
|
-
}
|
package/tsconfig.json
DELETED
package/tsconfig.lib.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"baseUrl": ".",
|
|
5
|
-
"rootDir": "src",
|
|
6
|
-
"outDir": "dist",
|
|
7
|
-
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
|
|
8
|
-
"emitDeclarationOnly": true,
|
|
9
|
-
"module": "ESNext",
|
|
10
|
-
"moduleResolution": "node",
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"types": ["node"]
|
|
13
|
-
},
|
|
14
|
-
"include": ["src/**/*.ts"],
|
|
15
|
-
"references": [
|
|
16
|
-
{
|
|
17
|
-
"path": "../../lib/plugin-sdk/tsconfig.lib.json"
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|