@visulima/api-platform 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/bin/index.js +46 -0
- package/dist/chunk-AOL5OFCG.mjs +284 -0
- package/dist/chunk-AOL5OFCG.mjs.map +1 -0
- package/dist/chunk-ATZDRT65.js +284 -0
- package/dist/chunk-ATZDRT65.js.map +1 -0
- package/dist/{chunk-AJKZCWFG.js → chunk-F7RHRCUQ.js} +2 -2
- package/dist/chunk-F7RHRCUQ.js.map +1 -0
- package/dist/{chunk-XXZ56SKG.mjs → chunk-RPHC5ZGB.mjs} +2 -2
- package/dist/chunk-RPHC5ZGB.mjs.map +1 -0
- package/dist/index-server.d.ts +4 -14
- package/dist/index-server.js +9 -10
- package/dist/index-server.js.map +1 -1
- package/dist/index-server.mjs +7 -8
- package/dist/index-server.mjs.map +1 -1
- package/dist/next/cli/index.js +8 -8
- package/dist/next/cli/index.js.map +1 -1
- package/dist/next/cli/index.mjs +8 -8
- package/dist/next/cli/index.mjs.map +1 -1
- package/dist/next/index-browser.js +2 -2
- package/dist/next/index-browser.mjs +1 -1
- package/dist/next/index-server.d.ts +14 -13
- package/dist/next/index-server.js +4 -4
- package/dist/next/index-server.js.map +1 -1
- package/dist/next/index-server.mjs +2 -2
- package/dist/next/index-server.mjs.map +1 -1
- package/dist/swagger-handler-ffed72c2.d.ts +19 -0
- package/next/cli/package.json +12 -3
- package/next/package.json +9 -0
- package/package.json +20 -20
- package/recipes/api/swagger.ts +12 -0
- package/recipes/pages/redoc-ui.tsx +5 -0
- package/recipes/pages/swagger-ui.tsx +5 -0
- package/dist/chunk-2LATTLUM.mjs +0 -166
- package/dist/chunk-2LATTLUM.mjs.map +0 -1
- package/dist/chunk-AJKZCWFG.js.map +0 -1
- package/dist/chunk-S7GUPAL4.js +0 -166
- package/dist/chunk-S7GUPAL4.js.map +0 -1
- package/dist/chunk-XXZ56SKG.mjs.map +0 -1
- package/src/connect/create-node-router.ts +0 -44
- package/src/connect/handler.ts +0 -46
- package/src/connect/middleware/cors-middleware.ts +0 -10
- package/src/connect/middleware/http-header-normalizer.ts +0 -93
- package/src/connect/middleware/rate-limiter-middleware.ts +0 -43
- package/src/connect/middleware/serializers-middleware.ts +0 -121
- package/src/connect/serializers/types.d.ts +0 -1
- package/src/connect/serializers/xml.ts +0 -13
- package/src/connect/serializers/yaml.ts +0 -7
- package/src/error-handler/jsonapi-error-handler.ts +0 -46
- package/src/error-handler/problem-error-handler.ts +0 -44
- package/src/error-handler/types.d.ts +0 -14
- package/src/error-handler/utils.ts +0 -39
- package/src/index-browser.tsx +0 -1
- package/src/index-server.ts +0 -75
- package/src/next/cli/index.ts +0 -2
- package/src/next/cli/list/api-route-file-parser.ts +0 -74
- package/src/next/cli/list/collect-api-route-files.ts +0 -42
- package/src/next/cli/list/list-command.ts +0 -105
- package/src/next/cli/list/routes-render.ts +0 -62
- package/src/next/cli/list/types.d.ts +0 -1
- package/src/next/index-browser.tsx +0 -3
- package/src/next/index-server.ts +0 -6
- package/src/next/routes/api/swagger.ts +0 -23
- package/src/next/routes/pages/swagger/get-static-properties-swagger.ts +0 -32
- package/src/next/routes/pages/swagger/redoc.tsx +0 -35
- package/src/next/routes/pages/swagger/swagger.tsx +0 -44
- package/src/next/webpack/with-open-api.ts +0 -63
- package/src/swagger/extend-swagger-spec.ts +0 -167
- package/src/swagger/swagger-handler.ts +0 -83
- package/src/utils.ts +0 -37
- package/src/zod/date-in-schema.ts +0 -57
- package/src/zod/date-out-schema.ts +0 -41
- package/src/zod/index.ts +0 -9
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { BaseDefinition } from "@visulima/jsdoc-open-api";
|
|
2
|
-
import { SwaggerCompilerPlugin } from "@visulima/jsdoc-open-api";
|
|
3
|
-
import type { NextConfig } from "next";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import type { Configuration } from "webpack";
|
|
7
|
-
|
|
8
|
-
const withOpenApi = ({
|
|
9
|
-
definition, sources, verbose, output = "swagger/swagger.json",
|
|
10
|
-
// eslint-disable-next-line max-len
|
|
11
|
-
}: { definition: Exclude<BaseDefinition, "openapi"> & { openapi?: string }; sources: string[]; verbose?: boolean; output: string }) => (nextConfig: NextConfig) => {
|
|
12
|
-
return {
|
|
13
|
-
...nextConfig,
|
|
14
|
-
webpack: (config: Configuration, options: any) => {
|
|
15
|
-
if (!options.isServer) {
|
|
16
|
-
return config;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (output.startsWith("/")) {
|
|
20
|
-
// eslint-disable-next-line no-param-reassign
|
|
21
|
-
output = output.slice(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (!output.endsWith(".json")) {
|
|
25
|
-
throw new Error("The output path must end with .json");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// eslint-disable-next-line no-param-reassign
|
|
29
|
-
config = {
|
|
30
|
-
...config,
|
|
31
|
-
plugins: [
|
|
32
|
-
// @ts-ignore
|
|
33
|
-
...config.plugins,
|
|
34
|
-
new SwaggerCompilerPlugin(
|
|
35
|
-
`${options.dir}/${output}`,
|
|
36
|
-
sources.map((source) => {
|
|
37
|
-
const combinedPath = path.join(options.dir, source.replace("./", ""));
|
|
38
|
-
|
|
39
|
-
// Check if the path is a directory
|
|
40
|
-
fs.lstatSync(combinedPath).isDirectory();
|
|
41
|
-
|
|
42
|
-
return combinedPath;
|
|
43
|
-
}),
|
|
44
|
-
{
|
|
45
|
-
// @ts-ignore
|
|
46
|
-
openapi: "3.0.0",
|
|
47
|
-
...definition,
|
|
48
|
-
},
|
|
49
|
-
{ verbose },
|
|
50
|
-
),
|
|
51
|
-
],
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
if (typeof nextConfig.webpack === "function") {
|
|
55
|
-
return nextConfig.webpack(config, options);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return config;
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export default withOpenApi;
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { header as headerCase } from "case";
|
|
2
|
-
import type { OpenAPIV3 } from "openapi-types";
|
|
3
|
-
import type { OAS3Definition, Operation, Responses } from "swagger-jsdoc";
|
|
4
|
-
|
|
5
|
-
const extendComponentSchemas = (spec: Partial<OAS3Definition>, schemaName: string, schema: OpenAPIV3.SchemaObject) => {
|
|
6
|
-
if (typeof spec.components !== "object") {
|
|
7
|
-
// eslint-disable-next-line no-param-reassign
|
|
8
|
-
spec.components = {};
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (typeof spec.components.schemas !== "object") {
|
|
12
|
-
// eslint-disable-next-line no-param-reassign
|
|
13
|
-
spec.components.schemas = {};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (typeof spec.components.schemas[schemaName] === "undefined") {
|
|
17
|
-
// eslint-disable-next-line no-param-reassign
|
|
18
|
-
spec.components.schemas[schemaName] = schema;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const extendComponentExamples = (spec: Partial<OAS3Definition>, exampleName: string, example: OpenAPIV3.SchemaObject) => {
|
|
23
|
-
if (typeof spec.components !== "object") {
|
|
24
|
-
// eslint-disable-next-line no-param-reassign
|
|
25
|
-
spec.components = {};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (typeof spec.components.examples !== "object") {
|
|
29
|
-
// eslint-disable-next-line no-param-reassign
|
|
30
|
-
spec.components.examples = {};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (typeof spec.components.examples[exampleName] === "undefined") {
|
|
34
|
-
// eslint-disable-next-line no-param-reassign
|
|
35
|
-
spec.components.examples[exampleName] = example;
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
function extendSwaggerWithMediaTypeSchema(
|
|
40
|
-
responseSpec: OpenAPIV3.ResponseObject,
|
|
41
|
-
allowedMediaTypes: { [p: string]: boolean } | undefined,
|
|
42
|
-
pathKey: string,
|
|
43
|
-
spec: Partial<OAS3Definition>,
|
|
44
|
-
methodSpec: Operation,
|
|
45
|
-
status: string,
|
|
46
|
-
) {
|
|
47
|
-
let examples:
|
|
48
|
-
| {
|
|
49
|
-
[media: string]: OpenAPIV3.ReferenceObject | OpenAPIV3.ExampleObject;
|
|
50
|
-
}
|
|
51
|
-
| undefined;
|
|
52
|
-
|
|
53
|
-
Object.entries(responseSpec.content as object).forEach(([mediaName, contentSpec]) => {
|
|
54
|
-
if (typeof contentSpec.schema === "object") {
|
|
55
|
-
const { schema } = contentSpec;
|
|
56
|
-
|
|
57
|
-
if (mediaName === "application/json" && typeof contentSpec.examples !== "undefined") {
|
|
58
|
-
examples = contentSpec.examples;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (typeof (schema as OpenAPIV3.ReferenceObject).$ref !== "undefined") {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const schemaIsArray = (schema as OpenAPIV3.SchemaObject).type === "array";
|
|
66
|
-
|
|
67
|
-
Object.entries(allowedMediaTypes || {}).forEach(([mediaType, allowed]) => {
|
|
68
|
-
if (!allowed) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// eslint-disable-next-line max-len
|
|
73
|
-
const schemaName = `${headerCase(pathKey.trim().replace("/", ""))}${mediaType === "application/ld+json" ? ".jsonld" : ""}`;
|
|
74
|
-
|
|
75
|
-
extendComponentSchemas(spec as OAS3Definition, schemaName, schema as OpenAPIV3.SchemaObject);
|
|
76
|
-
|
|
77
|
-
if (typeof methodSpec?.responses?.[status]?.content[mediaType]?.schema === "undefined") {
|
|
78
|
-
// eslint-disable-next-line no-param-reassign
|
|
79
|
-
(methodSpec.responses as Responses)[status].content[mediaType] = { schema: {} };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// eslint-disable-next-line no-param-reassign
|
|
83
|
-
(methodSpec.responses as Responses)[status].content[mediaType].schema = schemaIsArray
|
|
84
|
-
? {
|
|
85
|
-
type: "array",
|
|
86
|
-
items: {
|
|
87
|
-
$ref: `#/components/schemas/${schemaName}`,
|
|
88
|
-
},
|
|
89
|
-
}
|
|
90
|
-
: {
|
|
91
|
-
$ref: `#/components/schemas/${schemaName}`,
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
if (typeof methodSpec.produces === "undefined") {
|
|
95
|
-
// eslint-disable-next-line no-param-reassign
|
|
96
|
-
methodSpec.produces = [];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
methodSpec.produces.push(mediaType);
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
return examples;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function extendSwaggerWithMediaTypeExamples(
|
|
108
|
-
responseSpec: OpenAPIV3.ResponseObject,
|
|
109
|
-
allowedMediaTypes: { [p: string]: boolean } | undefined,
|
|
110
|
-
pathKey: string,
|
|
111
|
-
spec: Partial<OAS3Definition>,
|
|
112
|
-
examples: { [p: string]: OpenAPIV3.ReferenceObject | OpenAPIV3.ExampleObject } | undefined,
|
|
113
|
-
methodSpec: Operation,
|
|
114
|
-
status: string,
|
|
115
|
-
) {
|
|
116
|
-
Object.keys(responseSpec.content as object).forEach((mediaName) => {
|
|
117
|
-
if (mediaName === "application/json") {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
Object.entries(allowedMediaTypes || {}).forEach(([mediaType, allowed]) => {
|
|
122
|
-
if (!allowed) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// eslint-disable-next-line max-len
|
|
127
|
-
const examplesName = `${headerCase(pathKey.trim().replace("/", ""))}${mediaType === "application/ld+json" ? ".jsonld" : ""}`;
|
|
128
|
-
|
|
129
|
-
extendComponentExamples(spec as OAS3Definition, examplesName, examples as OpenAPIV3.SchemaObject);
|
|
130
|
-
|
|
131
|
-
if (typeof methodSpec?.responses?.[status]?.content[mediaType]?.examples === "undefined") {
|
|
132
|
-
// eslint-disable-next-line no-param-reassign
|
|
133
|
-
(methodSpec.responses as Responses)[status].content[mediaType] = { examples: {} };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// eslint-disable-next-line no-param-reassign
|
|
137
|
-
(methodSpec.responses as Responses)[status].content[mediaType].examples = examples;
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// eslint-disable-next-line radar/cognitive-complexity
|
|
143
|
-
export default function extendSwaggerSpec(spec: Partial<OAS3Definition>, allowedMediaTypes?: { [key: string]: boolean }): Partial<OAS3Definition> {
|
|
144
|
-
if (typeof spec === "object" && typeof spec.paths === "object") {
|
|
145
|
-
Object.entries(spec.paths).forEach(([pathKey, pathSpec]) => {
|
|
146
|
-
Object.values(pathSpec).forEach((methodSpec) => {
|
|
147
|
-
if (typeof methodSpec.responses === "object") {
|
|
148
|
-
Object.entries<OpenAPIV3.ResponseObject>(methodSpec.responses).forEach(([status, responseSpec]) => {
|
|
149
|
-
if (typeof responseSpec.content === "object") {
|
|
150
|
-
let examples:
|
|
151
|
-
| {
|
|
152
|
-
[media: string]: OpenAPIV3.ReferenceObject | OpenAPIV3.ExampleObject;
|
|
153
|
-
}
|
|
154
|
-
| undefined = extendSwaggerWithMediaTypeSchema(responseSpec, allowedMediaTypes, pathKey, spec, methodSpec, status);
|
|
155
|
-
|
|
156
|
-
if (typeof examples !== "undefined") {
|
|
157
|
-
extendSwaggerWithMediaTypeExamples(responseSpec, allowedMediaTypes, pathKey, spec, examples, methodSpec, status);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return spec;
|
|
167
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies
|
|
2
|
-
import type { ModelsToOpenApiParameters, SwaggerModelsConfig } from "@visulima/crud";
|
|
3
|
-
// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies
|
|
4
|
-
import { modelsToOpenApi } from "@visulima/crud";
|
|
5
|
-
import debug from "debug";
|
|
6
|
-
import merge from "lodash.merge";
|
|
7
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
-
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
9
|
-
import path from "node:path";
|
|
10
|
-
import type { OAS3Definition, Tag } from "swagger-jsdoc";
|
|
11
|
-
|
|
12
|
-
import yamlTransformer from "../connect/serializers/yaml";
|
|
13
|
-
import extendSwaggerSpec from "./extend-swagger-spec";
|
|
14
|
-
|
|
15
|
-
// eslint-disable-next-line testing-library/no-debugging-utils
|
|
16
|
-
const swaggerCrudDebug = debug("visulima:api-platform:swagger:crud:get-static-properties-swagger");
|
|
17
|
-
|
|
18
|
-
const swaggerHandler = (
|
|
19
|
-
options: Partial<{
|
|
20
|
-
allowedMediaTypes: { [key: string]: boolean };
|
|
21
|
-
swaggerFilePath: string;
|
|
22
|
-
crud: Exclude<ModelsToOpenApiParameters, "swagger"> & {
|
|
23
|
-
swagger?: {
|
|
24
|
-
models?: SwaggerModelsConfig<string>;
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
}> = {},
|
|
28
|
-
) => {
|
|
29
|
-
const {
|
|
30
|
-
allowedMediaTypes = {
|
|
31
|
-
"application/json": true,
|
|
32
|
-
},
|
|
33
|
-
swaggerFilePath,
|
|
34
|
-
crud,
|
|
35
|
-
} = options;
|
|
36
|
-
|
|
37
|
-
return async <Request extends IncomingMessage, Response extends ServerResponse>(request: Request, response: Response) => {
|
|
38
|
-
const swaggerPath = path.join(process.cwd(), swaggerFilePath || "swagger/swagger.json");
|
|
39
|
-
|
|
40
|
-
if (!existsSync(swaggerPath)) {
|
|
41
|
-
throw new Error(`Swagger file not found at ${swaggerPath}. Did you change the output path in "withOpenApi" inside the next.config.js file?`);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const fileContents = readFileSync(swaggerPath, "utf8");
|
|
45
|
-
|
|
46
|
-
let spec = extendSwaggerSpec(JSON.parse(fileContents) as OAS3Definition, allowedMediaTypes) as OAS3Definition;
|
|
47
|
-
let crudSwagger: Partial<OAS3Definition> = {};
|
|
48
|
-
|
|
49
|
-
if (typeof crud !== "undefined") {
|
|
50
|
-
try {
|
|
51
|
-
const modelsOpenApi = await modelsToOpenApi(crud);
|
|
52
|
-
|
|
53
|
-
crudSwagger = {
|
|
54
|
-
components: { schemas: modelsOpenApi.schemas, examples: modelsOpenApi.examples },
|
|
55
|
-
tags: modelsOpenApi.tags as Tag[],
|
|
56
|
-
paths: modelsOpenApi.paths,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
crudSwagger = extendSwaggerSpec(crudSwagger, allowedMediaTypes);
|
|
60
|
-
|
|
61
|
-
swaggerCrudDebug(JSON.stringify(crudSwagger, null, 2));
|
|
62
|
-
|
|
63
|
-
spec = merge(spec, crudSwagger);
|
|
64
|
-
} catch (error) {
|
|
65
|
-
// eslint-disable-next-line no-console
|
|
66
|
-
console.log(error);
|
|
67
|
-
throw new Error("Please install @visulima/crud to use the crud swagger generator.");
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (typeof request.headers.accept === "string" && /yaml|yml/.test(request.headers.accept)) {
|
|
72
|
-
response.statusCode = 200;
|
|
73
|
-
response.setHeader("Content-Type", request.headers.accept);
|
|
74
|
-
response.end(yamlTransformer(spec));
|
|
75
|
-
} else {
|
|
76
|
-
response.statusCode = 200;
|
|
77
|
-
response.setHeader("Content-Type", "application/json");
|
|
78
|
-
response.end(JSON.stringify(spec, null, 2));
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export default swaggerHandler;
|
package/src/utils.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage } from "node:http";
|
|
2
|
-
import { parse as urlParse } from "node:url";
|
|
3
|
-
|
|
4
|
-
type IncomingApiRequest<TApiRequest = IncomingMessage> = TApiRequest & {
|
|
5
|
-
body?: any;
|
|
6
|
-
query?: any;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const jsonResponse = (response: any, status: number, data?: unknown): void => {
|
|
10
|
-
response.statusCode = status;
|
|
11
|
-
response.setHeader("Content-Type", "application/json");
|
|
12
|
-
response.end(data ? JSON.stringify(data) : "");
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const parseBody = async (request: IncomingApiRequest): Promise<unknown> => {
|
|
16
|
-
if (request.body) {
|
|
17
|
-
return request.body;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const buffers = [];
|
|
21
|
-
|
|
22
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
23
|
-
for await (const chunk of request) {
|
|
24
|
-
buffers.push(chunk);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const data = Buffer.concat(buffers).toString();
|
|
28
|
-
|
|
29
|
-
return data ? JSON.parse(data) : null;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const parseQuery = (request: IncomingApiRequest): unknown => {
|
|
33
|
-
if (request.query) {
|
|
34
|
-
return request.query;
|
|
35
|
-
}
|
|
36
|
-
return urlParse(request.url ?? "", true).query;
|
|
37
|
-
};
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { ParseInput, ParseReturnType, ZodTypeDef } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
addIssueToContext, INVALID, ZodIssueCode, ZodParsedType, ZodType,
|
|
4
|
-
} from "zod";
|
|
5
|
-
|
|
6
|
-
const zodDateInKind = "ZodDateIn";
|
|
7
|
-
|
|
8
|
-
// simple regex for ISO date, supports the following formats:
|
|
9
|
-
// 2021-01-01T00:00:00.000Z
|
|
10
|
-
// 2021-01-01T00:00:00Z
|
|
11
|
-
// 2021-01-01T00:00:00
|
|
12
|
-
// 2021-01-01
|
|
13
|
-
export const isoDateRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?)?Z?$/;
|
|
14
|
-
|
|
15
|
-
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
16
|
-
export interface ZodDateInDef extends ZodTypeDef {
|
|
17
|
-
typeName: typeof zodDateInKind;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class ZodDateIn extends ZodType<Date, ZodDateInDef, string> {
|
|
21
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
22
|
-
_parse(input: ParseInput): ParseReturnType<Date> {
|
|
23
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
24
|
-
const { status, ctx } = this._processInputParams(input);
|
|
25
|
-
if (ctx.parsedType !== ZodParsedType.string) {
|
|
26
|
-
addIssueToContext(ctx, {
|
|
27
|
-
code: ZodIssueCode.invalid_type,
|
|
28
|
-
expected: ZodParsedType.string,
|
|
29
|
-
received: ctx.parsedType,
|
|
30
|
-
});
|
|
31
|
-
return INVALID;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (!isoDateRegex.test(ctx.data as string)) {
|
|
35
|
-
addIssueToContext(ctx, {
|
|
36
|
-
code: ZodIssueCode.invalid_string,
|
|
37
|
-
validation: "regex",
|
|
38
|
-
});
|
|
39
|
-
status.dirty();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const date = new Date(ctx.data);
|
|
43
|
-
|
|
44
|
-
if (Number.isNaN(date.getTime())) {
|
|
45
|
-
addIssueToContext(ctx, {
|
|
46
|
-
code: ZodIssueCode.invalid_date,
|
|
47
|
-
});
|
|
48
|
-
return INVALID;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return { status: status.value, value: date };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
static create = () => new ZodDateIn({
|
|
55
|
-
typeName: zodDateInKind,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { ParseInput, ParseReturnType, ZodTypeDef } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
addIssueToContext, INVALID, ZodIssueCode, ZodParsedType, ZodType,
|
|
4
|
-
} from "zod";
|
|
5
|
-
|
|
6
|
-
const zodDateOutKind = "ZodDateOut";
|
|
7
|
-
|
|
8
|
-
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
9
|
-
export interface ZodDateOutDef extends ZodTypeDef {
|
|
10
|
-
typeName: typeof zodDateOutKind;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class ZodDateOut extends ZodType<string, ZodDateOutDef, Date> {
|
|
14
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
15
|
-
_parse(input: ParseInput): ParseReturnType<string> {
|
|
16
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
17
|
-
const { status, ctx } = this._processInputParams(input);
|
|
18
|
-
|
|
19
|
-
if (ctx.parsedType !== ZodParsedType.date) {
|
|
20
|
-
addIssueToContext(ctx, {
|
|
21
|
-
code: ZodIssueCode.invalid_type,
|
|
22
|
-
expected: ZodParsedType.date,
|
|
23
|
-
received: ctx.parsedType,
|
|
24
|
-
});
|
|
25
|
-
return INVALID;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (Number.isNaN(ctx.data.getTime())) {
|
|
29
|
-
addIssueToContext(ctx, {
|
|
30
|
-
code: ZodIssueCode.invalid_date,
|
|
31
|
-
});
|
|
32
|
-
return INVALID;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return { status: status.value, value: (ctx.data as Date).toISOString() };
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
static create = () => new ZodDateOut({
|
|
39
|
-
typeName: zodDateOutKind,
|
|
40
|
-
});
|
|
41
|
-
}
|
package/src/zod/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { withGetType } from "zod-to-ts";
|
|
2
|
-
|
|
3
|
-
import { ZodDateIn } from "./date-in-schema";
|
|
4
|
-
import { ZodDateOut } from "./date-out-schema";
|
|
5
|
-
|
|
6
|
-
// eslint-disable-next-line max-len
|
|
7
|
-
export const dateIn = (...parameters: Parameters<typeof ZodDateIn.create>) => withGetType(ZodDateIn.create(...parameters), (ts) => ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword));
|
|
8
|
-
// eslint-disable-next-line max-len
|
|
9
|
-
export const dateOut = (...parameters: Parameters<typeof ZodDateOut.create>) => withGetType(ZodDateOut.create(...parameters), (ts) => ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword));
|