@ts-rest/core
Advanced tools
Comparing version 0.1.5 to 0.1.6
{ | ||
"name": "@ts-rest/core", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "RPC-like experience over a regular REST API, with type safe server implementations 🪄", | ||
@@ -20,2 +20,4 @@ "type": "commonjs", | ||
"peerDependencies": { | ||
"zod": "^3.17.10", | ||
"@tscont/ts-rest-utils": "0.0.1", | ||
"express": "4.18.1", | ||
@@ -22,0 +24,0 @@ "tslib": "^2.3.0" |
@@ -1,11 +0,16 @@ | ||
import { AppRoute, AppRouter } from './dsl'; | ||
import { z } from 'zod'; | ||
import { AppRoute, AppRouteMutation, AppRouter } from './dsl'; | ||
import { Without } from '@tscont/ts-rest-utils'; | ||
declare type RecursiveProxyObj<T extends AppRouter> = { | ||
[TKey in keyof T]: T[TKey] extends AppRouter ? RecursiveProxyObj<T[TKey]> : T[TKey] extends AppRoute ? DataReturn<T[TKey]> : never; | ||
}; | ||
declare type DataReturn<TRoute extends AppRoute> = Parameters<TRoute['path']>[0] extends undefined ? () => Promise<{ | ||
declare type AppRouteMutationType<T> = T extends z.AnyZodObject ? z.infer<T> : T; | ||
declare type DataReturnArgs<TRoute extends AppRoute> = { | ||
body: TRoute extends AppRouteMutation ? AppRouteMutationType<TRoute['body']> : never; | ||
params: Parameters<TRoute['path']>[0] extends undefined ? never : Parameters<TRoute['path']>[0]; | ||
query: TRoute['query'] extends z.AnyZodObject ? AppRouteMutationType<TRoute['query']> : never; | ||
}; | ||
declare type DataReturn<TRoute extends AppRoute> = (args: Without<DataReturnArgs<TRoute>, never>) => Promise<{ | ||
data: TRoute['response']; | ||
status: number; | ||
}> : (path: Parameters<TRoute['path']>[0]) => Promise<{ | ||
data: TRoute['response']; | ||
status: number; | ||
}>; | ||
@@ -21,2 +26,3 @@ declare type ClientArgs = { | ||
headers: Record<string, string>; | ||
body: string | undefined; | ||
}) => Promise<{ | ||
@@ -26,3 +32,4 @@ status: number; | ||
}>; | ||
export declare type InitClientReturn<T extends AppRouter> = RecursiveProxyObj<T>; | ||
export declare const initClient: <T extends AppRouter>(router: T, args: ClientArgs) => RecursiveProxyObj<T>; | ||
export {}; |
@@ -6,9 +6,26 @@ "use strict"; | ||
const dsl_1 = require("./dsl"); | ||
const getRouteQuery = (route, args) => { | ||
return (pathParams) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const path = route.path(pathParams); | ||
const result = yield args.api({ | ||
path: args.baseUrl + path, | ||
const getRouteQuery = (route, clientArgs) => { | ||
return (inputArgs) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const path = route.path(inputArgs.params); | ||
const queryString = typeof inputArgs.query === 'object' | ||
? Object.keys(inputArgs.query) | ||
.map((key) => { | ||
return (encodeURIComponent(key) + | ||
'=' + | ||
encodeURIComponent(inputArgs.query[key])); | ||
}) | ||
.join('&') | ||
: ''; | ||
const completeUrl = `${clientArgs.baseUrl}${path}${queryString.length > 0 && | ||
queryString !== null && | ||
queryString !== undefined | ||
? '?' + queryString | ||
: ''}`; | ||
const result = yield clientArgs.api({ | ||
path: completeUrl, | ||
method: route.method, | ||
headers: args.baseHeaders, | ||
headers: Object.assign(Object.assign({}, clientArgs.baseHeaders), { 'Content-Type': 'application/json' }), | ||
body: inputArgs.body !== null && inputArgs.body !== undefined | ||
? JSON.stringify(inputArgs.body) | ||
: undefined, | ||
}); | ||
@@ -24,2 +41,3 @@ return { data: result.data, status: result.status }; | ||
if ((0, dsl_1.isAppRoute)(subRouter)) { | ||
// If the current router.X is a route, return a function to handle the users args | ||
return getRouteQuery(subRouter, args); | ||
@@ -26,0 +44,0 @@ } |
@@ -1,6 +0,17 @@ | ||
export declare type AppRoute = { | ||
method: string; | ||
export declare type AppRouteQuery = { | ||
__type: 'AppRouteQuery'; | ||
method: 'GET'; | ||
path: PathFunction; | ||
response: unknown; | ||
query?: unknown; | ||
}; | ||
export declare type AppRouteMutation = { | ||
__type: 'AppRouteMutation'; | ||
method: 'POST' | 'DELETE' | 'PUT' | 'PATCH'; | ||
path: PathFunction; | ||
response: unknown; | ||
body: unknown; | ||
query?: unknown; | ||
}; | ||
export declare type AppRoute = AppRouteQuery | AppRouteMutation; | ||
export declare type AppRouter = { | ||
@@ -12,3 +23,5 @@ [key: string]: AppRouter | AppRoute; | ||
declare type TsCont = { | ||
router: <T extends AppRouter>(endpoints: T) => T; | ||
router: <T extends { | ||
[key: string]: AppRoute | AppRouter; | ||
}>(endpoints: T) => T; | ||
query: <T extends { | ||
@@ -18,7 +31,14 @@ method: 'GET'; | ||
response: unknown; | ||
}, P extends PathFunction>(query: T) => T; | ||
query: unknown; | ||
}, P extends PathFunction>(query: T) => T & { | ||
__type: 'AppRouteQuery'; | ||
}; | ||
mutation: <T extends { | ||
method: 'POST' | 'PUT' | 'DELETE'; | ||
method: 'POST' | 'DELETE' | 'PUT' | 'PATCH'; | ||
path: P; | ||
}, P extends PathFunction>(mutation: T) => T; | ||
response: unknown; | ||
body: unknown; | ||
}, P extends PathFunction>(mutation: T) => T & { | ||
__type: 'AppRouteMutation'; | ||
}; | ||
response: <T>() => T; | ||
@@ -25,0 +45,0 @@ path: <T>() => T; |
@@ -11,4 +11,4 @@ "use strict"; | ||
router: (args) => args, | ||
query: (args) => args, | ||
mutation: (args) => args, | ||
query: (args) => (Object.assign({ __type: 'AppRouteQuery' }, args)), | ||
mutation: (args) => (Object.assign({ __type: 'AppRouteMutation' }, args)), | ||
response: () => '', | ||
@@ -15,0 +15,0 @@ path: () => '', |
import { Express } from 'express'; | ||
import { AppRoute, AppRouter } from './dsl'; | ||
declare type AppRouteImplementation<T extends AppRoute> = (params: Parameters<T['path']>[0]) => Promise<T['response']>; | ||
import { z } from 'zod'; | ||
import { AppRoute, AppRouteMutation, AppRouteQuery, AppRouter } from './dsl'; | ||
declare type AppRouteQueryImplementation<T extends AppRouteQuery> = (input: { | ||
params: Parameters<T['path']>[0]; | ||
}) => Promise<T['response']>; | ||
declare type AppRouteMutationImplementation<T extends AppRouteMutation> = (input: { | ||
params: Parameters<T['path']>[0]; | ||
body: T['body'] extends z.AnyZodObject ? z.infer<T['body']> : null; | ||
}) => Promise<T['response']>; | ||
declare type AppRouteImplementation<T extends AppRoute> = T extends AppRouteMutation ? AppRouteMutationImplementation<T> : T extends AppRouteQuery ? AppRouteQueryImplementation<T> : never; | ||
declare type RecursiveRouterObj<T extends AppRouter> = { | ||
@@ -5,0 +13,0 @@ [TKey in keyof T]: T[TKey] extends AppRouter ? RecursiveRouterObj<T[TKey]> : T[TKey] extends AppRoute ? AppRouteImplementation<T[TKey]> : never; |
@@ -7,3 +7,3 @@ "use strict"; | ||
const server_1 = require("./server"); | ||
const type_utils_1 = require("./type-utils"); | ||
const ts_rest_utils_1 = require("@tscont/ts-rest-utils"); | ||
const initServer = () => { | ||
@@ -25,15 +25,51 @@ return { | ||
}; | ||
const transformAppRouteImplementation = (route, schema, app) => { | ||
const transformAppRouteQueryImplementation = (route, schema, app) => { | ||
const path = (0, server_1.getAppRoutePathRoute)(schema); | ||
console.log(`[tscont] Initialized ${schema.method} ${path}`); | ||
app.get(path, (req, res) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const result = yield route(req.params); | ||
return res.json(result); | ||
return res.json(yield route({ params: req.params })); | ||
})); | ||
}; | ||
const transformAppRouteMutationImplementation = (route, schema, app) => { | ||
const path = (0, server_1.getAppRoutePathRoute)(schema); | ||
console.log(`[tscont] Initialized ${schema.method} ${path}`); | ||
const method = schema.method; | ||
const callback = (req, res) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
try { | ||
const result = yield route({ params: req.params, body: req.body }); | ||
return res.json(result); | ||
} | ||
catch (e) { | ||
console.error(`[tscont] Error on ${method} ${path}`, e); | ||
return res.status(500).send('Internal Server Error'); | ||
} | ||
}); | ||
switch (method) { | ||
case 'DELETE': | ||
app.delete(path, callback); | ||
break; | ||
case 'POST': | ||
app.post(path, callback); | ||
break; | ||
case 'PUT': | ||
app.put(path, callback); | ||
break; | ||
case 'PATCH': | ||
app.patch(path, callback); | ||
break; | ||
default: | ||
// eslint-disable-next-line no-case-declarations, @typescript-eslint/no-unused-vars | ||
const _exhaustiveCheck = method; | ||
} | ||
}; | ||
const createExpressEndpoints = (schema, router, app) => { | ||
recursivelyApplyExpressRouter(router, [], (route, path) => { | ||
const routerViaPath = (0, type_utils_1.getValue)(schema, path.join('.')); | ||
const routerViaPath = (0, ts_rest_utils_1.getValue)(schema, path.join('.')); | ||
if ((0, dsl_1.isAppRoute)(routerViaPath)) { | ||
transformAppRouteImplementation(route, routerViaPath, app); | ||
if (routerViaPath.__type === 'AppRouteMutation') { | ||
transformAppRouteMutationImplementation(route, routerViaPath, app); | ||
} | ||
else { | ||
transformAppRouteQueryImplementation(route, routerViaPath, app); | ||
} | ||
} | ||
@@ -40,0 +76,0 @@ else { |
import { AppRoute, AppRouter } from './dsl'; | ||
import { Without } from './type-utils'; | ||
import { Without } from '@tscont/ts-rest-utils'; | ||
declare type AppRouteShape<T extends AppRoute> = (params: Parameters<T['path']>[0]) => Promise<T['response']>; | ||
@@ -4,0 +4,0 @@ declare type AppRouterControllerShape<T extends AppRouter> = { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26181
324
4
20