From a4db3c0ff390823a38527d5a803b26082e7ea8fd Mon Sep 17 00:00:00 2001 From: Igor Kamyshev Date: Tue, 30 Jul 2024 14:09:26 +0700 Subject: [PATCH] rec -> obj --- .../contracts/cookbook/custom_matchers.md | 4 ++-- .../contracts/cookbook/optional_fields.md | 10 ++++----- apps/website/docs/contracts/index.md | 16 +++++++------- packages/contracts/src/contracts.test.ts | 22 +++++++++---------- packages/contracts/src/index.ts | 20 ++++++++--------- packages/contracts/src/interop.test.ts | 4 ++-- 6 files changed, 37 insertions(+), 39 deletions(-) diff --git a/apps/website/docs/contracts/cookbook/custom_matchers.md b/apps/website/docs/contracts/cookbook/custom_matchers.md index 84e3b3b8..93d81a91 100644 --- a/apps/website/docs/contracts/cookbook/custom_matchers.md +++ b/apps/website/docs/contracts/cookbook/custom_matchers.md @@ -19,9 +19,9 @@ function age(min, max): Contract { Now you can use this matcher in your schema: ```ts -import { rec, str, and, num } from '@withease/contracts'; +import { obj, str, and, num } from '@withease/contracts'; -const User = rec({ +const User = obj({ name: str, age: and(num, age(18, 100)), }); diff --git a/apps/website/docs/contracts/cookbook/optional_fields.md b/apps/website/docs/contracts/cookbook/optional_fields.md index a5a1c55d..afafd65a 100644 --- a/apps/website/docs/contracts/cookbook/optional_fields.md +++ b/apps/website/docs/contracts/cookbook/optional_fields.md @@ -1,13 +1,13 @@ # Optional Fields -By default, all fields mentioned in the schema of `rec` are required. However, you can make a field optional explicitly. +By default, all fields mentioned in the schema of `obj` are required. However, you can make a field optional explicitly. In case you expect a field to have `null` as a value, you can add it to the field definition as follows: ```ts -import { rec, str, num, or, val } from '@withease/contracts'; +import { obj, str, num, or, val } from '@withease/contracts'; -const UserWithOptionalAge = rec({ +const UserWithOptionalAge = obj({ name: str, age: or(num, val(null)), }); @@ -16,9 +16,9 @@ const UserWithOptionalAge = rec({ If you expect a field to be missing, you can pass `undefined` as a value: ```ts -import { rec, str, num, or, val } from '@withease/contracts'; +import { obj, str, num, or, val } from '@withease/contracts'; -const UserWithPossibleNoAge = rec({ +const UserWithPossibleNoAge = obj({ name: str, age: or(num, val(undefined)), }); diff --git a/apps/website/docs/contracts/index.md b/apps/website/docs/contracts/index.md index d63752af..f1024eb9 100644 --- a/apps/website/docs/contracts/index.md +++ b/apps/website/docs/contracts/index.md @@ -48,9 +48,9 @@ npm install @withease/contracts `@withease/contracts` provides a special type `UnContract` that can be used to extract a type from a _Contract_. ```ts -import { type UnContract, rec, str, num } from '@withease/contracts'; +import { type UnContract, obj, str, num } from '@withease/contracts'; -const UserContract = rec({ +const UserContract = obj({ id: num, name: str, email: str, @@ -70,7 +70,7 @@ type User = UnContract; ```ts import { createJsonQuery } from '@farfetched/core'; -import { rec, str, arr, val, or } from '@withease/contracts'; +import { obj, str, arr, val, or } from '@withease/contracts'; const characterQuery = createJsonQuery({ params: declareParams<{ id: number }>(), @@ -82,15 +82,15 @@ const characterQuery = createJsonQuery({ // after receiving data from the server // check if it is conforms the Contract to ensure // API does not return something unexpected - contract: rec({ + contract: obj({ id: str, name: str, status: Status, species: str, type: str, gender: Gender, - origin: rec({ name: str, url: str }), - location: rec({ name: str, url: str }), + origin: obj({ name: str, url: str }), + location: obj({ name: str, url: str }), image: or(val('Female'), val('Male'), val('Genderless')), episode: arr(str), }), @@ -128,7 +128,7 @@ For instance, you can define a part of a [_Contract_](/protocols/contract) with ```ts import { z } from 'zod'; -import { arr, rec } from '@withease/contracts'; +import { arr, obj } from '@withease/contracts'; import { zodContract } from '@farfetched/zod'; const User = z.object({ @@ -136,7 +136,7 @@ const User = z.object({ }); const MyContract = arr( - rec({ + obj({ // 👇 easily integrate Zod via compatibility layer users: zodContract(User), }) diff --git a/packages/contracts/src/contracts.test.ts b/packages/contracts/src/contracts.test.ts index dcf25ccf..5216223e 100644 --- a/packages/contracts/src/contracts.test.ts +++ b/packages/contracts/src/contracts.test.ts @@ -1,6 +1,6 @@ import { describe, it, test, expect } from 'vitest'; -import { bool, num, str, rec, or, val, arr, and, Contract } from './index'; +import { bool, num, str, obj, or, val, arr, and, Contract } from './index'; describe('bool', () => { it('valid', () => { @@ -313,9 +313,9 @@ describe('str', () => { }); }); - describe('rec, overload with fields', () => { + describe('obj, overload with fields', () => { it('empty object', () => { - const cntrct = rec({}); + const cntrct = obj({}); expect(cntrct.isData({})).toBeTruthy(); expect(cntrct.getErrorMessages({})).toEqual([]); @@ -326,7 +326,7 @@ describe('str', () => { }); it('object with bool', () => { - const cntrct = rec({ enabled: bool }); + const cntrct = obj({ enabled: bool }); expect(cntrct.isData({ enabled: true })).toBeTruthy(); expect(cntrct.getErrorMessages({ enabled: true })).toEqual([]); @@ -358,20 +358,20 @@ describe('str', () => { }); it('optional field edge case', () => { - expect(rec({ name: or(str, val(undefined)) }).isData({})).toBeTruthy(); + expect(obj({ name: or(str, val(undefined)) }).isData({})).toBeTruthy(); }); }); - describe('rec, overload with types', () => { + describe('obj, overload with types', () => { it('empty object', () => { - const cntrct = rec(str, num); + const cntrct = obj(str, num); expect(cntrct.isData({})).toBeTruthy(); expect(cntrct.getErrorMessages({})).toEqual([]); }); it('invalid field type', () => { - const cntrct = rec(str, str); + const cntrct = obj(str, str); expect(cntrct.isData({ a: 'a' })).toBeTruthy(); expect(cntrct.getErrorMessages({ a: 'a' })).toEqual([]); @@ -451,8 +451,8 @@ describe('str', () => { describe('complex nested', () => { test('format errors for nested objects', () => { - const cntrct = rec({ - user: rec({ name: str }), + const cntrct = obj({ + user: obj({ name: str }), }); expect(cntrct.isData({ user: { name: 'a' } })).toBeTruthy(); @@ -468,7 +468,7 @@ describe('complex nested', () => { }); test('supports objects in arrays', () => { - const cntrct = arr(rec({ name: str })); + const cntrct = arr(obj({ name: str })); expect(cntrct.isData([])).toBeTruthy(); expect(cntrct.getErrorMessages([])).toEqual([]); diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts index b6fbf34a..7d9d669e 100644 --- a/packages/contracts/src/index.ts +++ b/packages/contracts/src/index.ts @@ -1,10 +1,8 @@ -import { func } from 'superstruct'; - /** * A type that allows to extract the result type of a _Contract_. * * @example - * const User = rec({ + * const User = obj({ * name: str, * age: num, * }); @@ -137,7 +135,7 @@ export function or>>( * }; * } * - * const User = rec({ + * const User = obj({ * name: str, * age: and(num, age(18, 100)), * }); @@ -164,15 +162,15 @@ export function and( /** * Function that creates a _Contract_ that checks if a value is object and every property is conform to the given _Contract_. * - * @overload "rec(str, contract)" + * @overload "obj(str, contract)" * * @example - * const Ids = rec(str, num); + * const Ids = obj(str, num); * * Ids.isData({ id1: 1, id2: 2 }) === true; * Ids.isData({ id1: 1, id2: '2' }) === false; */ -export function rec( +export function obj( keys: typeof str, values: Contract ): Contract>; @@ -180,10 +178,10 @@ export function rec( /** * Function that creates a _Contract_ that checks if a value is conform to an object with the given _Contracts_ as properties. * - * @overload "rec(shape)" + * @overload "obj(shape)" * * @example - * const User = rec({ + * const User = obj({ * name: str, * age: num, * }); @@ -191,11 +189,11 @@ export function rec( * User.isData({ name: 'Alice', age: 42 }) === true; * User.isData({ name: 'Alice' }) === false; */ -export function rec>>( +export function obj>>( c: C ): Contract }>; -export function rec(shape: any, fieldContract?: any): any { +export function obj(shape: any, fieldContract?: any): any { const check = (x: unknown) => { if (typeof x !== 'object' || x === null) return false; diff --git a/packages/contracts/src/interop.test.ts b/packages/contracts/src/interop.test.ts index 46a7759e..1b67dfdc 100644 --- a/packages/contracts/src/interop.test.ts +++ b/packages/contracts/src/interop.test.ts @@ -5,11 +5,11 @@ import { object, string } from 'superstruct'; import { runtypeContract } from '@farfetched/runtypes'; import { superstructContract } from '@farfetched/superstruct'; -import { rec, arr } from './index'; +import { obj, arr } from './index'; describe('runtypes', () => { it('supports Runtype inside', () => { - const cntrct = rec({ name: runtypeContract(Array(String)) }); + const cntrct = obj({ name: runtypeContract(Array(String)) }); expect(cntrct.isData({ name: ['foo'] })).toBe(true); expect(cntrct.getErrorMessages({ name: ['foo'] })).toEqual([]);