Skip to content

Commit

Permalink
Merge pull request #217 from samchon/v3.3
Browse files Browse the repository at this point in the history
Fix #216 - json schema's pattern does use `/`
  • Loading branch information
samchon authored Oct 2, 2022
2 parents 77b54e7 + 78fcafa commit 1b51534
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 49 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typescript-json",
"version": "3.3.1",
"version": "3.3.2",
"description": "Runtime type checkers and 5x faster JSON.stringify() function",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
6 changes: 1 addition & 5 deletions src/programmers/internal/application_default_string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ export const application_default_string =
if (schema.maxLength !== undefined)
conditions.push(str.length <= schema.maxLength);
if (schema.pattern !== undefined)
conditions.push(
new RegExp(
schema.pattern.substring(1, schema.pattern.length - 1),
).test(str),
);
conditions.push(new RegExp(schema.pattern).test(str));
return conditions.every((c) => c);
})((str) => str);
3 changes: 1 addition & 2 deletions src/programmers/internal/application_templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ export const application_templates = (
(c) => c.type === "string",
);
if (constant) patterns.push(...(constant.values as string[]));

output.pattern = "/" + patterns.map((str) => `(${str})`).join("|") + "/";
output.pattern = patterns.map((str) => `(${str})`).join("|");

// DEFAULT VALUE
output.default = application_default_string(meta, attribute)(output);
Expand Down
26 changes: 26 additions & 0 deletions src/programmers/internal/metadata_to_pattern.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Metadata } from "../../metadata/Metadata";

import { ArrayUtil } from "../../utils/ArrayUtil";
import { PatternUtil } from "../../utils/PatternUtil";

import { template_to_pattern } from "./template_to_pattern";

export function metadata_to_pattern(meta: Metadata): string {
if (meta.atomics.find((type) => type === "string") !== undefined)
return "(.*)";

const values: string[] = ArrayUtil.flat(
meta.constants.map((c) => {
if (c.type !== "string") return c.values.map((v) => v.toString());
return c.values.map((str) => PatternUtil.escape(str));
}),
);
for (const type of meta.atomics)
if (type === "number" || type === "bigint")
values.push(PatternUtil.NUMBER);
else if (type === "boolean") values.push(PatternUtil.BOOLEAN);
for (const childTpl of meta.templates)
values.push("(" + template_to_pattern(childTpl) + ")");

return values.length === 1 ? values[0]! : "(" + values.join("|") + ")";
}
27 changes: 2 additions & 25 deletions src/programmers/internal/template_to_pattern.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,9 @@
import { Metadata } from "../../metadata/Metadata";

import { ArrayUtil } from "../../utils/ArrayUtil";
import { metadata_to_pattern } from "./metadata_to_pattern";

/**
* @internal
*/
export const template_to_pattern = (template: Metadata[]) =>
template
.map((meta) => {
if (meta.atomics.find((type) => type === "string") !== undefined)
return "(.*)";

const values: string[] = ArrayUtil.flat(
meta.constants.map((c) => {
if (c.type !== "string")
return c.values.map((v) => v.toString());
return c.values.map((str) => escape(str));
}),
);
for (const type of meta.atomics)
if (type === "number" || type === "bigint")
values.push("\\d+(\\.\\d+)?");
else if (type === "boolean") values.push("true|false");
for (const childTpl of meta.templates)
values.push("(" + template_to_pattern(childTpl) + ")");
return "(" + values.join("|") + ")";
})
.join("");

