@webpieces/http-client 0.1.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/README.md +19 -0
- package/package.json +26 -0
- package/src/ClientFactory.d.ts +31 -0
- package/src/ClientFactory.js +87 -0
- package/src/ClientFactory.js.map +1 -0
- package/src/index.d.ts +34 -0
- package/src/index.js +47 -0
- package/src/index.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @webpieces/http-client
|
|
2
|
+
|
|
3
|
+
> HTTP client for WebPieces framework
|
|
4
|
+
|
|
5
|
+
Part of the [WebPieces TypeScript](https://github.com/deanhiller/webpieces-ts) framework.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @webpieces/http-client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Documentation
|
|
14
|
+
|
|
15
|
+
See the main [WebPieces README](https://github.com/deanhiller/webpieces-ts#readme) for complete documentation and examples.
|
|
16
|
+
|
|
17
|
+
## License
|
|
18
|
+
|
|
19
|
+
Apache-2.0
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webpieces/http-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "HTTP client for WebPieces framework",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"author": "Dean Hiller",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/deanhiller/webpieces-ts.git",
|
|
13
|
+
"directory": "packages/http/http-client"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"webpieces",
|
|
17
|
+
"http",
|
|
18
|
+
"client"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@webpieces/http-api": "0.1.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for HTTP client.
|
|
3
|
+
*/
|
|
4
|
+
export interface ClientConfig {
|
|
5
|
+
/** Base URL for all requests (e.g., 'http://localhost:3000') */
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
/** Optional headers to include in all requests */
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
/** Optional fetch implementation (defaults to global fetch) */
|
|
10
|
+
fetch?: typeof fetch;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a type-safe HTTP client from an API interface prototype.
|
|
14
|
+
*
|
|
15
|
+
* This is the client-side equivalent of RESTApiRoutes.
|
|
16
|
+
* - Server: RESTApiRoutes reads decorators → routes HTTP requests to controllers
|
|
17
|
+
* - Client: createClient reads decorators → generates HTTP requests from method calls
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const client = createClient(SaveApiPrototype, { baseUrl: 'http://localhost:3000' });
|
|
22
|
+
* const response = await client.save({ query: 'test' }); // Type-safe!
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @param apiPrototype - The API prototype class with decorators (e.g., SaveApiPrototype)
|
|
26
|
+
* @param config - Client configuration (baseUrl, headers, etc.)
|
|
27
|
+
* @returns A proxy object that implements the API interface
|
|
28
|
+
*/
|
|
29
|
+
export declare function createClient<T extends object>(apiPrototype: Function & {
|
|
30
|
+
prototype: T;
|
|
31
|
+
}, config: ClientConfig): T;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createClient = createClient;
|
|
4
|
+
const http_api_1 = require("@webpieces/http-api");
|
|
5
|
+
/**
|
|
6
|
+
* Creates a type-safe HTTP client from an API interface prototype.
|
|
7
|
+
*
|
|
8
|
+
* This is the client-side equivalent of RESTApiRoutes.
|
|
9
|
+
* - Server: RESTApiRoutes reads decorators → routes HTTP requests to controllers
|
|
10
|
+
* - Client: createClient reads decorators → generates HTTP requests from method calls
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const client = createClient(SaveApiPrototype, { baseUrl: 'http://localhost:3000' });
|
|
15
|
+
* const response = await client.save({ query: 'test' }); // Type-safe!
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @param apiPrototype - The API prototype class with decorators (e.g., SaveApiPrototype)
|
|
19
|
+
* @param config - Client configuration (baseUrl, headers, etc.)
|
|
20
|
+
* @returns A proxy object that implements the API interface
|
|
21
|
+
*/
|
|
22
|
+
function createClient(apiPrototype, config) {
|
|
23
|
+
// Validate that the API prototype is marked with @ApiInterface
|
|
24
|
+
if (!(0, http_api_1.isApiInterface)(apiPrototype)) {
|
|
25
|
+
const className = apiPrototype.name || 'Unknown';
|
|
26
|
+
throw new Error(`Class ${className} must be decorated with @ApiInterface()`);
|
|
27
|
+
}
|
|
28
|
+
// Get all routes from the API prototype
|
|
29
|
+
const routes = (0, http_api_1.getRoutes)(apiPrototype);
|
|
30
|
+
// Create a map of method name -> route metadata for fast lookup
|
|
31
|
+
const routeMap = new Map();
|
|
32
|
+
for (const route of routes) {
|
|
33
|
+
routeMap.set(route.methodName, route);
|
|
34
|
+
}
|
|
35
|
+
// Use fetch implementation from config or global
|
|
36
|
+
const fetchImpl = config.fetch || fetch;
|
|
37
|
+
// Create a proxy that intercepts method calls and makes HTTP requests
|
|
38
|
+
return new Proxy({}, {
|
|
39
|
+
get(target, prop) {
|
|
40
|
+
// Only handle string properties (method names)
|
|
41
|
+
if (typeof prop !== 'string') {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
// Get the route metadata for this method
|
|
45
|
+
const route = routeMap.get(prop);
|
|
46
|
+
if (!route) {
|
|
47
|
+
throw new Error(`No route found for method ${prop}`);
|
|
48
|
+
}
|
|
49
|
+
// Return a function that makes the HTTP request
|
|
50
|
+
return async (...args) => {
|
|
51
|
+
return makeRequest(fetchImpl, config, route, args);
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Make an HTTP request based on route metadata and arguments.
|
|
58
|
+
*/
|
|
59
|
+
async function makeRequest(fetchImpl, config, route, args) {
|
|
60
|
+
const { httpMethod, path } = route;
|
|
61
|
+
// Build the full URL
|
|
62
|
+
const url = `${config.baseUrl}${path}`;
|
|
63
|
+
// Build headers
|
|
64
|
+
const headers = {
|
|
65
|
+
'Content-Type': 'application/json',
|
|
66
|
+
...config.headers,
|
|
67
|
+
};
|
|
68
|
+
// Build request options
|
|
69
|
+
const options = {
|
|
70
|
+
method: httpMethod,
|
|
71
|
+
headers,
|
|
72
|
+
};
|
|
73
|
+
// For POST/PUT/PATCH, include the body (first argument)
|
|
74
|
+
if (['POST', 'PUT', 'PATCH'].includes(httpMethod) && args.length > 0) {
|
|
75
|
+
options.body = JSON.stringify(args[0]);
|
|
76
|
+
}
|
|
77
|
+
// Make the HTTP request
|
|
78
|
+
const response = await fetchImpl(url, options);
|
|
79
|
+
// Check for HTTP errors
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
const errorText = await response.text();
|
|
82
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}. ${errorText}`);
|
|
83
|
+
}
|
|
84
|
+
// Parse and return the JSON response
|
|
85
|
+
return response.json();
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=ClientFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientFactory.js","sourceRoot":"","sources":["../../../../../packages/http/http-client/src/ClientFactory.ts"],"names":[],"mappings":";;AA+BA,oCA4CC;AA3ED,kDAA+E;AAc/E;;;;;;;;;;;;;;;;GAgBG;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,iDAAiD;IACjD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;IAExC,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,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACrD,CAAC,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,WAAW,CACxB,SAAuB,EACvB,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;QAClC,GAAG,MAAM,CAAC,OAAO;KAClB,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,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE/C,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"}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @webpieces/http-client
|
|
3
|
+
*
|
|
4
|
+
* Client-side HTTP client generation package.
|
|
5
|
+
* Reads API decorators and generates type-safe HTTP clients.
|
|
6
|
+
*
|
|
7
|
+
* This is the client-side counterpart to @webpieces/http-routing:
|
|
8
|
+
* - Server (@webpieces/http-routing): API decorators → route HTTP to controllers
|
|
9
|
+
* - Client (@webpieces/http-client): API decorators → generate HTTP from method calls
|
|
10
|
+
*
|
|
11
|
+
* Both packages depend on @webpieces/http-api for shared decorator definitions.
|
|
12
|
+
*
|
|
13
|
+
* Architecture:
|
|
14
|
+
* ```
|
|
15
|
+
* http-api (defines the contract)
|
|
16
|
+
* ↑
|
|
17
|
+
* ├── http-routing (server: contract → handlers)
|
|
18
|
+
* └── http-client (client: contract → HTTP requests) ← YOU ARE HERE
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { createClient } from '@webpieces/http-client';
|
|
24
|
+
* import { SaveApiPrototype } from './api/SaveApi';
|
|
25
|
+
*
|
|
26
|
+
* const client = createClient(SaveApiPrototype, {
|
|
27
|
+
* baseUrl: 'http://localhost:3000'
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* const response = await client.save({ query: 'test' });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export { createClient, ClientConfig } from './ClientFactory';
|
|
34
|
+
export { ApiInterface, Get, Post, Put, Delete, Patch, Path, ValidateImplementation, } from '@webpieces/http-api';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @webpieces/http-client
|
|
4
|
+
*
|
|
5
|
+
* Client-side HTTP client generation package.
|
|
6
|
+
* Reads API decorators and generates type-safe HTTP clients.
|
|
7
|
+
*
|
|
8
|
+
* This is the client-side counterpart to @webpieces/http-routing:
|
|
9
|
+
* - Server (@webpieces/http-routing): API decorators → route HTTP to controllers
|
|
10
|
+
* - Client (@webpieces/http-client): API decorators → generate HTTP from method calls
|
|
11
|
+
*
|
|
12
|
+
* Both packages depend on @webpieces/http-api for shared decorator definitions.
|
|
13
|
+
*
|
|
14
|
+
* Architecture:
|
|
15
|
+
* ```
|
|
16
|
+
* http-api (defines the contract)
|
|
17
|
+
* ↑
|
|
18
|
+
* ├── http-routing (server: contract → handlers)
|
|
19
|
+
* └── http-client (client: contract → HTTP requests) ← YOU ARE HERE
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { createClient } from '@webpieces/http-client';
|
|
25
|
+
* import { SaveApiPrototype } from './api/SaveApi';
|
|
26
|
+
*
|
|
27
|
+
* const client = createClient(SaveApiPrototype, {
|
|
28
|
+
* baseUrl: 'http://localhost:3000'
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* const response = await client.save({ query: 'test' });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
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;
|
|
36
|
+
var ClientFactory_1 = require("./ClientFactory");
|
|
37
|
+
Object.defineProperty(exports, "createClient", { enumerable: true, get: function () { return ClientFactory_1.createClient; } });
|
|
38
|
+
// Re-export API decorators for convenience (same as http-routing does)
|
|
39
|
+
var http_api_1 = require("@webpieces/http-api");
|
|
40
|
+
Object.defineProperty(exports, "ApiInterface", { enumerable: true, get: function () { return http_api_1.ApiInterface; } });
|
|
41
|
+
Object.defineProperty(exports, "Get", { enumerable: true, get: function () { return http_api_1.Get; } });
|
|
42
|
+
Object.defineProperty(exports, "Post", { enumerable: true, get: function () { return http_api_1.Post; } });
|
|
43
|
+
Object.defineProperty(exports, "Put", { enumerable: true, get: function () { return http_api_1.Put; } });
|
|
44
|
+
Object.defineProperty(exports, "Delete", { enumerable: true, get: function () { return http_api_1.Delete; } });
|
|
45
|
+
Object.defineProperty(exports, "Patch", { enumerable: true, get: function () { return http_api_1.Patch; } });
|
|
46
|
+
Object.defineProperty(exports, "Path", { enumerable: true, get: function () { return http_api_1.Path; } });
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-client/src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;;;AAEH,iDAA6D;AAApD,6GAAA,YAAY,OAAA;AAErB,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"}
|