@forge-dashboard/sdk-node 1.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.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/package.json +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ryan Kes
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,139 @@
1
+ # forge-dashboard-sdk-node
2
+
3
+ [![CI](https://github.com/alrayyes/forge-dashboard-sdk-node/actions/workflows/ci.yml/badge.svg)](https://github.com/alrayyes/forge-dashboard-sdk-node/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/%40forge-dashboard%2Fsdk-node)](https://www.npmjs.com/package/@forge-dashboard/sdk-node)
5
+ [![Codecov](https://codecov.io/gh/alrayyes/forge-dashboard-sdk-node/graph/badge.svg)](https://codecov.io/gh/alrayyes/forge-dashboard-sdk-node)
6
+ [![docs](https://img.shields.io/badge/docs-typedoc-blue)](https://alrayyes.github.io/forge-dashboard-sdk-node/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
+
9
+ A Node/TypeScript client for [forge-dashboard](https://github.com/alrayyes/forge-dashboard)'s
10
+ REST API, generated from its OpenAPI spec with
11
+ [openapi-typescript](https://openapi-ts.dev/) and
12
+ [openapi-fetch](https://openapi-ts.dev/openapi-fetch/). It saves you from
13
+ hand-rolling HTTP requests and retries against the API yourself.
14
+
15
+ ## Requirements
16
+
17
+ - Node.js 20+ or [Bun](https://bun.sh) 1.1+ — anything with a native `fetch`.
18
+ - A running forge-dashboard instance.
19
+ - A personal API token for that instance (see "Authentication" below) —
20
+ every endpoint except `/healthz` and `/api/version` needs one.
21
+
22
+ ## Installation
23
+
24
+ ```sh
25
+ bun add @forge-dashboard/sdk-node
26
+ # or: npm install @forge-dashboard/sdk-node
27
+ ```
28
+
29
+ ### Alternative registry: GitHub Packages
30
+
31
+ Every release also publishes to GitHub Packages under
32
+ `@alrayyes/forge-dashboard-sdk-node` — the same code, a different scope,
33
+ because GitHub Packages' npm registry requires a package scoped to the
34
+ repo owner rather than the `forge-dashboard` npm org. Worth it if you're
35
+ already authenticated to GitHub (CI in another of your own repos, say) and
36
+ would rather not hold a separate npmjs.com credential just to install this
37
+ one package.
38
+
39
+ Add a `.npmrc` pointing that scope at GitHub Packages:
40
+
41
+ ```
42
+ @alrayyes:registry=https://npm.pkg.github.com
43
+ //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
44
+ ```
45
+
46
+ then install the scoped name instead:
47
+
48
+ ```sh
49
+ npm install @alrayyes/forge-dashboard-sdk-node
50
+ ```
51
+
52
+ ## Authentication
53
+
54
+ forge-dashboard authenticates browsers with passkeys (WebAuthn) and a
55
+ session cookie, but its spec documents a real headless alternative: a
56
+ personal API token, generated from the dashboard's own Settings page
57
+ (`POST /api/tokens`, signed in as yourself first) and sent as
58
+ `Authorization: Bearer <token>` on every request after. Pass it to
59
+ `createForgeDashboardClient` or set `FORGE_DASHBOARD_TOKEN` in the
60
+ environment:
61
+
62
+ ```ts
63
+ import { createForgeDashboardClient } from "@forge-dashboard/sdk-node";
64
+
65
+ const client = createForgeDashboardClient("https://dashboard.example.com", {
66
+ token: process.env.FORGE_DASHBOARD_TOKEN,
67
+ });
68
+ ```
69
+
70
+ A token is revocable from Settings at any point; there's nothing in this
71
+ SDK to refresh one automatically once it's gone.
72
+
73
+ ## Usage
74
+
75
+ `GET /api/version` needs no token and is a good first call to prove the
76
+ client reaches the server at all. The client is a typed
77
+ [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/) instance, so every
78
+ operation is `client.GET(path, ...)` / `client.POST(path, ...)`, returning
79
+ `{ data, error, response }`:
80
+
81
+ ```ts
82
+ import { createForgeDashboardClient } from "@forge-dashboard/sdk-node";
83
+
84
+ const client = createForgeDashboardClient("https://dashboard.example.com");
85
+
86
+ const { data } = await client.GET("/api/version", {});
87
+ console.log("server version:", data?.version);
88
+ ```
89
+
90
+ Fetching your own dashboard needs a token, and demonstrates typed error
91
+ handling:
92
+
93
+ ```ts
94
+ import {
95
+ ApiError,
96
+ createForgeDashboardClient,
97
+ decodeError,
98
+ } from "@forge-dashboard/sdk-node";
99
+
100
+ const client = createForgeDashboardClient("https://dashboard.example.com", {
101
+ token: process.env.FORGE_DASHBOARD_TOKEN,
102
+ });
103
+
104
+ const { data, error, response } = await client.GET("/api/dashboard", {});
105
+ if (error) {
106
+ const apiErr = decodeError(response, error);
107
+ if (apiErr instanceof ApiError && apiErr.statusCode === 401) {
108
+ throw new Error("token expired or invalid");
109
+ }
110
+ throw apiErr;
111
+ }
112
+ for (const pr of data.pullRequests) {
113
+ console.log(`${pr.repo}#${pr.number}: ${pr.title} (${pr.ci})`);
114
+ }
115
+ ```
116
+
117
+ Every other operation follows the same `client.GET`/`client.POST`/... pattern.
118
+ Use `decodeError` to turn any failed response into a
119
+ `@forge-dashboard/sdk-node` `ApiError` uniformly, as shown above.
120
+
121
+ The client retries a `429` or `5xx` response with exponential backoff and
122
+ jitter (honoring a server-sent `Retry-After`), and never retries any other
123
+ `4xx`. Tune it with the `retry` option, or swap the underlying `fetch`
124
+ entirely with the `fetch` option.
125
+
126
+ ## Regenerating the types
127
+
128
+ See [CONTRIBUTING.md](CONTRIBUTING.md) — the generated types are pinned to a
129
+ specific forge-dashboard commit and shouldn't drift from it silently.
130
+
131
+ ## Contributing
132
+
133
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for building, testing and the release
134
+ process.
135
+
136
+ ## License
137
+
138
+ [MIT](LICENSE) — a permissive license for the client, independent of
139
+ forge-dashboard's own AGPL-3.0.
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@forge-dashboard/sdk-node",
3
+ "version": "1.1.0",
4
+ "description": "Node/TypeScript client for forge-dashboard's REST API, generated from its OpenAPI spec.",
5
+ "homepage": "https://github.com/alrayyes/forge-dashboard-sdk-node",
6
+ "bugs": "https://github.com/alrayyes/forge-dashboard-sdk-node/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/alrayyes/forge-dashboard-sdk-node.git"
10
+ },
11
+ "license": "MIT",
12
+ "type": "module",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsc -p tsconfig.build.json",
26
+ "docs": "typedoc",
27
+ "generate": "openapi-typescript openapi/openapi.yaml -o src/generated/schema.ts",
28
+ "lint": "biome check .",
29
+ "lint:fix": "biome check --write .",
30
+ "test": "bun test",
31
+ "test:ci": "bun test --coverage --coverage-reporter=lcov --reporter=junit --reporter-outfile=junit.xml",
32
+ "test:mutation": "stryker run",
33
+ "typecheck": "tsc --noEmit"
34
+ },
35
+ "overrides": {
36
+ "qs": "6.16.0",
37
+ "smol-toml": "1.8.0"
38
+ },
39
+ "dependencies": {
40
+ "openapi-fetch": "0.17.0"
41
+ },
42
+ "devDependencies": {
43
+ "@biomejs/biome": "2.5.14",
44
+ "@commitlint/cli": "21.2.2",
45
+ "@commitlint/config-conventional": "21.2.2",
46
+ "@hughescr/stryker-bun-runner": "1.4.0",
47
+ "@stryker-mutator/core": "10.0.0",
48
+ "@stryker-mutator/typescript-checker": "10.0.0",
49
+ "@types/bun": "1.4.2",
50
+ "@types/node": "26.6.1",
51
+ "openapi-typescript": "7.13.0",
52
+ "sort-package-json": "4.0.0",
53
+ "typedoc": "0.28.20",
54
+ "typescript": "6.0.3"
55
+ },
56
+ "packageManager": "bun@1.3.14",
57
+ "engines": {
58
+ "node": ">=20"
59
+ },
60
+ "publishConfig": {
61
+ "access": "public"
62
+ }
63
+ }