@orpc/client 0.0.0-next.9ada823 → 0.0.0-next.9b3a030

Sign up to get free protection for your applications and to get access to all the features.
package/dist/fetch.js CHANGED
@@ -1,50 +1,87 @@
1
1
  // src/adapters/fetch/orpc-link.ts
2
+ import { ORPCError } from "@orpc/contract";
2
3
  import { ORPCPayloadCodec } from "@orpc/server/fetch";
3
4
  import { ORPC_HANDLER_HEADER, ORPC_HANDLER_VALUE, trim } from "@orpc/shared";
4
- import { ORPCError } from "@orpc/shared/error";
5
5
  var ORPCLink = class {
6
+ fetch;
7
+ payloadCodec;
8
+ maxURLLength;
9
+ fallbackMethod;
10
+ getMethod;
11
+ getHeaders;
12
+ url;
6
13
  constructor(options) {
7
- this.options = options;
8
14
  this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
9
15
  this.payloadCodec = options.payloadCodec ?? new ORPCPayloadCodec();
16
+ this.maxURLLength = options.maxURLLength ?? 2083;
17
+ this.fallbackMethod = options.fallbackMethod ?? "POST";
18
+ this.url = options.url;
19
+ this.getMethod = async (path, input, context) => {
20
+ return await options.method?.(path, input, context) ?? this.fallbackMethod;
21
+ };
22
+ this.getHeaders = async (path, input, context) => {
23
+ return new Headers(await options.headers?.(path, input, context));
24
+ };
10
25
  }
11
- fetch;
12
- payloadCodec;
13
26
  async call(path, input, options) {
14
27
  const clientContext = options.context;
15
- const url = new URL(`${trim(this.options.url, "/")}/${path.map(encodeURIComponent).join("/")}`);
16
- const method = await this.options.method?.(path, input, clientContext) ?? "POST";
17
- const encoded = this.payloadCodec.encode(input, method);
18
- if (encoded.query) {
19
- for (const [key, value] of encoded.query.entries()) {
20
- url.searchParams.append(key, value);
21
- }
22
- }
23
- const headers = new Headers(encoded.headers);
24
- headers.append(ORPC_HANDLER_HEADER, ORPC_HANDLER_VALUE);
25
- let customHeaders = await this.options.headers?.(path, input, clientContext);
26
- customHeaders = customHeaders instanceof Headers ? customHeaders : new Headers(customHeaders);
27
- for (const [key, value] of customHeaders.entries()) {
28
- headers.append(key, value);
29
- }
30
- const response = await this.fetch(url, {
31
- method,
32
- headers,
28
+ const encoded = await this.encode(path, input, options);
29
+ const response = await this.fetch(encoded.url, {
30
+ method: encoded.method,
31
+ headers: encoded.headers,
33
32
  body: encoded.body,
34
33
  signal: options.signal
35
34
  }, clientContext);
36
35
  const decoded = await this.payloadCodec.decode(response);
37
36
  if (!response.ok) {
38
- const error = ORPCError.fromJSON(decoded) ?? new ORPCError({
37
+ if (ORPCError.isValidJSON(decoded)) {
38
+ throw new ORPCError(decoded);
39
+ }
40
+ throw new ORPCError({
39
41
  status: response.status,
40
42
  code: "INTERNAL_SERVER_ERROR",
41
43
  message: "Internal server error",
42
44
  cause: decoded
43
45
  });
44
- throw error;
45
46
  }
46
47
  return decoded;
47
48
  }
49
+ async encode(path, input, options) {
50
+ const clientContext = options.context;
51
+ const expectMethod = await this.getMethod(path, input, clientContext);
52
+ const methods = /* @__PURE__ */ new Set([expectMethod, this.fallbackMethod]);
53
+ const baseHeaders = await this.getHeaders(path, input, clientContext);
54
+ const baseUrl = new URL(`${trim(this.url, "/")}/${path.map(encodeURIComponent).join("/")}`);
55
+ baseHeaders.append(ORPC_HANDLER_HEADER, ORPC_HANDLER_VALUE);
56
+ for (const method of methods) {
57
+ const url = new URL(baseUrl);
58
+ const headers = new Headers(baseHeaders);
59
+ const encoded = this.payloadCodec.encode(input, method, this.fallbackMethod);
60
+ if (encoded.query) {
61
+ for (const [key, value] of encoded.query.entries()) {
62
+ url.searchParams.append(key, value);
63
+ }
64
+ }
65
+ if (url.toString().length > this.maxURLLength) {
66
+ continue;
67
+ }
68
+ if (encoded.headers) {
69
+ for (const [key, value] of encoded.headers.entries()) {
70
+ headers.append(key, value);
71
+ }
72
+ }
73
+ return {
74
+ url,
75
+ headers,
76
+ method: encoded.method,
77
+ body: encoded.body
78
+ };
79
+ }
80
+ throw new ORPCError({
81
+ code: "BAD_REQUEST",
82
+ message: "Cannot encode the request, please check the url length or payload."
83
+ });
84
+ }
48
85
  };
49
86
  export {
50
87
  ORPCLink
package/dist/index.js CHANGED
@@ -24,16 +24,19 @@ var DynamicLink = class {
24
24
  this.linkResolver = linkResolver;
25
25
  }
26
26
  async call(path, input, options) {
27
- const resolvedLink = await this.linkResolver(path, input, options);
27
+ const resolvedLink = await this.linkResolver(path, input, options.context);
28
28
  const output = await resolvedLink.call(path, input, options);
29
29
  return output;
30
30
  }
31
31
  };
32
32
 
33
33
  // src/index.ts
34
- export * from "@orpc/shared/error";
34
+ import { isDefinedError, ORPCError, safe } from "@orpc/contract";
35
35
  export {
36
36
  DynamicLink,
37
- createORPCClient
37
+ ORPCError,
38
+ createORPCClient,
39
+ isDefinedError,
40
+ safe
38
41
  };
39
42
  //# sourceMappingURL=index.js.map
@@ -1,21 +1,47 @@
1
- import type { HTTPMethod } from '@orpc/contract';
2
1
  import type { ProcedureClientOptions } from '@orpc/server';
3
2
  import type { Promisable } from '@orpc/shared';
4
3
  import type { ClientLink } from '../../types';
5
4
  import type { FetchWithContext } from './types';
5
+ import { type HTTPMethod } from '@orpc/contract';
6
6
  import { type PublicORPCPayloadCodec } from '@orpc/server/fetch';
7
7
  export interface ORPCLinkOptions<TClientContext> {
8
+ /**
9
+ * Base url for all requests.
10
+ */
8
11
  url: string;
12
+ /**
13
+ * The maximum length of the URL.
14
+ *
15
+ * @default 2083
16
+ */
17
+ maxURLLength?: number;
18
+ /**
19
+ * The method used to make the request.
20
+ *
21
+ * @default 'POST'
22
+ */
9
23
  method?: (path: readonly string[], input: unknown, context: TClientContext) => Promisable<HTTPMethod | undefined>;
24
+ /**
25
+ * The method to use when the payload cannot safely pass to the server with method return from method function.
26
+ * Do not use GET as fallback method, it's very dangerous.
27
+ *
28
+ * @default 'POST'
29
+ */
30
+ fallbackMethod?: HTTPMethod;
10
31
  headers?: (path: readonly string[], input: unknown, context: TClientContext) => Promisable<Headers | Record<string, string>>;
11
32
  fetch?: FetchWithContext<TClientContext>;
12
33
  payloadCodec?: PublicORPCPayloadCodec;
13
34
  }
14
35
  export declare class ORPCLink<TClientContext> implements ClientLink<TClientContext> {
15
- private readonly options;
16
36
  private readonly fetch;
17
37
  private readonly payloadCodec;
38
+ private readonly maxURLLength;
39
+ private readonly fallbackMethod;
40
+ private readonly getMethod;
41
+ private readonly getHeaders;
42
+ private readonly url;
18
43
  constructor(options: ORPCLinkOptions<TClientContext>);
19
44
  call(path: readonly string[], input: unknown, options: ProcedureClientOptions<TClientContext>): Promise<unknown>;
45
+ private encode;
20
46
  }
21
47
  //# sourceMappingURL=orpc-link.d.ts.map
@@ -7,9 +7,7 @@ import type { ClientLink } from './types';
7
7
  */
8
8
  export declare class DynamicLink<TClientContext> implements ClientLink<TClientContext> {
9
9
  private readonly linkResolver;
10
- constructor(linkResolver: (path: readonly string[], input: unknown, options: ProcedureClientOptions<TClientContext> & {
11
- context: TClientContext;
12
- }) => Promisable<ClientLink<TClientContext>>);
10
+ constructor(linkResolver: (path: readonly string[], input: unknown, context: TClientContext) => Promisable<ClientLink<TClientContext>>);
13
11
  call(path: readonly string[], input: unknown, options: ProcedureClientOptions<TClientContext>): Promise<unknown>;
14
12
  }
15
13
  //# sourceMappingURL=dynamic-link.d.ts.map
@@ -2,5 +2,5 @@
2
2
  export * from './client';
3
3
  export * from './dynamic-link';
4
4
  export * from './types';
5
- export * from '@orpc/shared/error';
5
+ export { isDefinedError, ORPCError, safe } from '@orpc/contract';
6
6
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/client",
3
3
  "type": "module",
4
- "version": "0.0.0-next.9ada823",
4
+ "version": "0.0.0-next.9b3a030",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -33,16 +33,14 @@
33
33
  "!**/*.tsbuildinfo",
34
34
  "dist"
35
35
  ],
36
- "peerDependencies": {
37
- "@orpc/contract": "0.0.0-next.9ada823"
38
- },
39
36
  "dependencies": {
40
- "@orpc/server": "0.0.0-next.9ada823",
41
- "@orpc/shared": "0.0.0-next.9ada823"
37
+ "@orpc/contract": "0.0.0-next.9b3a030",
38
+ "@orpc/server": "0.0.0-next.9b3a030",
39
+ "@orpc/shared": "0.0.0-next.9b3a030"
42
40
  },
43
41
  "devDependencies": {
44
42
  "zod": "^3.24.1",
45
- "@orpc/openapi": "0.0.0-next.9ada823"
43
+ "@orpc/openapi": "0.0.0-next.9b3a030"
46
44
  },
47
45
  "scripts": {
48
46
  "build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/adapters/fetch/index.ts --format=esm --onSuccess='tsc -b --noCheck'",