@forge-dashboard/sdk-node 1.1.0 → 2.0.1

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 CHANGED
@@ -12,6 +12,8 @@ REST API, generated from its OpenAPI spec with
12
12
  [openapi-fetch](https://openapi-ts.dev/openapi-fetch/). It saves you from
13
13
  hand-rolling HTTP requests and retries against the API yourself.
14
14
 
15
+ Full API reference: <https://alrayyes.github.io/forge-dashboard-sdk-node/>
16
+
15
17
  ## Requirements
16
18
 
17
19
  - Node.js 20+ or [Bun](https://bun.sh) 1.1+ — anything with a native `fetch`.
@@ -0,0 +1,41 @@
1
+ import { type Client as OpenapiFetchClient } from "openapi-fetch";
2
+ import type { paths } from "./generated/schema.js";
3
+ import { type RetryConfig } from "./retry.js";
4
+ /**
5
+ * The environment variable {@link createForgeDashboardClient} falls back
6
+ * to when no token is passed explicitly via {@link ClientOptions.token}.
7
+ */
8
+ export declare const TOKEN_ENV_VAR = "FORGE_DASHBOARD_TOKEN";
9
+ export interface ClientOptions {
10
+ /**
11
+ * A forge-dashboard personal API token, generated from the dashboard's
12
+ * own Settings page (`POST /api/tokens`, signed in as yourself first).
13
+ * Overrides `FORGE_DASHBOARD_TOKEN` when both are set. See the README's
14
+ * "Authentication" section -- this is the real headless alternative
15
+ * forge-dashboard's spec documents to its browser session cookie.
16
+ */
17
+ token?: string;
18
+ /**
19
+ * Replaces the underlying `fetch`. The retry wrapper (see `retry`)
20
+ * wraps whatever this is, so pass something with its own request
21
+ * behavior already configured (a proxying fetch, a test double) rather
22
+ * than re-implementing retry yourself.
23
+ */
24
+ fetch?: (input: Request) => Promise<Response>;
25
+ /** Overrides the default retry policy. */
26
+ retry?: Partial<RetryConfig>;
27
+ }
28
+ /**
29
+ * A forge-dashboard API client -- the typed `openapi-fetch` client for
30
+ * `paths`, so every operation is available as `client.GET("/api/dashboard",
31
+ * ...)` / `client.POST("/api/pull-requests/merge", ...)` etc. See the
32
+ * README for the common operations and {@link decodeError} for turning a
33
+ * failed response into a typed error.
34
+ */
35
+ export type ForgeDashboardClient = OpenapiFetchClient<paths>;
36
+ /**
37
+ * Builds a client against `baseUrl` (the forge-dashboard instance's own
38
+ * origin, e.g. `"https://dashboard.example.com"`).
39
+ */
40
+ export declare function createForgeDashboardClient(baseUrl: string, options?: ClientOptions): ForgeDashboardClient;
41
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAqB,EAAE,KAAK,MAAM,IAAI,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,eAAO,MAAM,aAAa,0BAA0B,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,oBAAoB,CAqBtB"}
package/dist/client.js ADDED
@@ -0,0 +1,35 @@
1
+ import createClient, {} from "openapi-fetch";
2
+ import { createRetryFetch, defaultRetryConfig, } from "./retry.js";
3
+ /**
4
+ * The environment variable {@link createForgeDashboardClient} falls back
5
+ * to when no token is passed explicitly via {@link ClientOptions.token}.
6
+ */
7
+ export const TOKEN_ENV_VAR = "FORGE_DASHBOARD_TOKEN";
8
+ /**
9
+ * Builds a client against `baseUrl` (the forge-dashboard instance's own
10
+ * origin, e.g. `"https://dashboard.example.com"`).
11
+ */
12
+ export function createForgeDashboardClient(baseUrl, options = {}) {
13
+ const token = options.token ?? getEnv(TOKEN_ENV_VAR);
14
+ const retryConfig = { ...defaultRetryConfig, ...options.retry };
15
+ const baseFetch = options.fetch ?? ((request) => fetch(request));
16
+ const client = createClient({
17
+ baseUrl,
18
+ fetch: createRetryFetch(baseFetch, retryConfig),
19
+ });
20
+ if (token) {
21
+ client.use({
22
+ onRequest({ request }) {
23
+ request.headers.set("Authorization", `Bearer ${token}`);
24
+ return request;
25
+ },
26
+ });
27
+ }
28
+ return client;
29
+ }
30
+ function getEnv(name) {
31
+ // Bun and Node both expose process.env; guarded for a browser bundle
32
+ // that has no `process` at all.
33
+ return typeof process !== "undefined" ? process.env[name] : undefined;
34
+ }
35
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,EAAE,EAAqC,MAAM,eAAe,CAAC;AAEhF,OAAO,EACL,gBAAgB,EAChB,kBAAkB,GAEnB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AA+BrD;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAe,EACf,UAAyB,EAAE;IAE3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC;IACrD,MAAM,WAAW,GAAgB,EAAE,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC7E,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,OAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAE1E,MAAM,MAAM,GAAG,YAAY,CAAQ;QACjC,OAAO;QACP,KAAK,EAAE,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC;KAChD,CAAC,CAAC;IAEH,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,GAAG,CAAC;YACT,SAAS,CAAC,EAAE,OAAO,EAAE;gBACnB,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC;gBAExD,OAAO,OAAO,CAAC;YACjB,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,qEAAqE;IACrE,gCAAgC;IAChC,OAAO,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxE,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Every 4xx/5xx forge-dashboard returns shares the same `{error}` body
3
+ * (openapi/openapi.yaml's `Error` schema) -- one field, unlike some APIs'
4
+ * richer `{code, message}` shape. `ApiError` carries that alongside the
5
+ * HTTP status, so a caller never has to parse a raw `Response` or match
6
+ * against a bare string.
7
+ */
8
+ export declare class ApiError extends Error {
9
+ readonly statusCode: number;
10
+ readonly apiMessage: string;
11
+ constructor(statusCode: number, message: string);
12
+ }
13
+ /**
14
+ * Builds an ApiError from a response and its already-parsed error body --
15
+ * openapi-fetch decodes JSON before handing you `error`, so there's no
16
+ * `Response` to read a second time. Returns null for a response that
17
+ * isn't actually an error (status < 400), so callers can call this
18
+ * unconditionally on openapi-fetch's `{ data, error, response }` result:
19
+ *
20
+ * const { data, error, response } = await client.GET("/api/dashboard", {});
21
+ * const apiErr = decodeError(response, error);
22
+ * if (apiErr) throw apiErr;
23
+ */
24
+ export declare function decodeError(response: Response, body: unknown): ApiError | null;
25
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAMhD;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,OAAO,GACZ,QAAQ,GAAG,IAAI,CAQjB"}
package/dist/errors.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Every 4xx/5xx forge-dashboard returns shares the same `{error}` body
3
+ * (openapi/openapi.yaml's `Error` schema) -- one field, unlike some APIs'
4
+ * richer `{code, message}` shape. `ApiError` carries that alongside the
5
+ * HTTP status, so a caller never has to parse a raw `Response` or match
6
+ * against a bare string.
7
+ */
8
+ export class ApiError extends Error {
9
+ statusCode;
10
+ apiMessage;
11
+ constructor(statusCode, message) {
12
+ super(`forge-dashboard: ${statusCode}: ${message}`);
13
+ this.name = "ApiError";
14
+ this.statusCode = statusCode;
15
+ this.apiMessage = message;
16
+ }
17
+ }
18
+ /**
19
+ * Builds an ApiError from a response and its already-parsed error body --
20
+ * openapi-fetch decodes JSON before handing you `error`, so there's no
21
+ * `Response` to read a second time. Returns null for a response that
22
+ * isn't actually an error (status < 400), so callers can call this
23
+ * unconditionally on openapi-fetch's `{ data, error, response }` result:
24
+ *
25
+ * const { data, error, response } = await client.GET("/api/dashboard", {});
26
+ * const apiErr = decodeError(response, error);
27
+ * if (apiErr) throw apiErr;
28
+ */
29
+ export function decodeError(response, body) {
30
+ if (response.status < 400) {
31
+ return null;
32
+ }
33
+ const parsed = isErrorBody(body) ? body : {};
34
+ return new ApiError(response.status, parsed.error ?? response.statusText);
35
+ }
36
+ function isErrorBody(value) {
37
+ return typeof value === "object" && value !== null;
38
+ }
39
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,UAAU,CAAS;IACnB,UAAU,CAAS;IAE5B,YAAY,UAAkB,EAAE,OAAe;QAC7C,KAAK,CAAC,oBAAoB,UAAU,KAAK,OAAO,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;IAC5B,CAAC;CACF;AAMD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CACzB,QAAkB,EAClB,IAAa;IAEb,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7C,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC"}