From db8591fef78cbb39be1b36c3b3c85ec0a74accf0 Mon Sep 17 00:00:00 2001 From: Ryan Smith <3045513+ryasmi@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:53:53 +0000 Subject: [PATCH] feat: Adds rules for text, mediumText, and tinyText (#1520) --- readme.md | 3 ++ src/rulr.ts | 20 +++++++++- .../mediumText/mediumText.test.ts | 24 +++++++++++ src/sizedStrings/mediumText/mediumText.ts | 24 +++++++++++ src/sizedStrings/mediumText/readme.md | 40 +++++++++++++++++++ src/sizedStrings/text/readme.md | 40 +++++++++++++++++++ src/sizedStrings/text/text.test.ts | 24 +++++++++++ src/sizedStrings/text/text.ts | 24 +++++++++++ src/sizedStrings/tinyText/readme.md | 40 +++++++++++++++++++ src/sizedStrings/tinyText/tinyText.test.ts | 24 +++++++++++ src/sizedStrings/tinyText/tinyText.ts | 24 +++++++++++ 11 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 src/sizedStrings/mediumText/mediumText.test.ts create mode 100644 src/sizedStrings/mediumText/mediumText.ts create mode 100644 src/sizedStrings/mediumText/readme.md create mode 100644 src/sizedStrings/text/readme.md create mode 100644 src/sizedStrings/text/text.test.ts create mode 100644 src/sizedStrings/text/text.ts create mode 100644 src/sizedStrings/tinyText/readme.md create mode 100644 src/sizedStrings/tinyText/tinyText.test.ts create mode 100644 src/sizedStrings/tinyText/tinyText.ts diff --git a/readme.md b/readme.md index 1c19c27be..2982bfb1b 100644 --- a/readme.md +++ b/readme.md @@ -68,6 +68,9 @@ To save you some time, Rulr comes with the following rules. Since it's quite common to want to restrict the size of strings, Rulr comes with some convenient rules for doing just that. - [nonEmptyString](./src/sizedStrings/nonEmptyString/readme.md) +- [tinyText](./src/sizedStrings/tinyText/readme.md) (0 - 255 characters) +- [text](./src/sizedStrings/text/readme.md) (0 - 65,535 characters) +- [mediumText](./src/sizedStrings/mediumText/readme.md) (0 - 16,777,215 characters) ### Constraining Strings diff --git a/src/rulr.ts b/src/rulr.ts index e1e1e9b69..0c577e784 100644 --- a/src/rulr.ts +++ b/src/rulr.ts @@ -113,8 +113,26 @@ export { nonEmptyString, isNonEmptyString, NonEmptyString, - InvalidNonEmptyStringError + InvalidNonEmptyStringError, } from './sizedStrings/nonEmptyString/nonEmptyString' +export { + mediumText, + isMediumText, + MediumText, + InvalidMediumTextError, +} from './sizedStrings/mediumText/mediumText' +export { + text, + isText, + Text, + InvalidTextError, +} from './sizedStrings/text/text' +export { + tinyText, + isTinyText, + TinyText, + InvalidTinyTextError, +} from './sizedStrings/tinyText/tinyText' export { any } from './valueRules/any/any' export { bigint, isBigInt, InvalidBigIntError } from './valueRules/bigint/bigint' export { boolean, isBoolean, InvalidBooleanError } from './valueRules/boolean/boolean' diff --git a/src/sizedStrings/mediumText/mediumText.test.ts b/src/sizedStrings/mediumText/mediumText.test.ts new file mode 100644 index 000000000..7e08d4cd3 --- /dev/null +++ b/src/sizedStrings/mediumText/mediumText.test.ts @@ -0,0 +1,24 @@ +import * as assert from 'assert' +import { InvalidMediumTextError, MediumText, mediumText } from '../../rulr' + +test('mediumText should not allow invalid string input', () => { + const input = 0 + assert.throws(() => mediumText(input), InvalidMediumTextError) +}) + +test('mediumText should allow valid text with 0 characters', () => { + const input = '' + const output: MediumText = mediumText(input) + assert.strictEqual(output, input) +}) + +test('mediumText should allow valid text with 16,777,215 characters', () => { + const input = Array(16777215).fill('a').join('') + const output: MediumText = mediumText(input) + assert.strictEqual(output, input) +}) + +test('mediumText should not allow invalid text with more than 16,777,215 characters', () => { + const input = Array(16777216).fill('a').join('') + assert.throws(() => mediumText(input), InvalidMediumTextError) +}) diff --git a/src/sizedStrings/mediumText/mediumText.ts b/src/sizedStrings/mediumText/mediumText.ts new file mode 100644 index 000000000..26284fe81 --- /dev/null +++ b/src/sizedStrings/mediumText/mediumText.ts @@ -0,0 +1,24 @@ +import { BaseError } from 'make-error' +import { isString } from '../../valueRules/string/string' +import { Constrained } from '../../core' + +export class InvalidMediumTextError extends BaseError { + constructor() { + super('expected no more than 255 characters') + } +} + +export const mediumTextSymbol = Symbol() + +export type MediumText = Constrained + +export function isMediumText(input: unknown): input is MediumText { + return isString(input) && input.length <= 16777215 +} + +export function mediumText(input: unknown) { + if (isMediumText(input)) { + return input + } + throw new InvalidMediumTextError() +} diff --git a/src/sizedStrings/mediumText/readme.md b/src/sizedStrings/mediumText/readme.md new file mode 100644 index 000000000..d188fd1af --- /dev/null +++ b/src/sizedStrings/mediumText/readme.md @@ -0,0 +1,40 @@ +# mediumText + +[Back to root readme.md](../../../readme.md) + +This function uses the `rulr.mediumText` guard to check the input is a valid medium text string ([max 16,777,215 characters](https://www.w3schools.com/sql/sql_datatypes.asp)) as shown in the example below. It should only throw `rulr.InvalidMediumTextError`. + +```ts +import * as rulr from 'rulr' + +const constrainToExample = rulr.object({ + required: { + example: rulr.mediumText, + }, +}) + +type Example = rulr.Static +// { +// example: rulr.MediumText +// } + +// Valid +const example1: Example = constrainToExample({ + example: '', +}) + +// Valid +const example1: Example = constrainToExample({ + example: Array(16777215).fill('a').join(''), +}) + +// Invalid: Too many characters +const example2: Example = constrainToExample({ + example: Array(16777216).fill('a').join(''), +}) + +// Invalid: Not a string +const example3: Example = constrainToExample({ + example: 1, +}) +``` diff --git a/src/sizedStrings/text/readme.md b/src/sizedStrings/text/readme.md new file mode 100644 index 000000000..b6631a491 --- /dev/null +++ b/src/sizedStrings/text/readme.md @@ -0,0 +1,40 @@ +# text + +[Back to root readme.md](../../../readme.md) + +This function uses the `rulr.text` guard to check the input is a valid text string ([max 65,535 characters](https://www.w3schools.com/sql/sql_datatypes.asp)) as shown in the example below. It should only throw `rulr.InvalidTextError`. + +```ts +import * as rulr from 'rulr' + +const constrainToExample = rulr.object({ + required: { + example: rulr.text, + }, +}) + +type Example = rulr.Static +// { +// example: rulr.Text +// } + +// Valid +const example1: Example = constrainToExample({ + example: '', +}) + +// Valid +const example1: Example = constrainToExample({ + example: Array(65535).fill('a').join(''), +}) + +// Invalid: Too many characters +const example2: Example = constrainToExample({ + example: Array(65536).fill('a').join(''), +}) + +// Invalid: Not a string +const example3: Example = constrainToExample({ + example: 1, +}) +``` diff --git a/src/sizedStrings/text/text.test.ts b/src/sizedStrings/text/text.test.ts new file mode 100644 index 000000000..017757874 --- /dev/null +++ b/src/sizedStrings/text/text.test.ts @@ -0,0 +1,24 @@ +import * as assert from 'assert' +import { InvalidTextError, Text, text } from '../../rulr' + +test('text should not allow invalid string input', () => { + const input = 0 + assert.throws(() => text(input), InvalidTextError) +}) + +test('text should allow valid text with 0 characters', () => { + const input = '' + const output: Text = text(input) + assert.strictEqual(output, input) +}) + +test('text should allow valid text with 65,535 characters', () => { + const input = Array(65535).fill('a').join('') + const output: Text = text(input) + assert.strictEqual(output, input) +}) + +test('text should not allow invalid text with more than 65,535 characters', () => { + const input = Array(65536).fill('a').join('') + assert.throws(() => text(input), InvalidTextError) +}) diff --git a/src/sizedStrings/text/text.ts b/src/sizedStrings/text/text.ts new file mode 100644 index 000000000..3c470019f --- /dev/null +++ b/src/sizedStrings/text/text.ts @@ -0,0 +1,24 @@ +import { BaseError } from 'make-error' +import { isString } from '../../valueRules/string/string' +import { Constrained } from '../../core' + +export class InvalidTextError extends BaseError { + constructor() { + super('expected no more than 255 characters') + } +} + +export const textSymbol = Symbol() + +export type Text = Constrained + +export function isText(input: unknown): input is Text { + return isString(input) && input.length <= 65535 +} + +export function text(input: unknown) { + if (isText(input)) { + return input + } + throw new InvalidTextError() +} diff --git a/src/sizedStrings/tinyText/readme.md b/src/sizedStrings/tinyText/readme.md new file mode 100644 index 000000000..e2bcac21e --- /dev/null +++ b/src/sizedStrings/tinyText/readme.md @@ -0,0 +1,40 @@ +# tinyText + +[Back to root readme.md](../../../readme.md) + +This function uses the `rulr.tinyText` guard to check the input is a valid tiny text string ([max 255 characters](https://www.w3schools.com/sql/sql_datatypes.asp)) as shown in the example below. It should only throw `rulr.InvalidTinyTextError`. + +```ts +import * as rulr from 'rulr' + +const constrainToExample = rulr.object({ + required: { + example: rulr.tinyText, + }, +}) + +type Example = rulr.Static +// { +// example: rulr.TinyText +// } + +// Valid +const example1: Example = constrainToExample({ + example: '', +}) + +// Valid +const example1: Example = constrainToExample({ + example: Array(255).fill('a').join(''), +}) + +// Invalid: Too many characters +const example2: Example = constrainToExample({ + example: Array(256).fill('a').join(''), +}) + +// Invalid: Not a string +const example3: Example = constrainToExample({ + example: 1, +}) +``` diff --git a/src/sizedStrings/tinyText/tinyText.test.ts b/src/sizedStrings/tinyText/tinyText.test.ts new file mode 100644 index 000000000..be725e82d --- /dev/null +++ b/src/sizedStrings/tinyText/tinyText.test.ts @@ -0,0 +1,24 @@ +import * as assert from 'assert' +import { InvalidTinyTextError, TinyText, tinyText } from '../../rulr' + +test('tinyText should not allow invalid string input', () => { + const input = 0 + assert.throws(() => tinyText(input), InvalidTinyTextError) +}) + +test('tinyText should allow valid text with 0 characters', () => { + const input = '' + const output: TinyText = tinyText(input) + assert.strictEqual(output, input) +}) + +test('tinyText should allow valid text with 255 characters', () => { + const input = Array(255).fill('a').join('') + const output: TinyText = tinyText(input) + assert.strictEqual(output, input) +}) + +test('tinyText should not allow invalid text with more than 255 characters', () => { + const input = Array(256).fill('a').join('') + assert.throws(() => tinyText(input), InvalidTinyTextError) +}) diff --git a/src/sizedStrings/tinyText/tinyText.ts b/src/sizedStrings/tinyText/tinyText.ts new file mode 100644 index 000000000..732d86be7 --- /dev/null +++ b/src/sizedStrings/tinyText/tinyText.ts @@ -0,0 +1,24 @@ +import { BaseError } from 'make-error' +import { isString } from '../../valueRules/string/string' +import { Constrained } from '../../core' + +export class InvalidTinyTextError extends BaseError { + constructor() { + super('expected no more than 255 characters') + } +} + +export const tinyTextSymbol = Symbol() + +export type TinyText = Constrained + +export function isTinyText(input: unknown): input is TinyText { + return isString(input) && input.length <= 255 +} + +export function tinyText(input: unknown) { + if (isTinyText(input)) { + return input + } + throw new InvalidTinyTextError() +}