Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/kind-areas-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"monarch-orm": patch
---

Preserve concrete type with type modifier methods
47 changes: 25 additions & 22 deletions src/types/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,22 @@ export class MonarchArray<T extends AnyMonarchType> extends MonarchType<InferTyp
this.elementType = type;
}

protected copy() {
return new MonarchArray(this.elementType);
}

/**
* Validates minimum array length.
*
* @param length - Minimum length
* @returns MonarchArray with length validation
*/
public min(length: number) {
return array(this.elementType).extend(this, {
parse: (input) => {
if (input.length < length) {
throw new MonarchParseError(`array must have at least ${length} elements`);
}
return input;
},
return this.parse((input) => {
if (input.length < length) {
throw new MonarchParseError(`array must have at least ${length} elements`);
}
return input;
});
}

Expand All @@ -63,13 +65,11 @@ export class MonarchArray<T extends AnyMonarchType> extends MonarchType<InferTyp
* @returns MonarchArray with length validation
*/
public max(length: number) {
return array(this.elementType).extend(this, {
parse: (input) => {
if (input.length > length) {
throw new MonarchParseError(`array must have at most ${length} elements`);
}
return input;
},
return this.parse((input) => {
if (input.length > length) {
throw new MonarchParseError(`array must have at most ${length} elements`);
}
return input;
});
}

Expand All @@ -80,13 +80,11 @@ export class MonarchArray<T extends AnyMonarchType> extends MonarchType<InferTyp
* @returns MonarchArray with length validation
*/
public length(length: number) {
return array(this.elementType).extend(this, {
parse: (input) => {
if (input.length !== length) {
throw new MonarchParseError(`array must have exactly ${length} elements`);
}
return input;
},
return this.parse((input) => {
if (input.length !== length) {
throw new MonarchParseError(`array must have exactly ${length} elements`);
}
return input;
});
}

Expand All @@ -96,6 +94,11 @@ export class MonarchArray<T extends AnyMonarchType> extends MonarchType<InferTyp
* @returns MonarchArray with non-empty validation
*/
public nonempty() {
return this.min(1);
return this.parse((input) => {
if (input.length === 0) {
throw new MonarchParseError("array must not be empty");
}
return input;
});
}
}
4 changes: 4 additions & 0 deletions src/types/binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ export class MonarchBinary extends MonarchType<Buffer | Binary, Binary> {
throw new MonarchParseError(`expected 'Buffer' or 'Binary' received '${typeof input}'`);
});
}

protected copy() {
return new MonarchBinary();
}
}
4 changes: 4 additions & 0 deletions src/types/boolean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ export class MonarchBoolean extends MonarchType<boolean, boolean> {
throw new MonarchParseError(`expected 'boolean' received '${typeof input}'`);
});
}

protected copy() {
return new MonarchBoolean();
}
}
61 changes: 29 additions & 32 deletions src/types/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,22 @@ export class MonarchDate extends MonarchType<Date, Date> {
});
}

protected copy() {
return new MonarchDate();
}

/**
* Validates date is after a target date.
*
* @param targetDate - Target date for comparison
* @returns MonarchDate with after validation
*/
public after(targetDate: Date) {
return date().extend(this, {
parse: (input) => {
if (input <= targetDate) {
throw new MonarchParseError(`date must be after ${targetDate.toISOString()}`);
}
return input;
},
return this.parse((input) => {
if (input <= targetDate) {
throw new MonarchParseError(`date must be after ${targetDate.toISOString()}`);
}
return input;
});
}

Expand All @@ -43,13 +45,11 @@ export class MonarchDate extends MonarchType<Date, Date> {
* @returns MonarchDate with before validation
*/
public before(targetDate: Date) {
return date().extend(this, {
parse: (input) => {
if (input >= targetDate) {
throw new MonarchParseError(`date must be before ${targetDate.toISOString()}`);
}
return input;
},
return this.parse((input) => {
if (input >= targetDate) {
throw new MonarchParseError(`date must be before ${targetDate.toISOString()}`);
}
return input;
});
}
}
Expand All @@ -66,10 +66,7 @@ export const createdAt = () => date().default(() => new Date());
*
* @returns MonarchDate with update and default values
*/
export const updatedAt = () => {
const base = date();
return base.extend(base, { onUpdate: () => new Date() }).default(() => new Date());
};
export const updatedAt = () => createdAt().onUpdate(() => new Date());

/**
* Date string type that accepts ISO date strings.
Expand All @@ -91,20 +88,22 @@ export class MonarchDateString extends MonarchType<string, Date> {
});
}

protected copy() {
return new MonarchDateString();
}

/**
* Validates date is after a target date.
*
* @param targetDate - Target date for comparison
* @returns MonarchDateString with after validation
*/
public after(targetDate: Date) {
return dateString().extend(this, {
parse: (input) => {
if (input <= targetDate) {
throw new MonarchParseError(`date must be after ${targetDate.toISOString()}`);
}
return input;
},
return this.parse((input: Date) => {
if (input <= targetDate) {
throw new MonarchParseError(`date must be after ${targetDate.toISOString()}`);
}
return input;
});
}

Expand All @@ -115,13 +114,11 @@ export class MonarchDateString extends MonarchType<string, Date> {
* @returns MonarchDateString with before validation
*/
public before(targetDate: Date) {
return dateString().extend(this, {
parse: (input) => {
if (input >= targetDate) {
throw new MonarchParseError(`date must be before ${targetDate.toISOString()}`);
}
return input;
},
return this.parse((input: Date) => {
if (input >= targetDate) {
throw new MonarchParseError(`date must be before ${targetDate.toISOString()}`);
}
return input;
});
}
}
4 changes: 4 additions & 0 deletions src/types/decimal128.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ export class MonarchDecimal128 extends MonarchType<Decimal128 | string, Decimal1
throw new MonarchParseError(`expected 'Decimal128' or 'string' received '${typeof input}'`);
});
}

protected copy() {
return new MonarchDecimal128();
}
}
1 change: 0 additions & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export {
defaulted,
nullable,
optional,
pipeParser,
type,
type AnyMonarchType,
type Parser,
Expand Down
6 changes: 5 additions & 1 deletion src/types/literal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ export const literal = <T extends string | number | boolean>(...values: T[]) =>
* Type for literal fields.
*/
export class MonarchLiteral<T extends string | number | boolean> extends MonarchType<T, T> {
constructor(values: T[]) {
constructor(private values: T[]) {
super((input) => {
const _values = new Set(values);
if (_values.has(input)) return input;
throw new MonarchParseError(`unknown value '${input}', literal may only specify known values`);
});
}

protected copy() {
return new MonarchLiteral(this.values);
}
}
4 changes: 4 additions & 0 deletions src/types/long.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ export class MonarchLong extends MonarchType<Long | number | bigint, Long | numb
throw new MonarchParseError(`expected 'Long', 'number', or 'bigint' received '${typeof input}'`);
});
}

protected copy() {
return new MonarchLong();
}
}
4 changes: 4 additions & 0 deletions src/types/mixed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ export class MonarchMixed extends MonarchType<unknown, unknown> {
return input;
});
}

