Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ts-rest/core

Package Overview
Dependencies
Maintainers
1
Versions
136
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ts-rest/core - npm Package Compare versions

Comparing version 3.26.0-rc3.0 to 3.26.0

5

CHANGELOG.md
# @ts-rest/core
## 3.26.0-rc3.0
## 3.26.0
### Minor Changes
- e8ea535: Add new `SingleHandler` and `MultiHandler` API to `@ts-rest/nest`
- fcf877d: Allow defining non-json response types in the contract
- 48b138d: Add new `SingleHandler` and `MultiHandler` API to `@ts-rest/nest`
- 2763208: Added `pathPrefix` to contract options to allow recursive path prefixing.

@@ -9,0 +10,0 @@

24

index.js

@@ -94,2 +94,3 @@ 'use strict';

};
const ContractPlainTypeRuntimeSymbol = Symbol('ContractPlainType');
const initContract = () => {

@@ -100,4 +101,9 @@ return {

mutation: (args) => args,
response: () => undefined,
body: () => undefined,
response: () => ContractPlainTypeRuntimeSymbol,
body: () => ContractPlainTypeRuntimeSymbol,
type: () => ContractPlainTypeRuntimeSymbol,
otherResponse: ({ contentType, body, }) => ({
contentType,
body,
}),
};

@@ -109,3 +115,3 @@ };

.replace(/:([^/]+)/g, (_, p) => {
return (params === null || params === void 0 ? void 0 : params[p]) || '';
return params[p] || '';
})

