@kodycodes/cli 1.26.1 → 1.26.3

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 (271) hide show
  1. package/dist/auth-4FW6GCLG.js +26 -0
  2. package/dist/auth-4FW6GCLG.js.map +6 -0
  3. package/dist/bin.js +27 -3
  4. package/dist/bin.js.map +6 -1
  5. package/dist/chunk-46IJPEID.js +30 -0
  6. package/dist/chunk-46IJPEID.js.map +6 -0
  7. package/dist/chunk-4D6ORNXY.js +24404 -0
  8. package/dist/chunk-4D6ORNXY.js.map +6 -0
  9. package/dist/chunk-64IM6G4Z.js +341 -0
  10. package/dist/chunk-64IM6G4Z.js.map +6 -0
  11. package/dist/{package-local-runtime-source.js → chunk-64XN367G.js} +373 -52
  12. package/dist/chunk-64XN367G.js.map +6 -0
  13. package/dist/chunk-6XQP5SWX.js +26 -0
  14. package/dist/chunk-6XQP5SWX.js.map +6 -0
  15. package/dist/chunk-75RZUXQL.js +62 -0
  16. package/dist/chunk-75RZUXQL.js.map +6 -0
  17. package/dist/chunk-BISUL7CE.js +106 -0
  18. package/dist/chunk-BISUL7CE.js.map +6 -0
  19. package/dist/chunk-BPGY4IE7.js +57 -0
  20. package/dist/chunk-BPGY4IE7.js.map +6 -0
  21. package/dist/chunk-CASGRYOF.js +21 -0
  22. package/dist/chunk-CASGRYOF.js.map +6 -0
  23. package/dist/chunk-CWWHR4FH.js +19 -0
  24. package/dist/chunk-CWWHR4FH.js.map +6 -0
  25. package/dist/chunk-D55XPY3T.js +1382 -0
  26. package/dist/chunk-D55XPY3T.js.map +6 -0
  27. package/dist/chunk-EOCV74B2.js +948 -0
  28. package/dist/chunk-EOCV74B2.js.map +6 -0
  29. package/dist/chunk-FBVNFWR6.js +437 -0
  30. package/dist/chunk-FBVNFWR6.js.map +6 -0
  31. package/dist/chunk-G4YN6XP5.js +14 -0
  32. package/dist/chunk-G4YN6XP5.js.map +6 -0
  33. package/dist/chunk-G6LJWROP.js +18 -0
  34. package/dist/chunk-G6LJWROP.js.map +6 -0
  35. package/dist/chunk-IHP6PV6X.js +49 -0
  36. package/dist/chunk-IHP6PV6X.js.map +6 -0
  37. package/dist/chunk-JWEFKKAD.js +24 -0
  38. package/dist/chunk-JWEFKKAD.js.map +6 -0
  39. package/dist/chunk-LWNB26KO.js +147 -0
  40. package/dist/chunk-LWNB26KO.js.map +6 -0
  41. package/dist/chunk-OVGXPRSY.js +20 -0
  42. package/dist/chunk-OVGXPRSY.js.map +6 -0
  43. package/dist/chunk-PDWCKWQF.js +453 -0
  44. package/dist/chunk-PDWCKWQF.js.map +6 -0
  45. package/dist/chunk-QHBCP4OB.js +44 -0
  46. package/dist/chunk-QHBCP4OB.js.map +6 -0
  47. package/dist/chunk-R4IUV5P5.js +664 -0
  48. package/dist/chunk-R4IUV5P5.js.map +6 -0
  49. package/dist/chunk-RM34N3KI.js +525 -0
  50. package/dist/chunk-RM34N3KI.js.map +6 -0
  51. package/dist/chunk-RTWUNV76.js +309 -0
  52. package/dist/chunk-RTWUNV76.js.map +6 -0
  53. package/dist/chunk-SMURF26I.js +23 -0
  54. package/dist/chunk-SMURF26I.js.map +6 -0
  55. package/dist/chunk-SXHULGL4.js +426 -0
  56. package/dist/chunk-SXHULGL4.js.map +6 -0
  57. package/dist/chunk-TIL35OWA.js +1959 -0
  58. package/dist/chunk-TIL35OWA.js.map +6 -0
  59. package/dist/chunk-VQS5YSCI.js +54 -0
  60. package/dist/chunk-VQS5YSCI.js.map +6 -0
  61. package/dist/chunk-XDCOWU5R.js +696 -0
  62. package/dist/chunk-XDCOWU5R.js.map +6 -0
  63. package/dist/chunk-XOPPGRUP.js +605 -0
  64. package/dist/chunk-XOPPGRUP.js.map +6 -0
  65. package/dist/cli.js +74 -1500
  66. package/dist/cli.js.map +6 -1
  67. package/dist/dev/dev-watcher.d.ts +5 -1
  68. package/dist/dev-command-3LX234N6.js +4900 -0
  69. package/dist/dev-command-3LX234N6.js.map +6 -0
  70. package/dist/git-credential-FUE3JE3T.js +163 -0
  71. package/dist/git-credential-FUE3JE3T.js.map +6 -0
  72. package/dist/install-ZML2TCDG.js +10694 -0
  73. package/dist/install-ZML2TCDG.js.map +6 -0
  74. package/dist/local-execute-SZV6XN4T.js +368 -0
  75. package/dist/local-execute-SZV6XN4T.js.map +6 -0
  76. package/dist/local-package-run-2TMCAZZ2.js +23 -0
  77. package/dist/local-package-run-2TMCAZZ2.js.map +6 -0
  78. package/dist/mcp-G2AWTIXR.js +21 -0
  79. package/dist/mcp-G2AWTIXR.js.map +6 -0
  80. package/dist/mock-dep-resolve-TVABDNR7.js +52 -0
  81. package/dist/mock-dep-resolve-TVABDNR7.js.map +6 -0
  82. package/dist/mock-fetch-gateway-B5TFGGQS.js +34 -0
  83. package/dist/mock-fetch-gateway-B5TFGGQS.js.map +6 -0
  84. package/dist/mock-local-deps-5SZT3PWT.js +197 -0
  85. package/dist/mock-local-deps-5SZT3PWT.js.map +6 -0
  86. package/dist/mock-server-SV2IKC4I.js +21 -0
  87. package/dist/mock-server-SV2IKC4I.js.map +6 -0
  88. package/dist/open-api-client-DVVMLY7P.js +42 -0
  89. package/dist/open-api-client-DVVMLY7P.js.map +6 -0
  90. package/dist/org-X7B5BI4R.js +132 -0
  91. package/dist/org-X7B5BI4R.js.map +6 -0
  92. package/dist/package-manifest-QH2RU64C.js +14 -0
  93. package/dist/package-manifest-QH2RU64C.js.map +6 -0
  94. package/dist/remote-execute-QMQDVHOY.js +110 -0
  95. package/dist/remote-execute-QMQDVHOY.js.map +6 -0
  96. package/dist/setup-git-5KCUBYPB.js +88 -0
  97. package/dist/setup-git-5KCUBYPB.js.map +6 -0
  98. package/dist/skill-ENPATRIW.js +43 -0
  99. package/dist/skill-ENPATRIW.js.map +6 -0
  100. package/dist/store-WTMRH527.js +48 -0
  101. package/dist/store-WTMRH527.js.map +6 -0
  102. package/dist/structured-error-C65GQ53Z.js +13 -0
  103. package/dist/structured-error-C65GQ53Z.js.map +6 -0
  104. package/dist/target-3QHY7JT4.js +45 -0
  105. package/dist/target-3QHY7JT4.js.map +6 -0
  106. package/dist/webapi-NTVP4BO3.js +2482 -0
  107. package/dist/webapi-NTVP4BO3.js.map +6 -0
  108. package/package.json +8 -8
  109. package/dist/add-mcp-install.js +0 -59
  110. package/dist/add-mcp-install.js.map +0 -1
  111. package/dist/api-token-store.js +0 -120
  112. package/dist/api-token-store.js.map +0 -1
  113. package/dist/api-token.js +0 -238
  114. package/dist/api-token.js.map +0 -1
  115. package/dist/auth-bootstrap.js +0 -373
  116. package/dist/auth-bootstrap.js.map +0 -1
  117. package/dist/auth.js +0 -386
  118. package/dist/auth.js.map +0 -1
  119. package/dist/capability-proxy.js +0 -527
  120. package/dist/capability-proxy.js.map +0 -1
  121. package/dist/credential-call-map.js +0 -155
  122. package/dist/credential-call-map.js.map +0 -1
  123. package/dist/credential-client-runtime-source.js +0 -9
  124. package/dist/credential-client-runtime-source.js.map +0 -1
  125. package/dist/credentialed-fetch-scan.js +0 -98
  126. package/dist/credentialed-fetch-scan.js.map +0 -1
  127. package/dist/defaults.js +0 -34
  128. package/dist/defaults.js.map +0 -1
  129. package/dist/detect-running-hosts.js +0 -13
  130. package/dist/detect-running-hosts.js.map +0 -1
  131. package/dist/dev/dev-assets.js +0 -202
  132. package/dist/dev/dev-assets.js.map +0 -1
  133. package/dist/dev/dev-bundler.js +0 -65
  134. package/dist/dev/dev-bundler.js.map +0 -1
  135. package/dist/dev/dev-events.js +0 -94
  136. package/dist/dev/dev-events.js.map +0 -1
  137. package/dist/dev/dev-port.js +0 -80
  138. package/dist/dev/dev-port.js.map +0 -1
  139. package/dist/dev/dev-protocol.js +0 -14
  140. package/dist/dev/dev-protocol.js.map +0 -1
  141. package/dist/dev/dev-registry.js +0 -95
  142. package/dist/dev/dev-registry.js.map +0 -1
  143. package/dist/dev/dev-watcher.js +0 -156
  144. package/dist/dev/dev-watcher.js.map +0 -1
  145. package/dist/dev/error-page.js +0 -64
  146. package/dist/dev/error-page.js.map +0 -1
  147. package/dist/dev/live-reload.js +0 -148
  148. package/dist/dev/live-reload.js.map +0 -1
  149. package/dist/dev/prebuild.js +0 -102
  150. package/dist/dev/prebuild.js.map +0 -1
  151. package/dist/dev/process-reaper.js +0 -151
  152. package/dist/dev/process-reaper.js.map +0 -1
  153. package/dist/dev/stack-trace.js +0 -56
  154. package/dist/dev/stack-trace.js.map +0 -1
  155. package/dist/dev/workerd-process.js +0 -118
  156. package/dist/dev/workerd-process.js.map +0 -1
  157. package/dist/dev-command.js +0 -672
  158. package/dist/dev-command.js.map +0 -1
  159. package/dist/discover-login-identity.js +0 -77
  160. package/dist/discover-login-identity.js.map +0 -1
  161. package/dist/discover-org.js +0 -62
  162. package/dist/discover-org.js.map +0 -1
  163. package/dist/git-credential.js +0 -147
  164. package/dist/git-credential.js.map +0 -1
  165. package/dist/help.js +0 -333
  166. package/dist/help.js.map +0 -1
  167. package/dist/host-catalog.js +0 -427
  168. package/dist/host-catalog.js.map +0 -1
  169. package/dist/host-config.js +0 -80
  170. package/dist/host-config.js.map +0 -1
  171. package/dist/http-error-body.js +0 -35
  172. package/dist/http-error-body.js.map +0 -1
  173. package/dist/install-hosts.js +0 -328
  174. package/dist/install-hosts.js.map +0 -1
  175. package/dist/install.js +0 -120
  176. package/dist/install.js.map +0 -1
  177. package/dist/invoke-passthrough.js +0 -60
  178. package/dist/invoke-passthrough.js.map +0 -1
  179. package/dist/local-bundle.js +0 -200
  180. package/dist/local-bundle.js.map +0 -1
  181. package/dist/local-execute-auth.js +0 -53
  182. package/dist/local-execute-auth.js.map +0 -1
  183. package/dist/local-execute.js +0 -338
  184. package/dist/local-execute.js.map +0 -1
  185. package/dist/local-gateway-fetch-forward.js +0 -135
  186. package/dist/local-gateway-fetch-forward.js.map +0 -1
  187. package/dist/local-host-runtime-surface.js +0 -75
  188. package/dist/local-host-runtime-surface.js.map +0 -1
  189. package/dist/local-package-graph.js +0 -405
  190. package/dist/local-package-graph.js.map +0 -1
  191. package/dist/local-package-run.js +0 -307
  192. package/dist/local-package-run.js.map +0 -1
  193. package/dist/local-runtime-bridge.js +0 -132
  194. package/dist/local-runtime-bridge.js.map +0 -1
  195. package/dist/local-runtime-source.js +0 -541
  196. package/dist/local-runtime-source.js.map +0 -1
  197. package/dist/login-callback-assets.js +0 -10
  198. package/dist/login-callback-assets.js.map +0 -1
  199. package/dist/login-callback-page.js +0 -362
  200. package/dist/login-callback-page.js.map +0 -1
  201. package/dist/mcp.js +0 -134
  202. package/dist/mcp.js.map +0 -1
  203. package/dist/mock/ensure-msw.js +0 -215
  204. package/dist/mock/ensure-msw.js.map +0 -1
  205. package/dist/mock/install-mock-fetch-shim.js +0 -36
  206. package/dist/mock/install-mock-fetch-shim.js.map +0 -1
  207. package/dist/mock/load-package-mocks.js +0 -136
  208. package/dist/mock/load-package-mocks.js.map +0 -1
  209. package/dist/mock/mock-fetch-gateway.js +0 -343
  210. package/dist/mock/mock-fetch-gateway.js.map +0 -1
  211. package/dist/mock/mock-gateway-fetch-shim.js +0 -104
  212. package/dist/mock/mock-gateway-fetch-shim.js.map +0 -1
  213. package/dist/mock/mock-server.js +0 -499
  214. package/dist/mock/mock-server.js.map +0 -1
  215. package/dist/mock/mock-storage.js +0 -186
  216. package/dist/mock/mock-storage.js.map +0 -1
  217. package/dist/mock/mock-supported.js +0 -63
  218. package/dist/mock/mock-supported.js.map +0 -1
  219. package/dist/mock-dep-resolve.js +0 -47
  220. package/dist/mock-dep-resolve.js.map +0 -1
  221. package/dist/mock-local-deps.js +0 -207
  222. package/dist/mock-local-deps.js.map +0 -1
  223. package/dist/network-error.js +0 -11
  224. package/dist/network-error.js.map +0 -1
  225. package/dist/node-engine.js +0 -21
  226. package/dist/node-engine.js.map +0 -1
  227. package/dist/oauth-provider.js +0 -107
  228. package/dist/oauth-provider.js.map +0 -1
  229. package/dist/onboarding-prompt.js +0 -15
  230. package/dist/onboarding-prompt.js.map +0 -1
  231. package/dist/open-api-client.js +0 -432
  232. package/dist/open-api-client.js.map +0 -1
  233. package/dist/open-url.js +0 -21
  234. package/dist/open-url.js.map +0 -1
  235. package/dist/org-resolve.js +0 -16
  236. package/dist/org-resolve.js.map +0 -1
  237. package/dist/org-slug.js +0 -11
  238. package/dist/org-slug.js.map +0 -1
  239. package/dist/org.js +0 -100
  240. package/dist/org.js.map +0 -1
  241. package/dist/package-app-dev.js +0 -905
  242. package/dist/package-app-dev.js.map +0 -1
  243. package/dist/package-collaborators.js +0 -179
  244. package/dist/package-collaborators.js.map +0 -1
  245. package/dist/package-info.js +0 -19
  246. package/dist/package-info.js.map +0 -1
  247. package/dist/package-local-runtime-source.js.map +0 -1
  248. package/dist/package-manifest.js +0 -364
  249. package/dist/package-manifest.js.map +0 -1
  250. package/dist/process-info.js +0 -14
  251. package/dist/process-info.js.map +0 -1
  252. package/dist/redact.js +0 -16
  253. package/dist/redact.js.map +0 -1
  254. package/dist/remote-execute.js +0 -108
  255. package/dist/remote-execute.js.map +0 -1
  256. package/dist/setup-git.js +0 -676
  257. package/dist/setup-git.js.map +0 -1
  258. package/dist/skill.js +0 -35
  259. package/dist/skill.js.map +0 -1
  260. package/dist/store.js +0 -597
  261. package/dist/store.js.map +0 -1
  262. package/dist/structured-error.js +0 -57
  263. package/dist/structured-error.js.map +0 -1
  264. package/dist/target.js +0 -52
  265. package/dist/target.js.map +0 -1
  266. package/dist/tool-result.js +0 -19
  267. package/dist/tool-result.js.map +0 -1
  268. package/dist/which.js +0 -22
  269. package/dist/which.js.map +0 -1
  270. package/dist/workerd-binary.js +0 -98
  271. package/dist/workerd-binary.js.map +0 -1
