Skip to content

Commit

Permalink
feat!: remove validate property from argument types
Browse files Browse the repository at this point in the history
This property served no purpose, as all of the actual validation/error handling is done in the type's transform function.
  • Loading branch information
paradoxuum committed Sep 24, 2024
1 parent ae9f726 commit ecb0e98
Show file tree
Hide file tree
Showing 10 changed files with 2 additions and 73 deletions.
8 changes: 2 additions & 6 deletions docs/src/content/docs/guides/types/defining-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { TransformResult, TypeBuilder } from "@rbxts/centurion";
import { t } from "@rbxts/t";
const playerType = TypeBuilder.create<Player>("player")
.validate(t.instanceOf("Player"))
.transform((text, executor) => {
if (text === "@me") {
return TransformResult.ok(executor);
Expand All @@ -39,10 +38,7 @@ for an example.

## Methods

- **validate**: Requires a type guard. You can use `@rbxts/t` for this, or you can define
them manually.

- **transform**: Requires a function that takes the text and the executor
- **transform**: Takes a function that receives the argument text and the executor of the command
and returns a `TransformResult`.

- **suggestions**: Optional, requires a function that returns an array of strings.
- **suggestions**: Optional, takes a function that returns an array of strings.
11 changes: 0 additions & 11 deletions docs/src/content/docs/reference/types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ title: Types
- name: `string` - The name of the type.
- expensive: `boolean` - Whether the type's transformation function is expensive.
If `true`, type-checking will be disabled in the interface.
- validate: `(value) => boolean` - A function that validates a string as the type.
- transform: `(text, executor) => TransformResult.Object` - A function that transforms
a string into the type.
- suggestions: `(text, executor) => string[]` - A function that returns suggestions
Expand Down Expand Up @@ -39,16 +38,6 @@ from the provided type.
**Returns**:
A `TypeBuilder` instance.

### `validate(fn)`

Sets the validation function for the type.

**Parameters**:
- `fn` - The validation function.

**Returns**:
The `TypeBuilder` instance.

### `transform(fn, expensive)`

Sets the transformation function for the type.
Expand Down
9 changes: 0 additions & 9 deletions packages/core/src/shared/builtin/types/color.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { t } from "@rbxts/t";
import { CenturionType } from ".";
import { BaseRegistry, TransformResult, TypeBuilder } from "../../core";

Expand Down Expand Up @@ -216,7 +215,6 @@ const brickColorNames = new Set([
const brickColorNameArray = [...brickColorNames];

const brickColorType = TypeBuilder.create<BrickColor>(CenturionType.BrickColor)
.validate(t.BrickColor)
.transform((text) => {
if (!brickColorNames.has(text)) {
return TransformResult.err(`Invalid BrickColor: ${text}`);
Expand All @@ -229,14 +227,7 @@ const brickColorType = TypeBuilder.create<BrickColor>(CenturionType.BrickColor)
.build();

const HEX_COLOR_PATTERN = "^#?%x%x%x%x%x%x$";

function isHexColor(value: unknown): value is Color3 {
if (!typeIs(value, "string")) return false;
return !value.match(HEX_COLOR_PATTERN).isEmpty();
}

const hexColorType = TypeBuilder.create<Color3>(CenturionType.HexColor)
.validate(isHexColor)
.transform((text) => {
if (text.match(HEX_COLOR_PATTERN).isEmpty()) {
return TransformResult.err(`Invalid hex code: ${text}`);
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/shared/builtin/types/duration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { t } from "@rbxts/t";
import { CenturionType } from ".";
import { BaseRegistry, TransformResult, TypeBuilder } from "../../core";

Expand Down Expand Up @@ -32,7 +31,6 @@ assignUnit("month", ["mo", "mos", "months"]);
assignUnit("year", ["y", "yr", "yrs", "years"]);

const durationType = TypeBuilder.create<number>(CenturionType.Duration)
.validate(t.integer)
.transform((value: string) => {
if (value === "0") return TransformResult.ok(0);

Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/shared/builtin/types/players.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Players } from "@rbxts/services";
import { t } from "@rbxts/t";
import { CenturionType } from ".";
import {
BaseRegistry,
Expand Down Expand Up @@ -36,15 +35,12 @@ const getPlayerSuggestions = () => [
...Players.GetPlayers().map((player) => player.Name),
];

const isPlayer = t.instanceOf("Player");
const playerType = TypeBuilder.create<Player>(CenturionType.Player)
.validate(isPlayer)
.transform(getPlayer)
.suggestions(getPlayerSuggestions)
.build();

const playersType = ListTypeBuilder.create<Player[]>(CenturionType.Players)
.validate(t.array(isPlayer))
.transform((input, executor) => {
const includedPlayers = new Set<Player>();
let players: Player[] = [];
Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/shared/builtin/types/primitives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ const transformToNumber = (text: string) => {
};

const stringType = TypeBuilder.create<string>(CenturionType.String)
.validate(t.string)
.transform((text) => TransformResult.ok(text))
.build();

const numberType = TypeBuilder.create<number>(CenturionType.Number)
.validate(t.number)
.transform(transformToNumber)
.build();

const integerType = TypeBuilder.create<number>(CenturionType.Integer)
.validate(t.integer)
.transform((text) => {
const numResult = transformToNumber(text);
if (!numResult.ok) {
Expand All @@ -39,7 +36,6 @@ const integerType = TypeBuilder.create<number>(CenturionType.Integer)
const truthyValues = new Set<string>(["true", "yes", "y"]);
const falsyValues = new Set<string>(["false", "no", "n"]);
const booleanType = TypeBuilder.create<boolean>(CenturionType.Boolean)
.validate(t.boolean)
.transform((text) => {
const textLower = text.lower();
if (truthyValues.has(textLower)) return TransformResult.ok(true);
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/shared/builtin/types/team.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Teams } from "@rbxts/services";
import { t } from "@rbxts/t";
import { CenturionType } from ".";
import { BaseRegistry, TransformResult, TypeBuilder } from "../../core";

const teamType = TypeBuilder.create<Team>(CenturionType.Team)
.validate(t.instanceOf("Team"))
.transform((text) => {
const team = Teams.FindFirstChild(text);
if (team === undefined || !classIs(team, "Team")) {
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/shared/core/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ type Constructor = new (...args: never[]) => object;
const argTypeSchema = t.interface({
name: t.string,
expensive: t.boolean,
validate: t.callback,
transform: t.callback,
suggestions: t.optional(t.callback),
});
Expand Down
31 changes: 0 additions & 31 deletions packages/core/src/shared/core/type.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { t } from "@rbxts/t";
import { ListArgumentType, SingleArgumentType } from "../types";
import { DecoratorMetadata, MetadataKey } from "./metadata";

Expand Down Expand Up @@ -38,7 +37,6 @@ export namespace TransformResult {
export class TypeBuilder<T> {
private expensive = false;
private marked = false;
private validationFn?: t.check<T>;
private transformFn?: SingleArgumentType<T>["transform"];
private suggestionFn?: SingleArgumentType<T>["suggestions"];

Expand Down Expand Up @@ -66,23 +64,11 @@ export class TypeBuilder<T> {
static extend<T>(name: string, argumentType: SingleArgumentType<T>) {
const builder = new TypeBuilder<T>(name);
builder.expensive = argumentType.expensive;
builder.validationFn = argumentType.validate;
builder.transformFn = argumentType.transform;
builder.suggestionFn = argumentType.suggestions;
return builder;
}

/**
* Sets the validation function for this type.
*
* @param fn - The validation function.
* @returns The {@link TypeBuilder} instance.
*/
validate(fn: t.check<T>) {
this.validationFn = fn;
return this;
}

/**
* Sets the transformation function for this type.
*
Expand Down Expand Up @@ -133,14 +119,12 @@ export class TypeBuilder<T> {
* @returns A {@link SingleArgumentType} object.
*/
build(): SingleArgumentType<T> {
assert(this.validationFn !== undefined, "Validation function is required");
assert(this.transformFn !== undefined, "Transform function is required");

const argType = {
kind: "single",
name: this.name,
expensive: this.expensive,
validate: this.validationFn,
transform: this.transformFn,
suggestions: this.suggestionFn,
} satisfies SingleArgumentType<T>;
Expand All @@ -159,7 +143,6 @@ export class TypeBuilder<T> {
export class ListTypeBuilder<T extends defined[]> {
private expensive = false;
private marked = false;
private validationFn?: t.check<T>;
private transformFn?: ListArgumentType<T>["transform"];
private suggestionFn?: ListArgumentType<T>["suggestions"];

Expand Down Expand Up @@ -190,23 +173,11 @@ export class ListTypeBuilder<T extends defined[]> {
) {
const builder = new ListTypeBuilder<T>(name);
builder.expensive = argumentType.expensive;
builder.validationFn = argumentType.validate;
builder.transformFn = argumentType.transform;
builder.suggestionFn = argumentType.suggestions;
return builder;
}

/**
* Sets the validation function for this type.
*
* @param fn - The validation function.
* @returns The {@link ListTypeBuilder} instance.
*/
validate(fn: t.check<T>) {
this.validationFn = fn;
return this;
}

/**
* Sets the transformation function for this type.
*
Expand Down Expand Up @@ -257,14 +228,12 @@ export class ListTypeBuilder<T extends defined[]> {
* @returns A {@link ListArgumentType} object.
*/
build(): ListArgumentType<T> {
assert(this.validationFn !== undefined, "Validation function is required");
assert(this.transformFn !== undefined, "Transform function is required");

const argType = {
kind: "list",
name: this.name,
expensive: this.expensive,
validate: this.validationFn,
transform: this.transformFn,
suggestions: this.suggestionFn,
} satisfies ListArgumentType<T>;
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/shared/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { t } from "@rbxts/t";
import { CommandContext, TransformResult } from "./core";
import { CenturionLogLevel } from "./util";

Expand Down Expand Up @@ -32,7 +31,6 @@ export interface SingleArgumentType<T> {
kind: "single";
name: string;
expensive: boolean;
validate: t.check<T>;
transform: (text: string, executor: Player) => TransformResult.Object<T>;
suggestions?: (text: string, executor: Player) => string[];
}
Expand All @@ -41,7 +39,6 @@ export interface ListArgumentType<T> {
kind: "list";
name: string;
expensive: boolean;
validate: t.check<T>;
transform: (input: string[], executor: Player) => TransformResult.Object<T>;
suggestions?: (input: string[], executor: Player) => string[];
}
Expand Down

0 comments on commit ecb0e98

Please sign in to comment.