protected copy() {
return new MonarchMixed();
}
}
40 changes: 19 additions & 21 deletions src/types/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,22 @@ export class MonarchNumber extends MonarchType<number, number> {
});
}

protected copy() {
return new MonarchNumber();
}

/**
* Validates minimum value.
*
* @param value - Minimum value
* @returns MonarchNumber with min validation
*/
public min(value: number) {
return number().extend(this, {
parse: (input) => {
if (input < value) {
throw new MonarchParseError(`number must be greater than or equal to ${value}`);
}
return input;
},
return this.parse((input) => {
if (input < value) {
throw new MonarchParseError(`number must be greater than or equal to ${value}`);
}
return input;
});
}

Expand All @@ -43,13 +45,11 @@ export class MonarchNumber extends MonarchType<number, number> {
* @returns MonarchNumber with max validation
*/
public max(value: number) {
return number().extend(this, {
parse: (input) => {
if (input > value) {
throw new MonarchParseError(`number must be less than or equal to ${value}`);
}
return input;
},
return this.parse((input) => {
if (input > value) {
throw new MonarchParseError(`number must be less than or equal to ${value}`);
}
return input;
});
}

Expand All @@ -59,13 +59,11 @@ export class MonarchNumber extends MonarchType<number, number> {
* @returns MonarchNumber with integer validation
*/
public integer() {
return number().extend(this, {
parse: (input) => {
if (!Number.isInteger(input)) {
throw new MonarchParseError("number must be an integer");
}
return input;
},
return this.parse((input) => {
if (!Number.isInteger(input)) {
throw new MonarchParseError("number must be an integer");
}
return input;
});
}
}
6 changes: 5 additions & 1 deletion src/types/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class MonarchObject<T extends Record<string, AnyMonarchType>> extends Mon
InferTypeObjectInput<T>,
InferTypeObjectOutput<T>
> {
constructor(types: T) {
constructor(private types: T) {
super((input) => {
if (typeof input === "object" && input !== null) {
for (const key of Object.keys(input)) {
Expand All @@ -42,4 +42,8 @@ export class MonarchObject<T extends Record<string, AnyMonarchType>> extends Mon
throw new MonarchParseError(`expected 'object' received '${typeof input}'`);
});
}

protected copy() {
return new MonarchObject(this.types);
}
}
4 changes: 4 additions & 0 deletions src/types/objectId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ export class MonarchObjectId extends MonarchType<ObjectId | string, ObjectId> {
throw new MonarchParseError(`expected valid ObjectId received '${typeof input}' ${input}`);
});
}

protected copy() {
return new MonarchObjectId();
}
}
9 changes: 8 additions & 1 deletion src/types/pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ export class MonarchPipe<
TPipeIn extends AnyMonarchType,
TPipeOut extends AnyMonarchType<InferTypeOutput<TPipeIn>, any>,
> extends MonarchType<InferTypeInput<TPipeIn>, InferTypeOutput<TPipeOut>> {
constructor(pipeIn: TPipeIn, pipeOut: TPipeOut) {
constructor(
private pipeIn: TPipeIn,
private pipeOut: TPipeOut,
) {
super(
pipeParser<
InferTypeInput<TPipeIn>,
Expand All @@ -29,4 +32,8 @@ export class MonarchPipe<
>(MonarchType.parser(pipeIn), MonarchType.parser(pipeOut)),
);
}

protected copy() {
return new MonarchPipe(this.pipeIn, this.pipeOut);
}
}
Loading