@@ -0,0 +1,4900 @@
1
+ import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
+ import {
3
+ appLogMarker,
4
+ buildLocalPackageContext,
5
+ createPackageAppEntrySource,
6
+ createPackageLocalRuntimeModuleSource,
7
+ devErrorHeader,
8
+ devRequestIdHeader,
9
+ runLocalPackageModule
10
+ } from "./chunk-64XN367G.js";
11
+ import {
12
+ forwardLocalGatewayFetchStream,
13
+ installMockFetchShimModules,
14
+ startLocalRuntimeBridge
15
+ } from "./chunk-SXHULGL4.js";
16
+ import {
17
+ BundleError,
18
+ bundleLocalUserModule,
19
+ createBundleError,
20
+ createRuntimeFlatAliasSource,
21
+ createWorkerdConfig,
22
+ formatBundleDiagnostic,
23
+ init,
24
+ localBundleOptions,
25
+ localExecuteGatewayFetchShimModuleName,
26
+ localWorkerModuleNames,
27
+ parse,
28
+ resolveLocalPackageGraph,
29
+ runSecretEnvVar,
30
+ runSecretHeader,
31
+ writePackageModuleFiles
32
+ } from "./chunk-D55XPY3T.js";
33
+ import {
34
+ ensureMockTarget
35
+ } from "./chunk-XDCOWU5R.js";
36
+ import {
37
+ packageMocksRelativePath,
38
+ resolveMockFetchGateway,
39
+ tryHandleMockGatewayFetchCall
40
+ } from "./chunk-XOPPGRUP.js";
41
+ import {
42
+ loadPackageManifest,
43
+ resolveExportModulePath,
44
+ resolvePackagePath
45
+ } from "./chunk-64IM6G4Z.js";
46
+ import {
47
+ StructuredCliError
48
+ } from "./chunk-BPGY4IE7.js";
49
+ import {
50
+ formatToolResult
51
+ } from "./chunk-46IJPEID.js";
52
+ import {
53
+ assertTokenSafeApiUrl,
54
+ callCapabilityProxy
55
+ } from "./chunk-R4IUV5P5.js";
56
+ import {
57
+ ensureWorkerdBinary,
58
+ userCacheDir
59
+ } from "./chunk-BISUL7CE.js";
60
+ import "./chunk-G4YN6XP5.js";
61
+ import {
62
+ redact
63
+ } from "./chunk-CASGRYOF.js";
64
+ import "./chunk-G6LJWROP.js";
65
+ import "./chunk-RTWUNV76.js";
66
+ import "./chunk-RM34N3KI.js";
67
+ import {
68
+ apiTokenEnvVar
69
+ } from "./chunk-IHP6PV6X.js";
70
+ import "./chunk-QHBCP4OB.js";
71
+
72
+ // src/dev-command.ts
73
+ import { access, mkdir as mkdir3, readFile as readFile4, rm as rm4, writeFile as writeFile4 } from "node:fs/promises";
74
+ import { dirname as dirname3, join as join8, resolve as resolve7 } from "node:path";
75
+
76
+ // src/credentialed-fetch-scan.ts
77
+ var esModuleLexerReady = init();
78
+ async function detectCredentialedFetchInSource(code, where = "source") {
79
+ await esModuleLexerReady;
80
+ const signals = [];
81
+ const seen = /* @__PURE__ */ new Set();
82
+ const push = (kind) => {
83
+ if (seen.has(kind)) return;
84
+ seen.add(kind);
85
+ signals.push({ kind, where });
86
+ };
87
+ const codeWithoutComments = stripCommentsForScan(code);
88
+ if (/\bcreateAuthenticatedFetch\b/.test(codeWithoutComments)) {
89
+ push("createAuthenticatedFetch");
90
+ }
91
+ if (/\bauthenticatedFetch\b/.test(codeWithoutComments)) {
92
+ push("authenticatedFetch");
93
+ }
94
+ try {
95
+ const [imports] = parse(code);
96
+ for (const im of imports) {
97
+ if (im.type === "dynamic") {
98
+ continue;
99
+ }
100
+ if (im.typeOnly === true) continue;
101
+ if (im.specifier !== "kody:runtime") continue;
102
+ const record = im;
103
+ const statementStart = record.importStart ?? record.ss;
104
+ const statementEnd = record.importEnd ?? record.se;
105
+ if (typeof statementStart !== "number" || typeof statementEnd !== "number") {
106
+ continue;
107
+ }
108
+ const statement = code.slice(statementStart, statementEnd);
109
+ if (/\bcredentials?\b/.test(statement)) {
110
+ push("credential_runtime");
111
+ }
112
+ }
113
+ } catch {
114
+ }
115
+ return signals;
116
+ }
117
+ function stripCommentsForScan(code) {
118
+ return code.replace(/\/\*[\s\S]*?\*\//g, (block) => block.replace(/[^\n]/g, " ")).replace(/(^|[^:])\/\/.*$/gm, "$1");
119
+ }
120
+ function formatCredentialedFetchKinds(signals) {
121
+ const kinds = [...new Set(signals.map((s) => s.kind))];
122
+ return kinds.map((kind) => {
123
+ switch (kind) {
124
+ case "createAuthenticatedFetch":
125
+ return "createAuthenticatedFetch";
126
+ case "authenticatedFetch":
127
+ return "authenticatedFetch";
128
+ case "credential_runtime":
129
+ return "credential()/credentials()";
130
+ default: {
131
+ const _exhaustive = kind;
132
+ return _exhaustive;
133
+ }
134
+ }
135
+ }).join(", ");
136
+ }
137
+ function mocksSuggestionDetail(input) {
138
+ if (input.signals.length === 0) return null;
139
+ const kinds = formatCredentialedFetchKinds(input.signals);
140
+ if (input.hasMocksFile) {
141
+ return `present (credentialed fetch detected: ${kinds})`;
142
+ }
143
+ return `suggested \u2014 package uses credentialed fetch (${kinds}); add .kody/mocks.ts so --target mock can MSW-match outbound requests (unmocked credentialed hops fail closed)`;
144
+ }
145
+
146
+ // src/package-app-dev.ts
147
+ import { randomBytes } from "node:crypto";
148
+ import { rmSync } from "node:fs";
149
+ import { mkdir as mkdir2, mkdtemp, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
150
+ import {
151
+ createServer,
152
+ request as httpRequest
153
+ } from "node:http";
154
+ import { tmpdir as tmpdir2 } from "node:os";
155
+ import { join as join7, relative as relative4, resolve as resolve6, sep as sep3 } from "node:path";
156
+
157
+ // src/dev/dev-assets.ts
158
+ import * as esbuild2 from "esbuild";
159
+ import { createHash } from "node:crypto";
160
+ import { readFile, stat } from "node:fs/promises";
161
+ import { join as join2, resolve as resolve2, sep } from "node:path";
162
+
163
+ // src/dev/dev-bundler.ts
164
+ import * as esbuild from "esbuild";
165
+ import { join, resolve } from "node:path";
166
+ function createDevBundler(input) {
167
+ const entry = resolve(input.entryPath);
168
+ const base = localBundleOptions(entry);
169
+ const options = {
170
+ ...base,
171
+ sourcemap: "external",
172
+ sourcesContent: false,
173
+ metafile: true,
174
+ // Never written (write: false); only anchors source map paths at the root.
175
+ outfile: join(input.root, "__kody_dev_bundle.js")
176
+ };
177
+ const paths = { workingDir: base.absWorkingDir, displayRoot: input.root };
178
+ let disposed = false;
179
+ let context3 = null;
180
+ return {
181
+ build: async () => {
182
+ let result;
183
+ try {
184
+ if (disposed) throw new Error("kody dev bundler was already disposed.");
185
+ context3 ??= esbuild.context(options);
186
+ result = await (await context3).rebuild();
187
+ } catch (error) {
188
+ throw createBundleError(input.entryPath, error, paths);
189
+ }
190
+ return readBundle(result, base.absWorkingDir, input.entryPath);
191
+ },
192
+ dispose: async () => {
193
+ disposed = true;
194
+ const current = context3;
195
+ context3 = null;
196
+ await (await current?.catch(() => null))?.dispose();
197
+ }
198
+ };
199
+ }
200
+ function bundleInputs(metafile, workingDir) {
201
+ return Object.keys(metafile?.inputs ?? {}).filter((path) => !path.includes("node_modules") && !path.includes(":")).map((path) => resolve(workingDir, path));
202
+ }
203
+ function readBundle(result, workingDir, entryPath) {
204
+ const outputs = result.outputFiles ?? [];
205
+ const js = outputs.find((file) => file.path.endsWith(".js"));
206
+ const map = outputs.find((file) => file.path.endsWith(".js.map"));
207
+ if (!js) {
208
+ throw new BundleError(`Could not bundle ${entryPath}: esbuild produced no output.`, []);
209
+ }
210
+ return {
211
+ code: js.text.replace(/\n\/\/# sourceMappingURL=\S+\s*$/, "\n"),
212
+ sourceMap: map?.text ?? null,
213
+ inputs: bundleInputs(result.metafile, workingDir)
214
+ };
215
+ }
216
+
217
+ // src/dev/dev-assets.ts
218
+ var devAssetsPathPrefix = "/_assets/";
219
+ var devVersionAssetName = "__version.json";
220
+ var clientModuleHashLength = 16;
221
+ function createDevClientBundler(input) {
222
+ const externals = input.externals ?? [];
223
+ const workingDir = process.cwd();
224
+ let disposed = false;
225
+ let context3 = null;
226
+ const createContext = () => esbuild2.context({
227
+ absWorkingDir: workingDir,
228
+ entryPoints: [resolve2(input.entryPath)],
229
+ bundle: true,
230
+ write: false,
231
+ metafile: true,
232
+ format: "esm",
233
+ platform: "browser",
234
+ target: "es2022",
235
+ sourcemap: "inline",
236
+ logLevel: "silent",
237
+ outfile: join2(input.root, "_assets", "client.js"),
238
+ plugins: externals.length > 0 ? [clientExternalsPlugin(externals)] : []
239
+ });
240
+ return {
241
+ build: async () => {
242
+ try {
243
+ if (disposed) throw new Error("kody dev bundler was already disposed.");
244
+ context3 ??= createContext();
245
+ const result = await (await context3).rebuild();
246
+ const code = result.outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
247
+ const hash = createHash("sha256").update(code).digest("base64url").slice(0, clientModuleHashLength);
248
+ return {
249
+ name: `client.${hash}.js`,
250
+ code,
251
+ inputs: bundleInputs(result.metafile, workingDir)
252
+ };
253
+ } catch (error) {
254
+ throw createBundleError(input.entryPath, error, {
255
+ workingDir,
256
+ displayRoot: input.root
257
+ });
258
+ }
259
+ },
260
+ dispose: async () => {
261
+ disposed = true;
262
+ const current = context3;
263
+ context3 = null;
264
+ await (await current?.catch(() => null))?.dispose();
265
+ }
266
+ };
267
+ }
268
+ function clientExternalsPlugin(externals) {
269
+ return {
270
+ name: "kody-dev-client-externals",
271
+ setup(build) {
272
+ build.onResolve(
273
+ { filter: /^[^./]/ },
274
+ (args) => externals.some(
275
+ (external) => args.path === external || args.path.startsWith(`${external}/`)
276
+ ) ? { path: args.path, external: true } : void 0
277
+ );
278
+ }
279
+ };
280
+ }
281
+ function parseDevAssetPath(pathname) {
282
+ if (!pathname.startsWith(devAssetsPathPrefix)) return null;
283
+ const encoded = pathname.slice(devAssetsPathPrefix.length);
284
+ if (!encoded) return null;
285
+ try {
286
+ return decodeURIComponent(encoded);
287
+ } catch {
288
+ return null;
289
+ }
290
+ }
291
+ function resolveDevAssetFile(assetsDir, relativePath) {
292
+ if (relativePath.includes("\0") || relativePath.startsWith("/")) return null;
293
+ const root = resolve2(assetsDir);
294
+ const file = resolve2(root, relativePath);
295
+ return file.startsWith(`${root}${sep}`) ? file : null;
296
+ }
297
+ async function serveDevAsset(input) {
298
+ const { req, res } = input;
299
+ if (req.method !== "GET" && req.method !== "HEAD") {
300
+ res.writeHead(405, { allow: "GET, HEAD", "cache-control": "no-store" });
301
+ res.end("Method not allowed\n");
302
+ return;
303
+ }
304
+ if (input.relativePath === devVersionAssetName) {
305
+ send(req, res, "application/json; charset=utf-8", JSON.stringify({
306
+ clientModuleUrl: input.clientModuleUrl,
307
+ assetBasePath: `${input.appBasePath}/_assets`,
308
+ publishedCommit: null
309
+ }));
310
+ return;
311
+ }
312
+ if (input.client && input.relativePath === input.client.name) {
313
+ send(req, res, "text/javascript; charset=utf-8", input.client.code);
314
+ return;
315
+ }
316
+ const file = input.assetsDir ? resolveDevAssetFile(input.assetsDir, input.relativePath) : null;
317
+ const body = file ? await readAssetFile(file) : null;
318
+ if (!file || !body) {
319
+ res.writeHead(404, {
320
+ "content-type": "text/plain; charset=utf-8",
321
+ "cache-control": "no-store"
322
+ });
323
+ res.end("Not found\n");
324
+ return;
325
+ }
326
+ const contentType = inferDevAssetContentType(file);
327
+ send(req, res, contentType, body, contentType.startsWith("text/javascript") ? { "service-worker-allowed": `${input.appBasePath}/` } : {});
328
+ }
329
+ async function readAssetFile(file) {
330
+ try {
331
+ if (!(await stat(file)).isFile()) return null;
332
+ return await readFile(file);
333
+ } catch {
334
+ return null;
335
+ }
336
+ }
337
+ function send(req, res, contentType, body, extraHeaders = {}) {
338
+ const bytes = typeof body === "string" ? Buffer.from(body, "utf8") : body;
339
+ res.writeHead(200, {
340
+ "content-type": contentType,
341
+ "content-length": String(bytes.length),
342
+ "cache-control": "no-store",
343
+ "x-content-type-options": "nosniff",
344
+ ...extraHeaders
345
+ });
346
+ res.end(req.method === "HEAD" ? void 0 : bytes);
347
+ }
348
+ var contentTypesByExtension = {
349
+ avif: "image/avif",
350
+ css: "text/css; charset=utf-8",
351
+ csv: "text/csv; charset=utf-8",
352
+ gif: "image/gif",
353
+ htm: "text/html; charset=utf-8",
354
+ html: "text/html; charset=utf-8",
355
+ ico: "image/x-icon",
356
+ jpeg: "image/jpeg",
357
+ jpg: "image/jpeg",
358
+ js: "text/javascript; charset=utf-8",
359
+ json: "application/json; charset=utf-8",
360
+ map: "application/json; charset=utf-8",
361
+ md: "text/markdown; charset=utf-8",
362
+ mjs: "text/javascript; charset=utf-8",
363
+ mp3: "audio/mpeg",
364
+ mp4: "video/mp4",
365
+ oga: "audio/ogg",
366
+ ogg: "audio/ogg",
367
+ ogv: "video/ogg",
368
+ otf: "font/otf",
369
+ pdf: "application/pdf",
370
+ png: "image/png",
371
+ svg: "image/svg+xml; charset=utf-8",
372
+ ttf: "font/ttf",
373
+ txt: "text/plain; charset=utf-8",
374
+ wasm: "application/wasm",
375
+ wav: "audio/wav",
376
+ webm: "video/webm",
377
+ webmanifest: "application/manifest+json; charset=utf-8",
378
+ webp: "image/webp",
379
+ woff: "font/woff",
380
+ woff2: "font/woff2",
381
+ xml: "application/xml; charset=utf-8"
382
+ };
383
+ function inferDevAssetContentType(path) {
384
+ const name = path.split(/[\\/]/).pop() ?? "";
385
+ const separator = name.lastIndexOf(".");
386
+ const extension = separator <= 0 ? "" : name.slice(separator + 1).toLowerCase();
387
+ return contentTypesByExtension[extension] ?? "application/octet-stream";
388
+ }
389
+
390
+ // src/dev/dev-events.ts
391
+ var logLevels = /* @__PURE__ */ new Set(["log", "info", "warn", "error", "debug"]);
392
+ function parseWorkerdStdoutLine(line) {
393
+ if (line.startsWith(appLogMarker)) {
394
+ try {
395
+ const parsed = JSON.parse(line.slice(appLogMarker.length));
396
+ const level = typeof parsed.level === "string" && logLevels.has(parsed.level) ? parsed.level : "log";
397
+ return {
398
+ type: "log",
399
+ source: "app",
400
+ level,
401
+ message: typeof parsed.message === "string" ? parsed.message : String(parsed.message),
402
+ request: readRequestTag(parsed.request)
403
+ };
404
+ } catch {
405
+ }
406
+ }
407
+ return { type: "log", source: "app", level: "log", message: line, request: null };
408
+ }
409
+ function readRequestTag(value) {
410
+ if (!value || typeof value !== "object") return null;
411
+ const record = value;
412
+ if (typeof record.id !== "string") return null;
413
+ return {
414
+ id: record.id,
415
+ method: typeof record.method === "string" ? record.method : "GET",
416
+ path: typeof record.path === "string" ? record.path : "/"
417
+ };
418
+ }
419
+ function runtimeErrorFix(message) {
420
+ const dynamicRequire = /Dynamic require of "([^"]+)" is not supported/.exec(message);
421
+ if (dynamicRequire) {
422
+ return `A CommonJS dependency calls require("${dynamicRequire[1]}"), which an ESM Worker cannot run (hosted apps fail the same way). It likely resolved to its Node build: import the package\u2019s Workers/edge entry (an exports subpath or condition like \`edge\`, \`worker\`, or \`workerd\`) or an ESM build instead.`;
423
+ }
424
+ return void 0;
425
+ }
426
+ function formatRequestTag(request) {
427
+ return request ? `[${request.method} ${request.path} #${request.id}]` : "[app]";
428
+ }
429
+ function formatDevEvent(event) {
430
+ switch (event.type) {
431
+ case "rebuild_start":
432
+ return {
433
+ stream: "stderr",
434
+ text: event.files.length > 0 ? `Rebuilding (${event.files.join(", ")})\u2026` : "Building\u2026"
435
+ };
436
+ case "rebuild_ok":
437
+ return {
438
+ stream: "stderr",
439
+ text: event.restarted ? `Ready in ${event.ms}ms (build ${event.buildId})` : `No bundle changes (${event.ms}ms)`
440
+ };
441
+ case "build_error":
442
+ return {
443
+ stream: "stderr",
444
+ text: `Build failed${event.diagnostics.length > 0 ? `:
445
+ ${event.diagnostics.map(formatBundleDiagnostic).join("\n")}` : `: ${event.message}`}
446
+ The last good build is paused until this is fixed; requests get the error page.`
447
+ };
448
+ case "runtime_error":
449
+ return {
450
+ stream: "stderr",
451
+ text: `${formatRequestTag(event.request)} Uncaught ${event.stack || event.message}${event.fix ? `
452
+ fix: ${event.fix}` : ""}`
453
+ };
454
+ case "log": {
455
+ const tag = event.source === "app" ? formatRequestTag(event.request) : `[${event.source}]`;
456
+ const level = event.level === "log" || event.level === "info" ? "" : `${event.level}: `;
457
+ const stream = event.level === "error" || event.level === "warn" ? "stderr" : "stdout";
458
+ return { stream, text: `${tag} ${level}${event.message}` };
459
+ }
460
+ default: {
461
+ const exhaustive = event;
462
+ throw new Error(`Unhandled dev event: ${JSON.stringify(exhaustive)}`);
463
+ }
464
+ }
465
+ }
466
+
467
+ // src/dev/dev-port.ts
468
+ import { createHash as createHash2 } from "node:crypto";
469
+ var devPortRange = { min: 4100, max: 4999 };
470
+ var fallbackAttempts = 20;
471
+ function defaultDevPort(kodyId) {
472
+ const span = devPortRange.max - devPortRange.min + 1;
473
+ const hash = createHash2("sha256").update(kodyId).digest();
474
+ return devPortRange.min + hash.readUInt32BE(0) % span;
475
+ }
476
+ function parseDevPort(raw) {
477
+ const port = /^\d+$/.test(raw.trim()) ? Number(raw) : Number.NaN;
478
+ if (!Number.isInteger(port) || port > 65535) {
479
+ throw new StructuredCliError({
480
+ code: "invalid_port",
481
+ message: `--port must be an integer from 0 to 65535 (got "${raw}").`,
482
+ fix: "Pass --port 0 for any free port, or omit --port to use this package\u2019s stable default."
483
+ });
484
+ }
485
+ return port;
486
+ }
487
+ async function listenDevServer(server, input) {
488
+ const attempts = input.explicit || input.port === 0 ? 1 : fallbackAttempts;
489
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
490
+ const port = input.port === 0 ? 0 : wrapPort(input.port + attempt);
491
+ try {
492
+ await listenOnce(server, input.host, port);
493
+ return server.address().port;
494
+ } catch (error) {
495
+ if (!isAddressInUse(error)) throw error;
496
+ if (input.explicit) throw portInUseError(input.host, port);
497
+ }
498
+ }
499
+ throw new StructuredCliError({
500
+ code: "dev_port_in_use",
501
+ message: `Ports ${input.port}\u2013${wrapPort(input.port + attempts - 1)} on ${input.host} are all in use.`,
502
+ fix: "Stop old `kody dev` processes, or pass --port 0 for any free port."
503
+ });
504
+ }
505
+ function portInUseError(host, port) {
506
+ return new StructuredCliError({
507
+ code: "dev_port_in_use",
508
+ message: `Port ${port} on ${host} is already in use.`,
509
+ fix: `Find the owner with \`lsof -nP -iTCP:${port} -sTCP:LISTEN\` and stop it, pass another --port, or omit --port to use this package\u2019s default (it moves to the next free port automatically).`
510
+ });
511
+ }
512
+ function wrapPort(port) {
513
+ return port > 65535 ? devPortRange.min + (port - 65536) : port;
514
+ }
515
+ function listenOnce(server, host, port) {
516
+ return new Promise((resolve8, reject) => {
517
+ const onError = (error) => {
518
+ server.off("listening", onListening);
519
+ reject(error);
520
+ };
521
+ const onListening = () => {
522
+ server.off("error", onError);
523
+ resolve8();
524
+ };
525
+ server.once("error", onError);
526
+ server.once("listening", onListening);
527
+ server.listen(port, host);
528
+ });
529
+ }
530
+ function isAddressInUse(error) {
531
+ return error?.code === "EADDRINUSE";
532
+ }
533
+
534
+ // src/dev/dev-registry.ts
535
+ import { createHash as createHash3 } from "node:crypto";
536
+ import { mkdir, readFile as readFile3, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
537
+ import { join as join4 } from "node:path";
538
+
539
+ // src/dev/process-reaper.ts
540
+ import { spawn } from "node:child_process";
541
+ import { readdir, readFile as readFile2, rm, stat as stat2, writeFile } from "node:fs/promises";
542
+ import { tmpdir } from "node:os";
543
+ import { join as join3 } from "node:path";
544
+ import psList from "ps-list";
545
+ var devWorkDirPrefix = "kody-dev-";
546
+ var ownerFileName = "owner.json";
547
+ var legacyDirMinAgeMs = 10 * 6e4;
548
+ var reaperScript = `
549
+ pids=" "
550
+ while IFS= read -r line; do
551
+ case "$line" in
552
+ +*) pids="$pids\${line#+} " ;;
553
+ -*) pids="$(printf '%s' "$pids" | sed "s/ \${line#-} / /g")" ;;
554
+ esac
555
+ done
556
+ for entry in $pids; do
557
+ case "$entry" in
558
+ g*) /bin/kill -s KILL -- -\${entry#g} 2>/dev/null ;;
559
+ *) /bin/kill -s KILL -- $entry 2>/dev/null ;;
560
+ esac
561
+ done
562
+ rm -rf "$1"
563
+ `;
564
+ async function startProcessReaper(input) {
565
+ await writeFile(
566
+ join3(input.workDir, ownerFileName),
567
+ JSON.stringify({ pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
568
+ );
569
+ let reaper;
570
+ try {
571
+ reaper = spawn("/bin/sh", ["-c", reaperScript, "kody-dev-reaper", input.workDir], {
572
+ stdio: ["pipe", "ignore", "ignore"],
573
+ detached: true
574
+ });
575
+ reaper.on("error", () => {
576
+ reaper = void 0;
577
+ });
578
+ reaper.stdin?.on("error", () => {
579
+ });
580
+ reaper.unref();
581
+ reaper.stdin?.unref?.();
582
+ } catch {
583
+ reaper = void 0;
584
+ }
585
+ const send2 = (line) => {
586
+ if (reaper?.stdin?.writable) reaper.stdin.write(`${line}
587
+ `);
588
+ };
589
+ return {
590
+ track: (pid) => send2(`+${pid}`),
591
+ untrack: (pid) => send2(`-${pid}`),
592
+ trackGroup: (pid) => send2(`+g${pid}`),
593
+ untrackGroup: (pid) => send2(`-g${pid}`),
594
+ close: () => {
595
+ reaper?.stdin?.end();
596
+ reaper = void 0;
597
+ }
598
+ };
599
+ }
600
+ async function sweepStaleDevDirs(input = {}) {
601
+ const tmp = input.tmp ?? tmpdir();
602
+ const now = input.now ?? Date.now();
603
+ const isAlive = input.isAlive ?? isProcessAlive;
604
+ const kill = input.kill ?? ((pid) => process.kill(pid, "SIGKILL"));
605
+ const removed = [];
606
+ const killed = [];
607
+ let entries;
608
+ try {
609
+ entries = (await readdir(tmp)).filter((name) => name.startsWith(devWorkDirPrefix));
610
+ } catch {
611
+ return { removed, killed };
612
+ }
613
+ if (entries.length === 0) return { removed, killed };
614
+ let processes = [];
615
+ try {
616
+ processes = await (input.listProcesses ?? psList)();
617
+ } catch {
618
+ processes = [];
619
+ }
620
+ const byPid = new Map(processes.map((item) => [item.pid, item]));
621
+ for (const name of entries) {
622
+ const dir = join3(tmp, name);
623
+ try {
624
+ const owner = await readOwnerPid(dir);
625
+ if (owner !== null && isAlive(owner)) continue;
626
+ const workerds = processes.filter(
627
+ (item) => /workerd/.test(item.name) && (item.cmd ?? "").includes(`${dir}/`)
628
+ );
629
+ if (owner === null) {
630
+ const info = await stat2(dir);
631
+ if (now - info.mtimeMs < legacyDirMinAgeMs) continue;
632
+ if (workerds.some((item) => !isOrphaned(item, byPid, isAlive))) continue;
633
+ }
634
+ for (const item of workerds) {
635
+ try {
636
+ kill(item.pid);
637
+ killed.push(item.pid);
638
+ } catch {
639
+ }
640
+ }
641
+ await rm(dir, { recursive: true, force: true });
642
+ removed.push(dir);
643
+ } catch {
644
+ }
645
+ }
646
+ return { removed, killed };
647
+ }
648
+ function isOrphaned(item, byPid, isAlive) {
649
+ if (item.ppid === void 0) return false;
650
+ if (item.ppid <= 1 || !isAlive(item.ppid)) return true;
651
+ const parent = byPid.get(item.ppid);
652
+ return parent !== void 0 && !/node|kody/i.test(`${parent.name} ${parent.cmd ?? ""}`);
653
+ }
654
+ async function readOwnerPid(dir) {
655
+ try {
656
+ const parsed = JSON.parse(await readFile2(join3(dir, ownerFileName), "utf8"));
657
+ return typeof parsed.pid === "number" ? parsed.pid : null;
658
+ } catch {
659
+ return null;
660
+ }
661
+ }
662
+ function isProcessAlive(pid) {
663
+ try {
664
+ process.kill(pid, 0);
665
+ return true;
666
+ } catch (error) {
667
+ return error.code === "EPERM";
668
+ }
669
+ }
670
+
671
+ // src/dev/dev-registry.ts
672
+ var devStatusPath = "/__kody/dev/status";
673
+ function devRegistryPath(root, target, cacheDir = userCacheDir()) {
674
+ const key = createHash3("sha256").update(`${root}\0${target}`).digest("hex").slice(0, 16);
675
+ return join4(cacheDir, "dev-servers", `${key}.json`);
676
+ }
677
+ async function writeDevRegistration(registration, cacheDir) {
678
+ const path = devRegistryPath(registration.root, registration.target, cacheDir);
679
+ await mkdir(join4(path, ".."), { recursive: true });
680
+ await writeFile2(path, `${JSON.stringify(registration, null, 2)}
681
+ `);
682
+ return path;
683
+ }
684
+ async function removeDevRegistration(root, pid, target, cacheDir) {
685
+ const path = devRegistryPath(root, target, cacheDir);
686
+ try {
687
+ const current = await readRegistration(path);
688
+ if (!current || current.pid !== pid) return;
689
+ await rm2(path, { force: true });
690
+ } catch {
691
+ }
692
+ }
693
+ async function findRunningDevServer(input) {
694
+ const path = devRegistryPath(input.root, input.target, input.cacheDir);
695
+ const registration = await readRegistration(path);
696
+ if (!registration || registration.root !== input.root) return null;
697
+ if (!isProcessAlive(registration.pid)) {
698
+ const current = await readRegistration(path);
699
+ if (current && current.pid === registration.pid) {
700
+ await rm2(path, { force: true });
701
+ }
702
+ return null;
703
+ }
704
+ if (registration.target !== input.target) return null;
705
+ try {
706
+ const response = await (input.fetchFn ?? fetch)(
707
+ new URL(devStatusPath, registration.origin),
708
+ { signal: AbortSignal.timeout(input.timeoutMs ?? 1500) }
709
+ );
710
+ if (!response.ok) return null;
711
+ const status = await response.json();
712
+ if (status.package?.root !== input.root || status.target !== input.target) return null;
713
+ return { registration, status };
714
+ } catch {
715
+ return null;
716
+ }
717
+ }
718
+ async function readRegistration(path) {
719
+ try {
720
+ const parsed = JSON.parse(await readFile3(path, "utf8"));
721
+ if (typeof parsed.pid !== "number" || typeof parsed.origin !== "string" || typeof parsed.root !== "string" || parsed.target !== "mock" && parsed.target !== "prod") {
722
+ return null;
723
+ }
724
+ return {
725
+ pid: parsed.pid,
726
+ origin: parsed.origin,
727
+ port: typeof parsed.port === "number" ? parsed.port : Number(new URL(parsed.origin).port),
728
+ basePath: typeof parsed.basePath === "string" ? parsed.basePath : "",
729
+ target: parsed.target,
730
+ root: parsed.root
731
+ };
732
+ } catch {
733
+ return null;
734
+ }
735
+ }
736
+
737
+ // node_modules/chokidar/esm/index.js
738
+ import { stat as statcb } from "fs";
739
+ import { stat as stat5, readdir as readdir3 } from "fs/promises";
740
+ import { EventEmitter } from "events";
741
+ import * as sysPath2 from "path";
742
+
743
+ // node_modules/readdirp/esm/index.js
744
+ import { stat as stat3, lstat, readdir as readdir2, realpath } from "node:fs/promises";
745
+ import { Readable } from "node:stream";
746
+ import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from "node:path";
747
+ var EntryTypes = {
748
+ FILE_TYPE: "files",
749
+ DIR_TYPE: "directories",
750
+ FILE_DIR_TYPE: "files_directories",
751
+ EVERYTHING_TYPE: "all"
752
+ };
753
+ var defaultOptions = {
754
+ root: ".",
755
+ fileFilter: (_entryInfo) => true,
756
+ directoryFilter: (_entryInfo) => true,
757
+ type: EntryTypes.FILE_TYPE,
758
+ lstat: false,
759
+ depth: 2147483648,
760
+ alwaysStat: false,
761
+ highWaterMark: 4096
762
+ };
763
+ Object.freeze(defaultOptions);
764
+ var RECURSIVE_ERROR_CODE = "READDIRP_RECURSIVE_ERROR";
765
+ var NORMAL_FLOW_ERRORS = /* @__PURE__ */ new Set(["ENOENT", "EPERM", "EACCES", "ELOOP", RECURSIVE_ERROR_CODE]);
766
+ var ALL_TYPES = [
767
+ EntryTypes.DIR_TYPE,
768
+ EntryTypes.EVERYTHING_TYPE,
769
+ EntryTypes.FILE_DIR_TYPE,
770
+ EntryTypes.FILE_TYPE
771
+ ];
772
+ var DIR_TYPES = /* @__PURE__ */ new Set([
773
+ EntryTypes.DIR_TYPE,
774
+ EntryTypes.EVERYTHING_TYPE,
775
+ EntryTypes.FILE_DIR_TYPE
776
+ ]);
777
+ var FILE_TYPES = /* @__PURE__ */ new Set([
778
+ EntryTypes.EVERYTHING_TYPE,
779
+ EntryTypes.FILE_DIR_TYPE,
780
+ EntryTypes.FILE_TYPE
781
+ ]);
782
+ var isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);
783
+ var wantBigintFsStats = process.platform === "win32";
784
+ var emptyFn = (_entryInfo) => true;
785
+ var normalizeFilter = (filter) => {
786
+ if (filter === void 0)
787
+ return emptyFn;
788
+ if (typeof filter === "function")
789
+ return filter;
790
+ if (typeof filter === "string") {
791
+ const fl = filter.trim();
792
+ return (entry) => entry.basename === fl;
793
+ }
794
+ if (Array.isArray(filter)) {
795
+ const trItems = filter.map((item) => item.trim());
796
+ return (entry) => trItems.some((f) => entry.basename === f);
797
+ }
798
+ return emptyFn;
799
+ };
800
+ var ReaddirpStream = class extends Readable {
801
+ constructor(options = {}) {
802
+ super({
803
+ objectMode: true,
804
+ autoDestroy: true,
805
+ highWaterMark: options.highWaterMark
806
+ });
807
+ const opts = { ...defaultOptions, ...options };
808
+ const { root, type } = opts;
809
+ this._fileFilter = normalizeFilter(opts.fileFilter);
810
+ this._directoryFilter = normalizeFilter(opts.directoryFilter);
811
+ const statMethod = opts.lstat ? lstat : stat3;
812
+ if (wantBigintFsStats) {
813
+ this._stat = (path) => statMethod(path, { bigint: true });
814
+ } else {
815
+ this._stat = statMethod;
816
+ }
817
+ this._maxDepth = opts.depth ?? defaultOptions.depth;
818
+ this._wantsDir = type ? DIR_TYPES.has(type) : false;
819
+ this._wantsFile = type ? FILE_TYPES.has(type) : false;
820
+ this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
821
+ this._root = presolve(root);
822
+ this._isDirent = !opts.alwaysStat;
823
+ this._statsProp = this._isDirent ? "dirent" : "stats";
824
+ this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
825
+ this.parents = [this._exploreDir(root, 1)];
826
+ this.reading = false;
827
+ this.parent = void 0;
828
+ }
829
+ async _read(batch) {
830
+ if (this.reading)
831
+ return;
832
+ this.reading = true;
833
+ try {
834
+ while (!this.destroyed && batch > 0) {
835
+ const par = this.parent;
836
+ const fil = par && par.files;
837
+ if (fil && fil.length > 0) {
838
+ const { path, depth } = par;
839
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));
840
+ const awaited = await Promise.all(slice);
841
+ for (const entry of awaited) {
842
+ if (!entry)
843
+ continue;
844
+ if (this.destroyed)
845
+ return;
846
+ const entryType = await this._getEntryType(entry);
847
+ if (entryType === "directory" && this._directoryFilter(entry)) {
848
+ if (depth <= this._maxDepth) {
849
+ this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
850
+ }
851
+ if (this._wantsDir) {
852
+ this.push(entry);
853
+ batch--;
854
+ }
855
+ } else if ((entryType === "file" || this._includeAsFile(entry)) && this._fileFilter(entry)) {
856
+ if (this._wantsFile) {
857
+ this.push(entry);
858
+ batch--;
859
+ }
860
+ }
861
+ }
862
+ } else {
863
+ const parent = this.parents.pop();
864
+ if (!parent) {
865
+ this.push(null);
866
+ break;
867
+ }
868
+ this.parent = await parent;
869
+ if (this.destroyed)
870
+ return;
871
+ }
872
+ }
873
+ } catch (error) {
874
+ this.destroy(error);
875
+ } finally {
876
+ this.reading = false;
877
+ }
878
+ }
879
+ async _exploreDir(path, depth) {
880
+ let files;
881
+ try {
882
+ files = await readdir2(path, this._rdOptions);
883
+ } catch (error) {
884
+ this._onError(error);
885
+ }
886
+ return { files, depth, path };
887
+ }
888
+ async _formatEntry(dirent, path) {
889
+ let entry;
890
+ const basename3 = this._isDirent ? dirent.name : dirent;
891
+ try {
892
+ const fullPath = presolve(pjoin(path, basename3));
893
+ entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
894
+ entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
895
+ } catch (err) {
896
+ this._onError(err);
897
+ return;
898
+ }
899
+ return entry;
900
+ }
901
+ _onError(err) {
902
+ if (isNormalFlowError(err) && !this.destroyed) {
903
+ this.emit("warn", err);
904
+ } else {
905
+ this.destroy(err);
906
+ }
907
+ }
908
+ async _getEntryType(entry) {
909
+ if (!entry && this._statsProp in entry) {
910
+ return "";
911
+ }
912
+ const stats = entry[this._statsProp];
913
+ if (stats.isFile())
914
+ return "file";
915
+ if (stats.isDirectory())
916
+ return "directory";
917
+ if (stats && stats.isSymbolicLink()) {
918
+ const full = entry.fullPath;
919
+ try {
920
+ const entryRealPath = await realpath(full);
921
+ const entryRealPathStats = await lstat(entryRealPath);
922
+ if (entryRealPathStats.isFile()) {
923
+ return "file";
924
+ }
925
+ if (entryRealPathStats.isDirectory()) {
926
+ const len = entryRealPath.length;
927
+ if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {
928
+ const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
929
+ recursiveError.code = RECURSIVE_ERROR_CODE;
930
+ return this._onError(recursiveError);
931
+ }
932
+ return "directory";
933
+ }
934
+ } catch (error) {
935
+ this._onError(error);
936
+ return "";
937
+ }
938
+ }
939
+ }
940
+ _includeAsFile(entry) {
941
+ const stats = entry && entry[this._statsProp];
942
+ return stats && this._wantsEverything && !stats.isDirectory();
943
+ }
944
+ };
945
+ function readdirp(root, options = {}) {
946
+ let type = options.entryType || options.type;
947
+ if (type === "both")
948
+ type = EntryTypes.FILE_DIR_TYPE;
949
+ if (type)
950
+ options.type = type;
951
+ if (!root) {
952
+ throw new Error("readdirp: root argument is required. Usage: readdirp(root, options)");
953
+ } else if (typeof root !== "string") {
954
+ throw new TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");
955
+ } else if (type && !ALL_TYPES.includes(type)) {
956
+ throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(", ")}`);
957
+ }
958
+ options.root = root;
959
+ return new ReaddirpStream(options);
960
+ }
961
+
962
+ // node_modules/chokidar/esm/handler.js
963
+ import { watchFile, unwatchFile, watch as fs_watch } from "fs";
964
+ import { open, stat as stat4, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
965
+ import * as sysPath from "path";
966
+ import { type as osType } from "os";
967
+ var STR_DATA = "data";
968
+ var STR_END = "end";
969
+ var STR_CLOSE = "close";
970
+ var EMPTY_FN = () => {
971
+ };
972
+ var pl = process.platform;
973
+ var isWindows = pl === "win32";
974
+ var isMacos = pl === "darwin";
975
+ var isLinux = pl === "linux";
976
+ var isFreeBSD = pl === "freebsd";
977
+ var isIBMi = osType() === "OS400";
978
+ var EVENTS = {
979
+ ALL: "all",
980
+ READY: "ready",
981
+ ADD: "add",
982
+ CHANGE: "change",
983
+ ADD_DIR: "addDir",
984
+ UNLINK: "unlink",
985
+ UNLINK_DIR: "unlinkDir",
986
+ RAW: "raw",
987
+ ERROR: "error"
988
+ };
989
+ var EV = EVENTS;
990
+ var THROTTLE_MODE_WATCH = "watch";
991
+ var statMethods = { lstat: lstat2, stat: stat4 };
992
+ var KEY_LISTENERS = "listeners";
993
+ var KEY_ERR = "errHandlers";
994
+ var KEY_RAW = "rawEmitters";
995
+ var HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];
996
+ var binaryExtensions = /* @__PURE__ */ new Set([
997
+ "3dm",
998
+ "3ds",
999
+ "3g2",
1000
+ "3gp",
1001
+ "7z",
1002
+ "a",
1003
+ "aac",
1004
+ "adp",
1005
+ "afdesign",
1006
+ "afphoto",
1007
+ "afpub",
1008
+ "ai",
1009
+ "aif",
1010
+ "aiff",
1011
+ "alz",
1012
+ "ape",
1013
+ "apk",
1014
+ "appimage",
1015
+ "ar",
1016
+ "arj",
1017
+ "asf",
1018
+ "au",
1019
+ "avi",
1020
+ "bak",
1021
+ "baml",
1022
+ "bh",
1023
+ "bin",
1024
+ "bk",
1025
+ "bmp",
1026
+ "btif",
1027
+ "bz2",
1028
+ "bzip2",
1029
+ "cab",
1030
+ "caf",
1031
+ "cgm",
1032
+ "class",
1033
+ "cmx",
1034
+ "cpio",
1035
+ "cr2",
1036
+ "cur",
1037
+ "dat",
1038
+ "dcm",
1039
+ "deb",
1040
+ "dex",
1041
+ "djvu",
1042
+ "dll",
1043
+ "dmg",
1044
+ "dng",
1045
+ "doc",
1046
+ "docm",
1047
+ "docx",
1048
+ "dot",
1049
+ "dotm",
1050
+ "dra",
1051
+ "DS_Store",
1052
+ "dsk",
1053
+ "dts",
1054
+ "dtshd",
1055
+ "dvb",
1056
+ "dwg",
1057
+ "dxf",
1058
+ "ecelp4800",
1059
+ "ecelp7470",
1060
+ "ecelp9600",
1061
+ "egg",
1062
+ "eol",
1063
+ "eot",
1064
+ "epub",
1065
+ "exe",
1066
+ "f4v",
1067
+ "fbs",
1068
+ "fh",
1069
+ "fla",
1070
+ "flac",
1071
+ "flatpak",
1072
+ "fli",
1073
+ "flv",
1074
+ "fpx",
1075
+ "fst",
1076
+ "fvt",
1077
+ "g3",
1078
+ "gh",
1079
+ "gif",
1080
+ "graffle",
1081
+ "gz",
1082
+ "gzip",
1083
+ "h261",
1084
+ "h263",
1085
+ "h264",
1086
+ "icns",
1087
+ "ico",
1088
+ "ief",
1089
+ "img",
1090
+ "ipa",
1091
+ "iso",
1092
+ "jar",
1093
+ "jpeg",
1094
+ "jpg",
1095
+ "jpgv",
1096
+ "jpm",
1097
+ "jxr",
1098
+ "key",
1099
+ "ktx",
1100
+ "lha",
1101
+ "lib",
1102
+ "lvp",
1103
+ "lz",
1104
+ "lzh",
1105
+ "lzma",
1106
+ "lzo",
1107
+ "m3u",
1108
+ "m4a",
1109
+ "m4v",
1110
+ "mar",
1111
+ "mdi",
1112
+ "mht",
1113
+ "mid",
1114
+ "midi",
1115
+ "mj2",
1116
+ "mka",
1117
+ "mkv",
1118
+ "mmr",
1119
+ "mng",
1120
+ "mobi",
1121
+ "mov",
1122
+ "movie",
1123
+ "mp3",
1124
+ "mp4",
1125
+ "mp4a",
1126
+ "mpeg",
1127
+ "mpg",
1128
+ "mpga",
1129
+ "mxu",
1130
+ "nef",
1131
+ "npx",
1132
+ "numbers",
1133
+ "nupkg",
1134
+ "o",
1135
+ "odp",
1136
+ "ods",
1137
+ "odt",
1138
+ "oga",
1139
+ "ogg",
1140
+ "ogv",
1141
+ "otf",
1142
+ "ott",
1143
+ "pages",
1144
+ "pbm",
1145
+ "pcx",
1146
+ "pdb",
1147
+ "pdf",
1148
+ "pea",
1149
+ "pgm",
1150
+ "pic",
1151
+ "png",
1152
+ "pnm",
1153
+ "pot",
1154
+ "potm",
1155
+ "potx",
1156
+ "ppa",
1157
+ "ppam",
1158
+ "ppm",
1159
+ "pps",
1160
+ "ppsm",
1161
+ "ppsx",
1162
+ "ppt",
1163
+ "pptm",
1164
+ "pptx",
1165
+ "psd",
1166
+ "pya",
1167
+ "pyc",
1168
+ "pyo",
1169
+ "pyv",
1170
+ "qt",
1171
+ "rar",
1172
+ "ras",
1173
+ "raw",
1174
+ "resources",
1175
+ "rgb",
1176
+ "rip",
1177
+ "rlc",
1178
+ "rmf",
1179
+ "rmvb",
1180
+ "rpm",
1181
+ "rtf",
1182
+ "rz",
1183
+ "s3m",
1184
+ "s7z",
1185
+ "scpt",
1186
+ "sgi",
1187
+ "shar",
1188
+ "snap",
1189
+ "sil",
1190
+ "sketch",
1191
+ "slk",
1192
+ "smv",
1193
+ "snk",
1194
+ "so",
1195
+ "stl",
1196
+ "suo",
1197
+ "sub",
1198
+ "swf",
1199
+ "tar",
1200
+ "tbz",
1201
+ "tbz2",
1202
+ "tga",
1203
+ "tgz",
1204
+ "thmx",
1205
+ "tif",
1206
+ "tiff",
1207
+ "tlz",
1208
+ "ttc",
1209
+ "ttf",
1210
+ "txz",
1211
+ "udf",
1212
+ "uvh",
1213
+ "uvi",
1214
+ "uvm",
1215
+ "uvp",
1216
+ "uvs",
1217
+ "uvu",
1218
+ "viv",
1219
+ "vob",
1220
+ "war",
1221
+ "wav",
1222
+ "wax",
1223
+ "wbmp",
1224
+ "wdp",
1225
+ "weba",
1226
+ "webm",
1227
+ "webp",
1228
+ "whl",
1229
+ "wim",
1230
+ "wm",
1231
+ "wma",
1232
+ "wmv",
1233
+ "wmx",
1234
+ "woff",
1235
+ "woff2",
1236
+ "wrm",
1237
+ "wvx",
1238
+ "xbm",
1239
+ "xif",
1240
+ "xla",
1241
+ "xlam",
1242
+ "xls",
1243
+ "xlsb",
1244
+ "xlsm",
1245
+ "xlsx",
1246
+ "xlt",
1247
+ "xltm",
1248
+ "xltx",
1249
+ "xm",
1250
+ "xmind",
1251
+ "xpi",
1252
+ "xpm",
1253
+ "xwd",
1254
+ "xz",
1255
+ "z",
1256
+ "zip",
1257
+ "zipx"
1258
+ ]);
1259
+ var isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
1260
+ var foreach = (val, fn) => {
1261
+ if (val instanceof Set) {
1262
+ val.forEach(fn);
1263
+ } else {
1264
+ fn(val);
1265
+ }
1266
+ };
1267
+ var addAndConvert = (main, prop, item) => {
1268
+ let container = main[prop];
1269
+ if (!(container instanceof Set)) {
1270
+ main[prop] = container = /* @__PURE__ */ new Set([container]);
1271
+ }
1272
+ container.add(item);
1273
+ };
1274
+ var clearItem = (cont) => (key) => {
1275
+ const set = cont[key];
1276
+ if (set instanceof Set) {
1277
+ set.clear();
1278
+ } else {
1279
+ delete cont[key];
1280
+ }
1281
+ };
1282
+ var delFromSet = (main, prop, item) => {
1283
+ const container = main[prop];
1284
+ if (container instanceof Set) {
1285
+ container.delete(item);
1286
+ } else if (container === item) {
1287
+ delete main[prop];
1288
+ }
1289
+ };
1290
+ var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
1291
+ var FsWatchInstances = /* @__PURE__ */ new Map();
1292
+ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
1293
+ const handleEvent = (rawEvent, evPath) => {
1294
+ listener(path);
1295
+ emitRaw(rawEvent, evPath, { watchedPath: path });
1296
+ if (evPath && path !== evPath) {
1297
+ fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
1298
+ }
1299
+ };
1300
+ try {
1301
+ return fs_watch(path, {
1302
+ persistent: options.persistent
1303
+ }, handleEvent);
1304
+ } catch (error) {
1305
+ errHandler(error);
1306
+ return void 0;
1307
+ }
1308
+ }
1309
+ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
1310
+ const cont = FsWatchInstances.get(fullPath);
1311
+ if (!cont)
1312
+ return;
1313
+ foreach(cont[listenerType], (listener) => {
1314
+ listener(val1, val2, val3);
1315
+ });
1316
+ };
1317
+ var setFsWatchListener = (path, fullPath, options, handlers) => {
1318
+ const { listener, errHandler, rawEmitter } = handlers;
1319
+ let cont = FsWatchInstances.get(fullPath);
1320
+ let watcher;
1321
+ if (!options.persistent) {
1322
+ watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);
1323
+ if (!watcher)
1324
+ return;
1325
+ return watcher.close.bind(watcher);
1326
+ }
1327
+ if (cont) {
1328
+ addAndConvert(cont, KEY_LISTENERS, listener);
1329
+ addAndConvert(cont, KEY_ERR, errHandler);
1330
+ addAndConvert(cont, KEY_RAW, rawEmitter);
1331
+ } else {
1332
+ watcher = createFsWatchInstance(
1333
+ path,
1334
+ options,
1335
+ fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
1336
+ errHandler,
1337
+ // no need to use broadcast here
1338
+ fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
1339
+ );
1340
+ if (!watcher)
1341
+ return;
1342
+ watcher.on(EV.ERROR, async (error) => {
1343
+ const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
1344
+ if (cont)
1345
+ cont.watcherUnusable = true;
1346
+ if (isWindows && error.code === "EPERM") {
1347
+ try {
1348
+ const fd = await open(path, "r");
1349
+ await fd.close();
1350
+ broadcastErr(error);
1351
+ } catch (err) {
1352
+ }
1353
+ } else {
1354
+ broadcastErr(error);
1355
+ }
1356
+ });
1357
+ cont = {
1358
+ listeners: listener,
1359
+ errHandlers: errHandler,
1360
+ rawEmitters: rawEmitter,
1361
+ watcher
1362
+ };
1363
+ FsWatchInstances.set(fullPath, cont);
1364
+ }
1365
+ return () => {
1366
+ delFromSet(cont, KEY_LISTENERS, listener);
1367
+ delFromSet(cont, KEY_ERR, errHandler);
1368
+ delFromSet(cont, KEY_RAW, rawEmitter);
1369
+ if (isEmptySet(cont.listeners)) {
1370
+ cont.watcher.close();
1371
+ FsWatchInstances.delete(fullPath);
1372
+ HANDLER_KEYS.forEach(clearItem(cont));
1373
+ cont.watcher = void 0;
1374
+ Object.freeze(cont);
1375
+ }
1376
+ };
1377
+ };
1378
+ var FsWatchFileInstances = /* @__PURE__ */ new Map();
1379
+ var setFsWatchFileListener = (path, fullPath, options, handlers) => {
1380
+ const { listener, rawEmitter } = handlers;
1381
+ let cont = FsWatchFileInstances.get(fullPath);
1382
+ const copts = cont && cont.options;
1383
+ if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
1384
+ unwatchFile(fullPath);
1385
+ cont = void 0;
1386
+ }
1387
+ if (cont) {
1388
+ addAndConvert(cont, KEY_LISTENERS, listener);
1389
+ addAndConvert(cont, KEY_RAW, rawEmitter);
1390
+ } else {
1391
+ cont = {
1392
+ listeners: listener,
1393
+ rawEmitters: rawEmitter,
1394
+ options,
1395
+ watcher: watchFile(fullPath, options, (curr, prev) => {
1396
+ foreach(cont.rawEmitters, (rawEmitter2) => {
1397
+ rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
1398
+ });
1399
+ const currmtime = curr.mtimeMs;
1400
+ if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
1401
+ foreach(cont.listeners, (listener2) => listener2(path, curr));
1402
+ }
1403
+ })
1404
+ };
1405
+ FsWatchFileInstances.set(fullPath, cont);
1406
+ }
1407
+ return () => {
1408
+ delFromSet(cont, KEY_LISTENERS, listener);
1409
+ delFromSet(cont, KEY_RAW, rawEmitter);
1410
+ if (isEmptySet(cont.listeners)) {
1411
+ FsWatchFileInstances.delete(fullPath);
1412
+ unwatchFile(fullPath);
1413
+ cont.options = cont.watcher = void 0;
1414
+ Object.freeze(cont);
1415
+ }
1416
+ };
1417
+ };
1418
+ var NodeFsHandler = class {
1419
+ constructor(fsW) {
1420
+ this.fsw = fsW;
1421
+ this._boundHandleError = (error) => fsW._handleError(error);
1422
+ }
1423
+ /**
1424
+ * Watch file for changes with fs_watchFile or fs_watch.
1425
+ * @param path to file or dir
1426
+ * @param listener on fs change
1427
+ * @returns closer for the watcher instance
1428
+ */
1429
+ _watchWithNodeFs(path, listener) {
1430
+ const opts = this.fsw.options;
1431
+ const directory = sysPath.dirname(path);
1432
+ const basename3 = sysPath.basename(path);
1433
+ const parent = this.fsw._getWatchedDir(directory);
1434
+ parent.add(basename3);
1435
+ const absolutePath = sysPath.resolve(path);
1436
+ const options = {
1437
+ persistent: opts.persistent
1438
+ };
1439
+ if (!listener)
1440
+ listener = EMPTY_FN;
1441
+ let closer;
1442
+ if (opts.usePolling) {
1443
+ const enableBin = opts.interval !== opts.binaryInterval;
1444
+ options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
1445
+ closer = setFsWatchFileListener(path, absolutePath, options, {
1446
+ listener,
1447
+ rawEmitter: this.fsw._emitRaw
1448
+ });
1449
+ } else {
1450
+ closer = setFsWatchListener(path, absolutePath, options, {
1451
+ listener,
1452
+ errHandler: this._boundHandleError,
1453
+ rawEmitter: this.fsw._emitRaw
1454
+ });
1455
+ }
1456
+ return closer;
1457
+ }
1458
+ /**
1459
+ * Watch a file and emit add event if warranted.
1460
+ * @returns closer for the watcher instance
1461
+ */
1462
+ _handleFile(file, stats, initialAdd) {
1463
+ if (this.fsw.closed) {
1464
+ return;
1465
+ }
1466
+ const dirname4 = sysPath.dirname(file);
1467
+ const basename3 = sysPath.basename(file);
1468
+ const parent = this.fsw._getWatchedDir(dirname4);
1469
+ let prevStats = stats;
1470
+ if (parent.has(basename3))
1471
+ return;
1472
+ const listener = async (path, newStats) => {
1473
+ if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
1474
+ return;
1475
+ if (!newStats || newStats.mtimeMs === 0) {
1476
+ try {
1477
+ const newStats2 = await stat4(file);
1478
+ if (this.fsw.closed)
1479
+ return;
1480
+ const at = newStats2.atimeMs;
1481
+ const mt = newStats2.mtimeMs;
1482
+ if (!at || at <= mt || mt !== prevStats.mtimeMs) {
1483
+ this.fsw._emit(EV.CHANGE, file, newStats2);
1484
+ }
1485
+ if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
1486
+ this.fsw._closeFile(path);
1487
+ prevStats = newStats2;
1488
+ const closer2 = this._watchWithNodeFs(file, listener);
1489
+ if (closer2)
1490
+ this.fsw._addPathCloser(path, closer2);
1491
+ } else {
1492
+ prevStats = newStats2;
1493
+ }
1494
+ } catch (error) {
1495
+ this.fsw._remove(dirname4, basename3);
1496
+ }
1497
+ } else if (parent.has(basename3)) {
1498
+ const at = newStats.atimeMs;
1499
+ const mt = newStats.mtimeMs;
1500
+ if (!at || at <= mt || mt !== prevStats.mtimeMs) {
1501
+ this.fsw._emit(EV.CHANGE, file, newStats);
1502
+ }
1503
+ prevStats = newStats;
1504
+ }
1505
+ };
1506
+ const closer = this._watchWithNodeFs(file, listener);
1507
+ if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
1508
+ if (!this.fsw._throttle(EV.ADD, file, 0))
1509
+ return;
1510
+ this.fsw._emit(EV.ADD, file, stats);
1511
+ }
1512
+ return closer;
1513
+ }
1514
+ /**
1515
+ * Handle symlinks encountered while reading a dir.
1516
+ * @param entry returned by readdirp
1517
+ * @param directory path of dir being read
1518
+ * @param path of this item
1519
+ * @param item basename of this item
1520
+ * @returns true if no more processing is needed for this entry.
1521
+ */
1522
+ async _handleSymlink(entry, directory, path, item) {
1523
+ if (this.fsw.closed) {
1524
+ return;
1525
+ }
1526
+ const full = entry.fullPath;
1527
+ const dir = this.fsw._getWatchedDir(directory);
1528
+ if (!this.fsw.options.followSymlinks) {
1529
+ this.fsw._incrReadyCount();
1530
+ let linkPath;
1531
+ try {
1532
+ linkPath = await fsrealpath(path);
1533
+ } catch (e) {
1534
+ this.fsw._emitReady();
1535
+ return true;
1536
+ }
1537
+ if (this.fsw.closed)
1538
+ return;
1539
+ if (dir.has(item)) {
1540
+ if (this.fsw._symlinkPaths.get(full) !== linkPath) {
1541
+ this.fsw._symlinkPaths.set(full, linkPath);
1542
+ this.fsw._emit(EV.CHANGE, path, entry.stats);
1543
+ }
1544
+ } else {
1545
+ dir.add(item);
1546
+ this.fsw._symlinkPaths.set(full, linkPath);
1547
+ this.fsw._emit(EV.ADD, path, entry.stats);
1548
+ }
1549
+ this.fsw._emitReady();
1550
+ return true;
1551
+ }
1552
+ if (this.fsw._symlinkPaths.has(full)) {
1553
+ return true;
1554
+ }
1555
+ this.fsw._symlinkPaths.set(full, true);
1556
+ }
1557
+ _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
1558
+ directory = sysPath.join(directory, "");
1559
+ throttler = this.fsw._throttle("readdir", directory, 1e3);
1560
+ if (!throttler)
1561
+ return;
1562
+ const previous = this.fsw._getWatchedDir(wh.path);
1563
+ const current = /* @__PURE__ */ new Set();
1564
+ let stream = this.fsw._readdirp(directory, {
1565
+ fileFilter: (entry) => wh.filterPath(entry),
1566
+ directoryFilter: (entry) => wh.filterDir(entry)
1567
+ });
1568
+ if (!stream)
1569
+ return;
1570
+ stream.on(STR_DATA, async (entry) => {
1571
+ if (this.fsw.closed) {
1572
+ stream = void 0;
1573
+ return;
1574
+ }
1575
+ const item = entry.path;
1576
+ let path = sysPath.join(directory, item);
1577
+ current.add(item);
1578
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
1579
+ return;
1580
+ }
1581
+ if (this.fsw.closed) {
1582
+ stream = void 0;
1583
+ return;
1584
+ }
1585
+ if (item === target || !target && !previous.has(item)) {
1586
+ this.fsw._incrReadyCount();
1587
+ path = sysPath.join(dir, sysPath.relative(dir, path));
1588
+ this._addToNodeFs(path, initialAdd, wh, depth + 1);
1589
+ }
1590
+ }).on(EV.ERROR, this._boundHandleError);
1591
+ return new Promise((resolve8, reject) => {
1592
+ if (!stream)
1593
+ return reject();
1594
+ stream.once(STR_END, () => {
1595
+ if (this.fsw.closed) {
1596
+ stream = void 0;
1597
+ return;
1598
+ }
1599
+ const wasThrottled = throttler ? throttler.clear() : false;
1600
+ resolve8(void 0);
1601
+ previous.getChildren().filter((item) => {
1602
+ return item !== directory && !current.has(item);
1603
+ }).forEach((item) => {
1604
+ this.fsw._remove(directory, item);
1605
+ });
1606
+ stream = void 0;
1607
+ if (wasThrottled)
1608
+ this._handleRead(directory, false, wh, target, dir, depth, throttler);
1609
+ });
1610
+ });
1611
+ }
1612
+ /**
1613
+ * Read directory to add / remove files from `@watched` list and re-read it on change.
1614
+ * @param dir fs path
1615
+ * @param stats
1616
+ * @param initialAdd
1617
+ * @param depth relative to user-supplied path
1618
+ * @param target child path targeted for watch
1619
+ * @param wh Common watch helpers for this path
1620
+ * @param realpath
1621
+ * @returns closer for the watcher instance.
1622
+ */
1623
+ async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
1624
+ const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
1625
+ const tracked = parentDir.has(sysPath.basename(dir));
1626
+ if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
1627
+ this.fsw._emit(EV.ADD_DIR, dir, stats);
1628
+ }
1629
+ parentDir.add(sysPath.basename(dir));
1630
+ this.fsw._getWatchedDir(dir);
1631
+ let throttler;
1632
+ let closer;
1633
+ const oDepth = this.fsw.options.depth;
1634
+ if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath2)) {
1635
+ if (!target) {
1636
+ await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
1637
+ if (this.fsw.closed)
1638
+ return;
1639
+ }
1640
+ closer = this._watchWithNodeFs(dir, (dirPath, stats2) => {
1641
+ if (stats2 && stats2.mtimeMs === 0)
1642
+ return;
1643
+ this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
1644
+ });
1645
+ }
1646
+ return closer;
1647
+ }
1648
+ /**
1649
+ * Handle added file, directory, or glob pattern.
1650
+ * Delegates call to _handleFile / _handleDir after checks.
1651
+ * @param path to file or ir
1652
+ * @param initialAdd was the file added at watch instantiation?
1653
+ * @param priorWh depth relative to user-supplied path
1654
+ * @param depth Child path actually targeted for watch
1655
+ * @param target Child path actually targeted for watch
1656
+ */
1657
+ async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
1658
+ const ready = this.fsw._emitReady;
1659
+ if (this.fsw._isIgnored(path) || this.fsw.closed) {
1660
+ ready();
1661
+ return false;
1662
+ }
1663
+ const wh = this.fsw._getWatchHelpers(path);
1664
+ if (priorWh) {
1665
+ wh.filterPath = (entry) => priorWh.filterPath(entry);
1666
+ wh.filterDir = (entry) => priorWh.filterDir(entry);
1667
+ }
1668
+ try {
1669
+ const stats = await statMethods[wh.statMethod](wh.watchPath);
1670
+ if (this.fsw.closed)
1671
+ return;
1672
+ if (this.fsw._isIgnored(wh.watchPath, stats)) {
1673
+ ready();
1674
+ return false;
1675
+ }
1676
+ const follow = this.fsw.options.followSymlinks;
1677
+ let closer;
1678
+ if (stats.isDirectory()) {
1679
+ const absPath = sysPath.resolve(path);
1680
+ const targetPath = follow ? await fsrealpath(path) : path;
1681
+ if (this.fsw.closed)
1682
+ return;
1683
+ closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
1684
+ if (this.fsw.closed)
1685
+ return;
1686
+ if (absPath !== targetPath && targetPath !== void 0) {
1687
+ this.fsw._symlinkPaths.set(absPath, targetPath);
1688
+ }
1689
+ } else if (stats.isSymbolicLink()) {
1690
+ const targetPath = follow ? await fsrealpath(path) : path;
1691
+ if (this.fsw.closed)
1692
+ return;
1693
+ const parent = sysPath.dirname(wh.watchPath);
1694
+ this.fsw._getWatchedDir(parent).add(wh.watchPath);
1695
+ this.fsw._emit(EV.ADD, wh.watchPath, stats);
1696
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
1697
+ if (this.fsw.closed)
1698
+ return;
1699
+ if (targetPath !== void 0) {
1700
+ this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
1701
+ }
1702
+ } else {
1703
+ closer = this._handleFile(wh.watchPath, stats, initialAdd);
1704
+ }
1705
+ ready();
1706
+ if (closer)
1707
+ this.fsw._addPathCloser(path, closer);
1708
+ return false;
1709
+ } catch (error) {
1710
+ if (this.fsw._handleError(error)) {
1711
+ ready();
1712
+ return path;
1713
+ }
1714
+ }
1715
+ }
1716
+ };
1717
+
1718
+ // node_modules/chokidar/esm/index.js
1719
+ var SLASH = "/";
1720
+ var SLASH_SLASH = "//";
1721
+ var ONE_DOT = ".";
1722
+ var TWO_DOTS = "..";
1723
+ var STRING_TYPE = "string";
1724
+ var BACK_SLASH_RE = /\\/g;
1725
+ var DOUBLE_SLASH_RE = /\/\//;
1726
+ var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
1727
+ var REPLACER_RE = /^\.[/\\]/;
1728
+ function arrify(item) {
1729
+ return Array.isArray(item) ? item : [item];
1730
+ }
1731
+ var isMatcherObject = (matcher) => typeof matcher === "object" && matcher !== null && !(matcher instanceof RegExp);
1732
+ function createPattern(matcher) {
1733
+ if (typeof matcher === "function")
1734
+ return matcher;
1735
+ if (typeof matcher === "string")
1736
+ return (string) => matcher === string;
1737
+ if (matcher instanceof RegExp)
1738
+ return (string) => matcher.test(string);
1739
+ if (typeof matcher === "object" && matcher !== null) {
1740
+ return (string) => {
1741
+ if (matcher.path === string)
1742
+ return true;
1743
+ if (matcher.recursive) {
1744
+ const relative5 = sysPath2.relative(matcher.path, string);
1745
+ if (!relative5) {
1746
+ return false;
1747
+ }
1748
+ return !relative5.startsWith("..") && !sysPath2.isAbsolute(relative5);
1749
+ }
1750
+ return false;
1751
+ };
1752
+ }
1753
+ return () => false;
1754
+ }
1755
+ function normalizePath(path) {
1756
+ if (typeof path !== "string")
1757
+ throw new Error("string expected");
1758
+ path = sysPath2.normalize(path);
1759
+ path = path.replace(/\\/g, "/");
1760
+ let prepend = false;
1761
+ if (path.startsWith("//"))
1762
+ prepend = true;
1763
+ const DOUBLE_SLASH_RE2 = /\/\//;
1764
+ while (path.match(DOUBLE_SLASH_RE2))
1765
+ path = path.replace(DOUBLE_SLASH_RE2, "/");
1766
+ if (prepend)
1767
+ path = "/" + path;
1768
+ return path;
1769
+ }
1770
+ function matchPatterns(patterns, testString, stats) {
1771
+ const path = normalizePath(testString);
1772
+ for (let index = 0; index < patterns.length; index++) {
1773
+ const pattern = patterns[index];
1774
+ if (pattern(path, stats)) {
1775
+ return true;
1776
+ }
1777
+ }
1778
+ return false;
1779
+ }
1780
+ function anymatch(matchers, testString) {
1781
+ if (matchers == null) {
1782
+ throw new TypeError("anymatch: specify first argument");
1783
+ }
1784
+ const matchersArray = arrify(matchers);
1785
+ const patterns = matchersArray.map((matcher) => createPattern(matcher));
1786
+ if (testString == null) {
1787
+ return (testString2, stats) => {
1788
+ return matchPatterns(patterns, testString2, stats);
1789
+ };
1790
+ }
1791
+ return matchPatterns(patterns, testString);
1792
+ }
1793
+ var unifyPaths = (paths_) => {
1794
+ const paths = arrify(paths_).flat();
1795
+ if (!paths.every((p) => typeof p === STRING_TYPE)) {
1796
+ throw new TypeError(`Non-string provided as watch path: ${paths}`);
1797
+ }
1798
+ return paths.map(normalizePathToUnix);
1799
+ };
1800
+ var toUnix = (string) => {
1801
+ let str = string.replace(BACK_SLASH_RE, SLASH);
1802
+ let prepend = false;
1803
+ if (str.startsWith(SLASH_SLASH)) {
1804
+ prepend = true;
1805
+ }
1806
+ while (str.match(DOUBLE_SLASH_RE)) {
1807
+ str = str.replace(DOUBLE_SLASH_RE, SLASH);
1808
+ }
1809
+ if (prepend) {
1810
+ str = SLASH + str;
1811
+ }
1812
+ return str;
1813
+ };
1814
+ var normalizePathToUnix = (path) => toUnix(sysPath2.normalize(toUnix(path)));
1815
+ var normalizeIgnored = (cwd = "") => (path) => {
1816
+ if (typeof path === "string") {
1817
+ return normalizePathToUnix(sysPath2.isAbsolute(path) ? path : sysPath2.join(cwd, path));
1818
+ } else {
1819
+ return path;
1820
+ }
1821
+ };
1822
+ var getAbsolutePath = (path, cwd) => {
1823
+ if (sysPath2.isAbsolute(path)) {
1824
+ return path;
1825
+ }
1826
+ return sysPath2.join(cwd, path);
1827
+ };
1828
+ var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
1829
+ var DirEntry = class {
1830
+ constructor(dir, removeWatcher) {
1831
+ this.path = dir;
1832
+ this._removeWatcher = removeWatcher;
1833
+ this.items = /* @__PURE__ */ new Set();
1834
+ }
1835
+ add(item) {
1836
+ const { items } = this;
1837
+ if (!items)
1838
+ return;
1839
+ if (item !== ONE_DOT && item !== TWO_DOTS)
1840
+ items.add(item);
1841
+ }
1842
+ async remove(item) {
1843
+ const { items } = this;
1844
+ if (!items)
1845
+ return;
1846
+ items.delete(item);
1847
+ if (items.size > 0)
1848
+ return;
1849
+ const dir = this.path;
1850
+ try {
1851
+ await readdir3(dir);
1852
+ } catch (err) {
1853
+ if (this._removeWatcher) {
1854
+ this._removeWatcher(sysPath2.dirname(dir), sysPath2.basename(dir));
1855
+ }
1856
+ }
1857
+ }
1858
+ has(item) {
1859
+ const { items } = this;
1860
+ if (!items)
1861
+ return;
1862
+ return items.has(item);
1863
+ }
1864
+ getChildren() {
1865
+ const { items } = this;
1866
+ if (!items)
1867
+ return [];
1868
+ return [...items.values()];
1869
+ }
1870
+ dispose() {
1871
+ this.items.clear();
1872
+ this.path = "";
1873
+ this._removeWatcher = EMPTY_FN;
1874
+ this.items = EMPTY_SET;
1875
+ Object.freeze(this);
1876
+ }
1877
+ };
1878
+ var STAT_METHOD_F = "stat";
1879
+ var STAT_METHOD_L = "lstat";
1880
+ var WatchHelper = class {
1881
+ constructor(path, follow, fsw) {
1882
+ this.fsw = fsw;
1883
+ const watchPath = path;
1884
+ this.path = path = path.replace(REPLACER_RE, "");
1885
+ this.watchPath = watchPath;
1886
+ this.fullWatchPath = sysPath2.resolve(watchPath);
1887
+ this.dirParts = [];
1888
+ this.dirParts.forEach((parts) => {
1889
+ if (parts.length > 1)
1890
+ parts.pop();
1891
+ });
1892
+ this.followSymlinks = follow;
1893
+ this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
1894
+ }
1895
+ entryPath(entry) {
1896
+ return sysPath2.join(this.watchPath, sysPath2.relative(this.watchPath, entry.fullPath));
1897
+ }
1898
+ filterPath(entry) {
1899
+ const { stats } = entry;
1900
+ if (stats && stats.isSymbolicLink())
1901
+ return this.filterDir(entry);
1902
+ const resolvedPath = this.entryPath(entry);
1903
+ return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
1904
+ }
1905
+ filterDir(entry) {
1906
+ return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
1907
+ }
1908
+ };
1909
+ var FSWatcher = class extends EventEmitter {
1910
+ // Not indenting methods for history sake; for now.
1911
+ constructor(_opts = {}) {
1912
+ super();
1913
+ this.closed = false;
1914
+ this._closers = /* @__PURE__ */ new Map();
1915
+ this._ignoredPaths = /* @__PURE__ */ new Set();
1916
+ this._throttled = /* @__PURE__ */ new Map();
1917
+ this._streams = /* @__PURE__ */ new Set();
1918
+ this._symlinkPaths = /* @__PURE__ */ new Map();
1919
+ this._watched = /* @__PURE__ */ new Map();
1920
+ this._pendingWrites = /* @__PURE__ */ new Map();
1921
+ this._pendingUnlinks = /* @__PURE__ */ new Map();
1922
+ this._readyCount = 0;
1923
+ this._readyEmitted = false;
1924
+ const awf = _opts.awaitWriteFinish;
1925
+ const DEF_AWF = { stabilityThreshold: 2e3, pollInterval: 100 };
1926
+ const opts = {
1927
+ // Defaults
1928
+ persistent: true,
1929
+ ignoreInitial: false,
1930
+ ignorePermissionErrors: false,
1931
+ interval: 100,
1932
+ binaryInterval: 300,
1933
+ followSymlinks: true,
1934
+ usePolling: false,
1935
+ // useAsync: false,
1936
+ atomic: true,
1937
+ // NOTE: overwritten later (depends on usePolling)
1938
+ ..._opts,
1939
+ // Change format
1940
+ ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
1941
+ awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === "object" ? { ...DEF_AWF, ...awf } : false
1942
+ };
1943
+ if (isIBMi)
1944
+ opts.usePolling = true;
1945
+ if (opts.atomic === void 0)
1946
+ opts.atomic = !opts.usePolling;
1947
+ const envPoll = process.env.CHOKIDAR_USEPOLLING;
1948
+ if (envPoll !== void 0) {
1949
+ const envLower = envPoll.toLowerCase();
1950
+ if (envLower === "false" || envLower === "0")
1951
+ opts.usePolling = false;
1952
+ else if (envLower === "true" || envLower === "1")
1953
+ opts.usePolling = true;
1954
+ else
1955
+ opts.usePolling = !!envLower;
1956
+ }
1957
+ const envInterval = process.env.CHOKIDAR_INTERVAL;
1958
+ if (envInterval)
1959
+ opts.interval = Number.parseInt(envInterval, 10);
1960
+ let readyCalls = 0;
1961
+ this._emitReady = () => {
1962
+ readyCalls++;
1963
+ if (readyCalls >= this._readyCount) {
1964
+ this._emitReady = EMPTY_FN;
1965
+ this._readyEmitted = true;
1966
+ process.nextTick(() => this.emit(EVENTS.READY));
1967
+ }
1968
+ };
1969
+ this._emitRaw = (...args) => this.emit(EVENTS.RAW, ...args);
1970
+ this._boundRemove = this._remove.bind(this);
1971
+ this.options = opts;
1972
+ this._nodeFsHandler = new NodeFsHandler(this);
1973
+ Object.freeze(opts);
1974
+ }
1975
+ _addIgnoredPath(matcher) {
1976
+ if (isMatcherObject(matcher)) {
1977
+ for (const ignored of this._ignoredPaths) {
1978
+ if (isMatcherObject(ignored) && ignored.path === matcher.path && ignored.recursive === matcher.recursive) {
1979
+ return;
1980
+ }
1981
+ }
1982
+ }
1983
+ this._ignoredPaths.add(matcher);
1984
+ }
1985
+ _removeIgnoredPath(matcher) {
1986
+ this._ignoredPaths.delete(matcher);
1987
+ if (typeof matcher === "string") {
1988
+ for (const ignored of this._ignoredPaths) {
1989
+ if (isMatcherObject(ignored) && ignored.path === matcher) {
1990
+ this._ignoredPaths.delete(ignored);
1991
+ }
1992
+ }
1993
+ }
1994
+ }
1995
+ // Public methods
1996
+ /**
1997
+ * Adds paths to be watched on an existing FSWatcher instance.
1998
+ * @param paths_ file or file list. Other arguments are unused
1999
+ */
2000
+ add(paths_, _origAdd, _internal) {
2001
+ const { cwd } = this.options;
2002
+ this.closed = false;
2003
+ this._closePromise = void 0;
2004
+ let paths = unifyPaths(paths_);
2005
+ if (cwd) {
2006
+ paths = paths.map((path) => {
2007
+ const absPath = getAbsolutePath(path, cwd);
2008
+ return absPath;
2009
+ });
2010
+ }
2011
+ paths.forEach((path) => {
2012
+ this._removeIgnoredPath(path);
2013
+ });
2014
+ this._userIgnored = void 0;
2015
+ if (!this._readyCount)
2016
+ this._readyCount = 0;
2017
+ this._readyCount += paths.length;
2018
+ Promise.all(paths.map(async (path) => {
2019
+ const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, void 0, 0, _origAdd);
2020
+ if (res)
2021
+ this._emitReady();
2022
+ return res;
2023
+ })).then((results) => {
2024
+ if (this.closed)
2025
+ return;
2026
+ results.forEach((item) => {
2027
+ if (item)
2028
+ this.add(sysPath2.dirname(item), sysPath2.basename(_origAdd || item));
2029
+ });
2030
+ });
2031
+ return this;
2032
+ }
2033
+ /**
2034
+ * Close watchers or start ignoring events from specified paths.
2035
+ */
2036
+ unwatch(paths_) {
2037
+ if (this.closed)
2038
+ return this;
2039
+ const paths = unifyPaths(paths_);
2040
+ const { cwd } = this.options;
2041
+ paths.forEach((path) => {
2042
+ if (!sysPath2.isAbsolute(path) && !this._closers.has(path)) {
2043
+ if (cwd)
2044
+ path = sysPath2.join(cwd, path);
2045
+ path = sysPath2.resolve(path);
2046
+ }
2047
+ this._closePath(path);
2048
+ this._addIgnoredPath(path);
2049
+ if (this._watched.has(path)) {
2050
+ this._addIgnoredPath({
2051
+ path,
2052
+ recursive: true
2053
+ });
2054
+ }
2055
+ this._userIgnored = void 0;
2056
+ });
2057
+ return this;
2058
+ }
2059
+ /**
2060
+ * Close watchers and remove all listeners from watched paths.
2061
+ */
2062
+ close() {
2063
+ if (this._closePromise) {
2064
+ return this._closePromise;
2065
+ }
2066
+ this.closed = true;
2067
+ this.removeAllListeners();
2068
+ const closers = [];
2069
+ this._closers.forEach((closerList) => closerList.forEach((closer) => {
2070
+ const promise = closer();
2071
+ if (promise instanceof Promise)
2072
+ closers.push(promise);
2073
+ }));
2074
+ this._streams.forEach((stream) => stream.destroy());
2075
+ this._userIgnored = void 0;
2076
+ this._readyCount = 0;
2077
+ this._readyEmitted = false;
2078
+ this._watched.forEach((dirent) => dirent.dispose());
2079
+ this._closers.clear();
2080
+ this._watched.clear();
2081
+ this._streams.clear();
2082
+ this._symlinkPaths.clear();
2083
+ this._throttled.clear();
2084
+ this._closePromise = closers.length ? Promise.all(closers).then(() => void 0) : Promise.resolve();
2085
+ return this._closePromise;
2086
+ }
2087
+ /**
2088
+ * Expose list of watched paths
2089
+ * @returns for chaining
2090
+ */
2091
+ getWatched() {
2092
+ const watchList = {};
2093
+ this._watched.forEach((entry, dir) => {
2094
+ const key = this.options.cwd ? sysPath2.relative(this.options.cwd, dir) : dir;
2095
+ const index = key || ONE_DOT;
2096
+ watchList[index] = entry.getChildren().sort();
2097
+ });
2098
+ return watchList;
2099
+ }
2100
+ emitWithAll(event, args) {
2101
+ this.emit(event, ...args);
2102
+ if (event !== EVENTS.ERROR)
2103
+ this.emit(EVENTS.ALL, event, ...args);
2104
+ }
2105
+ // Common helpers
2106
+ // --------------
2107
+ /**
2108
+ * Normalize and emit events.
2109
+ * Calling _emit DOES NOT MEAN emit() would be called!
2110
+ * @param event Type of event
2111
+ * @param path File or directory path
2112
+ * @param stats arguments to be passed with event
2113
+ * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
2114
+ */
2115
+ async _emit(event, path, stats) {
2116
+ if (this.closed)
2117
+ return;
2118
+ const opts = this.options;
2119
+ if (isWindows)
2120
+ path = sysPath2.normalize(path);
2121
+ if (opts.cwd)
2122
+ path = sysPath2.relative(opts.cwd, path);
2123
+ const args = [path];
2124
+ if (stats != null)
2125
+ args.push(stats);
2126
+ const awf = opts.awaitWriteFinish;
2127
+ let pw;
2128
+ if (awf && (pw = this._pendingWrites.get(path))) {
2129
+ pw.lastChange = /* @__PURE__ */ new Date();
2130
+ return this;
2131
+ }
2132
+ if (opts.atomic) {
2133
+ if (event === EVENTS.UNLINK) {
2134
+ this._pendingUnlinks.set(path, [event, ...args]);
2135
+ setTimeout(() => {
2136
+ this._pendingUnlinks.forEach((entry, path2) => {
2137
+ this.emit(...entry);
2138
+ this.emit(EVENTS.ALL, ...entry);
2139
+ this._pendingUnlinks.delete(path2);
2140
+ });
2141
+ }, typeof opts.atomic === "number" ? opts.atomic : 100);
2142
+ return this;
2143
+ }
2144
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path)) {
2145
+ event = EVENTS.CHANGE;
2146
+ this._pendingUnlinks.delete(path);
2147
+ }
2148
+ }
2149
+ if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
2150
+ const awfEmit = (err, stats2) => {
2151
+ if (err) {
2152
+ event = EVENTS.ERROR;
2153
+ args[0] = err;
2154
+ this.emitWithAll(event, args);
2155
+ } else if (stats2) {
2156
+ if (args.length > 1) {
2157
+ args[1] = stats2;
2158
+ } else {
2159
+ args.push(stats2);
2160
+ }
2161
+ this.emitWithAll(event, args);
2162
+ }
2163
+ };
2164
+ this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
2165
+ return this;
2166
+ }
2167
+ if (event === EVENTS.CHANGE) {
2168
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path, 50);
2169
+ if (isThrottled)
2170
+ return this;
2171
+ }
2172
+ if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
2173
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path) : path;
2174
+ let stats2;
2175
+ try {
2176
+ stats2 = await stat5(fullPath);
2177
+ } catch (err) {
2178
+ }
2179
+ if (!stats2 || this.closed)
2180
+ return;
2181
+ args.push(stats2);
2182
+ }
2183
+ this.emitWithAll(event, args);
2184
+ return this;
2185
+ }
2186
+ /**
2187
+ * Common handler for errors
2188
+ * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
2189
+ */
2190
+ _handleError(error) {
2191
+ const code = error && error.code;
2192
+ if (error && code !== "ENOENT" && code !== "ENOTDIR" && (!this.options.ignorePermissionErrors || code !== "EPERM" && code !== "EACCES")) {
2193
+ this.emit(EVENTS.ERROR, error);
2194
+ }
2195
+ return error || this.closed;
2196
+ }
2197
+ /**
2198
+ * Helper utility for throttling
2199
+ * @param actionType type being throttled
2200
+ * @param path being acted upon
2201
+ * @param timeout duration of time to suppress duplicate actions
2202
+ * @returns tracking object or false if action should be suppressed
2203
+ */
2204
+ _throttle(actionType, path, timeout) {
2205
+ if (!this._throttled.has(actionType)) {
2206
+ this._throttled.set(actionType, /* @__PURE__ */ new Map());
2207
+ }
2208
+ const action = this._throttled.get(actionType);
2209
+ if (!action)
2210
+ throw new Error("invalid throttle");
2211
+ const actionPath = action.get(path);
2212
+ if (actionPath) {
2213
+ actionPath.count++;
2214
+ return false;
2215
+ }
2216
+ let timeoutObject;
2217
+ const clear = () => {
2218
+ const item = action.get(path);
2219
+ const count = item ? item.count : 0;
2220
+ action.delete(path);
2221
+ clearTimeout(timeoutObject);
2222
+ if (item)
2223
+ clearTimeout(item.timeoutObject);
2224
+ return count;
2225
+ };
2226
+ timeoutObject = setTimeout(clear, timeout);
2227
+ const thr = { timeoutObject, clear, count: 0 };
2228
+ action.set(path, thr);
2229
+ return thr;
2230
+ }
2231
+ _incrReadyCount() {
2232
+ return this._readyCount++;
2233
+ }
2234
+ /**
2235
+ * Awaits write operation to finish.
2236
+ * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
2237
+ * @param path being acted upon
2238
+ * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
2239
+ * @param event
2240
+ * @param awfEmit Callback to be called when ready for event to be emitted.
2241
+ */
2242
+ _awaitWriteFinish(path, threshold, event, awfEmit) {
2243
+ const awf = this.options.awaitWriteFinish;
2244
+ if (typeof awf !== "object")
2245
+ return;
2246
+ const pollInterval = awf.pollInterval;
2247
+ let timeoutHandler;
2248
+ let fullPath = path;
2249
+ if (this.options.cwd && !sysPath2.isAbsolute(path)) {
2250
+ fullPath = sysPath2.join(this.options.cwd, path);
2251
+ }
2252
+ const now = /* @__PURE__ */ new Date();
2253
+ const writes = this._pendingWrites;
2254
+ function awaitWriteFinishFn(prevStat) {
2255
+ statcb(fullPath, (err, curStat) => {
2256
+ if (err || !writes.has(path)) {
2257
+ if (err && err.code !== "ENOENT")
2258
+ awfEmit(err);
2259
+ return;
2260
+ }
2261
+ const now2 = Number(/* @__PURE__ */ new Date());
2262
+ if (prevStat && curStat.size !== prevStat.size) {
2263
+ writes.get(path).lastChange = now2;
2264
+ }
2265
+ const pw = writes.get(path);
2266
+ const df = now2 - pw.lastChange;
2267
+ if (df >= threshold) {
2268
+ writes.delete(path);
2269
+ awfEmit(void 0, curStat);
2270
+ } else {
2271
+ timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
2272
+ }
2273
+ });
2274
+ }
2275
+ if (!writes.has(path)) {
2276
+ writes.set(path, {
2277
+ lastChange: now,
2278
+ cancelWait: () => {
2279
+ writes.delete(path);
2280
+ clearTimeout(timeoutHandler);
2281
+ return event;
2282
+ }
2283
+ });
2284
+ timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
2285
+ }
2286
+ }
2287
+ /**
2288
+ * Determines whether user has asked to ignore this path.
2289
+ */
2290
+ _isIgnored(path, stats) {
2291
+ if (this.options.atomic && DOT_RE.test(path))
2292
+ return true;
2293
+ if (!this._userIgnored) {
2294
+ const { cwd } = this.options;
2295
+ const ign = this.options.ignored;
2296
+ const ignored = (ign || []).map(normalizeIgnored(cwd));
2297
+ const ignoredPaths = [...this._ignoredPaths];
2298
+ const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
2299
+ this._userIgnored = anymatch(list, void 0);
2300
+ }
2301
+ return this._userIgnored(path, stats);
2302
+ }
2303
+ _isntIgnored(path, stat7) {
2304
+ return !this._isIgnored(path, stat7);
2305
+ }
2306
+ /**
2307
+ * Provides a set of common helpers and properties relating to symlink handling.
2308
+ * @param path file or directory pattern being watched
2309
+ */
2310
+ _getWatchHelpers(path) {
2311
+ return new WatchHelper(path, this.options.followSymlinks, this);
2312
+ }
2313
+ // Directory helpers
2314
+ // -----------------
2315
+ /**
2316
+ * Provides directory tracking objects
2317
+ * @param directory path of the directory
2318
+ */
2319
+ _getWatchedDir(directory) {
2320
+ const dir = sysPath2.resolve(directory);
2321
+ if (!this._watched.has(dir))
2322
+ this._watched.set(dir, new DirEntry(dir, this._boundRemove));
2323
+ return this._watched.get(dir);
2324
+ }
2325
+ // File helpers
2326
+ // ------------
2327
+ /**
2328
+ * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
2329
+ */
2330
+ _hasReadPermissions(stats) {
2331
+ if (this.options.ignorePermissionErrors)
2332
+ return true;
2333
+ return Boolean(Number(stats.mode) & 256);
2334
+ }
2335
+ /**
2336
+ * Handles emitting unlink events for
2337
+ * files and directories, and via recursion, for
2338
+ * files and directories within directories that are unlinked
2339
+ * @param directory within which the following item is located
2340
+ * @param item base path of item/directory
2341
+ */
2342
+ _remove(directory, item, isDirectory) {
2343
+ const path = sysPath2.join(directory, item);
2344
+ const fullPath = sysPath2.resolve(path);
2345
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
2346
+ if (!this._throttle("remove", path, 100))
2347
+ return;
2348
+ if (!isDirectory && this._watched.size === 1) {
2349
+ this.add(directory, item, true);
2350
+ }
2351
+ const wp = this._getWatchedDir(path);
2352
+ const nestedDirectoryChildren = wp.getChildren();
2353
+ nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));
2354
+ const parent = this._getWatchedDir(directory);
2355
+ const wasTracked = parent.has(item);
2356
+ parent.remove(item);
2357
+ if (this._symlinkPaths.has(fullPath)) {
2358
+ this._symlinkPaths.delete(fullPath);
2359
+ }
2360
+ let relPath = path;
2361
+ if (this.options.cwd)
2362
+ relPath = sysPath2.relative(this.options.cwd, path);
2363
+ if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
2364
+ const event = this._pendingWrites.get(relPath).cancelWait();
2365
+ if (event === EVENTS.ADD)
2366
+ return;
2367
+ }
2368
+ this._watched.delete(path);
2369
+ this._watched.delete(fullPath);
2370
+ const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
2371
+ if (wasTracked && !this._isIgnored(path))
2372
+ this._emit(eventName, path);
2373
+ this._closePath(path);
2374
+ }
2375
+ /**
2376
+ * Closes all watchers for a path
2377
+ */
2378
+ _closePath(path) {
2379
+ this._closeFile(path);
2380
+ const dir = sysPath2.dirname(path);
2381
+ this._getWatchedDir(dir).remove(sysPath2.basename(path));
2382
+ }
2383
+ /**
2384
+ * Closes only file-specific watchers
2385
+ */
2386
+ _closeFile(path) {
2387
+ const closers = this._closers.get(path);
2388
+ if (!closers)
2389
+ return;
2390
+ closers.forEach((closer) => closer());
2391
+ this._closers.delete(path);
2392
+ }
2393
+ _addPathCloser(path, closer) {
2394
+ if (!closer)
2395
+ return;
2396
+ let list = this._closers.get(path);
2397
+ if (!list) {
2398
+ list = [];
2399
+ this._closers.set(path, list);
2400
+ }
2401
+ list.push(closer);
2402
+ }
2403
+ _readdirp(root, opts) {
2404
+ if (this.closed)
2405
+ return;
2406
+ const options = { type: EVENTS.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };
2407
+ let stream = readdirp(root, options);
2408
+ this._streams.add(stream);
2409
+ stream.once(STR_CLOSE, () => {
2410
+ stream = void 0;
2411
+ });
2412
+ stream.once(STR_END, () => {
2413
+ if (stream) {
2414
+ this._streams.delete(stream);
2415
+ stream = void 0;
2416
+ }
2417
+ });
2418
+ return stream;
2419
+ }
2420
+ };
2421
+ function watch(paths, options = {}) {
2422
+ const watcher = new FSWatcher(options);
2423
+ watcher.add(paths);
2424
+ return watcher;
2425
+ }
2426
+
2427
+ // src/dev/dev-watcher.ts
2428
+ import { stat as stat6 } from "node:fs/promises";
2429
+ import { relative as relative3, sep as sep2 } from "node:path";
2430
+ var defaultPollIntervalMs = 1e3;
2431
+ function createDevWatcher(input) {
2432
+ const ignorePrefixes = (input.ignore ?? []).map(normalizePrefix).filter(Boolean);
2433
+ const ignored = (path) => shouldIgnoreWatchPath(relative3(input.root, path), ignorePrefixes);
2434
+ const watcher = watch(input.root, {
2435
+ ignoreInitial: true,
2436
+ ignored,
2437
+ atomic: true
2438
+ });
2439
+ watcher.on("all", (_event, path) => {
2440
+ if (!ignored(path)) input.onChange(path);
2441
+ });
2442
+ let readySettled = false;
2443
+ const ready = new Promise((resolve8, reject) => {
2444
+ watcher.once("ready", () => {
2445
+ readySettled = true;
2446
+ resolve8();
2447
+ });
2448
+ watcher.on("error", (error) => {
2449
+ if (readySettled) return;
2450
+ readySettled = true;
2451
+ reject(error instanceof Error ? error : new Error(String(error)));
2452
+ });
2453
+ });
2454
+ let tracked = /* @__PURE__ */ new Map();
2455
+ let trackGeneration = 0;
2456
+ let polling = false;
2457
+ const poll = async () => {
2458
+ if (polling) return;
2459
+ polling = true;
2460
+ const map = tracked;
2461
+ const generation = trackGeneration;
2462
+ try {
2463
+ for (const [path, previous] of [...map]) {
2464
+ if (tracked !== map || generation !== trackGeneration) return;
2465
+ const next = await fingerprint(path);
2466
+ if (tracked !== map || generation !== trackGeneration) return;
2467
+ if (!map.has(path)) continue;
2468
+ if (previous !== null && next !== previous) {
2469
+ if (tracked !== map || generation !== trackGeneration) return;
2470
+ if (input.onChange(path) === false) continue;
2471
+ if (tracked !== map || generation !== trackGeneration) return;
2472
+ map.set(path, next);
2473
+ } else if (previous === null) {
2474
+ map.set(path, next);
2475
+ }
2476
+ }
2477
+ } finally {
2478
+ polling = false;
2479
+ }
2480
+ };
2481
+ const timer = setInterval(() => void poll(), input.pollIntervalMs ?? defaultPollIntervalMs);
2482
+ timer.unref();
2483
+ return {
2484
+ ready,
2485
+ rebaseline: async () => {
2486
+ const generation = ++trackGeneration;
2487
+ const previousTracked = tracked;
2488
+ tracked = /* @__PURE__ */ new Map();
2489
+ const next = /* @__PURE__ */ new Map();
2490
+ for (const path of previousTracked.keys()) {
2491
+ next.set(path, await fingerprint(path));
2492
+ if (generation !== trackGeneration) return;
2493
+ }
2494
+ if (generation !== trackGeneration) return;
2495
+ tracked = next;
2496
+ trackGeneration++;
2497
+ },
2498
+ track: async (paths, options) => {
2499
+ const ignoreChanges = new Set(options?.ignoreChanges ?? []);
2500
+ const generation = ++trackGeneration;
2501
+ const previousTracked = tracked;
2502
+ tracked = /* @__PURE__ */ new Map();
2503
+ const changedDuringBuild = [];
2504
+ const next = /* @__PURE__ */ new Map();
2505
+ for (const path of paths) {
2506
+ if (ignored(path)) continue;
2507
+ const current = await fingerprint(path);
2508
+ if (generation !== trackGeneration) return [];
2509
+ const previous = previousTracked.get(path);
2510
+ if (previous !== void 0 && previous !== null && current !== previous && !ignoreChanges.has(path)) {
2511
+ changedDuringBuild.push(path);
2512
+ }
2513
+ next.set(path, current);
2514
+ }
2515
+ if (generation !== trackGeneration) return [];
2516
+ tracked = next;
2517
+ trackGeneration++;
2518
+ return changedDuringBuild;
2519
+ },
2520
+ close: async () => {
2521
+ clearInterval(timer);
2522
+ trackGeneration++;
2523
+ tracked = /* @__PURE__ */ new Map();
2524
+ await watcher.close();
2525
+ }
2526
+ };
2527
+ }
2528
+ async function fingerprint(path) {
2529
+ try {
2530
+ const info = await stat6(path);
2531
+ return `${info.ino}:${info.size}:${info.mtimeMs}`;
2532
+ } catch {
2533
+ return "missing";
2534
+ }
2535
+ }
2536
+ function normalizePrefix(prefix) {
2537
+ return prefix.replace(/^\.\//, "").replace(/\/+$/, "").split("/").join(sep2);
2538
+ }
2539
+ function shouldIgnoreWatchPath(relativePath, ignorePrefixes = []) {
2540
+ if (!relativePath || relativePath === ".") return false;
2541
+ if (relativePath.startsWith("..")) return true;
2542
+ const segments = relativePath.split(sep2);
2543
+ if (segments.some((segment) => segment === "node_modules" || segment.startsWith("."))) {
2544
+ return true;
2545
+ }
2546
+ if (relativePath.endsWith(".map")) return true;
2547
+ return ignorePrefixes.some(
2548
+ (prefix) => relativePath === prefix || relativePath.startsWith(`${prefix}${sep2}`)
2549
+ );
2550
+ }
2551
+
2552
+ // src/dev/error-page.ts
2553
+ function wantsHtml(req) {
2554
+ const accept = req.headers.accept ?? "";
2555
+ return /\btext\/html\b/.test(accept);
2556
+ }
2557
+ function sendDevError(req, res, status, view, options = {}) {
2558
+ if (res.headersSent) {
2559
+ res.end();
2560
+ return;
2561
+ }
2562
+ const headers = {
2563
+ "cache-control": "no-store",
2564
+ "x-kody-dev-error": view.kind
2565
+ };
2566
+ if (wantsHtml(req)) {
2567
+ res.writeHead(status, { ...headers, "content-type": "text/html; charset=utf-8" });
2568
+ res.end(renderDevErrorPage(view) + (options.htmlTail ?? ""));
2569
+ return;
2570
+ }
2571
+ res.writeHead(status, { ...headers, "content-type": "text/plain; charset=utf-8" });
2572
+ res.end(`kody dev ${view.kind} error${view.request ? ` (${view.request})` : ""}
2573
+
2574
+ ${view.detail}
2575
+ `);
2576
+ }
2577
+ function renderDevErrorPage(view) {
2578
+ const label = view.kind === "build" ? "Build error" : "Runtime error";
2579
+ return `<!doctype html>
2580
+ <html lang="en">
2581
+ <head>
2582
+ <meta charset="utf-8">
2583
+ <meta name="viewport" content="width=device-width, initial-scale=1">
2584
+ <title>${escapeHtml(label)} \xB7 kody dev</title>
2585
+ <style>
2586
+ :root { color-scheme: dark; }
2587
+ body { margin: 0; font: 14px/1.5 ui-sans-serif, system-ui, sans-serif; background: #1a1015; color: #f5e9ee; }
2588
+ main { max-width: 960px; margin: 0 auto; padding: 32px 24px; }
2589
+ .label { display: inline-block; font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: #ff8fab; }
2590
+ h1 { font-size: 20px; margin: 8px 0 20px; word-break: break-word; }
2591
+ pre { margin: 0; padding: 16px; overflow: auto; background: #0e080b; border: 1px solid #3a2530; border-radius: 8px; font: 13px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre; }
2592
+ p { color: #bfa9b3; font-size: 13px; }
2593
+ </style>
2594
+ </head>
2595
+ <body>
2596
+ <main>
2597
+ <span class="label">${escapeHtml(label)}</span>
2598
+ <h1>${escapeHtml(view.title)}</h1>${view.request ? `
2599
+ <p>${escapeHtml(view.request)}</p>` : ""}
2600
+ <pre>${escapeHtml(view.detail)}</pre>
2601
+ <p>Served by <code>kody dev</code> only; published apps never see this page.</p>
2602
+ </main>
2603
+ </body>
2604
+ </html>
2605
+ `;
2606
+ }
2607
+ function escapeHtml(value) {
2608
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
2609
+ }
2610
+
2611
+ // src/dev/live-reload.ts
2612
+ var liveReloadEventsPath = "/__kody/dev/events";
2613
+ var liveReloadClientPath = "/__kody/dev/client.js";
2614
+ var liveReloadScriptTag = `<script type="module" src="${liveReloadClientPath}"></script>`;
2615
+ var keepAliveMs = 15e3;
2616
+ function createLiveReloadHub(input) {
2617
+ const clients = /* @__PURE__ */ new Set();
2618
+ const send2 = (res, event, data) => {
2619
+ res.write(`event: ${event}
2620
+ data: ${JSON.stringify(data)}
2621
+
2622
+ `);
2623
+ };
2624
+ const keepAlive = setInterval(() => {
2625
+ for (const res of clients) res.write(": keep-alive\n\n");
2626
+ }, keepAliveMs);
2627
+ keepAlive.unref();
2628
+ return {
2629
+ handleEvents: (req, res) => {
2630
+ res.writeHead(200, {
2631
+ "content-type": "text/event-stream; charset=utf-8",
2632
+ "cache-control": "no-store",
2633
+ connection: "keep-alive"
2634
+ });
2635
+ res.write("retry: 500\n\n");
2636
+ send2(res, "hello", input.state());
2637
+ clients.add(res);
2638
+ req.on("close", () => clients.delete(res));
2639
+ },
2640
+ broadcast: (message) => {
2641
+ for (const res of clients) send2(res, message.event, message.data);
2642
+ },
2643
+ clientCount: () => clients.size,
2644
+ close: () => {
2645
+ clearInterval(keepAlive);
2646
+ for (const res of clients) res.end();
2647
+ clients.clear();
2648
+ }
2649
+ };
2650
+ }
2651
+ function injectLiveReloadScript(html) {
2652
+ if (html.includes(liveReloadClientPath)) return html;
2653
+ for (const pattern of [/<\/head\s*>/i, /<\/body\s*>/i]) {
2654
+ const match = pattern.exec(html);
2655
+ if (match) {
2656
+ return `${html.slice(0, match.index)}${liveReloadScriptTag}${html.slice(match.index)}`;
2657
+ }
2658
+ }
2659
+ return `${html}${liveReloadScriptTag}`;
2660
+ }
2661
+ function shouldInjectLiveReload(input) {
2662
+ if (input.method === "HEAD") return false;
2663
+ if (!/\btext\/html\b/i.test(input.accept ?? "")) return false;
2664
+ if (input.status === 204 || input.status === 304 || input.status < 200) return false;
2665
+ const contentType = String(input.headers["content-type"] ?? "");
2666
+ if (!/^\s*text\/html\b/i.test(contentType)) return false;
2667
+ const encoding = String(input.headers["content-encoding"] ?? "identity").trim().toLowerCase();
2668
+ return encoding === "" || encoding === "identity";
2669
+ }
2670
+ var liveReloadClientSource = `
2671
+ const eventsUrl = ${JSON.stringify(liveReloadEventsPath)};
2672
+ let buildId = null;
2673
+ let overlay = null;
2674
+
2675
+ function hideOverlay() {
2676
+ overlay?.remove();
2677
+ overlay = null;
2678
+ }
2679
+
2680
+ function showOverlay(view) {
2681
+ if (globalThis.__kodyDevErrorPage) return;
2682
+ hideOverlay();
2683
+ const host = document.createElement('kody-dev-overlay');
2684
+ const root = host.attachShadow({ mode: 'open' });
2685
+ const label = view.kind === 'build' ? 'Build error' : 'Runtime error';
2686
+ // Keep CSS out of the text tree (page-text readers / textContent walkers).
2687
+ const sheet = new CSSStyleSheet();
2688
+ sheet.replaceSync(\`
2689
+ .backdrop { position: fixed; inset: 0; z-index: 2147483647; background: rgba(10, 4, 7, .82); display: flex; align-items: flex-start; justify-content: center; overflow: auto; font: 14px/1.5 ui-sans-serif, system-ui, sans-serif; }
2690
+ .panel { margin: 48px 16px; max-width: 960px; width: 100%; background: #1a1015; color: #f5e9ee; border: 1px solid #3a2530; border-radius: 10px; padding: 20px 24px; box-shadow: 0 20px 60px rgba(0,0,0,.5); }
2691
+ .top { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
2692
+ .label { font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: #ff8fab; }
2693
+ button { all: unset; cursor: pointer; color: #bfa9b3; font-size: 20px; line-height: 1; padding: 4px 8px; border-radius: 6px; }
2694
+ button:hover, button:focus-visible { background: #2a1a22; color: #fff; }
2695
+ h1 { font-size: 18px; margin: 8px 0 4px; word-break: break-word; }
2696
+ .request { color: #bfa9b3; font-size: 13px; margin: 0 0 12px; }
2697
+ pre { margin: 12px 0 0; padding: 14px; overflow: auto; background: #0e080b; border: 1px solid #3a2530; border-radius: 8px; font: 13px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre; }
2698
+ .hint { color: #bfa9b3; font-size: 12px; margin-top: 12px; }
2699
+ \`);
2700
+ root.adoptedStyleSheets = [sheet];
2701
+ root.innerHTML = \`
2702
+ <div class="backdrop" role="alertdialog" aria-modal="true" aria-labelledby="kody-dev-title">
2703
+ <div class="panel">
2704
+ <div class="top"><span class="label"></span><button type="button" aria-label="Dismiss">\xD7</button></div>
2705
+ <h1 id="kody-dev-title"></h1>
2706
+ <p class="request"></p>
2707
+ <pre></pre>
2708
+ <p class="hint">Fix it and save. The page reloads on the next good build. Esc dismisses.</p>
2709
+ </div>
2710
+ </div>\`;
2711
+ root.querySelector('.label').textContent = label;
2712
+ root.querySelector('h1').textContent = view.title;
2713
+ const request = root.querySelector('.request');
2714
+ if (view.request) request.textContent = view.request;
2715
+ else request.remove();
2716
+ root.querySelector('pre').textContent = view.detail;
2717
+ root.querySelector('button').addEventListener('click', hideOverlay);
2718
+ document.documentElement.appendChild(host);
2719
+ overlay = host;
2720
+ root.querySelector('button').focus();
2721
+ }
2722
+
2723
+ addEventListener('keydown', (event) => {
2724
+ if (event.key === 'Escape') hideOverlay();
2725
+ });
2726
+
2727
+ function connect() {
2728
+ const source = new EventSource(eventsUrl);
2729
+ source.addEventListener('hello', (event) => {
2730
+ const state = JSON.parse(event.data);
2731
+ if (buildId !== null && state.buildId !== null && state.buildId !== buildId) {
2732
+ location.reload();
2733
+ return;
2734
+ }
2735
+ buildId = state.buildId;
2736
+ if (state.error) showOverlay(state.error);
2737
+ });
2738
+ source.addEventListener('reload', () => location.reload());
2739
+ source.addEventListener('build_error', (event) => showOverlay(JSON.parse(event.data)));
2740
+ source.addEventListener('runtime_error', (event) => showOverlay(JSON.parse(event.data)));
2741
+ }
2742
+
2743
+ connect();
2744
+ `.trimStart();
2745
+
2746
+ // src/dev/prebuild.ts
2747
+ import { spawn as spawn2 } from "node:child_process";
2748
+ var outputTailLines = 20;
2749
+ var PrebuildError = class extends Error {
2750
+ constructor(message) {
2751
+ super(message);
2752
+ this.name = "PrebuildError";
2753
+ }
2754
+ };
2755
+ async function runPrebuild(input) {
2756
+ if (input.signal?.aborted) {
2757
+ throw new PrebuildError("kody.dev.prebuild aborted before start");
2758
+ }
2759
+ const env = { ...process.env, KODY_DEV: "1" };
2760
+ delete env[apiTokenEnvVar];
2761
+ const child = spawn2("sh", ["-c", input.command], {
2762
+ cwd: input.cwd,
2763
+ env,
2764
+ stdio: ["ignore", "pipe", "pipe"],
2765
+ detached: true
2766
+ });
2767
+ if (child.pid) input.onSpawn?.(child.pid);
2768
+ const tail = [];
2769
+ const collect = (stream) => (line) => {
2770
+ tail.push(line);
2771
+ if (tail.length > outputTailLines) tail.shift();
2772
+ input.onLine?.(line, stream);
2773
+ };
2774
+ forEachLine(child.stdout, collect("stdout"));
2775
+ forEachLine(child.stderr, collect("stderr"));
2776
+ const killChild = () => {
2777
+ if (child.exitCode !== null || child.signalCode !== null) return;
2778
+ const pid = child.pid;
2779
+ if (pid === void 0) return;
2780
+ try {
2781
+ process.kill(-pid, "SIGKILL");
2782
+ } catch {
2783
+ try {
2784
+ child.kill("SIGKILL");
2785
+ } catch {
2786
+ }
2787
+ }
2788
+ };
2789
+ if (input.signal) {
2790
+ if (input.signal.aborted) killChild();
2791
+ else input.signal.addEventListener("abort", killChild, { once: true });
2792
+ }
2793
+ try {
2794
+ const result = await new Promise(
2795
+ (resolve8, reject) => {
2796
+ child.once("error", reject);
2797
+ child.once("close", (code, signal) => resolve8({ code, signal }));
2798
+ }
2799
+ );
2800
+ if (input.signal?.aborted) {
2801
+ throw new PrebuildError("kody.dev.prebuild aborted");
2802
+ }
2803
+ if (result.code === 0) return;
2804
+ const how = result.signal ? `signal ${result.signal}` : `exit ${result.code}`;
2805
+ throw new PrebuildError(
2806
+ [`kody.dev.prebuild failed (${how}): ${input.command}`, ...tail.map((line) => ` ${line}`)].join(
2807
+ "\n"
2808
+ )
2809
+ );
2810
+ } finally {
2811
+ input.signal?.removeEventListener("abort", killChild);
2812
+ if (child.pid) input.onExit?.(child.pid);
2813
+ }
2814
+ }
2815
+ function forEachLine(stream, onLine) {
2816
+ if (!stream) return;
2817
+ let buffered = "";
2818
+ stream.on("data", (chunk) => {
2819
+ buffered += typeof chunk === "string" ? chunk : chunk.toString("utf8");
2820
+ const lines = buffered.split("\n");
2821
+ buffered = lines.pop() ?? "";
2822
+ for (const line of lines) {
2823
+ if (line.length > 0) onLine(line);
2824
+ }
2825
+ });
2826
+ stream.on("end", () => {
2827
+ if (buffered.length > 0) onLine(buffered);
2828
+ buffered = "";
2829
+ });
2830
+ }
2831
+
2832
+ // node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
2833
+ var comma = ",".charCodeAt(0);
2834
+ var semicolon = ";".charCodeAt(0);
2835
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2836
+ var intToChar = new Uint8Array(64);
2837
+ var charToInt = new Uint8Array(128);
2838
+ for (let i = 0; i < chars.length; i++) {
2839
+ const c = chars.charCodeAt(i);
2840
+ intToChar[i] = c;
2841
+ charToInt[c] = i;
2842
+ }
2843
+ function decodeInteger(reader) {
2844
+ let value = 0;
2845
+ let shift = 0;
2846
+ let integer = 0;
2847
+ do {
2848
+ const c = reader.next();
2849
+ integer = charToInt[c];
2850
+ value |= (integer & 31) << shift;
2851
+ shift += 5;
2852
+ } while (integer & 32);
2853
+ return value;
2854
+ }
2855
+ function decodeSign(num) {
2856
+ return num & 1 ? -2147483648 | -(num >>> 1) : num >>> 1;
2857
+ }
2858
+ function hasMoreVlq(reader, max) {
2859
+ if (reader.pos >= max) return false;
2860
+ return reader.peek() !== comma;
2861
+ }
2862
+ var bufLength = 1024 * 16;
2863
+ var StringReader = class {
2864
+ constructor(buffer) {
2865
+ this.pos = 0;
2866
+ this.buffer = buffer;
2867
+ }
2868
+ next() {
2869
+ return this.buffer.charCodeAt(this.pos++);
2870
+ }
2871
+ peek() {
2872
+ return this.buffer.charCodeAt(this.pos);
2873
+ }
2874
+ indexOf(char) {
2875
+ const { buffer, pos } = this;
2876
+ const idx = buffer.indexOf(char, pos);
2877
+ return idx === -1 ? buffer.length : idx;
2878
+ }
2879
+ };
2880
+ function decode(mappings) {
2881
+ const { length } = mappings;
2882
+ const reader = new StringReader(mappings);
2883
+ const decoded = [];
2884
+ let genColumn = 0;
2885
+ let sourcesIndex = 0;
2886
+ let sourceLine = 0;
2887
+ let sourceColumn = 0;
2888
+ let namesIndex = 0;
2889
+ do {
2890
+ const semi = reader.indexOf(";");
2891
+ const line = [];
2892
+ let sorted = true;
2893
+ let lastCol = 0;
2894
+ genColumn = 0;
2895
+ while (reader.pos < semi) {
2896
+ let seg;
2897
+ genColumn += decodeSign(decodeInteger(reader));
2898
+ if (genColumn < lastCol) sorted = false;
2899
+ lastCol = genColumn;
2900
+ if (hasMoreVlq(reader, semi)) {
2901
+ sourcesIndex += decodeSign(decodeInteger(reader));
2902
+ sourceLine += decodeSign(decodeInteger(reader));
2903
+ sourceColumn += decodeSign(decodeInteger(reader));
2904
+ if (hasMoreVlq(reader, semi)) {
2905
+ namesIndex += decodeSign(decodeInteger(reader));
2906
+ seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
2907
+ } else {
2908
+ seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
2909
+ }
2910
+ } else {
2911
+ seg = [genColumn];
2912
+ }
2913
+ line.push(seg);
2914
+ reader.pos++;
2915
+ }
2916
+ if (!sorted) sort(line);
2917
+ decoded.push(line);
2918
+ reader.pos = semi + 1;
2919
+ } while (reader.pos <= length);
2920
+ return decoded;
2921
+ }
2922
+ function sort(line) {
2923
+ line.sort(sortComparator);
2924
+ }
2925
+ function sortComparator(a, b) {
2926
+ return a[0] - b[0];
2927
+ }
2928
+
2929
+ // node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs
2930
+ var schemeRegex = /^[\w+.-]+:\/\//;
2931
+ var urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/;
2932
+ var fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;
2933
+ function isAbsoluteUrl(input) {
2934
+ return schemeRegex.test(input);
2935
+ }
2936
+ function isSchemeRelativeUrl(input) {
2937
+ return input.startsWith("//");
2938
+ }
2939
+ function isAbsolutePath(input) {
2940
+ return input.startsWith("/");
2941
+ }
2942
+ function isFileUrl(input) {
2943
+ return input.startsWith("file:");
2944
+ }
2945
+ function isRelative(input) {
2946
+ return /^[.?#]/.test(input);
2947
+ }
2948
+ function parseAbsoluteUrl(input) {
2949
+ const match = urlRegex.exec(input);
2950
+ return makeUrl(match[1], match[2] || "", match[3], match[4] || "", match[5] || "/", match[6] || "", match[7] || "");
2951
+ }
2952
+ function parseFileUrl(input) {
2953
+ const match = fileRegex.exec(input);
2954
+ const path = match[2];
2955
+ return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path) ? path : "/" + path, match[3] || "", match[4] || "");
2956
+ }
2957
+ function makeUrl(scheme, user, host, port, path, query, hash) {
2958
+ return {
2959
+ scheme,
2960
+ user,
2961
+ host,
2962
+ port,
2963
+ path,
2964
+ query,
2965
+ hash,
2966
+ type: 7
2967
+ };
2968
+ }
2969
+ function parseUrl(input) {
2970
+ if (isSchemeRelativeUrl(input)) {
2971
+ const url2 = parseAbsoluteUrl("http:" + input);
2972
+ url2.scheme = "";
2973
+ url2.type = 6;
2974
+ return url2;
2975
+ }
2976
+ if (isAbsolutePath(input)) {
2977
+ const url2 = parseAbsoluteUrl("http://foo.com" + input);
2978
+ url2.scheme = "";
2979
+ url2.host = "";
2980
+ url2.type = 5;
2981
+ return url2;
2982
+ }
2983
+ if (isFileUrl(input))
2984
+ return parseFileUrl(input);
2985
+ if (isAbsoluteUrl(input))
2986
+ return parseAbsoluteUrl(input);
2987
+ const url = parseAbsoluteUrl("http://foo.com/" + input);
2988
+ url.scheme = "";
2989
+ url.host = "";
2990
+ url.type = input ? input.startsWith("?") ? 3 : input.startsWith("#") ? 2 : 4 : 1;
2991
+ return url;
2992
+ }
2993
+ function stripPathFilename(path) {
2994
+ if (path.endsWith("/.."))
2995
+ return path;
2996
+ const index = path.lastIndexOf("/");
2997
+ return path.slice(0, index + 1);
2998
+ }
2999
+ function mergePaths(url, base) {
3000
+ normalizePath2(base, base.type);
3001
+ if (url.path === "/") {
3002
+ url.path = base.path;
3003
+ } else {
3004
+ url.path = stripPathFilename(base.path) + url.path;
3005
+ }
3006
+ }
3007
+ function normalizePath2(url, type) {
3008
+ const rel = type <= 4;
3009
+ const pieces = url.path.split("/");
3010
+ let pointer = 1;
3011
+ let positive = 0;
3012
+ let addTrailingSlash = false;
3013
+ for (let i = 1; i < pieces.length; i++) {
3014
+ const piece = pieces[i];
3015
+ if (!piece) {
3016
+ addTrailingSlash = true;
3017
+ continue;
3018
+ }
3019
+ addTrailingSlash = false;
3020
+ if (piece === ".")
3021
+ continue;
3022
+ if (piece === "..") {
3023
+ if (positive) {
3024
+ addTrailingSlash = true;
3025
+ positive--;
3026
+ pointer--;
3027
+ } else if (rel) {
3028
+ pieces[pointer++] = piece;
3029
+ }
3030
+ continue;
3031
+ }
3032
+ pieces[pointer++] = piece;
3033
+ positive++;
3034
+ }
3035
+ let path = "";
3036
+ for (let i = 1; i < pointer; i++) {
3037
+ path += "/" + pieces[i];
3038
+ }
3039
+ if (!path || addTrailingSlash && !path.endsWith("/..")) {
3040
+ path += "/";
3041
+ }
3042
+ url.path = path;
3043
+ }
3044
+ function resolve5(input, base) {
3045
+ if (!input && !base)
3046
+ return "";
3047
+ const url = parseUrl(input);
3048
+ let inputType = url.type;
3049
+ if (base && inputType !== 7) {
3050
+ const baseUrl = parseUrl(base);
3051
+ const baseType = baseUrl.type;
3052
+ switch (inputType) {
3053
+ case 1:
3054
+ url.hash = baseUrl.hash;
3055
+ // fall through
3056
+ case 2:
3057
+ url.query = baseUrl.query;
3058
+ // fall through
3059
+ case 3:
3060
+ case 4:
3061
+ mergePaths(url, baseUrl);
3062
+ // fall through
3063
+ case 5:
3064
+ url.user = baseUrl.user;
3065
+ url.host = baseUrl.host;
3066
+ url.port = baseUrl.port;
3067
+ // fall through
3068
+ case 6:
3069
+ url.scheme = baseUrl.scheme;
3070
+ }
3071
+ if (baseType > inputType)
3072
+ inputType = baseType;
3073
+ }
3074
+ normalizePath2(url, inputType);
3075
+ const queryHash = url.query + url.hash;
3076
+ switch (inputType) {
3077
+ // This is impossible, because of the empty checks at the start of the function.
3078
+ // case UrlType.Empty:
3079
+ case 2:
3080
+ case 3:
3081
+ return queryHash;
3082
+ case 4: {
3083
+ const path = url.path.slice(1);
3084
+ if (!path)
3085
+ return queryHash || ".";
3086
+ if (isRelative(base || input) && !isRelative(path)) {
3087
+ return "./" + path + queryHash;
3088
+ }
3089
+ return path + queryHash;
3090
+ }
3091
+ case 5:
3092
+ return url.path + queryHash;
3093
+ default:
3094
+ return url.scheme + "//" + url.user + url.host + url.port + url.path + queryHash;
3095
+ }
3096
+ }
3097
+
3098
+ // node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs
3099
+ function stripFilename(path) {
3100
+ if (!path) return "";
3101
+ const index = path.lastIndexOf("/");
3102
+ return path.slice(0, index + 1);
3103
+ }
3104
+ function resolver(mapUrl, sourceRoot) {
3105
+ const from = stripFilename(mapUrl);
3106
+ const prefix = sourceRoot ? sourceRoot + "/" : "";
3107
+ return (source) => resolve5(prefix + (source || ""), from);
3108
+ }
3109
+ var COLUMN = 0;
3110
+ var SOURCES_INDEX = 1;
3111
+ var SOURCE_LINE = 2;
3112
+ var SOURCE_COLUMN = 3;
3113
+ var NAMES_INDEX = 4;
3114
+ function maybeSort(mappings, owned) {
3115
+ const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
3116
+ if (unsortedIndex === mappings.length) return mappings;
3117
+ if (!owned) mappings = mappings.slice();
3118
+ for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) {
3119
+ mappings[i] = sortSegments(mappings[i], owned);
3120
+ }
3121
+ return mappings;
3122
+ }
3123
+ function nextUnsortedSegmentLine(mappings, start) {
3124
+ for (let i = start; i < mappings.length; i++) {
3125
+ if (!isSorted(mappings[i])) return i;
3126
+ }
3127
+ return mappings.length;
3128
+ }
3129
+ function isSorted(line) {
3130
+ for (let j = 1; j < line.length; j++) {
3131
+ if (line[j][COLUMN] < line[j - 1][COLUMN]) {
3132
+ return false;
3133
+ }
3134
+ }
3135
+ return true;
3136
+ }
3137
+ function sortSegments(line, owned) {
3138
+ if (!owned) line = line.slice();
3139
+ return line.sort(sortComparator2);
3140
+ }
3141
+ function sortComparator2(a, b) {
3142
+ return a[COLUMN] - b[COLUMN];
3143
+ }
3144
+ var found = false;
3145
+ function binarySearch(haystack, needle, low, high) {
3146
+ while (low <= high) {
3147
+ const mid = low + (high - low >> 1);
3148
+ const cmp = haystack[mid][COLUMN] - needle;
3149
+ if (cmp === 0) {
3150
+ found = true;
3151
+ return mid;
3152
+ }
3153
+ if (cmp < 0) {
3154
+ low = mid + 1;
3155
+ } else {
3156
+ high = mid - 1;
3157
+ }
3158
+ }
3159
+ found = false;
3160
+ return low - 1;
3161
+ }
3162
+ function upperBound(haystack, needle, index) {
3163
+ for (let i = index + 1; i < haystack.length; index = i++) {
3164
+ if (haystack[i][COLUMN] !== needle) break;
3165
+ }
3166
+ return index;
3167
+ }
3168
+ function lowerBound(haystack, needle, index) {
3169
+ for (let i = index - 1; i >= 0; index = i--) {
3170
+ if (haystack[i][COLUMN] !== needle) break;
3171
+ }
3172
+ return index;
3173
+ }
3174
+ function memoizedState() {
3175
+ return {
3176
+ lastKey: -1,
3177
+ lastNeedle: -1,
3178
+ lastIndex: -1
3179
+ };
3180
+ }
3181
+ function memoizedBinarySearch(haystack, needle, state, key) {
3182
+ const { lastKey, lastNeedle, lastIndex } = state;
3183
+ let low = 0;
3184
+ let high = haystack.length - 1;
3185
+ if (key === lastKey) {
3186
+ if (needle === lastNeedle) {
3187
+ found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
3188
+ return lastIndex;
3189
+ }
3190
+ if (needle >= lastNeedle) {
3191
+ low = lastIndex === -1 ? 0 : lastIndex;
3192
+ } else {
3193
+ high = lastIndex;
3194
+ }
3195
+ }
3196
+ state.lastKey = key;
3197
+ state.lastNeedle = needle;
3198
+ return state.lastIndex = binarySearch(haystack, needle, low, high);
3199
+ }
3200
+ function parse2(map) {
3201
+ return typeof map === "string" ? JSON.parse(map) : map;
3202
+ }
3203
+ var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
3204
+ var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
3205
+ var LEAST_UPPER_BOUND = -1;
3206
+ var GREATEST_LOWER_BOUND = 1;
3207
+ var TraceMap = class {
3208
+ constructor(map, mapUrl) {
3209
+ const isString = typeof map === "string";
3210
+ if (!isString && map._decodedMemo) return map;
3211
+ const parsed = parse2(map);
3212
+ const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
3213
+ this.version = version;
3214
+ this.file = file;
3215
+ this.names = names || [];
3216
+ this.sourceRoot = sourceRoot;
3217
+ this.sources = sources;
3218
+ this.sourcesContent = sourcesContent;
3219
+ this.ignoreList = parsed.ignoreList || parsed.x_google_ignoreList || void 0;
3220
+ const resolve8 = resolver(mapUrl, sourceRoot);
3221
+ this.resolvedSources = sources.map(resolve8);
3222
+ const { mappings } = parsed;
3223
+ if (typeof mappings === "string") {
3224
+ this._encoded = mappings;
3225
+ this._decoded = void 0;
3226
+ } else if (Array.isArray(mappings)) {
3227
+ this._encoded = void 0;
3228
+ this._decoded = maybeSort(mappings, isString);
3229
+ } else if (parsed.sections) {
3230
+ throw new Error(`TraceMap passed sectioned source map, please use FlattenMap export instead`);
3231
+ } else {
3232
+ throw new Error(`invalid source map: ${JSON.stringify(parsed)}`);
3233
+ }
3234
+ this._decodedMemo = memoizedState();
3235
+ this._bySources = void 0;
3236
+ this._bySourceMemos = void 0;
3237
+ }
3238
+ };
3239
+ function cast(map) {
3240
+ return map;
3241
+ }
3242
+ function decodedMappings(map) {
3243
+ var _a;
3244
+ return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
3245
+ }
3246
+ function originalPositionFor(map, needle) {
3247
+ let { line, column, bias } = needle;
3248
+ line--;
3249
+ if (line < 0) throw new Error(LINE_GTR_ZERO);
3250
+ if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
3251
+ const decoded = decodedMappings(map);
3252
+ if (line >= decoded.length) return OMapping(null, null, null, null);
3253
+ const segments = decoded[line];
3254
+ const index = traceSegmentInternal(
3255
+ segments,
3256
+ cast(map)._decodedMemo,
3257
+ line,
3258
+ column,
3259
+ bias || GREATEST_LOWER_BOUND
3260
+ );
3261
+ if (index === -1) return OMapping(null, null, null, null);
3262
+ const segment = segments[index];
3263
+ if (segment.length === 1) return OMapping(null, null, null, null);
3264
+ const { names, resolvedSources } = map;
3265
+ return OMapping(
3266
+ resolvedSources[segment[SOURCES_INDEX]],
3267
+ segment[SOURCE_LINE] + 1,
3268
+ segment[SOURCE_COLUMN],
3269
+ segment.length === 5 ? names[segment[NAMES_INDEX]] : null
3270
+ );
3271
+ }
3272
+ function OMapping(source, line, column, name) {
3273
+ return { source, line, column, name };
3274
+ }
3275
+ function traceSegmentInternal(segments, memo, line, column, bias) {
3276
+ let index = memoizedBinarySearch(segments, column, memo, line);
3277
+ if (found) {
3278
+ index = (bias === LEAST_UPPER_BOUND ? upperBound : lowerBound)(segments, column, index);
3279
+ } else if (bias === LEAST_UPPER_BOUND) index++;
3280
+ if (index === -1 || index === segments.length) return -1;
3281
+ return index;
3282
+ }
3283
+
3284
+ // src/dev/stack-trace.ts
3285
+ var internalModules = /* @__PURE__ */ new Set([
3286
+ "__kody_local_entry.js",
3287
+ "kody:runtime",
3288
+ ".__kody_runtime__.js",
3289
+ "runtime.js",
3290
+ "entry.js"
3291
+ ]);
3292
+ var framePattern = /^(\s*at\s+)(?:(.*?)\s+\()?([^()\s]+?):(\d+):(\d+)\)?\s*$/;
3293
+ function createStackMapper(input) {
3294
+ let map = null;
3295
+ if (input.sourceMap) {
3296
+ try {
3297
+ map = new TraceMap(input.sourceMap);
3298
+ } catch {
3299
+ map = null;
3300
+ }
3301
+ }
3302
+ return (stack) => {
3303
+ const out = [];
3304
+ for (const line of stack.split("\n")) {
3305
+ if (!/^\s*at\s/.test(line)) {
3306
+ out.push(line);
3307
+ continue;
3308
+ }
3309
+ const match = framePattern.exec(line);
3310
+ if (!match) continue;
3311
+ const [, lead, fn, file, lineText, colText] = match;
3312
+ const module = file.replace(/^file:\/\/\//, "").replace(/^\//, "");
3313
+ if (internalModules.has(module)) continue;
3314
+ const fnPart = fn ? `${fn} (` : "";
3315
+ const close = fn ? ")" : "";
3316
+ if (map && module === input.userModule) {
3317
+ const original = originalPositionFor(map, {
3318
+ line: Number(lineText),
3319
+ column: Number(colText) - 1
3320
+ });
3321
+ if (original.source && original.line !== null) {
3322
+ const name = fn ?? original.name;
3323
+ out.push(
3324
+ `${lead}${name ? `${name} (` : ""}${original.source}:${original.line}:${(original.column ?? 0) + 1}${name ? ")" : ""}`
3325
+ );
3326
+ continue;
3327
+ }
3328
+ }
3329
+ out.push(`${lead}${fnPart}${file}:${lineText}:${colText}${close}`);
3330
+ }
3331
+ return out.join("\n");
3332
+ };
3333
+ }
3334
+
3335
+ // src/dev/workerd-process.ts
3336
+ import { spawn as spawn3 } from "node:child_process";
3337
+ import { createInterface } from "node:readline";
3338
+ var workerdStartTimeoutMs = 3e4;
3339
+ async function startWorkerd(input) {
3340
+ const child = spawn3(input.workerdPath, ["serve", input.configPath, "--control-fd=3"], {
3341
+ cwd: input.cwd,
3342
+ env: input.env,
3343
+ stdio: ["ignore", "pipe", "pipe", "pipe"]
3344
+ });
3345
+ if (child.pid !== void 0) input.onSpawn?.(child.pid);
3346
+ let startupStderr = "";
3347
+ let listening = false;
3348
+ forEachLine2(child.stdout, input.onStdoutLine);
3349
+ forEachLine2(child.stderr, (line) => {
3350
+ if (!listening) startupStderr += `${line}
3351
+ `;
3352
+ input.onStderrLine(line);
3353
+ });
3354
+ const exited = new Promise((resolve8) => {
3355
+ child.once("exit", (code, signal) => resolve8(`workerd exit ${signal ?? code}`));
3356
+ child.once("error", (error) => resolve8(`workerd error: ${error.message}`));
3357
+ });
3358
+ const port = await waitForListen(child, exited, () => {
3359
+ const trimmed = redact(startupStderr.trim());
3360
+ return trimmed ? `
3361
+ ${trimmed}` : "";
3362
+ });
3363
+ listening = true;
3364
+ return {
3365
+ pid: child.pid ?? -1,
3366
+ port,
3367
+ exited,
3368
+ kill: async () => {
3369
+ if (child.exitCode !== null || child.signalCode !== null) return;
3370
+ child.kill("SIGKILL");
3371
+ await Promise.race([exited, new Promise((resolve8) => setTimeout(resolve8, 1e3))]);
3372
+ }
3373
+ };
3374
+ }
3375
+ function forEachLine2(stream, onLine) {
3376
+ if (!stream) return;
3377
+ const lines = createInterface({ input: stream, crlfDelay: Infinity });
3378
+ lines.on("line", (line) => {
3379
+ if (line.length > 0) onLine(line);
3380
+ });
3381
+ }
3382
+ function waitForListen(child, exited, stderr) {
3383
+ return new Promise((resolve8, reject) => {
3384
+ const control = child.stdio[3];
3385
+ let buffered = "";
3386
+ let settled = false;
3387
+ const settle = (fn) => {
3388
+ if (settled) return;
3389
+ settled = true;
3390
+ clearTimeout(timer);
3391
+ fn();
3392
+ };
3393
+ const timer = setTimeout(() => {
3394
+ settle(() => {
3395
+ child.kill("SIGKILL");
3396
+ reject(
3397
+ new Error(`workerd did not start within ${workerdStartTimeoutMs / 1e3}s.${stderr()}`)
3398
+ );
3399
+ });
3400
+ }, workerdStartTimeoutMs);
3401
+ control?.on("data", (chunk) => {
3402
+ buffered += chunk.toString("utf8");
3403
+ const lines = buffered.split("\n");
3404
+ buffered = lines.pop() ?? "";
3405
+ for (const line of lines) {
3406
+ const port = parseListenPort(line);
3407
+ if (port !== null) settle(() => resolve8(port));
3408
+ }
3409
+ });
3410
+ void exited.then((detail) => {
3411
+ settle(() => reject(new Error(`workerd failed to start (${detail})${stderr()}`)));
3412
+ });
3413
+ });
3414
+ }
3415
+ function parseListenPort(line) {
3416
+ if (!line.trim()) return null;
3417
+ try {
3418
+ const event = JSON.parse(line);
3419
+ return event.event === "listen" && event.socket === "http" && typeof event.port === "number" ? event.port : null;
3420
+ } catch {
3421
+ return null;
3422
+ }
3423
+ }
3424
+ function cleanWorkerdStderrLine(line) {
3425
+ const trimmed = line.trim();
3426
+ if (!trimmed) return null;
3427
+ if (/^stack:(\s+\S+@[0-9a-fx]+)+\s*$/i.test(trimmed)) return null;
3428
+ const prefixed = /^workerd\/\S+:\d+: (?:error|warning|info|debug): (.*)$/.exec(trimmed);
3429
+ const body = prefixed ? prefixed[1] : trimmed;
3430
+ return body.replace(/\S+\.(?:c\+\+|h):\d+: failed: /g, "").replace(/(?:remote\.)?jsg\.(\w*Error)(?=:)/g, "$1");
3431
+ }
3432
+
3433
+ // src/package-app-dev.ts
3434
+ var defaultDebounceMs = 30;
3435
+ var prebuildSettleMs = 150;
3436
+ var failedPrebuildAbsorbMs = 1500;
3437
+ var rebuildGateMs = 1e4;
3438
+ var drainTimeoutMs = 1e4;
3439
+ async function startPackageAppDev(options) {
3440
+ if (!options.manifest.app?.entry) {
3441
+ throw new Error(
3442
+ 'This package has no kody.app.entry. Add `"kody": { "app": { "entry": "./app/router.ts" } }` or use `kody dev job|webhook|emit|check`.'
3443
+ );
3444
+ }
3445
+ assertTokenSafeApiUrl(options.apiUrl);
3446
+ const host = options.host ?? "127.0.0.1";
3447
+ const appBasePath = normalizeBasePath(options.appBasePath ?? "");
3448
+ const root = options.manifest.root;
3449
+ const runSecret = randomBytes(32).toString("hex");
3450
+ const emit = (event) => options.onEvent?.(event);
3451
+ const liveReload = options.liveReload ?? options.watch !== false;
3452
+ const errorPageTail = liveReload ? `<script>globalThis.__kodyDevErrorPage = true</script>${liveReloadScriptTag}` : "";
3453
+ void sweepStaleDevDirs().catch(() => {
3454
+ });
3455
+ const workDir = await mkdtemp(join7(tmpdir2(), devWorkDirPrefix));
3456
+ const reaper = await startProcessReaper({ workDir });
3457
+ const workerdPath = options.workerdPath ?? await ensureWorkerdBinary({
3458
+ onDownload: (url) => options.onStatus?.(`Downloading workerd from ${url}\u2026`)
3459
+ });
3460
+ const client = {
3461
+ apiUrl: options.apiUrl,
3462
+ token: options.token,
3463
+ fetchFn: options.fetchFn,
3464
+ ...options.org ? { org: options.org } : {}
3465
+ };
3466
+ const generations = /* @__PURE__ */ new Set();
3467
+ let active;
3468
+ let buildFailure = null;
3469
+ let generationCounter = 0;
3470
+ let requestCounter = 0;
3471
+ let closed = false;
3472
+ let buildLoop = null;
3473
+ let rebuildAgain = false;
3474
+ const changedFiles = /* @__PURE__ */ new Set();
3475
+ let debouncePending = false;
3476
+ let debounceFlush = null;
3477
+ let resolveDebounceFlush = null;
3478
+ let debounceTimer;
3479
+ const liveReloadHub = createLiveReloadHub({
3480
+ state: () => ({
3481
+ buildId: active?.id ?? null,
3482
+ error: buildFailure ? buildErrorView(buildFailure) : null
3483
+ })
3484
+ });
3485
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
3486
+ let lastRebuild = null;
3487
+ let lastRuntimeError = null;
3488
+ let buildFailureAt = startedAt;
3489
+ let markStarted = () => {
3490
+ };
3491
+ const started = new Promise((resolve8) => {
3492
+ markStarted = resolve8;
3493
+ });
3494
+ const killAllSync = () => {
3495
+ for (const generation of generations) {
3496
+ try {
3497
+ process.kill(generation.workerd.pid, "SIGKILL");
3498
+ } catch {
3499
+ }
3500
+ }
3501
+ try {
3502
+ rmSync(workDir, { recursive: true, force: true });
3503
+ } catch {
3504
+ }
3505
+ };
3506
+ process.once("exit", killAllSync);
3507
+ const proxy = createServer((req, res) => {
3508
+ void handleRequest(req, res);
3509
+ });
3510
+ try {
3511
+ await listenDevServer(proxy, {
3512
+ host,
3513
+ port: options.port ?? options.defaultPort ?? 0,
3514
+ explicit: options.port !== void 0
3515
+ });
3516
+ } catch (error) {
3517
+ process.off("exit", killAllSync);
3518
+ reaper.close();
3519
+ await rm3(workDir, { recursive: true, force: true });
3520
+ throw error;
3521
+ }
3522
+ const address = proxy.address();
3523
+ const hostedUrl = `http://${host}:${address.port}`;
3524
+ try {
3525
+ await options.onListening?.({
3526
+ port: address.port,
3527
+ hostedUrl,
3528
+ appBasePath
3529
+ });
3530
+ } catch (error) {
3531
+ process.off("exit", killAllSync);
3532
+ reaper.close();
3533
+ proxy.closeAllConnections();
3534
+ await new Promise((resolve8) => {
3535
+ proxy.close(() => resolve8());
3536
+ });
3537
+ await rm3(workDir, { recursive: true, force: true });
3538
+ throw error;
3539
+ }
3540
+ const contextFor = (client2) => buildLocalPackageContext({
3541
+ kodyId: options.manifest.kodyId,
3542
+ packageId: `local:${options.manifest.kodyId}`,
3543
+ hostedUrl,
3544
+ appBasePath,
3545
+ clientModuleUrl: client2 ? clientModuleUrlFor(client2) : null
3546
+ });
3547
+ const clientModuleUrlFor = (client2) => `${hostedUrl}${appBasePath}/_assets/${client2.name}`;
3548
+ const mockFetchGateway = await resolveMockFetchGateway({
3549
+ target: options.target,
3550
+ packageRoot: root,
3551
+ passthroughHosts: options.passthroughHosts,
3552
+ allowPrivateNetwork: options.allowPrivateNetwork,
3553
+ onStatus: options.onStatus
3554
+ });
3555
+ const bridge = await startLocalRuntimeBridge({
3556
+ runSecret,
3557
+ forwardCall: async (call, signal) => {
3558
+ const mocked = tryHandleMockGatewayFetchCall({
3559
+ gateway: mockFetchGateway,
3560
+ path: call.path,
3561
+ args: call.args,
3562
+ signal
3563
+ });
3564
+ if (mocked) return await mocked;
3565
+ return await callCapabilityProxy({
3566
+ ...client,
3567
+ ...call,
3568
+ signal
3569
+ });
3570
+ },
3571
+ forwardGatewayFetchStream: async ({ request, response, signal }) => {
3572
+ await forwardLocalGatewayFetchStream({
3573
+ request,
3574
+ response,
3575
+ signal,
3576
+ client,
3577
+ ...mockFetchGateway ? { mockFetchGateway } : {}
3578
+ });
3579
+ }
3580
+ });
3581
+ const app = options.manifest.app;
3582
+ const entryPath = resolvePackagePath(options.manifest, app.entry);
3583
+ const bundler = createDevBundler({ entryPath, root });
3584
+ const clientBundler = app.client ? createDevClientBundler({
3585
+ entryPath: resolvePackagePath(options.manifest, app.client),
3586
+ root,
3587
+ externals: app.clientExternals
3588
+ }) : null;
3589
+ const assetsDir = app.assets ? resolve6(root, app.assets) : null;
3590
+ const prebuild = options.manifest.dev?.prebuild;
3591
+ let prebuildRunning = false;
3592
+ let prebuildSettledAt = 0;
3593
+ let ignoreWatcherUntil = 0;
3594
+ let prebuildAbort;
3595
+ const workerdEnv = { ...process.env, [runSecretEnvVar]: runSecret };
3596
+ delete workerdEnv[apiTokenEnvVar];
3597
+ function requestBuild(paths) {
3598
+ if (closed) return Promise.resolve();
3599
+ for (const path of paths) changedFiles.add(path);
3600
+ if (buildLoop) {
3601
+ rebuildAgain = true;
3602
+ return buildLoop;
3603
+ }
3604
+ buildLoop = (async () => {
3605
+ do {
3606
+ rebuildAgain = false;
3607
+ const files = [...changedFiles];
3608
+ changedFiles.clear();
3609
+ await buildOnce(files);
3610
+ } while (rebuildAgain && !closed);
3611
+ })().finally(() => {
3612
+ buildLoop = null;
3613
+ });
3614
+ return buildLoop;
3615
+ }
3616
+ async function buildOnce(files) {
3617
+ const started2 = performance.now();
3618
+ emit({ type: "rebuild_start", files: files.map((file) => relative4(root, file) || file) });
3619
+ const assetsChanged = assetsDir !== null && files.some((file) => file === assetsDir || file.startsWith(`${assetsDir}${sep3}`));
3620
+ try {
3621
+ if (prebuild) {
3622
+ await runPrebuildStep(prebuild);
3623
+ }
3624
+ const [bundle, client2] = await Promise.all([
3625
+ bundler.build(),
3626
+ clientBundler ? clientBundler.build() : Promise.resolve(null)
3627
+ ]);
3628
+ const midBuildEdits = await watcher?.track(
3629
+ [...bundle.inputs, ...client2?.inputs ?? [], options.manifest.packageJsonPath],
3630
+ { ignoreChanges: files }
3631
+ ) ?? [];
3632
+ if (midBuildEdits.length > 0) {
3633
+ for (const path of midBuildEdits) changedFiles.add(path);
3634
+ rebuildAgain = true;
3635
+ }
3636
+ if (active && !buildFailure && bundle.code === active.code && client2?.name === active.client?.name) {
3637
+ lastRebuild = { ms: elapsed(started2), at: (/* @__PURE__ */ new Date()).toISOString() };
3638
+ emit({
3639
+ type: "rebuild_ok",
3640
+ ms: lastRebuild.ms,
3641
+ buildId: active.id,
3642
+ restarted: false
3643
+ });
3644
+ if (assetsChanged || prebuild) {
3645
+ liveReloadHub.broadcast({ event: "reload", data: { buildId: active.id } });
3646
+ }
3647
+ return;
3648
+ }
3649
+ const generation = await startGeneration(bundle, client2);
3650
+ if (closed) {
3651
+ await stopGeneration(generation);
3652
+ return;
3653
+ }
3654
+ const previous = active;
3655
+ active = generation;
3656
+ buildFailure = null;
3657
+ if (previous) retireGeneration(previous);
3658
+ lastRuntimeError = null;
3659
+ lastRebuild = { ms: elapsed(started2), at: (/* @__PURE__ */ new Date()).toISOString() };
3660
+ emit({ type: "rebuild_ok", ms: lastRebuild.ms, buildId: generation.id, restarted: true });
3661
+ liveReloadHub.broadcast({ event: "reload", data: { buildId: generation.id } });
3662
+ } catch (error) {
3663
+ buildFailure = toBuildFailure(error);
3664
+ buildFailureAt = (/* @__PURE__ */ new Date()).toISOString();
3665
+ const [first] = buildFailure.diagnostics;
3666
+ emit({
3667
+ type: "build_error",
3668
+ ms: elapsed(started2),
3669
+ message: buildFailure.message,
3670
+ file: first?.file ?? null,
3671
+ line: first?.line ?? null,
3672
+ col: first?.col ?? null,
3673
+ diagnostics: buildFailure.diagnostics
3674
+ });
3675
+ liveReloadHub.broadcast({ event: "build_error", data: buildErrorView(buildFailure) });
3676
+ }
3677
+ }
3678
+ let clearWatcherPending = null;
3679
+ async function runPrebuildStep(command) {
3680
+ prebuildRunning = true;
3681
+ prebuildAbort = new AbortController();
3682
+ let failed = false;
3683
+ try {
3684
+ await runPrebuild({
3685
+ command,
3686
+ cwd: root,
3687
+ signal: prebuildAbort.signal,
3688
+ onSpawn: (pid) => reaper.trackGroup(pid),
3689
+ onExit: (pid) => reaper.untrackGroup(pid),
3690
+ onLine: (line, stream) => emit({
3691
+ type: "log",
3692
+ source: "prebuild",
3693
+ level: stream === "stderr" ? "warn" : "log",
3694
+ message: redact(line),
3695
+ request: null
3696
+ })
3697
+ });
3698
+ } catch (error) {
3699
+ failed = true;
3700
+ throw error;
3701
+ } finally {
3702
+ prebuildAbort = void 0;
3703
+ prebuildRunning = false;
3704
+ prebuildSettledAt = performance.now();
3705
+ await watcher?.rebaseline();
3706
+ if (failed) {
3707
+ changedFiles.clear();
3708
+ rebuildAgain = false;
3709
+ clearWatcherPending?.();
3710
+ ignoreWatcherUntil = performance.now() + failedPrebuildAbsorbMs;
3711
+ }
3712
+ }
3713
+ }
3714
+ async function startGeneration(bundle, client2) {
3715
+ const id = ++generationCounter;
3716
+ const dir = join7(workDir, `g${id}`);
3717
+ await writeWorkerFiles({
3718
+ workDir: dir,
3719
+ code: bundle.code,
3720
+ packageContext: contextFor(client2),
3721
+ packageRoot: root,
3722
+ mockStorage: options.target === "mock",
3723
+ bridgePort: bridge.port,
3724
+ allowPrivateNetwork: options.allowPrivateNetwork,
3725
+ apiUrl: options.apiUrl,
3726
+ token: options.token,
3727
+ org: options.org,
3728
+ fetchFn: options.fetchFn,
3729
+ depResolve: options.depResolve,
3730
+ mockFetchGateway,
3731
+ onStatus: options.onStatus
3732
+ });
3733
+ let trackedPid;
3734
+ let workerd;
3735
+ try {
3736
+ workerd = await startWorkerd({
3737
+ workerdPath,
3738
+ configPath: join7(dir, "config.capnp"),
3739
+ cwd: dir,
3740
+ env: workerdEnv,
3741
+ onSpawn: (pid) => {
3742
+ trackedPid = pid;
3743
+ reaper.track(pid);
3744
+ },
3745
+ onStdoutLine: (line) => emit(parseWorkerdStdoutLine(line)),
3746
+ onStderrLine: (line) => {
3747
+ const cleaned = cleanWorkerdStderrLine(line);
3748
+ if (cleaned === null) return;
3749
+ emit({
3750
+ type: "log",
3751
+ source: "workerd",
3752
+ level: "error",
3753
+ message: redact(cleaned),
3754
+ request: null
3755
+ });
3756
+ }
3757
+ });
3758
+ } catch (error) {
3759
+ if (trackedPid !== void 0) reaper.untrack(trackedPid);
3760
+ await rm3(dir, { recursive: true, force: true }).catch(() => {
3761
+ });
3762
+ throw error;
3763
+ }
3764
+ const generation = {
3765
+ id,
3766
+ dir,
3767
+ workerd,
3768
+ code: bundle.code,
3769
+ client: client2,
3770
+ mapStack: createStackMapper({
3771
+ sourceMap: bundle.sourceMap,
3772
+ userModule: localWorkerModuleNames.user
3773
+ }),
3774
+ inflight: 0,
3775
+ retired: false,
3776
+ stopped: false
3777
+ };
3778
+ generations.add(generation);
3779
+ void workerd.exited.then((detail) => {
3780
+ reaper.untrack(workerd.pid);
3781
+ if (closed || generation.retired || active !== generation) return;
3782
+ active = void 0;
3783
+ buildFailure = {
3784
+ message: `workerd stopped unexpectedly (${detail}). Save a file to restart it.`,
3785
+ diagnostics: []
3786
+ };
3787
+ options.onError?.(buildFailure.message);
3788
+ });
3789
+ return generation;
3790
+ }
3791
+ function retireGeneration(generation) {
3792
+ generation.retired = true;
3793
+ if (generation.inflight === 0) {
3794
+ void stopGeneration(generation);
3795
+ return;
3796
+ }
3797
+ setTimeout(() => void stopGeneration(generation), drainTimeoutMs).unref();
3798
+ }
3799
+ async function stopGeneration(generation) {
3800
+ if (generation.stopped) return;
3801
+ generation.stopped = true;
3802
+ generation.retired = true;
3803
+ await generation.workerd.kill();
3804
+ reaper.untrack(generation.workerd.pid);
3805
+ generations.delete(generation);
3806
+ await rm3(generation.dir, { recursive: true, force: true });
3807
+ }
3808
+ async function waitForBuild() {
3809
+ const flush = debounceFlush;
3810
+ if (flush) await flush;
3811
+ const pending = buildLoop ?? (active || buildFailure ? null : started);
3812
+ if (!pending) return;
3813
+ await Promise.race([
3814
+ pending.catch(() => {
3815
+ }),
3816
+ new Promise((resolve8) => setTimeout(resolve8, rebuildGateMs).unref())
3817
+ ]);
3818
+ }
3819
+ function status() {
3820
+ const [first] = buildFailure?.diagnostics ?? [];
3821
+ return {
3822
+ ok: buildFailure === null && active !== void 0,
3823
+ state: buildLoop || debouncePending ? "building" : buildFailure ? "build_error" : active ? "ready" : "starting",
3824
+ buildId: active?.id ?? null,
3825
+ url: `${hostedUrl}${appBasePath || "/"}`,
3826
+ port: address.port,
3827
+ basePath: appBasePath,
3828
+ target: options.target,
3829
+ package: {
3830
+ name: options.manifest.name,
3831
+ kodyId: options.manifest.kodyId,
3832
+ root
3833
+ },
3834
+ pid: process.pid,
3835
+ startedAt,
3836
+ lastRebuild,
3837
+ lastError: buildFailure ? {
3838
+ kind: "build",
3839
+ message: buildFailure.message,
3840
+ file: first?.file ?? null,
3841
+ line: first?.line ?? null,
3842
+ col: first?.col ?? null,
3843
+ at: buildFailureAt
3844
+ } : lastRuntimeError
3845
+ };
3846
+ }
3847
+ function handleDevRoute(req, res) {
3848
+ const pathname = stripMount(new URL(req.url ?? "/", hostedUrl).pathname, appBasePath);
3849
+ if (pathname === devStatusPath) {
3850
+ res.writeHead(200, {
3851
+ "content-type": "application/json; charset=utf-8",
3852
+ "cache-control": "no-store"
3853
+ });
3854
+ res.end(`${JSON.stringify(status(), null, 2)}
3855
+ `);
3856
+ return true;
3857
+ }
3858
+ if (!liveReload) return false;
3859
+ if (pathname === liveReloadEventsPath) {
3860
+ liveReloadHub.handleEvents(req, res);
3861
+ return true;
3862
+ }
3863
+ if (pathname === liveReloadClientPath) {
3864
+ res.writeHead(200, {
3865
+ "content-type": "text/javascript; charset=utf-8",
3866
+ "cache-control": "no-store"
3867
+ });
3868
+ res.end(liveReloadClientSource);
3869
+ return true;
3870
+ }
3871
+ return false;
3872
+ }
3873
+ async function handleRequest(req, res) {
3874
+ try {
3875
+ if (handleDevRoute(req, res)) return;
3876
+ await waitForBuild();
3877
+ const assetPath = parseDevAssetPath(
3878
+ stripMount(new URL(req.url ?? "/", hostedUrl).pathname, appBasePath)
3879
+ );
3880
+ if (assetPath !== null) {
3881
+ const client2 = active?.client ?? null;
3882
+ await serveDevAsset({
3883
+ req,
3884
+ res,
3885
+ relativePath: assetPath,
3886
+ assetsDir,
3887
+ client: client2,
3888
+ clientModuleUrl: client2 ? clientModuleUrlFor(client2) : null,
3889
+ appBasePath
3890
+ });
3891
+ return;
3892
+ }
3893
+ if (buildFailure) {
3894
+ sendDevError(req, res, 500, buildErrorView(buildFailure), {
3895
+ htmlTail: errorPageTail
3896
+ });
3897
+ return;
3898
+ }
3899
+ const generation = active;
3900
+ if (!generation) {
3901
+ res.writeHead(503, { "content-type": "text/plain; charset=utf-8" });
3902
+ res.end(closed ? "kody dev is shutting down.\n" : "kody dev is still starting.\n");
3903
+ return;
3904
+ }
3905
+ generation.inflight += 1;
3906
+ try {
3907
+ await forwardRequest(generation, req, res);
3908
+ } finally {
3909
+ generation.inflight -= 1;
3910
+ if (generation.retired && generation.inflight === 0) {
3911
+ void stopGeneration(generation);
3912
+ }
3913
+ }
3914
+ } catch (error) {
3915
+ const message = error instanceof Error ? error.message : String(error);
3916
+ options.onError?.(`Dev proxy error: ${message}`);
3917
+ if (!res.headersSent) {
3918
+ res.writeHead(502, { "content-type": "text/plain; charset=utf-8" });
3919
+ res.end(`Dev proxy error: ${message}
3920
+ `);
3921
+ } else if (!res.writableEnded) {
3922
+ res.destroy();
3923
+ }
3924
+ }
3925
+ }
3926
+ function forwardRequest(generation, req, res) {
3927
+ const incomingUrl = new URL(req.url ?? "/", hostedUrl);
3928
+ const restPath = stripMount(incomingUrl.pathname, appBasePath);
3929
+ const forwardUrl = new URL(
3930
+ restPath + incomingUrl.search,
3931
+ `http://127.0.0.1:${generation.workerd.port}`
3932
+ );
3933
+ const tag = {
3934
+ id: String(++requestCounter),
3935
+ method: req.method ?? "GET",
3936
+ path: restPath + incomingUrl.search
3937
+ };
3938
+ const headers = {
3939
+ ...req.headers,
3940
+ host: `127.0.0.1:${generation.workerd.port}`,
3941
+ [runSecretHeader]: runSecret,
3942
+ [devRequestIdHeader]: tag.id
3943
+ };
3944
+ return new Promise((resolve8, reject) => {
3945
+ const upstream = httpRequest(
3946
+ forwardUrl,
3947
+ { method: req.method, headers },
3948
+ (upstreamRes) => {
3949
+ if (upstreamRes.headers[devErrorHeader]) {
3950
+ void readStream(upstreamRes).then((raw) => {
3951
+ respondWithRuntimeError(generation, req, res, tag, raw);
3952
+ resolve8();
3953
+ }).catch(reject);
3954
+ return;
3955
+ }
3956
+ const status2 = upstreamRes.statusCode ?? 502;
3957
+ if (status2 >= 500) {
3958
+ emit({
3959
+ type: "log",
3960
+ source: "app",
3961
+ level: "warn",
3962
+ message: `responded HTTP ${status2}`,
3963
+ request: tag
3964
+ });
3965
+ }
3966
+ if (liveReload && shouldInjectLiveReload({
3967
+ method: req.method,
3968
+ accept: req.headers.accept,
3969
+ status: status2,
3970
+ headers: upstreamRes.headers
3971
+ })) {
3972
+ void readStream(upstreamRes).then((html) => {
3973
+ const body = Buffer.from(injectLiveReloadScript(html), "utf8");
3974
+ const headers2 = { ...upstreamRes.headers };
3975
+ delete headers2["transfer-encoding"];
3976
+ headers2["content-length"] = String(body.length);
3977
+ res.writeHead(status2, headers2);
3978
+ res.end(body);
3979
+ resolve8();
3980
+ }).catch(reject);
3981
+ return;
3982
+ }
3983
+ res.writeHead(status2, upstreamRes.headers);
3984
+ upstreamRes.pipe(res);
3985
+ upstreamRes.on("end", () => resolve8());
3986
+ upstreamRes.on("error", reject);
3987
+ }
3988
+ );
3989
+ upstream.on("error", reject);
3990
+ res.on("close", () => {
3991
+ if (!res.writableFinished) upstream.destroy();
3992
+ resolve8();
3993
+ });
3994
+ req.pipe(upstream);
3995
+ });
3996
+ }
3997
+ function respondWithRuntimeError(generation, req, res, tag, raw) {
3998
+ let message = "Uncaught error";
3999
+ let stack = "";
4000
+ try {
4001
+ const parsed = JSON.parse(raw);
4002
+ message = `${parsed.name ?? "Error"}: ${parsed.message ?? ""}`;
4003
+ stack = parsed.stack ?? message;
4004
+ } catch {
4005
+ stack = raw;
4006
+ }
4007
+ const mapped = redact(generation.mapStack(stack));
4008
+ const fix = runtimeErrorFix(message);
4009
+ lastRuntimeError = {
4010
+ kind: "runtime",
4011
+ message: redact(message),
4012
+ stack: mapped,
4013
+ request: tag,
4014
+ ...fix ? { fix } : {},
4015
+ at: (/* @__PURE__ */ new Date()).toISOString()
4016
+ };
4017
+ emit({
4018
+ type: "runtime_error",
4019
+ message: redact(message),
4020
+ stack: mapped,
4021
+ request: tag,
4022
+ ...fix ? { fix } : {}
4023
+ });
4024
+ const view = {
4025
+ kind: "runtime",
4026
+ title: redact(message),
4027
+ detail: fix ? `${mapped}
4028
+
4029
+ fix: ${fix}` : mapped,
4030
+ request: `${tag.method} ${tag.path}`
4031
+ };
4032
+ liveReloadHub.broadcast({ event: "runtime_error", data: view });
4033
+ sendDevError(req, res, 500, view, { htmlTail: errorPageTail });
4034
+ }
4035
+ const watcher = options.watch === false ? null : (() => {
4036
+ const pending = /* @__PURE__ */ new Set();
4037
+ clearWatcherPending = () => {
4038
+ pending.clear();
4039
+ clearTimeout(debounceTimer);
4040
+ debouncePending = false;
4041
+ const resolve8 = resolveDebounceFlush;
4042
+ resolveDebounceFlush = null;
4043
+ debounceFlush = null;
4044
+ resolve8?.();
4045
+ };
4046
+ return createDevWatcher({
4047
+ root,
4048
+ ignore: options.manifest.dev?.ignore,
4049
+ onChange: (path) => {
4050
+ if (closed) return;
4051
+ const now = performance.now();
4052
+ if (prebuildRunning || now - prebuildSettledAt < prebuildSettleMs) {
4053
+ return;
4054
+ }
4055
+ if (now < ignoreWatcherUntil) {
4056
+ return false;
4057
+ }
4058
+ if (buildLoop) {
4059
+ changedFiles.add(path);
4060
+ rebuildAgain = true;
4061
+ return;
4062
+ }
4063
+ pending.add(path);
4064
+ debouncePending = true;
4065
+ if (!debounceFlush) {
4066
+ debounceFlush = new Promise((resolve8) => {
4067
+ resolveDebounceFlush = resolve8;
4068
+ });
4069
+ }
4070
+ clearTimeout(debounceTimer);
4071
+ debounceTimer = setTimeout(() => {
4072
+ const paths = [...pending];
4073
+ pending.clear();
4074
+ debouncePending = false;
4075
+ const build = requestBuild(paths);
4076
+ const resolve8 = resolveDebounceFlush;
4077
+ resolveDebounceFlush = null;
4078
+ debounceFlush = null;
4079
+ resolve8?.();
4080
+ void build;
4081
+ }, options.debounceMs ?? defaultDebounceMs);
4082
+ }
4083
+ });
4084
+ })();
4085
+ const close = async () => {
4086
+ if (closed) return;
4087
+ closed = true;
4088
+ process.off("exit", killAllSync);
4089
+ clearTimeout(debounceTimer);
4090
+ debouncePending = false;
4091
+ const resolve8 = resolveDebounceFlush;
4092
+ resolveDebounceFlush = null;
4093
+ debounceFlush = null;
4094
+ resolve8?.();
4095
+ prebuildAbort?.abort();
4096
+ await watcher?.close();
4097
+ await buildLoop?.catch(() => {
4098
+ });
4099
+ await bundler.dispose();
4100
+ await clientBundler?.dispose();
4101
+ await Promise.all([...generations].map((generation) => stopGeneration(generation)));
4102
+ reaper.close();
4103
+ await bridge.close();
4104
+ liveReloadHub.close();
4105
+ proxy.closeAllConnections();
4106
+ await new Promise((resolve9) => {
4107
+ proxy.close(() => resolve9());
4108
+ });
4109
+ await rm3(workDir, { recursive: true, force: true });
4110
+ };
4111
+ try {
4112
+ await Promise.all([requestBuild([]), watcher?.ready]);
4113
+ } catch (error) {
4114
+ await close();
4115
+ throw error;
4116
+ } finally {
4117
+ markStarted();
4118
+ }
4119
+ if (options.watch === false && buildFailure) {
4120
+ const message = buildFailure.message;
4121
+ await close();
4122
+ throw new Error(message);
4123
+ }
4124
+ if (active) options.onStatus?.(`App ready at ${hostedUrl}${appBasePath || "/"}`);
4125
+ const fetchPath = async (path, init2 = {}) => {
4126
+ const url = new URL(joinUrlPath(appBasePath, path), hostedUrl);
4127
+ const response = await fetch(url, {
4128
+ method: init2.method ?? "GET",
4129
+ headers: init2.headers,
4130
+ body: init2.body
4131
+ });
4132
+ const body = await response.text();
4133
+ const headers = {};
4134
+ response.headers.forEach((value, key) => {
4135
+ headers[key] = value;
4136
+ });
4137
+ return { status: response.status, headers, body };
4138
+ };
4139
+ return {
4140
+ url: hostedUrl,
4141
+ port: address.port,
4142
+ hostedUrl,
4143
+ appBasePath,
4144
+ get packageContext() {
4145
+ return contextFor(active?.client ?? null);
4146
+ },
4147
+ fetchPath,
4148
+ status,
4149
+ close
4150
+ };
4151
+ }
4152
+ function elapsed(started) {
4153
+ return Math.round(performance.now() - started);
4154
+ }
4155
+ function toBuildFailure(error) {
4156
+ if (error instanceof BundleError) {
4157
+ return { message: error.message, diagnostics: error.diagnostics };
4158
+ }
4159
+ return {
4160
+ message: redact(error instanceof Error ? error.message : String(error)),
4161
+ diagnostics: []
4162
+ };
4163
+ }
4164
+ function buildErrorView(failure) {
4165
+ const [first] = failure.diagnostics;
4166
+ return {
4167
+ kind: "build",
4168
+ title: first ? `${first.file ?? "bundle"}${first.line !== null ? `:${first.line}:${first.col}` : ""} ${first.message}` : failure.message.split("\n")[0] ?? "Build failed",
4169
+ detail: failure.diagnostics.length > 0 ? failure.diagnostics.map(formatBundleDiagnostic).join("\n\n") : failure.message
4170
+ };
4171
+ }
4172
+ async function readStream(stream) {
4173
+ const chunks = [];
4174
+ for await (const chunk of stream) {
4175
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
4176
+ }
4177
+ return Buffer.concat(chunks).toString("utf8");
4178
+ }
4179
+ async function writeWorkerFiles(input) {
4180
+ await mkdir2(input.workDir, { recursive: true });
4181
+ const packageGraph = await resolveLocalPackageGraph({
4182
+ code: input.code,
4183
+ apiUrl: input.apiUrl,
4184
+ token: input.token,
4185
+ ...input.org ? { org: input.org } : {},
4186
+ fetchFn: input.fetchFn,
4187
+ ...input.depResolve ? { depResolve: input.depResolve } : {},
4188
+ ...input.packageRoot ? { packageRoot: input.packageRoot } : {},
4189
+ onStatus: input.onStatus
4190
+ });
4191
+ const files = { entry: "entry.js", user: "main.js", runtime: "runtime.js" };
4192
+ let packageModules = await writePackageModuleFiles(
4193
+ input.workDir,
4194
+ packageGraph,
4195
+ writeFile3,
4196
+ join7
4197
+ );
4198
+ let gatewayFetchShimModules = packageGraph.modules.map((module) => module.name).filter((name) => name === localExecuteGatewayFetchShimModuleName);
4199
+ if (input.mockFetchGateway) {
4200
+ const installed = await installMockFetchShimModules({
4201
+ workDir: input.workDir,
4202
+ packageModules
4203
+ });
4204
+ packageModules = installed.packageModules;
4205
+ gatewayFetchShimModules = installed.sideEffectModules;
4206
+ }
4207
+ await writeFile3(
4208
+ join7(input.workDir, files.entry),
4209
+ createPackageAppEntrySource({ sideEffectModules: gatewayFetchShimModules })
4210
+ );
4211
+ await writeFile3(join7(input.workDir, files.user), input.code);
4212
+ await writeFile3(
4213
+ join7(input.workDir, files.runtime),
4214
+ createPackageLocalRuntimeModuleSource({
4215
+ packageContext: input.packageContext,
4216
+ mockStorage: input.mockStorage
4217
+ })
4218
+ );
4219
+ await writeFile3(
4220
+ join7(input.workDir, localWorkerModuleNames.runtimeFlatAlias),
4221
+ createRuntimeFlatAliasSource()
4222
+ );
4223
+ await writeFile3(
4224
+ join7(input.workDir, "config.capnp"),
4225
+ createWorkerdConfig({
4226
+ bridgePort: input.bridgePort,
4227
+ files,
4228
+ packageModules,
4229
+ allowPrivateNetwork: input.allowPrivateNetwork
4230
+ })
4231
+ );
4232
+ }
4233
+ function normalizeBasePath(value) {
4234
+ const trimmed = value.trim();
4235
+ if (!trimmed || trimmed === "/") return "";
4236
+ const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
4237
+ return withSlash.replace(/\/+$/, "");
4238
+ }
4239
+ function stripMount(pathname, appBasePath) {
4240
+ if (!appBasePath) return pathname || "/";
4241
+ if (pathname === appBasePath) return "/";
4242
+ if (pathname.startsWith(`${appBasePath}/`)) {
4243
+ return pathname.slice(appBasePath.length) || "/";
4244
+ }
4245
+ return pathname || "/";
4246
+ }
4247
+ function joinUrlPath(base, path) {
4248
+ const rest = path.startsWith("/") ? path : `/${path}`;
4249
+ if (!base) return rest;
4250
+ return `${base}${rest === "/" ? "" : rest}` || base;
4251
+ }
4252
+
4253
+ // src/dev-command.ts
4254
+ async function resolveDevAuth(input) {
4255
+ if (input.target !== "mock") {
4256
+ return {
4257
+ token: input.token,
4258
+ apiUrl: input.apiUrl,
4259
+ ...input.org ? { org: input.org } : {},
4260
+ ...input.passthroughHosts?.length ? { passthroughHosts: input.passthroughHosts } : {}
4261
+ };
4262
+ }
4263
+ const ensured = await ensureMockTarget({
4264
+ sessionId: input.sessionId,
4265
+ resetStorage: input.resetStorage,
4266
+ packageId: input.packageId,
4267
+ orgSlug: input.orgSlug ?? input.org
4268
+ });
4269
+ let mockClosed = false;
4270
+ return {
4271
+ token: ensured.token,
4272
+ apiUrl: ensured.apiUrl,
4273
+ ...input.org ? { org: input.org } : {},
4274
+ ...input.depResolve ? { depResolve: input.depResolve } : {},
4275
+ ...input.passthroughHosts?.length ? { passthroughHosts: input.passthroughHosts } : {},
4276
+ mockServer: ensured.server,
4277
+ closeMock: ensured.started ? async () => {
4278
+ if (mockClosed) return;
4279
+ mockClosed = true;
4280
+ await ensured.server.close();
4281
+ } : void 0
4282
+ };
4283
+ }
4284
+ async function runDevServe(input) {
4285
+ const manifest = await loadPackageManifest(input.cwd);
4286
+ if (input.port === void 0) {
4287
+ const running = await findRunningDevServer({ root: manifest.root, target: input.target });
4288
+ if (running) {
4289
+ const { registration } = running;
4290
+ throw new StructuredCliError({
4291
+ code: "dev_already_running",
4292
+ target: input.target,
4293
+ message: `kody dev is already running for ${manifest.name} at ${registration.origin}${registration.basePath || "/"} (pid ${registration.pid}).`,
4294
+ fix: `Reuse it (\`kody dev fetch <path>\` attaches automatically), stop it with \`kill ${registration.pid}\`, or pass --port to start a second server.`
4295
+ });
4296
+ }
4297
+ }
4298
+ const onEvent = input.json ? (event) => writeJsonEvent(input.io, event) : (event) => writeDevEvent(input.io, event);
4299
+ let registered = false;
4300
+ let server;
4301
+ try {
4302
+ server = await startPackageAppDev({
4303
+ manifest,
4304
+ token: input.auth.token,
4305
+ apiUrl: input.auth.apiUrl,
4306
+ target: input.target,
4307
+ port: input.port,
4308
+ defaultPort: defaultDevPort(manifest.kodyId),
4309
+ appBasePath: input.appBasePath,
4310
+ ...input.auth.org ? { org: input.auth.org } : {},
4311
+ ...input.auth.depResolve ? { depResolve: input.auth.depResolve } : {},
4312
+ ...input.passthroughHosts?.length ? { passthroughHosts: input.passthroughHosts } : input.auth.passthroughHosts?.length ? { passthroughHosts: input.auth.passthroughHosts } : {},
4313
+ allowPrivateNetwork: input.allowPrivateNetwork,
4314
+ liveReload: input.liveReload ?? true,
4315
+ onStatus: (message) => input.io.stderr(`${message}
4316
+ `),
4317
+ onError: (message) => input.io.stderr(`${message}
4318
+ `),
4319
+ onEvent,
4320
+ // Register as soon as the port is bound so a second `kody dev`
4321
+ // during the first build hits `dev_already_running` instead of
4322
+ // stealing the next free port and overwriting the registry.
4323
+ // Explicit `--port` starts a second server on purpose — leave the
4324
+ // primary attach registry alone so fetch keeps talking to it.
4325
+ onListening: async ({ port, hostedUrl, appBasePath }) => {
4326
+ if (input.port !== void 0) return;
4327
+ await writeDevRegistration({
4328
+ pid: process.pid,
4329
+ origin: hostedUrl,
4330
+ port,
4331
+ basePath: appBasePath,
4332
+ target: input.target,
4333
+ root: manifest.root
4334
+ });
4335
+ registered = true;
4336
+ }
4337
+ });
4338
+ } catch (error) {
4339
+ if (registered) {
4340
+ await removeDevRegistration(manifest.root, process.pid, input.target).catch(() => {
4341
+ });
4342
+ }
4343
+ await input.auth.closeMock?.();
4344
+ throw error;
4345
+ }
4346
+ const shutdown = async () => {
4347
+ await server.close();
4348
+ await removeDevRegistration(manifest.root, process.pid, input.target).catch(() => {
4349
+ });
4350
+ if (input.readyFile) await removeOwnedReadyFile(input.readyFile, process.pid);
4351
+ await input.auth.closeMock?.();
4352
+ };
4353
+ try {
4354
+ const status = server.status();
4355
+ const statusUrl = `${server.hostedUrl}${devStatusPath}`;
4356
+ const ready = {
4357
+ url: status.url,
4358
+ port: server.port,
4359
+ basePath: server.appBasePath,
4360
+ pid: process.pid,
4361
+ statusUrl
4362
+ };
4363
+ if (input.readyFile) {
4364
+ await mkdir3(dirname3(input.readyFile), { recursive: true });
4365
+ await writeFile4(input.readyFile, `${JSON.stringify(ready, null, 2)}
4366
+ `);
4367
+ }
4368
+ if (input.json) {
4369
+ input.io.stdout(
4370
+ `${JSON.stringify({
4371
+ type: "ready",
4372
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
4373
+ ...ready,
4374
+ target: input.target,
4375
+ package: status.package,
4376
+ buildId: status.buildId,
4377
+ state: status.state
4378
+ })}
4379
+ `
4380
+ );
4381
+ } else {
4382
+ input.io.stdout(
4383
+ `kody dev listening on ${status.url}
4384
+ target: ${input.target}
4385
+ package: ${manifest.name} (${manifest.kodyId})
4386
+ status: ${statusUrl}
4387
+ Agents: kody dev fetch /path | job <name> | webhook <name> --body file.json | emit <event> --body file.json | check
4388
+ `
4389
+ );
4390
+ }
4391
+ } catch (error) {
4392
+ await shutdown().catch(() => {
4393
+ });
4394
+ throw error;
4395
+ }
4396
+ if (input.serveOnce) {
4397
+ await shutdown();
4398
+ return 0;
4399
+ }
4400
+ await new Promise((resolveWait) => {
4401
+ const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
4402
+ const stop = async () => {
4403
+ for (const signal of signals) process.off(signal, onSig);
4404
+ await shutdown();
4405
+ resolveWait();
4406
+ };
4407
+ const onSig = () => {
4408
+ void stop();
4409
+ };
4410
+ for (const signal of signals) process.on(signal, onSig);
4411
+ });
4412
+ return 0;
4413
+ }
4414
+ async function tryAttachedDevFetch(input) {
4415
+ let root;
4416
+ try {
4417
+ root = (await loadPackageManifest(input.cwd)).root;
4418
+ } catch {
4419
+ return null;
4420
+ }
4421
+ const running = await findRunningDevServer({ root, target: input.target });
4422
+ if (!running) return null;
4423
+ const { registration } = running;
4424
+ const rest = input.path.startsWith("/") ? input.path : `/${input.path}`;
4425
+ const url = new URL(
4426
+ `${registration.basePath}${rest === "/" && registration.basePath ? "" : rest}` || "/",
4427
+ registration.origin
4428
+ );
4429
+ input.io.stderr(`Attached to running kody dev (pid ${registration.pid}) at ${registration.origin}
4430
+ `);
4431
+ const response = await fetch(url, {
4432
+ method: input.method ?? "GET",
4433
+ headers: input.body ? { "content-type": "application/json" } : void 0,
4434
+ body: input.body
4435
+ });
4436
+ const body = await response.text();
4437
+ const headers = {};
4438
+ response.headers.forEach((value, key) => {
4439
+ headers[key] = value;
4440
+ });
4441
+ const result = { status: response.status, headers, body };
4442
+ if (input.json) {
4443
+ input.io.stdout(`${JSON.stringify(result, null, 2)}
4444
+ `);
4445
+ } else {
4446
+ input.io.stdout(`HTTP ${result.status}
4447
+ ${result.body}
4448
+ `);
4449
+ }
4450
+ return result.status >= 400 ? 1 : 0;
4451
+ }
4452
+ async function runDevFetch(input) {
4453
+ let server;
4454
+ try {
4455
+ const manifest = await loadPackageManifest(input.cwd);
4456
+ server = await startPackageAppDev({
4457
+ manifest,
4458
+ token: input.auth.token,
4459
+ apiUrl: input.auth.apiUrl,
4460
+ target: input.target,
4461
+ port: input.port,
4462
+ appBasePath: input.appBasePath,
4463
+ ...input.auth.org ? { org: input.auth.org } : {},
4464
+ ...input.auth.depResolve ? { depResolve: input.auth.depResolve } : {},
4465
+ ...input.auth.passthroughHosts?.length ? { passthroughHosts: input.auth.passthroughHosts } : {},
4466
+ allowPrivateNetwork: input.allowPrivateNetwork,
4467
+ watch: false,
4468
+ onStatus: (message) => input.io.stderr(`${message}
4469
+ `),
4470
+ onError: (message) => input.io.stderr(`${message}
4471
+ `),
4472
+ onEvent: (event) => {
4473
+ if (event.type === "log" || event.type === "runtime_error") {
4474
+ input.io.stderr(`${formatDevEvent(event).text}
4475
+ `);
4476
+ }
4477
+ }
4478
+ });
4479
+ } catch (error) {
4480
+ await input.auth.closeMock?.();
4481
+ if (input.json) {
4482
+ const message = error instanceof Error ? error.message : String(error);
4483
+ input.io.stdout(
4484
+ `${JSON.stringify({ type: "build_error", message, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)}
4485
+ `
4486
+ );
4487
+ }
4488
+ throw error;
4489
+ }
4490
+ try {
4491
+ const result = await server.fetchPath(input.path, {
4492
+ method: input.method,
4493
+ body: input.body,
4494
+ headers: input.body ? { "content-type": "application/json" } : void 0
4495
+ });
4496
+ if (input.json) {
4497
+ input.io.stdout(`${JSON.stringify(result, null, 2)}
4498
+ `);
4499
+ } else {
4500
+ input.io.stdout(`HTTP ${result.status}
4501
+ ${result.body}
4502
+ `);
4503
+ }
4504
+ return result.status >= 400 ? 1 : 0;
4505
+ } finally {
4506
+ await server.close();
4507
+ await input.auth.closeMock?.();
4508
+ }
4509
+ }
4510
+ async function runDevJob(input) {
4511
+ const manifest = await loadPackageManifest(input.cwd);
4512
+ const job = manifest.jobs[input.jobName];
4513
+ if (!job) {
4514
+ throw new StructuredCliError({
4515
+ code: "dev_surface_missing",
4516
+ message: `No job named ${JSON.stringify(input.jobName)}.`,
4517
+ where: manifest.packageJsonPath,
4518
+ fix: `Known jobs: ${Object.keys(manifest.jobs).join(", ") || "(none)"}.`,
4519
+ target: input.target
4520
+ });
4521
+ }
4522
+ const modulePath = resolvePackagePath(manifest, job.entry);
4523
+ if (input.dryRun) {
4524
+ return printDevDryRun({
4525
+ target: input.target,
4526
+ surface: `job:${input.jobName}`,
4527
+ modulePath,
4528
+ params: void 0,
4529
+ extra: {
4530
+ schedule: job.schedule,
4531
+ scheduleRaw: job.scheduleRaw,
4532
+ timezone: job.timezone ?? null,
4533
+ enabled: job.enabled ?? null
4534
+ },
4535
+ json: input.json,
4536
+ io: input.io,
4537
+ closeMock: input.auth.closeMock
4538
+ });
4539
+ }
4540
+ return await runPackageModuleOnce({
4541
+ manifest,
4542
+ modulePath,
4543
+ params: void 0,
4544
+ target: input.target,
4545
+ auth: input.auth,
4546
+ json: input.json,
4547
+ allowPrivateNetwork: input.allowPrivateNetwork,
4548
+ io: input.io,
4549
+ surface: `job:${input.jobName}`
4550
+ });
4551
+ }
4552
+ async function runDevWebhook(input) {
4553
+ const manifest = await loadPackageManifest(input.cwd);
4554
+ const webhook = manifest.webhooks[input.webhookName];
4555
+ if (!webhook) {
4556
+ throw new StructuredCliError({
4557
+ code: "dev_surface_missing",
4558
+ message: `No webhook named ${JSON.stringify(input.webhookName)}.`,
4559
+ where: manifest.packageJsonPath,
4560
+ fix: `Known webhooks: ${Object.keys(manifest.webhooks).join(", ") || "(none)"}.`,
4561
+ target: input.target
4562
+ });
4563
+ }
4564
+ const rawBody = await readFile4(resolve7(input.cwd ?? process.cwd(), input.bodyPath), "utf8");
4565
+ let jsonBody = null;
4566
+ try {
4567
+ jsonBody = JSON.parse(rawBody);
4568
+ } catch {
4569
+ jsonBody = null;
4570
+ }
4571
+ const params = webhook.inputMode === "params" ? jsonBody ?? {} : {
4572
+ webhook: {
4573
+ packageKodyId: manifest.kodyId,
4574
+ name: input.webhookName,
4575
+ receivedAt: (/* @__PURE__ */ new Date()).toISOString()
4576
+ },
4577
+ request: {
4578
+ method: "POST",
4579
+ contentType: "application/json",
4580
+ headers: { "content-type": "application/json" },
4581
+ body: rawBody,
4582
+ json: jsonBody
4583
+ },
4584
+ synthetic: true
4585
+ };
4586
+ const modulePath = resolveExportModulePath(manifest, webhook.export);
4587
+ if (input.dryRun) {
4588
+ return printDevDryRun({
4589
+ target: input.target,
4590
+ surface: `webhook:${input.webhookName}`,
4591
+ modulePath,
4592
+ params,
4593
+ extra: { export: webhook.export, bodyPath: input.bodyPath },
4594
+ json: input.json,
4595
+ io: input.io,
4596
+ closeMock: input.auth.closeMock
4597
+ });
4598
+ }
4599
+ return await runPackageModuleOnce({
4600
+ manifest,
4601
+ modulePath,
4602
+ params,
4603
+ target: input.target,
4604
+ auth: input.auth,
4605
+ json: input.json,
4606
+ allowPrivateNetwork: input.allowPrivateNetwork,
4607
+ io: input.io,
4608
+ surface: `webhook:${input.webhookName}`
4609
+ });
4610
+ }
4611
+ async function runDevEmit(input) {
4612
+ const manifest = await loadPackageManifest(input.cwd);
4613
+ const subscription = manifest.subscriptions[input.event];
4614
+ if (!subscription) {
4615
+ if (input.target !== "mock") {
4616
+ throw new StructuredCliError({
4617
+ code: "dev_surface_missing",
4618
+ message: `No subscription for event ${JSON.stringify(input.event)}.`,
4619
+ where: manifest.packageJsonPath,
4620
+ fix: `Known subscriptions: ${Object.keys(manifest.subscriptions).join(", ") || "(none)"}. On --target mock you can still declare the handler first.`,
4621
+ target: input.target
4622
+ });
4623
+ }
4624
+ throw new StructuredCliError({
4625
+ code: "dev_surface_missing",
4626
+ message: `No subscription for event ${JSON.stringify(input.event)} in package.json#kody.subscriptions.`,
4627
+ where: manifest.packageJsonPath,
4628
+ fix: `Add a handler under kody.subscriptions[${JSON.stringify(input.event)}], then retry. Mock allows any event type once declared.`,
4629
+ target: input.target
4630
+ });
4631
+ }
4632
+ const rawBody = await readFile4(resolve7(input.cwd ?? process.cwd(), input.bodyPath), "utf8");
4633
+ let envelope;
4634
+ try {
4635
+ const parsed = JSON.parse(rawBody);
4636
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
4637
+ throw new Error("body must be a JSON object");
4638
+ }
4639
+ envelope = { ...parsed };
4640
+ } catch (error) {
4641
+ throw new StructuredCliError({
4642
+ code: "package_manifest_invalid",
4643
+ message: `Could not parse event body ${input.bodyPath} as a JSON object.`,
4644
+ fix: "Pass --body event.json with the platform delivery envelope fields.",
4645
+ details: { cause: error instanceof Error ? error.message : String(error) },
4646
+ target: input.target
4647
+ });
4648
+ }
4649
+ if (typeof envelope.event !== "string") {
4650
+ envelope.event = input.event;
4651
+ }
4652
+ envelope.synthetic = true;
4653
+ if (envelope.idempotency_key === void 0) {
4654
+ envelope.idempotency_key = `synthetic:local:${Date.now()}`;
4655
+ }
4656
+ const modulePath = resolvePackagePath(manifest, subscription.handler);
4657
+ if (input.dryRun) {
4658
+ return printDevDryRun({
4659
+ target: input.target,
4660
+ surface: `subscription:${input.event}`,
4661
+ modulePath,
4662
+ params: envelope,
4663
+ extra: { handler: subscription.handler, bodyPath: input.bodyPath },
4664
+ json: input.json,
4665
+ io: input.io,
4666
+ closeMock: input.auth.closeMock
4667
+ });
4668
+ }
4669
+ return await runPackageModuleOnce({
4670
+ manifest,
4671
+ modulePath,
4672
+ params: envelope,
4673
+ target: input.target,
4674
+ auth: input.auth,
4675
+ json: input.json,
4676
+ allowPrivateNetwork: input.allowPrivateNetwork,
4677
+ io: input.io,
4678
+ surface: `subscription:${input.event}`
4679
+ });
4680
+ }
4681
+ async function runDevCheck(input) {
4682
+ const manifest = await loadPackageManifest(input.cwd);
4683
+ const checks = [];
4684
+ const credentialSignals = [];
4685
+ const push = (name, ok, detail) => {
4686
+ checks.push({ name, ok, detail });
4687
+ };
4688
+ const bundleAndScan = async (label, modulePath) => {
4689
+ try {
4690
+ const bundled = await bundleLocalUserModule(modulePath);
4691
+ push(label, true, label.startsWith("app.entry") ? modulePath : void 0);
4692
+ credentialSignals.push(...await detectCredentialedFetchInSource(bundled, label));
4693
+ } catch (error) {
4694
+ push(label, false, error instanceof Error ? error.message : String(error));
4695
+ }
4696
+ };
4697
+ push("package.json", true, manifest.name);
4698
+ push("kody.id", Boolean(manifest.kodyId), manifest.kodyId);
4699
+ try {
4700
+ await readFile4(resolve7(manifest.root, "README.md"));
4701
+ push("README.md", true);
4702
+ } catch {
4703
+ push("README.md", false, "Publish requires README.md");
4704
+ }
4705
+ try {
4706
+ await readFile4(resolve7(manifest.root, "AGENTS.md"));
4707
+ push("AGENTS.md", true);
4708
+ } catch {
4709
+ push("AGENTS.md", false, "Publish requires AGENTS.md");
4710
+ }
4711
+ if (manifest.app?.entry) {
4712
+ await bundleAndScan(
4713
+ "app.entry bundle",
4714
+ resolvePackagePath(manifest, manifest.app.entry)
4715
+ );
4716
+ } else {
4717
+ push("app.entry", true, "none (ok)");
4718
+ }
4719
+ for (const [name, job] of Object.entries(manifest.jobs)) {
4720
+ await bundleAndScan(`job:${name}`, resolvePackagePath(manifest, job.entry));
4721
+ }
4722
+ for (const [name, webhook] of Object.entries(manifest.webhooks)) {
4723
+ await bundleAndScan(
4724
+ `webhook:${name}`,
4725
+ resolveExportModulePath(manifest, webhook.export)
4726
+ );
4727
+ }
4728
+ for (const [topic, sub] of Object.entries(manifest.subscriptions)) {
4729
+ await bundleAndScan(
4730
+ `subscription:${topic}`,
4731
+ resolvePackagePath(manifest, sub.handler)
4732
+ );
4733
+ }
4734
+ for (const [key, rel] of Object.entries(manifest.exports)) {
4735
+ await bundleAndScan(`export:${key}`, resolvePackagePath(manifest, rel));
4736
+ }
4737
+ let hasMocksFile = false;
4738
+ try {
4739
+ await access(join8(manifest.root, packageMocksRelativePath));
4740
+ hasMocksFile = true;
4741
+ } catch {
4742
+ hasMocksFile = false;
4743
+ }
4744
+ const mocksDetail = mocksSuggestionDetail({
4745
+ signals: credentialSignals,
4746
+ hasMocksFile
4747
+ });
4748
+ if (mocksDetail) {
4749
+ push(packageMocksRelativePath, true, mocksDetail);
4750
+ }
4751
+ const failed = checks.filter((check) => !check.ok);
4752
+ if (input.json) {
4753
+ input.io.stdout(
4754
+ `${JSON.stringify(
4755
+ {
4756
+ target: input.target,
4757
+ checks,
4758
+ ok: failed.length === 0,
4759
+ ...credentialSignals.length > 0 ? {
4760
+ credentialedFetch: {
4761
+ detected: true,
4762
+ hasMocksFile,
4763
+ signals: credentialSignals
4764
+ }
4765
+ } : {}
4766
+ },
4767
+ null,
4768
+ 2
4769
+ )}
4770
+ `
4771
+ );
4772
+ } else {
4773
+ for (const check of checks) {
4774
+ const mark = check.ok ? "ok" : "FAIL";
4775
+ input.io.stdout(
4776
+ `${mark.padEnd(4)} ${check.name}${check.detail ? ` \u2014 ${check.detail}` : ""}
4777
+ `
4778
+ );
4779
+ }
4780
+ input.io.stdout(
4781
+ failed.length === 0 ? `kody dev check passed (${checks.length} checks, target ${input.target})
4782
+ ` : `kody dev check failed: ${failed.length}/${checks.length}
4783
+ `
4784
+ );
4785
+ }
4786
+ return failed.length === 0 ? 0 : 1;
4787
+ }
4788
+ async function runPackageModuleOnce(input) {
4789
+ const packageContext = buildLocalPackageContext({
4790
+ kodyId: input.manifest.kodyId,
4791
+ hostedUrl: input.auth.apiUrl.startsWith("http") ? "http://127.0.0.1:0" : "http://127.0.0.1:0",
4792
+ appBasePath: ""
4793
+ });
4794
+ try {
4795
+ const result = await runLocalPackageModule({
4796
+ modulePath: input.modulePath,
4797
+ params: input.params,
4798
+ token: input.auth.token,
4799
+ apiUrl: input.auth.apiUrl,
4800
+ target: input.target,
4801
+ packageContext,
4802
+ packageRoot: input.manifest.root,
4803
+ ...input.auth.org ? { org: input.auth.org } : {},
4804
+ ...input.auth.depResolve ? { depResolve: input.auth.depResolve } : {},
4805
+ ...input.auth.passthroughHosts?.length ? { passthroughHosts: input.auth.passthroughHosts } : {},
4806
+ allowPrivateNetwork: input.allowPrivateNetwork,
4807
+ onStatus: (message) => input.io.stderr(`${message}
4808
+ `)
4809
+ });
4810
+ input.io.stdout(formatToolResult(result, input.json === true));
4811
+ return result.isError ? 1 : 0;
4812
+ } finally {
4813
+ await input.auth.closeMock?.();
4814
+ }
4815
+ }
4816
+ async function printDevDryRun(input) {
4817
+ try {
4818
+ const plan = {
4819
+ dryRun: true,
4820
+ wouldInvoke: true,
4821
+ target: input.target,
4822
+ surface: input.surface,
4823
+ modulePath: input.modulePath,
4824
+ params: input.params ?? null,
4825
+ ...input.extra ?? {},
4826
+ note: input.target === "prod" ? "No module run and no prod side effects. Drop --dry-run to invoke once against prod CapabilityProxy." : "No module run. Drop --dry-run to invoke against the selected target."
4827
+ };
4828
+ if (input.json) {
4829
+ input.io.stdout(`${JSON.stringify(plan, null, 2)}
4830
+ `);
4831
+ } else {
4832
+ input.io.stdout(
4833
+ `dry-run: would invoke ${input.surface} on --target ${input.target}
4834
+ module: ${input.modulePath}
4835
+ params: ${JSON.stringify(input.params ?? null, null, 2)}
4836
+ ` + (input.extra ? `detail: ${JSON.stringify(input.extra, null, 2)}
4837
+ ` : "") + `${plan.note}
4838
+ `
4839
+ );
4840
+ }
4841
+ return 0;
4842
+ } finally {
4843
+ await input.closeMock?.();
4844
+ }
4845
+ }
4846
+ function writeJsonEvent(io, event) {
4847
+ io.stdout(`${JSON.stringify({ ...event, ts: (/* @__PURE__ */ new Date()).toISOString() })}
4848
+ `);
4849
+ }
4850
+ function writeDevEvent(io, event) {
4851
+ const { stream, text } = formatDevEvent(event);
4852
+ io[stream](`${text}
4853
+ `);
4854
+ }
4855
+ function parseDevSubcommand(positionals) {
4856
+ const raw = positionals[0];
4857
+ if (!raw || raw.startsWith("-")) {
4858
+ return { subcommand: "serve", rest: positionals };
4859
+ }
4860
+ switch (raw) {
4861
+ case "serve":
4862
+ case "fetch":
4863
+ case "job":
4864
+ case "webhook":
4865
+ case "emit":
4866
+ case "check":
4867
+ return { subcommand: raw, rest: positionals.slice(1) };
4868
+ default:
4869
+ throw new Error(
4870
+ `Unknown kody dev subcommand ${JSON.stringify(raw)}. Use serve | fetch | job | webhook | emit | check.`
4871
+ );
4872
+ }
4873
+ }
4874
+ async function removeOwnedReadyFile(path, ownerPid) {
4875
+ try {
4876
+ const parsed = JSON.parse(await readFile4(path, "utf8"));
4877
+ if (parsed.pid !== ownerPid) return;
4878
+ await rm4(path, { force: true });
4879
+ } catch {
4880
+ }
4881
+ }
4882
+ export {
4883
+ parseDevPort,
4884
+ parseDevSubcommand,
4885
+ removeOwnedReadyFile,
4886
+ resolveDevAuth,
4887
+ runDevCheck,
4888
+ runDevEmit,
4889
+ runDevFetch,
4890
+ runDevJob,
4891
+ runDevServe,
4892
+ runDevWebhook,
4893
+ tryAttachedDevFetch
4894
+ };
4895
+ /*! Bundled license information:
4896
+
4897
+ chokidar/esm/index.js:
4898
+ (*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
4899
+ */
4900
+ //# sourceMappingURL=dev-command-3LX234N6.js.map