@kubb/studio 5.2.7 → 5.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.
package/dist/index.d.ts CHANGED
@@ -114,6 +114,38 @@ export declare function waitForJob({ studioUrl, token, id, timeoutMs }: {
114
114
  */
115
115
  timeoutMs?: number;
116
116
  }): Promise<StudioJob>;
117
+ /**
118
+ * CI agent returned by {@link createAgent}. The token is issued only once, at creation or reuse.
119
+ */
120
+ type StudioAgent = {
121
+ /**
122
+ * Agent id, passed to {@link createJob} as `agentId`.
123
+ */
124
+ id: string;
125
+ /**
126
+ * Human-readable slug, used to build the readable snapshot URL and the agent's Studio page.
127
+ */
128
+ slug: string;
129
+ /**
130
+ * Agent display name.
131
+ */
132
+ name: string;
133
+ /**
134
+ * Bearer token for the WebSocket agent session. Mask it before logging.
135
+ */
136
+ token: string;
137
+ };
138
+ /**
139
+ * Creates or reuses a CI agent (`POST /api/agents`), keyed by `(organization, machineToken)`.
140
+ * Authenticates via `x-api-key`. Reusing the same `machineToken` reuses the same agent instead of
141
+ * consuming a new one from the organization's agent limit.
142
+ */
143
+ export declare function createAgent({ studioUrl, token, name, machineToken }: {
144
+ studioUrl: string;
145
+ token: string;
146
+ name: string;
147
+ machineToken: string;
148
+ }): Promise<StudioAgent>;
117
149
  //#endregion
118
150
  //#region src/StudioSession.d.ts
119
151
  type StudioSessionOptions = {
@@ -322,6 +354,11 @@ export declare function setStorage(next: Storage): void;
322
354
  * survive a restart. Repeated pairings of one machine depend on that secret staying put.
323
355
  */
324
356
  export declare function createFileStorage(base: string): Storage;
357
+ /**
358
+ * Hashes a stable secret into the machine token Studio expects, so a host can derive one from its
359
+ * own identity without duplicating `getMachineToken`'s SHA-256 step.
360
+ */
361
+ export declare function machineTokenFrom(secret: string): string;
325
362
  //#endregion
326
363
  //#region src/runConnection.d.ts
327
364
  /**
@@ -480,5 +517,5 @@ type PollOptions = {
480
517
  */
481
518
  export declare function pollForPairingToken({ studioUrl, session, signal }: PollOptions): Promise<PairingResult>;
482
519
  //#endregion
483
- export { type Client, type ClientOptions, type ConnectionOptions, type StudioConnectedContext, type StudioJob, type StudioJobStatus, type StudioSnapshot, createJobId };
520
+ export { type Client, type ClientOptions, type ConnectionOptions, type StudioAgent, type StudioConnectedContext, type StudioJob, type StudioJobStatus, type StudioSnapshot, createJobId };
484
521
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -2,12 +2,12 @@ import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
2
2
  import { createJobId, isCommandMessage, isDisconnectMessage, isStudioPingMessage, isStudioReadyMessage } from "./protocol.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { styleText } from "node:util";
5
+ import process$1 from "node:process";
6
+ import { spawn } from "node:child_process";
5
7
  import { readFile, writeFile } from "node:fs/promises";
6
8
  import path, { isAbsolute, relative, resolve } from "node:path";
7
- import { spawn } from "node:child_process";
8
9
  import { FetchError, ofetch } from "ofetch";
9
10
  import { hash, randomBytes } from "node:crypto";
10
- import process$1 from "node:process";
11
11
  import { createStorage } from "unstorage";
12
12
  import fsDriver from "unstorage/drivers/fs";
13
13
  import { Diagnostics, Hookable, createKubb, fsStorage, memoryStorage } from "@kubb/core";
@@ -406,14 +406,21 @@ async function loadOrCreateFallbackSecret() {
406
406
  return secret;
407
407
  }
408
408
  /**
409
+ * Hashes a stable secret into the machine token Studio expects, so a host can derive one from its
410
+ * own identity without duplicating `getMachineToken`'s SHA-256 step.
411
+ */
412
+ function machineTokenFrom(secret) {
413
+ return hash("sha256", secret);
414
+ }
415
+ /**
409
416
  * Returns the machine token derived from the `KUBB_AGENT_SECRET` environment variable.
410
417
  * Falls back to a generated secret persisted in the runtime storage if the env var is not set.
411
418
  * The token is hashed with SHA-256.
412
419
  */
413
420
  async function getMachineToken() {
414
- if (process$1.env.KUBB_AGENT_SECRET) return hash("sha256", process$1.env.KUBB_AGENT_SECRET);
421
+ if (process$1.env.KUBB_AGENT_SECRET) return machineTokenFrom(process$1.env.KUBB_AGENT_SECRET);
415
422
  fallbackSecretPromise ??= loadOrCreateFallbackSecret();
416
- return hash("sha256", await fallbackSecretPromise);
423
+ return machineTokenFrom(await fallbackSecretPromise);
417
424
  }
418
425
  //#endregion
419
426
  //#region src/api.ts
@@ -612,9 +619,34 @@ async function waitForJob({ studioUrl, token, id, timeoutMs = 6e4 }) {
612
619
  await new Promise((resolve) => setTimeout(resolve, 1e3));
613
620
  }
614
621
  }
622
+ /**
623
+ * Creates or reuses a CI agent (`POST /api/agents`), keyed by `(organization, machineToken)`.
624
+ * Authenticates via `x-api-key`. Reusing the same `machineToken` reuses the same agent instead of
625
+ * consuming a new one from the organization's agent limit.
626
+ */
627
+ async function createAgent({ studioUrl, token, name, machineToken }) {
628
+ try {
629
+ return await ofetch(`${studioUrl}/api/agents`, {
630
+ method: "POST",
631
+ headers: { "x-api-key": token },
632
+ body: {
633
+ name,
634
+ machineToken
635
+ }
636
+ });
637
+ } catch (error) {
638
+ if (error instanceof FetchError) {
639
+ const upgradeUrl = error.data?.data?.upgradeUrl;
640
+ const detail = responseMessage(error.data) ?? getErrorMessage(error);
641
+ const hint = upgradeUrl ? ` Agent limit reached; upgrade at ${upgradeUrl}.` : "";
642
+ throw new Error(`Failed to create a Kubb Studio agent: ${detail}${hint}`, { cause: error });
643
+ }
644
+ throw error;
645
+ }
646
+ }
615
647
  //#endregion
616
648
  //#region package.json
617
- var version = "5.2.7";
649
+ var version = "5.3.0";
618
650
  //#endregion
619
651
  //#region src/hooks.ts
620
652
  /**
@@ -2490,6 +2522,6 @@ async function pollForPairingToken({ studioUrl = agentDefaults.studioUrl, sessio
2490
2522
  throw new Error("The pairing code expired, pair again");
2491
2523
  }
2492
2524
  //#endregion
2493
- export { InvalidAgentTokenError, PairingCanceledError, createClient, createFileStorage, createJob, createJobId, defaultStudioUrl, pollForPairingToken, runConnection, setStorage, startPairing, waitForJob };
2525
+ export { InvalidAgentTokenError, PairingCanceledError, createAgent, createClient, createFileStorage, createJob, createJobId, defaultStudioUrl, machineTokenFrom, pollForPairingToken, runConnection, setStorage, startPairing, waitForJob };
2494
2526
 
2495
2527
  //# sourceMappingURL=index.js.map