Skip to content

Commit

Permalink
Merge pull request #1009 from samchon/features/title
Browse files Browse the repository at this point in the history
Custom JSON schema definer
  • Loading branch information
samchon authored Mar 19, 2024
2 parents 0ed7d40 + 27f978c commit ff2864c
Show file tree
Hide file tree
Showing 202 changed files with 14,849 additions and 10,508 deletions.
2 changes: 1 addition & 1 deletion benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@
"suppress-warnings": "^1.0.2",
"tstl": "^2.5.13",
"uuid": "^9.0.1",
"typia": "D:\\github\\samchon\\typia@master\\typia-5.5.6-dev.20240319.tgz"
"typia": "D:\\github\\samchon\\typia@master\\typia-5.5.7.tgz"
}
}
34 changes: 34 additions & 0 deletions debug/features/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import typia, { tags } from "typia";

type Monetary<Value extends string> = tags.TagBase<{
target: "number";
kind: "monetary";
value: Value;
schema: {
"x-monetary": Value;
};
}>;

type Placeholder<Value extends string> = tags.TagBase<{
target: "string";
kind: "placeholder";
value: Value;
schema: {
"x-placeholder": Value;
};
}>;

console.log(
JSON.stringify(
typia.json.application<
[
number & Monetary<"dollar">,
string &
tags.Format<"email"> &
Placeholder<"Insert your email address please">,
]
>(),
null,
2,
),
);
2 changes: 1 addition & 1 deletion debug/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
"typescript": "^5.4.2"
},
"dependencies": {
"typia": "D:\\github\\samchon\\typia@master\\typia-5.5.5-dev.20240314.tgz"
"typia": "D:\\github\\samchon\\typia@master\\typia-5.5.7-dev.20240320.tgz"
}
}
2 changes: 1 addition & 1 deletion errors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
"typescript": "^5.3.2"
},
"dependencies": {
"typia": "D:\\github\\samchon\\typia@master\\typia-5.5.6-dev.20240319.tgz"
"typia": "D:\\github\\samchon\\typia@master\\typia-5.5.7.tgz"
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typia",
"version": "5.5.5",
"version": "5.5.7",
"description": "Superfast runtime validators with only one line",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions packages/typescript-json/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typescript-json",
"version": "5.5.6-dev.20240319",
"version": "5.5.7",
"description": "Superfast runtime validators with only one line",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -62,7 +62,7 @@
},
"homepage": "https://typia.io",
"dependencies": {
"typia": "5.5.6-dev.20240319"
"typia": "5.5.7"
},
"peerDependencies": {
"typescript": ">=4.8.0 <5.5.0"
Expand Down
73 changes: 64 additions & 9 deletions src/factories/MetadataCommentTagFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ type TagRecord = {
[P in Target]?: NotDeterminedTypeTag[];
};
type Target = "bigint" | "number" | "string" | "array";
type NotDeterminedTypeTag = Omit<IMetadataTypeTag, "validate"> & {
type NotDeterminedTypeTag = Omit<IMetadataTypeTag, "validate" | "schema"> & {
validate: string | null;
schema: object | undefined;
};

const PARSER: Record<
Expand All @@ -139,6 +140,9 @@ const PARSER: Record<
value: parse_integer(report)(true)(Value),
validate: `${Value} <= $input.length`,
exclusive: true,
schema: {
minItems: parse_integer(report)(true)(Value),
},
},
{
name: `MaxItems<${Value}>`,
Expand All @@ -147,6 +151,9 @@ const PARSER: Record<
value: parse_integer(report)(true)(Value),
validate: `$input.length <= ${Value}`,
exclusive: true,
schema: {
maxItems: parse_integer(report)(true)(Value),
},
},
],
}),
Expand All @@ -159,6 +166,9 @@ const PARSER: Record<
value: parse_integer(report)(true)(Value),
validate: `${Value} <= $input.length`,
exclusive: true,
schema: {
minItems: parse_integer(report)(true)(Value),
},
},
],
}),
Expand All @@ -171,6 +181,9 @@ const PARSER: Record<
value: parse_integer(report)(true)(Value),
validate: `$input.length <= ${Value}`,
exclusive: true,
schema: {
maxItems: parse_integer(report)(true)(Value),
},
},
],
}),
Expand Down Expand Up @@ -203,15 +216,16 @@ const PARSER: Record<
Value === "int32"
? `Math.floor($input) === $input && -2147483648 <= $input && $input <= 2147483647`
: Value === "uint32"
? `Math.floor($input) === $input && 0 <= $input && $input <= 4294967295`
: Value === "int64"
? `Math.floor($input) === $input && -9223372036854775808 <= $input && $input <= 9223372036854775807`
: Value === "uint64"
? `Math.floor($input) === $input && 0 <= $input && $input <= 18446744073709551615`
: Value === "float"
? `-1.175494351e38 <= $input && $input <= 3.4028235e38`
: `true`,
? `Math.floor($input) === $input && 0 <= $input && $input <= 4294967295`
: Value === "int64"
? `Math.floor($input) === $input && -9223372036854775808 <= $input && $input <= 9223372036854775807`
: Value === "uint64"
? `Math.floor($input) === $input && 0 <= $input && $input <= 18446744073709551615`
: Value === "float"
? `-1.175494351e38 <= $input && $input <= 3.4028235e38`
: `true`,
exclusive: true,
schema: undefined,
},
],
bigint:
Expand All @@ -224,6 +238,7 @@ const PARSER: Record<
value: Value,
validate: Value === "int64" ? "true" : "BigInt(0) <= $input",
exclusive: true,
schema: undefined,
},
]
: [],
Expand All @@ -238,6 +253,9 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `${Value} <= $input`,
exclusive: ["minimum", "exclusiveMinimum"],
schema: {
minimum: parse_number(report)(Value),
},
},
],
bigint: [
Expand All @@ -251,6 +269,7 @@ const PARSER: Record<
})(),
validate: `${Value} <= $input`,
exclusive: ["minimum", "exclusiveMinimum"],
schema: undefined,
},
],
}),
Expand All @@ -263,6 +282,9 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `$input <= ${Value}`,
exclusive: ["maximum", "exclusiveMaximum"],
schema: {
maximum: parse_number(report)(Value),
},
},
],
bigint: [
Expand All @@ -276,6 +298,7 @@ const PARSER: Record<
})(),
validate: `$input <= ${Value}`,
exclusive: ["maximum", "exclusiveMaximum"],
schema: undefined,
},
],
}),
Expand All @@ -288,6 +311,10 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `${Value} < $input`,
exclusive: ["minimum", "exclusiveMinimum"],
schema: {
exclusiveMinimum: true,
minimum: parse_number(report)(Value),
},
},
],
bigint: [
Expand All @@ -301,6 +328,7 @@ const PARSER: Record<
})(),
validate: `${Value} < $input`,
exclusive: ["minimum", "exclusiveMinimum"],
schema: undefined,
},
],
}),
Expand All @@ -313,6 +341,10 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `$input < ${Value}`,
exclusive: ["maximum", "exclusiveMaximum"],
schema: {
exclusiveMaximum: true,
maximum: parse_number(report)(Value),
},
},
],
bigint: [
Expand All @@ -326,6 +358,7 @@ const PARSER: Record<
})(),
validate: `$input < ${Value}`,
exclusive: ["maximum", "exclusiveMaximum"],
schema: undefined,
},
],
}),
Expand All @@ -338,6 +371,9 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `$input % ${Value} === 0`,
exclusive: true,
schema: {
multipleOf: parse_number(report)(Value),
},
},
],
bigint: [
Expand All @@ -351,6 +387,7 @@ const PARSER: Record<
})(),
validate: `$input % ${Value}n === 0n`,
exclusive: true,
schema: undefined,
},
],
}),
Expand All @@ -370,6 +407,9 @@ const PARSER: Record<
value: matched[0],
validate: matched[1],
exclusive: true,
schema: {
format: matched[0],
},
},
],
};
Expand All @@ -383,6 +423,9 @@ const PARSER: Record<
value: Value,
validate: `RegExp(/${Value}/).test($input)`,
exclusive: ["format"],
schema: {
pattern: Value,
},
},
],
}),
Expand All @@ -395,6 +438,9 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `${Value} <= $input.length`,
exclusive: true,
schema: {
minLength: parse_number(report)(Value),
},
},
{
name: `MaxLength<${Value}>`,
Expand All @@ -403,6 +449,9 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `$input.length <= ${Value}`,
exclusive: true,
schema: {
maxLength: parse_number(report)(Value),
},
},
],
}),
Expand All @@ -415,6 +464,9 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `${Value} <= $input.length`,
exclusive: true,
schema: {
minLength: parse_number(report)(Value),
},
},
],
}),
Expand All @@ -427,6 +479,9 @@ const PARSER: Record<
value: parse_number(report)(Value),
validate: `$input.length <= ${Value}`,
exclusive: true,
schema: {
maxLength: parse_number(report)(Value),
},
},
],
}),
Expand Down
21 changes: 20 additions & 1 deletion src/factories/MetadataTypeTagFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { MetadataObject } from "../schemas/metadata/MetadataObject";
import { MetadataProperty } from "../schemas/metadata/MetadataProperty";

