@confighub/api 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) ConfigHub, Inc.
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/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @confighub/api
2
+
3
+ A typed, framework-agnostic client for the [ConfigHub](https://confighub.com) API,
4
+ generated from the ConfigHub OpenAPI spec. Built on
5
+ [openapi-fetch](https://openapi-ts.dev/openapi-fetch/) — a few KB, no Redux, no
6
+ React, no required provider. Every path, parameter, and response is typed against a
7
+ pinned server version.
8
+
9
+ ```ts
10
+ import { createConfigHubClient } from '@confighub/api';
11
+
12
+ const api = createConfigHubClient({
13
+ baseUrl: 'https://hub.confighub.com',
14
+ getToken: () => session.accessToken, // optional; sets Authorization: Bearer
15
+ });
16
+
17
+ const me = await api.GET('/me');
18
+ const { data, error } = await api.GET('/space/{space_id}/unit', {
19
+ params: { path: { space_id } },
20
+ });
21
+ ```
22
+
23
+ ## Options
24
+
25
+ - `baseUrl` — absolute base URL of the ConfigHub instance.
26
+ - `getToken?` — returns the current bearer token (may be async). Wired as a
27
+ per-request middleware. The client never stores or refreshes tokens; pair it with
28
+ [`@confighub/react-auth`](https://www.npmjs.com/package/@confighub/react-auth) or
29
+ supply your own token source.
30
+ - `onUnauthorized?` — called on a 401 so the caller can refresh or re-login. The
31
+ request is not retried automatically.
32
+ - `fetch?` — override the fetch implementation.
33
+
34
+ ## Types
35
+
36
+ The full generated surface is exported for reuse:
37
+
38
+ ```ts
39
+ import type { paths, components } from '@confighub/api';
40
+ type Unit = components['schemas']['Unit'];
41
+ ```
42
+
43
+ Types track the ConfigHub server version pinned in the SDK repo's `.spec-version`.
package/dist/index.cjs ADDED
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ var createClient = require('openapi-fetch');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var createClient__default = /*#__PURE__*/_interopDefault(createClient);
8
+
9
+ // src/client.ts
10
+ var trimTrailingSlash = (s) => s.replace(/\/+$/, "");
11
+ var apiBaseUrl = (baseUrl) => {
12
+ const trimmed = trimTrailingSlash(baseUrl);
13
+ return trimmed.endsWith("/api") ? trimmed : trimmed + "/api";
14
+ };
15
+ function createConfigHubClient(options) {
16
+ const { baseUrl, getToken, onUnauthorized, fetch: fetchImpl } = options;
17
+ const client = createClient__default.default({
18
+ baseUrl: apiBaseUrl(baseUrl),
19
+ fetch: fetchImpl
20
+ });
21
+ const middleware = {
22
+ async onRequest({ request }) {
23
+ if (getToken) {
24
+ const token = await getToken();
25
+ if (token) request.headers.set("Authorization", `Bearer ${token}`);
26
+ }
27
+ if (request.method === "PATCH" && request.body != null) {
28
+ request.headers.set("Content-Type", "application/merge-patch+json");
29
+ }
30
+ return request;
31
+ },
32
+ async onResponse({ response }) {
33
+ if (response.status === 401 && onUnauthorized) {
34
+ await onUnauthorized();
35
+ }
36
+ return response;
37
+ }
38
+ };
39
+ client.use(middleware);
40
+ return client;
41
+ }
42
+
43
+ exports.createConfigHubClient = createConfigHubClient;
44
+ //# sourceMappingURL=index.cjs.map
45
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"names":["createClient"],"mappings":";;;;;;;;;AAqCA,IAAM,oBAAoB,CAAC,CAAA,KAAsB,CAAA,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAIrE,IAAM,UAAA,GAAa,CAAC,OAAA,KAA4B;AAC9C,EAAA,MAAM,OAAA,GAAU,kBAAkB,OAAO,CAAA;AACzC,EAAA,OAAO,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,GAAI,UAAU,OAAA,GAAU,MAAA;AACxD,CAAA;AAaO,SAAS,sBAAsB,OAAA,EAAkD;AACtF,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,cAAA,EAAgB,KAAA,EAAO,WAAU,GAAI,OAAA;AAEhE,EAAA,MAAM,SAASA,6BAAA,CAAoB;AAAA,IACjC,OAAA,EAAS,WAAW,OAAO,CAAA;AAAA,IAC3B,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,MAAM,UAAA,GAAyB;AAAA,IAC7B,MAAM,SAAA,CAAU,EAAE,OAAA,EAAQ,EAAG;AAC3B,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,EAAS;AAC7B,QAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAI,eAAA,EAAiB,CAAA,OAAA,EAAU,KAAK,CAAA,CAAE,CAAA;AAAA,MACnE;AAIA,MAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,OAAA,IAAW,OAAA,CAAQ,QAAQ,IAAA,EAAM;AACtD,QAAA,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgB,8BAA8B,CAAA;AAAA,MACpE;AACA,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA,IACA,MAAM,UAAA,CAAW,EAAE,QAAA,EAAS,EAAG;AAC7B,MAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,IAAO,cAAA,EAAgB;AAC7C,QAAA,MAAM,cAAA,EAAe;AAAA,MACvB;AACA,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAI,UAAU,CAAA;AACrB,EAAA,OAAO,MAAA;AACT","file":"index.cjs","sourcesContent":["// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport createClient, { type Client, type Middleware } from 'openapi-fetch';\nimport type { paths } from './schema';\n\nexport interface ConfigHubClientOptions {\n /**\n * Base URL of the ConfigHub instance, e.g. `https://hub.confighub.com` — the same\n * value passed to the auth provider. The ConfigHub API is mounted under `/api`\n * (the spec's paths are relative to it), so the client targets `{baseUrl}/api`.\n * Passing a URL that already ends in `/api` is accepted as-is.\n */\n baseUrl: string;\n\n /**\n * Returns the current bearer token, or undefined when unauthenticated. May be\n * async so the caller can await a refresh. Wired as an openapi-fetch middleware\n * that sets `Authorization: Bearer <token>` per request. The client never stores\n * or refreshes tokens itself — that is the auth layer's job (see\n * `@confighub/react-auth`).\n */\n getToken?: () => string | undefined | Promise<string | undefined>;\n\n /**\n * Called when a request returns 401. A library must not redirect on its own, so\n * this hands control back to the caller — typically to trigger a token refresh\n * or re-login. The originating request is not retried automatically.\n */\n onUnauthorized?: () => void | Promise<void>;\n\n /** Override the fetch implementation (tests, non-browser runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\nexport type ConfigHubClient = Client<paths>;\n\nconst trimTrailingSlash = (s: string): string => s.replace(/\\/+$/, '');\n\n// The ConfigHub API lives under /api and the OpenAPI paths are relative to it. Accept\n// either the instance origin or a URL that already includes /api.\nconst apiBaseUrl = (baseUrl: string): string => {\n const trimmed = trimTrailingSlash(baseUrl);\n return trimmed.endsWith('/api') ? trimmed : trimmed + '/api';\n};\n\n/**\n * Create a typed ConfigHub API client. Every path, param, and response is derived\n * from the pinned OpenAPI spec (`src/schema.d.ts`), so it stays in lockstep with\n * the server.\n *\n * ```ts\n * const api = createConfigHubClient({ baseUrl, getToken: () => session.accessToken });\n * const { data, error } = await api.GET('/me');\n * const units = await api.GET('/space/{space_id}/unit', { params: { path: { space_id } } });\n * ```\n */\nexport function createConfigHubClient(options: ConfigHubClientOptions): ConfigHubClient {\n const { baseUrl, getToken, onUnauthorized, fetch: fetchImpl } = options;\n\n const client = createClient<paths>({\n baseUrl: apiBaseUrl(baseUrl),\n fetch: fetchImpl,\n });\n\n const middleware: Middleware = {\n async onRequest({ request }) {\n if (getToken) {\n const token = await getToken();\n if (token) request.headers.set('Authorization', `Bearer ${token}`);\n }\n // ConfigHub's PATCH endpoints expect RFC 7386 merge-patch semantics. This\n // mirrors the first-party UI, which sets the same content type for its\n // patch/bulk-patch operations.\n if (request.method === 'PATCH' && request.body != null) {\n request.headers.set('Content-Type', 'application/merge-patch+json');\n }\n return request;\n },\n async onResponse({ response }) {\n if (response.status === 401 && onUnauthorized) {\n await onUnauthorized();\n }\n return response;\n },\n };\n\n client.use(middleware);\n return client;\n}\n"]}