@xube/kit-generator 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/dist/index.d.ts +7 -0
- package/dist/index.js +23 -0
- package/dist/type/exports.d.ts +2 -0
- package/dist/type/exports.js +53 -0
- package/dist/type/identifier.d.ts +1 -0
- package/dist/type/identifier.js +14 -0
- package/dist/type/predicates.d.ts +2 -0
- package/dist/type/predicates.js +25 -0
- package/dist/type/type-helpers.d.ts +1 -0
- package/dist/type/type-helpers.js +2 -0
- package/dist/type/type-schema.d.ts +7 -0
- package/dist/type/type-schema.js +33 -0
- package/dist/type/types.d.ts +9 -0
- package/dist/type/types.js +40 -0
- package/dist/type/validators.d.ts +10 -0
- package/dist/type/validators.js +45 -0
- package/package.json +32 -0
- package/src/index.ts +7 -0
- package/src/type/exports.ts +38 -0
- package/src/type/identifier.ts +11 -0
- package/src/type/predicates.ts +32 -0
- package/src/type/type-helpers.ts +2 -0
- package/src/type/type-schema.ts +33 -0
- package/src/type/types.ts +50 -0
- package/src/type/validators.ts +57 -0
- package/tsconfig.json +13 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./type/exports"), exports);
|
|
18
|
+
__exportStar(require("./type/identifier"), exports);
|
|
19
|
+
__exportStar(require("./type/predicates"), exports);
|
|
20
|
+
__exportStar(require("./type/type-helpers"), exports);
|
|
21
|
+
__exportStar(require("./type/type-schema"), exports);
|
|
22
|
+
__exportStar(require("./type/types"), exports);
|
|
23
|
+
__exportStar(require("./type/validators"), exports);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.generateExportIndex = void 0;
|
|
27
|
+
const fs_1 = require("fs");
|
|
28
|
+
const pascal_case_1 = require("pascal-case");
|
|
29
|
+
const path_1 = __importStar(require("path"));
|
|
30
|
+
const isValidatorPath = (filePath) => filePath.includes("validators/");
|
|
31
|
+
const generateExportIndex = (filePaths, rootDir) => {
|
|
32
|
+
const dir = (0, path_1.join)(rootDir, "generated");
|
|
33
|
+
const exports = filePaths.map((filePath) => {
|
|
34
|
+
let exportString = "export ";
|
|
35
|
+
if (isValidatorPath(filePath)) {
|
|
36
|
+
exportString += `{validate as validate${(0, pascal_case_1.pascalCase)(path_1.default.parse(filePath).name)}} `;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
exportString += "* ";
|
|
40
|
+
}
|
|
41
|
+
return (exportString += `from '.${filePath
|
|
42
|
+
.replace(dir, "")
|
|
43
|
+
.replace(".js", "")
|
|
44
|
+
.replace(".ts", "")}'`);
|
|
45
|
+
});
|
|
46
|
+
const indexFilePath = (0, path_1.join)(dir, "index.ts");
|
|
47
|
+
(0, fs_1.writeFileSync)(indexFilePath, exports.join("\n"), {
|
|
48
|
+
flag: "w+",
|
|
49
|
+
});
|
|
50
|
+
console.log("Exported generated files");
|
|
51
|
+
return indexFilePath;
|
|
52
|
+
};
|
|
53
|
+
exports.generateExportIndex = generateExportIndex;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getIdentifierFromName: (name: string) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getIdentifierFromName = void 0;
|
|
4
|
+
const pascal_case_1 = require("pascal-case");
|
|
5
|
+
const getIdentifierFromName = (name) => {
|
|
6
|
+
const nameParts = name.split("_");
|
|
7
|
+
return nameParts.reduce((acc, curr, idx) => {
|
|
8
|
+
if (idx === 0) {
|
|
9
|
+
return `${acc}${(0, pascal_case_1.pascalCase)(curr)}`;
|
|
10
|
+
}
|
|
11
|
+
return `${acc}_${(0, pascal_case_1.pascalCase)(curr)}`;
|
|
12
|
+
}, "");
|
|
13
|
+
};
|
|
14
|
+
exports.getIdentifierFromName = getIdentifierFromName;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTypePredicateFromTypeAndValidator = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const validators_1 = require("./validators");
|
|
6
|
+
const identifier_1 = require("./identifier");
|
|
7
|
+
const generateTypePredicateFromTypeAndValidator = (name, generatedTypeFilePath) => {
|
|
8
|
+
const identifier = (0, identifier_1.getIdentifierFromName)(name);
|
|
9
|
+
const predicate = `
|
|
10
|
+
\n
|
|
11
|
+
import { XubeLog } from "@xube/kit-log";
|
|
12
|
+
import validate from "${(0, validators_1.getImportableValidatorFilePathRelativeToGeneratedFolder)(name)}";\n
|
|
13
|
+
export const is${identifier} = (item: unknown): item is ${identifier} => {
|
|
14
|
+
\tconst isValid: boolean = validate(item);
|
|
15
|
+
\tif(!isValid){
|
|
16
|
+
\t\tXubeLog.getInstance().info(JSON.stringify((validate as typeof validate & {errors: object}).errors, null, 2));
|
|
17
|
+
\t}
|
|
18
|
+
\treturn isValid;
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
(0, fs_1.appendFileSync)(generatedTypeFilePath, predicate);
|
|
22
|
+
console.log(`${name} type predicated generated`);
|
|
23
|
+
return generatedTypeFilePath;
|
|
24
|
+
};
|
|
25
|
+
exports.generateTypePredicateFromTypeAndValidator = generateTypePredicateFromTypeAndValidator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type GeneratedFilePath = string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ZodTypeAny } from "zod";
|
|
2
|
+
export * from "./predicates";
|
|
3
|
+
export * from "./type-helpers";
|
|
4
|
+
export * from "./types";
|
|
5
|
+
export * from "./validators";
|
|
6
|
+
export * from "./exports";
|
|
7
|
+
export declare const generateTypeSchemaFiles: (name: string, schema: ZodTypeAny, rootDir: string) => [string, string];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.generateTypeSchemaFiles = void 0;
|
|
18
|
+
const types_1 = require("./types");
|
|
19
|
+
const validators_1 = require("./validators");
|
|
20
|
+
const predicates_1 = require("./predicates");
|
|
21
|
+
__exportStar(require("./predicates"), exports);
|
|
22
|
+
__exportStar(require("./type-helpers"), exports);
|
|
23
|
+
__exportStar(require("./types"), exports);
|
|
24
|
+
__exportStar(require("./validators"), exports);
|
|
25
|
+
__exportStar(require("./exports"), exports);
|
|
26
|
+
const generateTypeSchemaFiles = (name, schema, rootDir) => {
|
|
27
|
+
const validatorFilePath = (0, validators_1.generateValidatorsFromZodSchema)(name, schema, rootDir);
|
|
28
|
+
const typeFilePath = (0, types_1.generateTypesFromZodSchema)(name, schema, rootDir);
|
|
29
|
+
(0, predicates_1.generateTypePredicateFromTypeAndValidator)(name, typeFilePath);
|
|
30
|
+
console.log(`${name} type, type predicate and schema generated`);
|
|
31
|
+
return [validatorFilePath, typeFilePath];
|
|
32
|
+
};
|
|
33
|
+
exports.generateTypeSchemaFiles = generateTypeSchemaFiles;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ZodTypeAny } from "zod";
|
|
2
|
+
import { GeneratedFilePath } from "./type-helpers";
|
|
3
|
+
/**
|
|
4
|
+
* Function that generates TS Type from Zod Schema
|
|
5
|
+
*
|
|
6
|
+
* @param name The name of the schema. The outputted compiled validation file will be <name>.ts
|
|
7
|
+
* @param schema The zod schema
|
|
8
|
+
*/
|
|
9
|
+
export declare const generateTypesFromZodSchema: (name: string, schema: ZodTypeAny, rootDir: string) => GeneratedFilePath;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTypesFromZodSchema = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const zod_to_ts_1 = require("zod-to-ts");
|
|
7
|
+
const identifier_1 = require("./identifier");
|
|
8
|
+
/**
|
|
9
|
+
* Function that generates TS Type from Zod Schema
|
|
10
|
+
*
|
|
11
|
+
* @param name The name of the schema. The outputted compiled validation file will be <name>.ts
|
|
12
|
+
* @param schema The zod schema
|
|
13
|
+
*/
|
|
14
|
+
const generateTypesFromZodSchema = (name, schema, rootDir) => {
|
|
15
|
+
if (!name) {
|
|
16
|
+
throw Error("Name must not be empty");
|
|
17
|
+
}
|
|
18
|
+
const identifier = (0, identifier_1.getIdentifierFromName)(name);
|
|
19
|
+
const typeAlias = (0, zod_to_ts_1.createTypeAlias)((0, zod_to_ts_1.zodToTs)(schema).node, identifier);
|
|
20
|
+
const dir = (0, path_1.join)(rootDir, "generated", "types");
|
|
21
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true });
|
|
22
|
+
const generatedFilePath = (0, path_1.join)(dir, `${name}.ts`);
|
|
23
|
+
const fileContents = `
|
|
24
|
+
/**
|
|
25
|
+
* I am a generated file.
|
|
26
|
+
*
|
|
27
|
+
* If you change me, you and other developers will be sad.
|
|
28
|
+
*
|
|
29
|
+
* #StayGeneratedStayHappy
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
export ${(0, zod_to_ts_1.printNode)(typeAlias)}
|
|
33
|
+
`;
|
|
34
|
+
(0, fs_1.writeFileSync)(generatedFilePath, fileContents, {
|
|
35
|
+
flag: "w+",
|
|
36
|
+
});
|
|
37
|
+
console.log(`${name} type created`);
|
|
38
|
+
return generatedFilePath;
|
|
39
|
+
};
|
|
40
|
+
exports.generateTypesFromZodSchema = generateTypesFromZodSchema;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ZodType, ZodTypeDef } from "zod";
|
|
2
|
+
import { GeneratedFilePath } from "./type-helpers";
|
|
3
|
+
/**
|
|
4
|
+
* Function that generates compiled ajv validation for fast validation of unknown data
|
|
5
|
+
*
|
|
6
|
+
* @param name The name of the schema. The outputted compiled validation file will be <name>.js
|
|
7
|
+
* @param schema The zod schema
|
|
8
|
+
*/
|
|
9
|
+
export declare const generateValidatorsFromZodSchema: (name: string, schema: ZodType<any, ZodTypeDef, any>, rootDir: string) => GeneratedFilePath;
|
|
10
|
+
export declare const getImportableValidatorFilePathRelativeToGeneratedFolder: (name: string) => string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getImportableValidatorFilePathRelativeToGeneratedFolder = exports.generateValidatorsFromZodSchema = void 0;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
10
|
+
const standalone_1 = __importDefault(require("ajv/dist/standalone"));
|
|
11
|
+
const ajv_formats_1 = __importDefault(require("ajv-formats"));
|
|
12
|
+
const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
|
|
13
|
+
/**
|
|
14
|
+
* Function that generates compiled ajv validation for fast validation of unknown data
|
|
15
|
+
*
|
|
16
|
+
* @param name The name of the schema. The outputted compiled validation file will be <name>.js
|
|
17
|
+
* @param schema The zod schema
|
|
18
|
+
*/
|
|
19
|
+
const generateValidatorsFromZodSchema = (name, schema, rootDir) => {
|
|
20
|
+
const ajv = new ajv_1.default({
|
|
21
|
+
$data: true,
|
|
22
|
+
allErrors: true,
|
|
23
|
+
useDefaults: true,
|
|
24
|
+
code: {
|
|
25
|
+
esm: true,
|
|
26
|
+
source: true,
|
|
27
|
+
},
|
|
28
|
+
strict: true,
|
|
29
|
+
});
|
|
30
|
+
(0, ajv_formats_1.default)(ajv);
|
|
31
|
+
const validationCode = (0, standalone_1.default)(ajv, ajv.compile((0, zod_to_json_schema_1.default)(schema, `${name.toLowerCase()}JsonSchema`)));
|
|
32
|
+
const dir = (0, path_1.join)(rootDir, "generated", "validators");
|
|
33
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true });
|
|
34
|
+
const generatedFilePath = (0, path_1.join)(dir, `${name}.js`);
|
|
35
|
+
(0, fs_1.writeFileSync)(generatedFilePath, validationCode, {
|
|
36
|
+
flag: "w+",
|
|
37
|
+
});
|
|
38
|
+
console.log(`${name} validator created`);
|
|
39
|
+
return generatedFilePath;
|
|
40
|
+
};
|
|
41
|
+
exports.generateValidatorsFromZodSchema = generateValidatorsFromZodSchema;
|
|
42
|
+
const getImportableValidatorFilePathRelativeToGeneratedFolder = (name) => {
|
|
43
|
+
return `../validators/${name}`;
|
|
44
|
+
};
|
|
45
|
+
exports.getImportableValidatorFilePathRelativeToGeneratedFolder = getImportableValidatorFilePathRelativeToGeneratedFolder;
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xube/kit-generator",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+ssh://git@github.com/XubeLtd/dev-kit.git"
|
|
12
|
+
},
|
|
13
|
+
"author": "Xube Pty Ltd",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/XubeLtd/dev-kit/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/XubeLtd/dev-kit#readme",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"ajv": "^8.12.0",
|
|
21
|
+
"ajv-formats": "^2.1.1",
|
|
22
|
+
"pascal-case": "^3.1.2",
|
|
23
|
+
"zod": "^3.21.4",
|
|
24
|
+
"zod-to-json-schema": "^3.21.4",
|
|
25
|
+
"zod-to-ts": "^1.1.4"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.4.7",
|
|
29
|
+
"ts-node": "^10.9.1",
|
|
30
|
+
"typescript": "^5.1.6"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { writeFileSync } from "fs";
|
|
2
|
+
import { pascalCase } from "pascal-case";
|
|
3
|
+
import path, { join } from "path";
|
|
4
|
+
import { GeneratedFilePath } from "./type-helpers";
|
|
5
|
+
|
|
6
|
+
const isValidatorPath = (filePath: string) =>
|
|
7
|
+
filePath.includes("validators/");
|
|
8
|
+
|
|
9
|
+
export const generateExportIndex = (
|
|
10
|
+
filePaths: string[],
|
|
11
|
+
rootDir: string
|
|
12
|
+
): GeneratedFilePath => {
|
|
13
|
+
const dir: string = join(rootDir, "generated");
|
|
14
|
+
const exports: string[] = filePaths.map((filePath) => {
|
|
15
|
+
let exportString = "export ";
|
|
16
|
+
if (isValidatorPath(filePath)) {
|
|
17
|
+
exportString += `{validate as validate${pascalCase(
|
|
18
|
+
path.parse(filePath).name
|
|
19
|
+
)}} `;
|
|
20
|
+
} else {
|
|
21
|
+
exportString += "* ";
|
|
22
|
+
}
|
|
23
|
+
return (exportString += `from '.${filePath
|
|
24
|
+
.replace(dir, "")
|
|
25
|
+
.replace(".js", "")
|
|
26
|
+
.replace(".ts", "")}'`);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const indexFilePath: GeneratedFilePath = join(dir, "index.ts");
|
|
30
|
+
|
|
31
|
+
writeFileSync(indexFilePath, exports.join("\n"), {
|
|
32
|
+
flag: "w+",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log("Exported generated files");
|
|
36
|
+
|
|
37
|
+
return indexFilePath;
|
|
38
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pascalCase } from "pascal-case";
|
|
2
|
+
|
|
3
|
+
export const getIdentifierFromName = (name: string): string => {
|
|
4
|
+
const nameParts: string[] = name.split("_");
|
|
5
|
+
return nameParts.reduce((acc, curr, idx) => {
|
|
6
|
+
if (idx === 0) {
|
|
7
|
+
return `${acc}${pascalCase(curr)}`;
|
|
8
|
+
}
|
|
9
|
+
return `${acc}_${pascalCase(curr)}`;
|
|
10
|
+
}, "");
|
|
11
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { appendFileSync } from "fs";
|
|
2
|
+
import { GeneratedFilePath } from "./type-helpers";
|
|
3
|
+
import { getImportableValidatorFilePathRelativeToGeneratedFolder } from "./validators";
|
|
4
|
+
import { getIdentifierFromName } from "./identifier";
|
|
5
|
+
|
|
6
|
+
export const generateTypePredicateFromTypeAndValidator = (
|
|
7
|
+
name: string,
|
|
8
|
+
generatedTypeFilePath: GeneratedFilePath
|
|
9
|
+
): GeneratedFilePath => {
|
|
10
|
+
const identifier = getIdentifierFromName(name);
|
|
11
|
+
|
|
12
|
+
const predicate: string = `
|
|
13
|
+
\n
|
|
14
|
+
import { XubeLog } from "@xube/kit-log";
|
|
15
|
+
import validate from "${getImportableValidatorFilePathRelativeToGeneratedFolder(
|
|
16
|
+
name
|
|
17
|
+
)}";\n
|
|
18
|
+
export const is${identifier} = (item: unknown): item is ${identifier} => {
|
|
19
|
+
\tconst isValid: boolean = validate(item);
|
|
20
|
+
\tif(!isValid){
|
|
21
|
+
\t\tXubeLog.getInstance().info(JSON.stringify((validate as typeof validate & {errors: object}).errors, null, 2));
|
|
22
|
+
\t}
|
|
23
|
+
\treturn isValid;
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
appendFileSync(generatedTypeFilePath, predicate);
|
|
28
|
+
|
|
29
|
+
console.log(`${name} type predicated generated`);
|
|
30
|
+
|
|
31
|
+
return generatedTypeFilePath;
|
|
32
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ZodTypeAny } from "zod";
|
|
2
|
+
import { generateTypesFromZodSchema } from "./types";
|
|
3
|
+
import { generateValidatorsFromZodSchema } from "./validators";
|
|
4
|
+
import { GeneratedFilePath } from "./type-helpers";
|
|
5
|
+
import { generateTypePredicateFromTypeAndValidator } from "./predicates";
|
|
6
|
+
|
|
7
|
+
export * from "./predicates"
|
|
8
|
+
export * from "./type-helpers";
|
|
9
|
+
export * from "./types";
|
|
10
|
+
export * from "./validators";
|
|
11
|
+
export * from "./exports";
|
|
12
|
+
|
|
13
|
+
export const generateTypeSchemaFiles = (
|
|
14
|
+
name: string,
|
|
15
|
+
schema: ZodTypeAny,
|
|
16
|
+
rootDir: string
|
|
17
|
+
): [string, string] => {
|
|
18
|
+
const validatorFilePath: GeneratedFilePath = generateValidatorsFromZodSchema(
|
|
19
|
+
name,
|
|
20
|
+
schema,
|
|
21
|
+
rootDir
|
|
22
|
+
);
|
|
23
|
+
const typeFilePath: GeneratedFilePath = generateTypesFromZodSchema(
|
|
24
|
+
name,
|
|
25
|
+
schema,
|
|
26
|
+
rootDir
|
|
27
|
+
);
|
|
28
|
+
generateTypePredicateFromTypeAndValidator(name, typeFilePath);
|
|
29
|
+
|
|
30
|
+
console.log(`${name} type, type predicate and schema generated`)
|
|
31
|
+
|
|
32
|
+
return [validatorFilePath, typeFilePath]
|
|
33
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { ZodTypeAny } from "zod";
|
|
4
|
+
import { createTypeAlias, printNode, zodToTs } from "zod-to-ts";
|
|
5
|
+
import { GeneratedFilePath } from "./type-helpers";
|
|
6
|
+
import { getIdentifierFromName } from "./identifier";
|
|
7
|
+
/**
|
|
8
|
+
* Function that generates TS Type from Zod Schema
|
|
9
|
+
*
|
|
10
|
+
* @param name The name of the schema. The outputted compiled validation file will be <name>.ts
|
|
11
|
+
* @param schema The zod schema
|
|
12
|
+
*/
|
|
13
|
+
export const generateTypesFromZodSchema = (
|
|
14
|
+
name: string,
|
|
15
|
+
schema: ZodTypeAny,
|
|
16
|
+
rootDir: string
|
|
17
|
+
): GeneratedFilePath => {
|
|
18
|
+
if (!name) {
|
|
19
|
+
throw Error("Name must not be empty");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const identifier = getIdentifierFromName(name);
|
|
23
|
+
|
|
24
|
+
const typeAlias = createTypeAlias(zodToTs(schema).node, identifier);
|
|
25
|
+
|
|
26
|
+
const dir: string = join(rootDir, "generated", "types");
|
|
27
|
+
mkdirSync(dir, { recursive: true });
|
|
28
|
+
|
|
29
|
+
const generatedFilePath: GeneratedFilePath = join(dir, `${name}.ts`);
|
|
30
|
+
|
|
31
|
+
const fileContents: string = `
|
|
32
|
+
/**
|
|
33
|
+
* I am a generated file.
|
|
34
|
+
*
|
|
35
|
+
* If you change me, you and other developers will be sad.
|
|
36
|
+
*
|
|
37
|
+
* #StayGeneratedStayHappy
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export ${printNode(typeAlias)}
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
writeFileSync(generatedFilePath, fileContents, {
|
|
44
|
+
flag: "w+",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
console.log(`${name} type created`);
|
|
48
|
+
|
|
49
|
+
return generatedFilePath;
|
|
50
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
|
|
4
|
+
import Ajv from "ajv";
|
|
5
|
+
import standaloneCode from "ajv/dist/standalone";
|
|
6
|
+
import addFormats from "ajv-formats";
|
|
7
|
+
|
|
8
|
+
import zodToJsonSchema from "zod-to-json-schema";
|
|
9
|
+
import { ZodType, ZodTypeDef } from "zod";
|
|
10
|
+
import { GeneratedFilePath } from "./type-helpers";
|
|
11
|
+
/**
|
|
12
|
+
* Function that generates compiled ajv validation for fast validation of unknown data
|
|
13
|
+
*
|
|
14
|
+
* @param name The name of the schema. The outputted compiled validation file will be <name>.js
|
|
15
|
+
* @param schema The zod schema
|
|
16
|
+
*/
|
|
17
|
+
export const generateValidatorsFromZodSchema = (
|
|
18
|
+
name: string,
|
|
19
|
+
schema: ZodType<any, ZodTypeDef, any>,
|
|
20
|
+
rootDir: string
|
|
21
|
+
): GeneratedFilePath => {
|
|
22
|
+
const ajv = new Ajv({
|
|
23
|
+
$data: true,
|
|
24
|
+
allErrors: true,
|
|
25
|
+
useDefaults: true,
|
|
26
|
+
code: {
|
|
27
|
+
esm: true,
|
|
28
|
+
source: true,
|
|
29
|
+
},
|
|
30
|
+
strict: true,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
addFormats(ajv);
|
|
34
|
+
const validationCode = standaloneCode(
|
|
35
|
+
ajv,
|
|
36
|
+
ajv.compile(zodToJsonSchema(schema, `${name.toLowerCase()}JsonSchema`))
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const dir: string = join(rootDir, "generated", "validators");
|
|
40
|
+
mkdirSync(dir, { recursive: true });
|
|
41
|
+
|
|
42
|
+
const generatedFilePath: GeneratedFilePath = join(dir, `${name}.js`);
|
|
43
|
+
|
|
44
|
+
writeFileSync(generatedFilePath, validationCode, {
|
|
45
|
+
flag: "w+",
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
console.log(`${name} validator created`)
|
|
49
|
+
|
|
50
|
+
return generatedFilePath;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const getImportableValidatorFilePathRelativeToGeneratedFolder = (
|
|
54
|
+
name: string
|
|
55
|
+
) => {
|
|
56
|
+
return `../validators/${name}`;
|
|
57
|
+
};
|
package/tsconfig.json
ADDED