@xemahq/space-registry-internal-api-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 ADDED
@@ -0,0 +1,62 @@
1
+ <!-- Generated by @xemahq/api-client-generator. Do not edit by hand. -->
2
+ <p align="center">
3
+ <svg width="680" height="120" viewBox="0 0 680 120" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="@xemahq/space-registry-internal-api-client">
4
+ <rect width="680" height="120" rx="14" fill="#0B1020"/>
5
+ <g transform="translate(28,34)">
6
+ <path d="M26 0 L52 15 L52 45 L26 60 L0 45 L0 15 Z" fill="#14B8A6" opacity="0.18"/>
7
+ <path d="M26 12 L41 21 L41 39 L26 48 L11 39 L11 21 Z" fill="#14B8A6"/>
8
+ </g>
9
+ <text x="92" y="52" font-family="ui-monospace,SFMono-Regular,Menlo,monospace" font-size="22" fill="#F8FAFC" font-weight="700">@xemahq/space-registry-internal-api-client</text>
10
+ <text x="92" y="80" font-family="ui-sans-serif,system-ui,sans-serif" font-size="15" fill="#94A3B8">Typed, generated internal HTTP client for the Space Registry API.</text>
11
+ <text x="652" y="105" text-anchor="end" font-family="ui-sans-serif,system-ui,sans-serif" font-size="12" fill="#475569">xema.dev</text>
12
+ </svg>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a href="https://xema.dev">Website</a> &middot;
17
+ <a href="https://www.npmjs.com/package/@xemahq/space-registry-internal-api-client">npm</a>
18
+ </p>
19
+
20
+ <p align="center">
21
+ <img alt="npm" src="https://img.shields.io/npm/v/%40xemahq%2Fspace-registry-internal-api-client?color=2563eb&label=npm">
22
+ <img alt="license" src="https://img.shields.io/npm/l/%40xemahq%2Fspace-registry-internal-api-client?color=10b981">
23
+ <img alt="types" src="https://img.shields.io/npm/types/%40xemahq%2Fspace-registry-internal-api-client?color=3178c6">
24
+ </p>
25
+
26
+ # @xemahq/space-registry-internal-api-client
27
+
28
+ > Typed, generated internal HTTP client for the Space Registry API.
29
+
30
+ ## Overview
31
+
32
+ Auto-generated TypeScript client for the **Space Registry API**. It exports typed
33
+ request functions and response models that mirror the service's OpenAPI surface,
34
+ so callers get end-to-end type safety without hand-writing HTTP calls. This
35
+ package is produced by `@xemahq/api-client-generator` and regenerated whenever
36
+ the service's API changes — do not edit it by hand.
37
+
38
+ ## When to use it
39
+
40
+ - Use it from any TypeScript service or app that calls the Space Registry API over HTTP.
41
+ - You get compile-time types for every endpoint and payload; regenerate to pick
42
+ up API changes rather than editing the client.
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ pnpm add @xemahq/space-registry-internal-api-client
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ```ts
53
+ // Every endpoint function and response model is exported from the package root.
54
+ import * as client from '@xemahq/space-registry-internal-api-client';
55
+ ```
56
+
57
+ Call the typed endpoint functions; request and response shapes are fully typed
58
+ from the service's OpenAPI spec.
59
+
60
+ ## License
61
+
62
+ Apache-2.0 &copy; Xema — [xema.dev](https://xema.dev)
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Configurable fetch wrapper for Orval-generated clients.
3
+ *
4
+ * Consumers must call `configureClient()` before using any endpoint function.
5
+ * The baseUrl is prepended to the relative paths generated by Orval.
6
+ *
7
+ * Features:
8
+ * - Automatic bearer-token injection via `getAuthToken` callback
9
+ * - Per-request header injection via `getHeaders` callback
10
+ * - Automatic 401 handling via `onUnauthorized` callback (single retry)
11
+ * - Exponential-backoff retry for transient failures (429, 502, 503, 504)
12
+ * - Typed `ClientError` for non-2xx responses
13
+ * - Per-call header overrides (take precedence over global headers)
14
+ *
15
+ * @example
16
+ * configureClient({
17
+ * baseUrl: 'http://governance-api:3400',
18
+ * getAuthToken: () => identityBootstrapService.getAccessToken(),
19
+ * getHeaders: () => ({ 'X-Org-Id': orgId, 'X-Correlation-Id': crypto.randomUUID() }),
20
+ * });
21
+ */
22
+ export interface ClientConfig {
23
+ /**
24
+ * Static base URL (e.g. 'http://localhost:3140') — no trailing slash.
25
+ * Mutually exclusive with `baseUrlResolver`; exactly one MUST be set.
26
+ */
27
+ baseUrl?: string;
28
+ /**
29
+ * Per-request base-URL resolver. When set, the peer URL is resolved from
30
+ * the service registry on EVERY request (boot-order-safe). Wired by
31
+ * `configureOrvalClientResolved` from `@xemahq/platform-common`.
32
+ */
33
+ baseUrlResolver?: () => string | Promise<string>;
34
+ /** Optional async callback to get an auth token. Auto-sets Authorization header on every request. */
35
+ getAuthToken?: () => Promise<string>;
36
+ /** Optional callback returning headers to inject on every request. Per-call headers take precedence. */
37
+ getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
38
+ /** Optional callback invoked on 401 before a single retry (e.g. force-refresh auth token). */
39
+ onUnauthorized?: () => Promise<void>;
40
+ /** Maximum retry attempts for transient failures (default: 3). Set to 0 to disable retries. */
41
+ maxRetries?: number;
42
+ }
43
+ export declare class ClientError extends Error {
44
+ readonly status: number;
45
+ readonly url: string;
46
+ readonly body: unknown;
47
+ constructor(status: number, url: string, body: unknown);
48
+ }
49
+ export declare function configureClient(config: ClientConfig): void;
50
+ export declare function getClientConfig(): ClientConfig;
51
+ export declare const customFetch: <T>(url: string, options: RequestInit) => Promise<T>;
52
+ export default customFetch;
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ /**
3
+ * Configurable fetch wrapper for Orval-generated clients.
4
+ *
5
+ * Consumers must call `configureClient()` before using any endpoint function.
6
+ * The baseUrl is prepended to the relative paths generated by Orval.
7
+ *
8
+ * Features:
9
+ * - Automatic bearer-token injection via `getAuthToken` callback
10
+ * - Per-request header injection via `getHeaders` callback
11
+ * - Automatic 401 handling via `onUnauthorized` callback (single retry)
12
+ * - Exponential-backoff retry for transient failures (429, 502, 503, 504)
13
+ * - Typed `ClientError` for non-2xx responses
14
+ * - Per-call header overrides (take precedence over global headers)
15
+ *
16
+ * @example
17
+ * configureClient({
18
+ * baseUrl: 'http://governance-api:3400',
19
+ * getAuthToken: () => identityBootstrapService.getAccessToken(),
20
+ * getHeaders: () => ({ 'X-Org-Id': orgId, 'X-Correlation-Id': crypto.randomUUID() }),
21
+ * });
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.customFetch = exports.ClientError = void 0;
25
+ exports.configureClient = configureClient;
26
+ exports.getClientConfig = getClientConfig;
27
+ class ClientError extends Error {
28
+ status;
29
+ url;
30
+ body;
31
+ constructor(status, url, body) {
32
+ super(`HTTP ${status} from ${url}`);
33
+ this.status = status;
34
+ this.url = url;
35
+ this.body = body;
36
+ this.name = 'ClientError';
37
+ }
38
+ }
39
+ exports.ClientError = ClientError;
40
+ let clientConfig = null;
41
+ function configureClient(config) {
42
+ clientConfig = config;
43
+ }
44
+ function getClientConfig() {
45
+ if (!clientConfig) {
46
+ throw new Error('Client not configured. Call configureClient({ baseUrl }) before using endpoint functions.');
47
+ }
48
+ return clientConfig;
49
+ }
50
+ const RETRYABLE_STATUSES = [429, 502, 503, 504];
51
+ async function buildHeaders(config, callerHeaders) {
52
+ const headers = new Headers(callerHeaders);
53
+ // Global headers from config (caller-provided headers take precedence)
54
+ if (config.getHeaders) {
55
+ const globalHeaders = await Promise.resolve(config.getHeaders());
56
+ for (const [key, value] of Object.entries(globalHeaders)) {
57
+ if (!headers.has(key)) {
58
+ headers.set(key, value);
59
+ }
60
+ }
61
+ }
62
+ // Auth token (caller or global headers take precedence)
63
+ if (config.getAuthToken && !headers.has('Authorization')) {
64
+ const token = await config.getAuthToken();
65
+ headers.set('Authorization', `Bearer ${token}`);
66
+ }
67
+ return headers;
68
+ }
69
+ const customFetch = async (url, options) => {
70
+ const config = getClientConfig();
71
+ const base = config.baseUrlResolver
72
+ ? await config.baseUrlResolver()
73
+ : config.baseUrl;
74
+ if (base === undefined) {
75
+ throw new Error('Client not configured: set baseUrl or baseUrlResolver via configureClient().');
76
+ }
77
+ const fullUrl = `${base}${url}`;
78
+ const maxRetries = config.maxRetries ?? 3;
79
+ const headers = await buildHeaders(config, options.headers);
80
+ const requestInit = { ...options, headers };
81
+ let delay = 1000;
82
+ let lastError;
83
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
84
+ try {
85
+ const response = await fetch(fullUrl, requestInit);
86
+ // 401 — invoke onUnauthorized and retry once (outside the transient retry loop)
87
+ if (response.status === 401 && config.onUnauthorized && attempt === 0) {
88
+ await config.onUnauthorized();
89
+ const refreshedHeaders = await buildHeaders(config, options.headers);
90
+ const retryResponse = await fetch(fullUrl, { ...options, headers: refreshedHeaders });
91
+ const retryBody = await parseBody(retryResponse);
92
+ if (retryResponse.status >= 400) {
93
+ throw new ClientError(retryResponse.status, fullUrl, retryBody);
94
+ }
95
+ return retryBody;
96
+ }
97
+ // Non-retryable status — return or throw
98
+ if (!RETRYABLE_STATUSES.includes(response.status) || attempt >= maxRetries) {
99
+ const body = await parseBody(response);
100
+ if (response.status >= 400) {
101
+ throw new ClientError(response.status, fullUrl, body);
102
+ }
103
+ return body;
104
+ }
105
+ // Retryable — wait and retry
106
+ const retryAfter = parseRetryAfter(response.headers.get('Retry-After'));
107
+ const waitMs = retryAfter ?? addJitter(delay);
108
+ await sleep(waitMs);
109
+ delay = Math.min(delay * 2, 30_000);
110
+ }
111
+ catch (error) {
112
+ if (error instanceof ClientError)
113
+ throw error; // Don't retry client errors
114
+ lastError = error instanceof Error ? error : new Error(String(error));
115
+ if (attempt >= maxRetries)
116
+ throw lastError;
117
+ const waitMs = addJitter(delay);
118
+ await sleep(waitMs);
119
+ delay = Math.min(delay * 2, 30_000);
120
+ }
121
+ }
122
+ throw lastError ?? new Error(`All retries exhausted for ${fullUrl}`);
123
+ };
124
+ exports.customFetch = customFetch;
125
+ async function parseBody(response) {
126
+ const contentType = response.headers.get('content-type');
127
+ if (contentType?.includes('application/json')) {
128
+ return response.json();
129
+ }
130
+ if (response.status === 204) {
131
+ return undefined;
132
+ }
133
+ return response.text();
134
+ }
135
+ function parseRetryAfter(value) {
136
+ if (!value)
137
+ return undefined;
138
+ const seconds = Number(value);
139
+ if (!isNaN(seconds) && seconds >= 0)
140
+ return seconds * 1000;
141
+ const date = new Date(value);
142
+ if (!isNaN(date.getTime()))
143
+ return Math.max(0, date.getTime() - Date.now());
144
+ return undefined;
145
+ }
146
+ function addJitter(delay) {
147
+ return delay + (Math.random() * 2 - 1) * delay * 0.25;
148
+ }
149
+ function sleep(ms) {
150
+ return new Promise(resolve => setTimeout(resolve, ms));
151
+ }
152
+ exports.default = exports.customFetch;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Generated by orval v8.15.0 🍺
3
+ * Do not edit manually.
4
+ * Space Registry API
5
+ * Authoritative Space ownership + data-classification plane: Space CRUD, hierarchy, and most-specific-wins classification resolution.
6
+ * OpenAPI spec version: 0.1.0
7
+ */
8
+ import type { SpaceItemPublishCapabilityRequestDto } from '../../models';
9
+ export declare const getSpaceItemPublishCapabilityControllerSpaceItemPublishUrl: () => string;
10
+ export declare const spaceItemPublishCapabilityControllerSpaceItemPublish: (spaceItemPublishCapabilityRequestDto: SpaceItemPublishCapabilityRequestDto, options?: RequestInit) => Promise<void>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spaceItemPublishCapabilityControllerSpaceItemPublish = exports.getSpaceItemPublishCapabilityControllerSpaceItemPublishUrl = void 0;
4
+ const custom_fetch_1 = require("../../custom-fetch");
5
+ const getSpaceItemPublishCapabilityControllerSpaceItemPublishUrl = () => {
6
+ return `/internal/capabilities/space-item-publish`;
7
+ };
8
+ exports.getSpaceItemPublishCapabilityControllerSpaceItemPublishUrl = getSpaceItemPublishCapabilityControllerSpaceItemPublishUrl;
9
+ const spaceItemPublishCapabilityControllerSpaceItemPublish = async (spaceItemPublishCapabilityRequestDto, options) => {
10
+ return (0, custom_fetch_1.customFetch)((0, exports.getSpaceItemPublishCapabilityControllerSpaceItemPublishUrl)(), {
11
+ ...options,
12
+ method: 'POST',
13
+ headers: { 'Content-Type': 'application/json', ...options?.headers },
14
+ body: JSON.stringify(spaceItemPublishCapabilityRequestDto)
15
+ });
16
+ };
17
+ exports.spaceItemPublishCapabilityControllerSpaceItemPublish = spaceItemPublishCapabilityControllerSpaceItemPublish;
@@ -0,0 +1,3 @@
1
+ export { configureClient, getClientConfig, ClientError, customFetch, type ClientConfig } from './custom-fetch';
2
+ export * from './models';
3
+ export * from './endpoints/capabilities/capabilities';
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.customFetch = exports.ClientError = exports.getClientConfig = exports.configureClient = void 0;
18
+ // Auto-generated by @xemahq/api-client-generator — do not edit manually.
19
+ var custom_fetch_1 = require("./custom-fetch");
20
+ Object.defineProperty(exports, "configureClient", { enumerable: true, get: function () { return custom_fetch_1.configureClient; } });
21
+ Object.defineProperty(exports, "getClientConfig", { enumerable: true, get: function () { return custom_fetch_1.getClientConfig; } });
22
+ Object.defineProperty(exports, "ClientError", { enumerable: true, get: function () { return custom_fetch_1.ClientError; } });
23
+ Object.defineProperty(exports, "customFetch", { enumerable: true, get: function () { return custom_fetch_1.customFetch; } });
24
+ __exportStar(require("./models"), exports);
25
+ __exportStar(require("./endpoints/capabilities/capabilities"), exports);
@@ -0,0 +1 @@
1
+ export * from './spaceItemPublishCapabilityRequestDto';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Auto-generated by tooling/codegen/regenerate-models-barrel.js — do not edit manually.
18
+ __exportStar(require("./spaceItemPublishCapabilityRequestDto"), exports);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Generated by orval v8.15.0 🍺
3
+ * Do not edit manually.
4
+ * Space Registry API
5
+ * Authoritative Space ownership + data-classification plane: Space CRUD, hierarchy, and most-specific-wins classification resolution.
6
+ * OpenAPI spec version: 0.1.0
7
+ */
8
+ export interface SpaceItemPublishCapabilityRequestDto {
9
+ /**
10
+ * Reference to the target space the item is published into (the space `refUri`). The feed item is scoped to this space.
11
+ * @minLength 1
12
+ */
13
+ spaceRef: string;
14
+ /**
15
+ * Opaque producer-defined kind of the published source (e.g. an artifact / render kind). Carried verbatim as deep-link metadata.
16
+ * @minLength 1
17
+ * @maxLength 200
18
+ */
19
+ sourceKind: string;
20
+ /**
21
+ * Opaque producer-defined reference id of the published source (e.g. an artifact id). Carried verbatim; opaque to this capability.
22
+ * @minLength 1
23
+ */
24
+ refId: string;
25
+ /**
26
+ * Feed item title shown in the space feed.
27
+ * @minLength 1
28
+ * @maxLength 300
29
+ */
30
+ title: string;
31
+ /**
32
+ * Optional feed item detail line shown under the title.
33
+ * @minLength 1
34
+ */
35
+ summary?: string;
36
+ /** Optional deep-link URL the recipient opens to view the underlying item. Opaque to this capability. */
37
+ url?: string;
38
+ /** Optional feed category label. When it names a real feed category the consumer uses it; otherwise the consumer applies its default. */
39
+ category?: string;
40
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Generated by orval v8.15.0 🍺
4
+ * Do not edit manually.
5
+ * Space Registry API
6
+ * Authoritative Space ownership + data-classification plane: Space CRUD, hierarchy, and most-specific-wins classification resolution.
7
+ * OpenAPI spec version: 0.1.0
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@xemahq/space-registry-internal-api-client",
3
+ "version": "0.1.0",
4
+ "main": "./dist/index.js",
5
+ "types": "./dist/index.d.ts",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "scripts": {
10
+ "build": "tsc -p tsconfig.json",
11
+ "prepublishOnly": "npm run build"
12
+ },
13
+ "publishConfig": {
14
+ "registry": "https://registry.npmjs.org/",
15
+ "access": "public"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "catalog:"
19
+ },
20
+ "xema": {
21
+ "kind": "api-client",
22
+ "surface": "internal",
23
+ "service": "space-registry-api",
24
+ "biome": "space-registry",
25
+ "target": "server",
26
+ "generator": "@xemahq/api-client-generator@0.1.2",
27
+ "source": "openapi.internal.json"
28
+ }
29
+ }