const escape = (str: string) =>
str.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
template.map((meta) => metadata_to_pattern(meta)).join("");
11 changes: 11 additions & 0 deletions src/utils/PatternUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export namespace PatternUtil {
export function escape(str: string): string {
return str
.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&")
.replace(/-/g, "\\x2d");
}

export const NUMBER = "\\d+(\\.\\d+)?";
export const BOOLEAN = "true|false";
export const STRING = "(.*)";
}
6 changes: 3 additions & 3 deletions test/features/application/test_application_tag_default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const test_application_tag_format = _test_application(
],
},
],
pattern: "/((prefix_)(.*))/",
pattern: "(prefix_(.*))",
default: "prefix_A",
},
boolean_and_number_and_string: {
Expand Down Expand Up @@ -474,7 +474,7 @@ export const test_application_tag_format = _test_application(
],
},
],
pattern: "/((prefix_)(.*))/",
pattern: "(prefix_(.*))",
},
boolean_and_number_and_template: {
oneOf: [
Expand Down Expand Up @@ -510,7 +510,7 @@ export const test_application_tag_format = _test_application(
],
},
],
pattern: "/((prefix_)(.*))/",
pattern: "(prefix_(.*))",
default: "prefix_B",
},
{
Expand Down
14 changes: 7 additions & 7 deletions test/features/application/test_application_template_atomic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,27 @@ export const test_application_template_atomic = _test_application(
prefix: {
type: "string",
nullable: false,
pattern: "/((prefix_)(.*))/",
pattern: "(prefix_(.*))",
},
postfix: {
type: "string",
nullable: false,
pattern: "/((.*)(_postfix))/",
pattern: "((.*)_postfix)",
},
middle_string: {
type: "string",
nullable: false,
pattern: "/((the_)(.*)(_value))/",
pattern: "(the_(.*)_value)",
},
middle_string_empty: {
type: "string",
nullable: false,
pattern: "/((the_)(.*)(_value))/",
pattern: "(the_(.*)_value)",
},
middle_numeric: {
type: "string",
nullable: false,
pattern: "/((the_)(\\d+(\\.\\d+)?)(_value))/",
pattern: "(the_\\d+(\\.\\d+)?_value)",
},
middle_boolean: {
type: "string",
Expand All @@ -50,12 +50,12 @@ export const test_application_template_atomic = _test_application(
type: "string",
nullable: false,
pattern:
"/((\\d+(\\.\\d+)?)(\\.)(\\d+(\\.\\d+)?)(\\.)(\\d+(\\.\\d+)?)(\\.)(\\d+(\\.\\d+)?))/",
"(\\d+(\\.\\d+)?\\.\\d+(\\.\\d+)?\\.\\d+(\\.\\d+)?\\.\\d+(\\.\\d+)?)",
},
email: {
type: "string",
nullable: false,
pattern: "/((.*)(@)(.*)(\\.)(.*))/",
pattern: "((.*)@(.*)\\.(.*))",
},
},
nullable: false,
Expand Down
10 changes: 4 additions & 6 deletions test/features/application/test_application_template_union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,26 @@ export const test_application_template_union = _test_application(
prefix: {
type: "string",
nullable: false,
pattern:
"/((prefix_)(.*))|((prefix_)(\\d+(\\.\\d+)?))/",
pattern: "(prefix_(.*))|(prefix_\\d+(\\.\\d+)?)",
},
postfix: {
type: "string",
nullable: false,
pattern:
"/((.*)(_postfix))|((\\d+(\\.\\d+)?)(_postfix))/",
pattern: "((.*)_postfix)|(\\d+(\\.\\d+)?_postfix)",
},
middle: {
type: "string",
nullable: false,
pattern:
"/((the_)(\\d+(\\.\\d+)?)(_value))|(the_false_value)|(the_true_value)/",
"(the_\\d+(\\.\\d+)?_value)|(the_false_value)|(the_true_value)",
},
mixed: {
oneOf: [
{
type: "string",
nullable: false,
pattern:
"/((the_)(\\d+(\\.\\d+)?)(_value))|(the_A_value)|(the_B_value)/",
"(the_\\d+(\\.\\d+)?_value)|(the_A_value)|(the_B_value)",
},
{
type: "number",
Expand Down

0 comments on commit 1b51534

Please sign in to comment.