@lokalise/frontend-http-client
Advanced tools
Comparing version
import { z, ZodSchema } from 'zod'; | ||
import { WretchResponse, Wretch } from 'wretch'; | ||
import { GetRouteDefinition, InferSchemaOutput, PayloadRouteDefinition, DeleteRouteDefinition } from '@lokalise/universal-ts-utils/api-contracts/apiContracts'; | ||
import { Wretch, WretchResponse } from 'wretch'; | ||
@@ -39,13 +40,32 @@ type FreeformRecord = Record<string, unknown>; | ||
}; | ||
type RequestResultType<ResponseBody, isNonJSONResponseExpected extends boolean, isEmptyResponseExpected extends boolean> = isEmptyResponseExpected extends true ? isNonJSONResponseExpected extends true ? WretchResponse | null : ResponseBody | null : isNonJSONResponseExpected extends true ? WretchResponse : ResponseBody; | ||
type ResourceChangeParams<RequestBody, ResponseBody, IsNonJSONResponseExpected extends boolean, IsEmptyResponseExpected extends boolean, RequestQuerySchema extends z.Schema | undefined = undefined> = (RequestBody extends z.Schema ? BodyRequestParams<RequestBody, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected> : FreeBodyRequestParams<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>) & (RequestQuerySchema extends z.Schema ? QueryParams<RequestQuerySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected> : FreeQueryParams<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>); | ||
type RequestResultType<ResponseBody, isNonJSONResponseExpected extends boolean, isEmptyResponseExpected extends boolean> = isEmptyResponseExpected extends true ? isNonJSONResponseExpected extends true ? WretchResponse | null : ResponseBody extends undefined ? null : ResponseBody | null : isNonJSONResponseExpected extends true ? WretchResponse : ResponseBody extends undefined ? null : ResponseBody; | ||
type PayloadRequestParamsWrapper<RequestBody, ResponseBody, IsNonJSONResponseExpected extends boolean, IsEmptyResponseExpected extends boolean, RequestQuerySchema extends z.Schema | undefined = undefined> = (RequestBody extends z.Schema ? BodyRequestParams<RequestBody, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected> : FreeBodyRequestParams<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>) & (RequestQuerySchema extends z.Schema ? QueryParams<RequestQuerySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected> : FreeQueryParams<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>); | ||
type GetParamsWrapper<ResponseBody, IsNonJSONResponseExpected extends boolean, IsEmptyResponseExpected extends boolean, RequestQuerySchema extends z.Schema | undefined = undefined> = RequestQuerySchema extends z.Schema ? QueryParams<RequestQuerySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected> : FreeQueryParams<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>; | ||
type PayloadRouteRequestParams<PathParams = undefined, RequestBody = undefined, RequestQuery = never, RequestHeader = never> = { | ||
body: RequestBody extends undefined ? never : RequestBody; | ||
queryParams: RequestQuery extends never | undefined ? never : RequestQuery; | ||
headers: RequestHeader extends never | undefined ? never : RequestHeader; | ||
pathParams: PathParams extends undefined ? never : PathParams; | ||
} extends infer Mandatory ? { | ||
[K in keyof Mandatory as Mandatory[K] extends never ? never : K]: Mandatory[K]; | ||
} : never; | ||
type RouteRequestParams<PathParams = undefined, RequestQuery = never, RequestHeader = never> = { | ||
queryParams: RequestQuery extends never | undefined ? never : RequestQuery; | ||
headers: RequestHeader extends never | undefined ? never : RequestHeader; | ||
pathParams: PathParams extends undefined ? never : PathParams; | ||
} extends infer Mandatory ? { | ||
[K in keyof Mandatory as Mandatory[K] extends never ? never : K]: Mandatory[K]; | ||
} : never; | ||
type WretchInstance = Wretch<any, unknown, undefined>; | ||
declare const UNKNOWN_SCHEMA: z.ZodUnknown; | ||
declare function sendGet<T extends WretchInstance, ResponseBody, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: RequestQuerySchema extends z.Schema ? QueryParams<RequestQuerySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected> : FreeQueryParams<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendPost<T extends WretchInstance, ResponseBody, RequestBodySchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: ResourceChangeParams<RequestBodySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected, RequestQuerySchema>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendPut<T extends WretchInstance, ResponseBody, RequestBodySchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: ResourceChangeParams<RequestBodySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected, RequestQuerySchema>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendPatch<T extends WretchInstance, ResponseBody, RequestBodySchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: ResourceChangeParams<RequestBodySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected, RequestQuerySchema>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendGet<T extends WretchInstance, ResponseBody, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: GetParamsWrapper<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected, RequestQuerySchema>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendPost<T extends WretchInstance, ResponseBody, RequestBodySchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: PayloadRequestParamsWrapper<RequestBodySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected, RequestQuerySchema>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendPut<T extends WretchInstance, ResponseBody, RequestBodySchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: PayloadRequestParamsWrapper<RequestBodySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected, RequestQuerySchema>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendPatch<T extends WretchInstance, ResponseBody, RequestBodySchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, params: PayloadRequestParamsWrapper<RequestBodySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected, RequestQuerySchema>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendDelete<T extends WretchInstance, ResponseBody, RequestQuerySchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = true>(wretch: T, params: RequestQuerySchema extends z.Schema ? DeleteParams<RequestQuerySchema, ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected> : FreeDeleteParams<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>): Promise<RequestResultType<ResponseBody, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendByPayloadRoute<T extends WretchInstance, RequestBodySchema extends z.Schema | undefined, ResponseBodySchema extends z.Schema | undefined = undefined, PathParamsSchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, RequestHeaderSchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, routeDefinition: PayloadRouteDefinition<InferSchemaOutput<PathParamsSchema>, RequestBodySchema, ResponseBodySchema, PathParamsSchema, RequestQuerySchema, RequestHeaderSchema, IsNonJSONResponseExpected, IsEmptyResponseExpected>, params: PayloadRouteRequestParams<InferSchemaOutput<PathParamsSchema>, InferSchemaOutput<RequestBodySchema>, InferSchemaOutput<RequestQuerySchema>, InferSchemaOutput<RequestHeaderSchema>>): Promise<RequestResultType<InferSchemaOutput<ResponseBodySchema>, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendByGetRoute<T extends WretchInstance, ResponseBodySchema extends z.Schema | undefined = undefined, PathParamsSchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, RequestHeaderSchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false>(wretch: T, routeDefinition: GetRouteDefinition<InferSchemaOutput<PathParamsSchema>, ResponseBodySchema, PathParamsSchema, RequestQuerySchema, RequestHeaderSchema, IsNonJSONResponseExpected, IsEmptyResponseExpected>, params: RouteRequestParams<InferSchemaOutput<PathParamsSchema>, InferSchemaOutput<RequestQuerySchema>, InferSchemaOutput<RequestHeaderSchema>>): Promise<RequestResultType<InferSchemaOutput<ResponseBodySchema>, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
declare function sendByDeleteRoute<T extends WretchInstance, ResponseBodySchema extends z.Schema | undefined = undefined, PathParamsSchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, RequestHeaderSchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = true>(wretch: T, routeDefinition: DeleteRouteDefinition<InferSchemaOutput<PathParamsSchema>, ResponseBodySchema, PathParamsSchema, RequestQuerySchema, RequestHeaderSchema, IsNonJSONResponseExpected, IsEmptyResponseExpected>, params: RouteRequestParams<InferSchemaOutput<PathParamsSchema>, InferSchemaOutput<RequestQuerySchema>, InferSchemaOutput<RequestHeaderSchema>>): Promise<RequestResultType<InferSchemaOutput<ResponseBodySchema>, IsNonJSONResponseExpected, IsEmptyResponseExpected>>; | ||
export { UNKNOWN_SCHEMA, sendDelete, sendGet, sendPatch, sendPost, sendPut }; | ||
export { UNKNOWN_SCHEMA, sendByDeleteRoute, sendByGetRoute, sendByPayloadRoute, sendDelete, sendGet, sendPatch, sendPost, sendPut }; |
145
package.json
{ | ||
"name": "@lokalise/frontend-http-client", | ||
"version": "2.1.0", | ||
"description": "Opinionated HTTP client for the frontend", | ||
"files": [ | ||
"dist/**", | ||
"LICENSE", | ||
"README.md" | ||
], | ||
"main": "./dist/index.cjs", | ||
"types": "./dist/index.d.ts", | ||
"module": "./dist/index.mjs", | ||
"type": "module", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.mjs" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
} | ||
}, | ||
"author": { | ||
"name": "Lokalise", | ||
"url": "https://lokalise.com/" | ||
}, | ||
"homepage": "https://github.com/lokalise/frontend-http-client", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/lokalise/frontend-http-client.git" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"build:dev": "tsc", | ||
"build:release": "tsup", | ||
"clean": "rimraf dist .eslintcache", | ||
"lint": "eslint --cache --max-warnings=0 . && prettier --check src \"**/*.{json,md,ts,tsx}\" && tsc --noEmit", | ||
"lint:fix": "prettier --write src \"**/*.{json,md,ts,tsx}\" --log-level=warn && eslint . --fix", | ||
"test": "vitest run --coverage", | ||
"prepublishOnly": "npm run clean && npm run build:release" | ||
}, | ||
"dependencies": { | ||
"fast-querystring": "^1.1.2" | ||
}, | ||
"peerDependencies": { | ||
"wretch": "^2.8.0", | ||
"zod": "^3.22.0" | ||
}, | ||
"devDependencies": { | ||
"@lokalise/prettier-config": "^1.0.0", | ||
"@types/node": "^20.11.5", | ||
"@typescript-eslint/eslint-plugin": "^7.0.1", | ||
"@typescript-eslint/parser": "^7.0.1", | ||
"@vitest/coverage-v8": "^1.6.0", | ||
"jest-fail-on-console": "^3.1.2", | ||
"eslint": "^8.56.0", | ||
"eslint-plugin-import": "^2.29.1", | ||
"eslint-plugin-vitest": "^0.4.0", | ||
"eslint-plugin-import-esm": "^2.0.0", | ||
"mockttp": "^3.10.1", | ||
"prettier": "^3.2.5", | ||
"rimraf": "^5.0.5", | ||
"tsup": "8.1.0", | ||
"typescript": "~5.5.3", | ||
"vitest": "^1.6.0" | ||
}, | ||
"keywords": [ | ||
"frontend", | ||
"web", | ||
"browser", | ||
"http", | ||
"client", | ||
"zod", | ||
"validation", | ||
"typesafe" | ||
], | ||
"prettier": "@lokalise/prettier-config" | ||
"name": "@lokalise/frontend-http-client", | ||
"version": "2.2.0", | ||
"description": "Opinionated HTTP client for the frontend", | ||
"files": ["dist/**", "LICENSE", "README.md"], | ||
"main": "./dist/index.cjs", | ||
"types": "./dist/index.d.ts", | ||
"module": "./dist/index.mjs", | ||
"type": "module", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.mjs" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
} | ||
}, | ||
"author": { | ||
"name": "Lokalise", | ||
"url": "https://lokalise.com/" | ||
}, | ||
"homepage": "https://github.com/lokalise/shared-ts-libs", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/lokalise/shared-ts-libs.git" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"build:dev": "tsc", | ||
"build:release": "tsup", | ||
"clean": "rimraf dist", | ||
"lint": "biome check . && tsc --project tsconfig.lint.json --noEmit", | ||
"lint:fix": "biome check --write", | ||
"package-version": "echo $npm_package_version", | ||
"test": "vitest run --coverage", | ||
"prepublishOnly": "npm run clean && npm run build:release", | ||
"postversion": "biome check --write package.json" | ||
}, | ||
"dependencies": { | ||
"fast-querystring": "^1.1.2" | ||
}, | ||
"peerDependencies": { | ||
"wretch": "^2.8.0", | ||
"zod": "^3.22.0" | ||
}, | ||
"devDependencies": { | ||
"@biomejs/biome": "^1.8.3", | ||
"@lokalise/biome-config": "^1.0.0", | ||
"@lokalise/universal-ts-utils": "^3.3.0", | ||
"@types/node": "^22.0.0", | ||
"@vitest/coverage-v8": "^3.0.5", | ||
"jest-fail-on-console": "^3.1.2", | ||
"mockttp": "^3.13.0", | ||
"rimraf": "^6.0.0", | ||
"tsup": "8.3.6", | ||
"typescript": "~5.7.2", | ||
"vitest": "^3.0.5" | ||
}, | ||
"keywords": ["frontend", "web", "browser", "http", "client", "zod", "validation", "typesafe"] | ||
} |
@@ -66,2 +66,34 @@ # Frontend HTTP client | ||
### API contract-based requests | ||
`frontend-http-client` supports using API contracts, created with `@lokalise/universal-ts-utils/api-contracts/apiContracts` in order to make fully type-safe HTTP requests. | ||
Usage example: | ||
```ts | ||
import { somePostRouteDefinition, someGetRouteDefinition } from 'some-service-api-contracts' | ||
import { sendByPayloadRoute } from '@lokalise/frontend-http-client' | ||
import wretch from 'wretch' | ||
const client = wretch(BASE_URL) | ||
const responseBody1 = await sendByPayloadRoute(client, somePostRouteDefinition, { | ||
pathParams: { | ||
userId: 1, | ||
}, | ||
body: { | ||
isActive: true, | ||
}, | ||
}) | ||
const responseBody2 = await sendByGetRoute(client, someGetRouteDefinition, { | ||
pathParams: { | ||
userId: 1, | ||
}, | ||
queryParams: { | ||
id: 'testId', | ||
}, | ||
}) | ||
``` | ||
## Credits | ||
@@ -68,0 +100,0 @@ |
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
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
106925
33.56%11
-31.25%752
20.13%108
42.11%