@webpieces/http-client 0.2.8 → 0.2.9
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/package.json +2 -2
- package/src/ClientFactory.d.ts +5 -7
- package/src/ClientFactory.js +16 -8
- package/src/ClientFactory.js.map +1 -1
- package/src/index.d.ts +3 -4
- package/src/index.js +5 -5
- package/src/index.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/http-client",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "HTTP client for WebPieces framework",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -21,6 +21,6 @@
|
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@webpieces/http-api": "0.2.
|
|
24
|
+
"@webpieces/http-api": "0.2.9"
|
|
25
25
|
}
|
|
26
26
|
}
|
package/src/ClientFactory.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Configuration options for HTTP client.
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
4
|
+
export declare class ClientConfig {
|
|
5
5
|
/** Base URL for all requests (e.g., 'http://localhost:3000') */
|
|
6
6
|
baseUrl: string;
|
|
7
|
-
|
|
8
|
-
headers?: Record<string, string>;
|
|
9
|
-
/** Optional fetch implementation (defaults to global fetch) */
|
|
10
|
-
fetch?: typeof fetch;
|
|
7
|
+
constructor(baseUrl: string);
|
|
11
8
|
}
|
|
12
9
|
/**
|
|
13
10
|
* Creates a type-safe HTTP client from an API interface prototype.
|
|
@@ -18,12 +15,13 @@ export interface ClientConfig {
|
|
|
18
15
|
*
|
|
19
16
|
* Usage:
|
|
20
17
|
* ```typescript
|
|
21
|
-
* const
|
|
18
|
+
* const config = new ClientConfig('http://localhost:3000');
|
|
19
|
+
* const client = createClient(SaveApiPrototype, config);
|
|
22
20
|
* const response = await client.save({ query: 'test' }); // Type-safe!
|
|
23
21
|
* ```
|
|
24
22
|
*
|
|
25
23
|
* @param apiPrototype - The API prototype class with decorators (e.g., SaveApiPrototype)
|
|
26
|
-
* @param config - Client configuration
|
|
24
|
+
* @param config - Client configuration with baseUrl
|
|
27
25
|
* @returns A proxy object that implements the API interface
|
|
28
26
|
*/
|
|
29
27
|
export declare function createClient<T extends object>(apiPrototype: Function & {
|
package/src/ClientFactory.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClientConfig = void 0;
|
|
3
4
|
exports.createClient = createClient;
|
|
4
5
|
const http_api_1 = require("@webpieces/http-api");
|
|
6
|
+
/**
|
|
7
|
+
* Configuration options for HTTP client.
|
|
8
|
+
*/
|
|
9
|
+
class ClientConfig {
|
|
10
|
+
constructor(baseUrl) {
|
|
11
|
+
this.baseUrl = baseUrl;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.ClientConfig = ClientConfig;
|
|
5
15
|
/**
|
|
6
16
|
* Creates a type-safe HTTP client from an API interface prototype.
|
|
7
17
|
*
|
|
@@ -11,12 +21,13 @@ const http_api_1 = require("@webpieces/http-api");
|
|
|
11
21
|
*
|
|
12
22
|
* Usage:
|
|
13
23
|
* ```typescript
|
|
14
|
-
* const
|
|
24
|
+
* const config = new ClientConfig('http://localhost:3000');
|
|
25
|
+
* const client = createClient(SaveApiPrototype, config);
|
|
15
26
|
* const response = await client.save({ query: 'test' }); // Type-safe!
|
|
16
27
|
* ```
|
|
17
28
|
*
|
|
18
29
|
* @param apiPrototype - The API prototype class with decorators (e.g., SaveApiPrototype)
|
|
19
|
-
* @param config - Client configuration
|
|
30
|
+
* @param config - Client configuration with baseUrl
|
|
20
31
|
* @returns A proxy object that implements the API interface
|
|
21
32
|
*/
|
|
22
33
|
function createClient(apiPrototype, config) {
|
|
@@ -32,8 +43,6 @@ function createClient(apiPrototype, config) {
|
|
|
32
43
|
for (const route of routes) {
|
|
33
44
|
routeMap.set(route.methodName, route);
|
|
34
45
|
}
|
|
35
|
-
// Use fetch implementation from config or global
|
|
36
|
-
const fetchImpl = config.fetch || fetch;
|
|
37
46
|
// Create a proxy that intercepts method calls and makes HTTP requests
|
|
38
47
|
return new Proxy({}, {
|
|
39
48
|
get(target, prop) {
|
|
@@ -48,7 +57,7 @@ function createClient(apiPrototype, config) {
|
|
|
48
57
|
}
|
|
49
58
|
// Return a function that makes the HTTP request
|
|
50
59
|
return async (...args) => {
|
|
51
|
-
return makeRequest(
|
|
60
|
+
return makeRequest(config, route, args);
|
|
52
61
|
};
|
|
53
62
|
},
|
|
54
63
|
});
|
|
@@ -56,14 +65,13 @@ function createClient(apiPrototype, config) {
|
|
|
56
65
|
/**
|
|
57
66
|
* Make an HTTP request based on route metadata and arguments.
|
|
58
67
|
*/
|
|
59
|
-
async function makeRequest(
|
|
68
|
+
async function makeRequest(config, route, args) {
|
|
60
69
|
const { httpMethod, path } = route;
|
|
61
70
|
// Build the full URL
|
|
62
71
|
const url = `${config.baseUrl}${path}`;
|
|
63
72
|
// Build headers
|
|
64
73
|
const headers = {
|
|
65
74
|
'Content-Type': 'application/json',
|
|
66
|
-
...config.headers,
|
|
67
75
|
};
|
|
68
76
|
// Build request options
|
|
69
77
|
const options = {
|
|
@@ -75,7 +83,7 @@ async function makeRequest(fetchImpl, config, route, args) {
|
|
|
75
83
|
options.body = JSON.stringify(args[0]);
|
|
76
84
|
}
|
|
77
85
|
// Make the HTTP request
|
|
78
|
-
const response = await
|
|
86
|
+
const response = await fetch(url, options);
|
|
79
87
|
// Check for HTTP errors
|
|
80
88
|
if (!response.ok) {
|
|
81
89
|
const errorText = await response.text();
|
package/src/ClientFactory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientFactory.js","sourceRoot":"","sources":["../../../../../packages/http/http-client/src/ClientFactory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClientFactory.js","sourceRoot":"","sources":["../../../../../packages/http/http-client/src/ClientFactory.ts"],"names":[],"mappings":";;;AAgCA,oCAyCC;AAzED,kDAA+E;AAE/E;;GAEG;AACH,MAAa,YAAY;IAIvB,YAAY,OAAe;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAPD,oCAOC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,YAAY,CAC1B,YAAyC,EACzC,MAAoB;IAEpB,+DAA+D;IAC/D,IAAI,CAAC,IAAA,yBAAc,EAAC,YAAY,CAAC,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,IAAI,SAAS,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,SAAS,SAAS,yCAAyC,CAC5D,CAAC;IACJ,CAAC;IAED,wCAAwC;IACxC,MAAM,MAAM,GAAG,IAAA,oBAAS,EAAC,YAAY,CAAC,CAAC;IAEvC,gEAAgE;IAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;IAClD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,sEAAsE;IACtE,OAAO,IAAI,KAAK,CAAC,EAAO,EAAE;QACxB,GAAG,CAAC,MAAM,EAAE,IAAqB;YAC/B,+CAA+C;YAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,yCAAyC;YACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,gDAAgD;YAChD,OAAO,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;gBAC9B,OAAO,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YAC1C,CAAC,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,WAAW,CACxB,MAAoB,EACpB,KAAoB,EACpB,IAAW;IAEX,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAEnC,qBAAqB;IACrB,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;IAEvC,gBAAgB;IAChB,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,wBAAwB;IACxB,MAAM,OAAO,GAAgB;QAC3B,MAAM,EAAE,UAAU;QAClB,OAAO;KACR,CAAC;IAEF,wDAAwD;IACxD,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,wBAAwB;IACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE3C,wBAAwB;IACxB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,CAChE,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC","sourcesContent":["import { getRoutes, isApiInterface, RouteMetadata } from '@webpieces/http-api';\n\n/**\n * Configuration options for HTTP client.\n */\nexport class ClientConfig {\n /** Base URL for all requests (e.g., 'http://localhost:3000') */\n baseUrl: string;\n\n constructor(baseUrl: string) {\n this.baseUrl = baseUrl;\n }\n}\n\n/**\n * Creates a type-safe HTTP client from an API interface prototype.\n *\n * This is the client-side equivalent of RESTApiRoutes.\n * - Server: RESTApiRoutes reads decorators → routes HTTP requests to controllers\n * - Client: createClient reads decorators → generates HTTP requests from method calls\n *\n * Usage:\n * ```typescript\n * const config = new ClientConfig('http://localhost:3000');\n * const client = createClient(SaveApiPrototype, config);\n * const response = await client.save({ query: 'test' }); // Type-safe!\n * ```\n *\n * @param apiPrototype - The API prototype class with decorators (e.g., SaveApiPrototype)\n * @param config - Client configuration with baseUrl\n * @returns A proxy object that implements the API interface\n */\nexport function createClient<T extends object>(\n apiPrototype: Function & { prototype: T },\n config: ClientConfig\n): T {\n // Validate that the API prototype is marked with @ApiInterface\n if (!isApiInterface(apiPrototype)) {\n const className = apiPrototype.name || 'Unknown';\n throw new Error(\n `Class ${className} must be decorated with @ApiInterface()`\n );\n }\n\n // Get all routes from the API prototype\n const routes = getRoutes(apiPrototype);\n\n // Create a map of method name -> route metadata for fast lookup\n const routeMap = new Map<string, RouteMetadata>();\n for (const route of routes) {\n routeMap.set(route.methodName, route);\n }\n\n // Create a proxy that intercepts method calls and makes HTTP requests\n return new Proxy({} as T, {\n get(target, prop: string | symbol) {\n // Only handle string properties (method names)\n if (typeof prop !== 'string') {\n return undefined;\n }\n\n // Get the route metadata for this method\n const route = routeMap.get(prop);\n if (!route) {\n throw new Error(`No route found for method ${prop}`);\n }\n\n // Return a function that makes the HTTP request\n return async (...args: any[]) => {\n return makeRequest(config, route, args);\n };\n },\n });\n}\n\n/**\n * Make an HTTP request based on route metadata and arguments.\n */\nasync function makeRequest(\n config: ClientConfig,\n route: RouteMetadata,\n args: any[]\n): Promise<any> {\n const { httpMethod, path } = route;\n\n // Build the full URL\n const url = `${config.baseUrl}${path}`;\n\n // Build headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n // Build request options\n const options: RequestInit = {\n method: httpMethod,\n headers,\n };\n\n // For POST/PUT/PATCH, include the body (first argument)\n if (['POST', 'PUT', 'PATCH'].includes(httpMethod) && args.length > 0) {\n options.body = JSON.stringify(args[0]);\n }\n\n // Make the HTTP request\n const response = await fetch(url, options);\n\n // Check for HTTP errors\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `HTTP ${response.status}: ${response.statusText}. ${errorText}`\n );\n }\n\n // Parse and return the JSON response\n return response.json();\n}\n"]}
|
package/src/index.d.ts
CHANGED
|
@@ -20,12 +20,11 @@
|
|
|
20
20
|
*
|
|
21
21
|
* Usage:
|
|
22
22
|
* ```typescript
|
|
23
|
-
* import { createClient } from '@webpieces/http-client';
|
|
23
|
+
* import { createClient, ClientConfig } from '@webpieces/http-client';
|
|
24
24
|
* import { SaveApiPrototype } from './api/SaveApi';
|
|
25
25
|
*
|
|
26
|
-
* const
|
|
27
|
-
*
|
|
28
|
-
* });
|
|
26
|
+
* const config = new ClientConfig('http://localhost:3000');
|
|
27
|
+
* const client = createClient(SaveApiPrototype, config);
|
|
29
28
|
*
|
|
30
29
|
* const response = await client.save({ query: 'test' });
|
|
31
30
|
* ```
|
package/src/index.js
CHANGED
|
@@ -21,20 +21,20 @@
|
|
|
21
21
|
*
|
|
22
22
|
* Usage:
|
|
23
23
|
* ```typescript
|
|
24
|
-
* import { createClient } from '@webpieces/http-client';
|
|
24
|
+
* import { createClient, ClientConfig } from '@webpieces/http-client';
|
|
25
25
|
* import { SaveApiPrototype } from './api/SaveApi';
|
|
26
26
|
*
|
|
27
|
-
* const
|
|
28
|
-
*
|
|
29
|
-
* });
|
|
27
|
+
* const config = new ClientConfig('http://localhost:3000');
|
|
28
|
+
* const client = createClient(SaveApiPrototype, config);
|
|
30
29
|
*
|
|
31
30
|
* const response = await client.save({ query: 'test' });
|
|
32
31
|
* ```
|
|
33
32
|
*/
|
|
34
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.Path = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.ApiInterface = exports.createClient = void 0;
|
|
34
|
+
exports.Path = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.ApiInterface = exports.ClientConfig = exports.createClient = void 0;
|
|
36
35
|
var ClientFactory_1 = require("./ClientFactory");
|
|
37
36
|
Object.defineProperty(exports, "createClient", { enumerable: true, get: function () { return ClientFactory_1.createClient; } });
|
|
37
|
+
Object.defineProperty(exports, "ClientConfig", { enumerable: true, get: function () { return ClientFactory_1.ClientConfig; } });
|
|
38
38
|
// Re-export API decorators for convenience (same as http-routing does)
|
|
39
39
|
var http_api_1 = require("@webpieces/http-api");
|
|
40
40
|
Object.defineProperty(exports, "ApiInterface", { enumerable: true, get: function () { return http_api_1.ApiInterface; } });
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-client/src/index.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-client/src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;AAEH,iDAA6D;AAApD,6GAAA,YAAY,OAAA;AAAE,6GAAA,YAAY,OAAA;AAEnC,uEAAuE;AACvE,gDAS6B;AAR3B,wGAAA,YAAY,OAAA;AACZ,+FAAA,GAAG,OAAA;AACH,gGAAA,IAAI,OAAA;AACJ,+FAAA,GAAG,OAAA;AACH,kGAAA,MAAM,OAAA;AACN,iGAAA,KAAK,OAAA;AACL,gGAAA,IAAI,OAAA","sourcesContent":["/**\n * @webpieces/http-client\n *\n * Client-side HTTP client generation package.\n * Reads API decorators and generates type-safe HTTP clients.\n *\n * This is the client-side counterpart to @webpieces/http-routing:\n * - Server (@webpieces/http-routing): API decorators → route HTTP to controllers\n * - Client (@webpieces/http-client): API decorators → generate HTTP from method calls\n *\n * Both packages depend on @webpieces/http-api for shared decorator definitions.\n *\n * Architecture:\n * ```\n * http-api (defines the contract)\n * ↑\n * ├── http-routing (server: contract → handlers)\n * └── http-client (client: contract → HTTP requests) ← YOU ARE HERE\n * ```\n *\n * Usage:\n * ```typescript\n * import { createClient, ClientConfig } from '@webpieces/http-client';\n * import { SaveApiPrototype } from './api/SaveApi';\n *\n * const config = new ClientConfig('http://localhost:3000');\n * const client = createClient(SaveApiPrototype, config);\n *\n * const response = await client.save({ query: 'test' });\n * ```\n */\n\nexport { createClient, ClientConfig } from './ClientFactory';\n\n// Re-export API decorators for convenience (same as http-routing does)\nexport {\n ApiInterface,\n Get,\n Post,\n Put,\n Delete,\n Patch,\n Path,\n ValidateImplementation,\n} from '@webpieces/http-api';\n"]}
|