@kubb/studio 5.2.3 → 5.2.5

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.
@@ -327,9 +327,10 @@ declare const commandTypes: readonly ["studio:generate", "studio:connect", "stud
327
327
  */
328
328
  type ClientInfo = {
329
329
  /**
330
- * `cli` for a `kubb studio` connection from a developer's machine, `docker` for the agent image.
330
+ * `cli` for a `kubb studio` connection from a developer's machine, `docker` for the agent image,
331
+ * `ci` for a client embedded directly in an automated pipeline (no `kubb studio` process).
331
332
  */
332
- kind: 'cli' | 'docker';
333
+ kind: 'cli' | 'docker' | 'ci';
333
334
  };
334
335
  /**
335
336
  * Payload of the `agent:connect` handshake, sent when the agent attaches to a session. Carries only
@@ -458,6 +459,14 @@ type AgentPingMessage = {
458
459
  type StudioPingMessage = {
459
460
  type: 'studio:ping';
460
461
  };
462
+ /**
463
+ * Studio's acknowledgement that an `agent:connect` handshake was received and the session is
464
+ * fully registered: the connection now counts as available for job dispatch. Distinct from the
465
+ * socket merely being open, which is not yet the same thing.
466
+ */
467
+ type StudioReadyMessage = {
468
+ type: 'studio:ready';
469
+ };
461
470
  /**
462
471
  * Disconnect message sent from Studio to Agent when the session is expired or revoked.
463
472
  * The agent should close the connection without reconnecting.
@@ -548,7 +557,7 @@ type AgentConnectResponse = {
548
557
  * Every message that can cross the agent WebSocket, in either direction. Narrow it with the
549
558
  * `is*Message` guards below before reading a variant's fields.
550
559
  */
551
- type AgentMessage = CommandMessage | DataMessage | AgentConnectMessage | AgentSaveMessage | AgentPingMessage | AgentDisconnectMessage | StudioErrorMessage | StudioPingMessage | StudioDisconnectMessage;
560
+ type AgentMessage = CommandMessage | DataMessage | AgentConnectMessage | AgentSaveMessage | AgentPingMessage | AgentDisconnectMessage | StudioErrorMessage | StudioPingMessage | StudioReadyMessage | StudioDisconnectMessage;
552
561
  declare function isCommandMessage(msg: AgentMessage): msg is CommandMessage;
553
562
  /**
554
563
  * Type guard to narrow a data message to a specific event type.
@@ -563,7 +572,8 @@ declare function isCommandMessage(msg: AgentMessage): msg is CommandMessage;
563
572
  */
564
573
  declare function isDataMessage<T extends KubbHook>(msg: AgentMessage, type?: T): msg is DataMessage<T>;
565
574
  declare function isStudioPingMessage(msg: AgentMessage): msg is StudioPingMessage;
575
+ declare function isStudioReadyMessage(msg: AgentMessage): msg is StudioReadyMessage;
566
576
  declare function isDisconnectMessage(msg: AgentMessage): msg is StudioDisconnectMessage;
567
577
  //#endregion
568
- export { isCommandMessage as A, StudioConnectMessage as C, StudioPingMessage as D, StudioGenerateMessage as E, isDisconnectMessage as M, isStudioPingMessage as N, StudioSaveMessage as O, PluginView as S, StudioErrorMessage as T, DataMessagePayload as _, AgentPermissions as a, KubbHooks$1 as b, ClientInfo as c, ConfigEditOutcome as d, ConfigFileView as f, DataMessage as g, ConnectMessagePayload as h, AgentMessage as i, isDataMessage as j, commandTypes as k, CommandMessage as l, ConfigView as m, AgentConnectResponse as n, AgentPingMessage as o, ConfigRef as p, AgentDisconnectMessage as r, AgentSaveMessage as s, AgentConnectMessage as t, ConfigEdit as u, JSONKubbConfig as v, StudioDisconnectMessage as w, OptionValue as x, KubbHook as y };
569
- //# sourceMappingURL=index-V3fjg2mj.d.ts.map
578
+ export { commandTypes as A, StudioConnectMessage as C, StudioPingMessage as D, StudioGenerateMessage as E, isStudioReadyMessage as F, isDataMessage as M, isDisconnectMessage as N, StudioReadyMessage as O, isStudioPingMessage as P, PluginView as S, StudioErrorMessage as T, DataMessagePayload as _, AgentPermissions as a, KubbHooks$1 as b, ClientInfo as c, ConfigEditOutcome as d, ConfigFileView as f, DataMessage as g, ConnectMessagePayload as h, AgentMessage as i, isCommandMessage as j, StudioSaveMessage as k, CommandMessage as l, ConfigView as m, AgentConnectResponse as n, AgentPingMessage as o, ConfigRef as p, AgentDisconnectMessage as r, AgentSaveMessage as s, AgentConnectMessage as t, ConfigEdit as u, JSONKubbConfig as v, StudioDisconnectMessage as w, OptionValue as x, KubbHook as y };
579
+ //# sourceMappingURL=index-Dq2uq38g.d.ts.map
package/dist/index.cjs CHANGED
@@ -569,7 +569,7 @@ async function disconnect({ sessionId, token, studioUrl, slug }) {
569
569
  }
570
570
  //#endregion
571
571
  //#region package.json
572
- var version = "5.2.3";
572
+ var version = "5.2.5";
573
573
  //#endregion
574
574
  //#region src/hooks.ts
575
575
  /**
@@ -675,6 +675,20 @@ function toPluginName(packageName) {
675
675
  return packageName.split("/").pop() ?? packageName;
676
676
  }
677
677
  /**
678
+ * Adds the `@kubb/` scope a plugin's package carries but its `name` does not, the inverse of
679
+ * {@link toPluginName}. A name outside the `plugin-` convention is left alone, so a third-party
680
+ * plugin is not reported as one of Kubb's.
681
+ *
682
+ * @example
683
+ * ```ts
684
+ * toPackageName('plugin-ts') // '@kubb/plugin-ts'
685
+ * toPackageName('@acme/my-plugin') // '@acme/my-plugin'
686
+ * ```
687
+ */
688
+ function toPackageName(name) {
689
+ return name.startsWith("plugin-") ? `@kubb/${name}` : name;
690
+ }
691
+ /**
678
692
  * Derives the conventional named export for a `@kubb/*` plugin package from its package name.
679
693
  *
680
694
  * @example
@@ -1509,7 +1523,7 @@ const CONNECT_TIMEOUT_MS = 5e3;
1509
1523
  const eventSeqCounters = /* @__PURE__ */ new WeakMap();
1510
1524
  const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
1511
1525
  async function resolvePeerDependencies(names) {
1512
- const uniqueNames = [...new Set(names)];
1526
+ const uniqueNames = [...new Set(names.map(toPackageName))];
1513
1527
  const peerDependencies = {};
1514
1528
  const missingDependencies = [];
1515
1529
  const versions = await Promise.all(uniqueNames.map(async (name) => {
@@ -1777,6 +1791,12 @@ function setupEventsStream(ws$5, hooks) {
1777
1791
  //#endregion
1778
1792
  //#region src/StudioSession.ts
1779
1793
  /**
1794
+ * How long the `agent:connect` handshake may go unacknowledged before `studio:ready` is given up
1795
+ * on for this open. A Studio that predates the ack never sends one, so this only ever produces a
1796
+ * warning, not a reconnect.
1797
+ */
1798
+ const READY_TIMEOUT_MS = 1e4;
1799
+ /**
1780
1800
  * Fills in a host's options: the hosted Studio URL, the current working directory, and every
1781
1801
  * permission off unless granted. Idempotent, so a reconnect can pass an already-resolved bag
1782
1802
  * back in.
@@ -1847,6 +1867,7 @@ var StudioSession = class {
1847
1867
  #disposed = false;
1848
1868
  #isGenerating = false;
1849
1869
  #heartbeatTimer;
1870
+ #readyTimer;
1850
1871
  #lastPongAt = Date.now();
1851
1872
  constructor(options) {
1852
1873
  this.#options = applyStudioDefaults(options);
@@ -1955,7 +1976,7 @@ var StudioSession = class {
1955
1976
  path: configPath,
1956
1977
  file: await this.#readConfigFileView(),
1957
1978
  plugins: config.plugins.map((plugin) => ({
1958
- name: `@kubb/${plugin.name}`,
1979
+ name: toPackageName(plugin.name),
1959
1980
  options: plugin.options ?? {}
1960
1981
  }))
1961
1982
  },
@@ -1980,10 +2001,24 @@ var StudioSession = class {
1980
2001
  });
1981
2002
  try {
1982
2003
  await this.#sendConnectedPayload();
2004
+ this.#waitForReady();
1983
2005
  } catch (error) {
1984
2006
  await this.#warn(`Failed to send the connect payload: ${getErrorMessage(error)}`);
1985
2007
  }
1986
2008
  }
2009
+ /**
2010
+ * Arms the timeout for Studio's `studio:ready` acknowledgement. Re-armed on every open, since a
2011
+ * command sent while the agent is not attached is lost either way (see `#sendConnectedPayload`),
2012
+ * so each reconnect needs its own fresh wait.
2013
+ */
2014
+ #waitForReady() {
2015
+ if (this.#disposed) return;
2016
+ clearTimeout(this.#readyTimer);
2017
+ this.#readyTimer = setTimeout(() => {
2018
+ this.#readyTimer = void 0;
2019
+ Promise.resolve(this.#warn(`Kubb Studio did not confirm the connection was ready within ${READY_TIMEOUT_MS}ms`)).catch(() => {});
2020
+ }, READY_TIMEOUT_MS);
2021
+ }
1987
2022
  #onOpen = () => void this.#handleOpen().catch(() => {});
1988
2023
  #onAbort = () => void this.#end({
1989
2024
  reason: "shutdown",
@@ -2003,6 +2038,8 @@ var StudioSession = class {
2003
2038
  dispose(reason = "cleanup") {
2004
2039
  clearInterval(this.#heartbeatTimer);
2005
2040
  this.#heartbeatTimer = void 0;
2041
+ clearTimeout(this.#readyTimer);
2042
+ this.#readyTimer = void 0;
2006
2043
  try {
2007
2044
  this.#ws?.close(1e3, reason);
2008
2045
  } catch {}
@@ -2037,6 +2074,12 @@ var StudioSession = class {
2037
2074
  this.#lastPongAt = Date.now();
2038
2075
  return;
2039
2076
  }
2077
+ if (require_protocol.isStudioReadyMessage(data)) {
2078
+ clearTimeout(this.#readyTimer);
2079
+ this.#readyTimer = void 0;
2080
+ await this.#hooks.callHook("studio:ready", {});
2081
+ return;
2082
+ }
2040
2083
  if (require_protocol.isDisconnectMessage(data)) {
2041
2084
  await this.#handleDisconnect(data.reason);
2042
2085
  return;