Skip to content

Commit

Permalink
Merge pull request #477 from streamich/jtd
Browse files Browse the repository at this point in the history
JTD support in `json-type`
  • Loading branch information
streamich authored Dec 7, 2023
2 parents 548a10c + c7b740b commit 76908ec
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 0 deletions.
70 changes: 70 additions & 0 deletions src/json-type/jtd/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// prettier-ignore
export type JtdForm =
| JtdEmptyForm
| JtdRefForm
| JtdTypeForm
| JtdEnumForm
| JtdElementsForm
| JtdPropertiesForm
| JtdValuesForm
| JtdDiscriminatorForm
;

export interface JtdFormBase {
metadata?: Record<string, unknown>;
}

export interface JtdEmptyForm extends JtdFormBase {
nullable?: boolean;
}

export interface JtdRefForm extends JtdFormBase {
ref: string;
}

export interface JtdTypeForm extends JtdFormBase {
type: JtdType;
}

// prettier-ignore
export type JtdType =
| 'boolean'
| 'float32'
| 'float64'
| 'int8'
| 'uint8'
| 'int16'
| 'uint16'
| 'int32'
| 'uint32'
| 'string'
| 'timestamp'
;

export interface JtdEnumForm extends JtdFormBase {
enum: string[];
}

export interface JtdElementsForm extends JtdFormBase {
elements: JtdForm[];
}

export interface JtdPropertiesForm extends JtdFormBase {
properties?: Record<string, JtdForm>;
optionalProperties?: Record<string, JtdForm>;
additionalProperties?: boolean;
}

export interface JtdValuesForm extends JtdFormBase {
values: JtdForm;
}

export interface JtdDiscriminatorForm extends JtdFormBase {
discriminator: string;
mapping: Record<string, JtdForm>;
}

export interface JtdError {
instancePath: string;
schemaPath: string;
}
6 changes: 6 additions & 0 deletions src/json-type/type/classes/AbstractType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import type {json_string} from '../../../json-brand';
import type * as ts from '../../typescript/types';
import type {TypeExportContext} from '../../system/TypeExportContext';
import type {Validators} from './types';
import type * as jtd from '../../jtd/types';

export abstract class AbstractType<S extends schema.Schema> implements BaseType<S>, Printable {
/** Default type system to use, if any. */
Expand Down Expand Up @@ -299,4 +300,9 @@ export abstract class AbstractType<S extends schema.Schema> implements BaseType<
const options = this.toStringOptions();
return this.toStringTitle() + (options ? ` ${options}` : '');
}

public toJtdForm(): jtd.JtdForm {
const form: jtd.JtdEmptyForm = {nullable: false};
return form;
}
}
6 changes: 6 additions & 0 deletions src/json-type/type/classes/AnyType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {AbstractType} from './AbstractType';
import type * as jsonSchema from '../../../json-schema';
import type * as ts from '../../typescript/types';
import type {TypeExportContext} from '../../system/TypeExportContext';
import type * as jtd from '../../jtd/types';

