56 | ? inferRaw
57 | : never;
58 |
59 | export type inferParsedPropertySchema
| Schema> = P extends Property<
60 | any,
61 | any,
62 | infer Parsed
63 | >
64 | ? Parsed
65 | : P extends Schema
66 | ? inferParsed
67 | : never;
68 |
69 | export type inferRawKey<
70 | ParsedKey extends string | number | symbol,
71 | P extends Property | Schema
72 | > = P extends Property ? Raw : ParsedKey;
73 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/primitives/any.ts:
--------------------------------------------------------------------------------
1 | import { SchemaType } from "../../Schema";
2 | import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator";
3 |
4 | export const any = createIdentitySchemaCreator(SchemaType.ANY, (value) => ({ ok: true, value }));
5 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/primitives/boolean.ts:
--------------------------------------------------------------------------------
1 | import { SchemaType } from "../../Schema";
2 | import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator";
3 | import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType";
4 |
5 | export const boolean = createIdentitySchemaCreator(
6 | SchemaType.BOOLEAN,
7 | (value, { breadcrumbsPrefix = [] } = {}) => {
8 | if (typeof value === "boolean") {
9 | return {
10 | ok: true,
11 | value,
12 | };
13 | } else {
14 | return {
15 | ok: false,
16 | errors: [
17 | {
18 | path: breadcrumbsPrefix,
19 | message: getErrorMessageForIncorrectType(value, "boolean"),
20 | },
21 | ],
22 | };
23 | }
24 | }
25 | );
26 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/primitives/index.ts:
--------------------------------------------------------------------------------
1 | export { any } from "./any";
2 | export { boolean } from "./boolean";
3 | export { number } from "./number";
4 | export { string } from "./string";
5 | export { unknown } from "./unknown";
6 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/primitives/number.ts:
--------------------------------------------------------------------------------
1 | import { SchemaType } from "../../Schema";
2 | import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator";
3 | import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType";
4 |
5 | export const number = createIdentitySchemaCreator(
6 | SchemaType.NUMBER,
7 | (value, { breadcrumbsPrefix = [] } = {}) => {
8 | if (typeof value === "number") {
9 | return {
10 | ok: true,
11 | value,
12 | };
13 | } else {
14 | return {
15 | ok: false,
16 | errors: [
17 | {
18 | path: breadcrumbsPrefix,
19 | message: getErrorMessageForIncorrectType(value, "number"),
20 | },
21 | ],
22 | };
23 | }
24 | }
25 | );
26 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/primitives/string.ts:
--------------------------------------------------------------------------------
1 | import { SchemaType } from "../../Schema";
2 | import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator";
3 | import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType";
4 |
5 | export const string = createIdentitySchemaCreator(
6 | SchemaType.STRING,
7 | (value, { breadcrumbsPrefix = [] } = {}) => {
8 | if (typeof value === "string") {
9 | return {
10 | ok: true,
11 | value,
12 | };
13 | } else {
14 | return {
15 | ok: false,
16 | errors: [
17 | {
18 | path: breadcrumbsPrefix,
19 | message: getErrorMessageForIncorrectType(value, "string"),
20 | },
21 | ],
22 | };
23 | }
24 | }
25 | );
26 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/primitives/unknown.ts:
--------------------------------------------------------------------------------
1 | import { SchemaType } from "../../Schema";
2 | import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator";
3 |
4 | export const unknown = createIdentitySchemaCreator(SchemaType.UNKNOWN, (value) => ({ ok: true, value }));
5 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/record/index.ts:
--------------------------------------------------------------------------------
1 | export { record } from "./record";
2 | export type { BaseRecordSchema, RecordSchema } from "./types";
3 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/record/record.ts:
--------------------------------------------------------------------------------
1 | import { MaybeValid, Schema, SchemaType, ValidationError } from "../../Schema";
2 | import { entries } from "../../utils/entries";
3 | import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType";
4 | import { isPlainObject } from "../../utils/isPlainObject";
5 | import { MaybePromise } from "../../utils/MaybePromise";
6 | import { maybeSkipValidation } from "../../utils/maybeSkipValidation";
7 | import { getSchemaUtils } from "../schema-utils";
8 | import { BaseRecordSchema, RecordSchema } from "./types";
9 |
10 | export function record(
11 | keySchema: Schema,
12 | valueSchema: Schema
13 | ): RecordSchema {
14 | const baseSchema: BaseRecordSchema = {
15 | parse: async (raw, opts) => {
16 | return validateAndTransformRecord({
17 | value: raw,
18 | isKeyNumeric: (await keySchema.getType()) === SchemaType.NUMBER,
19 | transformKey: (key) =>
20 | keySchema.parse(key, {
21 | ...opts,
22 | breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key} (key)`],
23 | }),
24 | transformValue: (value, key) =>
25 | valueSchema.parse(value, {
26 | ...opts,
27 | breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key}`],
28 | }),
29 | breadcrumbsPrefix: opts?.breadcrumbsPrefix,
30 | });
31 | },
32 | json: async (parsed, opts) => {
33 | return validateAndTransformRecord({
34 | value: parsed,
35 | isKeyNumeric: (await keySchema.getType()) === SchemaType.NUMBER,
36 | transformKey: (key) =>
37 | keySchema.json(key, {
38 | ...opts,
39 | breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key} (key)`],
40 | }),
41 | transformValue: (value, key) =>
42 | valueSchema.json(value, {
43 | ...opts,
44 | breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key}`],
45 | }),
46 | breadcrumbsPrefix: opts?.breadcrumbsPrefix,
47 | });
48 | },
49 | getType: () => SchemaType.RECORD,
50 | };
51 |
52 | return {
53 | ...maybeSkipValidation(baseSchema),
54 | ...getSchemaUtils(baseSchema),
55 | };
56 | }
57 |
58 | async function validateAndTransformRecord({
59 | value,
60 | isKeyNumeric,
61 | transformKey,
62 | transformValue,
63 | breadcrumbsPrefix = [],
64 | }: {
65 | value: unknown;
66 | isKeyNumeric: boolean;
67 | transformKey: (key: string | number) => MaybePromise>;
68 | transformValue: (value: unknown, key: string | number) => MaybePromise>;
69 | breadcrumbsPrefix: string[] | undefined;
70 | }): Promise>> {
71 | if (!isPlainObject(value)) {
72 | return {
73 | ok: false,
74 | errors: [
75 | {
76 | path: breadcrumbsPrefix,
77 | message: getErrorMessageForIncorrectType(value, "object"),
78 | },
79 | ],
80 | };
81 | }
82 |
83 | return entries(value).reduce>>>(
84 | async (accPromise, [stringKey, value]) => {
85 | // skip nullish keys
86 | if (value == null) {
87 | return accPromise;
88 | }
89 |
90 | const acc = await accPromise;
91 |
92 | let key: string | number = stringKey;
93 | if (isKeyNumeric) {
94 | const numberKey = stringKey.length > 0 ? Number(stringKey) : NaN;
95 | if (!isNaN(numberKey)) {
96 | key = numberKey;
97 | }
98 | }
99 | const transformedKey = await transformKey(key);
100 |
101 | const transformedValue = await transformValue(value, key);
102 |
103 | if (acc.ok && transformedKey.ok && transformedValue.ok) {
104 | return {
105 | ok: true,
106 | value: {
107 | ...acc.value,
108 | [transformedKey.value]: transformedValue.value,
109 | },
110 | };
111 | }
112 |
113 | const errors: ValidationError[] = [];
114 | if (!acc.ok) {
115 | errors.push(...acc.errors);
116 | }
117 | if (!transformedKey.ok) {
118 | errors.push(...transformedKey.errors);
119 | }
120 | if (!transformedValue.ok) {
121 | errors.push(...transformedValue.errors);
122 | }
123 |
124 | return {
125 | ok: false,
126 | errors,
127 | };
128 | },
129 | Promise.resolve({ ok: true, value: {} as Record })
130 | );
131 | }
132 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/record/types.ts:
--------------------------------------------------------------------------------
1 | import { BaseSchema } from "../../Schema";
2 | import { SchemaUtils } from "../schema-utils";
3 |
4 | export type RecordSchema<
5 | RawKey extends string | number,
6 | RawValue,
7 | ParsedKey extends string | number,
8 | ParsedValue
9 | > = BaseRecordSchema &
10 | SchemaUtils, Record>;
11 |
12 | export type BaseRecordSchema<
13 | RawKey extends string | number,
14 | RawValue,
15 | ParsedKey extends string | number,
16 | ParsedValue
17 | > = BaseSchema, Record>;
18 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/schema-utils/JsonError.ts:
--------------------------------------------------------------------------------
1 | import { ValidationError } from "../../Schema";
2 | import { stringifyValidationError } from "./stringifyValidationErrors";
3 |
4 | export class JsonError extends Error {
5 | constructor(public readonly errors: ValidationError[]) {
6 | super(errors.map(stringifyValidationError).join("; "));
7 | Object.setPrototypeOf(this, JsonError.prototype);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/schema-utils/ParseError.ts:
--------------------------------------------------------------------------------
1 | import { ValidationError } from "../../Schema";
2 | import { stringifyValidationError } from "./stringifyValidationErrors";
3 |
4 | export class ParseError extends Error {
5 | constructor(public readonly errors: ValidationError[]) {
6 | super(errors.map(stringifyValidationError).join("; "));
7 | Object.setPrototypeOf(this, ParseError.prototype);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/schema-utils/getSchemaUtils.ts:
--------------------------------------------------------------------------------
1 | import { BaseSchema, Schema, SchemaOptions, SchemaType } from "../../Schema";
2 | import { JsonError } from "./JsonError";
3 | import { ParseError } from "./ParseError";
4 |
5 | export interface SchemaUtils {
6 | optional: () => Schema;
7 | transform: (transformer: SchemaTransformer) => Schema;
8 | parseOrThrow: (raw: unknown, opts?: SchemaOptions) => Promise;
9 | jsonOrThrow: (raw: unknown, opts?: SchemaOptions) => Promise;
10 | }
11 |
12 | export interface SchemaTransformer {
13 | transform: (parsed: Parsed) => Transformed;
14 | untransform: (transformed: any) => Parsed;
15 | }
16 |
17 | export function getSchemaUtils(schema: BaseSchema): SchemaUtils {
18 | return {
19 | optional: () => optional(schema),
20 | transform: (transformer) => transform(schema, transformer),
21 | parseOrThrow: async (raw, opts) => {
22 | const parsed = await schema.parse(raw, opts);
23 | if (parsed.ok) {
24 | return parsed.value;
25 | }
26 | throw new ParseError(parsed.errors);
27 | },
28 | jsonOrThrow: async (parsed, opts) => {
29 | const raw = await schema.json(parsed, opts);
30 | if (raw.ok) {
31 | return raw.value;
32 | }
33 | throw new JsonError(raw.errors);
34 | },
35 | };
36 | }
37 |
38 | /**
39 | * schema utils are defined in one file to resolve issues with circular imports
40 | */
41 |
42 | export function optional(
43 | schema: BaseSchema
44 | ): Schema {
45 | const baseSchema: BaseSchema = {
46 | parse: (raw, opts) => {
47 | if (raw == null) {
48 | return {
49 | ok: true,
50 | value: undefined,
51 | };
52 | }
53 | return schema.parse(raw, opts);
54 | },
55 | json: (parsed, opts) => {
56 | if (parsed == null) {
57 | return {
58 | ok: true,
59 | value: null,
60 | };
61 | }
62 | return schema.json(parsed, opts);
63 | },
64 | getType: () => SchemaType.OPTIONAL,
65 | };
66 |
67 | return {
68 | ...baseSchema,
69 | ...getSchemaUtils(baseSchema),
70 | };
71 | }
72 |
73 | export function transform(
74 | schema: BaseSchema,
75 | transformer: SchemaTransformer
76 | ): Schema {
77 | const baseSchema: BaseSchema = {
78 | parse: async (raw, opts) => {
79 | const parsed = await schema.parse(raw, opts);
80 | if (!parsed.ok) {
81 | return parsed;
82 | }
83 | return {
84 | ok: true,
85 | value: transformer.transform(parsed.value),
86 | };
87 | },
88 | json: async (transformed, opts) => {
89 | const parsed = await transformer.untransform(transformed);
90 | return schema.json(parsed, opts);
91 | },
92 | getType: () => schema.getType(),
93 | };
94 |
95 | return {
96 | ...baseSchema,
97 | ...getSchemaUtils(baseSchema),
98 | };
99 | }
100 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/schema-utils/index.ts:
--------------------------------------------------------------------------------
1 | export { getSchemaUtils, optional, transform } from "./getSchemaUtils";
2 | export type { SchemaUtils } from "./getSchemaUtils";
3 | export { JsonError } from "./JsonError";
4 | export { ParseError } from "./ParseError";
5 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/schema-utils/stringifyValidationErrors.ts:
--------------------------------------------------------------------------------
1 | import { ValidationError } from "../../Schema";
2 |
3 | export function stringifyValidationError(error: ValidationError): string {
4 | if (error.path.length === 0) {
5 | return error.message;
6 | }
7 | return `${error.path.join(" -> ")}: ${error.message}`;
8 | }
9 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/set/index.ts:
--------------------------------------------------------------------------------
1 | export { set } from "./set";
2 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/set/set.ts:
--------------------------------------------------------------------------------
1 | import { BaseSchema, Schema, SchemaType } from "../../Schema";
2 | import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType";
3 | import { maybeSkipValidation } from "../../utils/maybeSkipValidation";
4 | import { list } from "../list";
5 | import { getSchemaUtils } from "../schema-utils";
6 |
7 | export function set(schema: Schema): Schema> {
8 | const listSchema = list(schema);
9 | const baseSchema: BaseSchema> = {
10 | parse: async (raw, opts) => {
11 | const parsedList = await listSchema.parse(raw, opts);
12 | if (parsedList.ok) {
13 | return {
14 | ok: true,
15 | value: new Set(parsedList.value),
16 | };
17 | } else {
18 | return parsedList;
19 | }
20 | },
21 | json: async (parsed, opts) => {
22 | if (!(parsed instanceof Set)) {
23 | return {
24 | ok: false,
25 | errors: [
26 | {
27 | path: opts?.breadcrumbsPrefix ?? [],
28 | message: getErrorMessageForIncorrectType(parsed, "Set"),
29 | },
30 | ],
31 | };
32 | }
33 | const jsonList = await listSchema.json([...parsed], opts);
34 | return jsonList;
35 | },
36 | getType: () => SchemaType.SET,
37 | };
38 |
39 | return {
40 | ...maybeSkipValidation(baseSchema),
41 | ...getSchemaUtils(baseSchema),
42 | };
43 | }
44 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/undiscriminated-union/index.ts:
--------------------------------------------------------------------------------
1 | export type {
2 | inferParsedUnidiscriminatedUnionSchema,
3 | inferRawUnidiscriminatedUnionSchema,
4 | UndiscriminatedUnionSchema,
5 | } from "./types";
6 | export { undiscriminatedUnion } from "./undiscriminatedUnion";
7 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/undiscriminated-union/types.ts:
--------------------------------------------------------------------------------
1 | import { inferParsed, inferRaw, Schema } from "../../Schema";
2 |
3 | export type UndiscriminatedUnionSchema = Schema<
4 | inferRawUnidiscriminatedUnionSchema,
5 | inferParsedUnidiscriminatedUnionSchema
6 | >;
7 |
8 | export type inferRawUnidiscriminatedUnionSchema = inferRaw;
9 |
10 | export type inferParsedUnidiscriminatedUnionSchema = inferParsed;
11 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/undiscriminated-union/undiscriminatedUnion.ts:
--------------------------------------------------------------------------------
1 | import { BaseSchema, MaybeValid, Schema, SchemaOptions, SchemaType, ValidationError } from "../../Schema";
2 | import { MaybePromise } from "../../utils/MaybePromise";
3 | import { maybeSkipValidation } from "../../utils/maybeSkipValidation";
4 | import { getSchemaUtils } from "../schema-utils";
5 | import { inferParsedUnidiscriminatedUnionSchema, inferRawUnidiscriminatedUnionSchema } from "./types";
6 |
7 | export function undiscriminatedUnion, ...Schema[]]>(
8 | schemas: Schemas
9 | ): Schema, inferParsedUnidiscriminatedUnionSchema> {
10 | const baseSchema: BaseSchema<
11 | inferRawUnidiscriminatedUnionSchema,
12 | inferParsedUnidiscriminatedUnionSchema
13 | > = {
14 | parse: async (raw, opts) => {
15 | return validateAndTransformUndiscriminatedUnion>(
16 | (schema, opts) => schema.parse(raw, opts),
17 | schemas,
18 | opts
19 | );
20 | },
21 | json: async (parsed, opts) => {
22 | return validateAndTransformUndiscriminatedUnion>(
23 | (schema, opts) => schema.json(parsed, opts),
24 | schemas,
25 | opts
26 | );
27 | },
28 | getType: () => SchemaType.UNDISCRIMINATED_UNION,
29 | };
30 |
31 | return {
32 | ...maybeSkipValidation(baseSchema),
33 | ...getSchemaUtils(baseSchema),
34 | };
35 | }
36 |
37 | async function validateAndTransformUndiscriminatedUnion(
38 | transform: (schema: Schema, opts: SchemaOptions) => MaybePromise>,
39 | schemas: Schema[],
40 | opts: SchemaOptions | undefined
41 | ): Promise> {
42 | const errors: ValidationError[] = [];
43 | for (const [index, schema] of schemas.entries()) {
44 | const transformed = await transform(schema, { ...opts, skipValidation: false });
45 | if (transformed.ok) {
46 | return transformed;
47 | } else {
48 | for (const error of transformed.errors) {
49 | errors.push({
50 | path: error.path,
51 | message: `[Variant ${index}] ${error.message}`,
52 | });
53 | }
54 | }
55 | }
56 |
57 | return {
58 | ok: false,
59 | errors,
60 | };
61 | }
62 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/union/discriminant.ts:
--------------------------------------------------------------------------------
1 | export function discriminant(
2 | parsedDiscriminant: ParsedDiscriminant,
3 | rawDiscriminant: RawDiscriminant
4 | ): Discriminant {
5 | return {
6 | parsedDiscriminant,
7 | rawDiscriminant,
8 | };
9 | }
10 |
11 | export interface Discriminant {
12 | parsedDiscriminant: ParsedDiscriminant;
13 | rawDiscriminant: RawDiscriminant;
14 | }
15 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/union/index.ts:
--------------------------------------------------------------------------------
1 | export { discriminant } from "./discriminant";
2 | export type { Discriminant } from "./discriminant";
3 | export type {
4 | inferParsedDiscriminant,
5 | inferParsedUnion,
6 | inferRawDiscriminant,
7 | inferRawUnion,
8 | UnionSubtypes,
9 | } from "./types";
10 | export { union } from "./union";
11 |
--------------------------------------------------------------------------------
/src/core/schemas/builders/union/types.ts:
--------------------------------------------------------------------------------
1 | import { inferParsedObject, inferRawObject, ObjectSchema } from "../object";
2 | import { Discriminant } from "./discriminant";
3 |
4 | export type UnionSubtypes = {
5 | [K in DiscriminantValues]: ObjectSchema;
6 | };
7 |
8 | export type inferRawUnion, U extends UnionSubtypes> = {
9 | [K in keyof U]: Record, K> & inferRawObject;
10 | }[keyof U];
11 |
12 | export type inferParsedUnion, U extends UnionSubtypes> = {
13 | [K in keyof U]: Record, K> & inferParsedObject;
14 | }[keyof U];
15 |
16 | export type inferRawDiscriminant> = D extends string
17 | ? D
18 | : D extends Discriminant
19 | ? Raw
20 | : never;
21 |
22 | export type inferParsedDiscriminant> = D extends string
23 | ? D
24 | : D extends Discriminant
25 | ? Parsed
26 | : never;
27 |
--------------------------------------------------------------------------------
/src/core/schemas/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./builders";
2 | export type { inferParsed, inferRaw, Schema, SchemaOptions } from "./Schema";
3 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/MaybePromise.ts:
--------------------------------------------------------------------------------
1 | export type MaybePromise = T | Promise;
2 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/addQuestionMarksToNullableProperties.ts:
--------------------------------------------------------------------------------
1 | export type addQuestionMarksToNullableProperties = {
2 | [K in OptionalKeys]?: T[K];
3 | } & Pick>;
4 |
5 | export type OptionalKeys = {
6 | [K in keyof T]-?: undefined extends T[K]
7 | ? K
8 | : null extends T[K]
9 | ? K
10 | : 1 extends (any extends T[K] ? 0 : 1)
11 | ? never
12 | : K;
13 | }[keyof T];
14 |
15 | export type RequiredKeys = Exclude>;
16 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/createIdentitySchemaCreator.ts:
--------------------------------------------------------------------------------
1 | import { getSchemaUtils } from "../builders/schema-utils";
2 | import { BaseSchema, MaybeValid, Schema, SchemaOptions, SchemaType } from "../Schema";
3 | import { maybeSkipValidation } from "./maybeSkipValidation";
4 |
5 | export function createIdentitySchemaCreator(
6 | schemaType: SchemaType,
7 | validate: (value: unknown, opts?: SchemaOptions) => MaybeValid
8 | ): () => Schema {
9 | return () => {
10 | const baseSchema: BaseSchema = {
11 | parse: validate,
12 | json: validate,
13 | getType: () => schemaType,
14 | };
15 |
16 | return {
17 | ...maybeSkipValidation(baseSchema),
18 | ...getSchemaUtils(baseSchema),
19 | };
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/entries.ts:
--------------------------------------------------------------------------------
1 | export function entries(object: T): [keyof T, T[keyof T]][] {
2 | return Object.entries(object) as [keyof T, T[keyof T]][];
3 | }
4 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/filterObject.ts:
--------------------------------------------------------------------------------
1 | export function filterObject(obj: T, keysToInclude: K[]): Pick {
2 | const keysToIncludeSet = new Set(keysToInclude);
3 | return Object.entries(obj).reduce((acc, [key, value]) => {
4 | if (keysToIncludeSet.has(key as K)) {
5 | acc[key as K] = value;
6 | }
7 | return acc;
8 | // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter
9 | }, {} as Pick);
10 | }
11 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/getErrorMessageForIncorrectType.ts:
--------------------------------------------------------------------------------
1 | export function getErrorMessageForIncorrectType(value: unknown, expectedType: string): string {
2 | return `Expected ${expectedType}. Received ${getTypeAsString(value)}.`;
3 | }
4 |
5 | function getTypeAsString(value: unknown): string {
6 | if (Array.isArray(value)) {
7 | return "list";
8 | }
9 | if (value === null) {
10 | return "null";
11 | }
12 | switch (typeof value) {
13 | case "string":
14 | return `"${value}"`;
15 | case "number":
16 | case "boolean":
17 | case "undefined":
18 | return `${value}`;
19 | }
20 | return typeof value;
21 | }
22 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/isPlainObject.ts:
--------------------------------------------------------------------------------
1 | // borrowed from https://github.com/lodash/lodash/blob/master/isPlainObject.js
2 | export function isPlainObject(value: unknown): value is Record {
3 | if (typeof value !== "object" || value === null) {
4 | return false;
5 | }
6 |
7 | if (Object.getPrototypeOf(value) === null) {
8 | return true;
9 | }
10 |
11 | let proto = value;
12 | while (Object.getPrototypeOf(proto) !== null) {
13 | proto = Object.getPrototypeOf(proto);
14 | }
15 |
16 | return Object.getPrototypeOf(value) === proto;
17 | }
18 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/keys.ts:
--------------------------------------------------------------------------------
1 | export function keys(object: T): (keyof T)[] {
2 | return Object.keys(object) as (keyof T)[];
3 | }
4 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/maybeSkipValidation.ts:
--------------------------------------------------------------------------------
1 | import { BaseSchema, MaybeValid, SchemaOptions } from "../Schema";
2 | import { MaybePromise } from "./MaybePromise";
3 |
4 | export function maybeSkipValidation, Raw, Parsed>(schema: S): S {
5 | return {
6 | ...schema,
7 | json: transformAndMaybeSkipValidation(schema.json),
8 | parse: transformAndMaybeSkipValidation(schema.parse),
9 | };
10 | }
11 |
12 | function transformAndMaybeSkipValidation(
13 | transform: (value: unknown, opts?: SchemaOptions) => MaybePromise>
14 | ): (value: unknown, opts?: SchemaOptions) => MaybePromise> {
15 | return async (value, opts): Promise> => {
16 | const transformed = await transform(value, opts);
17 | const { skipValidation = false } = opts ?? {};
18 | if (!transformed.ok && skipValidation) {
19 | // eslint-disable-next-line no-console
20 | console.warn(
21 | [
22 | "Failed to validate.",
23 | ...transformed.errors.map(
24 | (error) =>
25 | " - " +
26 | (error.path.length > 0 ? `${error.path.join(".")}: ${error.message}` : error.message)
27 | ),
28 | ].join("\n")
29 | );
30 |
31 | return {
32 | ok: true,
33 | value: value as T,
34 | };
35 | } else {
36 | return transformed;
37 | }
38 | };
39 | }
40 |
--------------------------------------------------------------------------------
/src/core/schemas/utils/partition.ts:
--------------------------------------------------------------------------------
1 | export function partition(items: readonly T[], predicate: (item: T) => boolean): [T[], T[]] {
2 | const trueItems: T[] = [],
3 | falseItems: T[] = [];
4 | for (const item of items) {
5 | if (predicate(item)) {
6 | trueItems.push(item);
7 | } else {
8 | falseItems.push(item);
9 | }
10 | }
11 | return [trueItems, falseItems];
12 | }
13 |
--------------------------------------------------------------------------------
/src/environments.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | export const SuperAgentEnvironment = {
6 | Default: "https://api.beta.superagent.sh",
7 | } as const;
8 |
9 | export type SuperAgentEnvironment = typeof SuperAgentEnvironment.Default;
10 |
--------------------------------------------------------------------------------
/src/errors/SuperAgentError.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | export class SuperAgentError extends Error {
6 | readonly statusCode?: number;
7 | readonly body?: unknown;
8 |
9 | constructor({ message, statusCode, body }: { message?: string; statusCode?: number; body?: unknown }) {
10 | super(buildMessage({ message, statusCode, body }));
11 | Object.setPrototypeOf(this, SuperAgentError.prototype);
12 | if (statusCode != null) {
13 | this.statusCode = statusCode;
14 | }
15 |
16 | if (body !== undefined) {
17 | this.body = body;
18 | }
19 | }
20 | }
21 |
22 | function buildMessage({
23 | message,
24 | statusCode,
25 | body,
26 | }: {
27 | message: string | undefined;
28 | statusCode: number | undefined;
29 | body: unknown | undefined;
30 | }): string {
31 | let lines: string[] = [];
32 | if (message != null) {
33 | lines.push(message);
34 | }
35 |
36 | if (statusCode != null) {
37 | lines.push(`Status code: ${statusCode.toString()}`);
38 | }
39 |
40 | if (body != null) {
41 | lines.push(`Body: ${JSON.stringify(body, undefined, 2)}`);
42 | }
43 |
44 | return lines.join("\n");
45 | }
46 |
--------------------------------------------------------------------------------
/src/errors/SuperAgentTimeoutError.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | export class SuperAgentTimeoutError extends Error {
6 | constructor() {
7 | super("Timeout");
8 | Object.setPrototypeOf(this, SuperAgentTimeoutError.prototype);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/errors/index.ts:
--------------------------------------------------------------------------------
1 | export { SuperAgentError } from "./SuperAgentError";
2 | export { SuperAgentTimeoutError } from "./SuperAgentTimeoutError";
3 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * as SuperAgent from "./api";
2 | export { SuperAgentClient } from "./Client";
3 | export { SuperAgentEnvironment } from "./environments";
4 | export { SuperAgentError, SuperAgentTimeoutError } from "./errors";
5 |
--------------------------------------------------------------------------------
/src/serialization/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./types";
2 | export * from "./resources";
3 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./requests";
2 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/requests/AgentUpdate.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const AgentUpdate: core.serialization.Schema =
10 | core.serialization.object({
11 | isActive: core.serialization.boolean().optional(),
12 | name: core.serialization.string().optional(),
13 | initialMessage: core.serialization.string().optional(),
14 | prompt: core.serialization.string().optional(),
15 | llmModel: core.serialization.string().optional(),
16 | description: core.serialization.string().optional(),
17 | avatar: core.serialization.string().optional(),
18 | type: core.serialization.string().optional(),
19 | metadata: core.serialization.record(core.serialization.string(), core.serialization.unknown()).optional(),
20 | outputSchema: core.serialization.string().optional(),
21 | });
22 |
23 | export declare namespace AgentUpdate {
24 | interface Raw {
25 | isActive?: boolean | null;
26 | name?: string | null;
27 | initialMessage?: string | null;
28 | prompt?: string | null;
29 | llmModel?: string | null;
30 | description?: string | null;
31 | avatar?: string | null;
32 | type?: string | null;
33 | metadata?: Record | null;
34 | outputSchema?: string | null;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/requests/AppModelsRequestAgent.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const AppModelsRequestAgent: core.serialization.Schema<
10 | serializers.AppModelsRequestAgent.Raw,
11 | SuperAgent.AppModelsRequestAgent
12 | > = core.serialization.object({
13 | isActive: core.serialization.boolean().optional(),
14 | name: core.serialization.string(),
15 | initialMessage: core.serialization.string().optional(),
16 | prompt: core.serialization.string().optional(),
17 | llmModel: core.serialization.string().optional(),
18 | llmProvider: core.serialization.lazy(async () => (await import("../../../..")).LlmProvider).optional(),
19 | description: core.serialization.string().optional(),
20 | avatar: core.serialization.string().optional(),
21 | type: core.serialization.lazy(async () => (await import("../../../..")).AgentType).optional(),
22 | parameters: core.serialization
23 | .lazyObject(async () => (await import("../../../..")).OpenAiAssistantParameters)
24 | .optional(),
25 | metadata: core.serialization.record(core.serialization.string(), core.serialization.unknown()).optional(),
26 | outputSchema: core.serialization.string().optional(),
27 | });
28 |
29 | export declare namespace AppModelsRequestAgent {
30 | interface Raw {
31 | isActive?: boolean | null;
32 | name: string;
33 | initialMessage?: string | null;
34 | prompt?: string | null;
35 | llmModel?: string | null;
36 | llmProvider?: serializers.LlmProvider.Raw | null;
37 | description?: string | null;
38 | avatar?: string | null;
39 | type?: serializers.AgentType.Raw | null;
40 | parameters?: serializers.OpenAiAssistantParameters.Raw | null;
41 | metadata?: Record | null;
42 | outputSchema?: string | null;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/requests/AppModelsRequestAgentDatasource.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const AppModelsRequestAgentDatasource: core.serialization.Schema<
10 | serializers.AppModelsRequestAgentDatasource.Raw,
11 | SuperAgent.AppModelsRequestAgentDatasource
12 | > = core.serialization.object({
13 | datasourceId: core.serialization.string(),
14 | });
15 |
16 | export declare namespace AppModelsRequestAgentDatasource {
17 | interface Raw {
18 | datasourceId: string;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/requests/AppModelsRequestAgentInvoke.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const AppModelsRequestAgentInvoke: core.serialization.Schema<
10 | serializers.AppModelsRequestAgentInvoke.Raw,
11 | SuperAgent.AppModelsRequestAgentInvoke
12 | > = core.serialization.object({
13 | input: core.serialization.string(),
14 | sessionId: core.serialization.string().optional(),
15 | enableStreaming: core.serialization.boolean(),
16 | outputSchema: core.serialization.string().optional(),
17 | llmParams: core.serialization.property(
18 | "llm_params",
19 | core.serialization.lazyObject(async () => (await import("../../../..")).LlmParams).optional()
20 | ),
21 | });
22 |
23 | export declare namespace AppModelsRequestAgentInvoke {
24 | interface Raw {
25 | input: string;
26 | sessionId?: string | null;
27 | enableStreaming: boolean;
28 | outputSchema?: string | null;
29 | llm_params?: serializers.LlmParams.Raw | null;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/requests/AppModelsRequestAgentLlm.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const AppModelsRequestAgentLlm: core.serialization.Schema<
10 | serializers.AppModelsRequestAgentLlm.Raw,
11 | SuperAgent.AppModelsRequestAgentLlm
12 | > = core.serialization.object({
13 | llmId: core.serialization.string(),
14 | });
15 |
16 | export declare namespace AppModelsRequestAgentLlm {
17 | interface Raw {
18 | llmId: string;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/requests/AppModelsRequestAgentTool.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const AppModelsRequestAgentTool: core.serialization.Schema<
10 | serializers.AppModelsRequestAgentTool.Raw,
11 | SuperAgent.AppModelsRequestAgentTool
12 | > = core.serialization.object({
13 | toolId: core.serialization.string(),
14 | });
15 |
16 | export declare namespace AppModelsRequestAgentTool {
17 | interface Raw {
18 | toolId: string;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/client/requests/index.ts:
--------------------------------------------------------------------------------
1 | export { AppModelsRequestAgent } from "./AppModelsRequestAgent";
2 | export { AgentUpdate } from "./AgentUpdate";
3 | export { AppModelsRequestAgentInvoke } from "./AppModelsRequestAgentInvoke";
4 | export { AppModelsRequestAgentLlm } from "./AppModelsRequestAgentLlm";
5 | export { AppModelsRequestAgentTool } from "./AppModelsRequestAgentTool";
6 | export { AppModelsRequestAgentDatasource } from "./AppModelsRequestAgentDatasource";
7 |
--------------------------------------------------------------------------------
/src/serialization/resources/agent/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./client";
2 |
--------------------------------------------------------------------------------
/src/serialization/resources/index.ts:
--------------------------------------------------------------------------------
1 | export * as agent from "./agent";
2 | export * from "./agent/client/requests";
3 | export * as tool from "./tool";
4 | export * from "./tool/client/requests";
5 | export * as workflow from "./workflow";
6 | export * from "./workflow/client/requests";
7 |
--------------------------------------------------------------------------------
/src/serialization/resources/tool/client/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./requests";
2 |
--------------------------------------------------------------------------------
/src/serialization/resources/tool/client/requests/AppModelsRequestTool.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const AppModelsRequestTool: core.serialization.Schema<
10 | serializers.AppModelsRequestTool.Raw,
11 | SuperAgent.AppModelsRequestTool
12 | > = core.serialization.object({
13 | name: core.serialization.string(),
14 | description: core.serialization.string().optional(),
15 | type: core.serialization.string(),
16 | metadata: core.serialization.record(core.serialization.string(), core.serialization.unknown()).optional(),
17 | returnDirect: core.serialization.boolean().optional(),
18 | });
19 |
20 | export declare namespace AppModelsRequestTool {
21 | interface Raw {
22 | name: string;
23 | description?: string | null;
24 | type: string;
25 | metadata?: Record | null;
26 | returnDirect?: boolean | null;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/serialization/resources/tool/client/requests/ToolUpdate.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const ToolUpdate: core.serialization.Schema =
10 | core.serialization.object({
11 | name: core.serialization.string().optional(),
12 | description: core.serialization.string().optional(),
13 | type: core.serialization.string().optional(),
14 | metadata: core.serialization.record(core.serialization.string(), core.serialization.unknown()).optional(),
15 | returnDirect: core.serialization.boolean().optional(),
16 | });
17 |
18 | export declare namespace ToolUpdate {
19 | interface Raw {
20 | name?: string | null;
21 | description?: string | null;
22 | type?: string | null;
23 | metadata?: Record | null;
24 | returnDirect?: boolean | null;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/serialization/resources/tool/client/requests/index.ts:
--------------------------------------------------------------------------------
1 | export { AppModelsRequestTool } from "./AppModelsRequestTool";
2 | export { ToolUpdate } from "./ToolUpdate";
3 |
--------------------------------------------------------------------------------
/src/serialization/resources/tool/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./client";
2 |
--------------------------------------------------------------------------------
/src/serialization/resources/workflow/client/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./requests";
2 |
--------------------------------------------------------------------------------
/src/serialization/resources/workflow/client/requests/WorkflowInvoke.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file was auto-generated by Fern from our API Definition.
3 | */
4 |
5 | import * as serializers from "../../../..";
6 | import * as SuperAgent from "../../../../../api";
7 | import * as core from "../../../../../core";
8 |
9 | export const WorkflowInvoke: core.serialization.Schema