@@ -340,6 +346,14 @@ .replace(/\/\//g, '/');

};
const isAppRouteOtherResponse = (response) => {
return (response != null &&
typeof response === 'object' &&
'contentType' in response);
};
const validateResponse = ({ responseType, response, }) => {
if (isAppRouteResponse(response)) {
const { body } = response;
const responseValidation = checkZodSchema(body, responseType);
const responseSchema = isAppRouteOtherResponse(responseType)
? responseType.body
: responseType;
const responseValidation = checkZodSchema(body, responseSchema);
if (!responseValidation.success) {

@@ -357,2 +371,3 @@ const { error } = responseValidation;

exports.ContractPlainTypeRuntimeSymbol = ContractPlainTypeRuntimeSymbol;
exports.ResponseValidationError = ResponseValidationError;

@@ -374,2 +389,3 @@ exports.UnknownStatusError = UnknownStatusError;

exports.isAppRoute = isAppRoute;
exports.isAppRouteOtherResponse = isAppRouteOtherResponse;
exports.isAppRouteResponse = isAppRouteResponse;

@@ -376,0 +392,0 @@ exports.isZodObject = isZodObject;

{
"name": "@ts-rest/core",
"version": "3.26.0-rc3.0",
"version": "3.26.0",
"description": "RPC-like experience over a regular REST API, with type safe server implementations 🪄",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -69,6 +69,3 @@ import { AppRoute, AppRouteMutation, AppRouter } from './dsl';

export declare const getCompleteUrl: (query: unknown, baseUrl: string, params: unknown, route: AppRoute, jsonQuery: boolean) => string;
type FullClientInferRequest = ClientInferRequest<AppRouteMutation & {
path: '/:placeholder';
}, ClientArgs>;
export declare const getRouteQuery: <TAppRoute extends AppRoute>(route: TAppRoute, clientArgs: InitClientArgs) => (inputArgs?: FullClientInferRequest) => Promise<{
export declare const getRouteQuery: <TAppRoute extends AppRoute>(route: TAppRoute, clientArgs: InitClientArgs) => (inputArgs?: ClientInferRequest<AppRouteMutation, ClientArgs>) => Promise<{
status: number;

@@ -75,0 +72,0 @@ body: unknown;

@@ -12,11 +12,19 @@ import { Merge, Opaque, Prettify, WithoutUnknown } from './type-utils';

type Path = string;
declare const NullSymbol: unique symbol;
export type ContractPlainType<T> = Opaque<T, 'ContractPlainType'>;
export type ContractNullType = Opaque<typeof NullSymbol, 'ContractNullType'>;
export type ContractAnyType = z.ZodTypeAny | ContractPlainType<unknown> | ContractNullType | null;
export type ContractOtherResponse<T extends ContractAnyType> = Opaque<{
contentType: string;
body: T;
}, 'ContractOtherResponse'>;
type AppRouteCommon = {
path: Path;
pathParams?: unknown;
query?: unknown;
headers?: unknown;
pathParams?: ContractAnyType;
query?: ContractAnyType;
headers?: ContractAnyType;
summary?: string;
description?: string;
deprecated?: boolean;
responses: Record<number, unknown>;
responses: Record<number, ContractAnyType | ContractOtherResponse<ContractAnyType>>;
strictStatusCodes?: boolean;

@@ -38,3 +46,3 @@ metadata?: unknown;

contentType?: 'application/json' | 'multipart/form-data';
body: unknown;
body: ContractAnyType;
};

@@ -96,3 +104,3 @@ type ValidatedHeaders<T extends AppRoute, TOptions extends RouterOptions, TOptionsApplied = ApplyOptions<T, TOptions>> = 'headers' extends keyof TOptionsApplied ? TOptionsApplied['headers'] extends MixedZodError<infer A, infer B> ? {

*/
router: <TRouter extends AppRouter, TPrefix extends string, TOptions extends RouterOptions<TPrefix>>(endpoints: RecursivelyProcessAppRouter<TRouter, TOptions>, options?: TOptions) => RecursivelyApplyOptions<TRouter, TOptions>;
router: <TRouter extends AppRouter, TPrefix extends string, TOptions extends RouterOptions<TPrefix> = {}>(endpoints: RecursivelyProcessAppRouter<TRouter, TOptions>, options?: TOptions) => RecursivelyApplyOptions<TRouter, TOptions>;
/**

@@ -109,9 +117,20 @@ * A single query route, should exist within

/**
* Exists to allow storing a Type in the contract (at compile time only)
* @deprecated Please use type() instead.
*/
response: <T>() => T;
response: <T>() => T extends null ? ContractNullType : ContractPlainType<T>;
/**
* @deprecated Please use type() instead.
*/
body: <T>() => T extends null ? ContractNullType : ContractPlainType<T>;
/**
* Exists to allow storing a Type in the contract (at compile time only)
*/
body: <T>() => T;
type: <T>() => T extends null ? ContractNullType : ContractPlainType<T>;
/**
* Define a custom response type
*/
otherResponse: <T extends ContractAnyType>({ contentType, body, }: {
contentType: string;
body: T;
}) => ContractOtherResponse<T>;
};

@@ -123,2 +142,3 @@ /**

export declare const initTsRest: () => ContractInstance;
export declare const ContractPlainTypeRuntimeSymbol: any;
/**

@@ -125,0 +145,0 @@ * Instantiate a ts-rest client, primarily to access `router`, `response`, and `body`

@@ -1,2 +0,2 @@

import { AppRoute, AppRouteMutation, AppRouter, AppRouteStrictStatusCodes } from './dsl';
import { AppRoute, AppRouteMutation, AppRouter, AppRouteStrictStatusCodes, ContractAnyType, ContractOtherResponse } from './dsl';
import { HTTPStatusCode } from './status-codes';

@@ -15,6 +15,7 @@ import { And, Extends, LowercaseKeys, Merge, Not, OptionalIfAllOptional, Or, PartialByLooseKeys, Prettify, Without, ZodInferOrType, ZodInputOrType } from './type-utils';

type PathParamsWithCustomValidators<T extends AppRoute, TClientOrServer extends 'client' | 'server' = 'server'> = T['pathParams'] extends undefined ? PathParamsFromUrl<T> : Merge<PathParamsFromUrl<T>, TClientOrServer extends 'server' ? ZodInferOrType<T['pathParams']> : ZodInputOrType<T['pathParams']>>;
export type ResolveResponseType<T extends ContractAnyType | ContractOtherResponse<ContractAnyType>> = T extends ContractOtherResponse<infer U> ? U : T;
type AppRouteResponses<T extends AppRoute, TStatus extends HTTPStatusCode, TClientOrServer extends 'client' | 'server', TStrictStatusCodes extends 'default' | 'ignore' | 'force' = 'default'> = {
[K in keyof T['responses'] & TStatus]: {
status: K;
body: TClientOrServer extends 'server' ? ZodInputOrType<T['responses'][K]> : ZodInferOrType<T['responses'][K]>;
body: TClientOrServer extends 'server' ? ZodInputOrType<ResolveResponseType<T['responses'][K]>> : ZodInferOrType<ResolveResponseType<T['responses'][K]>>;
} & (TClientOrServer extends 'client' ? {

@@ -37,5 +38,5 @@ headers: Headers;

export type ClientInferResponseBody<T extends AppRoute, TStatus extends keyof T['responses'] = keyof T['responses']> = Prettify<AppRouteResponses<T, TStatus & HTTPStatusCode, 'client'>['body']>;
type BodyWithoutFileIfMultiPart<T extends AppRouteMutation> = Prettify<T['contentType'] extends 'multipart/form-data' ? Without<ZodInferOrType<T['body']>, File> : ZodInferOrType<T['body']>>;
type BodyWithoutFileIfMultiPart<T extends AppRouteMutation> = T['contentType'] extends 'multipart/form-data' ? Without<ZodInferOrType<T['body']>, File> : ZodInferOrType<T['body']>;
export type ServerInferRequest<T extends AppRoute | AppRouter, TServerHeaders = never> = T extends AppRoute ? Prettify<Without<{
params: [undefined] extends PathParamsWithCustomValidators<T> ? never : Prettify<PathParamsWithCustomValidators<T>>;
params: [keyof PathParamsWithCustomValidators<T>] extends [never] ? never : Prettify<PathParamsWithCustomValidators<T>>;
body: T extends AppRouteMutation ? BodyWithoutFileIfMultiPart<T> : never;

@@ -50,3 +51,5 @@ query: 'query' extends keyof T ? ZodInferOrType<T['query']> : never;

}, THeaders = 'headers' extends keyof T ? Prettify<PartialByLooseKeys<LowercaseKeys<ZodInputOrType<T['headers']>>, keyof LowercaseKeys<TClientArgs['baseHeaders']>>> : never> = Prettify<Without<{
params: [undefined] extends PathParamsWithCustomValidators<T, 'client'> ? never : Prettify<PathParamsWithCustomValidators<T, 'client'>>;
params: [keyof PathParamsWithCustomValidators<T, 'client'>] extends [
never
] ? never : Prettify<PathParamsWithCustomValidators<T, 'client'>>;
body: T extends AppRouteMutation ? T['body'] extends null ? never : T['contentType'] extends 'multipart/form-data' ? FormData | ZodInputOrType<T['body']> : ZodInputOrType<T['body']> : never;

@@ -53,0 +56,0 @@ query: 'query' extends keyof T ? T['query'] extends null ? never : ZodInputOrType<T['query']> : never;

@@ -21,3 +21,3 @@ /**

*/
export type ParamsFromUrl<T extends string> = RecursivelyExtractPathParams<T, {}> extends infer U ? keyof U extends never ? undefined : {
export type ParamsFromUrl<T extends string> = RecursivelyExtractPathParams<T, {}> extends infer U ? {
[key in keyof U]: U[key];

@@ -24,0 +24,0 @@ } : never;

import { HTTPStatusCode } from './status-codes';
import { ContractAnyType, ContractOtherResponse } from './dsl';
export declare const isAppRouteResponse: (value: unknown) => value is {

@@ -6,4 +7,5 @@ status: HTTPStatusCode;

};
export declare const isAppRouteOtherResponse: (response: ContractAnyType | ContractOtherResponse<ContractAnyType>) => response is ContractOtherResponse<ContractAnyType>;
export declare const validateResponse: ({ responseType, response, }: {
responseType: unknown;
responseType: ContractAnyType | ContractOtherResponse<ContractAnyType>;
response: {

@@ -10,0 +12,0 @@ status: number;

import { z } from 'zod';
import { ContractNullType, ContractPlainType } from './dsl';
type GetIndexedField<T, K> = K extends keyof T ? T[K] : K extends `${number}` ? '0' extends keyof T ? undefined : number extends keyof T ? T[number] : undefined : undefined;

@@ -14,4 +15,4 @@ type FieldWithPossiblyUndefined<T, Key> = GetFieldType<Exclude<T, undefined>, Key> | Extract<T, undefined>;

export type With<T, V> = Pick<T, ExcludeKeysWithoutTypeOf<T, V>>;
export type ZodInferOrType<T> = T extends z.ZodTypeAny ? z.infer<T> : T;
export type ZodInputOrType<T> = T extends z.ZodTypeAny ? z.input<T> : T;
export type ZodInferOrType<T> = T extends ContractNullType ? null : T extends ContractPlainType<infer U> ? U : T extends z.ZodTypeAny ? z.infer<T> : T;
export type ZodInputOrType<T> = T extends ContractNullType ? null : T extends ContractPlainType<infer U> ? U : T extends z.ZodTypeAny ? z.input<T> : T;
export type Merge<T, U> = Omit<T, keyof U> & U;

@@ -44,2 +45,3 @@ type Try<A, B, C> = A extends B ? A : C;

export type Opaque<Type, Token = unknown> = Type & Tagged<Token>;
export type UnwrapOpaque<OpaqueType extends Tagged<unknown>> = OpaqueType extends Opaque<infer Type, OpaqueType[typeof tag]> ? Type : OpaqueType;
export type WithoutUnknown<T> = Pick<T, {

@@ -46,0 +48,0 @@ [K in keyof T]: unknown extends Exclude<T[K], undefined> ? never : K;

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc