@palbase/backend-client 0.7.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present Palbase
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs ADDED
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BackendClient: () => BackendClient,
24
+ BackendInvocationBuilder: () => BackendInvocationBuilder
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/backend-client.ts
29
+ var BackendInvocationBuilder = class {
30
+ httpClient;
31
+ path;
32
+ constructor(httpClient, path) {
33
+ this.httpClient = httpClient;
34
+ this.path = path.replace(/^\/+/, "");
35
+ }
36
+ get(options) {
37
+ return this.call("GET", options);
38
+ }
39
+ post(body, options) {
40
+ return this.call("POST", { ...options, body });
41
+ }
42
+ put(body, options) {
43
+ return this.call("PUT", { ...options, body });
44
+ }
45
+ patch(body, options) {
46
+ return this.call("PATCH", { ...options, body });
47
+ }
48
+ del(options) {
49
+ return this.call("DELETE", options);
50
+ }
51
+ call(method, options) {
52
+ const qs = options?.query ? this.buildQuery(options.query) : "";
53
+ const fullPath = `/api/${this.path}${qs}`;
54
+ const reqOpts = {
55
+ headers: options?.headers,
56
+ signal: options?.signal
57
+ };
58
+ if (options?.body !== void 0) {
59
+ reqOpts.body = options.body;
60
+ }
61
+ return this.httpClient.request(method, fullPath, reqOpts);
62
+ }
63
+ buildQuery(q) {
64
+ const parts = [];
65
+ for (const [k, v] of Object.entries(q)) {
66
+ if (v === void 0 || v === null) continue;
67
+ parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
68
+ }
69
+ return parts.length ? `?${parts.join("&")}` : "";
70
+ }
71
+ };
72
+ var BackendClient = class {
73
+ httpClient;
74
+ constructor(httpClient) {
75
+ this.httpClient = httpClient;
76
+ }
77
+ /**
78
+ * Build a request for one of the user's defineEndpoint handlers.
79
+ * Path mirrors the file-based routing: `endpoints/users/get.ts`
80
+ * → `pb.backend.invoke('users')`. Subdirectories add segments:
81
+ * `endpoints/orders/[id]/get.ts` → `pb.backend.invoke('orders/123')`.
82
+ */
83
+ invoke(path) {
84
+ return new BackendInvocationBuilder(this.httpClient, path);
85
+ }
86
+ /**
87
+ * One-shot fetch helper. Same semantics as `invoke(path).call(method, options)`.
88
+ * Useful for dynamic method+path combinations where the chained
89
+ * builder reads worse, e.g. when the method is a runtime variable.
90
+ */
91
+ call(method, path, options) {
92
+ return this.invoke(path).call(method, options);
93
+ }
94
+ };
95
+ // Annotate the CommonJS export names for ESM import in node:
96
+ 0 && (module.exports = {
97
+ BackendClient,
98
+ BackendInvocationBuilder
99
+ });
100
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/backend-client.ts"],"sourcesContent":["export { BackendClient, BackendInvocationBuilder } from './backend-client.js';\nexport type { InvokeOptions } from './backend-client.js';\n","import type { HttpClient, PalbaseResponse, RequestOptions } from '@palbase/core';\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 * 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>/api/<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 const fullPath = `/api/${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/**\n * BackendClient is the entry point exposed as `pb.backend` on the\n * unified client. It issues calls to per-tenant backend-runtime pods\n * routed through Kong as `<ref>.<host>/api/<path>`. Each defineEndpoint\n * a user ships in their `endpoints/` tree becomes one path here.\n */\nexport class BackendClient {\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Build a request for one of the user's defineEndpoint handlers.\n * Path mirrors the file-based routing: `endpoints/users/get.ts`\n * → `pb.backend.invoke('users')`. Subdirectories add segments:\n * `endpoints/orders/[id]/get.ts` → `pb.backend.invoke('orders/123')`.\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. Same semantics as `invoke(path).call(method, options)`.\n * Useful for dynamic method+path combinations where the chained\n * builder reads worse, e.g. when the method is a runtime variable.\n */\n call<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;;;ACsBO,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;AAC7D,UAAM,WAAW,QAAQ,KAAK,IAAI,GAAG,EAAE;AACvC,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;AAQO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EAEjB,YAAY,YAAwB;AAClC,SAAK,aAAa;AAAA,EACpB;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,KACE,QACA,MACA,SAC6B;AAC7B,WAAO,KAAK,OAAU,IAAI,EAAE,KAAQ,QAAQ,OAAO;AAAA,EACrD;AACF;","names":[]}
@@ -0,0 +1,58 @@
1
+ import { HttpClient, PalbaseResponse } from '@palbase/core';
2
+
3
+ /**
4
+ * Options accepted by every backend invocation. `body` is JSON-encoded
5
+ * for POST/PUT/PATCH; `query` is appended as a query string. `signal`
6
+ * lets callers wire AbortController for cancellation.
7
+ */
8
+ interface InvokeOptions {
9
+ body?: unknown;
10
+ query?: Record<string, string | number | boolean | null | undefined>;
11
+ headers?: Record<string, string>;
12
+ signal?: AbortSignal;
13
+ }
14
+ /**
15
+ * BackendInvocationBuilder is the chainable handle returned by
16
+ * `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,
17
+ * `put`, `patch`, `del`, `call`) issues a request to
18
+ * `<host>/api/<path>` with the given HTTP verb. The builder is
19
+ * intentionally tiny — backend endpoints are user-defined, so we
20
+ * don't bake any DSL on top.
21
+ */
22
+ declare class BackendInvocationBuilder<T = unknown> {
23
+ private readonly httpClient;
24
+ private readonly path;
25
+ constructor(httpClient: HttpClient, path: string);
26
+ get(options?: InvokeOptions): Promise<PalbaseResponse<T>>;
27
+ post(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>>;
28
+ put(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>>;
29
+ patch(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>>;
30
+ del(options?: InvokeOptions): Promise<PalbaseResponse<T>>;
31
+ call<R = T>(method: string, options?: InvokeOptions): Promise<PalbaseResponse<R>>;
32
+ private buildQuery;
33
+ }
34
+ /**
35
+ * BackendClient is the entry point exposed as `pb.backend` on the
36
+ * unified client. It issues calls to per-tenant backend-runtime pods
37
+ * routed through Kong as `<ref>.<host>/api/<path>`. Each defineEndpoint
38
+ * a user ships in their `endpoints/` tree becomes one path here.
39
+ */
40
+ declare class BackendClient {
41
+ private readonly httpClient;
42
+ constructor(httpClient: HttpClient);
43
+ /**
44
+ * Build a request for one of the user's defineEndpoint handlers.
45
+ * Path mirrors the file-based routing: `endpoints/users/get.ts`
46
+ * → `pb.backend.invoke('users')`. Subdirectories add segments:
47
+ * `endpoints/orders/[id]/get.ts` → `pb.backend.invoke('orders/123')`.
48
+ */
49
+ invoke<T = unknown>(path: string): BackendInvocationBuilder<T>;
50
+ /**
51
+ * One-shot fetch helper. Same semantics as `invoke(path).call(method, options)`.
52
+ * Useful for dynamic method+path combinations where the chained
53
+ * builder reads worse, e.g. when the method is a runtime variable.
54
+ */
55
+ call<T = unknown>(method: string, path: string, options?: InvokeOptions): Promise<PalbaseResponse<T>>;
56
+ }
57
+
58
+ export { BackendClient, BackendInvocationBuilder, type InvokeOptions };
@@ -0,0 +1,58 @@
1
+ import { HttpClient, PalbaseResponse } from '@palbase/core';
2
+
3
+ /**
4
+ * Options accepted by every backend invocation. `body` is JSON-encoded
5
+ * for POST/PUT/PATCH; `query` is appended as a query string. `signal`
6
+ * lets callers wire AbortController for cancellation.
7
+ */
8
+ interface InvokeOptions {
9
+ body?: unknown;
10
+ query?: Record<string, string | number | boolean | null | undefined>;
11
+ headers?: Record<string, string>;
12
+ signal?: AbortSignal;
13
+ }
14
+ /**
15
+ * BackendInvocationBuilder is the chainable handle returned by
16
+ * `pb.backend.invoke('<path>')`. Each terminal method (`get`, `post`,
17
+ * `put`, `patch`, `del`, `call`) issues a request to
18
+ * `<host>/api/<path>` with the given HTTP verb. The builder is
19
+ * intentionally tiny — backend endpoints are user-defined, so we
20
+ * don't bake any DSL on top.
21
+ */
22
+ declare class BackendInvocationBuilder<T = unknown> {
23
+ private readonly httpClient;
24
+ private readonly path;
25
+ constructor(httpClient: HttpClient, path: string);
26
+ get(options?: InvokeOptions): Promise<PalbaseResponse<T>>;
27
+ post(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>>;
28
+ put(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>>;
29
+ patch(body?: unknown, options?: Omit<InvokeOptions, 'body'>): Promise<PalbaseResponse<T>>;
30
+ del(options?: InvokeOptions): Promise<PalbaseResponse<T>>;
31
+ call<R = T>(method: string, options?: InvokeOptions): Promise<PalbaseResponse<R>>;
32
+ private buildQuery;
33
+ }
34
+ /**
35
+ * BackendClient is the entry point exposed as `pb.backend` on the
36
+ * unified client. It issues calls to per-tenant backend-runtime pods
37
+ * routed through Kong as `<ref>.<host>/api/<path>`. Each defineEndpoint
38
+ * a user ships in their `endpoints/` tree becomes one path here.
39
+ */
40
+ declare class BackendClient {
41
+ private readonly httpClient;
42
+ constructor(httpClient: HttpClient);
43
+ /**
44
+ * Build a request for one of the user's defineEndpoint handlers.
45
+ * Path mirrors the file-based routing: `endpoints/users/get.ts`
46
+ * → `pb.backend.invoke('users')`. Subdirectories add segments:
47
+ * `endpoints/orders/[id]/get.ts` → `pb.backend.invoke('orders/123')`.
48
+ */
49
+ invoke<T = unknown>(path: string): BackendInvocationBuilder<T>;
50
+ /**
51
+ * One-shot fetch helper. Same semantics as `invoke(path).call(method, options)`.
52
+ * Useful for dynamic method+path combinations where the chained
53
+ * builder reads worse, e.g. when the method is a runtime variable.
54
+ */
55
+ call<T = unknown>(method: string, path: string, options?: InvokeOptions): Promise<PalbaseResponse<T>>;
56
+ }
57
+
58
+ export { BackendClient, BackendInvocationBuilder, type InvokeOptions };
package/dist/index.js ADDED
@@ -0,0 +1,72 @@
1
+ // src/backend-client.ts
2
+ var BackendInvocationBuilder = class {
3
+ httpClient;
4
+ path;
5
+ constructor(httpClient, path) {
6
+ this.httpClient = httpClient;
7
+ this.path = path.replace(/^\/+/, "");
8
+ }
9
+ get(options) {
10
+ return this.call("GET", options);
11
+ }
12
+ post(body, options) {
13
+ return this.call("POST", { ...options, body });
14
+ }
15
+ put(body, options) {
16
+ return this.call("PUT", { ...options, body });
17
+ }
18
+ patch(body, options) {
19
+ return this.call("PATCH", { ...options, body });
20
+ }
21
+ del(options) {
22
+ return this.call("DELETE", options);
23
+ }
24
+ call(method, options) {
25
+ const qs = options?.query ? this.buildQuery(options.query) : "";
26
+ const fullPath = `/api/${this.path}${qs}`;
27
+ const reqOpts = {
28
+ headers: options?.headers,
29
+ signal: options?.signal
30
+ };
31
+ if (options?.body !== void 0) {
32
+ reqOpts.body = options.body;
33
+ }
34
+ return this.httpClient.request(method, fullPath, reqOpts);
35
+ }
36
+ buildQuery(q) {
37
+ const parts = [];
38
+ for (const [k, v] of Object.entries(q)) {
39
+ if (v === void 0 || v === null) continue;
40
+ parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
41
+ }
42
+ return parts.length ? `?${parts.join("&")}` : "";
43
+ }
44
+ };
45
+ var BackendClient = class {
46
+ httpClient;
47
+ constructor(httpClient) {
48
+ this.httpClient = httpClient;
49
+ }
50
+ /**
51
+ * Build a request for one of the user's defineEndpoint handlers.
52
+ * Path mirrors the file-based routing: `endpoints/users/get.ts`
53
+ * → `pb.backend.invoke('users')`. Subdirectories add segments:
54
+ * `endpoints/orders/[id]/get.ts` → `pb.backend.invoke('orders/123')`.
55
+ */
56
+ invoke(path) {
57
+ return new BackendInvocationBuilder(this.httpClient, path);
58
+ }
59
+ /**
60
+ * One-shot fetch helper. Same semantics as `invoke(path).call(method, options)`.
61
+ * Useful for dynamic method+path combinations where the chained
62
+ * builder reads worse, e.g. when the method is a runtime variable.
63
+ */
64
+ call(method, path, options) {
65
+ return this.invoke(path).call(method, options);
66
+ }
67
+ };
68
+ export {
69
+ BackendClient,
70
+ BackendInvocationBuilder
71
+ };
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/backend-client.ts"],"sourcesContent":["import type { HttpClient, PalbaseResponse, RequestOptions } from '@palbase/core';\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 * 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>/api/<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 const fullPath = `/api/${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/**\n * BackendClient is the entry point exposed as `pb.backend` on the\n * unified client. It issues calls to per-tenant backend-runtime pods\n * routed through Kong as `<ref>.<host>/api/<path>`. Each defineEndpoint\n * a user ships in their `endpoints/` tree becomes one path here.\n */\nexport class BackendClient {\n private readonly httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Build a request for one of the user's defineEndpoint handlers.\n * Path mirrors the file-based routing: `endpoints/users/get.ts`\n * → `pb.backend.invoke('users')`. Subdirectories add segments:\n * `endpoints/orders/[id]/get.ts` → `pb.backend.invoke('orders/123')`.\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. Same semantics as `invoke(path).call(method, options)`.\n * Useful for dynamic method+path combinations where the chained\n * builder reads worse, e.g. when the method is a runtime variable.\n */\n call<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":";AAsBO,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;AAC7D,UAAM,WAAW,QAAQ,KAAK,IAAI,GAAG,EAAE;AACvC,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;AAQO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EAEjB,YAAY,YAAwB;AAClC,SAAK,aAAa;AAAA,EACpB;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,KACE,QACA,MACA,SAC6B;AAC7B,WAAO,KAAK,OAAU,IAAI,EAAE,KAAQ,QAAQ,OAAO;AAAA,EACrD;AACF;","names":[]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@palbase/backend-client",
3
+ "version": "0.7.0",
4
+ "description": "Palbase backend client — call your project's defineEndpoint handlers from the browser/server",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/palgroup/palbase-ts.git",
9
+ "directory": "modules/backend-client"
10
+ },
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "import": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "require": {
19
+ "types": "./dist/index.d.cts",
20
+ "default": "./dist/index.cjs"
21
+ }
22
+ }
23
+ },
24
+ "main": "./dist/index.cjs",
25
+ "module": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "dependencies": {
31
+ "@palbase/core": "^0.7.0"
32
+ },
33
+ "devDependencies": {
34
+ "@biomejs/biome": "^2.0.0",
35
+ "tsup": "^8.4.0",
36
+ "typescript": "^5.8.0",
37
+ "vitest": "^3.1.0"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "test": "vitest run",
45
+ "lint": "biome check src/ __tests__/"
46
+ }
47
+ }