@kubb/agent 5.0.0-beta.2 → 5.0.0-beta.21

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 (153) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/server/chunks/nitro/nitro.mjs +2071 -2109
  3. package/.output/server/chunks/nitro/nitro.mjs.map +1 -1
  4. package/.output/server/chunks/routes/api/health.get.mjs +1 -1
  5. package/.output/server/index.mjs +1 -1
  6. package/.output/server/node_modules/ajv/dist/2019.d.ts +1 -1
  7. package/.output/server/node_modules/ajv/dist/2019.js.map +1 -1
  8. package/.output/server/node_modules/ajv/dist/2020.d.ts +1 -1
  9. package/.output/server/node_modules/ajv/dist/2020.js.map +1 -1
  10. package/.output/server/node_modules/ajv/dist/ajv.d.ts +1 -1
  11. package/.output/server/node_modules/ajv/dist/ajv.js.map +1 -1
  12. package/.output/server/node_modules/ajv/dist/compile/index.d.ts +2 -1
  13. package/.output/server/node_modules/ajv/dist/compile/index.js +10 -3
  14. package/.output/server/node_modules/ajv/dist/compile/index.js.map +1 -1
  15. package/.output/server/node_modules/ajv/dist/compile/jtd/parse.js +1 -1
  16. package/.output/server/node_modules/ajv/dist/compile/jtd/parse.js.map +1 -1
  17. package/.output/server/node_modules/ajv/dist/compile/jtd/serialize.js +1 -1
  18. package/.output/server/node_modules/ajv/dist/compile/jtd/serialize.js.map +1 -1
  19. package/.output/server/node_modules/ajv/dist/compile/names.d.ts +1 -0
  20. package/.output/server/node_modules/ajv/dist/compile/names.js +1 -0
  21. package/.output/server/node_modules/ajv/dist/compile/names.js.map +1 -1
  22. package/.output/server/node_modules/ajv/dist/compile/validate/index.d.ts +1 -1
  23. package/.output/server/node_modules/ajv/dist/compile/validate/index.js +18 -4
  24. package/.output/server/node_modules/ajv/dist/compile/validate/index.js.map +1 -1
  25. package/.output/server/node_modules/ajv/dist/core.d.ts +4 -0
  26. package/.output/server/node_modules/ajv/dist/core.js +15 -1
  27. package/.output/server/node_modules/ajv/dist/core.js.map +1 -1
  28. package/.output/server/node_modules/ajv/dist/draft4.d.ts +19 -0
  29. package/.output/server/node_modules/ajv/dist/draft4.js +57 -0
  30. package/.output/server/node_modules/ajv/dist/draft4.js.map +1 -0
  31. package/.output/server/node_modules/ajv/dist/refs/json-schema-draft-04.json +138 -0
  32. package/.output/server/node_modules/ajv/dist/types/index.d.ts +3 -0
  33. package/.output/server/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js +2 -1
  34. package/.output/server/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js.map +1 -1
  35. package/.output/server/node_modules/ajv/dist/vocabularies/applicator/allOf.js +1 -1
  36. package/.output/server/node_modules/ajv/dist/vocabularies/applicator/allOf.js.map +1 -1
  37. package/.output/server/node_modules/ajv/dist/vocabularies/applicator/properties.js +2 -1
  38. package/.output/server/node_modules/ajv/dist/vocabularies/applicator/properties.js.map +1 -1
  39. package/.output/server/node_modules/ajv/dist/vocabularies/code.d.ts +1 -1
  40. package/.output/server/node_modules/ajv/dist/vocabularies/code.js +10 -3
  41. package/.output/server/node_modules/ajv/dist/vocabularies/code.js.map +1 -1
  42. package/.output/server/node_modules/ajv/dist/vocabularies/core/ref.js +12 -2
  43. package/.output/server/node_modules/ajv/dist/vocabularies/core/ref.js.map +1 -1
  44. package/.output/server/node_modules/ajv/dist/vocabularies/discriminator/index.js +56 -21
  45. package/.output/server/node_modules/ajv/dist/vocabularies/discriminator/index.js.map +1 -1
  46. package/.output/server/node_modules/ajv/dist/vocabularies/draft4.d.ts +3 -0
  47. package/.output/server/node_modules/ajv/dist/vocabularies/draft4.js +29 -0
  48. package/.output/server/node_modules/ajv/dist/vocabularies/draft4.js.map +1 -0
  49. package/.output/server/node_modules/ajv/dist/vocabularies/metadata.js +10 -2
  50. package/.output/server/node_modules/ajv/dist/vocabularies/metadata.js.map +1 -1
  51. package/.output/server/node_modules/ajv/dist/vocabularies/oasContext.d.ts +3 -0
  52. package/.output/server/node_modules/ajv/dist/vocabularies/oasContext.js +26 -0
  53. package/.output/server/node_modules/ajv/dist/vocabularies/oasContext.js.map +1 -0
  54. package/.output/server/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js +22 -3
  55. package/.output/server/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js.map +1 -1
  56. package/.output/server/node_modules/ajv/dist/vocabularies/validation/draft04/limitNumber.d.ts +12 -0
  57. package/.output/server/node_modules/ajv/dist/vocabularies/validation/draft04/limitNumber.js +43 -0
  58. package/.output/server/node_modules/ajv/dist/vocabularies/validation/draft04/limitNumber.js.map +1 -0
  59. package/.output/server/node_modules/ajv/dist/vocabularies/validation/draft04/limitNumberExclusive.d.ts +3 -0
  60. package/.output/server/node_modules/ajv/dist/vocabularies/validation/draft04/limitNumberExclusive.js +19 -0
  61. package/.output/server/node_modules/ajv/dist/vocabularies/validation/draft04/limitNumberExclusive.js.map +1 -0
  62. package/.output/server/node_modules/ajv/dist/vocabularies/validation/index.js +4 -0
  63. package/.output/server/node_modules/ajv/dist/vocabularies/validation/index.js.map +1 -1
  64. package/.output/server/node_modules/ajv/dist/vocabularies/validation/readOnly.d.ts +3 -0
  65. package/.output/server/node_modules/ajv/dist/vocabularies/validation/readOnly.js +20 -0
  66. package/.output/server/node_modules/ajv/dist/vocabularies/validation/readOnly.js.map +1 -0
  67. package/.output/server/node_modules/ajv/dist/vocabularies/validation/required.js +8 -1
  68. package/.output/server/node_modules/ajv/dist/vocabularies/validation/required.js.map +1 -1
  69. package/.output/server/node_modules/ajv/dist/vocabularies/validation/writeOnly.d.ts +3 -0
  70. package/.output/server/node_modules/ajv/dist/vocabularies/validation/writeOnly.js +20 -0
  71. package/.output/server/node_modules/ajv/dist/vocabularies/validation/writeOnly.js.map +1 -0
  72. package/.output/server/node_modules/ajv/lib/2019.ts +1 -0
  73. package/.output/server/node_modules/ajv/lib/2020.ts +1 -0
  74. package/.output/server/node_modules/ajv/lib/ajv.ts +1 -0
  75. package/.output/server/node_modules/ajv/lib/compile/index.ts +16 -3
  76. package/.output/server/node_modules/ajv/lib/compile/jtd/parse.ts +3 -1
  77. package/.output/server/node_modules/ajv/lib/compile/jtd/serialize.ts +3 -1
  78. package/.output/server/node_modules/ajv/lib/compile/names.ts +1 -0
  79. package/.output/server/node_modules/ajv/lib/compile/validate/index.ts +21 -4
  80. package/.output/server/node_modules/ajv/lib/core.ts +20 -1
  81. package/.output/server/node_modules/ajv/lib/draft4.ts +79 -0
  82. package/.output/server/node_modules/ajv/lib/refs/json-schema-draft-04.json +138 -0
  83. package/.output/server/node_modules/ajv/lib/types/index.ts +4 -0
  84. package/.output/server/node_modules/ajv/lib/vocabularies/applicator/additionalProperties.ts +2 -1
  85. package/.output/server/node_modules/ajv/lib/vocabularies/applicator/allOf.ts +1 -1
  86. package/.output/server/node_modules/ajv/lib/vocabularies/applicator/properties.ts +4 -1
  87. package/.output/server/node_modules/ajv/lib/vocabularies/code.ts +10 -3
  88. package/.output/server/node_modules/ajv/lib/vocabularies/core/ref.ts +21 -5
  89. package/.output/server/node_modules/ajv/lib/vocabularies/discriminator/index.ts +69 -19
  90. package/.output/server/node_modules/ajv/lib/vocabularies/draft4.ts +32 -0
  91. package/.output/server/node_modules/ajv/lib/vocabularies/metadata.ts +10 -2
  92. package/.output/server/node_modules/ajv/lib/vocabularies/oasContext.ts +27 -0
  93. package/.output/server/node_modules/ajv/lib/vocabularies/unevaluated/unevaluatedProperties.ts +29 -7
  94. package/.output/server/node_modules/ajv/lib/vocabularies/validation/draft04/limitNumber.ts +75 -0
  95. package/.output/server/node_modules/ajv/lib/vocabularies/validation/draft04/limitNumberExclusive.ts +26 -0
  96. package/.output/server/node_modules/ajv/lib/vocabularies/validation/index.ts +4 -0
  97. package/.output/server/node_modules/ajv/lib/vocabularies/validation/readOnly.ts +23 -0
  98. package/.output/server/node_modules/ajv/lib/vocabularies/validation/required.ts +7 -1
  99. package/.output/server/node_modules/ajv/lib/vocabularies/validation/writeOnly.ts +22 -0
  100. package/.output/server/node_modules/ajv/package.json +9 -6
  101. package/.output/server/node_modules/fflate/esm/index.mjs +87 -56
  102. package/.output/server/node_modules/fflate/package.json +12 -11
  103. package/.output/server/node_modules/jiti/LICENSE +21 -0
  104. package/.output/server/node_modules/jiti/README.md +258 -0
  105. package/.output/server/node_modules/jiti/dist/babel.cjs +257 -0
  106. package/.output/server/node_modules/jiti/dist/jiti.cjs +1 -0
  107. package/.output/server/node_modules/jiti/lib/jiti-cli.mjs +34 -0
  108. package/.output/server/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
  109. package/.output/server/node_modules/jiti/lib/jiti-native.mjs +121 -0
  110. package/.output/server/node_modules/jiti/lib/jiti-register.d.mts +1 -0
  111. package/.output/server/node_modules/jiti/lib/jiti-register.mjs +4 -0
  112. package/.output/server/node_modules/jiti/lib/jiti-static.mjs +23 -0
  113. package/.output/server/node_modules/jiti/lib/jiti.cjs +30 -0
  114. package/.output/server/node_modules/jiti/lib/jiti.d.cts +8 -0
  115. package/.output/server/node_modules/jiti/lib/jiti.d.mts +8 -0
  116. package/.output/server/node_modules/jiti/lib/jiti.mjs +29 -0
  117. package/.output/server/node_modules/jiti/lib/types.d.ts +420 -0
  118. package/.output/server/node_modules/jiti/package.json +146 -0
  119. package/.output/server/node_modules/remeda/dist/hasProp.js +2 -0
  120. package/.output/server/node_modules/remeda/dist/index.js +1 -1
  121. package/.output/server/node_modules/remeda/package.json +12 -12
  122. package/.output/server/node_modules/ws/lib/sender.js +6 -1
  123. package/.output/server/node_modules/ws/package.json +1 -1
  124. package/.output/server/package.json +5 -8
  125. package/README.md +62 -27
  126. package/package.json +15 -14
  127. package/.output/server/node_modules/@rolldown/binding-linux-x64-gnu/package.json +0 -40
  128. package/.output/server/node_modules/@rolldown/binding-linux-x64-gnu/rolldown-binding.linux-x64-gnu.node +0 -0
  129. package/.output/server/node_modules/@rolldown/pluginutils/dist/filter/composable-filters.js +0 -256
  130. package/.output/server/node_modules/@rolldown/pluginutils/dist/filter/filter-vite-plugins.js +0 -75
  131. package/.output/server/node_modules/@rolldown/pluginutils/dist/filter/index.js +0 -3
  132. package/.output/server/node_modules/@rolldown/pluginutils/dist/filter/simple-filters.js +0 -70
  133. package/.output/server/node_modules/@rolldown/pluginutils/dist/index.js +0 -1
  134. package/.output/server/node_modules/@rolldown/pluginutils/dist/utils.js +0 -17
  135. package/.output/server/node_modules/@rolldown/pluginutils/package.json +0 -37
  136. package/.output/server/node_modules/rolldown/dist/index.mjs +0 -50
  137. package/.output/server/node_modules/rolldown/dist/parse-ast-index.mjs +0 -60
  138. package/.output/server/node_modules/rolldown/dist/shared/binding-BeU_1iEk.mjs +0 -582
  139. package/.output/server/node_modules/rolldown/dist/shared/bindingify-input-options-DbbBhzky.mjs +0 -2211
  140. package/.output/server/node_modules/rolldown/dist/shared/define-config-DJOr6Iwt.mjs +0 -6
  141. package/.output/server/node_modules/rolldown/dist/shared/error-DL-e8-oE.mjs +0 -85
  142. package/.output/server/node_modules/rolldown/dist/shared/logs-D80CXhvg.mjs +0 -180
  143. package/.output/server/node_modules/rolldown/dist/shared/misc-DJYbNKZX.mjs +0 -21
  144. package/.output/server/node_modules/rolldown/dist/shared/normalize-string-or-regex-CbQQ69gT.mjs +0 -66
  145. package/.output/server/node_modules/rolldown/dist/shared/parse-B_ZnWxLZ.mjs +0 -74
  146. package/.output/server/node_modules/rolldown/dist/shared/prompt-U5ajztzG.mjs +0 -847
  147. package/.output/server/node_modules/rolldown/dist/shared/rolldown-D3JZ9rMt.mjs +0 -40
  148. package/.output/server/node_modules/rolldown/dist/shared/rolldown-build-DSxL8qiP.mjs +0 -3325
  149. package/.output/server/node_modules/rolldown/dist/shared/watch-Bd8v9ewv.mjs +0 -374
  150. package/.output/server/node_modules/rolldown/package.json +0 -153
  151. package/.output/server/node_modules/unrun/dist/index.mjs +0 -2
  152. package/.output/server/node_modules/unrun/dist/src-GU5PtktT.mjs +0 -887
  153. package/.output/server/node_modules/unrun/package.json +0 -125
@@ -18,7 +18,7 @@ import { deflateSync } from 'fflate';
18
18
  import { x } from 'tinyexec';
19
19
  import { access, rm, readFile as readFile$1, readdir as readdir$1, mkdir, writeFile as writeFile$1 } from 'node:fs/promises';
20
20
  import { styleText } from 'node:util';
21
- import { unrun } from 'unrun';
21
+ import { createJiti } from 'jiti';
22
22
  import { mergeDeep } from 'remeda';
23
23
  import WebSocket from 'ws';
24
24
 
@@ -90,26 +90,26 @@ function destr(value, options = {}) {
90
90
  }
91
91
  }
92
92
 
93
- const HASH_RE$1 = /#/g;
94
- const AMPERSAND_RE$1 = /&/g;
95
- const SLASH_RE$1 = /\//g;
96
- const EQUAL_RE$1 = /=/g;
97
- const PLUS_RE$1 = /\+/g;
98
- const ENC_CARET_RE$1 = /%5e/gi;
99
- const ENC_BACKTICK_RE$1 = /%60/gi;
100
- const ENC_PIPE_RE$1 = /%7c/gi;
101
- const ENC_SPACE_RE$1 = /%20/gi;
93
+ const HASH_RE = /#/g;
94
+ const AMPERSAND_RE = /&/g;
95
+ const SLASH_RE = /\//g;
96
+ const EQUAL_RE = /=/g;
97
+ const PLUS_RE = /\+/g;
98
+ const ENC_CARET_RE = /%5e/gi;
99
+ const ENC_BACKTICK_RE = /%60/gi;
100
+ const ENC_PIPE_RE = /%7c/gi;
101
+ const ENC_SPACE_RE = /%20/gi;
102
102
  const ENC_SLASH_RE = /%2f/gi;
