@webpieces/http-client 0.2.7 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/http-client",
3
- "version": "0.2.7",
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.7"
24
+ "@webpieces/http-api": "0.2.9"
25
25
  }
26
26
  }
@@ -1,13 +1,10 @@
1
1
  /**
2
2
  * Configuration options for HTTP client.
3
3
  */
4
- export interface ClientConfig {
4
+ export declare class ClientConfig {
5
5
  /** Base URL for all requests (e.g., 'http://localhost:3000') */
6
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;
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 client = createClient(SaveApiPrototype, { baseUrl: 'http://localhost:3000' });
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 (baseUrl, headers, etc.)
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 & {
@@ -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 client = createClient(SaveApiPrototype, { baseUrl: 'http://localhost:3000' });
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 (baseUrl, headers, etc.)
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(fetchImpl, config, route, args);
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(fetchImpl, config, route, args) {
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 fetchImpl(url, options);
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();
@@ -1 +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"}
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 client = createClient(SaveApiPrototype, {
27
- * baseUrl: 'http://localhost:3000'
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 client = createClient(SaveApiPrototype, {
28
- * baseUrl: 'http://localhost:3000'
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
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"]}