export class AnyType extends AbstractType<schema.AnySchema> {
constructor(protected schema: schema.AnySchema) {
Expand Down Expand Up @@ -111,4 +112,9 @@ export class AnyType extends AbstractType<schema.AnySchema> {
public toTypeScriptAst(): ts.TsType {
return {node: 'AnyKeyword'};
}

public toJtdForm(): jtd.JtdEmptyForm {
const form: jtd.JtdEmptyForm = {nullable: true};
return form;
}
}
6 changes: 6 additions & 0 deletions src/json-type/type/classes/BooleanType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {TypeSystem} from '../../system/TypeSystem';
import type {json_string} from '../../../json-brand';
import type * as ts from '../../typescript/types';
import type {TypeExportContext} from '../../system/TypeExportContext';
import type * as jtd from '../../jtd/types';

export class BooleanType extends AbstractType<schema.BooleanSchema> {
constructor(protected schema: schema.BooleanSchema) {
Expand Down Expand Up @@ -77,4 +78,9 @@ export class BooleanType extends AbstractType<schema.BooleanSchema> {
public toJson(value: unknown, system: TypeSystem | undefined = this.system) {
return (value ? 'true' : 'false') as json_string<boolean>;
}

public toJtdForm(): jtd.JtdTypeForm {
const form: jtd.JtdTypeForm = {type: 'boolean'};
return form;
}
}
25 changes: 25 additions & 0 deletions src/json-type/type/classes/ConstType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {TypeSystem} from '../../system/TypeSystem';
import type {json_string} from '../../../json-brand';
import type * as ts from '../../typescript/types';
import type {TypeExportContext} from '../../system/TypeExportContext';
import type * as jtd from '../../jtd/types';

export class ConstType<V = any> extends AbstractType<schema.ConstSchema<V>> {
private __json: json_string<V>;
Expand Down Expand Up @@ -128,4 +129,28 @@ export class ConstType<V = any> extends AbstractType<schema.ConstSchema<V>> {
public toString(tab: string = ''): string {
return `${super.toString(tab)}${JSON.stringify(this.schema.value)}`;
}

public toJtdForm(): jtd.JtdForm {
const value = this.value();
const type = typeof value;
switch (type) {
case 'boolean':
case 'string':
return {type};
case 'number': {
if (value !== Math.round(value)) return {type: 'float64'};
if (value >= 0) {
if (value <= 255) return {type: 'uint8'};
if (value <= 65535) return {type: 'uint16'};
if (value <= 4294967295) return {type: 'uint32'};
} else {
if (value >= -128) return {type: 'int8'};
if (value >= -32768) return {type: 'int16'};
if (value >= -2147483648) return {type: 'int32'};
}
return {type: 'float64'};
}
}
return super.toJtdForm();
}
}
22 changes: 22 additions & 0 deletions src/json-type/type/classes/NumberType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {TypeSystem} from '../../system/TypeSystem';
import type {json_string} from '../../../json-brand';
import type * as ts from '../../typescript/types';
import type {TypeExportContext} from '../../system/TypeExportContext';
import type * as jtd from '../../jtd/types';

export class NumberType extends AbstractType<schema.NumberSchema> {
constructor(protected schema: schema.NumberSchema) {
Expand Down Expand Up @@ -229,4 +230,25 @@ export class NumberType extends AbstractType<schema.NumberSchema> {
public toJson(value: unknown, system: TypeSystem | undefined = this.system) {
return ('' + value) as json_string<number>;
}

public toJtdForm(): jtd.JtdTypeForm {
switch (this.schema.format) {
case 'u8':
return {type: 'uint8'};
case 'u16':
return {type: 'uint16'};
case 'u32':
return {type: 'uint32'};
case 'i8':
return {type: 'int8'};
case 'i16':
return {type: 'int16'};
case 'i32':
return {type: 'int32'};
case 'f32':
return {type: 'float32'};
default:
return {type: 'float64'};
}
}
}
5 changes: 5 additions & 0 deletions src/json-type/type/classes/StringType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {TypeSystem} from '../../system/TypeSystem';
import type {json_string} from '../../../json-brand';
import type * as ts from '../../typescript/types';
import type {TypeExportContext} from '../../system/TypeExportContext';
import type * as jtd from '../../jtd/types';

export class StringType extends AbstractType<schema.StringSchema> {
constructor(protected schema: schema.StringSchema) {
Expand Down Expand Up @@ -118,4 +119,8 @@ export class StringType extends AbstractType<schema.StringSchema> {
public toJson(value: unknown, system: TypeSystem | undefined = this.system): json_string<unknown> {
return <json_string<string>>(this.schema.noJsonEscape ? '"' + value + '"' : asString(value as string));
}

public toJtdForm(): jtd.JtdTypeForm {
return {type: 'string'};
}
}

0 comments on commit 76908ec

Please sign in to comment.