103
- function encode$1(text) {
104
- return encodeURI("" + text).replace(ENC_PIPE_RE$1, "|");
103
+ function encode(text) {
104
+ return encodeURI("" + text).replace(ENC_PIPE_RE, "|");
105
105
  }
106
- function encodeQueryValue$1(input) {
107
- return encode$1(typeof input === "string" ? input : JSON.stringify(input)).replace(PLUS_RE$1, "%2B").replace(ENC_SPACE_RE$1, "+").replace(HASH_RE$1, "%23").replace(AMPERSAND_RE$1, "%26").replace(ENC_BACKTICK_RE$1, "`").replace(ENC_CARET_RE$1, "^").replace(SLASH_RE$1, "%2F");
106
+ function encodeQueryValue(input) {
107
+ return encode(typeof input === "string" ? input : JSON.stringify(input)).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CARET_RE, "^").replace(SLASH_RE, "%2F");
108
108
  }
109
- function encodeQueryKey$1(text) {
110
- return encodeQueryValue$1(text).replace(EQUAL_RE$1, "%3D");
109
+ function encodeQueryKey(text) {
110
+ return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
111
111
  }
112
- function decode$1(text = "") {
112
+ function decode(text = "") {
113
113
  try {
114
114
  return decodeURIComponent("" + text);
115
115
  } catch {
@@ -117,16 +117,16 @@ function decode$1(text = "") {
117
117
  }
118
118
  }
119
119
  function decodePath(text) {
120
- return decode$1(text.replace(ENC_SLASH_RE, "%252F"));
120
+ return decode(text.replace(ENC_SLASH_RE, "%252F"));
121
121
  }
122
- function decodeQueryKey$1(text) {
123
- return decode$1(text.replace(PLUS_RE$1, " "));
122
+ function decodeQueryKey(text) {
123
+ return decode(text.replace(PLUS_RE, " "));
124
124
  }
125
- function decodeQueryValue$1(text) {
126
- return decode$1(text.replace(PLUS_RE$1, " "));
125
+ function decodeQueryValue(text) {
126
+ return decode(text.replace(PLUS_RE, " "));
127
127
  }
128
128
 
129
- function parseQuery$1(parametersString = "") {
129
+ function parseQuery(parametersString = "") {
130
130
  const object = /* @__PURE__ */ Object.create(null);
131
131
  if (parametersString[0] === "?") {
132
132
  parametersString = parametersString.slice(1);
@@ -136,11 +136,11 @@ function parseQuery$1(parametersString = "") {
136
136
  if (s.length < 2) {
137
137
  continue;
138
138
  }
139
- const key = decodeQueryKey$1(s[1]);
139
+ const key = decodeQueryKey(s[1]);
140
140
  if (key === "__proto__" || key === "constructor") {
141
141
  continue;
142
142
  }
143
- const value = decodeQueryValue$1(s[2] || "");
143
+ const value = decodeQueryValue(s[2] || "");
144
144
  if (object[key] === void 0) {
145
145
  object[key] = value;
146
146
  } else if (Array.isArray(object[key])) {
@@ -151,48 +151,48 @@ function parseQuery$1(parametersString = "") {
151
151
  }
152
152
  return object;
153
153
  }
154
- function encodeQueryItem$1(key, value) {
154
+ function encodeQueryItem(key, value) {
155
155
  if (typeof value === "number" || typeof value === "boolean") {
156
156
  value = String(value);
157
157
  }
158
158
  if (!value) {
159
- return encodeQueryKey$1(key);
159
+ return encodeQueryKey(key);
160
160
  }
161
161
  if (Array.isArray(value)) {
162
162
  return value.map(
163
- (_value) => `${encodeQueryKey$1(key)}=${encodeQueryValue$1(_value)}`
163
+ (_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`
164
164
  ).join("&");
165
165
  }
166
- return `${encodeQueryKey$1(key)}=${encodeQueryValue$1(value)}`;
166
+ return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;
167
167
  }
168
- function stringifyQuery$1(query) {
169
- return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem$1(k, query[k])).filter(Boolean).join("&");
168
+ function stringifyQuery(query) {
169
+ return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join("&");
170
170
  }
171
171
 
172
- const PROTOCOL_STRICT_REGEX$1 = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/;
173
- const PROTOCOL_REGEX$1 = /^[\s\w\0+.-]{2,}:([/\\]{2})?/;
174
- const PROTOCOL_RELATIVE_REGEX$1 = /^([/\\]\s*){2,}[^/\\]/;
175
- const JOIN_LEADING_SLASH_RE$1 = /^\.?\//;
176
- function hasProtocol$1(inputString, opts = {}) {
172
+ const PROTOCOL_STRICT_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/;
173
+ const PROTOCOL_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{2})?/;
174
+ const PROTOCOL_RELATIVE_REGEX = /^([/\\]\s*){2,}[^/\\]/;
175
+ const JOIN_LEADING_SLASH_RE = /^\.?\//;
176
+ function hasProtocol(inputString, opts = {}) {
177
177
  if (typeof opts === "boolean") {
178
178
  opts = { acceptRelative: opts };
179
179
  }
180
180
  if (opts.strict) {
181
- return PROTOCOL_STRICT_REGEX$1.test(inputString);
181
+ return PROTOCOL_STRICT_REGEX.test(inputString);
182
182
  }
183
- return PROTOCOL_REGEX$1.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX$1.test(inputString) : false);
183
+ return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
184
184
  }
185
- function hasTrailingSlash$1(input = "", respectQueryAndFragment) {
185
+ function hasTrailingSlash(input = "", respectQueryAndFragment) {
186
186
  {
187
187
  return input.endsWith("/");
188
188
  }
189
189
  }
190
- function withoutTrailingSlash$1(input = "", respectQueryAndFragment) {
190
+ function withoutTrailingSlash(input = "", respectQueryAndFragment) {
191
191
  {
192
- return (hasTrailingSlash$1(input) ? input.slice(0, -1) : input) || "/";
192
+ return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
193
193
  }
194
194
  }
195
- function withTrailingSlash$1(input = "", respectQueryAndFragment) {
195
+ function withTrailingSlash(input = "", respectQueryAndFragment) {
196
196
  {
197
197
  return input.endsWith("/") ? input : input + "/";
198
198
  }
@@ -204,36 +204,54 @@ function withLeadingSlash(input = "") {
204
204
  return hasLeadingSlash(input) ? input : "/" + input;
205
205
  }
206
206
  function withBase(input, base) {
207
- if (isEmptyURL$1(base) || hasProtocol$1(input)) {
207
+ if (isEmptyURL(base) || hasProtocol(input)) {
208
208
  return input;
209
209
  }
210
- const _base = withoutTrailingSlash$1(base);
210
+ const _base = withoutTrailingSlash(base);
211
211
  if (input.startsWith(_base)) {
212
212
  const nextChar = input[_base.length];
213
213
  if (!nextChar || nextChar === "/" || nextChar === "?") {
214
214
  return input;
215
215
  }
216
216
  }
217
- return joinURL$1(_base, input);
217
+ return joinURL(_base, input);
218
+ }
219
+ function withoutBase(input, base) {
220
+ if (isEmptyURL(base)) {
221
+ return input;
222
+ }
223
+ const _base = withoutTrailingSlash(base);
224
+ if (!input.startsWith(_base)) {
225
+ return input;
226
+ }
227
+ const nextChar = input[_base.length];
228
+ if (nextChar && nextChar !== "/" && nextChar !== "?") {
229
+ return input;
230
+ }
231
+ const trimmed = input.slice(_base.length).replace(/^\/+/, "");
232
+ return "/" + trimmed;
218
233
  }
219
- function withQuery$1(input, query) {
220
- const parsed = parseURL$1(input);
221
- const mergedQuery = { ...parseQuery$1(parsed.search), ...query };
222
- parsed.search = stringifyQuery$1(mergedQuery);
223
- return stringifyParsedURL$1(parsed);
234
+ function withQuery(input, query) {
235
+ const parsed = parseURL(input);
236
+ const mergedQuery = { ...parseQuery(parsed.search), ...query };
237
+ parsed.search = stringifyQuery(mergedQuery);
238
+ return stringifyParsedURL(parsed);
239
+ }
240
+ function getQuery(input) {
241
+ return parseQuery(parseURL(input).search);
224
242
  }
225
- function isEmptyURL$1(url) {
243
+ function isEmptyURL(url) {
226
244
  return !url || url === "/";
227
245
  }
228
- function isNonEmptyURL$1(url) {
246
+ function isNonEmptyURL(url) {
229
247
  return url && url !== "/";
230
248
  }
231
- function joinURL$1(base, ...input) {
249
+ function joinURL(base, ...input) {
232
250
  let url = base || "";
233
- for (const segment of input.filter((url2) => isNonEmptyURL$1(url2))) {
251
+ for (const segment of input.filter((url2) => isNonEmptyURL(url2))) {
234
252
  if (url) {
235
- const _segment = segment.replace(JOIN_LEADING_SLASH_RE$1, "");
236
- url = withTrailingSlash$1(url) + _segment;
253
+ const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
254
+ url = withTrailingSlash(url) + _segment;
237
255
  } else {
238
256
  url = segment;
239
257
  }
@@ -241,8 +259,8 @@ function joinURL$1(base, ...input) {
241
259
  return url;
242
260
  }
243
261
 
244
- const protocolRelative$1 = Symbol.for("ufo:protocolRelative");
245
- function parseURL$1(input = "", defaultProto) {
262
+ const protocolRelative = Symbol.for("ufo:protocolRelative");
263
+ function parseURL(input = "", defaultProto) {
246
264
  const _specialProtoMatch = input.match(
247
265
  /^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i
248
266
  );
@@ -258,15 +276,15 @@ function parseURL$1(input = "", defaultProto) {
258
276
  hash: ""
259
277
  };
260
278
  }
261
- if (!hasProtocol$1(input, { acceptRelative: true })) {
262
- return parsePath$1(input);
279
+ if (!hasProtocol(input, { acceptRelative: true })) {
280
+ return parsePath(input);
263
281
  }
264
282
  const [, protocol = "", auth, hostAndPath = ""] = input.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
265
283
  let [, host = "", path = ""] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];
266
284
  if (protocol === "file:") {
267
285
  path = path.replace(/\/(?=[A-Za-z]:)/, "");
268
286
  }
269
- const { pathname, search, hash } = parsePath$1(path);
287
+ const { pathname, search, hash } = parsePath(path);
270
288
  return {
271
289
  protocol: protocol.toLowerCase(),
272
290
  auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : "",
@@ -274,10 +292,10 @@ function parseURL$1(input = "", defaultProto) {
274
292
  pathname,
275
293
  search,
276
294
  hash,
277
- [protocolRelative$1]: !protocol
295
+ [protocolRelative]: !protocol
278
296
  };
279
297
  }
280
- function parsePath$1(input = "") {
298
+ function parsePath(input = "") {
281
299
  const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
282
300
  return {
283
301
  pathname,
@@ -285,13 +303,13 @@ function parsePath$1(input = "") {
285
303
  hash
286
304
  };
287
305
  }
288
- function stringifyParsedURL$1(parsed) {
306
+ function stringifyParsedURL(parsed) {
289
307
  const pathname = parsed.pathname || "";
290
308
  const search = parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "";
291
309
  const hash = parsed.hash || "";
292
310
  const auth = parsed.auth ? parsed.auth + "@" : "";
293
311
  const host = parsed.host || "";
294
- const proto = parsed.protocol || parsed[protocolRelative$1] ? (parsed.protocol || "") + "//" : "";
312
+ const proto = parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "";
295
313
  return proto + auth + host + pathname + search + hash;
296
314
  }
297
315
 
@@ -1591,7 +1609,7 @@ function createResolver(stack) {
1591
1609
  res = {
1592
1610
  ...res,
1593
1611
  ..._res,
1594
- route: joinURL$1(res.route || "/", _res.route || "/")
1612
+ route: joinURL(res.route || "/", _res.route || "/")
1595
1613
  };
1596
1614
  }
1597
1615
  return res;
@@ -1609,7 +1627,7 @@ function normalizeLayer(input) {
1609
1627
  handler = toEventHandler(handler, void 0, input.route);
1610
1628
  }
1611
1629
  return {
1612
- route: withoutTrailingSlash$1(input.route),
1630
+ route: withoutTrailingSlash(input.route),
1613
1631
  match: input.match,
1614
1632
  handler
1615
1633
  };
@@ -1676,7 +1694,7 @@ function websocketOptions(evResolver, appOptions) {
1676
1694
  ...appOptions.websocket,
1677
1695
  async resolve(info) {
1678
1696
  const url = info.request?.url || info.url || "/";
1679
- const { pathname } = typeof url === "string" ? parseURL$1(url) : url;
1697
+ const { pathname } = typeof url === "string" ? parseURL(url) : url;
1680
1698
  const resolved = await evResolver(pathname);
1681
1699
  return resolved?.handler?.__websocket__ || {};
1682
1700
  }
@@ -2268,7 +2286,7 @@ function createFetch(globalOptions = {}) {
2268
2286
  context.request = withBase(context.request, context.options.baseURL);
2269
2287
  }
2270
2288
  if (context.options.query) {
2271
- context.request = withQuery$1(context.request, context.options.query);
2289
+ context.request = withQuery(context.request, context.options.query);
2272
2290
  delete context.options.query;
2273
2291
  }
2274
2292
  if ("query" in context.options) {
@@ -2413,269 +2431,69 @@ const Headers$1 = globalThis.Headers || s$1;
2413
2431
  const AbortController = globalThis.AbortController || i;
2414
2432
  createFetch({ fetch, Headers: Headers$1, AbortController });
2415
2433
 
2416
- const HASH_RE = /#/g;
2417
- const AMPERSAND_RE = /&/g;
2418
- const SLASH_RE = /\//g;
2419
- const EQUAL_RE = /=/g;
2420
- const PLUS_RE = /\+/g;
2421
- const ENC_CARET_RE = /%5e/gi;
2422
- const ENC_BACKTICK_RE = /%60/gi;
2423
- const ENC_PIPE_RE = /%7c/gi;
2424
- const ENC_SPACE_RE = /%20/gi;
2425
- function encode(text) {
2426
- return encodeURI("" + text).replace(ENC_PIPE_RE, "|");
2427
- }
2428
- function encodeQueryValue(input) {
2429
- return encode(typeof input === "string" ? input : JSON.stringify(input)).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CARET_RE, "^").replace(SLASH_RE, "%2F");
2430
- }
2431
- function encodeQueryKey(text) {
2432
- return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
2434
+ function wrapToPromise(value) {
2435
+ if (!value || typeof value.then !== "function") {
2436
+ return Promise.resolve(value);
2437
+ }
2438
+ return value;
2433
2439
  }
2434
- function decode(text = "") {
2440
+ function asyncCall(function_, ...arguments_) {
2435
2441
  try {
2436
- return decodeURIComponent("" + text);
2437
- } catch {
2438
- return "" + text;
2442
+ return wrapToPromise(function_(...arguments_));
2443
+ } catch (error) {
2444
+ return Promise.reject(error);
2439
2445
  }
2440
2446
  }
2441
- function decodeQueryKey(text) {
2442
- return decode(text.replace(PLUS_RE, " "));
2443
- }
2444
- function decodeQueryValue(text) {
2445
- return decode(text.replace(PLUS_RE, " "));
2447
+ function isPrimitive(value) {
2448
+ const type = typeof value;
2449
+ return value === null || type !== "object" && type !== "function";
2446
2450
  }
2447
-
2448
- function parseQuery(parametersString = "") {
2449
- const object = /* @__PURE__ */ Object.create(null);
2450
- if (parametersString[0] === "?") {
2451
- parametersString = parametersString.slice(1);
2452
- }
2453
- for (const parameter of parametersString.split("&")) {
2454
- const s = parameter.match(/([^=]+)=?(.*)/) || [];
2455
- if (s.length < 2) {
2456
- continue;
2457
- }
2458
- const key = decodeQueryKey(s[1]);
2459
- if (key === "__proto__" || key === "constructor") {
2460
- continue;
2461
- }
2462
- const value = decodeQueryValue(s[2] || "");
2463
- if (object[key] === void 0) {
2464
- object[key] = value;
2465
- } else if (Array.isArray(object[key])) {
2466
- object[key].push(value);
2467
- } else {
2468
- object[key] = [object[key], value];
2469
- }
2470
- }
2471
- return object;
2451
+ function isPureObject(value) {
2452
+ const proto = Object.getPrototypeOf(value);
2453
+ return !proto || proto.isPrototypeOf(Object);
2472
2454
  }
2473
- function encodeQueryItem(key, value) {
2474
- if (typeof value === "number" || typeof value === "boolean") {
2475
- value = String(value);
2476
- }
2477
- if (!value) {
2478
- return encodeQueryKey(key);
2479
- }
2480
- if (Array.isArray(value)) {
2481
- return value.map(
2482
- (_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`
2483
- ).join("&");
2455
+ function stringify(value) {
2456
+ if (isPrimitive(value)) {
2457
+ return String(value);
2484
2458
  }
2485
- return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;
2486
- }
2487
- function stringifyQuery(query) {
2488
- return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join("&");
2489
- }
2490
-
2491
- const PROTOCOL_STRICT_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/;
2492
- const PROTOCOL_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{2})?/;
2493
- const PROTOCOL_RELATIVE_REGEX = /^([/\\]\s*){2,}[^/\\]/;
2494
- const JOIN_LEADING_SLASH_RE = /^\.?\//;
2495
- function hasProtocol(inputString, opts = {}) {
2496
- if (typeof opts === "boolean") {
2497
- opts = { acceptRelative: opts };
2459
+ if (isPureObject(value) || Array.isArray(value)) {
2460
+ return JSON.stringify(value);
2498
2461
  }
2499
- if (opts.strict) {
2500
- return PROTOCOL_STRICT_REGEX.test(inputString);
2462
+ if (typeof value.toJSON === "function") {
2463
+ return stringify(value.toJSON());
2501
2464
  }
2502
- return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
2465
+ throw new Error("[unstorage] Cannot stringify value!");
2503
2466
  }
2504
- function hasTrailingSlash(input = "", respectQueryAndFragment) {
2505
- {
2506
- return input.endsWith("/");
2467
+ const BASE64_PREFIX = "base64:";
2468
+ function serializeRaw(value) {
2469
+ if (typeof value === "string") {
2470
+ return value;
2507
2471
  }
2472
+ return BASE64_PREFIX + base64Encode(value);
2508
2473
  }
2509
- function withoutTrailingSlash(input = "", respectQueryAndFragment) {
2510
- {
2511
- return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
2474
+ function deserializeRaw(value) {
2475
+ if (typeof value !== "string") {
2476
+ return value;
2512
2477
  }
2513
- }
2514
- function withTrailingSlash(input = "", respectQueryAndFragment) {
2515
- {
2516
- return input.endsWith("/") ? input : input + "/";
2478
+ if (!value.startsWith(BASE64_PREFIX)) {
2479
+ return value;
2517
2480
  }
2481
+ return base64Decode(value.slice(BASE64_PREFIX.length));
2518
2482
  }
2519
- function withoutBase(input, base) {
2520
- if (isEmptyURL(base)) {
2521
- return input;
2522
- }
2523
- const _base = withoutTrailingSlash(base);
2524
- if (!input.startsWith(_base)) {
2525
- return input;
2526
- }
2527
- const nextChar = input[_base.length];
2528
- if (nextChar && nextChar !== "/" && nextChar !== "?") {
2529
- return input;
2483
+ function base64Decode(input) {
2484
+ if (globalThis.Buffer) {
2485
+ return Buffer.from(input, "base64");
2530
2486
  }
2531
- const trimmed = input.slice(_base.length).replace(/^\/+/, "");
2532
- return "/" + trimmed;
2533
- }
2534
- function withQuery(input, query) {
2535
- const parsed = parseURL(input);
2536
- const mergedQuery = { ...parseQuery(parsed.search), ...query };
2537
- parsed.search = stringifyQuery(mergedQuery);
2538
- return stringifyParsedURL(parsed);
2539
- }
2540
- function getQuery(input) {
2541
- return parseQuery(parseURL(input).search);
2542
- }
2543
- function isEmptyURL(url) {
2544
- return !url || url === "/";
2545
- }
2546
- function isNonEmptyURL(url) {
2547
- return url && url !== "/";
2487
+ return Uint8Array.from(
2488
+ globalThis.atob(input),
2489
+ (c) => c.codePointAt(0)
2490
+ );
2548
2491
  }
2549
- function joinURL(base, ...input) {
2550
- let url = base || "";
2551
- for (const segment of input.filter((url2) => isNonEmptyURL(url2))) {
2552
- if (url) {
2553
- const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
2554
- url = withTrailingSlash(url) + _segment;
2555
- } else {
2556
- url = segment;
2557
- }
2492
+ function base64Encode(input) {
2493
+ if (globalThis.Buffer) {
2494
+ return Buffer.from(input).toString("base64");
2558
2495
  }
2559
- return url;
2560
- }
2561
-
2562
- const protocolRelative = Symbol.for("ufo:protocolRelative");
2563
- function parseURL(input = "", defaultProto) {
2564
- const _specialProtoMatch = input.match(
2565
- /^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i
2566
- );
2567
- if (_specialProtoMatch) {
2568
- const [, _proto, _pathname = ""] = _specialProtoMatch;
2569
- return {
2570
- protocol: _proto.toLowerCase(),
2571
- pathname: _pathname,
2572
- href: _proto + _pathname,
2573
- auth: "",
2574
- host: "",
2575
- search: "",
2576
- hash: ""
2577
- };
2578
- }
2579
- if (!hasProtocol(input, { acceptRelative: true })) {
2580
- return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
2581
- }
2582
- const [, protocol = "", auth, hostAndPath = ""] = input.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
2583
- let [, host = "", path = ""] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];
2584
- if (protocol === "file:") {
2585
- path = path.replace(/\/(?=[A-Za-z]:)/, "");
2586
- }
2587
- const { pathname, search, hash } = parsePath(path);
2588
- return {
2589
- protocol: protocol.toLowerCase(),
2590
- auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : "",
2591
- host,
2592
- pathname,
2593
- search,
2594
- hash,
2595
- [protocolRelative]: !protocol
2596
- };
2597
- }
2598
- function parsePath(input = "") {
2599
- const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
2600
- return {
2601
- pathname,
2602
- search,
2603
- hash
2604
- };
2605
- }
2606
- function stringifyParsedURL(parsed) {
2607
- const pathname = parsed.pathname || "";
2608
- const search = parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "";
2609
- const hash = parsed.hash || "";
2610
- const auth = parsed.auth ? parsed.auth + "@" : "";
2611
- const host = parsed.host || "";
2612
- const proto = parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "";
2613
- return proto + auth + host + pathname + search + hash;
2614
- }
2615
-
2616
- function wrapToPromise(value) {
2617
- if (!value || typeof value.then !== "function") {
2618
- return Promise.resolve(value);
2619
- }
2620
- return value;
2621
- }
2622
- function asyncCall(function_, ...arguments_) {
2623
- try {
2624
- return wrapToPromise(function_(...arguments_));
2625
- } catch (error) {
2626
- return Promise.reject(error);
2627
- }
2628
- }
2629
- function isPrimitive(value) {
2630
- const type = typeof value;
2631
- return value === null || type !== "object" && type !== "function";
2632
- }
2633
- function isPureObject(value) {
2634
- const proto = Object.getPrototypeOf(value);
2635
- return !proto || proto.isPrototypeOf(Object);
2636
- }
2637
- function stringify(value) {
2638
- if (isPrimitive(value)) {
2639
- return String(value);
2640
- }
2641
- if (isPureObject(value) || Array.isArray(value)) {
2642
- return JSON.stringify(value);
2643
- }
2644
- if (typeof value.toJSON === "function") {
2645
- return stringify(value.toJSON());
2646
- }
2647
- throw new Error("[unstorage] Cannot stringify value!");
2648
- }
2649
- const BASE64_PREFIX = "base64:";
2650
- function serializeRaw(value) {
2651
- if (typeof value === "string") {
2652
- return value;
2653
- }
2654
- return BASE64_PREFIX + base64Encode(value);
2655
- }
2656
- function deserializeRaw(value) {
2657
- if (typeof value !== "string") {
2658
- return value;
2659
- }
2660
- if (!value.startsWith(BASE64_PREFIX)) {
2661
- return value;
2662
- }
2663
- return base64Decode(value.slice(BASE64_PREFIX.length));
2664
- }
2665
- function base64Decode(input) {
2666
- if (globalThis.Buffer) {
2667
- return Buffer.from(input, "base64");
2668
- }
2669
- return Uint8Array.from(
2670
- globalThis.atob(input),
2671
- (c) => c.codePointAt(0)
2672
- );
2673
- }
2674
- function base64Encode(input) {
2675
- if (globalThis.Buffer) {
2676
- return Buffer.from(input).toString("base64");
2677
- }
2678
- return globalThis.btoa(String.fromCodePoint(...input));
2496
+ return globalThis.btoa(String.fromCodePoint(...input));
2679
2497
  }
2680
2498
 
2681
2499
  const storageKeyProperties = [
@@ -4608,12 +4426,17 @@ function sendToBetterStack(level, tag, message, ctx) {
4608
4426
  const fullMessage = message !== void 0 ? `[${tag}] ${message}` : tag;
4609
4427
  const context = toBetterStackContext(ctx);
4610
4428
  if (level === "error") {
4611
- client.error(fullMessage, context).then(() => client.flush());
4612
- } else if (level === "warn") {
4613
- client.warn(fullMessage, context).then(() => client.flush());
4614
- } else {
4615
- client.info(fullMessage, context).then(() => client.flush());
4429
+ client.error(fullMessage, context).then(() => client.flush()).catch(() => {
4430
+ });
4431
+ return;
4432
+ }
4433
+ if (level === "warn") {
4434
+ client.warn(fullMessage, context).then(() => client.flush()).catch(() => {
4435
+ });
4436
+ return;
4616
4437
  }
4438
+ client.info(fullMessage, context).then(() => client.flush()).catch(() => {
4439
+ });
4617
4440
  } catch (_e) {
4618
4441
  }
4619
4442
  }
@@ -4887,15 +4710,17 @@ async function disconnect({ sessionId, token, studioUrl }) {
4887
4710
  }
4888
4711
  }
4889
4712
 
4890
- var __defProp$2 = Object.defineProperty;
4891
- var __name = (target, value) => __defProp$2(target, "name", {
4892
- value,
4893
- configurable: true
4894
- });
4895
-
4896
4713
  const visitorDepths = {
4897
4714
  deep: "deep"
4898
4715
  };
4716
+ function memoize$1(store, factory) {
4717
+ return (key) => {
4718
+ if (store.has(key)) return store.get(key);
4719
+ const value = factory(key);
4720
+ store.set(key, value);
4721
+ return value;
4722
+ };
4723
+ }
4899
4724
  function trimExtName(text) {
4900
4725
  const dotIndex = text.lastIndexOf(".");
4901
4726
  if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
@@ -4910,235 +4735,136 @@ function extractRefName(ref) {
4910
4735
  var _a;
4911
4736
  return (_a = ref.split("/").at(-1)) != null ? _a : ref;
4912
4737
  }
4913
- function createLimit(concurrency) {
4914
- let active = 0;
4915
- const queue = [];
4916
- function next() {
4917
- if (active < concurrency && queue.length > 0) {
4918
- active++;
4919
- queue.shift()();
4920
- }
4738
+ function* getChildren(node, recurse) {
4739
+ var _a;
4740
+ if (node.kind === "Input") {
4741
+ yield* node.schemas;
4742
+ yield* node.operations;
4743
+ return;
4921
4744
  }
4922
- return function limit(fn) {
4923
- return new Promise((resolve, reject) => {
4924
- queue.push(() => {
4925
- Promise.resolve(fn()).then(resolve, reject).finally(() => {
4926
- active--;
4927
- next();
4928
- });
4929
- });
4930
- next();
4931
- });
4932
- };
4933
- }
4934
- function getChildren(node, recurse) {
4935
- var _a, _b, _c;
4936
- switch (node.kind) {
4937
- case "Input":
4938
- return [...node.schemas, ...node.operations];
4939
- case "Output":
4940
- return [];
4941
- case "Operation":
4942
- return [
4943
- ...node.parameters,
4944
- ...(_c = (_b = (_a = node.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b.flatMap((c) => c.schema ? [c.schema] : [])) != null ? _c : [],
4945
- ...node.responses
4946
- ];
4947
- case "Schema": {
4948
- const children = [];
4949
- if (!recurse) return [];
4950
- if ("properties" in node && node.properties.length > 0) children.push(...node.properties);
4951
- if ("items" in node && node.items) children.push(...node.items);
4952
- if ("members" in node && node.members) children.push(...node.members);
4953
- if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties);
4954
- return children;
4745
+ if (node.kind === "Output") return;
4746
+ if (node.kind === "Operation") {
4747
+ yield* node.parameters;
4748
+ if ((_a = node.requestBody) == null ? void 0 : _a.content) {
4749
+ for (const c of node.requestBody.content) if (c.schema) yield c.schema;
4955
4750
  }
4956
- case "Property":
4957
- return [node.schema];
4958
- case "Parameter":
4959
- return [node.schema];
4960
- case "Response":
4961
- return node.schema ? [node.schema] : [];
4962
- case "FunctionParameter":
4963
- case "ParameterGroup":
4964
- case "FunctionParameters":
4965
- case "Type":
4966
- return [];
4967
- default:
4968
- return [];
4751
+ yield* node.responses;
4752
+ return;
4969
4753
  }
4970
- }
4971
- async function walk(node, options) {
4972
- var _a, _b;
4973
- return _walk(node, options, ((_a = options.depth) != null ? _a : visitorDepths.deep) === visitorDepths.deep, createLimit((_b = options.concurrency) != null ? _b : 30), void 0);
4974
- }
4975
- async function _walk(node, visitor, recurse, limit, parent) {
4976
- switch (node.kind) {
4977
- case "Input":
4978
- await limit(() => {
4979
- var _a;
4980
- return (_a = visitor.input) == null ? void 0 : _a.call(visitor, node, { parent });
4981
- });
4982
- break;
4983
- case "Output":
4984
- await limit(() => {
4985
- var _a;
4986
- return (_a = visitor.output) == null ? void 0 : _a.call(visitor, node, { parent });
4987
- });
4988
- break;
4989
- case "Operation":
4990
- await limit(() => {
4991
- var _a;
4992
- return (_a = visitor.operation) == null ? void 0 : _a.call(visitor, node, { parent });
4993
- });
4994
- break;
4995
- case "Schema":
4996
- await limit(() => {
4997
- var _a;
4998
- return (_a = visitor.schema) == null ? void 0 : _a.call(visitor, node, { parent });
4999
- });
5000
- break;
5001
- case "Property":
5002
- await limit(() => {
5003
- var _a;
5004
- return (_a = visitor.property) == null ? void 0 : _a.call(visitor, node, { parent });
5005
- });
5006
- break;
5007
- case "Parameter":
5008
- await limit(() => {
5009
- var _a;
5010
- return (_a = visitor.parameter) == null ? void 0 : _a.call(visitor, node, { parent });
5011
- });
5012
- break;
5013
- case "Response":
5014
- await limit(() => {
5015
- var _a;
5016
- return (_a = visitor.response) == null ? void 0 : _a.call(visitor, node, { parent });
5017
- });
5018
- break;
4754
+ if (node.kind === "Schema") {
4755
+ if (!recurse) return;
4756
+ if ("properties" in node && node.properties.length > 0) yield* node.properties;
4757
+ if ("items" in node && node.items) yield* node.items;
4758
+ if ("members" in node && node.members) yield* node.members;
4759
+ if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) yield node.additionalProperties;
4760
+ return;
4761
+ }
4762
+ if (node.kind === "Property") {
4763
+ yield node.schema;
4764
+ return;
4765
+ }
4766
+ if (node.kind === "Parameter") {
4767
+ yield node.schema;
4768
+ return;
4769
+ }
4770
+ if (node.kind === "Response") {
4771
+ if (node.schema) yield node.schema;
4772
+ return;
5019
4773
  }
5020
- const children = getChildren(node, recurse);
5021
- for (const child of children) await _walk(child, visitor, recurse, limit, node);
5022
4774
  }
5023
4775
  function transform(node, options) {
5024
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4776
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
5025
4777
  const { depth, parent, ...visitor } = options;
5026
4778
  const recurse = (depth != null ? depth : visitorDepths.deep) === visitorDepths.deep;
5027
- switch (node.kind) {
5028
- case "Input": {
5029
- let input = node;
5030
- const replaced = (_a = visitor.input) == null ? void 0 : _a.call(visitor, input, { parent });
5031
- if (replaced) input = replaced;
5032
- return {
5033
- ...input,
5034
- schemas: input.schemas.map((s) => transform(s, {
5035
- ...options,
5036
- parent: input
5037
- })),
5038
- operations: input.operations.map((op) => transform(op, {
5039
- ...options,
5040
- parent: input
5041
- }))
5042
- };
5043
- }
5044
- case "Output": {
5045
- let output = node;
5046
- const replaced = (_b = visitor.output) == null ? void 0 : _b.call(visitor, output, { parent });
5047
- if (replaced) output = replaced;
5048
- return output;
5049
- }
5050
- case "Operation": {
5051
- let op = node;
5052
- const replaced = (_c = visitor.operation) == null ? void 0 : _c.call(visitor, op, { parent });
5053
- if (replaced) op = replaced;
5054
- return {
5055
- ...op,
5056
- parameters: op.parameters.map((p) => transform(p, {
5057
- ...options,
5058
- parent: op
5059
- })),
5060
- requestBody: op.requestBody ? {
5061
- ...op.requestBody,
5062
- content: (_d = op.requestBody.content) == null ? void 0 : _d.map((c) => ({
5063
- ...c,
5064
- schema: c.schema ? transform(c.schema, {
5065
- ...options,
5066
- parent: op
5067
- }) : void 0
5068
- }))
5069
- } : void 0,
5070
- responses: op.responses.map((r) => transform(r, {
5071
- ...options,
5072
- parent: op
4779
+ if (node.kind === "Input") {
4780
+ const input = (_b = (_a = visitor.input) == null ? void 0 : _a.call(visitor, node, { parent })) != null ? _b : node;
4781
+ return {
4782
+ ...input,
4783
+ schemas: input.schemas.map((s) => transform(s, {
4784
+ ...options,
4785
+ parent: input
4786
+ })),
4787
+ operations: input.operations.map((op) => transform(op, {
4788
+ ...options,
4789
+ parent: input
4790
+ }))
4791
+ };
4792
+ }
4793
+ if (node.kind === "Output") return (_d = (_c = visitor.output) == null ? void 0 : _c.call(visitor, node, { parent })) != null ? _d : node;
4794
+ if (node.kind === "Operation") {
4795
+ const op = (_f = (_e = visitor.operation) == null ? void 0 : _e.call(visitor, node, { parent })) != null ? _f : node;
4796
+ return {
4797
+ ...op,
4798
+ parameters: op.parameters.map((p) => transform(p, {
4799
+ ...options,
4800
+ parent: op
4801
+ })),
4802
+ requestBody: op.requestBody ? {
4803
+ ...op.requestBody,
4804
+ content: (_g = op.requestBody.content) == null ? void 0 : _g.map((c) => ({
4805
+ ...c,
4806
+ schema: c.schema ? transform(c.schema, {
4807
+ ...options,
4808
+ parent: op
4809
+ }) : void 0
5073
4810
  }))
5074
- };
5075
- }
5076
- case "Schema": {
5077
- let schema = node;
5078
- const replaced = (_e = visitor.schema) == null ? void 0 : _e.call(visitor, schema, { parent });
5079
- if (replaced) schema = replaced;
5080
- const childOptions = {
4811
+ } : void 0,
4812
+ responses: op.responses.map((r) => transform(r, {
5081
4813
  ...options,
5082
- parent: schema
5083
- };
5084
- return {
5085
- ...schema,
5086
- ..."properties" in schema && recurse ? { properties: schema.properties.map((p) => transform(p, childOptions)) } : {},
5087
- ..."items" in schema && recurse ? { items: (_f = schema.items) == null ? void 0 : _f.map((i) => transform(i, childOptions)) } : {},
5088
- ..."members" in schema && recurse ? { members: (_g = schema.members) == null ? void 0 : _g.map((m) => transform(m, childOptions)) } : {},
5089
- ..."additionalProperties" in schema && recurse && schema.additionalProperties && schema.additionalProperties !== true ? { additionalProperties: transform(schema.additionalProperties, childOptions) } : {}
5090
- };
5091
- }
5092
- case "Property": {
5093
- let prop = node;
5094
- const replaced = (_h = visitor.property) == null ? void 0 : _h.call(visitor, prop, { parent });
5095
- if (replaced) prop = replaced;
5096
- return createProperty({
5097
- ...prop,
5098
- schema: transform(prop.schema, {
5099
- ...options,
5100
- parent: prop
5101
- })
5102
- });
5103
- }
5104
- case "Parameter": {
5105
- let param = node;
5106
- const replaced = (_i = visitor.parameter) == null ? void 0 : _i.call(visitor, param, { parent });
5107
- if (replaced) param = replaced;
5108
- return createParameter({
5109
- ...param,
5110
- schema: transform(param.schema, {
5111
- ...options,
5112
- parent: param
5113
- })
5114
- });
5115
- }
5116
- case "Response": {
5117
- let response = node;
5118
- const replaced = (_j = visitor.response) == null ? void 0 : _j.call(visitor, response, { parent });
5119
- if (replaced) response = replaced;
5120
- return {
5121
- ...response,
5122
- schema: transform(response.schema, {
5123
- ...options,
5124
- parent: response
5125
- })
5126
- };
5127
- }
5128
- case "FunctionParameter":
5129
- case "ParameterGroup":
5130
- case "FunctionParameters":
5131
- case "Type":
5132
- return node;
5133
- default:
5134
- return node;
4814
+ parent: op
4815
+ }))
4816
+ };
4817
+ }
4818
+ if (node.kind === "Schema") {
4819
+ const schema = (_i = (_h = visitor.schema) == null ? void 0 : _h.call(visitor, node, { parent })) != null ? _i : node;
4820
+ const childOptions = {
4821
+ ...options,
4822
+ parent: schema
4823
+ };
4824
+ return {
4825
+ ...schema,
4826
+ ..."properties" in schema && recurse ? { properties: schema.properties.map((p) => transform(p, childOptions)) } : {},
4827
+ ..."items" in schema && recurse ? { items: (_j = schema.items) == null ? void 0 : _j.map((i) => transform(i, childOptions)) } : {},
4828
+ ..."members" in schema && recurse ? { members: (_k = schema.members) == null ? void 0 : _k.map((m) => transform(m, childOptions)) } : {},
4829
+ ..."additionalProperties" in schema && recurse && schema.additionalProperties && schema.additionalProperties !== true ? { additionalProperties: transform(schema.additionalProperties, childOptions) } : {}
4830
+ };
4831
+ }
4832
+ if (node.kind === "Property") {
4833
+ const prop = (_m = (_l = visitor.property) == null ? void 0 : _l.call(visitor, node, { parent })) != null ? _m : node;
4834
+ return createProperty({
4835
+ ...prop,
4836
+ schema: transform(prop.schema, {
4837
+ ...options,
4838
+ parent: prop
4839
+ })
4840
+ });
4841
+ }
4842
+ if (node.kind === "Parameter") {
4843
+ const param = (_o = (_n = visitor.parameter) == null ? void 0 : _n.call(visitor, node, { parent })) != null ? _o : node;
4844
+ return createParameter({
4845
+ ...param,
4846
+ schema: transform(param.schema, {
4847
+ ...options,
4848
+ parent: param
4849
+ })
4850
+ });
4851
+ }
4852
+ if (node.kind === "Response") {
4853
+ const response = (_q = (_p = visitor.response) == null ? void 0 : _p.call(visitor, node, { parent })) != null ? _q : node;
4854
+ return {
4855
+ ...response,
4856
+ schema: transform(response.schema, {
4857
+ ...options,
4858
+ parent: response
4859
+ })
4860
+ };
5135
4861
  }
4862
+ return node;
5136
4863
  }
5137
- function collect(node, options) {
4864
+ function* collectLazy(node, options) {
5138
4865
  var _a, _b, _c, _d, _e, _f, _g;
5139
4866
  const { depth, parent, ...visitor } = options;
5140
4867
  const recurse = (depth != null ? depth : visitorDepths.deep) === visitorDepths.deep;
5141
- const results = [];
5142
4868
  let v;
5143
4869
  switch (node.kind) {
5144
4870
  case "Input":
@@ -5163,12 +4889,14 @@ function collect(node, options) {
5163
4889
  v = (_g = visitor.response) == null ? void 0 : _g.call(visitor, node, { parent });
5164
4890
  break;
5165
4891
  }
5166
- if (v !== void 0) results.push(v);
5167
- for (const child of getChildren(node, recurse)) for (const item of collect(child, {
4892
+ if (v != null) yield v;
4893
+ for (const child of getChildren(node, recurse)) yield* collectLazy(child, {
5168
4894
  ...options,
5169
4895
  parent: node
5170
- })) results.push(item);
5171
- return results;
4896
+ });
4897
+ }
4898
+ function collect(node, options) {
4899
+ return Array.from(collectLazy(node, options));
5172
4900
  }
5173
4901
  function sourceKey(source) {
5174
4902
  var _a, _b, _c;
@@ -5199,11 +4927,11 @@ function combineSources(sources) {
5199
4927
  }
5200
4928
  return [...seen.values()];
5201
4929
  }
5202
- function combineExports(exports$1) {
4930
+ function combineExports(exports) {
5203
4931
  const result = [];
5204
4932
  const namedByPath = /* @__PURE__ */ new Map();
5205
4933
  const seen = /* @__PURE__ */ new Set();
5206
- const keyed = exports$1.map((node) => ({
4934
+ const keyed = exports.map((node) => ({
5207
4935
  node,
5208
4936
  key: sortKey(node)
5209
4937
  }));
@@ -5236,9 +4964,17 @@ function combineExports(exports$1) {
5236
4964
  }
5237
4965
  return result;
5238
4966
  }
5239
- function combineImports(imports, exports$1, source) {
5240
- const exportedNames = new Set(exports$1.flatMap((e) => Array.isArray(e.name) ? e.name : e.name ? [e.name] : []));
4967
+ function combineImports(imports, exports, source) {
4968
+ const exportedNames = new Set(exports.flatMap((e) => Array.isArray(e.name) ? e.name : e.name ? [e.name] : []));
5241
4969
  const isUsed = (importName) => !source || source.includes(importName) || exportedNames.has(importName);
4970
+ const importNameMemo = /* @__PURE__ */ new Map();
4971
+ const canonicalizeName = (n) => {
4972
+ var _a;
4973
+ if (typeof n === "string") return n;
4974
+ const key = `${n.propertyName}:${(_a = n.name) != null ? _a : ""}`;
4975
+ if (!importNameMemo.has(key)) importNameMemo.set(key, n);
4976
+ return importNameMemo.get(key);
4977
+ };
5242
4978
  const result = [];
5243
4979
  const namedByPath = /* @__PURE__ */ new Map();
5244
4980
  const seen = /* @__PURE__ */ new Set();
@@ -5252,7 +4988,7 @@ function combineImports(imports, exports$1, source) {
5252
4988
  const { path: path2, isTypeOnly } = curr;
5253
4989
  let { name } = curr;
5254
4990
  if (Array.isArray(name)) {
5255
- name = [...new Set(name)].filter((item) => {
4991
+ name = [...new Set(name.map(canonicalizeName))].filter((item) => {
5256
4992
  var _a;
5257
4993
  return typeof item === "string" ? isUsed(item) : isUsed((_a = item.name) != null ? _a : item.propertyName);
5258
4994
  });
@@ -5301,21 +5037,27 @@ function extractStringsFromNodes(nodes) {
5301
5037
  }
5302
5038
  function resolveRefName(node) {
5303
5039
  var _a, _b, _c, _d, _e, _f, _g;
5304
- if (!node || node.type !== "ref") return void 0;
5305
- if (node.ref) return (_d = (_c = (_a = extractRefName(node.ref)) != null ? _a : node.name) != null ? _c : (_b = node.schema) == null ? void 0 : _b.name) != null ? _d : void 0;
5306
- return (_g = (_f = node.name) != null ? _f : (_e = node.schema) == null ? void 0 : _e.name) != null ? _g : void 0;
5040
+ if (!node || node.type !== "ref") return null;
5041
+ if (node.ref) return (_d = (_c = (_a = extractRefName(node.ref)) != null ? _a : node.name) != null ? _c : (_b = node.schema) == null ? void 0 : _b.name) != null ? _d : null;
5042
+ return (_g = (_f = node.name) != null ? _f : (_e = node.schema) == null ? void 0 : _e.name) != null ? _g : null;
5307
5043
  }
5308
- function collectReferencedSchemaNames(node, out = /* @__PURE__ */ new Set()) {
5309
- if (!node) return out;
5044
+ const collectSchemaRefs = memoize$1(/* @__PURE__ */ new WeakMap(), (node) => {
5045
+ const refs = /* @__PURE__ */ new Set();
5310
5046
  collect(node, { schema(child) {
5311
5047
  if (child.type === "ref") {
5312
5048
  const name = resolveRefName(child);
5313
- if (name) out.add(name);
5049
+ if (name) refs.add(name);
5314
5050
  }
5315
5051
  } });
5052
+ return refs;
5053
+ });
5054
+ function collectReferencedSchemaNames(node, out = /* @__PURE__ */ new Set()) {
5055
+ if (!node) return out;
5056
+ for (const name of collectSchemaRefs(node)) out.add(name);
5316
5057
  return out;
5317
5058
  }
5318
- function collectUsedSchemaNames(operations, schemas) {
5059
+ const collectUsedSchemaNamesMemo = memoize$1(/* @__PURE__ */ new WeakMap(), (ops) => memoize$1(/* @__PURE__ */ new WeakMap(), (schemas) => computeUsedSchemaNames(ops, schemas)));
5060
+ function computeUsedSchemaNames(operations, schemas) {
5319
5061
  const schemaMap = /* @__PURE__ */ new Map();
5320
5062
  for (const schema of schemas) if (schema.name) schemaMap.set(schema.name, schema);
5321
5063
  const result = /* @__PURE__ */ new Set();
@@ -5327,12 +5069,15 @@ function collectUsedSchemaNames(operations, schemas) {
5327
5069
  if (namedSchema) visitSchema(namedSchema);
5328
5070
  }
5329
5071
  }
5330
- for (const op of operations) for (const schema of collect(op, {
5072
+ for (const op of operations) for (const schema of collectLazy(op, {
5331
5073
  depth: "shallow",
5332
5074
  schema: (node) => node
5333
5075
  })) visitSchema(schema);
5334
5076
  return result;
5335
5077
  }
5078
+ function collectUsedSchemaNames(operations, schemas) {
5079
+ return collectUsedSchemaNamesMemo(operations)(schemas);
5080
+ }
5336
5081
  function syncOptionality(schema, required) {
5337
5082
  var _a;
5338
5083
  const nullable = (_a = schema.nullable) != null ? _a : false;
@@ -5342,6 +5087,14 @@ function syncOptionality(schema, required) {
5342
5087
  nullish: !required && nullable ? true : void 0
5343
5088
  };
5344
5089
  }
5090
+ function createStreamInput(schemas, operations, meta) {
5091
+ return {
5092
+ kind: "Input",
5093
+ schemas,
5094
+ operations,
5095
+ meta
5096
+ };
5097
+ }
5345
5098
  function createProperty(props) {
5346
5099
  var _a;
5347
5100
  const required = (_a = props.required) != null ? _a : false;
@@ -5397,15 +5150,123 @@ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "rea
5397
5150
  var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
5398
5151
  var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
5399
5152
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
5400
- var _cache, _filesCache, _FileManager_instances, store_fn, _a$1, _studioIsOpen, _pluginsWithEventGenerators, _resolvers, _defaultResolvers, _hookListeners, _PluginDriver_instances, normalizePlugin_fn, trackHookListener_fn, createDefaultResolver_fn, _b$1;
5401
- function toCamelOrPascal(text, pascal) {
5402
- return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
5403
- if (word.length > 1 && word === word.toUpperCase()) return word;
5404
- if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
5405
- return word.charAt(0).toUpperCase() + word.slice(1);
5406
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
5407
- }
5408
- function applyToFileParts(text, transformPart) {
5153
+ var _emitter, _AsyncEventEmitter_instances, emitAll_fn, _a$1, _options, _URLPath_instances, transformParam_fn, eachParam_fn, _b, _cache, _sorted, _onUpsert, _FileManager_instances, store_fn, dedupe_fn, _c, _studio, _middlewareListeners, _fileProcessor, _eventGeneratorPlugins, _resolvers, _defaultResolvers, _hookListeners, _KubbDriver_instances, normalizePlugin_fn, registerAdapter_fn, registerMiddleware_fn, registerPlugin_fn, filesPayload_fn, emitPluginEnd_fn, runGenerators_fn, trackHookListener_fn, _getDefaultResolver, _d;
5154
+ var BuildError = class extends Error {
5155
+ constructor(message, options) {
5156
+ super(message, { cause: options.cause });
5157
+ __publicField$1(this, "errors");
5158
+ this.name = "BuildError";
5159
+ this.errors = options.errors;
5160
+ }
5161
+ };
5162
+ function toError(value) {
5163
+ return value instanceof Error ? value : new Error(String(value));
5164
+ }
5165
+ var AsyncEventEmitter = (_a$1 = class {
5166
+ /**
5167
+ * Maximum number of listeners per event before Node emits a memory-leak warning.
5168
+ * @default 10
5169
+ */
5170
+ constructor(maxListener = 10) {
5171
+ __privateAdd$1(this, _AsyncEventEmitter_instances);
5172
+ __privateAdd$1(this, _emitter, new EventEmitter());
5173
+ __privateGet$1(this, _emitter).setMaxListeners(maxListener);
5174
+ }
5175
+ /**
5176
+ * Emits `eventName` and awaits all registered listeners sequentially.
5177
+ * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
5178
+ *
5179
+ * @example
5180
+ * ```ts
5181
+ * await emitter.emit('build', 'petstore')
5182
+ * ```
5183
+ */
5184
+ emit(eventName, ...eventArgs) {
5185
+ const listeners = __privateGet$1(this, _emitter).listeners(eventName);
5186
+ if (listeners.length === 0) return;
5187
+ return __privateMethod$1(this, _AsyncEventEmitter_instances, emitAll_fn).call(this, eventName, listeners, eventArgs);
5188
+ }
5189
+ /**
5190
+ * Registers a persistent listener for `eventName`.
5191
+ *
5192
+ * @example
5193
+ * ```ts
5194
+ * emitter.on('build', async (name) => { console.log(name) })
5195
+ * ```
5196
+ */
5197
+ on(eventName, handler) {
5198
+ __privateGet$1(this, _emitter).on(eventName, handler);
5199
+ }
5200
+ /**
5201
+ * Registers a one-shot listener that removes itself after the first invocation.
5202
+ *
5203
+ * @example
5204
+ * ```ts
5205
+ * emitter.onOnce('build', async (name) => { console.log(name) })
5206
+ * ```
5207
+ */
5208
+ onOnce(eventName, handler) {
5209
+ const wrapper = (...args) => {
5210
+ this.off(eventName, wrapper);
5211
+ return handler(...args);
5212
+ };
5213
+ this.on(eventName, wrapper);
5214
+ }
5215
+ /**
5216
+ * Removes a previously registered listener.
5217
+ *
5218
+ * @example
5219
+ * ```ts
5220
+ * emitter.off('build', handler)
5221
+ * ```
5222
+ */
5223
+ off(eventName, handler) {
5224
+ __privateGet$1(this, _emitter).off(eventName, handler);
5225
+ }
5226
+ /**
5227
+ * Returns the number of listeners registered for `eventName`.
5228
+ *
5229
+ * @example
5230
+ * ```ts
5231
+ * emitter.on('build', handler)
5232
+ * emitter.listenerCount('build') // 1
5233
+ * ```
5234
+ */
5235
+ listenerCount(eventName) {
5236
+ return __privateGet$1(this, _emitter).listenerCount(eventName);
5237
+ }
5238
+ /**
5239
+ * Removes all listeners from every event channel.
5240
+ *
5241
+ * @example
5242
+ * ```ts
5243
+ * emitter.removeAll()
5244
+ * ```
5245
+ */
5246
+ removeAll() {
5247
+ __privateGet$1(this, _emitter).removeAllListeners();
5248
+ }
5249
+ }, _emitter = new WeakMap(), _AsyncEventEmitter_instances = new WeakSet(), emitAll_fn = async function(eventName, listeners, eventArgs) {
5250
+ for (const listener of listeners) try {
5251
+ await listener(...eventArgs);
5252
+ } catch (err) {
5253
+ let serializedArgs;
5254
+ try {
5255
+ serializedArgs = JSON.stringify(eventArgs);
5256
+ } catch {
5257
+ serializedArgs = String(eventArgs);
5258
+ }
5259
+ throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
5260
+ }
5261
+ }, _a$1);
5262
+ function toCamelOrPascal(text, pascal) {
5263
+ return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
5264
+ if (word.length > 1 && word === word.toUpperCase()) return word;
5265
+ if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
5266
+ return word.charAt(0).toUpperCase() + word.slice(1);
5267
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
5268
+ }
5269
+ function applyToFileParts(text, transformPart) {
5409
5270
  const parts = text.split(/\.(?=[a-zA-Z])/);
5410
5271
  return parts.map((part, i) => transformPart(part, i === parts.length - 1)).filter(Boolean).join("/");
5411
5272
  }
@@ -5423,1170 +5284,1533 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
5423
5284
  }) : camelCase(part));
5424
5285
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
5425
5286
  }
5426
- const DEFAULT_STUDIO_URL = "https://studio.kubb.dev";
5427
- const DEFAULT_BANNER = "simple";
5428
- const DEFAULT_EXTENSION = { ".ts": ".ts" };
5429
- const stringPatternCache = /* @__PURE__ */ new Map();
5430
- function testPattern(value, pattern) {
5431
- if (typeof pattern === "string") {
5432
- let regex = stringPatternCache.get(pattern);
5433
- if (!regex) {
5434
- regex = new RegExp(pattern);
5435
- stringPatternCache.set(pattern, regex);
5436
- }
5437
- return regex.test(value);
5438
- }
5439
- return value.match(pattern) !== null;
5440
- }
5441
- function matchesOperationPattern(node, type, pattern) {
5442
- var _a2, _b2, _c;
5443
- switch (type) {
5444
- case "tag":
5445
- return node.tags.some((tag) => testPattern(tag, pattern));
5446
- case "operationId":
5447
- return testPattern(node.operationId, pattern);
5448
- case "path":
5449
- return testPattern(node.path, pattern);
5450
- case "method":
5451
- return testPattern(node.method.toLowerCase(), pattern);
5452
- case "contentType":
5453
- return (_c = (_b2 = (_a2 = node.requestBody) == null ? void 0 : _a2.content) == null ? void 0 : _b2.some((c) => testPattern(c.contentType, pattern))) != null ? _c : false;
5454
- default:
5455
- return false;
5456
- }
5287
+ function getElapsedMs(hrStart) {
5288
+ const [seconds, nanoseconds] = process.hrtime(hrStart);
5289
+ const ms = seconds * 1e3 + nanoseconds / 1e6;
5290
+ return Math.round(ms * 100) / 100;
5457
5291
  }
5458
- function matchesSchemaPattern(node, type, pattern) {
5459
- switch (type) {
5460
- case "schemaName":
5461
- return node.name ? testPattern(node.name, pattern) : false;
5462
- default:
5463
- return null;
5464
- }
5292
+ function formatMs(ms) {
5293
+ if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
5294
+ if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
5295
+ return `${Math.round(ms)}ms`;
5465
5296
  }
5466
- function defaultResolver(name, type) {
5467
- let resolvedName = camelCase(name);
5468
- if (type === "file" || type === "function") resolvedName = camelCase(name, { isFile: type === "file" });
5469
- if (type === "type") resolvedName = pascalCase(name);
5470
- return resolvedName;
5297
+ function* chunks(arr, size) {
5298
+ for (let i = 0; i < arr.length; i += size) yield arr.slice(i, i + size);
5471
5299
  }
5472
- function defaultResolveOptions(node, { options, exclude = [], include, override = [] }) {
5473
- var _a2, _b2;
5474
- if (isOperationNode(node)) {
5475
- if (exclude.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
5476
- if (include && !include.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
5477
- const overrideOptions = (_a2 = override.find(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) == null ? void 0 : _a2.options;
5478
- return {
5479
- ...options,
5480
- ...overrideOptions
5481
- };
5482
- }
5483
- if (isSchemaNode(node)) {
5484
- if (exclude.some(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) return null;
5485
- if (include) {
5486
- const applicable = include.map(({ type, pattern }) => matchesSchemaPattern(node, type, pattern)).filter((r) => r !== null);
5487
- if (applicable.length > 0 && !applicable.includes(true)) return null;
5300
+ async function forBatches(source, process2, options) {
5301
+ const { concurrency, flush } = options;
5302
+ if (Array.isArray(source)) {
5303
+ for (const batch2 of chunks(source, concurrency)) {
5304
+ await process2(batch2);
5305
+ if (flush) await flush();
5488
5306
  }
5489
- const overrideOptions = (_b2 = override.find(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) == null ? void 0 : _b2.options;
5490
- return {
5491
- ...options,
5492
- ...overrideOptions
5493
- };
5307
+ return;
5494
5308
  }
5495
- return options;
5496
- }
5497
- function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }, { root, output, group }) {
5498
- var _a2;
5499
- if ((pathMode != null ? pathMode : PluginDriver.getMode(path$1.resolve(root, output.path))) === "single") return path$1.resolve(root, output.path);
5500
- let result;
5501
- if (group && (groupPath || tag)) {
5502
- const groupValue = group.type === "path" ? groupPath : tag;
5503
- const defaultName = group.type === "tag" ? ({ group: g }) => `${camelCase(g)}Controller` : ({ group: g }) => {
5504
- const segment = g.split("/").filter((s) => s !== "" && s !== "." && s !== "..")[0];
5505
- return segment ? camelCase(segment) : "";
5506
- };
5507
- const resolveName = (_a2 = group.name) != null ? _a2 : defaultName;
5508
- result = path$1.resolve(root, output.path, resolveName({ group: groupValue }), baseName);
5509
- } else result = path$1.resolve(root, output.path, baseName);
5510
- const outputDir = path$1.resolve(root, output.path);
5511
- const outputDirWithSep = outputDir.endsWith(path$1.sep) ? outputDir : `${outputDir}${path$1.sep}`;
5512
- if (result !== outputDir && !result.startsWith(outputDirWithSep)) throw new Error(`[Kubb] Resolved path "${result}" is outside the output directory "${outputDir}". This may indicate a path traversal attempt in the OpenAPI specification or a misconfigured group.name function.`);
5513
- return result;
5514
- }
5515
- function defaultResolveFile({ name, extname: extname2, tag, path: groupPath }, context, ctx) {
5516
- const pathMode = PluginDriver.getMode(path$1.resolve(context.root, context.output.path));
5517
- const baseName = `${pathMode === "single" ? "" : ctx.default(name, "file")}${extname2}`;
5518
- const filePath = ctx.resolvePath({
5519
- baseName,
5520
- pathMode,
5521
- tag,
5522
- path: groupPath
5523
- }, context);
5524
- return createFile({
5525
- path: filePath,
5526
- baseName: path$1.basename(filePath),
5527
- meta: { pluginName: ctx.pluginName },
5528
- sources: [],
5529
- imports: [],
5530
- exports: []
5531
- });
5532
- }
5533
- function buildDefaultBanner({ title, description, version, config }) {
5534
- try {
5535
- let source = "";
5536
- if (Array.isArray(config.input)) {
5537
- const first = config.input[0];
5538
- if (first && "path" in first) source = path$1.basename(first.path);
5539
- } else if ("path" in config.input) source = path$1.basename(config.input.path);
5540
- else if ("data" in config.input) source = "text content";
5541
- let banner = "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n";
5542
- if (config.output.defaultBanner === "simple") {
5543
- banner += "*/\n";
5544
- return banner;
5545
- }
5546
- if (source) banner += `* Source: ${source}
5547
- `;
5548
- if (title) banner += `* Title: ${title}
5549
- `;
5550
- if (description) {
5551
- const formattedDescription = description.replace(/\n/gm, "\n* ");
5552
- banner += `* Description: ${formattedDescription}
5553
- `;
5309
+ const batch = [];
5310
+ for await (const item of source) {
5311
+ batch.push(item);
5312
+ if (batch.length >= concurrency) {
5313
+ await process2(batch.splice(0));
5314
+ if (flush) await flush();
5554
5315
  }
5555
- if (version) banner += `* OpenAPI spec version: ${version}
5556
- `;
5557
- banner += "*/\n";
5558
- return banner;
5559
- } catch (_error) {
5560
- return "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/";
5561
5316
  }
5562
- }
5563
- function defaultResolveBanner(node, { output, config }) {
5564
- var _a2, _b2;
5565
- if (typeof (output == null ? void 0 : output.banner) === "function") return output.banner(node);
5566
- if (typeof (output == null ? void 0 : output.banner) === "string") return output.banner;
5567
- if (config.output.defaultBanner === false) return;
5568
- return buildDefaultBanner({
5569
- title: (_a2 = node == null ? void 0 : node.meta) == null ? void 0 : _a2.title,
5570
- version: (_b2 = node == null ? void 0 : node.meta) == null ? void 0 : _b2.version,
5571
- config
5572
- });
5573
- }
5574
- function defaultResolveFooter(node, { output }) {
5575
- if (typeof (output == null ? void 0 : output.footer) === "function") return node ? output.footer(node) : void 0;
5576
- if (typeof (output == null ? void 0 : output.footer) === "string") return output.footer;
5577
- }
5578
- function defineResolver(build) {
5579
- const resolver = {};
5580
- Object.assign(resolver, {
5581
- default: defaultResolver,
5582
- resolveOptions: defaultResolveOptions,
5583
- resolvePath: defaultResolvePath,
5584
- resolveFile: (params, context) => defaultResolveFile(params, context, resolver),
5585
- resolveBanner: defaultResolveBanner,
5586
- resolveFooter: defaultResolveFooter,
5587
- ...build(resolver)
5588
- });
5589
- return resolver;
5590
- }
5591
- function encodeAst(input) {
5592
- const compressed = deflateSync(new TextEncoder().encode(JSON.stringify(input)));
5593
- return Buffer.from(compressed).toString("base64url");
5594
- }
5595
- function getStudioUrl(input, studioUrl, options = {}) {
5596
- return `${studioUrl.replace(/\/$/, "")}${options.ast ? "/ast" : ""}?root=${encodeAst(input)}`;
5597
- }
5598
- async function openInStudio(input, studioUrl, options = {}) {
5599
- const url = getStudioUrl(input, studioUrl, options);
5600
- const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
5601
- const args = process.platform === "win32" ? [
5602
- "/c",
5603
- "start",
5604
- "",
5605
- url
5606
- ] : [url];
5607
- try {
5608
- await x(cmd, args);
5609
- } catch {
5610
- console.log(`
5611
- ${url}
5612
- `);
5317
+ if (batch.length > 0) {
5318
+ await process2(batch.splice(0));
5319
+ if (flush) await flush();
5613
5320
  }
5614
5321
  }
5615
- function mergeFile(a, b) {
5616
- return {
5617
- ...a,
5618
- banner: b.banner,
5619
- footer: b.footer,
5620
- sources: [...a.sources || [], ...b.sources || []],
5621
- imports: [...a.imports || [], ...b.imports || []],
5622
- exports: [...a.exports || [], ...b.exports || []]
5322
+ function isPromise(result) {
5323
+ return result !== null && result !== void 0 && typeof result["then"] === "function";
5324
+ }
5325
+ function memoize(store, factory) {
5326
+ return (key) => {
5327
+ if (store.has(key)) return store.get(key);
5328
+ const value = factory(key);
5329
+ store.set(key, value);
5330
+ return value;
5623
5331
  };
5624
5332
  }
5625
- function mergeFilesByPath(files) {
5626
- const merged = /* @__PURE__ */ new Map();
5627
- for (const file of files) {
5628
- const existing = merged.get(file.path);
5629
- merged.set(file.path, existing ? mergeFile(existing, file) : file);
5630
- }
5631
- return merged;
5333
+ function arrayToAsyncIterable(arr) {
5334
+ return { [Symbol.asyncIterator]() {
5335
+ return (async function* () {
5336
+ yield* arr;
5337
+ })();
5338
+ } };
5632
5339
  }
5633
- var FileManager = (_a$1 = class {
5634
- constructor() {
5635
- __privateAdd$1(this, _FileManager_instances);
5636
- __privateAdd$1(this, _cache, /* @__PURE__ */ new Map());
5637
- __privateAdd$1(this, _filesCache, null);
5638
- }
5639
- /**
5640
- * Adds one or more files. Incoming files with the same path are merged
5641
- * (sources/imports/exports concatenated), but existing cache entries are
5642
- * replaced — use {@link upsert} when you want to merge into the cache too.
5643
- */
5644
- add(...files) {
5645
- return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, false);
5646
- }
5647
- /**
5648
- * Adds or merges one or more files.
5649
- * If a file with the same path already exists in the cache, its
5650
- * sources/imports/exports are merged into the incoming file.
5651
- */
5652
- upsert(...files) {
5653
- return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, true);
5654
- }
5655
- getByPath(path2) {
5656
- var _a2;
5657
- return (_a2 = __privateGet$1(this, _cache).get(path2)) != null ? _a2 : null;
5658
- }
5659
- deleteByPath(path2) {
5660
- __privateGet$1(this, _cache).delete(path2);
5661
- __privateSet$1(this, _filesCache, null);
5662
- }
5663
- clear() {
5664
- __privateGet$1(this, _cache).clear();
5665
- __privateSet$1(this, _filesCache, null);
5666
- }
5667
- /**
5668
- * All stored files, sorted by path length (shorter paths first).
5669
- */
5670
- get files() {
5671
- if (__privateGet$1(this, _filesCache)) return __privateGet$1(this, _filesCache);
5672
- __privateSet$1(this, _filesCache, [...__privateGet$1(this, _cache).values()].sort((a, b) => {
5673
- const lenDiff = a.path.length - b.path.length;
5674
- if (lenDiff !== 0) return lenDiff;
5675
- const aIsIndex = a.path.endsWith("/index.ts") || a.path === "index.ts";
5676
- const bIsIndex = b.path.endsWith("/index.ts") || b.path === "index.ts";
5677
- if (aIsIndex && !bIsIndex) return 1;
5678
- if (!aIsIndex && bIsIndex) return -1;
5679
- return 0;
5680
- }));
5681
- return __privateGet$1(this, _filesCache);
5682
- }
5683
- }, _cache = new WeakMap(), _filesCache = new WeakMap(), _FileManager_instances = new WeakSet(), store_fn = function(files, mergeExisting) {
5684
- const resolvedFiles = [];
5685
- for (const file of mergeFilesByPath(files).values()) {
5686
- const existing = mergeExisting ? __privateGet$1(this, _cache).get(file.path) : void 0;
5687
- const resolvedFile = createFile(existing ? mergeFile(existing, file) : file);
5688
- __privateGet$1(this, _cache).set(resolvedFile.path, resolvedFile);
5689
- resolvedFiles.push(resolvedFile);
5690
- }
5691
- __privateSet$1(this, _filesCache, null);
5692
- return resolvedFiles;
5693
- }, _a$1);
5694
- async function applyHookResult(result, driver, rendererFactory) {
5695
- if (!result) return;
5696
- if (Array.isArray(result)) {
5697
- driver.fileManager.upsert(...result);
5698
- return;
5699
- }
5700
- if (!rendererFactory) return;
5701
- const renderer = rendererFactory();
5702
- await renderer.render(result);
5703
- driver.fileManager.upsert(...renderer.files);
5704
- renderer.unmount();
5705
- }
5706
- function enforceOrder(enforce) {
5707
- return enforce === "pre" ? -1 : enforce === "post" ? 1 : 0;
5340
+ const reservedWords = /* @__PURE__ */ new Set([
5341
+ "abstract",
5342
+ "arguments",
5343
+ "boolean",
5344
+ "break",
5345
+ "byte",
5346
+ "case",
5347
+ "catch",
5348
+ "char",
5349
+ "class",
5350
+ "const",
5351
+ "continue",
5352
+ "debugger",
5353
+ "default",
5354
+ "delete",
5355
+ "do",
5356
+ "double",
5357
+ "else",
5358
+ "enum",
5359
+ "eval",
5360
+ "export",
5361
+ "extends",
5362
+ "false",
5363
+ "final",
5364
+ "finally",
5365
+ "float",
5366
+ "for",
5367
+ "function",
5368
+ "goto",
5369
+ "if",
5370
+ "implements",
5371
+ "import",
5372
+ "in",
5373
+ "instanceof",
5374
+ "int",
5375
+ "interface",
5376
+ "let",
5377
+ "long",
5378
+ "native",
5379
+ "new",
5380
+ "null",
5381
+ "package",
5382
+ "private",
5383
+ "protected",
5384
+ "public",
5385
+ "return",
5386
+ "short",
5387
+ "static",
5388
+ "super",
5389
+ "switch",
5390
+ "synchronized",
5391
+ "this",
5392
+ "throw",
5393
+ "throws",
5394
+ "transient",
5395
+ "true",
5396
+ "try",
5397
+ "typeof",
5398
+ "var",
5399
+ "void",
5400
+ "volatile",
5401
+ "while",
5402
+ "with",
5403
+ "yield",
5404
+ "Array",
5405
+ "Date",
5406
+ "hasOwnProperty",
5407
+ "Infinity",
5408
+ "isFinite",
5409
+ "isNaN",
5410
+ "isPrototypeOf",
5411
+ "length",
5412
+ "Math",
5413
+ "name",
5414
+ "NaN",
5415
+ "Number",
5416
+ "Object",
5417
+ "prototype",
5418
+ "String",
5419
+ "toString",
5420
+ "undefined",
5421
+ "valueOf"
5422
+ ]);
5423
+ function isValidVarName(name) {
5424
+ if (!name || reservedWords.has(name)) return false;
5425
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
5708
5426
  }
5709
- var PluginDriver = (_b$1 = class {
5710
- constructor(config, options) {
5711
- __privateAdd$1(this, _PluginDriver_instances);
5712
- __publicField$1(this, "config");
5713
- __publicField$1(this, "options");
5714
- /**
5715
- * The universal `@kubb/ast` `InputNode` produced by the adapter, set by
5716
- * the build pipeline after the adapter's `parse()` resolves.
5717
- */
5718
- __publicField$1(this, "inputNode");
5719
- __publicField$1(this, "adapter");
5720
- __privateAdd$1(this, _studioIsOpen, false);
5721
- /**
5722
- * Central file store for all generated files.
5723
- * Plugins should use `this.addFile()` / `this.upsertFile()` (via their context) to
5724
- * add files; this property gives direct read/write access when needed.
5725
- */
5726
- __publicField$1(this, "fileManager", new FileManager());
5727
- __publicField$1(this, "plugins", /* @__PURE__ */ new Map());
5427
+ var URLPath = (_b = class {
5428
+ constructor(path2, options = {}) {
5429
+ __privateAdd$1(this, _URLPath_instances);
5728
5430
  /**
5729
- * Tracks which plugins have generators registered via `addGenerator()` (event-based path).
5730
- * Used by the build loop to decide whether to emit generator events for a given plugin.
5431
+ * The raw OpenAPI/Swagger path string, e.g. `/pet/{petId}`.
5731
5432
  */
5732
- __privateAdd$1(this, _pluginsWithEventGenerators, /* @__PURE__ */ new Set());
5733
- __privateAdd$1(this, _resolvers, /* @__PURE__ */ new Map());
5734
- __privateAdd$1(this, _defaultResolvers, /* @__PURE__ */ new Map());
5735
- __privateAdd$1(this, _hookListeners, /* @__PURE__ */ new Map());
5736
- this.config = config;
5737
- this.options = options;
5738
- config.plugins.map((rawPlugin) => __privateMethod$1(this, _PluginDriver_instances, normalizePlugin_fn).call(this, rawPlugin)).filter((plugin) => {
5739
- if (typeof plugin.apply === "function") return plugin.apply(config);
5740
- return true;
5741
- }).sort((a, b) => {
5742
- var _a2, _b2;
5743
- if ((_a2 = b.dependencies) == null ? void 0 : _a2.includes(a.name)) return -1;
5744
- if ((_b2 = a.dependencies) == null ? void 0 : _b2.includes(b.name)) return 1;
5745
- return enforceOrder(a.enforce) - enforceOrder(b.enforce);
5746
- }).forEach((plugin) => {
5747
- this.plugins.set(plugin.name, plugin);
5748
- });
5433
+ __publicField$1(this, "path");
5434
+ __privateAdd$1(this, _options);
5435
+ this.path = path2;
5436
+ __privateSet$1(this, _options, options);
5749
5437
  }
5750
- /**
5751
- * Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
5438
+ /** Converts the OpenAPI path to Express-style colon syntax, e.g. `/pet/{petId}` → `/pet/:petId`.
5752
5439
  *
5753
5440
  * @example
5754
5441
  * ```ts
5755
- * PluginDriver.getMode('src/gen/types.ts') // 'single'
5756
- * PluginDriver.getMode('src/gen/types') // 'split'
5442
+ * new URLPath('/pet/{petId}').URL // '/pet/:petId'
5757
5443
  * ```
5758
5444
  */
5759
- static getMode(fileOrFolder) {
5760
- if (!fileOrFolder) return "split";
5761
- return extname(fileOrFolder) ? "single" : "split";
5762
- }
5763
- get hooks() {
5764
- return this.options.hooks;
5445
+ get URL() {
5446
+ return this.toURLPath();
5765
5447
  }
5766
- /**
5767
- * Registers a hook-style plugin's lifecycle handlers on the shared `AsyncEventEmitter`.
5768
- *
5769
- * For `kubb:plugin:setup`, the registered listener wraps the globally emitted context with a
5770
- * plugin-specific one so that `addGenerator`, `setResolver`, `setTransformer`, and
5771
- * `setRenderer` all target the correct `normalizedPlugin` entry in the plugins map.
5772
- *
5773
- * All other hooks are iterated and registered directly as pass-through listeners.
5774
- * Any event key present in the global `KubbHooks` interface can be subscribed to.
5775
- *
5776
- * External tooling can subscribe to any of these events via `hooks.on(...)` to observe
5777
- * the plugin lifecycle without modifying plugin behavior.
5448
+ /** Returns `true` when `path` is a fully-qualified URL (e.g. starts with `https://`).
5778
5449
  *
5779
- * @internal
5450
+ * @example
5451
+ * ```ts
5452
+ * new URLPath('https://petstore.swagger.io/v2/pet').isURL // true
5453
+ * new URLPath('/pet/{petId}').isURL // false
5454
+ * ```
5780
5455
  */
5781
- registerPluginHooks(hookPlugin, normalizedPlugin) {
5782
- const { hooks } = hookPlugin;
5783
- if (hooks["kubb:plugin:setup"]) {
5784
- const setupHandler = (globalCtx) => {
5785
- var _a2;
5786
- const pluginCtx = {
5787
- ...globalCtx,
5788
- options: (_a2 = hookPlugin.options) != null ? _a2 : {},
5789
- addGenerator: (gen) => {
5790
- this.registerGenerator(normalizedPlugin.name, gen);
5791
- },
5792
- setResolver: (resolver) => {
5793
- this.setPluginResolver(normalizedPlugin.name, resolver);
5794
- },
5795
- setTransformer: (visitor) => {
5796
- normalizedPlugin.transformer = visitor;
5797
- },
5798
- setRenderer: (renderer) => {
5799
- normalizedPlugin.renderer = renderer;
5800
- },
5801
- setOptions: (opts) => {
5802
- normalizedPlugin.options = {
5803
- ...normalizedPlugin.options,
5804
- ...opts
5805
- };
5806
- },
5807
- injectFile: (userFileNode) => {
5808
- this.fileManager.add(createFile(userFileNode));
5809
- }
5810
- };
5811
- return hooks["kubb:plugin:setup"](pluginCtx);
5812
- };
5813
- this.hooks.on("kubb:plugin:setup", setupHandler);
5814
- __privateMethod$1(this, _PluginDriver_instances, trackHookListener_fn).call(this, "kubb:plugin:setup", setupHandler);
5815
- }
5816
- for (const [event, handler] of Object.entries(hooks)) {
5817
- if (event === "kubb:plugin:setup" || !handler) continue;
5818
- this.hooks.on(event, handler);
5819
- __privateMethod$1(this, _PluginDriver_instances, trackHookListener_fn).call(this, event, handler);
5456
+ get isURL() {
5457
+ try {
5458
+ return !!new URL(this.path).href;
5459
+ } catch {
5460
+ return false;
5820
5461
  }
5821
5462
  }
5822
5463
  /**
5823
- * Emits the `kubb:plugin:setup` event so that all registered hook-style plugin listeners
5824
- * can configure generators, resolvers, transformers and renderers before `buildStart` runs.
5464
+ * Converts the OpenAPI path to a TypeScript template literal string.
5825
5465
  *
5826
- * Call this once from `safeBuild` before the plugin execution loop begins.
5466
+ * @example
5467
+ * new URLPath('/pet/{petId}').template // '`/pet/${petId}`'
5468
+ * new URLPath('/account/monetary-accountID').template // '`/account/${monetaryAccountId}`'
5827
5469
  */
5828
- async emitSetupHooks() {
5829
- const noop = () => {
5830
- };
5831
- await this.hooks.emit("kubb:plugin:setup", {
5832
- config: this.config,
5833
- options: {},
5834
- addGenerator: noop,
5835
- setResolver: noop,
5836
- setTransformer: noop,
5837
- setRenderer: noop,
5838
- setOptions: noop,
5839
- injectFile: noop,
5840
- updateConfig: noop
5841
- });
5470
+ get template() {
5471
+ return this.toTemplateString();
5842
5472
  }
5843
- /**
5844
- * Registers a generator for the given plugin on the shared event emitter.
5845
- *
5846
- * The generator's `schema`, `operation`, and `operations` methods are registered as
5847
- * listeners on `kubb:generate:schema`, `kubb:generate:operation`, and `kubb:generate:operations`
5848
- * respectively. Each listener is scoped to the owning plugin via a `ctx.plugin.name` check
5849
- * so that generators from different plugins do not cross-fire.
5473
+ /** Returns the path and its extracted params as a structured `URLObject`, or as a stringified expression when `stringify` is set.
5850
5474
  *
5851
- * The renderer resolution chain is: `generator.renderer → plugin.renderer → config.renderer`.
5852
- * Set `generator.renderer = null` to explicitly opt out of rendering even when the plugin
5853
- * declares a renderer.
5475
+ * @example
5476
+ * ```ts
5477
+ * new URLPath('/pet/{petId}').object
5478
+ * // { url: '/pet/:petId', params: { petId: 'petId' } }
5479
+ * ```
5480
+ */
5481
+ get object() {
5482
+ return this.toObject();
5483
+ }
5484
+ /** Returns a map of path parameter names, or `undefined` when the path has no parameters.
5854
5485
  *
5855
- * Call this method inside `addGenerator()` (in `kubb:plugin:setup`) to wire up a generator.
5486
+ * @example
5487
+ * ```ts
5488
+ * new URLPath('/pet/{petId}').params // { petId: 'petId' }
5489
+ * new URLPath('/pet').params // undefined
5490
+ * ```
5856
5491
  */
5857
- registerGenerator(pluginName, gen) {
5858
- const resolveRenderer = () => {
5859
- var _a2, _b2;
5860
- const plugin = this.plugins.get(pluginName);
5861
- return gen.renderer === null ? void 0 : (_b2 = (_a2 = gen.renderer) != null ? _a2 : plugin == null ? void 0 : plugin.renderer) != null ? _b2 : this.config.renderer;
5492
+ get params() {
5493
+ return this.getParams();
5494
+ }
5495
+ toObject({ type = "path", replacer, stringify } = {}) {
5496
+ const object = {
5497
+ url: type === "path" ? this.toURLPath() : this.toTemplateString({ replacer }),
5498
+ params: this.getParams()
5862
5499
  };
5863
- if (gen.schema) {
5864
- const schemaHandler = async (node, ctx) => {
5865
- if (ctx.plugin.name !== pluginName) return;
5866
- await applyHookResult(await gen.schema(node, ctx), this, resolveRenderer());
5867
- };
5868
- this.hooks.on("kubb:generate:schema", schemaHandler);
5869
- __privateMethod$1(this, _PluginDriver_instances, trackHookListener_fn).call(this, "kubb:generate:schema", schemaHandler);
5870
- }
5871
- if (gen.operation) {
5872
- const operationHandler = async (node, ctx) => {
5873
- if (ctx.plugin.name !== pluginName) return;
5874
- await applyHookResult(await gen.operation(node, ctx), this, resolveRenderer());
5875
- };
5876
- this.hooks.on("kubb:generate:operation", operationHandler);
5877
- __privateMethod$1(this, _PluginDriver_instances, trackHookListener_fn).call(this, "kubb:generate:operation", operationHandler);
5878
- }
5879
- if (gen.operations) {
5880
- const operationsHandler = async (nodes, ctx) => {
5881
- if (ctx.plugin.name !== pluginName) return;
5882
- await applyHookResult(await gen.operations(nodes, ctx), this, resolveRenderer());
5883
- };
5884
- this.hooks.on("kubb:generate:operations", operationsHandler);
5885
- __privateMethod$1(this, _PluginDriver_instances, trackHookListener_fn).call(this, "kubb:generate:operations", operationsHandler);
5500
+ if (stringify) {
5501
+ if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
5502
+ if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
5503
+ return `{ url: '${object.url}' }`;
5886
5504
  }
5887
- __privateGet$1(this, _pluginsWithEventGenerators).add(pluginName);
5505
+ return object;
5888
5506
  }
5889
5507
  /**
5890
- * Returns `true` when at least one generator was registered for the given plugin
5891
- * via `addGenerator()` in `kubb:plugin:setup` (event-based path).
5508
+ * Converts the OpenAPI path to a TypeScript template literal string.
5509
+ * An optional `replacer` can transform each extracted parameter name before interpolation.
5892
5510
  *
5893
- * Used by the build loop to decide whether to walk the AST and emit generator events
5894
- * for a plugin that has no static `plugin.generators`.
5511
+ * @example
5512
+ * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
5895
5513
  */
5896
- hasRegisteredGenerators(pluginName) {
5897
- return __privateGet$1(this, _pluginsWithEventGenerators).has(pluginName);
5514
+ toTemplateString({ prefix = "", replacer } = {}) {
5515
+ return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
5516
+ if (i % 2 === 0) return part;
5517
+ const param = __privateMethod$1(this, _URLPath_instances, transformParam_fn).call(this, part);
5518
+ return `\${${replacer ? replacer(param) : param}}`;
5519
+ }).join("")}\``;
5898
5520
  }
5899
5521
  /**
5900
- * Unregisters all plugin lifecycle listeners from the shared event emitter.
5901
- * Called at the end of a build to prevent listener leaks across repeated builds.
5522
+ * Extracts all `{param}` segments from the path and returns them as a key-value map.
5523
+ * An optional `replacer` transforms each parameter name in both key and value positions.
5524
+ * Returns `undefined` when no path parameters are found.
5902
5525
  *
5903
- * @internal
5526
+ * @example
5527
+ * ```ts
5528
+ * new URLPath('/pet/{petId}/tag/{tagId}').getParams()
5529
+ * // { petId: 'petId', tagId: 'tagId' }
5530
+ * ```
5904
5531
  */
5905
- dispose() {
5906
- for (const [event, handlers] of __privateGet$1(this, _hookListeners)) for (const handler of handlers) this.hooks.off(event, handler);
5907
- __privateGet$1(this, _hookListeners).clear();
5908
- __privateGet$1(this, _pluginsWithEventGenerators).clear();
5532
+ getParams(replacer) {
5533
+ const params = {};
5534
+ __privateMethod$1(this, _URLPath_instances, eachParam_fn).call(this, (_raw, param) => {
5535
+ const key = replacer ? replacer(param) : param;
5536
+ params[key] = key;
5537
+ });
5538
+ return Object.keys(params).length > 0 ? params : void 0;
5909
5539
  }
5910
- /**
5911
- * Merges `partial` with the plugin's default resolver and stores the result.
5912
- * Also mirrors it onto `plugin.resolver` so callers using `getPlugin(name).resolver`
5913
- * get the up-to-date resolver without going through `getResolver()`.
5540
+ /** Converts the OpenAPI path to Express-style colon syntax.
5541
+ *
5542
+ * @example
5543
+ * ```ts
5544
+ * new URLPath('/pet/{petId}').toURLPath() // '/pet/:petId'
5545
+ * ```
5914
5546
  */
5915
- setPluginResolver(pluginName, partial) {
5916
- const merged = {
5917
- ...__privateMethod$1(this, _PluginDriver_instances, createDefaultResolver_fn).call(this, pluginName),
5918
- ...partial
5919
- };
5920
- __privateGet$1(this, _resolvers).set(pluginName, merged);
5921
- const plugin = this.plugins.get(pluginName);
5922
- if (plugin) plugin.resolver = merged;
5547
+ toURLPath() {
5548
+ return this.path.replace(/\{([^}]+)\}/g, ":$1");
5923
5549
  }
5924
- getResolver(pluginName) {
5925
- var _a2, _b2, _c;
5926
- return (_c = (_b2 = __privateGet$1(this, _resolvers).get(pluginName)) != null ? _b2 : (_a2 = this.plugins.get(pluginName)) == null ? void 0 : _a2.resolver) != null ? _c : __privateMethod$1(this, _PluginDriver_instances, createDefaultResolver_fn).call(this, pluginName);
5550
+ }, _options = new WeakMap(), _URLPath_instances = new WeakSet(), transformParam_fn = function(raw) {
5551
+ const param = isValidVarName(raw) ? raw : camelCase(raw);
5552
+ return __privateGet$1(this, _options).casing === "camelcase" ? camelCase(param) : param;
5553
+ }, /**
5554
+ * Iterates over every `{param}` token in `path`, calling `fn` with the raw token and transformed name.
5555
+ */
5556
+ eachParam_fn = function(fn) {
5557
+ for (const match of this.path.matchAll(/\{([^}]+)\}/g)) {
5558
+ const raw = match[1];
5559
+ fn(raw, __privateMethod$1(this, _URLPath_instances, transformParam_fn).call(this, raw));
5927
5560
  }
5928
- getContext(plugin) {
5929
- const driver = this;
5561
+ }, _b);
5562
+ const DEFAULT_STUDIO_URL = "https://kubb.studio";
5563
+ const DEFAULT_BANNER = "simple";
5564
+ const DEFAULT_EXTENSION = { ".ts": ".ts" };
5565
+ function getMode(fileOrFolder) {
5566
+ if (!fileOrFolder) return "split";
5567
+ return extname(fileOrFolder) ? "single" : "split";
5568
+ }
5569
+ const stringPatternCache = /* @__PURE__ */ new Map();
5570
+ function testPattern(value, pattern) {
5571
+ if (typeof pattern === "string") {
5572
+ let regex = stringPatternCache.get(pattern);
5573
+ if (!regex) {
5574
+ regex = new RegExp(pattern);
5575
+ stringPatternCache.set(pattern, regex);
5576
+ }
5577
+ return regex.test(value);
5578
+ }
5579
+ return value.match(pattern) !== null;
5580
+ }
5581
+ function matchesOperationPattern(node, type, pattern) {
5582
+ var _a2, _b2, _c2;
5583
+ if (type === "tag") return node.tags.some((tag) => testPattern(tag, pattern));
5584
+ if (type === "operationId") return testPattern(node.operationId, pattern);
5585
+ if (type === "path") return testPattern(node.path, pattern);
5586
+ if (type === "method") return testPattern(node.method.toLowerCase(), pattern);
5587
+ if (type === "contentType") return (_c2 = (_b2 = (_a2 = node.requestBody) == null ? void 0 : _a2.content) == null ? void 0 : _b2.some((c) => testPattern(c.contentType, pattern))) != null ? _c2 : false;
5588
+ return false;
5589
+ }
5590
+ function matchesSchemaPattern(node, type, pattern) {
5591
+ if (type === "schemaName") return node.name ? testPattern(node.name, pattern) : false;
5592
+ return null;
5593
+ }
5594
+ function defaultResolver(name, type) {
5595
+ if (type === "file" || type === "function") return camelCase(name, { isFile: type === "file" });
5596
+ if (type === "type") return pascalCase(name);
5597
+ return camelCase(name);
5598
+ }
5599
+ const resolveOptionsCache = /* @__PURE__ */ new WeakMap();
5600
+ function computeOptions(node, options, exclude, include, override) {
5601
+ var _a2, _b2;
5602
+ if (isOperationNode(node)) {
5603
+ if (exclude.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
5604
+ if (include && !include.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
5605
+ const overrideOptions = (_a2 = override.find(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) == null ? void 0 : _a2.options;
5930
5606
  return {
5931
- config: driver.config,
5932
- get root() {
5933
- return resolve(driver.config.root, driver.config.output.path);
5934
- },
5935
- getMode(output) {
5936
- return _b$1.getMode(resolve(driver.config.root, driver.config.output.path, output.path));
5937
- },
5938
- hooks: driver.hooks,
5939
- plugin,
5940
- getPlugin: driver.getPlugin.bind(driver),
5941
- requirePlugin: driver.requirePlugin.bind(driver),
5942
- getResolver: driver.getResolver.bind(driver),
5943
- driver,
5944
- addFile: async (...files) => {
5945
- driver.fileManager.add(...files);
5946
- },
5947
- upsertFile: async (...files) => {
5948
- driver.fileManager.upsert(...files);
5949
- },
5950
- get inputNode() {
5951
- return driver.inputNode;
5952
- },
5953
- get adapter() {
5954
- return driver.adapter;
5955
- },
5956
- get resolver() {
5957
- return driver.getResolver(plugin.name);
5958
- },
5959
- get transformer() {
5960
- return plugin.transformer;
5961
- },
5962
- warn(message) {
5963
- driver.hooks.emit("kubb:warn", { message });
5964
- },
5965
- error(error) {
5966
- driver.hooks.emit("kubb:error", { error: typeof error === "string" ? new Error(error) : error });
5967
- },
5968
- info(message) {
5969
- driver.hooks.emit("kubb:info", { message });
5970
- },
5971
- openInStudio(options) {
5972
- var _a2, _b2;
5973
- if (!driver.config.devtools || __privateGet$1(driver, _studioIsOpen)) return;
5974
- if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
5975
- if (!driver.inputNode || !driver.adapter) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
5976
- __privateSet$1(driver, _studioIsOpen, true);
5977
- const studioUrl = (_b2 = (_a2 = driver.config.devtools) == null ? void 0 : _a2.studioUrl) != null ? _b2 : "https://studio.kubb.dev";
5978
- return openInStudio(driver.inputNode, studioUrl, options);
5979
- }
5607
+ ...options,
5608
+ ...overrideOptions
5980
5609
  };
5981
5610
  }
5982
- getPlugin(pluginName) {
5983
- return this.plugins.get(pluginName);
5984
- }
5985
- requirePlugin(pluginName) {
5986
- const plugin = this.plugins.get(pluginName);
5987
- if (!plugin) throw new Error(`[kubb] Plugin "${pluginName}" is required but not found. Make sure it is included in your Kubb config.`);
5988
- return plugin;
5611
+ if (isSchemaNode(node)) {
5612
+ if (exclude.some(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) return null;
5613
+ if (include) {
5614
+ const applicable = include.map(({ type, pattern }) => matchesSchemaPattern(node, type, pattern)).filter((r) => r !== null);
5615
+ if (applicable.length > 0 && !applicable.includes(true)) return null;
5616
+ }
5617
+ const overrideOptions = (_b2 = override.find(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) == null ? void 0 : _b2.options;
5618
+ return {
5619
+ ...options,
5620
+ ...overrideOptions
5621
+ };
5989
5622
  }
5990
- }, _studioIsOpen = new WeakMap(), _pluginsWithEventGenerators = new WeakMap(), _resolvers = new WeakMap(), _defaultResolvers = new WeakMap(), _hookListeners = new WeakMap(), _PluginDriver_instances = new WeakSet(), /**
5991
- * Creates an `NormalizedPlugin` from a hook-style plugin and registers
5992
- * its lifecycle handlers on the `AsyncEventEmitter`.
5993
- */
5994
- normalizePlugin_fn = function(hookPlugin) {
5995
- const normalizedPlugin = {
5996
- name: hookPlugin.name,
5997
- dependencies: hookPlugin.dependencies,
5998
- enforce: hookPlugin.enforce,
5999
- options: {
6000
- output: { path: "." },
6001
- exclude: [],
6002
- override: []
5623
+ return options;
5624
+ }
5625
+ function defaultResolveOptions(node, { options, exclude = [], include, override = [] }) {
5626
+ const optionsKey = options;
5627
+ let byOptions = resolveOptionsCache.get(optionsKey);
5628
+ if (!byOptions) {
5629
+ byOptions = /* @__PURE__ */ new WeakMap();
5630
+ resolveOptionsCache.set(optionsKey, byOptions);
5631
+ }
5632
+ const cached = byOptions.get(node);
5633
+ if (cached !== void 0) return cached.value;
5634
+ const result = computeOptions(node, options, exclude, include, override);
5635
+ byOptions.set(node, { value: result });
5636
+ return result;
5637
+ }
5638
+ function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }, { root, output, group }) {
5639
+ if ((pathMode != null ? pathMode : getMode(path$1.resolve(root, output.path))) === "single") return path$1.resolve(root, output.path);
5640
+ const result = (() => {
5641
+ var _a2;
5642
+ if (group && (groupPath || tag)) {
5643
+ const groupValue = group.type === "path" ? groupPath : tag;
5644
+ const defaultName = group.type === "tag" ? ({ group: g }) => `${camelCase(g)}Controller` : ({ group: g }) => {
5645
+ const segment = g.split("/").filter((s) => s !== "" && s !== "." && s !== "..")[0];
5646
+ return segment ? camelCase(segment) : "";
5647
+ };
5648
+ const resolveName = (_a2 = group.name) != null ? _a2 : defaultName;
5649
+ return path$1.resolve(root, output.path, resolveName({ group: groupValue }), baseName);
6003
5650
  }
6004
- };
6005
- this.registerPluginHooks(hookPlugin, normalizedPlugin);
6006
- return normalizedPlugin;
6007
- }, trackHookListener_fn = function(event, handler) {
6008
- let handlers = __privateGet$1(this, _hookListeners).get(event);
6009
- if (!handlers) {
6010
- handlers = /* @__PURE__ */ new Set();
6011
- __privateGet$1(this, _hookListeners).set(event, handlers);
5651
+ return path$1.resolve(root, output.path, baseName);
5652
+ })();
5653
+ const outputDir = path$1.resolve(root, output.path);
5654
+ const outputDirWithSep = outputDir.endsWith(path$1.sep) ? outputDir : `${outputDir}${path$1.sep}`;
5655
+ if (result !== outputDir && !result.startsWith(outputDirWithSep)) throw new Error(`[Kubb] Resolved path "${result}" is outside the output directory "${outputDir}". This may indicate a path traversal attempt in the OpenAPI specification or a misconfigured group.name function.`);
5656
+ return result;
5657
+ }
5658
+ function defaultResolveFile({ name, extname: extname2, tag, path: groupPath }, context) {
5659
+ const pathMode = getMode(path$1.resolve(context.root, context.output.path));
5660
+ const baseName = `${pathMode === "single" ? "" : this.default(name, "file")}${extname2}`;
5661
+ const filePath = this.resolvePath({
5662
+ baseName,
5663
+ pathMode,
5664
+ tag,
5665
+ path: groupPath
5666
+ }, context);
5667
+ return createFile({
5668
+ path: filePath,
5669
+ baseName: path$1.basename(filePath),
5670
+ meta: { pluginName: this.pluginName },
5671
+ sources: [],
5672
+ imports: [],
5673
+ exports: []
5674
+ });
5675
+ }
5676
+ function buildDefaultBanner({ title, description, version, config }) {
5677
+ try {
5678
+ const source = (() => {
5679
+ if (Array.isArray(config.input)) {
5680
+ const first = config.input[0];
5681
+ if (first && "path" in first) return path$1.basename(first.path);
5682
+ return "";
5683
+ }
5684
+ if (config.input && "path" in config.input) return path$1.basename(config.input.path);
5685
+ if (config.input && "data" in config.input) return "text content";
5686
+ return "";
5687
+ })();
5688
+ let banner = "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n";
5689
+ if (config.output.defaultBanner === "simple") {
5690
+ banner += "*/\n";
5691
+ return banner;
5692
+ }
5693
+ if (source) banner += `* Source: ${source}
5694
+ `;
5695
+ if (title) banner += `* Title: ${title}
5696
+ `;
5697
+ if (description) {
5698
+ const formattedDescription = description.replace(/\n/gm, "\n* ");
5699
+ banner += `* Description: ${formattedDescription}
5700
+ `;
5701
+ }
5702
+ if (version) banner += `* OpenAPI spec version: ${version}
5703
+ `;
5704
+ banner += "*/\n";
5705
+ return banner;
5706
+ } catch (_error) {
5707
+ return "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/";
6012
5708
  }
6013
- handlers.add(handler);
6014
- }, createDefaultResolver_fn = function(pluginName) {
6015
- const existingResolver = __privateGet$1(this, _defaultResolvers).get(pluginName);
6016
- if (existingResolver) return existingResolver;
6017
- const resolver = defineResolver((_ctx) => ({
6018
- name: "default",
6019
- pluginName
6020
- }));
6021
- __privateGet$1(this, _defaultResolvers).set(pluginName, resolver);
5709
+ }
5710
+ function defaultResolveBanner(meta, { output, config }) {
5711
+ if (typeof (output == null ? void 0 : output.banner) === "function") return output.banner(meta);
5712
+ if (typeof (output == null ? void 0 : output.banner) === "string") return output.banner;
5713
+ if (config.output.defaultBanner === false) return null;
5714
+ return buildDefaultBanner({
5715
+ title: meta == null ? void 0 : meta.title,
5716
+ version: meta == null ? void 0 : meta.version,
5717
+ config
5718
+ });
5719
+ }
5720
+ function defaultResolveFooter(meta, { output }) {
5721
+ if (typeof (output == null ? void 0 : output.footer) === "function") return output.footer(meta);
5722
+ if (typeof (output == null ? void 0 : output.footer) === "string") return output.footer;
5723
+ return null;
5724
+ }
5725
+ function defineResolver(build) {
5726
+ let resolver;
5727
+ resolver = {
5728
+ default: defaultResolver,
5729
+ resolveOptions: defaultResolveOptions,
5730
+ resolvePath: defaultResolvePath,
5731
+ resolveFile: (params, context) => defaultResolveFile.call(resolver, params, context),
5732
+ resolveBanner: defaultResolveBanner,
5733
+ resolveFooter: defaultResolveFooter,
5734
+ ...build()
5735
+ };
6022
5736
  return resolver;
6023
- }, _b$1);
6024
-
6025
- var __defProp = Object.defineProperty;
6026
- var __typeError = (msg) => {
6027
- throw TypeError(msg);
6028
- };
6029
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6030
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6031
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
6032
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6033
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
6034
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
6035
- var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
6036
- var __privateWrapper = (obj, member, setter, getter) => ({
6037
- set _(value) {
6038
- __privateSet(obj, member, value);
6039
- },
6040
- get _() {
6041
- return __privateGet(obj, member, getter);
6042
- }
6043
- });
6044
- var _emitter, _a, _options, _URLPath_instances, transformParam_fn, eachParam_fn, _b, _c, _head, _tail, _size, _d, _limit, _e;
6045
- var BuildError = class extends Error {
6046
- constructor(message, options) {
6047
- super(message, { cause: options.cause });
6048
- __publicField(this, "errors");
6049
- this.name = "BuildError";
6050
- this.errors = options.errors;
5737
+ }
5738
+ function encodeAst(input) {
5739
+ const compressed = deflateSync(new TextEncoder().encode(JSON.stringify(input)));
5740
+ return Buffer.from(compressed).toString("base64url");
5741
+ }
5742
+ function getStudioUrl(input, studioUrl, options = {}) {
5743
+ return `${studioUrl.replace(/\/$/, "")}${options.ast ? "/ast" : ""}?root=${encodeAst(input)}`;
5744
+ }
5745
+ async function openInStudio(input, studioUrl, options = {}) {
5746
+ const url = getStudioUrl(input, studioUrl, options);
5747
+ const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
5748
+ const args = process.platform === "win32" ? [
5749
+ "/c",
5750
+ "start",
5751
+ "",
5752
+ url
5753
+ ] : [url];
5754
+ try {
5755
+ await x(cmd, args);
5756
+ } catch {
5757
+ console.log(`
5758
+ ${url}
5759
+ `);
6051
5760
  }
6052
- };
6053
- function toError(value) {
6054
- return value instanceof Error ? value : new Error(String(value));
6055
5761
  }
6056
- var AsyncEventEmitter = (_a = class {
6057
- /**
6058
- * Maximum number of listeners per event before Node emits a memory-leak warning.
6059
- * @default 10
6060
- */
6061
- constructor(maxListener = 10) {
6062
- __privateAdd(this, _emitter, new EventEmitter());
6063
- __privateGet(this, _emitter).setMaxListeners(maxListener);
5762
+ function mergeFile(a, b) {
5763
+ return {
5764
+ ...a,
5765
+ banner: b.banner,
5766
+ footer: b.footer,
5767
+ sources: a.sources.length ? b.sources.length ? [...a.sources, ...b.sources] : a.sources : b.sources,
5768
+ imports: a.imports.length ? b.imports.length ? [...a.imports, ...b.imports] : a.imports : b.imports,
5769
+ exports: a.exports.length ? b.exports.length ? [...a.exports, ...b.exports] : a.exports : b.exports
5770
+ };
5771
+ }
5772
+ function isIndexPath(path2) {
5773
+ return path2.endsWith("/index.ts") || path2 === "index.ts";
5774
+ }
5775
+ function compareFiles(a, b) {
5776
+ const lenDiff = a.path.length - b.path.length;
5777
+ if (lenDiff !== 0) return lenDiff;
5778
+ const aIsIndex = isIndexPath(a.path);
5779
+ const bIsIndex = isIndexPath(b.path);
5780
+ if (aIsIndex && !bIsIndex) return 1;
5781
+ if (!aIsIndex && bIsIndex) return -1;
5782
+ return 0;
5783
+ }
5784
+ var FileManager = (_c = class {
5785
+ constructor() {
5786
+ __privateAdd$1(this, _FileManager_instances);
5787
+ __privateAdd$1(this, _cache, /* @__PURE__ */ new Map());
5788
+ __privateAdd$1(this, _sorted, null);
5789
+ __privateAdd$1(this, _onUpsert, null);
6064
5790
  }
6065
5791
  /**
6066
- * Emits `eventName` and awaits all registered listeners sequentially.
6067
- * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
6068
- *
6069
- * @example
6070
- * ```ts
6071
- * await emitter.emit('build', 'petstore')
6072
- * ```
5792
+ * Registers a callback invoked with the resolved {@link FileNode} on every
5793
+ * `add` / `upsert`. Used by the build loop to track newly written files
5794
+ * without keeping its own scan-based diff. Single subscriber by design —
5795
+ * setting again replaces the previous callback. Pass `null` to detach.
6073
5796
  */
6074
- async emit(eventName, ...eventArgs) {
6075
- const listeners = __privateGet(this, _emitter).listeners(eventName);
6076
- if (listeners.length === 0) return;
6077
- for (const listener of listeners) try {
6078
- await listener(...eventArgs);
6079
- } catch (err) {
6080
- let serializedArgs;
6081
- try {
6082
- serializedArgs = JSON.stringify(eventArgs);
6083
- } catch {
6084
- serializedArgs = String(eventArgs);
6085
- }
6086
- throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
6087
- }
5797
+ setOnUpsert(callback) {
5798
+ __privateSet$1(this, _onUpsert, callback);
6088
5799
  }
6089
- /**
6090
- * Registers a persistent listener for `eventName`.
6091
- *
6092
- * @example
6093
- * ```ts
6094
- * emitter.on('build', async (name) => { console.log(name) })
6095
- * ```
6096
- */
6097
- on(eventName, handler) {
6098
- __privateGet(this, _emitter).on(eventName, handler);
5800
+ add(...files) {
5801
+ return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, false);
6099
5802
  }
6100
- /**
6101
- * Registers a one-shot listener that removes itself after the first invocation.
6102
- *
6103
- * @example
6104
- * ```ts
6105
- * emitter.onOnce('build', async (name) => { console.log(name) })
6106
- * ```
6107
- */
6108
- onOnce(eventName, handler) {
6109
- const wrapper = (...args) => {
6110
- this.off(eventName, wrapper);
6111
- return handler(...args);
6112
- };
6113
- this.on(eventName, wrapper);
5803
+ upsert(...files) {
5804
+ return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, true);
6114
5805
  }
6115
- /**
6116
- * Removes a previously registered listener.
6117
- *
6118
- * @example
6119
- * ```ts
6120
- * emitter.off('build', handler)
6121
- * ```
6122
- */
6123
- off(eventName, handler) {
6124
- __privateGet(this, _emitter).off(eventName, handler);
5806
+ getByPath(path2) {
5807
+ var _a2;
5808
+ return (_a2 = __privateGet$1(this, _cache).get(path2)) != null ? _a2 : null;
6125
5809
  }
6126
- /**
6127
- * Returns the number of listeners registered for `eventName`.
6128
- *
6129
- * @example
6130
- * ```ts
6131
- * emitter.on('build', handler)
6132
- * emitter.listenerCount('build') // 1
6133
- * ```
6134
- */
6135
- listenerCount(eventName) {
6136
- return __privateGet(this, _emitter).listenerCount(eventName);
5810
+ deleteByPath(path2) {
5811
+ if (!__privateGet$1(this, _cache).delete(path2)) return;
5812
+ __privateSet$1(this, _sorted, null);
5813
+ }
5814
+ clear() {
5815
+ __privateGet$1(this, _cache).clear();
5816
+ __privateSet$1(this, _sorted, null);
6137
5817
  }
6138
5818
  /**
6139
- * Removes all listeners from every event channel.
6140
- *
6141
- * @example
6142
- * ```ts
6143
- * emitter.removeAll()
6144
- * ```
5819
+ * Releases all stored files. Called by the core after `kubb:build:end`.
6145
5820
  */
6146
- removeAll() {
6147
- __privateGet(this, _emitter).removeAllListeners();
5821
+ dispose() {
5822
+ this.clear();
5823
+ __privateSet$1(this, _onUpsert, null);
6148
5824
  }
6149
- }, _emitter = new WeakMap(), _a);
6150
- function getElapsedMs(hrStart) {
6151
- const [seconds, nanoseconds] = process.hrtime(hrStart);
6152
- const ms = seconds * 1e3 + nanoseconds / 1e6;
6153
- return Math.round(ms * 100) / 100;
6154
- }
6155
- function formatMs(ms) {
6156
- if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
6157
- if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
6158
- return `${Math.round(ms)}ms`;
6159
- }
6160
- async function exists(path) {
6161
- if (typeof Bun !== "undefined") return Bun.file(path).exists();
6162
- return access(path).then(() => true, () => false);
6163
- }
6164
- async function write(path, data, options = {}) {
6165
- const trimmed = data.trim();
6166
- if (trimmed === "") return null;
6167
- const resolved = resolve(path);
6168
- if (typeof Bun !== "undefined") {
6169
- const file = Bun.file(resolved);
6170
- if ((await file.exists() ? await file.text() : null) === trimmed) return null;
6171
- await Bun.write(resolved, trimmed);
6172
- return trimmed;
5825
+ [Symbol.dispose]() {
5826
+ this.dispose();
6173
5827
  }
6174
- try {
6175
- if (await readFile$1(resolved, { encoding: "utf-8" }) === trimmed) return null;
6176
- } catch {
5828
+ /**
5829
+ * All stored files in stable sort order (shortest path first, barrel files
5830
+ * last within a length bucket). Returns a cached view — do not mutate.
5831
+ */
5832
+ get files() {
5833
+ var _a2;
5834
+ return (_a2 = __privateGet$1(this, _sorted)) != null ? _a2 : __privateSet$1(this, _sorted, [...__privateGet$1(this, _cache).values()].sort(compareFiles));
6177
5835
  }
6178
- await mkdir(dirname(resolved), { recursive: true });
6179
- await writeFile$1(resolved, trimmed, { encoding: "utf-8" });
6180
- if (options.sanity) {
6181
- const savedData = await readFile$1(resolved, { encoding: "utf-8" });
6182
- if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}
6183
-
6184
- Data[${data.length}]:
6185
- ${data}
6186
-
6187
- Saved[${savedData.length}]:
6188
- ${savedData}
6189
- `);
6190
- return savedData;
5836
+ }, _cache = new WeakMap(), _sorted = new WeakMap(), _onUpsert = new WeakMap(), _FileManager_instances = new WeakSet(), store_fn = function(files, mergeExisting) {
5837
+ var _a2;
5838
+ const batch = files.length > 1 ? __privateMethod$1(this, _FileManager_instances, dedupe_fn).call(this, files) : files;
5839
+ const resolved = [];
5840
+ for (const file of batch) {
5841
+ const existing = __privateGet$1(this, _cache).get(file.path);
5842
+ const merged = existing && mergeExisting ? createFile(mergeFile(existing, file)) : file;
5843
+ __privateGet$1(this, _cache).set(merged.path, merged);
5844
+ resolved.push(merged);
5845
+ (_a2 = __privateGet$1(this, _onUpsert)) == null ? void 0 : _a2.call(this, merged);
5846
+ }
5847
+ if (resolved.length > 0) __privateSet$1(this, _sorted, null);
5848
+ return resolved;
5849
+ }, dedupe_fn = function(files) {
5850
+ const seen = /* @__PURE__ */ new Map();
5851
+ for (const file of files) {
5852
+ const prev = seen.get(file.path);
5853
+ seen.set(file.path, prev ? mergeFile(prev, file) : file);
6191
5854
  }
6192
- return trimmed;
6193
- }
6194
- async function clean(path) {
6195
- return rm(path, {
6196
- recursive: true,
6197
- force: true
6198
- });
6199
- }
6200
- const reservedWords = /* @__PURE__ */ new Set([
6201
- "abstract",
6202
- "arguments",
6203
- "boolean",
6204
- "break",
6205
- "byte",
6206
- "case",
6207
- "catch",
6208
- "char",
6209
- "class",
6210
- "const",
6211
- "continue",
6212
- "debugger",
6213
- "default",
6214
- "delete",
6215
- "do",
6216
- "double",
6217
- "else",
6218
- "enum",
6219
- "eval",
6220
- "export",
6221
- "extends",
6222
- "false",
6223
- "final",
6224
- "finally",
6225
- "float",
6226
- "for",
6227
- "function",
6228
- "goto",
6229
- "if",
6230
- "implements",
6231
- "import",
6232
- "in",
6233
- "instanceof",
6234
- "int",
6235
- "interface",
6236
- "let",
6237
- "long",
6238
- "native",
6239
- "new",
6240
- "null",
6241
- "package",
6242
- "private",
6243
- "protected",
6244
- "public",
6245
- "return",
6246
- "short",
6247
- "static",
6248
- "super",
6249
- "switch",
6250
- "synchronized",
6251
- "this",
6252
- "throw",
6253
- "throws",
6254
- "transient",
6255
- "true",
6256
- "try",
6257
- "typeof",
6258
- "var",
6259
- "void",
6260
- "volatile",
6261
- "while",
6262
- "with",
6263
- "yield",
6264
- "Array",
6265
- "Date",
6266
- "hasOwnProperty",
6267
- "Infinity",
6268
- "isFinite",
6269
- "isNaN",
6270
- "isPrototypeOf",
6271
- "length",
6272
- "Math",
6273
- "name",
6274
- "NaN",
6275
- "Number",
6276
- "Object",
6277
- "prototype",
6278
- "String",
6279
- "toString",
6280
- "undefined",
6281
- "valueOf"
6282
- ]);
6283
- function isValidVarName(name) {
6284
- if (!name || reservedWords.has(name)) return false;
6285
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
5855
+ return [...seen.values()];
5856
+ }, _c);
5857
+ function joinSources(file) {
5858
+ const sources = file.sources;
5859
+ if (sources.length === 0) return "";
5860
+ const parts = [];
5861
+ for (const source of sources) {
5862
+ const s = extractStringsFromNodes(source.nodes);
5863
+ if (s) parts.push(s);
5864
+ }
5865
+ return parts.join("\n\n");
6286
5866
  }
6287
- var URLPath = (_b = class {
6288
- constructor(path, options = {}) {
6289
- __privateAdd(this, _URLPath_instances);
5867
+ var FileProcessor = class {
5868
+ constructor() {
5869
+ __publicField$1(this, "events", new AsyncEventEmitter());
5870
+ }
5871
+ parse(file, { parsers, extension } = {}) {
5872
+ const parseExtName = (extension == null ? void 0 : extension[file.extname]) || void 0;
5873
+ if (!parsers || !file.extname) return joinSources(file);
5874
+ const parser = parsers.get(file.extname);
5875
+ if (!parser) return joinSources(file);
5876
+ return parser.parse(file, { extname: parseExtName });
5877
+ }
5878
+ *stream(files, options = {}) {
5879
+ const total = files.length;
5880
+ if (total === 0) return;
5881
+ let processed = 0;
5882
+ for (const file of files) {
5883
+ const source = this.parse(file, options);
5884
+ processed++;
5885
+ yield {
5886
+ file,
5887
+ source,
5888
+ processed,
5889
+ total,
5890
+ percentage: processed / total * 100
5891
+ };
5892
+ }
5893
+ }
5894
+ async run(files, options = {}) {
5895
+ await this.events.emit("start", files);
5896
+ for (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
5897
+ file,
5898
+ source,
5899
+ processed,
5900
+ percentage,
5901
+ total
5902
+ });
5903
+ await this.events.emit("end", files);
5904
+ return files;
5905
+ }
5906
+ /**
5907
+ * Clears all registered event listeners.
5908
+ */
5909
+ dispose() {
5910
+ this.events.removeAll();
5911
+ }
5912
+ [Symbol.dispose]() {
5913
+ this.dispose();
5914
+ }
5915
+ };
5916
+ function _usingCtx() {
5917
+ var r = "function" == typeof SuppressedError ? SuppressedError : function(r2, e2) {
5918
+ var n2 = Error();
5919
+ return n2.name = "SuppressedError", n2.error = r2, n2.suppressed = e2, n2;
5920
+ };
5921
+ var e = {};
5922
+ var n = [];
5923
+ function using(r2, e2) {
5924
+ if (null != e2) {
5925
+ if (Object(e2) !== e2) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
5926
+ if (r2) var o = e2[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
5927
+ if (void 0 === o && (o = e2[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r2)) var t = o;
5928
+ if ("function" != typeof o) throw new TypeError("Object is not disposable.");
5929
+ t && (o = function o2() {
5930
+ try {
5931
+ t.call(e2);
5932
+ } catch (r3) {
5933
+ return Promise.reject(r3);
5934
+ }
5935
+ }), n.push({
5936
+ v: e2,
5937
+ d: o,
5938
+ a: r2
5939
+ });
5940
+ } else r2 && n.push({
5941
+ d: e2,
5942
+ a: r2
5943
+ });
5944
+ return e2;
5945
+ }
5946
+ return {
5947
+ e,
5948
+ u: using.bind(null, false),
5949
+ a: using.bind(null, true),
5950
+ d: function d() {
5951
+ var o;
5952
+ var t = this.e;
5953
+ var s = 0;
5954
+ function next() {
5955
+ for (; o = n.pop(); ) try {
5956
+ if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
5957
+ if (o.d) {
5958
+ var r2 = o.d.call(o.v);
5959
+ if (o.a) return s |= 2, Promise.resolve(r2).then(next, err);
5960
+ } else s |= 1;
5961
+ } catch (r3) {
5962
+ return err(r3);
5963
+ }
5964
+ if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
5965
+ if (t !== e) throw t;
5966
+ }
5967
+ function err(n2) {
5968
+ return t = t !== e ? new r(n2, t) : n2, next();
5969
+ }
5970
+ return next();
5971
+ }
5972
+ };
5973
+ }
5974
+ function enforceOrder(enforce) {
5975
+ return enforce === "pre" ? -1 : enforce === "post" ? 1 : 0;
5976
+ }
5977
+ const OPERATION_FILTER_TYPES = /* @__PURE__ */ new Set([
5978
+ "tag",
5979
+ "operationId",
5980
+ "path",
5981
+ "method",
5982
+ "contentType"
5983
+ ]);
5984
+ var KubbDriver = (_d = class {
5985
+ constructor(config, options) {
5986
+ __privateAdd$1(this, _KubbDriver_instances);
5987
+ __publicField$1(this, "config");
5988
+ __publicField$1(this, "options");
6290
5989
  /**
6291
- * The raw OpenAPI/Swagger path string, e.g. `/pet/{petId}`.
5990
+ * The streaming `InputStreamNode` produced by the adapter.
5991
+ * Always set after adapter setup — parse-only adapters are wrapped automatically.
5992
+ */
5993
+ __publicField$1(this, "inputNode", null);
5994
+ __publicField$1(this, "adapter", null);
5995
+ /**
5996
+ * Studio session state, kept together so `dispose()` can reset it atomically.
5997
+ *
5998
+ * - `source` holds the raw adapter source so `adapter.parse()` can be called lazily.
5999
+ * Intentionally outlives the build; cleared by `dispose()`.
6000
+ * - `isOpen` prevents opening the studio more than once per build.
6001
+ * - `inputNode` caches the parse promise so `adapter.parse()` is called at most once
6002
+ * per studio session, even when `openInStudio()` is called multiple times.
6003
+ */
6004
+ __privateAdd$1(this, _studio, {
6005
+ source: null,
6006
+ isOpen: false,
6007
+ inputNode: null
6008
+ });
6009
+ __privateAdd$1(this, _middlewareListeners, []);
6010
+ /**
6011
+ * Central file store for all generated files.
6012
+ * Plugins should use `this.addFile()` / `this.upsertFile()` (via their context) to
6013
+ * add files; this property gives direct read/write access when needed.
6014
+ */
6015
+ __publicField$1(this, "fileManager", new FileManager());
6016
+ __privateAdd$1(this, _fileProcessor, new FileProcessor());
6017
+ __publicField$1(this, "plugins", /* @__PURE__ */ new Map());
6018
+ /**
6019
+ * Tracks which plugins have generators registered via `addGenerator()` (event-based path).
6020
+ * Used by the build loop to decide whether to emit generator events for a given plugin.
6292
6021
  */
6293
- __publicField(this, "path");
6294
- __privateAdd(this, _options);
6295
- this.path = path;
6296
- __privateSet(this, _options, options);
6022
+ __privateAdd$1(this, _eventGeneratorPlugins, /* @__PURE__ */ new Set());
6023
+ __privateAdd$1(this, _resolvers, /* @__PURE__ */ new Map());
6024
+ __privateAdd$1(this, _defaultResolvers, /* @__PURE__ */ new Map());
6025
+ __privateAdd$1(this, _hookListeners, /* @__PURE__ */ new Map());
6026
+ __privateAdd$1(this, _getDefaultResolver, memoize(__privateGet$1(this, _defaultResolvers), (pluginName) => defineResolver(() => ({
6027
+ name: "default",
6028
+ pluginName
6029
+ }))));
6030
+ var _a2;
6031
+ this.config = config;
6032
+ this.options = options;
6033
+ this.adapter = (_a2 = config.adapter) != null ? _a2 : null;
6297
6034
  }
6298
- /** Converts the OpenAPI path to Express-style colon syntax, e.g. `/pet/{petId}` → `/pet/:petId`.
6035
+ /**
6036
+ * Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
6299
6037
  *
6300
6038
  * @example
6301
6039
  * ```ts
6302
- * new URLPath('/pet/{petId}').URL // '/pet/:petId'
6040
+ * KubbDriver.getMode('src/gen/types.ts') // 'single'
6041
+ * KubbDriver.getMode('src/gen/types') // 'split'
6303
6042
  * ```
6304
6043
  */
6305
- get URL() {
6306
- return this.toURLPath();
6044
+ static getMode(fileOrFolder) {
6045
+ return getMode(fileOrFolder);
6307
6046
  }
6308
- /** Returns `true` when `path` is a fully-qualified URL (e.g. starts with `https://`).
6309
- *
6310
- * @example
6311
- * ```ts
6312
- * new URLPath('https://petstore.swagger.io/v2/pet').isURL // true
6313
- * new URLPath('/pet/{petId}').isURL // false
6314
- * ```
6315
- */
6316
- get isURL() {
6317
- try {
6318
- return !!new URL(this.path).href;
6319
- } catch {
6320
- return false;
6047
+ async setup() {
6048
+ const normalized = this.config.plugins.map((rawPlugin) => __privateMethod$1(this, _KubbDriver_instances, normalizePlugin_fn).call(this, rawPlugin));
6049
+ normalized.sort((a, b) => {
6050
+ var _a2, _b2;
6051
+ if ((_a2 = b.dependencies) == null ? void 0 : _a2.includes(a.name)) return -1;
6052
+ if ((_b2 = a.dependencies) == null ? void 0 : _b2.includes(b.name)) return 1;
6053
+ return enforceOrder(a.enforce) - enforceOrder(b.enforce);
6054
+ });
6055
+ for (const plugin of normalized) {
6056
+ if (plugin.apply) plugin.apply(this.config);
6057
+ __privateMethod$1(this, _KubbDriver_instances, registerPlugin_fn).call(this, plugin);
6058
+ this.plugins.set(plugin.name, plugin);
6321
6059
  }
6060
+ if (this.config.middleware) for (const middleware of this.config.middleware) for (const event of Object.keys(middleware.hooks)) __privateMethod$1(this, _KubbDriver_instances, registerMiddleware_fn).call(this, event, middleware.hooks);
6061
+ if (this.config.adapter) await __privateMethod$1(this, _KubbDriver_instances, registerAdapter_fn).call(this, this.config.adapter);
6062
+ }
6063
+ get hooks() {
6064
+ return this.options.hooks;
6322
6065
  }
6323
6066
  /**
6324
- * Converts the OpenAPI path to a TypeScript template literal string.
6067
+ * Emits the `kubb:plugin:setup` event so that all registered hook-style plugin listeners
6068
+ * can configure generators, resolvers, transformers and renderers before `buildStart` runs.
6325
6069
  *
6326
- * @example
6327
- * new URLPath('/pet/{petId}').template // '`/pet/${petId}`'
6328
- * new URLPath('/account/monetary-accountID').template // '`/account/${monetaryAccountId}`'
6070
+ * Call this once from `safeBuild` before the plugin execution loop begins.
6329
6071
  */
6330
- get template() {
6331
- return this.toTemplateString();
6072
+ async emitSetupHooks() {
6073
+ const noop = () => {
6074
+ };
6075
+ await this.hooks.emit("kubb:plugin:setup", {
6076
+ config: this.config,
6077
+ options: {},
6078
+ addGenerator: noop,
6079
+ setResolver: noop,
6080
+ setTransformer: noop,
6081
+ setRenderer: noop,
6082
+ setOptions: noop,
6083
+ injectFile: noop,
6084
+ updateConfig: noop
6085
+ });
6332
6086
  }
6333
- /** Returns the path and its extracted params as a structured `URLObject`, or as a stringified expression when `stringify` is set.
6087
+ /**
6088
+ * Registers a generator for the given plugin on the shared event emitter.
6334
6089
  *
6335
- * @example
6336
- * ```ts
6337
- * new URLPath('/pet/{petId}').object
6338
- * // { url: '/pet/:petId', params: { petId: 'petId' } }
6339
- * ```
6340
- */
6341
- get object() {
6342
- return this.toObject();
6343
- }
6344
- /** Returns a map of path parameter names, or `undefined` when the path has no parameters.
6090
+ * The generator's `schema`, `operation`, and `operations` methods are registered as
6091
+ * listeners on `kubb:generate:schema`, `kubb:generate:operation`, and `kubb:generate:operations`
6092
+ * respectively. Each listener is scoped to the owning plugin via a `ctx.plugin.name` check
6093
+ * so that generators from different plugins do not cross-fire.
6345
6094
  *
6346
- * @example
6347
- * ```ts
6348
- * new URLPath('/pet/{petId}').params // { petId: 'petId' }
6349
- * new URLPath('/pet').params // undefined
6350
- * ```
6095
+ * The renderer resolution chain is: `generator.renderer → plugin.renderer → config.renderer`.
6096
+ * Set `generator.renderer = null` to explicitly opt out of rendering even when the plugin
6097
+ * declares a renderer.
6098
+ *
6099
+ * Call this method inside `addGenerator()` (in `kubb:plugin:setup`) to wire up a generator.
6351
6100
  */
6352
- get params() {
6353
- return this.getParams();
6354
- }
6355
- toObject({ type = "path", replacer, stringify } = {}) {
6356
- const object = {
6357
- url: type === "path" ? this.toURLPath() : this.toTemplateString({ replacer }),
6358
- params: this.getParams()
6101
+ registerGenerator(pluginName, gen) {
6102
+ const resolveRenderer = () => {
6103
+ var _a2, _b2;
6104
+ const plugin = this.plugins.get(pluginName);
6105
+ return gen.renderer === null ? void 0 : (_b2 = (_a2 = gen.renderer) != null ? _a2 : plugin == null ? void 0 : plugin.renderer) != null ? _b2 : this.config.renderer;
6359
6106
  };
6360
- if (stringify) {
6361
- if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
6362
- if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
6363
- return `{ url: '${object.url}' }`;
6107
+ if (gen.schema) {
6108
+ const schemaHandler = async (node, ctx) => {
6109
+ if (ctx.plugin.name !== pluginName) return;
6110
+ await applyHookResult({
6111
+ result: await gen.schema(node, ctx),
6112
+ driver: this,
6113
+ rendererFactory: resolveRenderer()
6114
+ });
6115
+ };
6116
+ this.hooks.on("kubb:generate:schema", schemaHandler);
6117
+ __privateMethod$1(this, _KubbDriver_instances, trackHookListener_fn).call(this, "kubb:generate:schema", schemaHandler);
6364
6118
  }
6365
- return object;
6119
+ if (gen.operation) {
6120
+ const operationHandler = async (node, ctx) => {
6121
+ if (ctx.plugin.name !== pluginName) return;
6122
+ await applyHookResult({
6123
+ result: await gen.operation(node, ctx),
6124
+ driver: this,
6125
+ rendererFactory: resolveRenderer()
6126
+ });
6127
+ };
6128
+ this.hooks.on("kubb:generate:operation", operationHandler);
6129
+ __privateMethod$1(this, _KubbDriver_instances, trackHookListener_fn).call(this, "kubb:generate:operation", operationHandler);
6130
+ }
6131
+ if (gen.operations) {
6132
+ const operationsHandler = async (nodes, ctx) => {
6133
+ if (ctx.plugin.name !== pluginName) return;
6134
+ await applyHookResult({
6135
+ result: await gen.operations(nodes, ctx),
6136
+ driver: this,
6137
+ rendererFactory: resolveRenderer()
6138
+ });
6139
+ };
6140
+ this.hooks.on("kubb:generate:operations", operationsHandler);
6141
+ __privateMethod$1(this, _KubbDriver_instances, trackHookListener_fn).call(this, "kubb:generate:operations", operationsHandler);
6142
+ }
6143
+ __privateGet$1(this, _eventGeneratorPlugins).add(pluginName);
6366
6144
  }
6367
6145
  /**
6368
- * Converts the OpenAPI path to a TypeScript template literal string.
6369
- * An optional `replacer` can transform each extracted parameter name before interpolation.
6146
+ * Returns `true` when at least one generator was registered for the given plugin
6147
+ * via `addGenerator()` in `kubb:plugin:setup` (event-based path).
6370
6148
  *
6371
- * @example
6372
- * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
6149
+ * Used by the build loop to decide whether to walk the AST and emit generator events
6150
+ * for a plugin that has no static `plugin.generators`.
6373
6151
  */
6374
- toTemplateString({ prefix = "", replacer } = {}) {
6375
- return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
6376
- if (i % 2 === 0) return part;
6377
- const param = __privateMethod(this, _URLPath_instances, transformParam_fn).call(this, part);
6378
- return `\${${replacer ? replacer(param) : param}}`;
6379
- }).join("")}\``;
6152
+ hasEventGenerators(pluginName) {
6153
+ return __privateGet$1(this, _eventGeneratorPlugins).has(pluginName);
6380
6154
  }
6381
6155
  /**
6382
- * Extracts all `{param}` segments from the path and returns them as a key-value map.
6383
- * An optional `replacer` transforms each parameter name in both key and value positions.
6384
- * Returns `undefined` when no path parameters are found.
6385
- *
6386
- * @example
6387
- * ```ts
6388
- * new URLPath('/pet/{petId}/tag/{tagId}').getParams()
6389
- * // { petId: 'petId', tagId: 'tagId' }
6390
- * ```
6156
+ * Runs the full plugin pipeline. Returns timings/failures collected so far even
6157
+ * when an outer hook throws the orchestrator preserves partial state by capturing
6158
+ * the error into `error` instead of propagating.
6159
+ */
6160
+ async run({ storage }) {
6161
+ var _a2;
6162
+ const hooks = this.hooks;
6163
+ const config = this.config;
6164
+ const failedPlugins = /* @__PURE__ */ new Set();
6165
+ const pluginTimings = /* @__PURE__ */ new Map();
6166
+ const parsersMap = /* @__PURE__ */ new Map();
6167
+ for (const parser of config.parsers) if (parser.extNames) for (const ext of parser.extNames) parsersMap.set(ext, parser);
6168
+ const pendingFiles = /* @__PURE__ */ new Map();
6169
+ this.fileManager.setOnUpsert((file) => {
6170
+ pendingFiles.set(file.path, file);
6171
+ });
6172
+ try {
6173
+ const flushPending = async () => {
6174
+ if (pendingFiles.size === 0) return;
6175
+ const files2 = [...pendingFiles.values()];
6176
+ pendingFiles.clear();
6177
+ await hooks.emit("kubb:debug", {
6178
+ date: /* @__PURE__ */ new Date(),
6179
+ logs: [`Writing ${files2.length} files...`]
6180
+ });
6181
+ await hooks.emit("kubb:files:processing:start", { files: files2 });
6182
+ const items = [...__privateGet$1(this, _fileProcessor).stream(files2, {
6183
+ parsers: parsersMap,
6184
+ extension: config.output.extension
6185
+ })];
6186
+ await hooks.emit("kubb:files:processing:update", { files: items.map(({ file, source, processed, total, percentage }) => ({
6187
+ file,
6188
+ source,
6189
+ processed,
6190
+ total,
6191
+ percentage,
6192
+ config
6193
+ })) });
6194
+ const queue = [];
6195
+ for (const { file, source } of items) if (source) {
6196
+ queue.push(storage.setItem(file.path, source));
6197
+ if (queue.length >= 50) await Promise.all(queue.splice(0));
6198
+ }
6199
+ await Promise.all(queue);
6200
+ await hooks.emit("kubb:files:processing:end", { files: files2 });
6201
+ await hooks.emit("kubb:debug", {
6202
+ date: /* @__PURE__ */ new Date(),
6203
+ logs: [`\u2713 File write process completed for ${files2.length} files`]
6204
+ });
6205
+ };
6206
+ await this.emitSetupHooks();
6207
+ if (this.adapter && this.inputNode) await hooks.emit("kubb:build:start", Object.assign({
6208
+ config,
6209
+ adapter: this.adapter,
6210
+ meta: this.inputNode.meta,
6211
+ getPlugin: this.getPlugin.bind(this)
6212
+ }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6213
+ const generatorPlugins = [];
6214
+ for (const plugin of this.plugins.values()) {
6215
+ const context = this.getContext(plugin);
6216
+ const hrStart = process.hrtime();
6217
+ try {
6218
+ await hooks.emit("kubb:plugin:start", { plugin });
6219
+ await hooks.emit("kubb:debug", {
6220
+ date: /* @__PURE__ */ new Date(),
6221
+ logs: ["Starting plugin...", ` \u2022 Plugin Name: ${plugin.name}`]
6222
+ });
6223
+ } catch (caughtError) {
6224
+ const error = caughtError;
6225
+ const duration2 = getElapsedMs(hrStart);
6226
+ pluginTimings.set(plugin.name, duration2);
6227
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6228
+ plugin,
6229
+ duration: duration2,
6230
+ success: false,
6231
+ error
6232
+ });
6233
+ failedPlugins.add({
6234
+ plugin,
6235
+ error
6236
+ });
6237
+ continue;
6238
+ }
6239
+ if (((_a2 = plugin.generators) == null ? void 0 : _a2.length) || this.hasEventGenerators(plugin.name)) {
6240
+ generatorPlugins.push({
6241
+ plugin,
6242
+ context,
6243
+ hrStart
6244
+ });
6245
+ continue;
6246
+ }
6247
+ const duration = getElapsedMs(hrStart);
6248
+ pluginTimings.set(plugin.name, duration);
6249
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6250
+ plugin,
6251
+ duration,
6252
+ success: true
6253
+ });
6254
+ await hooks.emit("kubb:debug", {
6255
+ date: /* @__PURE__ */ new Date(),
6256
+ logs: [`\u2713 Plugin started successfully (${formatMs(duration)})`]
6257
+ });
6258
+ }
6259
+ if (generatorPlugins.length > 0) if (this.inputNode) {
6260
+ const { timings, failed } = await __privateMethod$1(this, _KubbDriver_instances, runGenerators_fn).call(this, generatorPlugins, flushPending);
6261
+ await flushPending();
6262
+ for (const [name, duration] of timings) pluginTimings.set(name, duration);
6263
+ for (const entry of failed) failedPlugins.add(entry);
6264
+ } else for (const { plugin, hrStart } of generatorPlugins) {
6265
+ const duration = getElapsedMs(hrStart);
6266
+ pluginTimings.set(plugin.name, duration);
6267
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6268
+ plugin,
6269
+ duration,
6270
+ success: true
6271
+ });
6272
+ }
6273
+ await hooks.emit("kubb:plugins:end", Object.assign({ config }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6274
+ await flushPending();
6275
+ const files = this.fileManager.files;
6276
+ await hooks.emit("kubb:build:end", {
6277
+ files,
6278
+ config,
6279
+ outputDir: resolve(config.root, config.output.path)
6280
+ });
6281
+ return {
6282
+ failedPlugins,
6283
+ pluginTimings
6284
+ };
6285
+ } catch (caughtError) {
6286
+ return {
6287
+ failedPlugins,
6288
+ pluginTimings,
6289
+ error: caughtError
6290
+ };
6291
+ } finally {
6292
+ this.fileManager.setOnUpsert(null);
6293
+ }
6294
+ }
6295
+ /**
6296
+ * Unregisters all plugin lifecycle listeners from the shared event emitter.
6297
+ * Called at the end of a build to prevent listener leaks across repeated builds.
6298
+ *
6299
+ * @internal
6391
6300
  */
6392
- getParams(replacer) {
6393
- const params = {};
6394
- __privateMethod(this, _URLPath_instances, eachParam_fn).call(this, (_raw, param) => {
6395
- const key = replacer ? replacer(param) : param;
6396
- params[key] = key;
6301
+ dispose() {
6302
+ for (const [event, handlers] of __privateGet$1(this, _hookListeners)) for (const handler of handlers) this.hooks.off(event, handler);
6303
+ __privateGet$1(this, _hookListeners).clear();
6304
+ __privateGet$1(this, _eventGeneratorPlugins).clear();
6305
+ __privateGet$1(this, _resolvers).clear();
6306
+ __privateGet$1(this, _defaultResolvers).clear();
6307
+ this.fileManager.dispose();
6308
+ __privateGet$1(this, _fileProcessor).dispose();
6309
+ this.inputNode = null;
6310
+ __privateSet$1(this, _studio, {
6311
+ source: null,
6312
+ isOpen: false,
6313
+ inputNode: null
6397
6314
  });
6398
- return Object.keys(params).length > 0 ? params : void 0;
6315
+ for (const [event, handler] of __privateGet$1(this, _middlewareListeners)) this.hooks.off(event, handler);
6399
6316
  }
6400
- /** Converts the OpenAPI path to Express-style colon syntax.
6401
- *
6402
- * @example
6403
- * ```ts
6404
- * new URLPath('/pet/{petId}').toURLPath() // '/pet/:petId'
6405
- * ```
6317
+ [Symbol.dispose]() {
6318
+ this.dispose();
6319
+ }
6320
+ /**
6321
+ * Merges `partial` with the plugin's default resolver and stores the result.
6322
+ * Also mirrors it onto `plugin.resolver` so callers using `getPlugin(name).resolver`
6323
+ * get the up-to-date resolver without going through `getResolver()`.
6406
6324
  */
6407
- toURLPath() {
6408
- return this.path.replace(/\{([^}]+)\}/g, ":$1");
6325
+ setPluginResolver(pluginName, partial) {
6326
+ const merged = {
6327
+ ...__privateGet$1(this, _getDefaultResolver).call(this, pluginName),
6328
+ ...partial
6329
+ };
6330
+ __privateGet$1(this, _resolvers).set(pluginName, merged);
6331
+ const plugin = this.plugins.get(pluginName);
6332
+ if (plugin) plugin.resolver = merged;
6409
6333
  }
6410
- }, _options = new WeakMap(), _URLPath_instances = new WeakSet(), transformParam_fn = function(raw) {
6411
- const param = isValidVarName(raw) ? raw : camelCase(raw);
6412
- return __privateGet(this, _options).casing === "camelcase" ? camelCase(param) : param;
6413
- }, /**
6414
- * Iterates over every `{param}` token in `path`, calling `fn` with the raw token and transformed name.
6415
- */
6416
- eachParam_fn = function(fn) {
6417
- for (const match of this.path.matchAll(/\{([^}]+)\}/g)) {
6418
- const raw = match[1];
6419
- fn(raw, __privateMethod(this, _URLPath_instances, transformParam_fn).call(this, raw));
6334
+ getResolver(pluginName) {
6335
+ var _a2, _b2, _c2;
6336
+ return (_c2 = (_b2 = __privateGet$1(this, _resolvers).get(pluginName)) != null ? _b2 : (_a2 = this.plugins.get(pluginName)) == null ? void 0 : _a2.resolver) != null ? _c2 : __privateGet$1(this, _getDefaultResolver).call(this, pluginName);
6420
6337
  }
6421
- }, _b);
6422
- var Node$1 = (_c = class {
6423
- constructor(value) {
6424
- __publicField(this, "value");
6425
- __publicField(this, "next");
6426
- this.value = value;
6427
- }
6428
- }, __name(_c, "Node"), _c);
6429
- var Queue = (_d = class {
6430
- constructor() {
6431
- __privateAdd(this, _head);
6432
- __privateAdd(this, _tail);
6433
- __privateAdd(this, _size);
6434
- this.clear();
6338
+ getContext(plugin) {
6339
+ const driver = this;
6340
+ return {
6341
+ config: driver.config,
6342
+ get root() {
6343
+ return resolve(driver.config.root, driver.config.output.path);
6344
+ },
6345
+ getMode(output) {
6346
+ return _d.getMode(resolve(driver.config.root, driver.config.output.path, output.path));
6347
+ },
6348
+ hooks: driver.hooks,
6349
+ plugin,
6350
+ getPlugin: driver.getPlugin.bind(driver),
6351
+ requirePlugin: driver.requirePlugin.bind(driver),
6352
+ getResolver: driver.getResolver.bind(driver),
6353
+ driver,
6354
+ addFile: async (...files) => {
6355
+ driver.fileManager.add(...files);
6356
+ },
6357
+ upsertFile: async (...files) => {
6358
+ driver.fileManager.upsert(...files);
6359
+ },
6360
+ get meta() {
6361
+ var _a2, _b2;
6362
+ return (_b2 = (_a2 = driver.inputNode) == null ? void 0 : _a2.meta) != null ? _b2 : {
6363
+ circularNames: [],
6364
+ enumNames: []
6365
+ };
6366
+ },
6367
+ get adapter() {
6368
+ return driver.adapter;
6369
+ },
6370
+ get resolver() {
6371
+ return driver.getResolver(plugin.name);
6372
+ },
6373
+ get transformer() {
6374
+ return plugin.transformer;
6375
+ },
6376
+ warn(message) {
6377
+ driver.hooks.emit("kubb:warn", { message });
6378
+ },
6379
+ error(error) {
6380
+ driver.hooks.emit("kubb:error", { error: typeof error === "string" ? new Error(error) : error });
6381
+ },
6382
+ info(message) {
6383
+ driver.hooks.emit("kubb:info", { message });
6384
+ },
6385
+ async openInStudio(options) {
6386
+ var _a2, _b2, _c2, _d2;
6387
+ if (!driver.config.devtools || __privateGet$1(driver, _studio).isOpen) return;
6388
+ if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
6389
+ if (!driver.adapter || !__privateGet$1(driver, _studio).source) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
6390
+ __privateGet$1(driver, _studio).isOpen = true;
6391
+ const studioUrl = (_b2 = (_a2 = driver.config.devtools) == null ? void 0 : _a2.studioUrl) != null ? _b2 : "https://kubb.studio";
6392
+ (_d2 = (_c2 = __privateGet$1(driver, _studio)).inputNode) != null ? _d2 : _c2.inputNode = Promise.resolve(driver.adapter.parse(__privateGet$1(driver, _studio).source));
6393
+ return openInStudio(await __privateGet$1(driver, _studio).inputNode, studioUrl, options);
6394
+ }
6395
+ };
6435
6396
  }
6436
- enqueue(value) {
6437
- const node = new Node$1(value);
6438
- if (__privateGet(this, _head)) {
6439
- __privateGet(this, _tail).next = node;
6440
- __privateSet(this, _tail, node);
6441
- } else {
6442
- __privateSet(this, _head, node);
6443
- __privateSet(this, _tail, node);
6397
+ getPlugin(pluginName) {
6398
+ return this.plugins.get(pluginName);
6399
+ }
6400
+ requirePlugin(pluginName) {
6401
+ const plugin = this.plugins.get(pluginName);
6402
+ if (!plugin) throw new Error(`[kubb] Plugin "${pluginName}" is required but not found. Make sure it is included in your Kubb config.`);
6403
+ return plugin;
6404
+ }
6405
+ }, _studio = new WeakMap(), _middlewareListeners = new WeakMap(), _fileProcessor = new WeakMap(), _eventGeneratorPlugins = new WeakMap(), _resolvers = new WeakMap(), _defaultResolvers = new WeakMap(), _hookListeners = new WeakMap(), _KubbDriver_instances = new WeakSet(), /**
6406
+ * Creates an `NormalizedPlugin` from a hook-style plugin and registers
6407
+ * its lifecycle handlers on the `AsyncEventEmitter`.
6408
+ */
6409
+ normalizePlugin_fn = function(plugin) {
6410
+ var _a2;
6411
+ const normalized = {
6412
+ name: plugin.name,
6413
+ dependencies: plugin.dependencies,
6414
+ enforce: plugin.enforce,
6415
+ hooks: plugin.hooks,
6416
+ options: (_a2 = plugin.options) != null ? _a2 : {
6417
+ output: { path: "." },
6418
+ exclude: [],
6419
+ override: []
6444
6420
  }
6445
- __privateWrapper(this, _size)._++;
6421
+ };
6422
+ if ("apply" in plugin && typeof plugin.apply === "function") normalized.apply = plugin.apply;
6423
+ return normalized;
6424
+ }, registerAdapter_fn = async function(adapter) {
6425
+ const source = inputToAdapterSource(this.config);
6426
+ __privateGet$1(this, _studio).source = source;
6427
+ if (adapter.stream) {
6428
+ this.inputNode = await adapter.stream(source);
6429
+ await this.hooks.emit("kubb:debug", {
6430
+ date: /* @__PURE__ */ new Date(),
6431
+ logs: [`\u2713 Adapter '${adapter.name}' producing input stream`]
6432
+ });
6433
+ } else {
6434
+ const inputNode = await adapter.parse(source);
6435
+ this.inputNode = createStreamInput(arrayToAsyncIterable(inputNode.schemas), arrayToAsyncIterable(inputNode.operations), inputNode.meta);
6436
+ await this.hooks.emit("kubb:debug", {
6437
+ date: /* @__PURE__ */ new Date(),
6438
+ logs: [
6439
+ `\u2713 Adapter '${adapter.name}' resolved InputNode (wrapped as stream)`,
6440
+ ` \u2022 Schemas: ${inputNode.schemas.length}`,
6441
+ ` \u2022 Operations: ${inputNode.operations.length}`
6442
+ ]
6443
+ });
6446
6444
  }
6447
- dequeue() {
6448
- const current = __privateGet(this, _head);
6449
- if (!current) return;
6450
- __privateSet(this, _head, __privateGet(this, _head).next);
6451
- __privateWrapper(this, _size)._--;
6452
- if (!__privateGet(this, _head)) __privateSet(this, _tail, void 0);
6453
- return current.value;
6445
+ }, registerMiddleware_fn = function(event, middlewareHooks) {
6446
+ const handler = middlewareHooks[event];
6447
+ if (!handler) return;
6448
+ this.hooks.on(event, handler);
6449
+ __privateGet$1(this, _middlewareListeners).push([event, handler]);
6450
+ }, /**
6451
+ * Registers a hook-style plugin's lifecycle handlers on the shared `AsyncEventEmitter`.
6452
+ *
6453
+ * For `kubb:plugin:setup`, the registered listener wraps the globally emitted context with a
6454
+ * plugin-specific one so that `addGenerator`, `setResolver`, `setTransformer`, and
6455
+ * `setRenderer` all target the correct `normalizedPlugin` entry in the plugins map.
6456
+ *
6457
+ * All other hooks are iterated and registered directly as pass-through listeners.
6458
+ * Any event key present in the global `KubbHooks` interface can be subscribed to.
6459
+ *
6460
+ * External tooling can subscribe to any of these events via `hooks.on(...)` to observe
6461
+ * the plugin lifecycle without modifying plugin behavior.
6462
+ *
6463
+ * @internal
6464
+ */
6465
+ registerPlugin_fn = function(plugin) {
6466
+ const { hooks } = plugin;
6467
+ if (!hooks) return;
6468
+ if (hooks["kubb:plugin:setup"]) {
6469
+ const setupHandler = (globalCtx) => {
6470
+ var _a2;
6471
+ const pluginCtx = {
6472
+ ...globalCtx,
6473
+ options: (_a2 = plugin.options) != null ? _a2 : {},
6474
+ addGenerator: (gen) => {
6475
+ this.registerGenerator(plugin.name, gen);
6476
+ },
6477
+ setResolver: (resolver) => {
6478
+ this.setPluginResolver(plugin.name, resolver);
6479
+ },
6480
+ setTransformer: (visitor) => {
6481
+ plugin.transformer = visitor;
6482
+ },
6483
+ setRenderer: (renderer) => {
6484
+ plugin.renderer = renderer;
6485
+ },
6486
+ setOptions: (opts) => {
6487
+ plugin.options = {
6488
+ ...plugin.options,
6489
+ ...opts
6490
+ };
6491
+ },
6492
+ injectFile: (userFileNode) => {
6493
+ this.fileManager.add(createFile(userFileNode));
6494
+ }
6495
+ };
6496
+ return hooks["kubb:plugin:setup"](pluginCtx);
6497
+ };
6498
+ this.hooks.on("kubb:plugin:setup", setupHandler);
6499
+ __privateMethod$1(this, _KubbDriver_instances, trackHookListener_fn).call(this, "kubb:plugin:setup", setupHandler);
6454
6500
  }
6455
- peek() {
6456
- if (!__privateGet(this, _head)) return;
6457
- return __privateGet(this, _head).value;
6501
+ for (const [event, handler] of Object.entries(hooks)) {
6502
+ if (event === "kubb:plugin:setup" || !handler) continue;
6503
+ this.hooks.on(event, handler);
6504
+ __privateMethod$1(this, _KubbDriver_instances, trackHookListener_fn).call(this, event, handler);
6458
6505
  }
6459
- clear() {
6460
- __privateSet(this, _head, void 0);
6461
- __privateSet(this, _tail, void 0);
6462
- __privateSet(this, _size, 0);
6463
- }
6464
- get size() {
6465
- return __privateGet(this, _size);
6466
- }
6467
- *[Symbol.iterator]() {
6468
- let current = __privateGet(this, _head);
6469
- while (current) {
6470
- yield current.value;
6471
- current = current.next;
6472
- }
6473
- }
6474
- *drain() {
6475
- while (__privateGet(this, _head)) yield this.dequeue();
6476
- }
6477
- }, _head = new WeakMap(), _tail = new WeakMap(), _size = new WeakMap(), _d);
6478
- function pLimit(concurrency) {
6479
- let rejectOnClear = false;
6480
- if (typeof concurrency === "object") ({ concurrency, rejectOnClear = false } = concurrency);
6481
- validateConcurrency(concurrency);
6482
- if (typeof rejectOnClear !== "boolean") throw new TypeError("Expected `rejectOnClear` to be a boolean");
6483
- const queue = new Queue();
6484
- let activeCount = 0;
6485
- const resumeNext = () => {
6486
- if (activeCount < concurrency && queue.size > 0) {
6487
- activeCount++;
6488
- queue.dequeue().run();
6489
- }
6506
+ }, filesPayload_fn = function() {
6507
+ const driver = this;
6508
+ return {
6509
+ get files() {
6510
+ return driver.fileManager.files;
6511
+ },
6512
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
6490
6513
  };
6491
- const next = () => {
6492
- activeCount--;
6493
- resumeNext();
6514
+ }, emitPluginEnd_fn = function({ plugin, duration, success, error }) {
6515
+ return this.hooks.emit("kubb:plugin:end", Object.assign({
6516
+ plugin,
6517
+ duration,
6518
+ success,
6519
+ ...error ? { error } : {},
6520
+ config: this.config
6521
+ }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6522
+ }, runGenerators_fn = async function(entries, flushPending) {
6523
+ var _a2, _b2;
6524
+ const timings = /* @__PURE__ */ new Map();
6525
+ const failed = /* @__PURE__ */ new Set();
6526
+ const driver = this;
6527
+ const { schemas, operations } = this.inputNode;
6528
+ const states = entries.map(({ plugin, context, hrStart }) => {
6529
+ var _a3;
6530
+ const { exclude, include, override } = plugin.options;
6531
+ const hasExclude = Array.isArray(exclude) && exclude.length > 0;
6532
+ const hasInclude = Array.isArray(include) && include.length > 0;
6533
+ const hasOverride = Array.isArray(override) && override.length > 0;
6534
+ return {
6535
+ plugin,
6536
+ generatorContext: {
6537
+ ...context,
6538
+ resolver: this.getResolver(plugin.name)
6539
+ },
6540
+ generators: (_a3 = plugin.generators) != null ? _a3 : [],
6541
+ hrStart,
6542
+ failed: false,
6543
+ error: null,
6544
+ optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,
6545
+ allowedSchemaNames: null
6546
+ };
6547
+ });
6548
+ const emitsSchemaHook = this.hooks.listenerCount("kubb:generate:schema") > 0;
6549
+ const emitsOperationHook = this.hooks.listenerCount("kubb:generate:operation") > 0;
6550
+ const pruningStates = states.filter(({ plugin }) => {
6551
+ var _a3, _b3;
6552
+ const { include } = plugin.options;
6553
+ return ((_a3 = include == null ? void 0 : include.some(({ type }) => OPERATION_FILTER_TYPES.has(type))) != null ? _a3 : false) && !((_b3 = include == null ? void 0 : include.some(({ type }) => type === "schemaName")) != null ? _b3 : false);
6554
+ });
6555
+ if (pruningStates.length > 0) {
6556
+ const allSchemas = [];
6557
+ for await (const schema of schemas) allSchemas.push(schema);
6558
+ const includedOpsByState = new Map(pruningStates.map((s) => [s, []]));
6559
+ for await (const operation of operations) for (const state of pruningStates) {
6560
+ const { exclude, include, override } = state.plugin.options;
6561
+ if (state.generatorContext.resolver.resolveOptions(operation, {
6562
+ options: state.plugin.options,
6563
+ exclude,
6564
+ include,
6565
+ override
6566
+ }) !== null) (_a2 = includedOpsByState.get(state)) == null ? void 0 : _a2.push(operation);
6567
+ }
6568
+ for (const state of pruningStates) {
6569
+ state.allowedSchemaNames = collectUsedSchemaNames((_b2 = includedOpsByState.get(state)) != null ? _b2 : [], allSchemas);
6570
+ includedOpsByState.delete(state);
6571
+ }
6572
+ }
6573
+ const resolveRendererFor = (gen, state) => {
6574
+ var _a3, _b3;
6575
+ return gen.renderer === null ? void 0 : (_b3 = (_a3 = gen.renderer) != null ? _a3 : state.plugin.renderer) != null ? _b3 : state.generatorContext.config.renderer;
6494
6576
  };
6495
- const run = async (function_, resolve2, arguments_) => {
6496
- const result = (async () => function_(...arguments_))();
6497
- resolve2(result);
6577
+ const dispatchSchema = async (state, node) => {
6578
+ if (state.failed) return;
6498
6579
  try {
6499
- await result;
6500
- } catch {
6580
+ const { plugin, generatorContext, generators } = state;
6581
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6582
+ if (state.allowedSchemaNames !== null && transformedNode.name && !state.allowedSchemaNames.has(transformedNode.name)) return;
6583
+ const { exclude, include, override } = plugin.options;
6584
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6585
+ options: plugin.options,
6586
+ exclude,
6587
+ include,
6588
+ override
6589
+ });
6590
+ if (options === null) return;
6591
+ const ctx = {
6592
+ ...generatorContext,
6593
+ options
6594
+ };
6595
+ for (const gen of generators) {
6596
+ if (!gen.schema) continue;
6597
+ const raw = gen.schema(transformedNode, ctx);
6598
+ const applied = applyHookResult({
6599
+ result: isPromise(raw) ? await raw : raw,
6600
+ driver,
6601
+ rendererFactory: resolveRendererFor(gen, state)
6602
+ });
6603
+ if (isPromise(applied)) await applied;
6604
+ }
6605
+ if (emitsSchemaHook) await this.hooks.emit("kubb:generate:schema", transformedNode, ctx);
6606
+ } catch (caughtError) {
6607
+ state.failed = true;
6608
+ state.error = caughtError;
6501
6609
  }
6502
- next();
6503
6610
  };
6504
- const enqueue = (function_, resolve2, reject, arguments_) => {
6505
- const queueItem = { reject };
6506
- new Promise((internalResolve) => {
6507
- queueItem.run = internalResolve;
6508
- queue.enqueue(queueItem);
6509
- }).then(run.bind(void 0, function_, resolve2, arguments_));
6510
- if (activeCount < concurrency) resumeNext();
6611
+ const dispatchOperation = async (state, node) => {
6612
+ if (state.failed) return;
6613
+ try {
6614
+ const { plugin, generatorContext, generators } = state;
6615
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6616
+ const { exclude, include, override } = plugin.options;
6617
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6618
+ options: plugin.options,
6619
+ exclude,
6620
+ include,
6621
+ override
6622
+ });
6623
+ if (options === null) return;
6624
+ const ctx = {
6625
+ ...generatorContext,
6626
+ options
6627
+ };
6628
+ for (const gen of generators) {
6629
+ if (!gen.operation) continue;
6630
+ const raw = gen.operation(transformedNode, ctx);
6631
+ const applied = applyHookResult({
6632
+ result: isPromise(raw) ? await raw : raw,
6633
+ driver,
6634
+ rendererFactory: resolveRendererFor(gen, state)
6635
+ });
6636
+ if (isPromise(applied)) await applied;
6637
+ }
6638
+ if (emitsOperationHook) await this.hooks.emit("kubb:generate:operation", transformedNode, ctx);
6639
+ } catch (caughtError) {
6640
+ state.failed = true;
6641
+ state.error = caughtError;
6642
+ }
6511
6643
  };
6512
- const generator = (function_, ...arguments_) => new Promise((resolve2, reject) => {
6513
- enqueue(function_, resolve2, reject, arguments_);
6644
+ const needsCollectedOperations = this.hooks.listenerCount("kubb:generate:operations") > 0 || states.some((s) => s.generators.some((g) => !!g.operations));
6645
+ const collectedOperations = needsCollectedOperations ? [] : void 0;
6646
+ await forBatches(schemas, (nodes) => Promise.all(nodes.flatMap((n) => states.map((state) => dispatchSchema(state, n)))), {
6647
+ concurrency: 8,
6648
+ flush: flushPending
6514
6649
  });
6515
- Object.defineProperties(generator, {
6516
- activeCount: { get: () => activeCount },
6517
- pendingCount: { get: () => queue.size },
6518
- clearQueue: { value() {
6519
- if (!rejectOnClear) {
6520
- queue.clear();
6521
- return;
6522
- }
6523
- const abortError = AbortSignal.abort().reason;
6524
- while (queue.size > 0) queue.dequeue().reject(abortError);
6525
- } },
6526
- concurrency: {
6527
- get: () => concurrency,
6528
- set(newConcurrency) {
6529
- validateConcurrency(newConcurrency);
6530
- concurrency = newConcurrency;
6531
- queueMicrotask(() => {
6532
- while (activeCount < concurrency && queue.size > 0) resumeNext();
6650
+ await forBatches(operations, (nodes) => {
6651
+ if (needsCollectedOperations) collectedOperations.push(...nodes);
6652
+ return Promise.all(nodes.flatMap((n) => states.map((state) => dispatchOperation(state, n))));
6653
+ }, {
6654
+ concurrency: 8,
6655
+ flush: flushPending
6656
+ });
6657
+ for (const state of states) {
6658
+ if (!state.failed && needsCollectedOperations) try {
6659
+ const { plugin, generatorContext, generators } = state;
6660
+ const ctx = {
6661
+ ...generatorContext,
6662
+ options: plugin.options
6663
+ };
6664
+ for (const gen of generators) {
6665
+ if (!gen.operations) continue;
6666
+ await applyHookResult({
6667
+ result: await gen.operations(collectedOperations, ctx),
6668
+ driver,
6669
+ rendererFactory: resolveRendererFor(gen, state)
6533
6670
  });
6534
6671
  }
6535
- },
6536
- map: { async value(iterable, function_) {
6537
- const promises = Array.from(iterable, (value, index) => this(function_, value, index));
6538
- return Promise.all(promises);
6539
- } }
6672
+ await this.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
6673
+ } catch (caughtError) {
6674
+ state.failed = true;
6675
+ state.error = caughtError;
6676
+ }
6677
+ const duration = getElapsedMs(state.hrStart);
6678
+ timings.set(state.plugin.name, duration);
6679
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6680
+ plugin: state.plugin,
6681
+ duration,
6682
+ success: !state.failed,
6683
+ error: state.failed && state.error ? state.error : void 0
6684
+ });
6685
+ if (state.failed && state.error) failed.add({
6686
+ plugin: state.plugin,
6687
+ error: state.error
6688
+ });
6689
+ await this.hooks.emit("kubb:debug", {
6690
+ date: /* @__PURE__ */ new Date(),
6691
+ logs: [state.failed ? "\u2717 Plugin start failed" : `\u2713 Plugin started successfully (${formatMs(duration)})`]
6692
+ });
6693
+ }
6694
+ return {
6695
+ timings,
6696
+ failed
6697
+ };
6698
+ }, trackHookListener_fn = function(event, handler) {
6699
+ let handlers = __privateGet$1(this, _hookListeners).get(event);
6700
+ if (!handlers) {
6701
+ handlers = /* @__PURE__ */ new Set();
6702
+ __privateGet$1(this, _hookListeners).set(event, handlers);
6703
+ }
6704
+ handlers.add(handler);
6705
+ }, _getDefaultResolver = new WeakMap(), _d);
6706
+ function applyHookResult({ result, driver, rendererFactory }) {
6707
+ if (!result) return;
6708
+ if (Array.isArray(result)) {
6709
+ driver.fileManager.upsert(...result);
6710
+ return;
6711
+ }
6712
+ if (!rendererFactory) return;
6713
+ const renderer = rendererFactory();
6714
+ if (renderer.stream) try {
6715
+ var _usingCtx$1 = _usingCtx();
6716
+ const r = _usingCtx$1.u(renderer);
6717
+ for (const file of r.stream(result)) driver.fileManager.upsert(file);
6718
+ return;
6719
+ } catch (_) {
6720
+ _usingCtx$1.e = _;
6721
+ } finally {
6722
+ _usingCtx$1.d();
6723
+ }
6724
+ return applyAsyncRender({
6725
+ renderer,
6726
+ result,
6727
+ driver
6540
6728
  });
6541
- return generator;
6542
6729
  }
6543
- function validateConcurrency(concurrency) {
6544
- if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
6730
+ async function applyAsyncRender({ renderer, result, driver }) {
6731
+ try {
6732
+ var _usingCtx3 = _usingCtx();
6733
+ const r = _usingCtx3.u(renderer);
6734
+ await r.render(result);
6735
+ driver.fileManager.upsert(...r.files);
6736
+ } catch (_) {
6737
+ _usingCtx3.e = _;
6738
+ } finally {
6739
+ _usingCtx3.d();
6740
+ }
6545
6741
  }
6546
- function joinSources(file) {
6547
- return file.sources.map((item) => extractStringsFromNodes(item.nodes)).filter(Boolean).join("\n\n");
6742
+ function inputToAdapterSource(config) {
6743
+ const input = config.input;
6744
+ if (!input) throw new Error("[kubb] input is required when using an adapter. Provide input.path or input.data in your config.");
6745
+ if ("data" in input) return {
6746
+ type: "data",
6747
+ data: input.data
6748
+ };
6749
+ if (new URLPath(input.path).isURL) return {
6750
+ type: "path",
6751
+ path: input.path
6752
+ };
6753
+ return {
6754
+ type: "path",
6755
+ path: resolve(config.root, input.path)
6756
+ };
6548
6757
  }
6549
- var FileProcessor = (_e = class {
6550
- constructor() {
6551
- __privateAdd(this, _limit, pLimit(100));
6552
- }
6553
- async parse(file, { parsers, extension } = {}) {
6554
- const parseExtName = (extension == null ? void 0 : extension[file.extname]) || void 0;
6555
- if (!parsers || !file.extname) return joinSources(file);
6556
- const parser = parsers.get(file.extname);
6557
- if (!parser) return joinSources(file);
6558
- return parser.parse(file, { extname: parseExtName });
6559
- }
6560
- async run(files, { parsers, mode = "sequential", extension, onStart, onEnd, onUpdate } = {}) {
6561
- await (onStart == null ? void 0 : onStart(files));
6562
- const total = files.length;
6563
- let processed = 0;
6564
- const processOne = async (file) => {
6565
- const source = await this.parse(file, {
6566
- extension,
6567
- parsers
6568
- });
6569
- const currentProcessed = ++processed;
6570
- const percentage = currentProcessed / total * 100;
6571
- await (onUpdate == null ? void 0 : onUpdate({
6572
- file,
6573
- source,
6574
- processed: currentProcessed,
6575
- percentage,
6576
- total
6577
- }));
6578
- };
6579
- if (mode === "sequential") for (const file of files) await processOne(file);
6580
- else await Promise.all(files.map((file) => __privateGet(this, _limit).call(this, () => processOne(file))));
6581
- await (onEnd == null ? void 0 : onEnd(files));
6582
- return files;
6758
+
6759
+ var __defProp = Object.defineProperty;
6760
+ var __typeError = (msg) => {
6761
+ throw TypeError(msg);
6762
+ };
6763
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6764
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
6765
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
6766
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6767
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
6768
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
6769
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
6770
+ var _userConfig, _config, _driver, _storage, _Kubb_instances, configLogs_fn, _a;
6771
+ async function exists(path) {
6772
+ if (typeof Bun !== "undefined") return Bun.file(path).exists();
6773
+ return access(path).then(() => true, () => false);
6774
+ }
6775
+ async function write(path, data, options = {}) {
6776
+ const trimmed = data.trim();
6777
+ if (trimmed === "") return null;
6778
+ const resolved = resolve(path);
6779
+ if (typeof Bun !== "undefined") {
6780
+ const file = Bun.file(resolved);
6781
+ if ((await file.exists() ? await file.text() : null) === trimmed) return null;
6782
+ await Bun.write(resolved, trimmed);
6783
+ return trimmed;
6784
+ }
6785
+ try {
6786
+ if (await readFile$1(resolved, { encoding: "utf-8" }) === trimmed) return null;
6787
+ } catch {
6788
+ }
6789
+ await mkdir(dirname(resolved), { recursive: true });
6790
+ await writeFile$1(resolved, trimmed, { encoding: "utf-8" });
6791
+ if (options.sanity) {
6792
+ const savedData = await readFile$1(resolved, { encoding: "utf-8" });
6793
+ if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}
6794
+
6795
+ Data[${data.length}]:
6796
+ ${data}
6797
+
6798
+ Saved[${savedData.length}]:
6799
+ ${savedData}
6800
+ `);
6801
+ return savedData;
6583
6802
  }
6584
- }, _limit = new WeakMap(), _e);
6585
- function createStorage(build2) {
6586
- return (options) => build2(options != null ? options : {});
6803
+ return trimmed;
6804
+ }
6805
+ async function clean(path) {
6806
+ return rm(path, {
6807
+ recursive: true,
6808
+ force: true
6809
+ });
6587
6810
  }
6588
- function isMissingPathError(error) {
6589
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
6811
+ var version$1 = "5.0.0-beta.21";
6812
+ function createStorage(build) {
6813
+ return (options) => build(options != null ? options : {});
6590
6814
  }
6591
6815
  const fsStorage = createStorage(() => ({
6592
6816
  name: "fs",
@@ -6594,17 +6818,15 @@ const fsStorage = createStorage(() => ({
6594
6818
  try {
6595
6819
  await access(resolve(key));
6596
6820
  return true;
6597
- } catch (error) {
6598
- if (isMissingPathError(error)) return false;
6599
- throw new Error(`Failed to access storage item "${key}"`, { cause: error });
6821
+ } catch (_error) {
6822
+ return false;
6600
6823
  }
6601
6824
  },
6602
6825
  async getItem(key) {
6603
6826
  try {
6604
6827
  return await readFile$1(resolve(key), "utf8");
6605
- } catch (error) {
6606
- if (isMissingPathError(error)) return null;
6607
- throw new Error(`Failed to read storage item "${key}"`, { cause: error });
6828
+ } catch (_error) {
6829
+ return null;
6608
6830
  }
6609
6831
  },
6610
6832
  async setItem(key, value) {
@@ -6614,23 +6836,22 @@ const fsStorage = createStorage(() => ({
6614
6836
  await rm(resolve(key), { force: true });
6615
6837
  },
6616
6838
  async getKeys(base) {
6617
- const keys = [];
6618
6839
  const resolvedBase = resolve(base != null ? base : process.cwd());
6619
- async function walk2(dir, prefix) {
6840
+ async function* walk(dir, prefix) {
6620
6841
  let entries;
6621
6842
  try {
6622
6843
  entries = await readdir$1(dir, { withFileTypes: true });
6623
- } catch (error) {
6624
- if (isMissingPathError(error)) return;
6625
- throw new Error(`Failed to list storage keys under "${resolvedBase}"`, { cause: error });
6844
+ } catch (_error) {
6845
+ return;
6626
6846
  }
6627
6847
  for (const entry of entries) {
6628
6848
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
6629
- if (entry.isDirectory()) await walk2(join(dir, entry.name), rel);
6630
- else keys.push(rel);
6849
+ if (entry.isDirectory()) yield* walk(join(dir, entry.name), rel);
6850
+ else yield rel;
6631
6851
  }
6632
6852
  }
6633
- await walk2(resolvedBase, "");
6853
+ const keys = [];
6854
+ for await (const key of walk(resolvedBase, "")) keys.push(key);
6634
6855
  return keys;
6635
6856
  },
6636
6857
  async clear(base) {
@@ -6638,410 +6859,192 @@ const fsStorage = createStorage(() => ({
6638
6859
  await clean(resolve(base));
6639
6860
  }
6640
6861
  }));
6641
- var version$1 = "5.0.0-beta.2";
6642
- function getDiagnosticInfo() {
6643
- return {
6644
- nodeVersion: version$2,
6645
- KubbVersion: version$1,
6646
- platform: process.platform,
6647
- arch: process.arch,
6648
- cwd: process.cwd()
6649
- };
6650
- }
6651
- function isInputPath(config) {
6652
- return typeof (config == null ? void 0 : config.input) === "object" && config.input !== null && "path" in config.input;
6653
- }
6654
- async function setup(userConfig, options = {}) {
6655
- var _a2, _b2, _c2, _d2, _e2, _f, _g, _h, _i;
6656
- const hooks = (_a2 = options.hooks) != null ? _a2 : new AsyncEventEmitter();
6657
- const sources = /* @__PURE__ */ new Map();
6658
- const diagnosticInfo = getDiagnosticInfo();
6659
- if (Array.isArray(userConfig.input)) await hooks.emit("kubb:warn", { message: "This feature is still under development \u2014 use with caution" });
6660
- await hooks.emit("kubb:debug", {
6661
- date: /* @__PURE__ */ new Date(),
6662
- logs: [
6663
- "Configuration:",
6664
- ` \u2022 Name: ${userConfig.name || "unnamed"}`,
6665
- ` \u2022 Root: ${userConfig.root || process.cwd()}`,
6666
- ` \u2022 Output: ${((_b2 = userConfig.output) == null ? void 0 : _b2.path) || "not specified"}`,
6667
- ` \u2022 Plugins: ${((_c2 = userConfig.plugins) == null ? void 0 : _c2.length) || 0}`,
6668
- "Output Settings:",
6669
- ` \u2022 Storage: ${userConfig.storage ? `custom(${userConfig.storage.name})` : ((_d2 = userConfig.output) == null ? void 0 : _d2.write) === false ? "disabled" : "filesystem (default)"}`,
6670
- ` \u2022 Formatter: ${((_e2 = userConfig.output) == null ? void 0 : _e2.format) || "none"}`,
6671
- ` \u2022 Linter: ${((_f = userConfig.output) == null ? void 0 : _f.lint) || "none"}`,
6672
- "Environment:",
6673
- Object.entries(diagnosticInfo).map(([key, value]) => ` \u2022 ${key}: ${value}`).join("\n")
6674
- ]
6675
- });
6676
- try {
6677
- if (isInputPath(userConfig) && !new URLPath(userConfig.input.path).isURL) {
6678
- await exists(userConfig.input.path);
6679
- await hooks.emit("kubb:debug", {
6680
- date: /* @__PURE__ */ new Date(),
6681
- logs: [`\u2713 Input file validated: ${userConfig.input.path}`]
6682
- });
6683
- }
6684
- } catch (caughtError) {
6685
- if (isInputPath(userConfig)) {
6686
- const error = caughtError;
6687
- throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${userConfig.input.path}`, { cause: error });
6862
+ function createSourcesView(storage) {
6863
+ const paths = /* @__PURE__ */ new Set();
6864
+ return createStorage(() => ({
6865
+ name: `${storage.name}:sources`,
6866
+ async hasItem(key) {
6867
+ return paths.has(key) && await storage.hasItem(key);
6868
+ },
6869
+ async getItem(key) {
6870
+ return paths.has(key) ? storage.getItem(key) : null;
6871
+ },
6872
+ async setItem(key, value) {
6873
+ paths.add(key);
6874
+ await storage.setItem(key, value);
6875
+ },
6876
+ async removeItem(key) {
6877
+ paths.delete(key);
6878
+ await storage.removeItem(key);
6879
+ },
6880
+ async getKeys(base) {
6881
+ if (!base) return [...paths];
6882
+ const result = [];
6883
+ for (const key of paths) if (key.startsWith(base)) result.push(key);
6884
+ return result;
6885
+ },
6886
+ async clear() {
6887
+ paths.clear();
6888
+ await storage.clear();
6688
6889
  }
6689
- }
6690
- if (!userConfig.adapter) throw new Error("Adapter should be defined");
6691
- const config = {
6890
+ }))();
6891
+ }
6892
+ function resolveConfig(userConfig) {
6893
+ var _a2, _b, _c;
6894
+ return {
6692
6895
  ...userConfig,
6693
6896
  root: userConfig.root || process.cwd(),
6694
- parsers: (_g = userConfig.parsers) != null ? _g : [],
6695
- adapter: userConfig.adapter,
6897
+ parsers: (_a2 = userConfig.parsers) != null ? _a2 : [],
6696
6898
  output: {
6697
6899
  format: false,
6698
6900
  lint: false,
6699
- write: true,
6700
6901
  extension: DEFAULT_EXTENSION,
6701
6902
  defaultBanner: DEFAULT_BANNER,
6702
6903
  ...userConfig.output
6703
6904
  },
6905
+ storage: (_b = userConfig.storage) != null ? _b : fsStorage(),
6704
6906
  devtools: userConfig.devtools ? {
6705
6907
  studioUrl: DEFAULT_STUDIO_URL,
6706
6908
  ...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
6707
6909
  } : void 0,
6708
- plugins: userConfig.plugins
6910
+ plugins: (_c = userConfig.plugins) != null ? _c : []
6709
6911
  };
6710
- const storage = config.output.write === false ? null : (_h = config.storage) != null ? _h : fsStorage();
6711
- if (config.output.clean) {
6712
- await hooks.emit("kubb:debug", {
6713
- date: /* @__PURE__ */ new Date(),
6714
- logs: ["Cleaning output directories", ` \u2022 Output: ${config.output.path}`]
6715
- });
6716
- await (storage == null ? void 0 : storage.clear(resolve(config.root, config.output.path)));
6717
- }
6718
- const driver = new PluginDriver(config, { hooks });
6719
- function registerMiddlewareHook(event, middlewareHooks) {
6720
- const handler = middlewareHooks[event];
6721
- if (handler) hooks.on(event, handler);
6722
- }
6723
- for (const middleware of (_i = config.middleware) != null ? _i : []) for (const event of Object.keys(middleware.hooks)) registerMiddlewareHook(event, middleware.hooks);
6724
- const adapter = config.adapter;
6725
- if (!adapter) throw new Error("No adapter configured. Please provide an adapter in your kubb.config.ts.");
6726
- const source = inputToAdapterSource(config);
6727
- await hooks.emit("kubb:debug", {
6728
- date: /* @__PURE__ */ new Date(),
6729
- logs: [`Running adapter: ${adapter.name}`]
6730
- });
6731
- driver.adapter = adapter;
6732
- driver.inputNode = await adapter.parse(source);
6733
- await hooks.emit("kubb:debug", {
6734
- date: /* @__PURE__ */ new Date(),
6735
- logs: [
6736
- `\u2713 Adapter '${adapter.name}' resolved InputNode`,
6737
- ` \u2022 Schemas: ${driver.inputNode.schemas.length}`,
6738
- ` \u2022 Operations: ${driver.inputNode.operations.length}`
6739
- ]
6740
- });
6912
+ }
6913
+ function getDiagnosticInfo() {
6741
6914
  return {
6742
- config,
6743
- hooks,
6744
- driver,
6745
- sources,
6746
- storage
6915
+ nodeVersion: version$2,
6916
+ KubbVersion: version$1,
6917
+ platform: process.platform,
6918
+ arch: process.arch,
6919
+ cwd: process.cwd()
6747
6920
  };
6748
6921
  }
6749
- async function runPluginAstHooks(plugin, context) {
6750
- var _a2, _b2, _c2;
6751
- const { adapter, inputNode, resolver, driver } = context;
6752
- const { exclude, include, override } = plugin.options;
6753
- if (!adapter || !inputNode) throw new Error(`[${plugin.name}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
6754
- function resolveRenderer(gen) {
6755
- var _a3, _b3;
6756
- return gen.renderer === null ? void 0 : (_b3 = (_a3 = gen.renderer) != null ? _a3 : plugin.renderer) != null ? _b3 : context.config.renderer;
6922
+ function isInputPath(config) {
6923
+ return typeof (config == null ? void 0 : config.input) === "object" && config.input !== null && "path" in config.input;
6924
+ }
6925
+ var Kubb = (_a = class {
6926
+ constructor(userConfig, options = {}) {
6927
+ __privateAdd(this, _Kubb_instances);
6928
+ __publicField(this, "hooks");
6929
+ __privateAdd(this, _userConfig);
6930
+ __privateAdd(this, _config, null);
6931
+ __privateAdd(this, _driver, null);
6932
+ __privateAdd(this, _storage, null);
6933
+ var _a2;
6934
+ __privateSet(this, _userConfig, userConfig);
6935
+ this.hooks = (_a2 = options.hooks) != null ? _a2 : new AsyncEventEmitter();
6757
6936
  }
6758
- const generators = (_a2 = plugin.generators) != null ? _a2 : [];
6759
- const collectedOperations = [];
6760
- const generatorContext = {
6761
- ...context,
6762
- resolver: driver.getResolver(plugin.name)
6763
- };
6764
- const operationFilterTypes = /* @__PURE__ */ new Set([
6765
- "tag",
6766
- "operationId",
6767
- "path",
6768
- "method",
6769
- "contentType"
6770
- ]);
6771
- const hasOperationBasedIncludes = (_b2 = include == null ? void 0 : include.some(({ type }) => operationFilterTypes.has(type))) != null ? _b2 : false;
6772
- const hasSchemaNameIncludes = (_c2 = include == null ? void 0 : include.some(({ type }) => type === "schemaName")) != null ? _c2 : false;
6773
- let allowedSchemaNames;
6774
- if (hasOperationBasedIncludes && !hasSchemaNameIncludes) allowedSchemaNames = collectUsedSchemaNames(inputNode.operations.filter((op) => resolver.resolveOptions(op, {
6775
- options: plugin.options,
6776
- exclude,
6777
- include,
6778
- override
6779
- }) !== null), inputNode.schemas);
6780
- await walk(inputNode, {
6781
- depth: "shallow",
6782
- async schema(node) {
6783
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6784
- if (allowedSchemaNames !== void 0 && transformedNode.name && !allowedSchemaNames.has(transformedNode.name)) return;
6785
- const options = resolver.resolveOptions(transformedNode, {
6786
- options: plugin.options,
6787
- exclude,
6788
- include,
6789
- override
6790
- });
6791
- if (options === null) return;
6792
- const ctx = {
6793
- ...generatorContext,
6794
- options
6795
- };
6796
- for (const gen of generators) {
6797
- if (!gen.schema) continue;
6798
- await applyHookResult(await gen.schema(transformedNode, ctx), driver, resolveRenderer(gen));
6799
- }
6800
- await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
6801
- },
6802
- async operation(node) {
6803
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6804
- const options = resolver.resolveOptions(transformedNode, {
6805
- options: plugin.options,
6806
- exclude,
6807
- include,
6808
- override
6937
+ get storage() {
6938
+ if (!__privateGet(this, _storage)) throw new Error("[kubb] setup() must be called before accessing storage");
6939
+ return __privateGet(this, _storage);
6940
+ }
6941
+ get driver() {
6942
+ if (!__privateGet(this, _driver)) throw new Error("[kubb] setup() must be called before accessing driver");
6943
+ return __privateGet(this, _driver);
6944
+ }
6945
+ get config() {
6946
+ if (!__privateGet(this, _config)) throw new Error("[kubb] setup() must be called before accessing config");
6947
+ return __privateGet(this, _config);
6948
+ }
6949
+ /**
6950
+ * Resolves config and initializes the driver. `build()` calls this automatically.
6951
+ */
6952
+ async setup() {
6953
+ const config = resolveConfig(__privateGet(this, _userConfig));
6954
+ const driver = new KubbDriver(config, { hooks: this.hooks });
6955
+ const storage = createSourcesView(config.storage);
6956
+ await this.hooks.emit("kubb:debug", {
6957
+ date: /* @__PURE__ */ new Date(),
6958
+ logs: __privateMethod(this, _Kubb_instances, configLogs_fn).call(this, config)
6959
+ });
6960
+ if (isInputPath(__privateGet(this, _userConfig)) && !new URLPath(__privateGet(this, _userConfig).input.path).isURL) try {
6961
+ await exists(__privateGet(this, _userConfig).input.path);
6962
+ await this.hooks.emit("kubb:debug", {
6963
+ date: /* @__PURE__ */ new Date(),
6964
+ logs: [`\u2713 Input file validated: ${__privateGet(this, _userConfig).input.path}`]
6809
6965
  });
6810
- if (options !== null) {
6811
- collectedOperations.push(transformedNode);
6812
- const ctx = {
6813
- ...generatorContext,
6814
- options
6815
- };
6816
- for (const gen of generators) {
6817
- if (!gen.operation) continue;
6818
- await applyHookResult(await gen.operation(transformedNode, ctx), driver, resolveRenderer(gen));
6819
- }
6820
- await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
6821
- }
6966
+ } catch (caughtError) {
6967
+ throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${__privateGet(this, _userConfig).input.path}`, { cause: caughtError });
6822
6968
  }
6823
- });
6824
- if (collectedOperations.length > 0) {
6825
- const ctx = {
6826
- ...generatorContext,
6827
- options: plugin.options
6828
- };
6829
- for (const gen of generators) {
6830
- if (!gen.operations) continue;
6831
- await applyHookResult(await gen.operations(collectedOperations, ctx), driver, resolveRenderer(gen));
6969
+ if (config.output.clean) {
6970
+ await this.hooks.emit("kubb:debug", {
6971
+ date: /* @__PURE__ */ new Date(),
6972
+ logs: ["Cleaning output directories", ` \u2022 Output: ${config.output.path}`]
6973
+ });
6974
+ await config.storage.clear(resolve(config.root, config.output.path));
6832
6975
  }
6833
- await driver.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
6976
+ await driver.setup();
6977
+ __privateSet(this, _config, config);
6978
+ __privateSet(this, _driver, driver);
6979
+ __privateSet(this, _storage, storage);
6834
6980
  }
6835
- }
6836
- async function safeBuild(setupResult) {
6837
- var _a2;
6838
- const { driver, hooks, sources, storage } = setupResult;
6839
- const failedPlugins = /* @__PURE__ */ new Set();
6840
- const pluginTimings = /* @__PURE__ */ new Map();
6841
- const config = driver.config;
6842
- try {
6843
- await driver.emitSetupHooks();
6844
- if (driver.adapter && driver.inputNode) await hooks.emit("kubb:build:start", {
6845
- config,
6846
- adapter: driver.adapter,
6847
- inputNode: driver.inputNode,
6848
- getPlugin: driver.getPlugin.bind(driver),
6849
- get files() {
6850
- return driver.fileManager.files;
6851
- },
6852
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6853
- });
6854
- for (const plugin of driver.plugins.values()) {
6855
- const context = driver.getContext(plugin);
6856
- const hrStart = process.hrtime();
6857
- try {
6858
- const timestamp = /* @__PURE__ */ new Date();
6859
- await hooks.emit("kubb:plugin:start", { plugin });
6860
- await hooks.emit("kubb:debug", {
6861
- date: timestamp,
6862
- logs: ["Starting plugin...", ` \u2022 Plugin Name: ${plugin.name}`]
6863
- });
6864
- if (((_a2 = plugin.generators) == null ? void 0 : _a2.length) || driver.hasRegisteredGenerators(plugin.name)) await runPluginAstHooks(plugin, context);
6865
- const duration = getElapsedMs(hrStart);
6866
- pluginTimings.set(plugin.name, duration);
6867
- await hooks.emit("kubb:plugin:end", {
6868
- plugin,
6869
- duration,
6870
- success: true,
6871
- config,
6872
- get files() {
6873
- return driver.fileManager.files;
6874
- },
6875
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6876
- });
6877
- await hooks.emit("kubb:debug", {
6878
- date: /* @__PURE__ */ new Date(),
6879
- logs: [`\u2713 Plugin started successfully (${formatMs(duration)})`]
6880
- });
6881
- } catch (caughtError) {
6882
- const error = caughtError;
6883
- const errorTimestamp = /* @__PURE__ */ new Date();
6884
- const duration = getElapsedMs(hrStart);
6885
- await hooks.emit("kubb:plugin:end", {
6886
- plugin,
6887
- duration,
6888
- success: false,
6889
- error,
6890
- config,
6891
- get files() {
6892
- return driver.fileManager.files;
6893
- },
6894
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6895
- });
6896
- await hooks.emit("kubb:debug", {
6897
- date: errorTimestamp,
6898
- logs: [
6899
- "\u2717 Plugin start failed",
6900
- ` \u2022 Plugin Name: ${plugin.name}`,
6901
- ` \u2022 Error: ${error.constructor.name} - ${error.message}`,
6902
- " \u2022 Stack Trace:",
6903
- error.stack || "No stack trace available"
6904
- ]
6905
- });
6906
- failedPlugins.add({
6907
- plugin,
6908
- error
6909
- });
6910
- }
6981
+ /**
6982
+ * Runs the full pipeline and throws on any plugin error.
6983
+ * Automatically calls `setup()` if needed.
6984
+ */
6985
+ async build() {
6986
+ const out = await this.safeBuild();
6987
+ if (out.error) throw out.error;
6988
+ if (out.failedPlugins.size > 0) {
6989
+ const errors = [...out.failedPlugins].map(({ error }) => error);
6990
+ throw new BuildError(`Build Error with ${out.failedPlugins.size} failed plugins`, { errors });
6911
6991
  }
6912
- await hooks.emit("kubb:plugins:end", {
6913
- config,
6914
- get files() {
6915
- return driver.fileManager.files;
6916
- },
6917
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6918
- });
6919
- const files = driver.fileManager.files;
6920
- const parsersMap = /* @__PURE__ */ new Map();
6921
- for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
6922
- const fileProcessor = new FileProcessor();
6923
- await hooks.emit("kubb:debug", {
6924
- date: /* @__PURE__ */ new Date(),
6925
- logs: [`Writing ${files.length} files...`]
6926
- });
6927
- await fileProcessor.run(files, {
6928
- parsers: parsersMap,
6929
- extension: config.output.extension,
6930
- onStart: async (processingFiles) => {
6931
- await hooks.emit("kubb:files:processing:start", { files: processingFiles });
6932
- },
6933
- onUpdate: async ({ file, source, processed, total, percentage }) => {
6934
- await hooks.emit("kubb:file:processing:update", {
6935
- file,
6936
- source,
6937
- processed,
6938
- total,
6939
- percentage,
6940
- config
6941
- });
6942
- if (source) {
6943
- await (storage == null ? void 0 : storage.setItem(file.path, source));
6944
- sources.set(file.path, source);
6945
- }
6946
- },
6947
- onEnd: async (processedFiles) => {
6948
- await hooks.emit("kubb:files:processing:end", { files: processedFiles });
6949
- await hooks.emit("kubb:debug", {
6950
- date: /* @__PURE__ */ new Date(),
6951
- logs: [`\u2713 File write process completed for ${processedFiles.length} files`]
6952
- });
6953
- }
6954
- });
6955
- await hooks.emit("kubb:build:end", {
6956
- files,
6957
- config,
6958
- outputDir: resolve(config.root, config.output.path)
6959
- });
6960
- return {
6961
- failedPlugins,
6962
- files,
6963
- driver,
6964
- pluginTimings,
6965
- sources
6966
- };
6967
- } catch (error) {
6968
- return {
6969
- failedPlugins,
6970
- files: [],
6971
- driver,
6972
- pluginTimings,
6973
- error,
6974
- sources
6975
- };
6976
- } finally {
6977
- driver.dispose();
6992
+ return out;
6978
6993
  }
6979
- }
6980
- async function build(setupResult) {
6981
- const { files, driver, failedPlugins, pluginTimings, error, sources } = await safeBuild(setupResult);
6982
- if (error) throw error;
6983
- if (failedPlugins.size > 0) {
6984
- const errors = [...failedPlugins].map(({ error: error2 }) => error2);
6985
- throw new BuildError(`Build Error with ${failedPlugins.size} failed plugins`, { errors });
6994
+ /**
6995
+ * Runs the full pipeline and captures errors in `BuildOutput` instead of throwing.
6996
+ * Automatically calls `setup()` if needed.
6997
+ */
6998
+ async safeBuild() {
6999
+ try {
7000
+ var _usingCtx$1 = _usingCtx();
7001
+ if (!__privateGet(this, _driver)) await this.setup();
7002
+ const cleanup = _usingCtx$1.u(this);
7003
+ const driver = cleanup.driver;
7004
+ const storage = cleanup.storage;
7005
+ const { failedPlugins, pluginTimings, error } = await driver.run({ storage });
7006
+ return {
7007
+ failedPlugins,
7008
+ files: driver.fileManager.files,
7009
+ driver,
7010
+ pluginTimings,
7011
+ storage,
7012
+ ...error ? { error } : {}
7013
+ };
7014
+ } catch (_) {
7015
+ _usingCtx$1.e = _;
7016
+ } finally {
7017
+ _usingCtx$1.d();
7018
+ }
6986
7019
  }
6987
- return {
6988
- failedPlugins,
6989
- files,
6990
- driver,
6991
- pluginTimings,
6992
- error: void 0,
6993
- sources
6994
- };
6995
- }
6996
- function inputToAdapterSource(config) {
6997
- if (Array.isArray(config.input)) return {
6998
- type: "paths",
6999
- paths: config.input.map((i) => new URLPath(i.path).isURL ? i.path : resolve(config.root, i.path))
7000
- };
7001
- if ("data" in config.input) return {
7002
- type: "data",
7003
- data: config.input.data
7004
- };
7005
- if (new URLPath(config.input.path).isURL) return {
7006
- type: "path",
7007
- path: config.input.path
7008
- };
7009
- return {
7010
- type: "path",
7011
- path: resolve(config.root, config.input.path)
7012
- };
7013
- }
7020
+ dispose() {
7021
+ var _a2;
7022
+ (_a2 = __privateGet(this, _driver)) == null ? void 0 : _a2.dispose();
7023
+ }
7024
+ [Symbol.dispose]() {
7025
+ this.dispose();
7026
+ }
7027
+ }, _userConfig = new WeakMap(), _config = new WeakMap(), _driver = new WeakMap(), _storage = new WeakMap(), _Kubb_instances = new WeakSet(), configLogs_fn = function(config) {
7028
+ var _a2, _b, _c, _d, _e;
7029
+ const u = __privateGet(this, _userConfig);
7030
+ const diag = getDiagnosticInfo();
7031
+ return [
7032
+ "Configuration:",
7033
+ ` \u2022 Name: ${u.name || "unnamed"}`,
7034
+ ` \u2022 Root: ${u.root || process.cwd()}`,
7035
+ ` \u2022 Output: ${((_a2 = u.output) == null ? void 0 : _a2.path) || "not specified"}`,
7036
+ ` \u2022 Plugins: ${((_b = u.plugins) == null ? void 0 : _b.length) || 0}`,
7037
+ "Output Settings:",
7038
+ ` \u2022 Storage: ${config.storage.name}`,
7039
+ ` \u2022 Formatter: ${((_c = u.output) == null ? void 0 : _c.format) || "none"}`,
7040
+ ` \u2022 Linter: ${((_d = u.output) == null ? void 0 : _d.lint) || "none"}`,
7041
+ `Running adapter: ${((_e = config.adapter) == null ? void 0 : _e.name) || "none"}`,
7042
+ "Environment:",
7043
+ Object.entries(diag).map(([key, value]) => ` \u2022 ${key}: ${value}`).join("\n")
7044
+ ];
7045
+ }, _a);
7014
7046
  function createKubb(userConfig, options = {}) {
7015
- var _a2;
7016
- const hooks = (_a2 = options.hooks) != null ? _a2 : new AsyncEventEmitter();
7017
- let setupResult;
7018
- const instance = {
7019
- get hooks() {
7020
- return hooks;
7021
- },
7022
- get sources() {
7023
- var _a3;
7024
- return (_a3 = setupResult == null ? void 0 : setupResult.sources) != null ? _a3 : /* @__PURE__ */ new Map();
7025
- },
7026
- get driver() {
7027
- return setupResult == null ? void 0 : setupResult.driver;
7028
- },
7029
- get config() {
7030
- return setupResult == null ? void 0 : setupResult.config;
7031
- },
7032
- async setup() {
7033
- setupResult = await setup(userConfig, { hooks });
7034
- },
7035
- async build() {
7036
- if (!setupResult) await instance.setup();
7037
- return build(setupResult);
7038
- },
7039
- async safeBuild() {
7040
- if (!setupResult) await instance.setup();
7041
- return safeBuild(setupResult);
7042
- }
7043
- };
7044
- return instance;
7047
+ return new Kubb(userConfig, options);
7045
7048
  }
7046
7049
  const memoryStorage = createStorage(() => {
7047
7050
  const store = /* @__PURE__ */ new Map();
@@ -7074,7 +7077,7 @@ const memoryStorage = createStorage(() => {
7074
7077
  };
7075
7078
  });
7076
7079
 
7077
- var version = "5.0.0-beta.2";
7080
+ var version = "5.0.0-beta.21";
7078
7081
 
7079
7082
  function isCommandMessage(msg) {
7080
7083
  return msg.type === "command";
@@ -7085,9 +7088,6 @@ function isPongMessage(msg) {
7085
7088
  function isDisconnectMessage(msg) {
7086
7089
  return msg.type === "disconnect";
7087
7090
  }
7088
- function isPublishCommandMessage(msg) {
7089
- return msg.type === "command" && msg.command === "publish";
7090
- }
7091
7091
 
7092
7092
  function getStorage() {
7093
7093
  return useStorage("kubb");
@@ -7131,7 +7131,7 @@ async function generate({ config, hooks }) {
7131
7131
  const kubb = createKubb(config, { hooks });
7132
7132
  await kubb.setup();
7133
7133
  await hooks.emit("kubb:info", { message: config.name ? `Build generation ${config.name}` : "Build generation" });
7134
- const { files, failedPlugins, error } = await kubb.safeBuild();
7134
+ const { failedPlugins, error } = await kubb.safeBuild();
7135
7135
  await hooks.emit("kubb:info", { message: "Load summary" });
7136
7136
  const hasFailures = failedPlugins.size > 0 || error;
7137
7137
  if (hasFailures) {
@@ -7142,11 +7142,11 @@ async function generate({ config, hooks }) {
7142
7142
  allErrors.forEach((err) => {
7143
7143
  hooks.emit("kubb:error", { error: err });
7144
7144
  });
7145
- await hooks.emit("kubb:generation:end", { config, files, sources: kubb.sources });
7145
+ await hooks.emit("kubb:generation:end", { config, storage: kubb.storage });
7146
7146
  throw new Error("Generation failed");
7147
7147
  }
7148
7148
  await hooks.emit("kubb:success", { message: "Generation successfully" });
7149
- await hooks.emit("kubb:generation:end", { config, files, sources: kubb.sources });
7149
+ await hooks.emit("kubb:generation:end", { config, storage: kubb.storage });
7150
7150
  if (config.output.format) {
7151
7151
  await hooks.emit("kubb:format:start");
7152
7152
  let formatter = config.output.format;
@@ -7221,20 +7221,15 @@ async function generate({ config, hooks }) {
7221
7221
  }
7222
7222
  }
7223
7223
 
7224
- const unrunInputOptions = {
7225
- transform: {
7226
- jsx: {
7227
- runtime: "automatic",
7228
- importSource: "@kubb/renderer-jsx"
7229
- }
7230
- }
7231
- };
7224
+ const jiti = createJiti(globalThis._importMeta_.url, {
7225
+ jsx: {
7226
+ runtime: "automatic",
7227
+ importSource: "@kubb/renderer-jsx"
7228
+ },
7229
+ moduleCache: false
7230
+ });
7232
7231
  const tsLoader = async (configFile) => {
7233
- const { module } = await unrun({
7234
- path: configFile,
7235
- inputOptions: unrunInputOptions
7236
- });
7237
- return module;
7232
+ return jiti.import(configFile, { default: true });
7238
7233
  };
7239
7234
  async function getCosmiConfig(configPath) {
7240
7235
  var _a;
@@ -7295,6 +7290,21 @@ async function resolvePlugins(plugins) {
7295
7290
  })
7296
7291
  );
7297
7292
  }
7293
+ async function resolveMiddlewares(middlewares) {
7294
+ return Promise.all(
7295
+ middlewares.map(async ({ name, options }) => {
7296
+ const factory = await loadPluginFactory(name);
7297
+ return factory(options != null ? options : {});
7298
+ })
7299
+ );
7300
+ }
7301
+ async function checkPeerDependencies() {
7302
+ try {
7303
+ await import('@kubb/renderer-jsx');
7304
+ } catch {
7305
+ logger.warn("Missing peer dependency @kubb/renderer-jsx. Install it alongside kubb plugins.");
7306
+ }
7307
+ }
7298
7308
 
7299
7309
  async function mergePlugins(diskPlugins, studioPlugins) {
7300
7310
  if (!diskPlugins && !studioPlugins) return void 0;
@@ -7323,44 +7333,6 @@ async function mergePlugins(diskPlugins, studioPlugins) {
7323
7333
  return [...mergedDisk, ...studioOnly];
7324
7334
  }
7325
7335
 
7326
- async function publish({ command, outputPath, root, hooks }) {
7327
- var _a, _b, _c, _d;
7328
- const resolvedOutputPath = path$1.isAbsolute(outputPath) ? outputPath : path$1.resolve(root, outputPath);
7329
- const [cmd, ...args] = tokenize(command);
7330
- if (!cmd) {
7331
- throw new Error(`[plugin-publish] Invalid publish command: "${command}"`);
7332
- }
7333
- const commandWithArgs = args.length ? `${cmd} ${args.join(" ")}` : cmd;
7334
- await hooks.emit("kubb:info", { message: `[publish] Running "${commandWithArgs}" in "${resolvedOutputPath}"` });
7335
- const startTime = Date.now();
7336
- let exitCode = null;
7337
- try {
7338
- const proc = x(cmd, args, {
7339
- nodeOptions: { cwd: resolvedOutputPath }
7340
- });
7341
- for await (const line of proc) {
7342
- if (line.trim()) {
7343
- await hooks.emit("kubb:info", { message: line.trim() });
7344
- }
7345
- }
7346
- const result = await proc;
7347
- exitCode = (_a = result.exitCode) != null ? _a : null;
7348
- } catch (err) {
7349
- const message = (_d = (_c = (_b = err == null ? void 0 : err.stderr) == null ? void 0 : _b.trim()) != null ? _c : err == null ? void 0 : err.message) != null ? _d : String(err);
7350
- const error = new Error(`[publish] Failed to run "${commandWithArgs}": ${message}`);
7351
- error.cause = err;
7352
- await hooks.emit("kubb:error", { error });
7353
- throw error;
7354
- }
7355
- if (exitCode !== 0) {
7356
- const error = new Error(`[publish] "${commandWithArgs}" exited with code ${exitCode}`);
7357
- await hooks.emit("kubb:error", { error });
7358
- throw error;
7359
- }
7360
- const duration = Date.now() - startTime;
7361
- await hooks.emit("kubb:success", { message: `[publish] Published successfully in ${duration}ms` });
7362
- }
7363
-
7364
7336
  function setupHookListener(hooks, root) {
7365
7337
  hooks.on("kubb:hook:start", async (ctx) => {
7366
7338
  const { id, command, args } = ctx;
@@ -7396,7 +7368,7 @@ function setupHookListener(hooks, root) {
7396
7368
  }
7397
7369
 
7398
7370
  const agentDefaults = {
7399
- studioUrl: "https://studio.kubb.dev",
7371
+ studioUrl: "https://kubb.studio",
7400
7372
  configPath: "kubb.config.ts",
7401
7373
  retryIntervalMs: 3e4,
7402
7374
  heartbeatIntervalMs: 3e4,
@@ -7431,24 +7403,24 @@ function sendAgentMessage(ws, message) {
7431
7403
  throw new Error("Failed to send message to Kubb Studio", { cause: error });
7432
7404
  }
7433
7405
  }
7434
- function setupEventsStream(ws, hooks, getSource) {
7406
+ function setupEventsStream(ws, hooks) {
7435
7407
  function sendDataMessage(payload) {
7436
7408
  sendAgentMessage(ws, {
7437
7409
  type: "data",
7438
- payload: { ...payload, source: getSource == null ? void 0 : getSource() }
7410
+ payload
7439
7411
  });
7440
7412
  }
7441
7413
  hooks.on("kubb:plugin:start", (ctx) => {
7442
7414
  sendDataMessage({
7443
7415
  type: "kubb:plugin:start",
7444
- data: [ctx.plugin],
7416
+ data: [{ plugin: ctx.plugin }],
7445
7417
  timestamp: Date.now()
7446
7418
  });
7447
7419
  });
7448
7420
  hooks.on("kubb:plugin:end", (ctx) => {
7449
7421
  sendDataMessage({
7450
7422
  type: "kubb:plugin:end",
7451
- data: [ctx.plugin, { duration: ctx.duration, success: ctx.success }],
7423
+ data: [{ plugin: ctx.plugin, duration: ctx.duration, success: ctx.success }],
7452
7424
  timestamp: Date.now()
7453
7425
  });
7454
7426
  });
@@ -7459,15 +7431,17 @@ function setupEventsStream(ws, hooks, getSource) {
7459
7431
  timestamp: Date.now()
7460
7432
  });
7461
7433
  });
7462
- hooks.on("kubb:file:processing:update", (ctx) => {
7434
+ hooks.on("kubb:files:processing:update", ({ files }) => {
7463
7435
  sendDataMessage({
7464
- type: "kubb:file:processing:update",
7436
+ type: "kubb:files:processing:update",
7465
7437
  data: [
7466
7438
  {
7467
- file: ctx.file.path,
7468
- processed: ctx.processed,
7469
- total: ctx.total,
7470
- percentage: ctx.percentage
7439
+ files: files.map((ctx) => ({
7440
+ file: ctx.file.path,
7441
+ processed: ctx.processed,
7442
+ total: ctx.total,
7443
+ percentage: ctx.percentage
7444
+ }))
7471
7445
  }
7472
7446
  ],
7473
7447
  timestamp: Date.now()
@@ -7483,21 +7457,21 @@ function setupEventsStream(ws, hooks, getSource) {
7483
7457
  hooks.on("kubb:info", ({ message, info }) => {
7484
7458
  sendDataMessage({
7485
7459
  type: "kubb:info",
7486
- data: [message, info],
7460
+ data: [{ message, info }],
7487
7461
  timestamp: Date.now()
7488
7462
  });
7489
7463
  });
7490
7464
  hooks.on("kubb:success", ({ message, info }) => {
7491
7465
  sendDataMessage({
7492
7466
  type: "kubb:success",
7493
- data: [message, info],
7467
+ data: [{ message, info }],
7494
7468
  timestamp: Date.now()
7495
7469
  });
7496
7470
  });
7497
7471
  hooks.on("kubb:warn", ({ message, info }) => {
7498
7472
  sendDataMessage({
7499
7473
  type: "kubb:warn",
7500
- data: [message, info],
7474
+ data: [{ message, info }],
7501
7475
  timestamp: Date.now()
7502
7476
  });
7503
7477
  });
@@ -7513,14 +7487,17 @@ function setupEventsStream(ws, hooks, getSource) {
7513
7487
  timestamp: Date.now()
7514
7488
  });
7515
7489
  });
7516
- hooks.on("kubb:generation:end", ({ config, files, sources }) => {
7490
+ hooks.on("kubb:generation:end", async ({ config, storage }) => {
7517
7491
  const sourcesRecord = {};
7518
- sources.forEach((value, key) => {
7519
- sourcesRecord[key] = value;
7520
- });
7492
+ for (const key of await storage.getKeys()) {
7493
+ const value = await storage.getItem(key);
7494
+ if (value !== null) {
7495
+ sourcesRecord[key] = value;
7496
+ }
7497
+ }
7521
7498
  sendDataMessage({
7522
7499
  type: "kubb:generation:end",
7523
- data: [config, files, sourcesRecord],
7500
+ data: [{ config, storage: sourcesRecord }],
7524
7501
  timestamp: Date.now()
7525
7502
  });
7526
7503
  });
@@ -7547,7 +7524,6 @@ async function connectToStudio(options) {
7547
7524
  resolvedConfigPath,
7548
7525
  allowAll,
7549
7526
  allowWrite,
7550
- allowPublish,
7551
7527
  root,
7552
7528
  retryInterval,
7553
7529
  heartbeatInterval = 3e4,
@@ -7555,7 +7531,6 @@ async function connectToStudio(options) {
7555
7531
  nitro
7556
7532
  } = options;
7557
7533
  const hooks = new AsyncEventEmitter();
7558
- let currentSource;
7559
7534
  async function reconnect() {
7560
7535
  logger.info(`Retrying connection in ${formatMs$1(retryInterval)} to Kubb Studio ...`);
7561
7536
  setTimeout(() => connectToStudio({ ...options, initialSession: void 0 }), retryInterval);
@@ -7570,7 +7545,6 @@ async function connectToStudio(options) {
7570
7545
  const maskedSessionId = maskString(sessionId);
7571
7546
  const effectiveAllowAll = isSandbox ? false : allowAll;
7572
7547
  const effectiveWrite = isSandbox ? false : allowWrite;
7573
- const effectivePublish = isSandbox ? false : allowPublish;
7574
7548
  let serverDisconnected = false;
7575
7549
  let heartbeatTimer;
7576
7550
  async function cleanup(reason = "cleanup") {
@@ -7582,6 +7556,7 @@ async function connectToStudio(options) {
7582
7556
  ws.removeEventListener("open", onOpen);
7583
7557
  ws.removeEventListener("close", onClose);
7584
7558
  ws.removeEventListener("error", onError);
7559
+ ws.removeEventListener("message", onMessage);
7585
7560
  } catch (_error) {
7586
7561
  }
7587
7562
  }
@@ -7614,9 +7589,9 @@ async function connectToStudio(options) {
7614
7589
  });
7615
7590
  });
7616
7591
  heartbeatTimer = setInterval(() => sendAgentMessage(ws, { type: "ping" }), heartbeatInterval);
7617
- setupEventsStream(ws, hooks, () => currentSource);
7618
- ws.addEventListener("message", async (message) => {
7619
- var _a2, _b, _c, _d, _e, _f;
7592
+ setupEventsStream(ws, hooks);
7593
+ const onMessage = async (message) => {
7594
+ var _a2, _b, _c, _d;
7620
7595
  try {
7621
7596
  const data = JSON.parse(message.data);
7622
7597
  logger.info(`[${maskedSessionId}] Received "${data.type}" from Studio`);
@@ -7638,11 +7613,11 @@ async function connectToStudio(options) {
7638
7613
  }
7639
7614
  if (isCommandMessage(data)) {
7640
7615
  if (data.command === "generate") {
7641
- currentSource = "generate";
7642
7616
  const config = await loadConfig(resolvedConfigPath);
7643
7617
  const storedConfig = data.payload ? null : await getLatestStudioConfigFromStorage({ sessionId }).catch(() => null);
7644
7618
  const patch = (_b = (_a2 = data.payload) != null ? _a2 : storedConfig) != null ? _b : void 0;
7645
7619
  const plugins = await mergePlugins(config.plugins, patch == null ? void 0 : patch.plugins);
7620
+ const middleware = (patch == null ? void 0 : patch.middleware) ? await resolveMiddlewares(patch.middleware) : config.middleware;
7646
7621
  const inputOverride = isSandbox ? { data: (_c = patch == null ? void 0 : patch.input) != null ? _c : "" } : void 0;
7647
7622
  if (allowWrite && isSandbox) {
7648
7623
  logger.warn(`[${maskedSessionId}] Agent is running in a sandbox environment, write will be disabled`);
@@ -7658,6 +7633,9 @@ async function connectToStudio(options) {
7658
7633
  logger.warn(`[${maskedSessionId}] Failed to save studio config: ${err == null ? void 0 : err.message}`);
7659
7634
  });
7660
7635
  }
7636
+ const generationHooks = new AsyncEventEmitter();
7637
+ setupHookListener(generationHooks, root);
7638
+ setupEventsStream(ws, generationHooks);
7661
7639
  await generate({
7662
7640
  config: {
7663
7641
  ...config,
@@ -7667,12 +7645,15 @@ async function connectToStudio(options) {
7667
7645
  output: {
7668
7646
  ...config.output
7669
7647
  },
7670
- plugins
7648
+ plugins,
7649
+ middleware,
7650
+ // Studio may send an opaque adapter options blob; forward it unchanged to createKubb.
7651
+ // The adapter factory is responsible for validating and merging its own options.
7652
+ ...(patch == null ? void 0 : patch.adapter) != null && { adapter: patch.adapter }
7671
7653
  },
7672
- hooks
7654
+ hooks: generationHooks
7673
7655
  });
7674
7656
  logger.success(`[${maskedSessionId}] Completed "${data.type}" from Studio`);
7675
- currentSource = void 0;
7676
7657
  return;
7677
7658
  }
7678
7659
  if (data.command === "connect") {
@@ -7684,8 +7665,7 @@ async function connectToStudio(options) {
7684
7665
  configPath,
7685
7666
  permissions: {
7686
7667
  allowAll: effectiveAllowAll,
7687
- allowWrite: effectiveWrite,
7688
- allowPublish: effectivePublish
7668
+ allowWrite: effectiveWrite
7689
7669
  },
7690
7670
  config: {
7691
7671
  plugins: config.plugins.map((plugin) => ({
@@ -7698,30 +7678,13 @@ async function connectToStudio(options) {
7698
7678
  logger.success(`[${maskedSessionId}] Completed "${data.type}" from Studio`);
7699
7679
  return;
7700
7680
  }
7701
- if (isPublishCommandMessage(data)) {
7702
- if (!effectivePublish) {
7703
- logger.warn(`[${maskedSessionId}] Publish command rejected \u2014 KUBB_AGENT_ALLOW_PUBLISH is not enabled`);
7704
- return;
7705
- }
7706
- currentSource = "publish";
7707
- const config = await loadConfig(resolvedConfigPath);
7708
- const resolvedCommand = (_e = (_d = data.payload.command) != null ? _d : process.env.KUBB_AGENT_PUBLISH_COMMAND) != null ? _e : "npm publish";
7709
- await publish({
7710
- command: resolvedCommand,
7711
- outputPath: config.output.path,
7712
- root,
7713
- hooks
7714
- });
7715
- logger.success(`[${maskedSessionId}] Completed "${data.command}" from Studio`);
7716
- currentSource = void 0;
7717
- return;
7718
- }
7719
7681
  }
7720
7682
  logger.warn(`[${maskedSessionId}] Unknown message type from Kubb Studio: ${message.data}`);
7721
7683
  } catch (error) {
7722
- logger.error(`[${maskedSessionId}] [unhandledRejection] ${(_f = error == null ? void 0 : error.message) != null ? _f : error}`);
7684
+ logger.error(`[${maskedSessionId}] [unhandledRejection] ${(_d = error == null ? void 0 : error.message) != null ? _d : error}`);
7723
7685
  }
7724
- });
7686
+ };
7687
+ ws.addEventListener("message", onMessage);
7725
7688
  } catch (error) {
7726
7689
  throw new Error(`[unhandledRejection] ${(_a = error == null ? void 0 : error.message) != null ? _a : error}`, {
7727
7690
  cause: error
@@ -7751,7 +7714,6 @@ function resolveStudioRuntimeConfig(env = process$1.env, cwd = process$1.cwd())
7751
7714
  root,
7752
7715
  allowAll,
7753
7716
  allowWrite: allowAll || parseBooleanEnv(env.KUBB_AGENT_ALLOW_WRITE),
7754
- allowPublish: allowAll || parseBooleanEnv(env.KUBB_AGENT_ALLOW_PUBLISH),
7755
7717
  poolSize: parsePositiveIntegerEnv(env.KUBB_AGENT_POOL_SIZE, agentDefaults.poolSize),
7756
7718
  hasSecret: Boolean(env.KUBB_AGENT_SECRET)
7757
7719
  };
@@ -7761,7 +7723,7 @@ function getErrorMessage(error) {
7761
7723
  return error instanceof Error ? error.message : String(error);
7762
7724
  }
7763
7725
  const _zcw7I4pYH8OiCfaDcjy_x7I6IH1tLDQR3W_yRZgP6E = defineNitroPlugin(async (nitro) => {
7764
- const { studioUrl, token, configPath, resolvedConfigPath, retryInterval, heartbeatInterval, root, allowAll, allowWrite, allowPublish, poolSize, hasSecret } = resolveStudioRuntimeConfig(process$1.env);
7726
+ const { studioUrl, token, configPath, resolvedConfigPath, retryInterval, heartbeatInterval, root, allowAll, allowWrite, poolSize, hasSecret } = resolveStudioRuntimeConfig(process$1.env);
7765
7727
  if (!token) {
7766
7728
  logger.warn("KUBB_AGENT_TOKEN not set", "cannot authenticate with studio");
7767
7729
  return null;
@@ -7771,6 +7733,7 @@ const _zcw7I4pYH8OiCfaDcjy_x7I6IH1tLDQR3W_yRZgP6E = defineNitroPlugin(async (nit
7771
7733
  }
7772
7734
  const maskedToken = maskString(token);
7773
7735
  try {
7736
+ await checkPeerDependencies();
7774
7737
  await registerAgent({ token, studioUrl, poolSize });
7775
7738
  const baseOptions = {
7776
7739
  token,
@@ -7779,7 +7742,6 @@ const _zcw7I4pYH8OiCfaDcjy_x7I6IH1tLDQR3W_yRZgP6E = defineNitroPlugin(async (nit
7779
7742
  resolvedConfigPath,
7780
7743
  allowAll,
7781
7744
  allowWrite,
7782
- allowPublish,
7783
7745
  root,
7784
7746
  retryInterval,
7785
7747
  heartbeatInterval,