@hlix/sdk 0.2.0 → 0.3.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.
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `@hlix/api-client` — the generated, typed transport for the hlix API.
3
+ *
4
+ * Derived from `apps/backend/openapi.json`, which is itself emitted from the
5
+ * Zod validators the routes run. One schema, all the way from request
6
+ * validation to this package's types, so a client cannot be typed against a
7
+ * shape the server does not accept.
8
+ *
9
+ * Transport-only. See `client.ts` for what that excludes and why.
10
+ */
11
+ export { createHlixClient } from "./client";
12
+ export type { HlixClient, HlixClientOptions } from "./client";
13
+ export type { components, operations, paths } from "./generated/schema";
package/dist/auth.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Credentials and tenancy — the two things every caller would otherwise
3
+ * reimplement, and the two the transport layer deliberately refuses to own.
4
+ *
5
+ * THREE credential kinds, because the API really does accept three:
6
+ *
7
+ * - `apiKey` → `x-api-key`. The documented scheme for programmatic callers.
8
+ * - `session` → the better-auth session cookie, which is what a browser
9
+ * already holds. Browser-login exchange can mint a scoped API key for a CLI.
10
+ * - `bearer` → `Authorization: Bearer <session token>`, the same session
11
+ * as a bare token (better-auth's bearer plugin). What the desktop app holds
12
+ * and hands to the `hlix` sidecar it runs on the person's machine.
13
+ *
14
+ * The backend verifies API keys in its explicit API middleware rather than
15
+ * enabling Better Auth's session emulation for keys. A key authenticates its
16
+ * owner but carries no active workspace; programmatic callers should always
17
+ * provide `organizationId`.
18
+ */
19
+ export type HlixCredential = {
20
+ readonly kind: "apiKey";
21
+ readonly apiKey: string;
22
+ } | {
23
+ readonly kind: "session";
24
+ readonly cookie: string;
25
+ } | {
26
+ readonly kind: "bearer";
27
+ readonly token: string;
28
+ };
29
+ export declare const apiKeyCredential: (apiKey: string) => HlixCredential;
30
+ export declare const sessionCredential: (cookie: string) => HlixCredential;
31
+ export declare const bearerCredential: (token: string) => HlixCredential;
32
+ /** The credential header pair. Never logged — callers print SDK errors. */
33
+ export declare function credentialHeaders(credential: HlixCredential): Record<string, string>;
34
+ /**
35
+ * Tenant selection. Omitted, the server falls back to the session's active
36
+ * organization — which is a real default for a browser, and a trap for a
37
+ * script that assumes it knows which workspace it just wrote to. The SDK
38
+ * therefore sends the header whenever it was given one and never invents one.
39
+ */
40
+ export declare function organizationHeaders(organizationId: string | undefined): Record<string, string>;
41
+ export declare function authHeaders(credential: HlixCredential, organizationId: string | undefined): Record<string, string>;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Typed errors, so a caller branches on a denial instead of string-matching.
3
+ *
4
+ * Every class carries the HTTP status and the server's parsed body. The shapes
5
+ * come from the published contract (`apps/backend/openapi.json`): a handled
6
+ * failure is `{ error: string }` (`ApiError`), and a body that fails schema
7
+ * validation is `{ success: false, error: { name, message } }`
8
+ * (`ValidationError`), where `message` is a JSON-encoded array of issues rather
9
+ * than a sentence. `HlixValidationError` parses that for you — printing it raw
10
+ * is what the contract warns against.
11
+ */
12
+ export interface HlixErrorInit {
13
+ status: number;
14
+ body: unknown;
15
+ /** `x-request-id`, when the response carried one — the handle for support. */
16
+ requestId?: string | null;
17
+ method: string;
18
+ url: string;
19
+ }
20
+ export declare class HlixError extends Error {
21
+ readonly status: number;
22
+ readonly body: unknown;
23
+ readonly requestId: string | null;
24
+ readonly method: string;
25
+ readonly url: string;
26
+ constructor(message: string, init: HlixErrorInit);
27
+ }
28
+ /** 400 — the request body did not satisfy the route's schema. */
29
+ export declare class HlixValidationError extends HlixError {
30
+ /** The decoded `ZodIssue[]`; empty when the server sent a plain message. */
31
+ readonly issues: unknown[];
32
+ constructor(message: string, init: HlixErrorInit, issues: unknown[]);
33
+ }
34
+ /** 400 that is not a schema failure — e.g. no active organization. */
35
+ export declare class HlixBadRequestError extends HlixError {
36
+ }
37
+ /** 401 — no valid credential. */
38
+ export declare class HlixAuthenticationError extends HlixError {
39
+ }
40
+ /** 403 — authenticated, but not permitted. */
41
+ export declare class HlixPermissionError extends HlixError {
42
+ }
43
+ /**
44
+ * 404 — absent, OR present and deliberately hidden. The API answers 404 rather
45
+ * than 403 for a resource the caller was never granted, so this does NOT mean
46
+ * "does not exist".
47
+ */
48
+ export declare class HlixNotFoundError extends HlixError {
49
+ }
50
+ /** 409 — the request conflicts with current state. */
51
+ export declare class HlixConflictError extends HlixError {
52
+ }
53
+ /** 429 — rate limited. `retryAfter` is seconds, when the server said. */
54
+ export declare class HlixRateLimitError extends HlixError {
55
+ readonly retryAfter: number | null;
56
+ constructor(message: string, init: HlixErrorInit, retryAfter: number | null);
57
+ }
58
+ /** 501 — a documented, permanent refusal. Never retried. */
59
+ export declare class HlixNotImplementedError extends HlixError {
60
+ }
61
+ /** 5xx. */
62
+ export declare class HlixServerError extends HlixError {
63
+ }
64
+ /** The request never produced a response: DNS, TLS, connection, abort. */
65
+ export declare class HlixTransportError extends Error {
66
+ readonly method: string;
67
+ readonly url: string;
68
+ constructor(message: string, init: {
69
+ method: string;
70
+ url: string;
71
+ cause?: unknown;
72
+ });
73
+ }
74
+ /** Build the error class that fits a failed response. */
75
+ export declare function errorForResponse(response: Response, body: unknown, request: {
76
+ method: string;
77
+ url: string;
78
+ }): HlixError;
package/dist/http.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The retrying transport and the throw-on-failure boundary.
3
+ *
4
+ * Retry lives HERE, wrapping `fetch`, rather than around a resource method:
5
+ * this is the only layer that can see the real HTTP verb, and the verb is what
6
+ * decides whether a second attempt is permissible at all (see `retry.ts`).
7
+ * Deciding higher up would mean re-deriving the verb from the method name,
8
+ * which is exactly the sort of indirection that eventually gets it wrong.
9
+ */
10
+ import { type HlixError } from "./errors";
11
+ import { type RetryPolicy } from "./retry";
12
+ export type FetchLike = (input: Request) => Promise<Response>;
13
+ export interface RetryingFetchOptions {
14
+ base: FetchLike;
15
+ policy: RetryPolicy;
16
+ /** Injected so tests do not actually sleep. */
17
+ sleep?: (ms: number) => Promise<void>;
18
+ random?: () => number;
19
+ }
20
+ /**
21
+ * `fetch` with bounded retry on idempotent verbs only.
22
+ *
23
+ * A non-idempotent request is issued exactly once — including when the
24
+ * transport throws and the SDK therefore cannot know whether the server acted.
25
+ * "Might not have happened" is not a licence to do it again.
26
+ */
27
+ export declare function retryingFetch(options: RetryingFetchOptions): FetchLike;
28
+ /** An openapi-fetch result, narrowed to what the SDK needs. */
29
+ export interface ClientResult<T> {
30
+ data?: T;
31
+ error?: unknown;
32
+ response: Response;
33
+ }
34
+ /**
35
+ * Return the body or throw a typed error.
36
+ *
37
+ * The transport reports failure as a value (`{ error }`); the SDK is allowed
38
+ * the opinion that a 404 is exceptional, because a caller who wants the value
39
+ * form can use `raw`.
40
+ */
41
+ export declare function unwrap<T>(result: ClientResult<T>, request: {
42
+ method: string;
43
+ url: string;
44
+ }): T;
45
+ export type { HlixError };