Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/smikhalevski/jtdc
JSON Type Definition to TypeScript compiler.
https://github.com/smikhalevski/jtdc
compile guard json-schema jtd narrowing ts typescript validator
Last synced: 3 days ago
JSON representation
JSON Type Definition to TypeScript compiler.
- Host: GitHub
- URL: https://github.com/smikhalevski/jtdc
- Owner: smikhalevski
- License: mit
- Created: 2021-07-05T11:54:15.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2021-12-03T15:28:43.000Z (almost 3 years ago)
- Last Synced: 2024-10-27T10:04:52.949Z (18 days ago)
- Topics: compile, guard, json-schema, jtd, narrowing, ts, typescript, validator
- Language: TypeScript
- Homepage: https://smikhalevski.github.io/jtdc/
- Size: 770 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# JTDc
[JSON Type Definition (RFC8927)](https://jsontypedef.com/) to TypeScript compiler.
- Compile enums, interface and types;
- Modify naming of enums, enum keys and values, interfaces, types, properties and any other rendered entities;
- Compile validator functions that produce an array of detected validation errors;
- Validators support recursive structures and shallow checks;
- Compile [type narrowing functions](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) aka type guards;
- Create custom validator dialect and have explicit control over every aspect of code generation;
- CLI and programmatic usage;[Full API documentation.](https://smikhalevski.github.io/jtdc/)
```shell
npm install --save-dev @jtdc/cli
```By default, validators and type guards use a `@jtdc/jtd-dialect` runtime dependency. You can alter validator compiler
dialect by providing `validatorDialectFactory` option to the compiler.```shell
npm install --save-prod @jtdc/jtd-dialect
```## CLI usage
Let's assume you have user and account type definitions in separate files under `./src` folder:
./src/user.json
```json
{
"user": {
"properties": {
"email": {"type": "string"},
"friends": {
"elements": {"ref": "user"}
}
},
"optionalProperties": {
"name": {"type": "string"},
"age": {"type": "int8"}
}
}
}
```
./src/account.json
```json
{
"account": {
"properties": {
"user": {"ref": "./user.json#user"},
"stats": {
"properties": {
"visitCount": {"type": "int32"}
}
}
},
"optionalProperties": {
"roles": {
"metadata": {
"comment": "The default role is guest"
},
"elements": {"ref": "role"}
}
}
},
"role": {
"enum": ["admin", "guest"]
}
}
```To compile these definitions to TypeScript use this command:
```sh
npx jtdc --package @jtdc/cli --rootDir ./src --includes '*.json' --outDir ./src/gen --typeGuards
```The result would be output to `./src/gen` folder:
./src/gen/user.ts
```ts
import * as runtime from '@jtdc/jtd-dialect/lib/runtime';export interface User {
email: string;
friends: Array;
name?: string;
age?: number;
}export let validateUser: runtime.Validator = (a, b, c) => {
let d, e, f, g, h;
b = b || {};
c = c || '';
if (runtime.checkObject(a, b, c)) {
runtime.checkString(a.email, b, c + '/email');
d = a.friends;
e = c + '/friends';
if (runtime.checkArray(d, b, e)) {
for (f = 0; f < d.length; f++) {
validateUser(d[f], b, e + runtime.JSON_POINTER_SEPARATOR + f);
}
}
g = a.name;
if (runtime.isDefined(g)) {
runtime.checkString(g, b, c + '/name');
}
h = a.age;
if (runtime.isDefined(h)) {
runtime.checkInteger(h, b, c + '/age');
}
}
return b.errors;
};export let isUser = (value: unknown): value is User => !validateUser(value, {shallow: true});
```
./src/gen/account.ts
```ts
import * as runtime from '@jtdc/jtd-dialect/lib/runtime';
import {User, validateUser} from './user';export interface Account {
user: User;
stats: { visitCount: number; };
/**
* The default role is guest
*/
roles?: Array;
}export enum Role {
ADMIN = 'admin',
GUEST = 'guest',
}export let validateAccount: runtime.Validator = (a, b, c) => {
let d, e, f, g, h;
b = b || {};
c = c || '';
if (runtime.checkObject(a, b, c)) {
validateUser(a.user, b, c + '/user');
d = a.stats;
e = c + '/stats';
if (runtime.checkObject(d, b, e)) {
runtime.checkInteger(d.visitCount, b, e + '/visitCount');
}
f = a.roles;
if (runtime.isDefined(f)) {
g = c + '/roles';
if (runtime.checkArray(f, b, g)) {
for (h = 0; h < f.length; h++) {
validateRole(f[h], b, g + runtime.JSON_POINTER_SEPARATOR + h);
}
}
}
}
return b.errors;
};export let isAccount = (value: unknown): value is Account => !validateAccount(value, {shallow: true});
export let validateRole: runtime.Validator = (a, b, c) => {
b = b || {};
runtime.checkEnum(a, (validateRole.cache ||= {}).a ||= ['admin', 'guest'], b, c || '');
return b.errors;
};export let isRole = (value: unknown): value is Role => !validateRole(value, {shallow: true});
```You can find [the source code of this example here](./example).
## Programmatic usage
[Full API documentation.](https://smikhalevski.github.io/jtdc/)
```ts
import {compileModules} from '@jtdc/compiler';
import userJson from './src/user.json';
import accountJson from './src/account.json';compileModules({
'./user': userJson,
'./account': accountJson,
});
// → {'./user': 'import …', './account': 'import …'}
```