@palbase/backend-client 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +4 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -6
- package/dist/index.d.ts +5 -6
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,7 @@ var BackendInvocationBuilder = class {
|
|
|
52
52
|
}
|
|
53
53
|
call(method, options) {
|
|
54
54
|
const qs = options?.query ? this.buildQuery(options.query) : "";
|
|
55
|
-
const fullPath =
|
|
55
|
+
const fullPath = `/${this.path}${qs}`;
|
|
56
56
|
const reqOpts = {
|
|
57
57
|
headers: options?.headers,
|
|
58
58
|
signal: options?.signal
|
|
@@ -92,10 +92,9 @@ var BackendClient = class {
|
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* Lower-level builder for callers that need GET/PUT/DELETE etc. The
|
|
95
|
-
* builder talks to the same
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* affordances the simple `call()` doesn't expose.
|
|
95
|
+
* builder talks to the same file-based route as `call()` — the
|
|
96
|
+
* builder remains for headers/query/AbortSignal affordances the simple
|
|
97
|
+
* `call()` doesn't expose.
|
|
99
98
|
*/
|
|
100
99
|
invoke(path) {
|
|
101
100
|
return new BackendInvocationBuilder(this.httpClient, path);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/backend-client.ts"],"sourcesContent":["export {\n BackendClient,\n BackendInvocationBuilder,\n LOCALHOST,\n} from './backend-client.js';\nexport type {\n InvokeOptions,\n RpcCallOptions,\n BackendEndpoints,\n BackendEnvironment,\n} from './backend-client.js';\n","import type { HttpClient, PalbaseResponse, RequestOptions } from '@palbase/core';\n\n/**\n * Module augmentation hook — users export their endpoint map from\n * `.palbase/types.d.ts` and add the type via:\n *\n * ```ts\n * declare module '@palbase/backend-client' {\n * interface BackendEndpoints {\n * checkout: { input: { items: string[] }; output: { orderId: string } };\n * }\n * }\n * ```\n *\n * `pb.backend.call('checkout', { items: ['a'] })` then resolves the\n * input + output types automatically. Without augmentation the call\n * falls back to `unknown` and the developer has to cast manually.\n */\n// biome-ignore lint/suspicious/noEmptyInterface: augmentation target on purpose\nexport interface BackendEndpoints {}\n\n/**\n * Options accepted by every backend invocation. `body` is JSON-encoded\n * for POST/PUT/PATCH; `query` is appended as a query string. `signal`\n * lets callers wire AbortController for cancellation.\n */\nexport interface InvokeOptions {\n body?: unknown;\n query?: Record<string, string | number | boolean | null | undefined>;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Per-call options for the typed RPC `call(name, input)` API.\n * `headers` and `signal` cover the common needs; the body is the\n * input argument itself, so there is no `body` here.\n */\nexport interface RpcCallOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Backend connection environment. Drives the base path the client\n * issues requests against. Default is `'remote'` — Kong gateway via\n * the configured Palbase host.\n */\nexport type BackendEnvironment =\n | 'remote'\n | { custom: string };\n\n/** Convenience alias for the most common dev override. */\nexport const LOCALHOST: BackendEnvironment = { custom: 'http://localhost:4003' };\n\n/**\n * BackendInvocationBuilder is the chainable handle returned by\n * `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,\n * `put`, `patch`, `del`, `call`) issues a request to\n * `<host
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/backend-client.ts"],"sourcesContent":["export {\n BackendClient,\n BackendInvocationBuilder,\n LOCALHOST,\n} from './backend-client.js';\nexport type {\n InvokeOptions,\n RpcCallOptions,\n BackendEndpoints,\n BackendEnvironment,\n} from './backend-client.js';\n","import type { HttpClient, PalbaseResponse, RequestOptions } from '@palbase/core';\n\n/**\n * Module augmentation hook — users export their endpoint map from\n * `.palbase/types.d.ts` and add the type via:\n *\n * ```ts\n * declare module '@palbase/backend-client' {\n * interface BackendEndpoints {\n * checkout: { input: { items: string[] }; output: { orderId: string } };\n * }\n * }\n * ```\n *\n * `pb.backend.call('checkout', { items: ['a'] })` then resolves the\n * input + output types automatically. Without augmentation the call\n * falls back to `unknown` and the developer has to cast manually.\n */\n// biome-ignore lint/suspicious/noEmptyInterface: augmentation target on purpose\nexport interface BackendEndpoints {}\n\n/**\n * Options accepted by every backend invocation. `body` is JSON-encoded\n * for POST/PUT/PATCH; `query` is appended as a query string. `signal`\n * lets callers wire AbortController for cancellation.\n */\nexport interface InvokeOptions {\n body?: unknown;\n query?: Record<string, string | number | boolean | null | undefined>;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Per-call options for the typed RPC `call(name, input)` API.\n * `headers` and `signal` cover the common needs; the body is the\n * input argument itself, so there is no `body` here.\n */\nexport interface RpcCallOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Backend connection environment. Drives the base path the client\n * issues requests against. Default is `'remote'` — Kong gateway via\n * the configured Palbase host.\n */\nexport type BackendEnvironment =\n | 'remote'\n | { custom: string };\n\n/** Convenience alias for the most common dev override. */\nexport const LOCALHOST: BackendEnvironment = { custom: 'http://localhost:4003' };\n\n/**\n * BackendInvocationBuilder is the chainable handle returned by\n * `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,\n * `put`, `patch`, `del`, `call`) issues a request to\n * `<host>/<path>` with the given HTTP verb. The builder is\n * intentionally tiny — backend endpoints are user-defined, so we\n * don't bake any DSL on top.\n */\nexport class BackendInvocationBuilder<T = unknown> {\n private readonly httpClient: HttpClient;\n private readonly path: string;\n\n constructor(httpClient: HttpClient, path: string) {\n this.httpClient = httpClient;\n // Strip exactly one leading slash so callers can type either\n // `pb.backend.invoke('hello')` or `pb.backend.invoke('/hello')`.\n this.path = path.replace(/^\\/+/, '');\n }\n\n get(options?: InvokeOptions): Promise<PalbaseResponse<T>> {\n return this.call<T>('GET', options);\n }\n post(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>> {\n return this.call<T>('POST', { ...options, body });\n }\n put(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>> {\n return this.call<T>('PUT', { ...options, body });\n }\n patch(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>> {\n return this.call<T>('PATCH', { ...options, body });\n }\n del(options?: InvokeOptions): Promise<PalbaseResponse<T>> {\n return this.call<T>('DELETE', options);\n }\n\n call<R = T>(method: string, options?: InvokeOptions): Promise<PalbaseResponse<R>> {\n const qs = options?.query ? this.buildQuery(options.query) : '';\n // Adım B14 — endpoints are file-based (`pb.backend.call(\"users/list\")`\n // -> `POST /users/list`), so the request path is exactly the\n // endpoint name passed to invoke().\n const fullPath = `/${this.path}${qs}`;\n const reqOpts: RequestOptions = {\n headers: options?.headers,\n signal: options?.signal,\n };\n if (options?.body !== undefined) {\n // HttpClient JSON-encodes body when content-type is unset.\n // We pass through raw — caller can override Content-Type via\n // headers if they need form-urlencoded etc.\n (reqOpts as RequestOptions & { body?: unknown }).body = options.body;\n }\n return this.httpClient.request<R>(method, fullPath, reqOpts);\n }\n\n private buildQuery(q: NonNullable<InvokeOptions['query']>): string {\n const parts: string[] = [];\n for (const [k, v] of Object.entries(q)) {\n if (v === undefined || v === null) continue;\n parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);\n }\n return parts.length ? `?${parts.join('&')}` : '';\n }\n}\n\n/** Resolve typed input/output for an operation when the user has\n * augmented `BackendEndpoints`; otherwise fall back to `unknown`. */\ntype EndpointInput<K extends string> = K extends keyof BackendEndpoints\n ? BackendEndpoints[K] extends { input: infer I }\n ? I\n : unknown\n : unknown;\ntype EndpointOutput<K extends string> = K extends keyof BackendEndpoints\n ? BackendEndpoints[K] extends { output: infer O }\n ? O\n : unknown\n : unknown;\n\n/**\n * BackendClient is the entry point exposed as `pb.backend` on the\n * unified client. It issues typed RPC calls to per-tenant\n * backend-runtime pods routed through Kong as `<ref>.<host>/<name>`.\n * Each defineEndpoint a user ships in their `endpoints/` tree becomes\n * one operation here.\n */\nexport class BackendClient {\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Typed RPC dispatch — the primary API. When the user augments\n * `BackendEndpoints` (typically via `palbase backend types`), the\n * `name` argument autocompletes and `input` / return type are\n * inferred. Without augmentation both default to `unknown`.\n *\n * ```ts\n * const r = await pb.backend.call('checkout', { items: ['a'] });\n * // r.data is typed when BackendEndpoints['checkout'] is declared.\n * ```\n */\n call<K extends string>(\n name: K & (K extends keyof BackendEndpoints ? K : string),\n input: EndpointInput<K>,\n options?: RpcCallOptions,\n ): Promise<PalbaseResponse<EndpointOutput<K>>> {\n return this.invoke<EndpointOutput<K>>(name).post(input, options) as Promise<\n PalbaseResponse<EndpointOutput<K>>\n >;\n }\n\n /**\n * Lower-level builder for callers that need GET/PUT/DELETE etc. The\n * builder talks to the same file-based route as `call()` — the\n * builder remains for headers/query/AbortSignal affordances the simple\n * `call()` doesn't expose.\n */\n invoke<T = unknown>(path: string): BackendInvocationBuilder<T> {\n return new BackendInvocationBuilder<T>(this.httpClient, path);\n }\n\n /**\n * One-shot fetch helper for explicit method+path. Kept so existing\n * callers (legacy code, tests) compile; new code should use\n * `call(name, input)` for the typed RPC path.\n */\n request<T = unknown>(\n method: string,\n path: string,\n options?: InvokeOptions,\n ): Promise<PalbaseResponse<T>> {\n return this.invoke<T>(path).call<T>(method, options);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqDO,IAAM,YAAgC,EAAE,QAAQ,wBAAwB;AAUxE,IAAM,2BAAN,MAA4C;AAAA,EAChC;AAAA,EACA;AAAA,EAEjB,YAAY,YAAwB,MAAc;AAChD,SAAK,aAAa;AAGlB,SAAK,OAAO,KAAK,QAAQ,QAAQ,EAAE;AAAA,EACrC;AAAA,EAEA,IAAI,SAAsD;AACxD,WAAO,KAAK,KAAQ,OAAO,OAAO;AAAA,EACpC;AAAA,EACA,KAAK,MAAgB,SAAoE;AACvF,WAAO,KAAK,KAAQ,QAAQ,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EAClD;AAAA,EACA,IAAI,MAAgB,SAAoE;AACtF,WAAO,KAAK,KAAQ,OAAO,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EACjD;AAAA,EACA,MAAM,MAAgB,SAAoE;AACxF,WAAO,KAAK,KAAQ,SAAS,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EACnD;AAAA,EACA,IAAI,SAAsD;AACxD,WAAO,KAAK,KAAQ,UAAU,OAAO;AAAA,EACvC;AAAA,EAEA,KAAY,QAAgB,SAAsD;AAChF,UAAM,KAAK,SAAS,QAAQ,KAAK,WAAW,QAAQ,KAAK,IAAI;AAI7D,UAAM,WAAW,IAAI,KAAK,IAAI,GAAG,EAAE;AACnC,UAAM,UAA0B;AAAA,MAC9B,SAAS,SAAS;AAAA,MAClB,QAAQ,SAAS;AAAA,IACnB;AACA,QAAI,SAAS,SAAS,QAAW;AAI/B,MAAC,QAAgD,OAAO,QAAQ;AAAA,IAClE;AACA,WAAO,KAAK,WAAW,QAAW,QAAQ,UAAU,OAAO;AAAA,EAC7D;AAAA,EAEQ,WAAW,GAAgD;AACjE,UAAM,QAAkB,CAAC;AACzB,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,CAAC,GAAG;AACtC,UAAI,MAAM,UAAa,MAAM,KAAM;AACnC,YAAM,KAAK,GAAG,mBAAmB,CAAC,CAAC,IAAI,mBAAmB,OAAO,CAAC,CAAC,CAAC,EAAE;AAAA,IACxE;AACA,WAAO,MAAM,SAAS,IAAI,MAAM,KAAK,GAAG,CAAC,KAAK;AAAA,EAChD;AACF;AAsBO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EAEjB,YAAY,YAAwB;AAClC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,KACE,MACA,OACA,SAC6C;AAC7C,WAAO,KAAK,OAA0B,IAAI,EAAE,KAAK,OAAO,OAAO;AAAA,EAGjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAoB,MAA2C;AAC7D,WAAO,IAAI,yBAA4B,KAAK,YAAY,IAAI;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QACE,QACA,MACA,SAC6B;AAC7B,WAAO,KAAK,OAAU,IAAI,EAAE,KAAQ,QAAQ,OAAO;AAAA,EACrD;AACF;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -52,7 +52,7 @@ declare const LOCALHOST: BackendEnvironment;
|
|
|
52
52
|
* BackendInvocationBuilder is the chainable handle returned by
|
|
53
53
|
* `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,
|
|
54
54
|
* `put`, `patch`, `del`, `call`) issues a request to
|
|
55
|
-
* `<host
|
|
55
|
+
* `<host>/<path>` with the given HTTP verb. The builder is
|
|
56
56
|
* intentionally tiny — backend endpoints are user-defined, so we
|
|
57
57
|
* don't bake any DSL on top.
|
|
58
58
|
*/
|
|
@@ -79,7 +79,7 @@ type EndpointOutput<K extends string> = K extends keyof BackendEndpoints ? Backe
|
|
|
79
79
|
/**
|
|
80
80
|
* BackendClient is the entry point exposed as `pb.backend` on the
|
|
81
81
|
* unified client. It issues typed RPC calls to per-tenant
|
|
82
|
-
* backend-runtime pods routed through Kong as `<ref>.<host
|
|
82
|
+
* backend-runtime pods routed through Kong as `<ref>.<host>/<name>`.
|
|
83
83
|
* Each defineEndpoint a user ships in their `endpoints/` tree becomes
|
|
84
84
|
* one operation here.
|
|
85
85
|
*/
|
|
@@ -100,10 +100,9 @@ declare class BackendClient {
|
|
|
100
100
|
call<K extends string>(name: K & (K extends keyof BackendEndpoints ? K : string), input: EndpointInput<K>, options?: RpcCallOptions): Promise<PalbaseResponse<EndpointOutput<K>>>;
|
|
101
101
|
/**
|
|
102
102
|
* Lower-level builder for callers that need GET/PUT/DELETE etc. The
|
|
103
|
-
* builder talks to the same
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* affordances the simple `call()` doesn't expose.
|
|
103
|
+
* builder talks to the same file-based route as `call()` — the
|
|
104
|
+
* builder remains for headers/query/AbortSignal affordances the simple
|
|
105
|
+
* `call()` doesn't expose.
|
|
107
106
|
*/
|
|
108
107
|
invoke<T = unknown>(path: string): BackendInvocationBuilder<T>;
|
|
109
108
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ declare const LOCALHOST: BackendEnvironment;
|
|
|
52
52
|
* BackendInvocationBuilder is the chainable handle returned by
|
|
53
53
|
* `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,
|
|
54
54
|
* `put`, `patch`, `del`, `call`) issues a request to
|
|
55
|
-
* `<host
|
|
55
|
+
* `<host>/<path>` with the given HTTP verb. The builder is
|
|
56
56
|
* intentionally tiny — backend endpoints are user-defined, so we
|
|
57
57
|
* don't bake any DSL on top.
|
|
58
58
|
*/
|
|
@@ -79,7 +79,7 @@ type EndpointOutput<K extends string> = K extends keyof BackendEndpoints ? Backe
|
|
|
79
79
|
/**
|
|
80
80
|
* BackendClient is the entry point exposed as `pb.backend` on the
|
|
81
81
|
* unified client. It issues typed RPC calls to per-tenant
|
|
82
|
-
* backend-runtime pods routed through Kong as `<ref>.<host
|
|
82
|
+
* backend-runtime pods routed through Kong as `<ref>.<host>/<name>`.
|
|
83
83
|
* Each defineEndpoint a user ships in their `endpoints/` tree becomes
|
|
84
84
|
* one operation here.
|
|
85
85
|
*/
|
|
@@ -100,10 +100,9 @@ declare class BackendClient {
|
|
|
100
100
|
call<K extends string>(name: K & (K extends keyof BackendEndpoints ? K : string), input: EndpointInput<K>, options?: RpcCallOptions): Promise<PalbaseResponse<EndpointOutput<K>>>;
|
|
101
101
|
/**
|
|
102
102
|
* Lower-level builder for callers that need GET/PUT/DELETE etc. The
|
|
103
|
-
* builder talks to the same
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* affordances the simple `call()` doesn't expose.
|
|
103
|
+
* builder talks to the same file-based route as `call()` — the
|
|
104
|
+
* builder remains for headers/query/AbortSignal affordances the simple
|
|
105
|
+
* `call()` doesn't expose.
|
|
107
106
|
*/
|
|
108
107
|
invoke<T = unknown>(path: string): BackendInvocationBuilder<T>;
|
|
109
108
|
/**
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ var BackendInvocationBuilder = class {
|
|
|
24
24
|
}
|
|
25
25
|
call(method, options) {
|
|
26
26
|
const qs = options?.query ? this.buildQuery(options.query) : "";
|
|
27
|
-
const fullPath =
|
|
27
|
+
const fullPath = `/${this.path}${qs}`;
|
|
28
28
|
const reqOpts = {
|
|
29
29
|
headers: options?.headers,
|
|
30
30
|
signal: options?.signal
|
|
@@ -64,10 +64,9 @@ var BackendClient = class {
|
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* Lower-level builder for callers that need GET/PUT/DELETE etc. The
|
|
67
|
-
* builder talks to the same
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* affordances the simple `call()` doesn't expose.
|
|
67
|
+
* builder talks to the same file-based route as `call()` — the
|
|
68
|
+
* builder remains for headers/query/AbortSignal affordances the simple
|
|
69
|
+
* `call()` doesn't expose.
|
|
71
70
|
*/
|
|
72
71
|
invoke(path) {
|
|
73
72
|
return new BackendInvocationBuilder(this.httpClient, path);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/backend-client.ts"],"sourcesContent":["import type { HttpClient, PalbaseResponse, RequestOptions } from '@palbase/core';\n\n/**\n * Module augmentation hook — users export their endpoint map from\n * `.palbase/types.d.ts` and add the type via:\n *\n * ```ts\n * declare module '@palbase/backend-client' {\n * interface BackendEndpoints {\n * checkout: { input: { items: string[] }; output: { orderId: string } };\n * }\n * }\n * ```\n *\n * `pb.backend.call('checkout', { items: ['a'] })` then resolves the\n * input + output types automatically. Without augmentation the call\n * falls back to `unknown` and the developer has to cast manually.\n */\n// biome-ignore lint/suspicious/noEmptyInterface: augmentation target on purpose\nexport interface BackendEndpoints {}\n\n/**\n * Options accepted by every backend invocation. `body` is JSON-encoded\n * for POST/PUT/PATCH; `query` is appended as a query string. `signal`\n * lets callers wire AbortController for cancellation.\n */\nexport interface InvokeOptions {\n body?: unknown;\n query?: Record<string, string | number | boolean | null | undefined>;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Per-call options for the typed RPC `call(name, input)` API.\n * `headers` and `signal` cover the common needs; the body is the\n * input argument itself, so there is no `body` here.\n */\nexport interface RpcCallOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Backend connection environment. Drives the base path the client\n * issues requests against. Default is `'remote'` — Kong gateway via\n * the configured Palbase host.\n */\nexport type BackendEnvironment =\n | 'remote'\n | { custom: string };\n\n/** Convenience alias for the most common dev override. */\nexport const LOCALHOST: BackendEnvironment = { custom: 'http://localhost:4003' };\n\n/**\n * BackendInvocationBuilder is the chainable handle returned by\n * `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,\n * `put`, `patch`, `del`, `call`) issues a request to\n * `<host
|
|
1
|
+
{"version":3,"sources":["../src/backend-client.ts"],"sourcesContent":["import type { HttpClient, PalbaseResponse, RequestOptions } from '@palbase/core';\n\n/**\n * Module augmentation hook — users export their endpoint map from\n * `.palbase/types.d.ts` and add the type via:\n *\n * ```ts\n * declare module '@palbase/backend-client' {\n * interface BackendEndpoints {\n * checkout: { input: { items: string[] }; output: { orderId: string } };\n * }\n * }\n * ```\n *\n * `pb.backend.call('checkout', { items: ['a'] })` then resolves the\n * input + output types automatically. Without augmentation the call\n * falls back to `unknown` and the developer has to cast manually.\n */\n// biome-ignore lint/suspicious/noEmptyInterface: augmentation target on purpose\nexport interface BackendEndpoints {}\n\n/**\n * Options accepted by every backend invocation. `body` is JSON-encoded\n * for POST/PUT/PATCH; `query` is appended as a query string. `signal`\n * lets callers wire AbortController for cancellation.\n */\nexport interface InvokeOptions {\n body?: unknown;\n query?: Record<string, string | number | boolean | null | undefined>;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Per-call options for the typed RPC `call(name, input)` API.\n * `headers` and `signal` cover the common needs; the body is the\n * input argument itself, so there is no `body` here.\n */\nexport interface RpcCallOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * Backend connection environment. Drives the base path the client\n * issues requests against. Default is `'remote'` — Kong gateway via\n * the configured Palbase host.\n */\nexport type BackendEnvironment =\n | 'remote'\n | { custom: string };\n\n/** Convenience alias for the most common dev override. */\nexport const LOCALHOST: BackendEnvironment = { custom: 'http://localhost:4003' };\n\n/**\n * BackendInvocationBuilder is the chainable handle returned by\n * `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,\n * `put`, `patch`, `del`, `call`) issues a request to\n * `<host>/<path>` with the given HTTP verb. The builder is\n * intentionally tiny — backend endpoints are user-defined, so we\n * don't bake any DSL on top.\n */\nexport class BackendInvocationBuilder<T = unknown> {\n private readonly httpClient: HttpClient;\n private readonly path: string;\n\n constructor(httpClient: HttpClient, path: string) {\n this.httpClient = httpClient;\n // Strip exactly one leading slash so callers can type either\n // `pb.backend.invoke('hello')` or `pb.backend.invoke('/hello')`.\n this.path = path.replace(/^\\/+/, '');\n }\n\n get(options?: InvokeOptions): Promise<PalbaseResponse<T>> {\n return this.call<T>('GET', options);\n }\n post(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>> {\n return this.call<T>('POST', { ...options, body });\n }\n put(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>> {\n return this.call<T>('PUT', { ...options, body });\n }\n patch(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>> {\n return this.call<T>('PATCH', { ...options, body });\n }\n del(options?: InvokeOptions): Promise<PalbaseResponse<T>> {\n return this.call<T>('DELETE', options);\n }\n\n call<R = T>(method: string, options?: InvokeOptions): Promise<PalbaseResponse<R>> {\n const qs = options?.query ? this.buildQuery(options.query) : '';\n // Adım B14 — endpoints are file-based (`pb.backend.call(\"users/list\")`\n // -> `POST /users/list`), so the request path is exactly the\n // endpoint name passed to invoke().\n const fullPath = `/${this.path}${qs}`;\n const reqOpts: RequestOptions = {\n headers: options?.headers,\n signal: options?.signal,\n };\n if (options?.body !== undefined) {\n // HttpClient JSON-encodes body when content-type is unset.\n // We pass through raw — caller can override Content-Type via\n // headers if they need form-urlencoded etc.\n (reqOpts as RequestOptions & { body?: unknown }).body = options.body;\n }\n return this.httpClient.request<R>(method, fullPath, reqOpts);\n }\n\n private buildQuery(q: NonNullable<InvokeOptions['query']>): string {\n const parts: string[] = [];\n for (const [k, v] of Object.entries(q)) {\n if (v === undefined || v === null) continue;\n parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);\n }\n return parts.length ? `?${parts.join('&')}` : '';\n }\n}\n\n/** Resolve typed input/output for an operation when the user has\n * augmented `BackendEndpoints`; otherwise fall back to `unknown`. */\ntype EndpointInput<K extends string> = K extends keyof BackendEndpoints\n ? BackendEndpoints[K] extends { input: infer I }\n ? I\n : unknown\n : unknown;\ntype EndpointOutput<K extends string> = K extends keyof BackendEndpoints\n ? BackendEndpoints[K] extends { output: infer O }\n ? O\n : unknown\n : unknown;\n\n/**\n * BackendClient is the entry point exposed as `pb.backend` on the\n * unified client. It issues typed RPC calls to per-tenant\n * backend-runtime pods routed through Kong as `<ref>.<host>/<name>`.\n * Each defineEndpoint a user ships in their `endpoints/` tree becomes\n * one operation here.\n */\nexport class BackendClient {\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Typed RPC dispatch — the primary API. When the user augments\n * `BackendEndpoints` (typically via `palbase backend types`), the\n * `name` argument autocompletes and `input` / return type are\n * inferred. Without augmentation both default to `unknown`.\n *\n * ```ts\n * const r = await pb.backend.call('checkout', { items: ['a'] });\n * // r.data is typed when BackendEndpoints['checkout'] is declared.\n * ```\n */\n call<K extends string>(\n name: K & (K extends keyof BackendEndpoints ? K : string),\n input: EndpointInput<K>,\n options?: RpcCallOptions,\n ): Promise<PalbaseResponse<EndpointOutput<K>>> {\n return this.invoke<EndpointOutput<K>>(name).post(input, options) as Promise<\n PalbaseResponse<EndpointOutput<K>>\n >;\n }\n\n /**\n * Lower-level builder for callers that need GET/PUT/DELETE etc. The\n * builder talks to the same file-based route as `call()` — the\n * builder remains for headers/query/AbortSignal affordances the simple\n * `call()` doesn't expose.\n */\n invoke<T = unknown>(path: string): BackendInvocationBuilder<T> {\n return new BackendInvocationBuilder<T>(this.httpClient, path);\n }\n\n /**\n * One-shot fetch helper for explicit method+path. Kept so existing\n * callers (legacy code, tests) compile; new code should use\n * `call(name, input)` for the typed RPC path.\n */\n request<T = unknown>(\n method: string,\n path: string,\n options?: InvokeOptions,\n ): Promise<PalbaseResponse<T>> {\n return this.invoke<T>(path).call<T>(method, options);\n }\n}\n"],"mappings":";AAqDO,IAAM,YAAgC,EAAE,QAAQ,wBAAwB;AAUxE,IAAM,2BAAN,MAA4C;AAAA,EAChC;AAAA,EACA;AAAA,EAEjB,YAAY,YAAwB,MAAc;AAChD,SAAK,aAAa;AAGlB,SAAK,OAAO,KAAK,QAAQ,QAAQ,EAAE;AAAA,EACrC;AAAA,EAEA,IAAI,SAAsD;AACxD,WAAO,KAAK,KAAQ,OAAO,OAAO;AAAA,EACpC;AAAA,EACA,KAAK,MAAgB,SAAoE;AACvF,WAAO,KAAK,KAAQ,QAAQ,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EAClD;AAAA,EACA,IAAI,MAAgB,SAAoE;AACtF,WAAO,KAAK,KAAQ,OAAO,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EACjD;AAAA,EACA,MAAM,MAAgB,SAAoE;AACxF,WAAO,KAAK,KAAQ,SAAS,EAAE,GAAG,SAAS,KAAK,CAAC;AAAA,EACnD;AAAA,EACA,IAAI,SAAsD;AACxD,WAAO,KAAK,KAAQ,UAAU,OAAO;AAAA,EACvC;AAAA,EAEA,KAAY,QAAgB,SAAsD;AAChF,UAAM,KAAK,SAAS,QAAQ,KAAK,WAAW,QAAQ,KAAK,IAAI;AAI7D,UAAM,WAAW,IAAI,KAAK,IAAI,GAAG,EAAE;AACnC,UAAM,UAA0B;AAAA,MAC9B,SAAS,SAAS;AAAA,MAClB,QAAQ,SAAS;AAAA,IACnB;AACA,QAAI,SAAS,SAAS,QAAW;AAI/B,MAAC,QAAgD,OAAO,QAAQ;AAAA,IAClE;AACA,WAAO,KAAK,WAAW,QAAW,QAAQ,UAAU,OAAO;AAAA,EAC7D;AAAA,EAEQ,WAAW,GAAgD;AACjE,UAAM,QAAkB,CAAC;AACzB,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,CAAC,GAAG;AACtC,UAAI,MAAM,UAAa,MAAM,KAAM;AACnC,YAAM,KAAK,GAAG,mBAAmB,CAAC,CAAC,IAAI,mBAAmB,OAAO,CAAC,CAAC,CAAC,EAAE;AAAA,IACxE;AACA,WAAO,MAAM,SAAS,IAAI,MAAM,KAAK,GAAG,CAAC,KAAK;AAAA,EAChD;AACF;AAsBO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EAEjB,YAAY,YAAwB;AAClC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,KACE,MACA,OACA,SAC6C;AAC7C,WAAO,KAAK,OAA0B,IAAI,EAAE,KAAK,OAAO,OAAO;AAAA,EAGjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAoB,MAA2C;AAC7D,WAAO,IAAI,yBAA4B,KAAK,YAAY,IAAI;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QACE,QACA,MACA,SAC6B;AAC7B,WAAO,KAAK,OAAU,IAAI,EAAE,KAAQ,QAAQ,OAAO;AAAA,EACrD;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@palbase/backend-client",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Palbase backend client — call your project's defineEndpoint handlers from the browser/server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@palbase/core": "^0.
|
|
31
|
+
"@palbase/core": "^1.0.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@biomejs/biome": "^2.0.0",
|