Skip to content

Commit

Permalink
♻️ [refactor]: Refactor decorators package, add autotranslate plugin …
Browse files Browse the repository at this point in the history
…script
  • Loading branch information
brunotot committed Sep 14, 2023
1 parent da16a41 commit eed5ed7
Show file tree
Hide file tree
Showing 70 changed files with 351 additions and 324 deletions.
9 changes: 5 additions & 4 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { makeValidator } from "./src/decorators/facade/validator.facade";
import { makeValidator } from "./src/decorators/decorator.facade";
import {
DecoratorContext,
DecoratorContextMetadata,
} from "./src/decorators/types/DecoratorContext.type";
import { ValidationGroup } from "./src/decorators/types/DecoratorProps.type";
import { Locale, getLocale, setLocale } from "./src/messages/model/Locale";
ValidationGroup,
} from "./src/decorators/decorator.types";
import { Locale } from "./src/messages/message.types";
import { getLocale, setLocale } from "./src/messages/model/locale";
import EntityProcessor, {
EntityProcessorConfig,
} from "./src/model/processor/EntityProcessor";
Expand Down
8 changes: 4 additions & 4 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@
"url": "https://github.com/brunotot/typescript-decorator-validation/issues"
},
"homepage": "https://github.com/brunotot/typescript-decorator-validation#readme",
"dependencies": {
"reflect-metadata": "^0.1.13"
"peerDependencies": {
"typescript": "^5.2.2"
},
"devDependencies": {
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"auto-i18n": "^1.0.0",
"esm": "^3.2.25",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
"ts-node": "^10.9.1"
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import MetadataProcessor from "../../model/processor/MetadataProcessor";
import { ValidationEvaluator } from "../../types/ValidationEvaluator.type";
import { makeDecorator } from "../decorator.factory";
import { Decorator } from "../types/Decorator.type";
import MetadataProcessor from "../model/processor/MetadataProcessor";
import { ValidationEvaluator } from "../types/ValidationEvaluator.type";
import { makeDecorator } from "./decorator.factory";
import {
Decorator,
ValidationGroup,
ValidationGroupProp,
} from "../types/DecoratorProps.type";
} from "./decorator.types";

export type ValidatorBuilder<T> = {
isValid: ValidationEvaluator<T>;
groups?: ValidationGroupProp;
};

export function makeValidator<T>(builder: ValidatorBuilder<T>): Decorator<T> {
export function makeValidator<T>({
groups,
isValid,
}: ValidatorBuilder<T>): Decorator<T> {
return makeDecorator<T>((key, processor) => {
saveMetadata(processor, key, builder.groups!, builder.isValid);
saveMetadata(processor, key, isValid, groups);
});
}

Expand All @@ -29,11 +32,12 @@ function getSanitizedGroups(unsanitizedGroups?: ValidationGroupProp) {
function saveMetadata(
processor: MetadataProcessor,
key: string,
groups: ValidationGroupProp,
isValid: ValidationEvaluator<any>
isValid: ValidationEvaluator<any>,
groups?: ValidationGroupProp
) {
const validate = processor.field(key);
validate.rules.root.add({
const fieldDescriptor = processor.field(key);
const rootRules = fieldDescriptor.rules.root;
rootRules.add({
groups: getSanitizedGroups(groups),
validate: isValid,
});
Expand Down
8 changes: 5 additions & 3 deletions packages/core/src/decorators/decorator.factory.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import MetadataProcessor from "../model/processor/MetadataProcessor";
import { Decorator } from "./types/Decorator.type";
import { DecoratorContext } from "./types/DecoratorContext.type";
import { DecoratorSupplier } from "./types/DecoratorSupplier.type";
import {
Decorator,
DecoratorContext,
DecoratorSupplier,
} from "./decorator.types";

function isDecoratorsStage2(context: DecoratorContext) {
return typeof context === "string";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
import { $ } from "../../types/namespace/Utility.ns";
import MetadataProcessor from "../model/processor/MetadataProcessor";
import { $ } from "../types/namespace/Utility.ns";

export type Decorator<T = unknown> = (
target: any,
context: DecoratorContext<T>
) => void;

export type DecoratorContextMetadata = DecoratorMetadata;

export type DecoratorContext<Accept = unknown> = Readonly<{
kind: "field" | "method" | "getter";
static: boolean;
private: boolean;
name: string;
metadata: DecoratorContextMetadata;
access: {
get(object: any): Accept;
};
}>;

export type ValidationGroup = string | number | symbol;

Expand Down Expand Up @@ -33,3 +52,9 @@ type DecoratorGroupsProps = {
type DecoratorMessageProps = {
message: string;
};

export type DecoratorSupplier<T = unknown> = (
name: string,
processor: MetadataProcessor,
context: DecoratorContext<T>
) => void;
6 changes: 0 additions & 6 deletions packages/core/src/decorators/types/Decorator.type.ts

This file was deleted.

12 changes: 0 additions & 12 deletions packages/core/src/decorators/types/DecoratorContext.type.ts

This file was deleted.

8 changes: 0 additions & 8 deletions packages/core/src/decorators/types/DecoratorSupplier.type.ts

This file was deleted.

101 changes: 0 additions & 101 deletions packages/core/src/messages/impl/ErrorMessage.ts

This file was deleted.

15 changes: 7 additions & 8 deletions packages/core/src/messages/message.factory.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { $ } from "../types/namespace/Utility.ns";
import { getLocale } from "./model/Locale";
import translations from "./model/Translations";
import { getLocale } from "./model/locale";
import localizedMessages from "./model/messages";

function sprintf(str: string, ...args: any[]) {
return str.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] != "undefined" ? args[number] : match;
});
}

export type MessageFn<T extends any[] = []> = $.FuncFactory<T, string>;

// Central method for getting translation handlers.
export function t(key: string, ...args: any[]): string {
const t = (key: string, ...args: any[]) => {
const locale = getLocale();
const service = translations[locale];
const service = localizedMessages[locale];
return sprintf(service[key], ...args);
}
};

export default t;
7 changes: 7 additions & 0 deletions packages/core/src/messages/message.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { $ } from "../types/namespace/Utility.ns";

export type Locale = "hr" | "en";

export type LocaleDefault = "en";

export type MessageFn<T extends any[] = []> = $.FuncFactory<T, string>;
12 changes: 0 additions & 12 deletions packages/core/src/messages/model/Translations.ts

This file was deleted.

52 changes: 52 additions & 0 deletions packages/core/src/messages/model/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import t from "../message.factory";

// prettier-ignore
const errorMessages = {
Alpha: () => t("Alpha"),
Alphanumeric: () => t("Alphanumeric"),
ArrayContains: (o: any) => t("ArrayContains", JSON.stringify(o, null, 2)),
ArrayEmpty: () => t("ArrayEmpty"),
ArraySizeExact: (exact: number, actual: number) => t("ArraySizeExact", exact, actual),
ArraySizeMax: (max: number, actual: number) => t("ArraySizeMax", max, actual),
ArraySizeMin: (min: number, actual: number) => t("ArraySizeMin", min, actual),
ArraySizeRange: (min: number, max: number, actual: number) => t("ArraySizeRange", min, max, actual),
ArrayUnique: () => t("ArrayUnique"),
Date: (format: string) => t("Date", format),
Decimal: (actual: number) => t("Decimal", actual),
Digits: (maxInteger: number, maxFraction: number) => t("Digits", maxInteger, maxFraction),
Email: () => t("Email"),
ExactLength: (exact: number) => t("ExactLength", exact),
Falsy: () => t("Falsy"),
FutureDate: (date: Date) => t("FutureDate", date?.toDateString()),
IPAddress: () => t("IPAddress"),
Integer: (actual: number) => t("Integer", actual),
InvalidDigits: (maxInteger: number, maxFraction: number) => t("InvalidDigits", maxInteger, maxFraction),
JSON: () => t("JSON"),
Lowercase: () => t("Lowercase"),
MaxLength: (max: number) => t("MaxLength", max),
MinLength: (min: number) => t("MinLength", min),
Negative: (actual: number) => t("Negative", actual),
NonNegative: (actual: number) => t("NonNegative", actual),
NonPositive: (actual: number) => t("NonPositive", actual),
Numeric: () => t("Numeric"),
PasswordLength: (length: number) => t("PasswordLength", length),
PasswordLowercase: () => t("PasswordLowercase"),
PasswordNumbers: () => t("PasswordNumbers"),
PasswordSpecials: () => t("PasswordSpecials"),
PasswordUppercase: () => t("PasswordUppercase"),
PastDate: (date: Date) => t("PastDate", date?.toDateString()),
Positive: (actual: number) => t("Positive", actual),
RangeLength: (min: number, max: number) => t("RangeLength", min, max),
Required: () => t('Required'),
Time: (locale: string, hour12: boolean) => t("Time", locale, hour12 ? "12-hour" : "24:hour"),
TodayDate: (date: Date) => t("TodayDate", date?.toDateString()),
Truthy: () => t("Truthy"),
Uppercase: () => t("Uppercase"),
URL: () => t("URL"),
ValueMax: (value: number, actual: number) => t("ValueMax", value, actual),
ValueMin: (value: number, actual: number) => t("ValueMin", value, actual),
ValueRange: (min: number, max: number, actual: number) => t("ValueRange", min, max, actual),
XML: () => t("XML"),
} as const;

export default errorMessages;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type Locale = "hr" | "en";
import { Locale } from "../message.types";

let locale: Locale = "en";

Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/messages/model/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Locale } from "../message.types";
import * as MessageFormatEn from "../translations/en.json";
import * as MessageFormatHr from "../translations/hr.json";

export type LocalizedMessages = Record<Locale, Messages>;

export type Messages = Record<string, string>;

const localizedMessages: LocalizedMessages = {
en: MessageFormatEn,
hr: MessageFormatHr,
};

export default localizedMessages;
2 changes: 1 addition & 1 deletion packages/core/src/model/descriptor/ClassDescriptor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ValidationGroup } from "../../decorators/types/DecoratorProps.type";
import { ValidationGroup } from "../../decorators/decorator.types";
import { Class } from "../../types/Class.type";
import { getClassFieldNames } from "../../utils/class.utils";
import MetadataProcessor from "../processor/MetadataProcessor";
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/model/descriptor/FieldDescriptorRule.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ValidationGroup } from "../../decorators/types/DecoratorProps.type";
import { ValidationGroup } from "../../decorators/decorator.types";
import { Payload } from "../../types/Payload.type";
import { ValidationMetadata } from "../../types/ValidationMetadata.type";
import { ValidationResult } from "../../types/ValidationResult.type";
Expand Down
Loading

0 comments on commit eed5ed7

Please sign in to comment.