import { MetadataFactory } from "./MetadataFactory";
import { MetadataTypeTagSchemaFactory } from "./MetadataTypeTagSchemaFactory";

export namespace MetadataTypeTagFactory {
export const analyze =
Expand Down Expand Up @@ -83,6 +84,7 @@ export namespace MetadataTypeTagFactory {
value: tag.value,
validate: tag.validate[type]!,
exclusive: tag.exclusive,
schema: tag.schema,
});
validate(report)(type)(output);

Expand Down Expand Up @@ -256,14 +258,30 @@ export namespace MetadataTypeTagFactory {
]),
);
})();

const schema: object | undefined = (() => {
const p: Metadata | undefined = find("schema")?.value;
if (p === undefined) return undefined;
else if (p.size() === 0 && p.isRequired() === false) return undefined;
else if (
p.size() === 1 &&
p.nullable === false &&
p.isRequired() === true &&
p.any === false
)
return MetadataTypeTagSchemaFactory.object((msg) =>
report("schema")(msg),
)(p.objects[0]!);
report("schema")("must be an object type");
return undefined;
})();
return {
name: obj.name,
target,
kind,
value,
validate,
exclusive: exclusive ?? false,
schema,
};
};

Expand Down Expand Up @@ -307,6 +325,7 @@ interface ITypeTag {
value?: undefined | boolean | bigint | number | string;
validate: Record<string, string>;
exclusive: boolean | string[];
schema?: undefined | any;
}

const ESSENTIAL_FIELDS = ["target", "kind", "value"];
Expand Down
Loading

0 comments on commit ff2864c

Please sign in to comment.