vector-framework 1.2.1 → 1.2.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 (190) hide show
  1. package/README.md +18 -6
  2. package/dist/auth/protected.d.ts +4 -4
  3. package/dist/auth/protected.d.ts.map +1 -1
  4. package/dist/auth/protected.js +10 -7
  5. package/dist/auth/protected.js.map +1 -1
  6. package/dist/cache/manager.d.ts +2 -0
  7. package/dist/cache/manager.d.ts.map +1 -1
  8. package/dist/cache/manager.js +21 -4
  9. package/dist/cache/manager.js.map +1 -1
  10. package/dist/checkpoint/artifacts/compressor.d.ts +5 -0
  11. package/dist/checkpoint/artifacts/compressor.d.ts.map +1 -0
  12. package/dist/checkpoint/artifacts/compressor.js +24 -0
  13. package/dist/checkpoint/artifacts/compressor.js.map +1 -0
  14. package/dist/checkpoint/artifacts/decompress-worker.d.ts +2 -0
  15. package/dist/checkpoint/artifacts/decompress-worker.d.ts.map +1 -0
  16. package/dist/checkpoint/artifacts/decompress-worker.js +31 -0
  17. package/dist/checkpoint/artifacts/decompress-worker.js.map +1 -0
  18. package/dist/checkpoint/artifacts/hasher.d.ts +2 -0
  19. package/dist/checkpoint/artifacts/hasher.d.ts.map +1 -0
  20. package/dist/checkpoint/artifacts/hasher.js +7 -0
  21. package/dist/checkpoint/artifacts/hasher.js.map +1 -0
  22. package/dist/checkpoint/artifacts/manifest.d.ts +6 -0
  23. package/dist/checkpoint/artifacts/manifest.d.ts.map +1 -0
  24. package/dist/checkpoint/artifacts/manifest.js +55 -0
  25. package/dist/checkpoint/artifacts/manifest.js.map +1 -0
  26. package/dist/checkpoint/artifacts/materializer.d.ts +16 -0
  27. package/dist/checkpoint/artifacts/materializer.d.ts.map +1 -0
  28. package/dist/checkpoint/artifacts/materializer.js +168 -0
  29. package/dist/checkpoint/artifacts/materializer.js.map +1 -0
  30. package/dist/checkpoint/artifacts/packager.d.ts +12 -0
  31. package/dist/checkpoint/artifacts/packager.d.ts.map +1 -0
  32. package/dist/checkpoint/artifacts/packager.js +82 -0
  33. package/dist/checkpoint/artifacts/packager.js.map +1 -0
  34. package/dist/checkpoint/artifacts/repository.d.ts +11 -0
  35. package/dist/checkpoint/artifacts/repository.d.ts.map +1 -0
  36. package/dist/checkpoint/artifacts/repository.js +29 -0
  37. package/dist/checkpoint/artifacts/repository.js.map +1 -0
  38. package/dist/checkpoint/artifacts/store.d.ts +13 -0
  39. package/dist/checkpoint/artifacts/store.d.ts.map +1 -0
  40. package/dist/checkpoint/artifacts/store.js +85 -0
  41. package/dist/checkpoint/artifacts/store.js.map +1 -0
  42. package/dist/checkpoint/artifacts/types.d.ts +21 -0
  43. package/dist/checkpoint/artifacts/types.d.ts.map +1 -0
  44. package/dist/checkpoint/artifacts/types.js +2 -0
  45. package/dist/checkpoint/artifacts/types.js.map +1 -0
  46. package/dist/checkpoint/artifacts/worker-decompressor.d.ts +17 -0
  47. package/dist/checkpoint/artifacts/worker-decompressor.d.ts.map +1 -0
  48. package/dist/checkpoint/artifacts/worker-decompressor.js +148 -0
  49. package/dist/checkpoint/artifacts/worker-decompressor.js.map +1 -0
  50. package/dist/checkpoint/asset-store.d.ts +10 -0
  51. package/dist/checkpoint/asset-store.d.ts.map +1 -0
  52. package/dist/checkpoint/asset-store.js +46 -0
  53. package/dist/checkpoint/asset-store.js.map +1 -0
  54. package/dist/checkpoint/bundler.d.ts +15 -0
  55. package/dist/checkpoint/bundler.d.ts.map +1 -0
  56. package/dist/checkpoint/bundler.js +45 -0
  57. package/dist/checkpoint/bundler.js.map +1 -0
  58. package/dist/checkpoint/cli.d.ts +2 -0
  59. package/dist/checkpoint/cli.d.ts.map +1 -0
  60. package/dist/checkpoint/cli.js +157 -0
  61. package/dist/checkpoint/cli.js.map +1 -0
  62. package/dist/checkpoint/entrypoint-generator.d.ts +17 -0
  63. package/dist/checkpoint/entrypoint-generator.d.ts.map +1 -0
  64. package/dist/checkpoint/entrypoint-generator.js +251 -0
  65. package/dist/checkpoint/entrypoint-generator.js.map +1 -0
  66. package/dist/checkpoint/forwarder.d.ts +6 -0
  67. package/dist/checkpoint/forwarder.d.ts.map +1 -0
  68. package/dist/checkpoint/forwarder.js +74 -0
  69. package/dist/checkpoint/forwarder.js.map +1 -0
  70. package/dist/checkpoint/gateway.d.ts +11 -0
  71. package/dist/checkpoint/gateway.d.ts.map +1 -0
  72. package/dist/checkpoint/gateway.js +30 -0
  73. package/dist/checkpoint/gateway.js.map +1 -0
  74. package/dist/checkpoint/ipc.d.ts +12 -0
  75. package/dist/checkpoint/ipc.d.ts.map +1 -0
  76. package/dist/checkpoint/ipc.js +96 -0
  77. package/dist/checkpoint/ipc.js.map +1 -0
  78. package/dist/checkpoint/manager.d.ts +20 -0
  79. package/dist/checkpoint/manager.d.ts.map +1 -0
  80. package/dist/checkpoint/manager.js +214 -0
  81. package/dist/checkpoint/manager.js.map +1 -0
  82. package/dist/checkpoint/process-manager.d.ts +35 -0
  83. package/dist/checkpoint/process-manager.d.ts.map +1 -0
  84. package/dist/checkpoint/process-manager.js +203 -0
  85. package/dist/checkpoint/process-manager.js.map +1 -0
  86. package/dist/checkpoint/resolver.d.ts +25 -0
  87. package/dist/checkpoint/resolver.d.ts.map +1 -0
  88. package/dist/checkpoint/resolver.js +95 -0
  89. package/dist/checkpoint/resolver.js.map +1 -0
  90. package/dist/checkpoint/socket-path.d.ts +2 -0
  91. package/dist/checkpoint/socket-path.d.ts.map +1 -0
  92. package/dist/checkpoint/socket-path.js +51 -0
  93. package/dist/checkpoint/socket-path.js.map +1 -0
  94. package/dist/checkpoint/types.d.ts +54 -0
  95. package/dist/checkpoint/types.d.ts.map +1 -0
  96. package/dist/checkpoint/types.js +2 -0
  97. package/dist/checkpoint/types.js.map +1 -0
  98. package/dist/cli/index.js +10 -2
  99. package/dist/cli/index.js.map +1 -1
  100. package/dist/cli/option-resolution.d.ts +1 -1
  101. package/dist/cli/option-resolution.d.ts.map +1 -1
  102. package/dist/cli/option-resolution.js.map +1 -1
  103. package/dist/cli.js +3817 -350
  104. package/dist/core/config-loader.d.ts +1 -0
  105. package/dist/core/config-loader.d.ts.map +1 -1
  106. package/dist/core/config-loader.js +10 -2
  107. package/dist/core/config-loader.js.map +1 -1
  108. package/dist/core/router.d.ts +24 -3
  109. package/dist/core/router.d.ts.map +1 -1
  110. package/dist/core/router.js +398 -249
  111. package/dist/core/router.js.map +1 -1
  112. package/dist/core/server.d.ts +3 -0
  113. package/dist/core/server.d.ts.map +1 -1
  114. package/dist/core/server.js +35 -10
  115. package/dist/core/server.js.map +1 -1
  116. package/dist/core/vector.d.ts +3 -0
  117. package/dist/core/vector.d.ts.map +1 -1
  118. package/dist/core/vector.js +51 -1
  119. package/dist/core/vector.js.map +1 -1
  120. package/dist/dev/route-scanner.d.ts.map +1 -1
  121. package/dist/dev/route-scanner.js +2 -1
  122. package/dist/dev/route-scanner.js.map +1 -1
  123. package/dist/errors/index.cjs +2 -0
  124. package/dist/http.d.ts +32 -7
  125. package/dist/http.d.ts.map +1 -1
  126. package/dist/http.js +144 -13
  127. package/dist/http.js.map +1 -1
  128. package/dist/index.cjs +2657 -0
  129. package/dist/index.d.ts +3 -2
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +12 -1433
  132. package/dist/index.js.map +1 -1
  133. package/dist/index.mjs +1301 -77
  134. package/dist/middleware/manager.d.ts +3 -3
  135. package/dist/middleware/manager.d.ts.map +1 -1
  136. package/dist/middleware/manager.js +9 -8
  137. package/dist/middleware/manager.js.map +1 -1
  138. package/dist/openapi/docs-ui.d.ts.map +1 -1
  139. package/dist/openapi/docs-ui.js +1097 -61
  140. package/dist/openapi/docs-ui.js.map +1 -1
  141. package/dist/openapi/generator.d.ts +2 -1
  142. package/dist/openapi/generator.d.ts.map +1 -1
  143. package/dist/openapi/generator.js +332 -16
  144. package/dist/openapi/generator.js.map +1 -1
  145. package/dist/types/index.d.ts +71 -28
  146. package/dist/types/index.d.ts.map +1 -1
  147. package/dist/types/index.js +24 -1
  148. package/dist/types/index.js.map +1 -1
  149. package/dist/utils/validation.d.ts.map +1 -1
  150. package/dist/utils/validation.js +3 -2
  151. package/dist/utils/validation.js.map +1 -1
  152. package/package.json +9 -14
  153. package/src/auth/protected.ts +11 -8
  154. package/src/cache/manager.ts +23 -4
  155. package/src/checkpoint/artifacts/compressor.ts +30 -0
  156. package/src/checkpoint/artifacts/decompress-worker.ts +49 -0
  157. package/src/checkpoint/artifacts/hasher.ts +6 -0
  158. package/src/checkpoint/artifacts/manifest.ts +72 -0
  159. package/src/checkpoint/artifacts/materializer.ts +211 -0
  160. package/src/checkpoint/artifacts/packager.ts +100 -0
  161. package/src/checkpoint/artifacts/repository.ts +36 -0
  162. package/src/checkpoint/artifacts/store.ts +102 -0
  163. package/src/checkpoint/artifacts/types.ts +24 -0
  164. package/src/checkpoint/artifacts/worker-decompressor.ts +192 -0
  165. package/src/checkpoint/asset-store.ts +61 -0
  166. package/src/checkpoint/bundler.ts +64 -0
  167. package/src/checkpoint/cli.ts +177 -0
  168. package/src/checkpoint/entrypoint-generator.ts +275 -0
  169. package/src/checkpoint/forwarder.ts +84 -0
  170. package/src/checkpoint/gateway.ts +40 -0
  171. package/src/checkpoint/ipc.ts +107 -0
  172. package/src/checkpoint/manager.ts +254 -0
  173. package/src/checkpoint/process-manager.ts +250 -0
  174. package/src/checkpoint/resolver.ts +124 -0
  175. package/src/checkpoint/socket-path.ts +61 -0
  176. package/src/checkpoint/types.ts +63 -0
  177. package/src/cli/index.ts +11 -2
  178. package/src/cli/option-resolution.ts +5 -1
  179. package/src/core/config-loader.ts +11 -2
  180. package/src/core/router.ts +505 -264
  181. package/src/core/server.ts +51 -11
  182. package/src/core/vector.ts +60 -1
  183. package/src/dev/route-scanner.ts +2 -1
  184. package/src/http.ts +219 -19
  185. package/src/index.ts +3 -2
  186. package/src/middleware/manager.ts +10 -10
  187. package/src/openapi/docs-ui.ts +1097 -61
  188. package/src/openapi/generator.ts +380 -13
  189. package/src/types/index.ts +83 -30
  190. package/src/utils/validation.ts +5 -3
package/dist/index.cjs ADDED
@@ -0,0 +1,2657 @@
1
+ // @bun @bun-cjs
2
+ (function(exports, require, module, __filename, __dirname) {var{defineProperty:me,getOwnPropertyNames:mr,getOwnPropertyDescriptor:br}=Object,ur=Object.prototype.hasOwnProperty;var We=new WeakMap,hr=(e)=>{var t=We.get(e),r;if(t)return t;if(t=me({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")mr(e).map((a)=>!ur.call(t,a)&&me(t,a,{get:()=>e[a],enumerable:!(r=br(e,a))||r.enumerable}));return We.set(e,t),t};var J=(e,t)=>{for(var r in t)me(e,r,{get:t[r],enumerable:!0,configurable:!0,set:(a)=>t[r]=()=>a})};var B=(e,t)=>()=>(e&&(t=e(e=0)),t);var He=1;function kt(e,t="gzip"){let r=new Uint8Array(e);switch(t){case"none":return r;case"gzip":return Bun.gzipSync(r);default:throw new Error(`Unsupported compression codec: ${t}`)}}var Et="gzip";function N(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),r=Bun.SHA256.hash(t),a=new Uint8Array(r.buffer,r.byteOffset,r.byteLength);return Buffer.from(a).toString("hex")}function ee(e){let t=Y(e).trim(),n=(Oe(t)?la(t):t).split("/").filter((i)=>i.length>0&&i!=="."&&i!=="..").join("/").replace(Bt,"_").replace(/^\/+/,"");if(n.length>0)return n;let o=Q.basename(t).replace(Bt,"_");return o.length>0?`external/${o}`:"external/asset.bin"}function Ct(e){return Y(e).replace(/^\/+/,"")}function Oe(e){let t=Y(e).trim();return Q.isAbsolute(t)||It.test(t)||Tt.test(e)}function Lt(e){let t=e.map((r)=>({type:r.type,logicalPath:r.logicalPath,contentHash:r.contentHash??r.hash,blobHash:r.blobHash??"",blobPath:r.blobPath??r.storedPath,codec:r.codec??"none",size:r.contentSize??r.size})).sort((r,a)=>`${r.type}:${r.logicalPath}:${r.contentHash}:${r.blobHash}`.localeCompare(`${a.type}:${a.logicalPath}:${a.contentHash}:${a.blobHash}`));return JSON.stringify(t)}function Y(e){return e.replace(/\\/g,"/")}function la(e){let t=Y(e);if(It.test(t))return t.replace(/^[a-zA-Z]:/,"").replace(/^\/+/,"");if(Tt.test(e))return Y(e).replace(/^\\\\[^\\]+\\[^\\]+/,"").replace(/^\/+/,"");return Y(Q.relative(process.cwd(),t))}var Q,Bt,It,Tt;var De=B(()=>{Q=require("path"),Bt=/[^a-zA-Z0-9._/-]/g,It=/^[a-zA-Z]:[\\/]/,Tt=/^\\\\[^\\]+\\[^\\]+/});class je{storageDir;codec;constructor(e,t={}){this.storageDir=e,this.codec=t.assetCodec??Et}async addEmbedded(e,t){return this.addAsset("embedded",e,t)}async addSidecar(e,t){return this.addAsset("sidecar",e,t)}async collect(e,t){let r=[];for(let a of e)r.push(await this.addEmbedded(a,a));for(let a of t)r.push(await this.addSidecar(a,a));return r}async addAsset(e,t,r){let a=await A.promises.readFile(r),n=new Uint8Array(a.buffer,a.byteOffset,a.byteLength),o=N(n),i=kt(n,this.codec),d=N(i),l=Ct(de.join(Nt,`${d}${this.codec==="gzip"?".gz":""}`)),c=de.join(this.storageDir,l);if(await A.promises.mkdir(de.join(this.storageDir,Nt),{recursive:!0}),!A.existsSync(c))await this.writeAtomically(c,i);else{let m=await A.promises.readFile(c),s=new Uint8Array(m.buffer,m.byteOffset,m.byteLength);if(N(s)!==d)await this.writeAtomically(c,i)}return{type:e,logicalPath:ee(t),storedPath:c,hash:o,size:a.byteLength,contentHash:o,contentSize:a.byteLength,blobHash:d,blobSize:i.byteLength,blobPath:l,codec:this.codec}}async writeAtomically(e,t){let r=`${e}.tmp.${process.pid}.${Date.now()}`;await A.promises.writeFile(r,t);try{await A.promises.rename(r,e)}catch(a){if(!sa(a))throw a;await A.promises.rm(e,{force:!0}),await A.promises.rename(r,e)}}}function sa(e){if(typeof e!=="object"||e===null||!("code"in e))return!1;let t=e.code;return t==="EEXIST"||t==="EPERM"}var A,de,Nt="_assets/blobs";var At=B(()=>{A=require("fs"),de=require("path");De()});class $e{artifactStore;constructor(e){this.artifactStore=new je(e)}async addEmbedded(e,t){let r=await Ht.promises.readFile(t);if(r.byteLength>St)throw new Error(`Embedded asset "${e}" is ${ie(r.byteLength)} \u2014 exceeds ${ie(St)} per-file budget. Use sidecar instead.`);return await this.artifactStore.addEmbedded(e,t)}async addSidecar(e,t){return await this.artifactStore.addSidecar(e,t)}async collect(e,t){let r=[];for(let a of e)r.push(await this.addEmbedded(a,a));for(let a of t)r.push(await this.addSidecar(a,a));return r}validateBudgets(e){let t=e.filter((r)=>r.type==="embedded").reduce((r,a)=>r+(a.contentSize??a.size),0);if(t>Rt)throw new Error(`Total embedded asset size ${ie(t)} exceeds ${ie(Rt)} budget.`)}}function ie(e){if(e<1024)return`${e} B`;if(e<1048576)return`${(e/1024).toFixed(1)} KB`;return`${(e/1048576).toFixed(1)} MB`}var Ht,St=65536,Rt=524288;var Ot=B(()=>{Ht=require("fs");At()});class Ue{async bundle(e){let t=e.outputFile??"checkpoint.js",r=await Bun.build({entrypoints:[e.entrypointPath],outdir:e.outputDir,target:"bun",format:"esm",minify:!0,naming:{entry:t}});if(!r.success){let n=r.logs.map((o)=>o.message??String(o)).join(`
3
+ `);throw new Error(`Checkpoint bundle failed:
4
+ ${n}`)}let a=Dt.join(e.outputDir,t);if(!_e.existsSync(a)){let n=r.outputs.find((o)=>o.kind==="entry-point");if(n){let o=n.path;if(_e.existsSync(o))return this.hashFile(o)}throw new Error(`Bundle output not found at expected path: ${a}`)}return this.hashFile(a)}async hashFile(e){let r=await Bun.file(e).arrayBuffer(),a=Bun.SHA256.hash(new Uint8Array(r)),n=new Uint8Array(a.buffer,a.byteOffset,a.byteLength),o=Buffer.from(n).toString("hex");return{outputPath:e,hash:o,size:r.byteLength}}}var _e,Dt;var jt=B(()=>{_e=require("fs"),Dt=require("path")});class Me{discoveredRoutes=[];async generate(e){let t=await this.scanRouteFiles(e.routesDir),r=this.buildSource(t,e),a=j.join(e.outputDir,"entrypoint.ts");return await V.promises.writeFile(a,r,"utf-8"),a}getDiscoveredRoutes(){return this.discoveredRoutes}async scanRouteFiles(e){if(!V.existsSync(e))return[];let t=[];return await this.walkDir(e,t),t}async walkDir(e,t){let r=await V.promises.readdir(e);for(let a of r){let n=j.join(e,a);if((await V.promises.stat(n)).isDirectory())await this.walkDir(n,t);else if((a.endsWith(".ts")||a.endsWith(".js"))&&!a.endsWith(".test.ts")&&!a.endsWith(".test.js")&&!a.endsWith(".spec.ts")&&!a.endsWith(".spec.js")&&!a.endsWith(".d.ts"))t.push(n)}}buildSource(e,t){this.discoveredRoutes=[];let r=[],a=[];for(let[n,o]of e.entries()){let i=`routeModule_${n}`,d=this.toImportSpecifier(o,t.outputDir);r.push(`import * as ${i} from ${JSON.stringify(d)};`),a.push(` registerModule(${i});`);let l=j.relative(t.routesDir,o).replace(/\.(ts|js)$/,"").split(j.sep).join("/");this.discoveredRoutes.push({method:"*",path:`/${l}`})}return`// Checkpoint entrypoint \u2014 auto-generated for version ${t.version}
5
+ // DO NOT EDIT: This file is generated by Vector checkpoint publish.
6
+
7
+ ${r.join(`
8
+ `)}
9
+
10
+ const socketPath = process.env.VECTOR_CHECKPOINT_SOCKET ?? '${t.socketPath}';
11
+ const checkpointContextHeader = 'x-vector-checkpoint-context';
12
+
13
+ // Route registration helper
14
+ type RouteDefinition = {
15
+ entry: { method: string; path: string };
16
+ options: { method: string; path: string; [key: string]: any };
17
+ handler: (ctx: any) => any;
18
+ };
19
+
20
+ function isRouteDefinition(value: unknown): value is RouteDefinition {
21
+ return (
22
+ value !== null &&
23
+ typeof value === 'object' &&
24
+ 'entry' in value &&
25
+ 'options' in value &&
26
+ 'handler' in value &&
27
+ typeof (value as any).handler === 'function'
28
+ );
29
+ }
30
+
31
+ const routeTable: Record<string, Record<string, (req: Request) => Response | Promise<Response>>> = {};
32
+
33
+ function parseCheckpointContext(req: Request): Record<string, unknown> {
34
+ const encoded = req.headers.get(checkpointContextHeader);
35
+ if (!encoded) {
36
+ return {};
37
+ }
38
+
39
+ try {
40
+ const json = Buffer.from(encoded, 'base64url').toString('utf-8');
41
+ const parsed = JSON.parse(json);
42
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
43
+ return {};
44
+ }
45
+ return parsed as Record<string, unknown>;
46
+ } catch {
47
+ return {};
48
+ }
49
+ }
50
+
51
+ function parseQuery(url: URL): Record<string, string | string[]> {
52
+ const query: Record<string, string | string[]> = {};
53
+ for (const [key, value] of url.searchParams) {
54
+ if (key in query) {
55
+ const existing = query[key];
56
+ if (Array.isArray(existing)) {
57
+ existing.push(value);
58
+ } else {
59
+ query[key] = [existing as string, value];
60
+ }
61
+ } else {
62
+ query[key] = value;
63
+ }
64
+ }
65
+ return query;
66
+ }
67
+
68
+ function parseCookies(cookieHeader: string | null): Record<string, string> {
69
+ const cookies: Record<string, string> = {};
70
+ if (!cookieHeader) {
71
+ return cookies;
72
+ }
73
+ for (const pair of cookieHeader.split(';')) {
74
+ const idx = pair.indexOf('=');
75
+ if (idx > 0) {
76
+ cookies[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();
77
+ }
78
+ }
79
+ return cookies;
80
+ }
81
+
82
+ function extractRouteParams(req: Request): Record<string, string> {
83
+ const nativeParams = (req as Request & { params?: Record<string, string> }).params;
84
+ if (nativeParams && typeof nativeParams === 'object' && !Array.isArray(nativeParams)) {
85
+ return nativeParams;
86
+ }
87
+ return {};
88
+ }
89
+
90
+ function createContext(req: Request): Record<string, unknown> {
91
+ const ctx: Record<string, unknown> = Object.create(null);
92
+ setContextField(ctx, 'request', req);
93
+
94
+ // Initialize always-present VectorContext fields with defaults derived from the request
95
+ setContextField(ctx, 'params', extractRouteParams(req));
96
+
97
+ try {
98
+ setContextField(ctx, 'query', parseQuery(new URL(req.url)));
99
+ } catch {
100
+ setContextField(ctx, 'query', {});
101
+ }
102
+
103
+ setContextField(ctx, 'cookies', parseCookies(req.headers.get('cookie')));
104
+ setContextField(ctx, 'metadata', {});
105
+
106
+ const checkpointContext = parseCheckpointContext(req);
107
+ const allowedCheckpointKeys = ['metadata', 'content', 'validatedInput', 'authUser'] as const;
108
+ for (const key of allowedCheckpointKeys) {
109
+ if (!Object.prototype.hasOwnProperty.call(checkpointContext, key)) {
110
+ continue;
111
+ }
112
+ const value = checkpointContext[key];
113
+ setContextField(ctx, key, value);
114
+ }
115
+
116
+ return ctx;
117
+ }
118
+
119
+ function setContextField(target: Record<string, unknown>, key: string, value: unknown) {
120
+ const ownDescriptor = Object.getOwnPropertyDescriptor(target as object, key);
121
+ if (ownDescriptor && ownDescriptor.writable === false && typeof ownDescriptor.set !== 'function') {
122
+ return;
123
+ }
124
+
125
+ try {
126
+ target[key] = value;
127
+ return;
128
+ } catch {
129
+ // Fall back to own-property define when inherited Request field is readonly.
130
+ }
131
+
132
+ try {
133
+ Object.defineProperty(target, key, {
134
+ value,
135
+ writable: true,
136
+ configurable: true,
137
+ enumerable: true,
138
+ });
139
+ } catch {
140
+ // Ignore non-extensible context edge cases.
141
+ }
142
+ }
143
+
144
+ function addToRouteTable(method: string, path: string, handler: (ctx: any) => any) {
145
+ if (!routeTable[path]) {
146
+ routeTable[path] = Object.create(null);
147
+ }
148
+ routeTable[path][method.toUpperCase()] = async (req: Request) => {
149
+ const ctx = createContext(req);
150
+ const result = await handler(ctx);
151
+ if (result instanceof Response) return result;
152
+ return Response.json(result);
153
+ };
154
+ }
155
+
156
+ function registerModule(mod: Record<string, unknown>) {
157
+ for (const [name, value] of Object.entries(mod)) {
158
+ if (isRouteDefinition(value)) {
159
+ addToRouteTable(value.options.method, value.options.path, value.handler);
160
+ } else if (name === 'default' && typeof value === 'function') {
161
+ // Default export functions need path context \u2014 skip for now
162
+ }
163
+ }
164
+ }
165
+
166
+ ${a.join(`
167
+ `)}
168
+
169
+ // Health check endpoint for parent process
170
+ routeTable['/_vector/health'] = {
171
+ GET: () => Response.json({ status: 'ok', version: '${t.version}' }),
172
+ };
173
+
174
+ const server = Bun.serve({
175
+ unix: socketPath,
176
+ routes: routeTable,
177
+ fetch(req: Request) {
178
+ return Response.json(
179
+ { error: true, message: 'Not Found', statusCode: 404 },
180
+ { status: 404 }
181
+ );
182
+ },
183
+ });
184
+
185
+ // Signal readiness to parent process
186
+ process.stdout.write('READY\\n');
187
+ `}toImportSpecifier(e,t){let r=j.relative(t,e).split(j.sep).join("/");if(r.startsWith(".")||r.startsWith("/"))return r;return`./${r}`}}var V,j;var $t=B(()=>{V=require("fs"),j=require("path")});class Pe{storageDir;codec;constructor(e,t="gzip"){this.storageDir=e,this.codec=t}async packageVersion(e){let t=S.join(this.storageDir,e),r=S.join(_t,`${e}${this.archiveSuffix()}`).replace(/\\/g,"/"),a=S.join(this.storageDir,r);await le.promises.mkdir(S.join(this.storageDir,_t),{recursive:!0});let n=await ca(t),o=await this.buildArchiveBytes(t,a,n);return{archivePath:r,archiveHash:N(o),archiveSize:o.byteLength,codec:this.codec}}async buildArchiveBytes(e,t,r){let a=Bun.Archive;if(typeof a==="function"){let o=Object.fromEntries(r.map((c)=>{return[S.relative(e,c).replace(/\\/g,"/"),Bun.file(c)]})),i=new a(o),d=new Uint8Array(await i.bytes()),l=this.codec==="gzip"?Bun.gzipSync(d):d;return await Bun.write(t,l),l}await this.buildArchiveWithTar(e,t,r);let n=await le.promises.readFile(t);return new Uint8Array(n.buffer,n.byteOffset,n.byteLength)}async buildArchiveWithTar(e,t,r){let a=r.map((l)=>S.relative(e,l));if(a.length===0)throw new Error(`Cannot package checkpoint: no files found in "${e}"`);let n=this.codec==="gzip"?["-czf",t]:["-cf",t],o=Bun.spawn(["tar",...n,"-C",e,...a],{stdout:"pipe",stderr:"pipe"}),i=await o.exited;if(i===0)return;let d=await new Response(o.stderr).text();throw new Error(`Failed to package checkpoint archive with tar (exit ${i}): ${d.trim()}`)}archiveSuffix(){return this.codec==="gzip"?".tar.gz":".tar"}}async function ca(e){let t=[];return await Ut(e,t),t.filter((r)=>S.relative(e,r).replace(/\\/g,"/")!=="manifest.json")}async function Ut(e,t){let r=await le.promises.readdir(e,{withFileTypes:!0});for(let a of r){let n=S.join(e,a.name);if(a.isDirectory()){await Ut(n,t);continue}if(a.isFile())t.push(n)}}var le,S,_t="_archives";var Mt=B(()=>{le=require("fs"),S=require("path")});function Pt(e){return $.isAbsolute(e)?e:$.resolve(e)}function zt(e){return Buffer.byteLength(e,"utf8")<=ma}function ba(e,t){let r=t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-+|-+$)/g,"").slice(0,12),a=Jt.createHash("sha256").update(e).update("\x00").update(t).digest("hex").slice(0,16);return`vector-${r.length>0?`${r}-`:""}${a}.sock`}function ua(){let e=new Set,t=process.env.VECTOR_CHECKPOINT_SOCKET_DIR?.trim();if(t)e.add(Pt(t));if(process.platform!=="win32")e.add("/tmp"),e.add("/private/tmp");return e.add(Pt(Ft.tmpdir())),[...e]}function se(e,t){let r=$.join(e,t,pa);if(process.platform==="win32"||zt(r))return r;let a=ba(e,t);for(let n of ua()){let o=$.join(n,a);if(zt(o))return o}return $.join("/tmp",a)}var Jt,Ft,$,pa="run.sock",ma=103;var ze=B(()=>{Jt=require("crypto"),Ft=require("os"),$=require("path")});var Qt={};J(Qt,{CheckpointManager:()=>Yt});function fa(e){if(e.codec)return e.codec;return(e.blobPath??e.storedPath??"").trim().toLowerCase().endsWith(".gz")?"gzip":"none"}class Yt{storageDir;maxCheckpoints;constructor(e={}){this.storageDir=T.resolve(process.cwd(),e.storageDir??ha),this.maxCheckpoints=e.maxCheckpoints??10}getStorageDir(){return this.storageDir}versionDir(e){return T.join(this.storageDir,e)}socketPath(e){return se(this.storageDir,e)}async ensureStorageDir(){await g.promises.mkdir(this.storageDir,{recursive:!0})}async publish(e){await this.ensureStorageDir();let t=this.versionDir(e.version);await g.promises.mkdir(t,{recursive:!0});let r=new Me,a=await r.generate({version:e.version,outputDir:t,routesDir:T.resolve(process.cwd(),e.routesDir),socketPath:this.socketPath(e.version)}),o=await new Ue().bundle({entrypointPath:a,outputDir:t}),i=new $e(this.storageDir),d=await i.collect(e.embeddedAssetPaths??[],e.sidecarAssetPaths??[]);i.validateBudgets(d);let l={formatVersion:He,version:e.version,createdAt:new Date().toISOString(),entrypoint:"checkpoint.js",routes:r.getDiscoveredRoutes(),assets:d,bundleHash:o.hash,bundleSize:o.size,checkpointArchivePath:void 0,checkpointArchiveHash:void 0,checkpointArchiveSize:void 0,checkpointArchiveCodec:void 0};await this.writeManifest(e.version,l);try{await g.promises.unlink(a)}catch{}let m=await new Pe(this.storageDir).packageVersion(e.version);return l.checkpointArchivePath=m.archivePath,l.checkpointArchiveHash=m.archiveHash,l.checkpointArchiveSize=m.archiveSize,l.checkpointArchiveCodec=m.codec,await this.writeManifest(e.version,l),await this.pruneOld(),l}async readManifest(e){let t=T.join(this.versionDir(e),"manifest.json"),r=await g.promises.readFile(t,"utf-8");return this.normalizeManifest(JSON.parse(r))}async writeManifest(e,t){let r=T.join(this.versionDir(e),"manifest.json");await g.promises.writeFile(r,JSON.stringify(t,null,2),"utf-8")}async listVersions(){if(!g.existsSync(this.storageDir))return[];let e=await g.promises.readdir(this.storageDir),t=[];for(let r of e){let a=T.join(this.storageDir,r,"manifest.json");if(g.existsSync(a))try{let n=await g.promises.readFile(a,"utf-8");t.push(this.normalizeManifest(JSON.parse(n)))}catch{}}return t.sort((r,a)=>new Date(a.createdAt).getTime()-new Date(r.createdAt).getTime()),t}async getActive(){let e=T.join(this.storageDir,Gt);if(!g.existsSync(e))return null;try{let t=await g.promises.readFile(e,"utf-8");return JSON.parse(t)}catch{return null}}async setActive(e){let t=this.versionDir(e);if(!g.existsSync(t))throw new Error(`Checkpoint version ${e} does not exist`);let r=T.join(t,"manifest.json");if(!g.existsSync(r))throw new Error(`Checkpoint version ${e} has no manifest`);await this.ensureStorageDir();let a={version:e,activatedAt:new Date().toISOString()},n=T.join(this.storageDir,Gt);await g.promises.writeFile(n,JSON.stringify(a,null,2),"utf-8")}async remove(e){if((await this.getActive())?.version===e)throw new Error(`Cannot remove active checkpoint version ${e}. Rollback to a different version first.`);let r=this.versionDir(e);if(!g.existsSync(r))throw new Error(`Checkpoint version ${e} does not exist`);await g.promises.rm(r,{recursive:!0,force:!0})}async pruneOld(){if(this.maxCheckpoints<=0)return;let e=await this.listVersions();if(e.length<=this.maxCheckpoints)return;let t=await this.getActive(),r=e.slice(this.maxCheckpoints);for(let a of r){if(t?.version===a.version)continue;try{let n=this.versionDir(a.version);await g.promises.rm(n,{recursive:!0,force:!0})}catch{}}}normalizeManifest(e){let t=(e.assets??[]).map((r)=>({...r,contentHash:r.contentHash??r.hash,contentSize:r.contentSize??r.size,blobPath:r.blobPath??r.storedPath,blobHash:r.blobHash,blobSize:r.blobSize,codec:fa(r)}));return{formatVersion:e.formatVersion??He,version:e.version??"unknown",createdAt:e.createdAt??new Date(0).toISOString(),entrypoint:e.entrypoint??"checkpoint.js",routes:e.routes??[],assets:t,bundleHash:e.bundleHash??"",bundleSize:e.bundleSize??0,checkpointArchivePath:e.checkpointArchivePath,checkpointArchiveHash:e.checkpointArchiveHash,checkpointArchiveSize:e.checkpointArchiveSize,checkpointArchiveCodec:e.checkpointArchiveCodec}}}var g,T,ha=".vector/checkpoints",Gt="active.json";var Vt=B(()=>{g=require("fs"),T=require("path");Ot();jt();$t();Mt();ze()});function ga(e){let t=e.trim();if(!t)return null;if(t==="READY")return{type:"ready"};try{return JSON.parse(t)}catch{return null}}async function Wt(e,t=1e4){return new Promise((r,a)=>{let n=!1,o=e.getReader(),i=new TextDecoder,d="";function l(p){if(n)return;n=!0,clearTimeout(c);try{o.releaseLock()}catch{}p()}let c=setTimeout(()=>{l(()=>a(new Error(`Checkpoint process did not become ready within ${t}ms`)))},t),m=(p)=>{let h=ga(p);if(h?.type==="ready")return l(()=>r()),"ready";if(h?.type==="error")return l(()=>a(new Error(`Checkpoint process error: ${h.message}`))),"error";return"continue"},s=()=>{let p=d.indexOf(`
188
+ `);while(p!==-1){let h=d.slice(0,p);d=d.slice(p+1);let u=m(h);if(u!=="continue")return u;p=d.indexOf(`
189
+ `)}return"continue"};(async()=>{try{while(!0){let{done:p,value:h}=await o.read();if(p){d+=i.decode();let w=d.trim();if(w.length>0){if(m(w)!=="continue")return}l(()=>a(new Error("Checkpoint process stdout closed before READY signal")));return}if(d+=i.decode(h,{stream:!0}),d.length>1048576){l(()=>a(new Error("Checkpoint process stdout exceeded 1048576 chars before READY")));return}if(s()!=="continue")return}}catch(p){l(()=>a(p))}})()})}class Je{workers=[];idleWorkers=[];queue=[];activeJobsByWorker=new Map;nextJobId=1;disposed=!1;constructor(e=wa()){let t=va(e),r=Ea();for(let a=0;a<t;a++){let n=new Worker(r.href);n.onmessage=(o)=>this.handleWorkerMessage(n,o),n.onerror=(o)=>this.handleWorkerError(n,o),this.workers.push(n),this.idleWorkers.push(n)}}async decompress(e,t){if(t==="none")return new Uint8Array(e);if(this.disposed)throw new Error("Checkpoint worker decompressor is disposed");let r=new Uint8Array(e);return await new Promise((a,n)=>{let o=this.nextJobId++;this.queue.push({id:o,request:{id:o,codec:t,input:r.buffer},resolve:a,reject:n}),this.pump()})}async dispose(){if(this.disposed)return;this.disposed=!0;let e=new Error("Checkpoint worker decompressor disposed");this.failAll(e);for(let t of this.workers)try{t.terminate()}catch{}this.workers=[],this.idleWorkers=[],this.activeJobsByWorker.clear()}pump(){while(this.idleWorkers.length>0&&this.queue.length>0){let e=this.idleWorkers.pop(),t=this.queue.shift();this.activeJobsByWorker.set(e,t),e.postMessage(t.request,[t.request.input])}}handleWorkerMessage(e,t){let r=this.activeJobsByWorker.get(e);if(this.activeJobsByWorker.delete(e),!this.disposed)this.idleWorkers.push(e);if(!r){this.pump();return}let a=t.data;if(a.error)r.reject(new Error(a.error));else if(a.output instanceof ArrayBuffer)r.resolve(new Uint8Array(a.output));else r.reject(new Error("Worker returned no output"));this.pump()}handleWorkerError(e,t){let r=this.activeJobsByWorker.get(e);this.activeJobsByWorker.delete(e),this.idleWorkers=this.idleWorkers.filter((o)=>o!==e);let a=t.message?.trim()||"Checkpoint decompression worker crashed",n=new Error(a);if(r)r.reject(n);this.failAll(n),this.dispose().catch(()=>{})}failAll(e){let t=this.queue.splice(0,this.queue.length);for(let r of t)r.reject(e);for(let r of this.activeJobsByWorker.values())r.reject(e);this.activeJobsByWorker.clear()}}function wa(){let e=xa(),t=Math.max(1,e-1);return Math.max(1,Math.min(ya,t))}function xa(){try{let t=ce.availableParallelism();if(Number.isFinite(t)&&t>0)return t}catch{}let e=ce.cpus().length;return Number.isFinite(e)&&e>0?e:1}function va(e){if(!Number.isFinite(e)||e<=0)return 1;return Math.max(1,Math.floor(e))}function Ea(){if(import.meta.url.endsWith(".ts"))return new URL("./decompress-worker.ts",import.meta.url);return new URL("./decompress-worker.js",import.meta.url)}var ce,ya=4;var Xt=B(()=>{ce=require("os")});class Fe{verifyChecksums;materializedDirName;lockTimeoutMs;constructor(e={}){this.verifyChecksums=e.verifyChecksums??!0,this.materializedDirName=e.materializedDirName??ka,this.lockTimeoutMs=e.lockTimeoutMs??Ba}async materialize(e,t){let r=y.join(t,e.version),a=y.join(r,".assets.ready.json"),n=y.join(r,".assets.lock"),o=Lt(e.assets);if(await this.isReady(a,o,e.assets,y.join(r,this.materializedDirName)))return;await this.acquireLock(n);try{if(await this.isReady(a,o,e.assets,y.join(r,this.materializedDirName)))return;let i=y.join(r,this.materializedDirName);await f.promises.rm(i,{recursive:!0,force:!0}),await f.promises.mkdir(i,{recursive:!0});let d=new Je;try{for(let c of e.assets){let m=await this.materializeAsset(c,t,r,i,d);c.materializedPath=m}}finally{await d.dispose()}let l={fingerprint:o,createdAt:new Date().toISOString()};await f.promises.writeFile(a,JSON.stringify(l,null,2),"utf-8")}finally{await f.promises.rm(n,{recursive:!0,force:!0})}}async materializeAsset(e,t,r,a,n){let o=this.resolveSourcePath(e,t);if(!f.existsSync(o))throw new Error(`Checkpoint asset blob not found: ${o}`);let i=await f.promises.readFile(o),d=new Uint8Array(i.buffer,i.byteOffset,i.byteLength),l=e.blobHash;if(this.verifyChecksums&&l&&N(d)!==l)throw new Error(`Checkpoint asset blob checksum mismatch for ${e.logicalPath}`);let c=e.codec??(e.blobHash?"gzip":"none"),m=await n.decompress(d,c),s=e.contentHash??e.hash;if(this.verifyChecksums&&s&&N(m)!==s)throw new Error(`Checkpoint asset content checksum mismatch for ${e.logicalPath}`);let p=await this.writeDecompressedCache(e,t,m),h=ee(e.logicalPath),u=y.join(a,h);return await f.promises.mkdir(y.dirname(u),{recursive:!0}),await f.promises.rm(u,{force:!0}),await this.linkWithFallback(p,u),Ta(y.relative(r,u))}async writeDecompressedCache(e,t,r){let a=e.contentHash??e.hash,n=y.extname(e.logicalPath)||".bin",o=y.join(t,"_assets/cache",`${a}${n}`);if(await f.promises.mkdir(y.dirname(o),{recursive:!0}),f.existsSync(o)){if(!this.verifyChecksums)return o;let i=await f.promises.readFile(o),d=new Uint8Array(i.buffer,i.byteOffset,i.byteLength);if(N(d)===a)return o}return await f.promises.writeFile(o,r),o}resolveSourcePath(e,t){let r=e.blobPath??e.storedPath;if(Oe(r))return r;return y.join(t,r)}async linkWithFallback(e,t){try{await f.promises.link(e,t);return}catch{}try{await f.promises.symlink(e,t);return}catch{}await f.promises.copyFile(e,t)}async acquireLock(e){let t=Date.now()+this.lockTimeoutMs;while(Date.now()<t){try{await f.promises.mkdir(e);return}catch(r){if(!Ca(r))throw r}await La(Ia)}throw new Error(`Timed out waiting for checkpoint asset lock: ${e}`)}async isReady(e,t,r,a){if(!f.existsSync(e))return!1;try{if(JSON.parse(await f.promises.readFile(e,"utf-8")).fingerprint!==t)return!1;for(let o of r){let i=y.join(a,ee(o.logicalPath));if(!f.existsSync(i))return!1}return!0}catch{return!1}}}function Ta(e){return e.replace(/\\/g,"/")}function Ca(e){return typeof e==="object"&&e!==null&&"code"in e&&e.code==="EEXIST"}function La(e){return new Promise((t)=>setTimeout(t,e))}var f,y,ka="_materialized",Ba=15000,Ia=50;var Zt=B(()=>{f=require("fs"),y=require("path");De();Xt()});var tr={};J(tr,{CheckpointProcessManager:()=>er});class er{running=new Map;pending=new Map;readyTimeoutMs;idleTimeoutMs;idleTimers=new Map;lastUsedAt=new Map;materializer;constructor(e=qt){if(typeof e==="number")this.readyTimeoutMs=e,this.idleTimeoutMs=Kt;else this.readyTimeoutMs=e.readyTimeoutMs??qt,this.idleTimeoutMs=e.idleTimeoutMs??Kt;this.materializer=new Fe}async spawn(e,t){if(this.running.has(e.version))return this.running.get(e.version);if(this.pending.has(e.version))return this.pending.get(e.version);let r=this.doSpawn(e,t);this.pending.set(e.version,r);try{return await r}finally{this.pending.delete(e.version)}}async doSpawn(e,t){let r=te.join(t,e.version),a=te.join(r,e.entrypoint),n=se(t,e.version);if(!P.existsSync(a))throw new Error(`Checkpoint bundle not found: ${a}`);await this.materializer.materialize(e,t),await P.promises.mkdir(te.dirname(n),{recursive:!0}),this.tryUnlinkSocket(n);let o=Bun.spawn(["bun","run",a],{env:{...process.env,VECTOR_CHECKPOINT_SOCKET:n,VECTOR_CHECKPOINT_VERSION:e.version},stdout:"pipe",stderr:"inherit"});if(!o.stdout)throw o.kill("SIGTERM"),new Error(`Checkpoint process for ${e.version} did not provide stdout`);try{await Wt(o.stdout,this.readyTimeoutMs)}catch(d){throw o.kill("SIGTERM"),d}let i={version:e.version,socketPath:n,process:o,pid:o.pid};return this.running.set(e.version,i),this.lastUsedAt.set(e.version,Date.now()),this.scheduleIdleCheck(e.version),i}markUsed(e){if(!this.running.has(e))return;this.lastUsedAt.set(e,Date.now())}async stop(e){let t=this.running.get(e);if(!t)return;if(this.running.delete(e),this.clearIdleTimer(e),this.lastUsedAt.delete(e),t.process.kill("SIGTERM"),!await Promise.race([t.process.exited.then(()=>!0),new Promise((a)=>setTimeout(()=>a(!1),Na))]))try{t.process.kill("SIGKILL"),await t.process.exited}catch{}this.tryUnlinkSocket(t.socketPath)}async stopAll(){let e=[...this.running.keys()];for(let t of e)await this.stop(t)}isRunning(e){return this.running.has(e)}getRunning(e){return this.running.get(e)}async health(e){let t=this.running.get(e);if(!t)return!1;try{return(await fetch("http://localhost/_vector/health",{unix:t.socketPath,signal:AbortSignal.timeout(2000)})).ok}catch{return!1}}getRunningVersions(){return[...this.running.keys()]}scheduleIdleCheck(e,t=this.idleTimeoutMs){if(this.clearIdleTimer(e),this.idleTimeoutMs<=0)return;let r=setTimeout(()=>{this.handleIdleCheck(e)},Math.max(1,t));if(typeof r.unref==="function")r.unref();this.idleTimers.set(e,r)}async handleIdleCheck(e){if(!this.running.has(e))return;let t=this.lastUsedAt.get(e)??0,r=Date.now()-t,a=this.idleTimeoutMs-r;if(a>0){this.scheduleIdleCheck(e,a);return}try{await this.stop(e)}catch(n){console.error(`[CheckpointProcessManager] Failed to stop idle checkpoint ${e}:`,n)}}clearIdleTimer(e){let t=this.idleTimers.get(e);if(!t)return;clearTimeout(t),this.idleTimers.delete(e)}tryUnlinkSocket(e){try{if(P.existsSync(e))P.unlinkSync(e)}catch{}}}var P,te,qt=1e4,Kt=600000,Na=5000;var rr=B(()=>{P=require("fs"),te=require("path");Zt();ze()});var nr={};J(nr,{CheckpointResolver:()=>ar});class ar{manager;processManager;versionHeader;cacheKeyOverride;allowFallbackVersionHeader;pendingVersionResolves=new Map;constructor(e,t,r={}){this.manager=e,this.processManager=t,this.versionHeader=Aa(r.versionHeader??"x-vector-checkpoint-version"),this.cacheKeyOverride=r.cacheKeyOverride===!0,this.allowFallbackVersionHeader=r.versionHeader===void 0}async resolve(e){let t=this.getRequestedVersion(e);if(!t)return null;return await this.resolveVersion(t)}getRequestedVersion(e){return this.getRequestedHeader(e)?.value??null}getCacheKeyOverrideValue(e){if(!this.cacheKeyOverride)return null;let t=this.getRequestedHeader(e);if(!t)return null;return`${t.name}:${t.value}`}getRequestedHeader(e){let t=e.headers.get(this.versionHeader);if(t&&t.trim().length>0)return{name:this.versionHeader,value:t.trim()};if(this.allowFallbackVersionHeader&&this.versionHeader!=="x-vector-checkpoint"){let r=e.headers.get("x-vector-checkpoint");if(r&&r.trim().length>0)return{name:"x-vector-checkpoint",value:r.trim()}}return null}async resolveVersion(e){let t=this.processManager.getRunning(e);if(!t){let r=this.pendingVersionResolves.get(e);if(r){let o=await r;if(!o)return null;return this.processManager.markUsed(e),o}let a=(async()=>{try{let o=await this.manager.readManifest(e);return(await this.processManager.spawn(o,this.manager.getStorageDir())).socketPath}catch{return null}})();this.pendingVersionResolves.set(e,a);let n=await a;if(this.pendingVersionResolves.delete(e),!n)return null;return this.processManager.markUsed(e),n}return this.processManager.markUsed(e),t.socketPath}invalidateCache(){}}function Aa(e){let t=e.trim().toLowerCase();return t.length>0?t:"x-vector-checkpoint-version"}var dr={};J(dr,{CheckpointForwarder:()=>or,CHECKPOINT_CONTEXT_HEADER:()=>Sa});class or{async forward(e,t,r){try{let a=Oa(r),n=Ra(e.headers,a),o=await fetch(e.url,{method:e.method,headers:n,body:e.body,unix:t,duplex:e.body?"half":void 0});return new Response(o.body,{status:o.status,statusText:o.statusText,headers:new Headers(o.headers)})}catch(a){return console.error("[CheckpointForwarder] Forward failed:",a),new Response(JSON.stringify({error:!0,message:"Checkpoint unavailable",statusCode:503}),{status:503,headers:{"content-type":"application/json"}})}}}function Ra(e,t){let r=new Headers(e);if(Ha(r),t)r.set("x-vector-checkpoint-context",t);return r}function Ha(e){let t=e.get("connection");if(t)for(let r of t.split(",")){let a=r.trim().toLowerCase();if(a)e.delete(a)}e.delete("connection"),e.delete("keep-alive"),e.delete("proxy-authenticate"),e.delete("proxy-authorization"),e.delete("te"),e.delete("trailer"),e.delete("transfer-encoding"),e.delete("upgrade")}function Oa(e){if(!e)return null;if(Object.keys(e).length===0)return null;try{return Buffer.from(JSON.stringify(e),"utf-8").toString("base64url")}catch{return null}}var Sa="x-vector-checkpoint-context";var lr={};J(lr,{CheckpointGateway:()=>ir});class ir{resolver;forwarder;constructor(e,t){this.resolver=e,this.forwarder=t}getRequestedVersion(e){return this.resolver.getRequestedVersion(e)}getCacheKeyOverrideValue(e){return this.resolver.getCacheKeyOverrideValue(e)}async handle(e,t){let r=this.getRequestedVersion(e),a=await this.resolver.resolve(e);if(!a){if(r)return new Response(JSON.stringify({error:!0,message:`Requested checkpoint version "${r}" is unavailable`,statusCode:503}),{status:503,headers:{"content-type":"application/json"}});return null}return await this.forwarder.forward(e,a,t)}}var Ua={};J(Ua,{startVector:()=>pr,route:()=>Ye,depRoute:()=>sr,createResponse:()=>_,OpenApiSecuritySchemeType:()=>ye,HttpAuthScheme:()=>we,AuthKind:()=>G,APIError:()=>D});module.exports=hr(Ua);var O={OK:200,CREATED:201,ACCEPTED:202,NON_AUTHORITATIVE_INFORMATION:203,NO_CONTENT:204,RESET_CONTENT:205,PARTIAL_CONTENT:206,MULTI_STATUS:207,ALREADY_REPORTED:208,IM_USED:226,MULTIPLE_CHOICES:300,MOVED_PERMANENTLY:301,FOUND:302,SEE_OTHER:303,NOT_MODIFIED:304,USE_PROXY:305,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,BAD_REQUEST:400,UNAUTHORIZED:401,PAYMENT_REQUIRED:402,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,NOT_ACCEPTABLE:406,PROXY_AUTHENTICATION_REQUIRED:407,REQUEST_TIMEOUT:408,CONFLICT:409,GONE:410,LENGTH_REQUIRED:411,PRECONDITION_FAILED:412,PAYLOAD_TOO_LARGE:413,URI_TOO_LONG:414,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,EXPECTATION_FAILED:417,IM_A_TEAPOT:418,MISDIRECTED_REQUEST:421,UNPROCESSABLE_ENTITY:422,LOCKED:423,FAILED_DEPENDENCY:424,TOO_EARLY:425,UPGRADE_REQUIRED:426,PRECONDITION_REQUIRED:428,TOO_MANY_REQUESTS:429,REQUEST_HEADER_FIELDS_TOO_LARGE:431,UNAVAILABLE_FOR_LEGAL_REASONS:451,INTERNAL_SERVER_ERROR:500,NOT_IMPLEMENTED:501,BAD_GATEWAY:502,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504,HTTP_VERSION_NOT_SUPPORTED:505,VARIANT_ALSO_NEGOTIATES:506,INSUFFICIENT_STORAGE:507,LOOP_DETECTED:508,NOT_EXTENDED:510,NETWORK_AUTHENTICATION_REQUIRED:511},F={PORT:3000,HOSTNAME:"localhost",ROUTES_DIR:"./routes",CACHE_TTL:0,CORS_MAX_AGE:86400},W={JSON:"application/json",TEXT:"text/plain",HTML:"text/html",FORM_URLENCODED:"application/x-www-form-urlencoded",MULTIPART:"multipart/form-data"};var Xe={NOT_FOUND:new Response(JSON.stringify({error:!0,message:"Not Found",statusCode:404}),{status:404,headers:{"content-type":"application/json"}})};class be{protectedHandler=null;setProtectedHandler(e){this.protectedHandler=e}clearProtectedHandler(){this.protectedHandler=null}async authenticate(e){if(!this.protectedHandler)throw new Error("Protected handler not configured. Use vector.protected() to set authentication handler.");if(!e||typeof e!=="object"||!e.request)throw new Error("Authentication context is invalid: missing request");try{let t=await this.protectedHandler(e);return e.authUser=t,t}catch(t){throw new Error(`Authentication failed: ${t instanceof Error?t.message:String(t)}`)}}isAuthenticated(e){return!!e.authUser}getUser(e){return e.authUser||null}}class ue{cacheHandler=null;memoryCache=new Map;cleanupInterval=null;inflight=new Map;setCacheHandler(e){this.cacheHandler=e}clearCacheHandler(){this.cacheHandler=null}async get(e,t,r=F.CACHE_TTL){if(r<=0)return t();if(this.cacheHandler)return this.cacheHandler(e,t,r);return this.getFromMemoryCache(e,t,r)}async getFromMemoryCache(e,t,r){let a=Date.now(),n=this.memoryCache.get(e);if(this.isCacheValid(n,a))return this.cloneCachedValue(n.value);if(this.inflight.has(e)){let i=await this.inflight.get(e);return this.cloneCachedValue(i)}let o=(async()=>{let i=await t();return this.setInMemoryCache(e,i,r),i})();this.inflight.set(e,o);try{return await o}finally{this.inflight.delete(e)}}isCacheValid(e,t){return e!==void 0&&e.expires>t}setInMemoryCache(e,t,r){let a=Date.now()+r*1000;this.memoryCache.set(e,{value:this.cloneForStore(t),expires:a}),this.scheduleCleanup()}cloneForStore(e){if(e instanceof Response)return e.clone();return e}cloneCachedValue(e){if(e instanceof Response)return e.clone();return e}scheduleCleanup(){if(this.cleanupInterval)return;let e=setInterval(()=>{this.cleanupExpired()},60000);if(typeof e.unref==="function")e.unref();this.cleanupInterval=e}cleanupExpired(){let e=Date.now();for(let[t,r]of this.memoryCache.entries())if(r.expires<=e)this.memoryCache.delete(t);if(this.memoryCache.size===0&&this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}clear(){if(this.memoryCache.clear(),this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}async set(e,t,r=F.CACHE_TTL){if(r<=0)return;if(this.cacheHandler){await this.cacheHandler(e,async()=>t,r);return}this.setInMemoryCache(e,t,r)}delete(e){return this.memoryCache.delete(e)}has(e){let t=this.memoryCache.get(e);if(!t)return!1;if(t.expires<=Date.now())return this.memoryCache.delete(e),!1;return!0}generateKey(e,t){let r=e._parsedUrl??new URL(e.url),a=t?.authUser?.id!=null?String(t.authUser.id):"anonymous";return`${e.method}:${r.pathname}:${r.search}:${a}`}}var he=require("fs"),X=require("path");class fe{outputPath;constructor(e="./.vector/routes.generated.ts"){this.outputPath=e}async generate(e){let t=X.dirname(this.outputPath);await he.promises.mkdir(t,{recursive:!0});let r=[],a=new Map;for(let d of e){if(!a.has(d.path))a.set(d.path,[]);a.get(d.path).push(d)}let n=0,o=[];for(let[d,l]of a){let c=X.relative(X.dirname(this.outputPath),d).replace(/\\/g,"/").replace(/\.(ts|js)$/,""),m=`route_${n++}`,s=l.filter((p)=>p.name!=="default").map((p)=>p.name);if(l.some((p)=>p.name==="default"))if(s.length>0)r.push(`import ${m}, { ${s.join(", ")} } from '${c}';`);else r.push(`import ${m} from '${c}';`);else if(s.length>0)r.push(`import { ${s.join(", ")} } from '${c}';`);for(let p of l){let h=p.name==="default"?m:p.name;o.push(` ${h},`)}}let i=`// This file is auto-generated. Do not edit manually.
190
+ // Generated at: ${new Date().toISOString()}
191
+
192
+ ${r.join(`
193
+ `)}
194
+
195
+ export const routes = [
196
+ ${o.join(`
197
+ `)}
198
+ ];
199
+
200
+ export default routes;
201
+ `;await he.promises.writeFile(this.outputPath,i,"utf-8")}async generateDynamic(e){let t=[];for(let r of e){let a=JSON.stringify({method:r.method,path:r.options.path,options:r.options});t.push(` await import('${r.path}').then(m => ({
202
+ ...${a},
203
+ handler: m.${r.name==="default"?"default":r.name}
204
+ }))`)}return`export const loadRoutes = async () => {
205
+ return Promise.all([
206
+ ${t.join(`,
207
+ `)}
208
+ ]);
209
+ };`}}var Z=require("fs"),C=require("path");class re{routesDir;excludePatterns;static DEFAULT_EXCLUDE_PATTERNS=["*.test.ts","*.test.js","*.test.tsx","*.test.jsx","*.spec.ts","*.spec.js","*.spec.tsx","*.spec.jsx","*.tests.ts","*.tests.js","**/__tests__/**","*.interface.ts","*.type.ts","*.d.ts"];constructor(e="./routes",t){this.routesDir=C.resolve(process.cwd(),e),this.excludePatterns=t||re.DEFAULT_EXCLUDE_PATTERNS}async scan(){let e=[];if(!Z.existsSync(this.routesDir))return[];try{await this.scanDirectory(this.routesDir,e)}catch(t){if(t.code==="ENOENT")return console.warn(` \u2717 Routes directory not accessible: ${this.routesDir}`),[];throw t}return e}isExcluded(e){let t=C.relative(this.routesDir,e);for(let r of this.excludePatterns){let a=r.replace(/\./g,"\\.").replace(/\*\*/g,"__GLOBSTAR__").replace(/\*/g,"[^/]*").replace(/__GLOBSTAR__/g,".*").replace(/\?/g,"."),n=new RegExp(`^${a}$`),o=t.split(C.sep).pop()||"";if(n.test(t)||n.test(o))return!0}return!1}async scanDirectory(e,t,r=""){let a=await Z.promises.readdir(e);for(let n of a){let o=C.join(e,n);if((await Z.promises.stat(o)).isDirectory()){let d=r?`${r}/${n}`:n;await this.scanDirectory(o,t,d)}else if(n.endsWith(".ts")||n.endsWith(".js")){if(this.isExcluded(o))continue;let d=C.relative(this.routesDir,o).replace(/\.(ts|js)$/,"").split(C.sep).join("/");try{let c=await import(`${process.platform==="win32"?`file:///${o.replace(/\\/g,"/")}`:o}?t=${Date.now()}`);if(c.default&&typeof c.default==="function")t.push({name:"default",path:o,method:"GET",options:{method:"GET",path:`/${d}`,expose:!0}});for(let[m,s]of Object.entries(c)){if(m==="default")continue;if(s&&typeof s==="object"&&"entry"in s&&"options"in s&&"handler"in s){let p=s;t.push({name:m,path:o,method:p.options.method,options:p.options})}else if(Array.isArray(s)&&s.length>=4){let[p,,,h]=s;t.push({name:m,path:o,method:p,options:{method:p,path:h,expose:!0}})}}}catch(l){console.error(`Failed to load route from ${o}:`,l)}}}}enableWatch(e){if(typeof Bun!=="undefined"&&Bun.env.NODE_ENV==="development")console.log(`Watching for route changes in ${this.routesDir}`),setInterval(async()=>{await e()},1000)}}class ae{beforeHandlers=[];finallyHandlers=[];addBefore(...e){this.beforeHandlers.push(...e)}addFinally(...e){this.finallyHandlers.push(...e)}async executeBefore(e){if(this.beforeHandlers.length===0)return null;for(let t of this.beforeHandlers){let r=await t(e);if(r instanceof Response)return r;if(r!==void 0)throw new TypeError("Before middleware must return void or Response")}return null}async executeFinally(e,t){if(this.finallyHandlers.length===0)return e;let r=e;for(let a of this.finallyHandlers)try{r=await a(r,t)}catch(n){console.error("After middleware error:",n)}return r}clone(){let e=new ae;return e.beforeHandlers=[...this.beforeHandlers],e.finallyHandlers=[...this.finallyHandlers],e}clear(){this.beforeHandlers=[],this.finallyHandlers=[]}}function ne(e){return process.platform==="win32"?`file:///${e.replace(/\\/g,"/")}`:e}function ge(e){return RegExp(`^${e.replace(/\/+(\/|$)/g,"$1").replace(/(\/?\.?):(\w+)\+/g,"($1(?<$2>[\\s\\S]+))").replace(/(\/?\.?):(\w+)/g,"($1(?<$2>[^$1/]+?))").replace(/\./g,"\\.").replace(/(\/?)\*/g,"($1.*)?")}/*$`)}var ye;((o)=>{o.ApiKey="apiKey";o.Http="http";o.MutualTls="mutualTLS";o.OAuth2="oauth2";o.OpenIdConnect="openIdConnect"})(ye||={});var we;((a)=>{a.Basic="basic";a.Bearer="bearer";a.Digest="digest"})(we||={});var G;((d)=>{d.ApiKey="ApiKey";d.HttpBasic="HttpBasic";d.HttpBearer="HttpBearer";d.HttpDigest="HttpDigest";d.OAuth2="OAuth2";d.OpenIdConnect="OpenIdConnect";d.MutualTls="MutualTls"})(G||={});function Ze(e){let t=e?.["~standard"];return!!t&&typeof t==="object"&&typeof t.validate==="function"&&t.version===1}async function qe(e,t){let r=await e["~standard"].validate(t),a=r?.issues;if(Array.isArray(a)&&a.length>0)return{success:!1,issues:a};return{success:!0,value:r?.value}}function Ke(e){if(Array.isArray(e))return e;if(e&&typeof e==="object"&&Array.isArray(e.issues))return e.issues;if(e&&typeof e==="object"&&e.cause&&Array.isArray(e.cause.issues))return e.cause.issues;return null}function fr(e){if(!Array.isArray(e))return[];let t=[];for(let r=0;r<e.length;r++){let a=e[r],n=a;if(a&&typeof a==="object"&&"key"in a)n=a.key;if(typeof n==="string"||typeof n==="number")t.push(n);else if(typeof n==="symbol")t.push(String(n));else if(n!==void 0&&n!==null)t.push(String(n))}return t}function xe(e,t){let r=[];for(let a=0;a<e.length;a++){let n=e[a],o=n,i={message:typeof o?.message==="string"&&o.message.length>0?o.message:"Invalid value",path:fr(o?.path)};if(typeof o?.code==="string")i.code=o.code;if(t)i.raw=n;r.push(i)}return r}function ve(e,t){return{error:!0,message:"Validation failed",statusCode:422,source:"validation",target:e,issues:t,timestamp:new Date().toISOString()}}var gr=new Set(Object.values(G));function yr(e){return typeof e==="string"&&gr.has(e)}class q{middlewareManager;authManager;cacheManager;routeBooleanDefaults={};developmentMode=void 0;routeDefinitions=[];routeTable=Object.create(null);routeMatchers=[];corsHeadersEntries=null;corsHandler=null;checkpointGateway=null;constructor(e,t,r){this.middlewareManager=e,this.authManager=t,this.cacheManager=r}setCorsHeaders(e){this.corsHeadersEntries=e}setCorsHandler(e){this.corsHandler=e}setCheckpointGateway(e){this.checkpointGateway=e}setRouteBooleanDefaults(e){this.routeBooleanDefaults={...e}}setDevelopmentMode(e){this.developmentMode=e}applyRouteBooleanDefaults(e){let t={...e},r=this.routeBooleanDefaults,a=["auth","expose","rawRequest","validate","rawResponse"];for(let n of a)if(t[n]===void 0&&r[n]!==void 0)t[n]=r[n];if(t.auth===!0&&yr(r.auth))t.auth=r.auth;return t}route(e,t){let r=this.applyRouteBooleanDefaults(e),a=r.method.toUpperCase(),n=r.path,o=this.wrapHandler(r,t),i=this.getOrCreateMethodMap(n);i[a]=o,this.routeDefinitions.push({method:a,path:n,options:r})}addRoute(e){let[t,,r,a]=e;if(!a)return;let n=this.getOrCreateMethodMap(a);n[t.toUpperCase()]=r[0];let o=t.toUpperCase();this.routeDefinitions.push({method:o,path:a,options:{method:o,path:a,expose:!0}})}bulkAddRoutes(e){for(let t of e)this.addRoute(t)}addStaticRoute(e,t){let r=this.routeTable[e];if(r&&!(r instanceof Response))throw new Error(`Cannot register static route for path "${e}" because method routes already exist.`);this.routeTable[e]=t,this.removeRouteMatcher(e)}getRouteTable(){return this.routeTable}getRoutes(){let e=[];for(let t of this.routeMatchers){let r=this.routeTable[t.path];if(!r||r instanceof Response)continue;for(let[a,n]of Object.entries(r))e.push([a,t.regex,[n],t.path])}return e}getRouteDefinitions(){return[...this.routeDefinitions]}clearRoutes(){this.routeTable=Object.create(null),this.routeMatchers=[],this.routeDefinitions=[]}sortRoutes(){}async handle(e){let t;try{t=new URL(e.url)}catch{return D.badRequest("Malformed request URL")}let r=t.pathname,a=this.routeTable[r];if(a){if(a instanceof Response)return this.applyCorsResponse(a.clone(),e);let n=a,o=n[e.method]??(e.method==="HEAD"?n.GET:void 0);if(o){let i=await o(e);if(i)return i}}for(let n of this.routeMatchers){let o=n.path,i=this.routeTable[o];if(!i)continue;if(i instanceof Response){if(r===o)return this.applyCorsResponse(i.clone(),e);continue}let d=i,l=d[e.method]??(e.method==="HEAD"?d.GET:void 0);if(!l)continue;if(!r.match(n.regex))continue;let m=await l(e);if(m)return m}return this.applyCorsResponse(Xe.NOT_FOUND.clone(),e)}cloneMetadata(e){if(Array.isArray(e))return[...e];if(e&&typeof e==="object")return{...e};return e}createContext(e,t){let r={request:e};return this.setContextField(r,"metadata",t?.metadata!==void 0?this.cloneMetadata(t.metadata):{}),this.setContextField(r,"params",t?.params??{}),this.setContextField(r,"query",t?.query??{}),this.setContextField(r,"cookies",t?.cookies??{}),r}setContextField(e,t,r){e[t]=r}hasOwnContextField(e,t){return Object.prototype.hasOwnProperty.call(e,t)}buildCheckpointContextPayload(e){let t={},r=["metadata","content","validatedInput","authUser"];for(let a of r){if(!this.hasOwnContextField(e,a))continue;let n=e[a];if(typeof n==="function"||typeof n==="symbol"||n===void 0)continue;t[a]=n}return t}resolveFallbackParams(e,t){if(!t)return;let r=e.match(t);if(!r?.groups)return;return r.groups}getRequestedCheckpointVersion(e){if(!this.checkpointGateway)return null;let t=this.checkpointGateway;if(t?.getRequestedVersion)return t.getRequestedVersion(e);let r=e.headers.get("x-vector-checkpoint-version");if(r&&r.trim().length>0)return r.trim();let a=e.headers.get("x-vector-checkpoint");if(a&&a.trim().length>0)return a.trim();return null}getCheckpointCacheKeyOverrideValue(e){if(!this.checkpointGateway)return null;let t=this.checkpointGateway;if(t?.getCacheKeyOverrideValue)return t.getCacheKeyOverrideValue(e);let r=e.headers.get("x-vector-checkpoint-version");if(r&&r.trim().length>0)return`x-vector-checkpoint-version:${r.trim()}`;let a=e.headers.get("x-vector-checkpoint");if(a&&a.trim().length>0)return`x-vector-checkpoint:${a.trim()}`;return null}applyCheckpointCacheNamespace(e,t){let r=this.getRequestedCheckpointVersion(t);if(!r)return e;return`${e}:checkpoint=${r}`}applyCheckpointRouteKeyOverride(e,t){let r=this.getCheckpointCacheKeyOverrideValue(t);if(!r)return e;return r}async parseRequestBodyForContext(e,t,r){let a=null;try{let n=r?t.clone():t,o=n.headers.get("content-type");if(o?.startsWith("application/json"))a=await n.json();else if(o?.startsWith("application/x-www-form-urlencoded"))a=Object.fromEntries(await n.formData());else if(o?.startsWith("multipart/form-data"))a=await n.formData();else a=await n.text()}catch{a=null}this.setContextField(e,"content",a)}isLikelyStreamingBodyRequest(e){if(e.method==="GET"||e.method==="HEAD")return!1;if(!e.body)return!1;if(e.duplex==="half")return!0;let t=e.headers.get("transfer-encoding");if(t){if(t.split(",").some((a)=>a.trim().toLowerCase()==="chunked"))return!0}return!1}wrapHandler(e,t){let r=e.path,a=r.includes(":")?ge(r):null;return async(n)=>{let o=n,i="";try{i=new URL(n.url).pathname}catch{}let d=this.resolveFallbackParams(i,a),l=this.createContext(o,{metadata:e.metadata,params:this.getRequestParams(n,d),query:this.getRequestQuery(n),cookies:this.getRequestCookies(n)});try{if(e.expose===!1)return D.forbidden("Forbidden");let c=await this.middlewareManager.executeBefore(l);if(c instanceof Response)return c;if(e.auth)try{await this.authManager.authenticate(l)}catch(u){return D.unauthorized(u instanceof Error?u.message:"Authentication failed",e.responseContentType)}let m=async()=>{let u=l.request,w=u,R=this.getRequestedCheckpointVersion(w)!==null,E=this.isLikelyStreamingBodyRequest(w)&&e.schema?.input!==void 0&&e.validate!==!1;if(!e.rawRequest&&u.method!=="GET"&&u.method!=="HEAD"&&!E)await this.parseRequestBodyForContext(l,w,R);if(E){let H=await this.validateInputSchema(l,e,d,{includeBody:!1,allowBodyDeferral:!0});if(H.response)return H.response;if(H.requiresBody){if(!e.rawRequest&&u.method!=="GET"&&u.method!=="HEAD")await this.parseRequestBodyForContext(l,w,R);let Ve=await this.validateInputSchema(l,e,d);if(Ve.response)return Ve.response}}else{let H=await this.validateInputSchema(l,e,d);if(H.response)return H.response}if(this.checkpointGateway){let H=await this.checkpointGateway.handle(u,this.buildCheckpointContextPayload(l));if(H)return H}return await t(l)},s,p=e.cache;if(p&&typeof p==="number"&&p>0){let u=this.applyCheckpointCacheNamespace(this.cacheManager.generateKey(l.request,{authUser:l.authUser}),l.request);s=await this.cacheManager.get(u,async()=>await m(),p)}else if(p&&typeof p==="object"&&p.ttl){let u=typeof p.key==="string"&&p.key.length>0,w;if(u)w=this.applyCheckpointRouteKeyOverride(p.key,l.request);else{let R=this.cacheManager.generateKey(l.request,{authUser:l.authUser});w=this.applyCheckpointCacheNamespace(R,l.request)}s=await this.cacheManager.get(w,async()=>await m(),p.ttl)}else s=await m();if(s instanceof Response&&!!p)s=s.clone();let h;if(e.rawResponse||s instanceof Response)h=s instanceof Response?s:new Response(s);else h=_(200,s,e.responseContentType);return h=await this.middlewareManager.executeFinally(h,l),this.applyCorsResponse(h,l.request)}catch(c){if(c instanceof Response)return c;return console.error("Route handler error:",c),D.internalServerError(c instanceof Error?c.message:String(c),e.responseContentType)}}}isDevelopmentMode(){if(this.developmentMode!==void 0)return this.developmentMode;return(typeof Bun!=="undefined"?Bun.env.NODE_ENV:"development")!=="production"}async buildInputValidationPayload(e,t,r,a){let n=e.request,o=a?.includeBody!==!1,i=o&&this.hasOwnContextField(e,"content")?e.content:void 0;if(o&&t.rawRequest&&n.method!=="GET"&&n.method!=="HEAD")try{i=await n.clone().text()}catch{i=null}return{params:this.getRequestParams(n,r),query:this.getRequestQuery(n),headers:Object.fromEntries(n.headers.entries()),cookies:this.getRequestCookies(n),body:i}}getRequestParams(e,t){let r=this.readRequestObjectField(e,"params");if(r&&Object.keys(r).length>0)return r;return t??{}}getRequestQuery(e){let t=this.readRequestObjectField(e,"query");if(t)return t;try{return q.parseQuery(new URL(e.url))}catch{return{}}}getRequestCookies(e){let t=this.readRequestObjectField(e,"cookies");if(t)return t;return q.parseCookies(e.headers.get("cookie"))}readRequestObjectField(e,t){let r=e[t];if(!r||typeof r!=="object"||Array.isArray(r))return;return r}applyValidatedInput(e,t){this.setContextField(e,"validatedInput",t)}issueHasBodyPath(e){if(!e||typeof e!=="object"||!("path"in e))return!1;let t=e.path;if(!Array.isArray(t)||t.length===0)return!1;let r=t[0];if(r&&typeof r==="object"&&"key"in r)return r.key==="body";return r==="body"}issueHasExplicitNonBodyPath(e){if(!e||typeof e!=="object"||!("path"in e))return!1;let t=e.path;if(!Array.isArray(t)||t.length===0)return!1;let r=t[0];if(r&&typeof r==="object"&&"key"in r)return r.key!=="body";return r!=="body"}issueHasUnknownPath(e){if(!e||typeof e!=="object"||!("path"in e))return!0;let t=e.path;if(!Array.isArray(t))return!0;return t.length===0}shouldDeferBodyValidation(e,t,r){if(!(r?.allowBodyDeferral===!0&&r?.includeBody===!1))return!1;let a=t.request;if(!(a.method!=="GET"&&a.method!=="HEAD"&&a.body!==null)||e.length===0)return!1;if(e.some((d)=>this.issueHasBodyPath(d)))return!0;let o=e.some((d)=>this.issueHasExplicitNonBodyPath(d)),i=e.some((d)=>this.issueHasUnknownPath(d));return!o&&i}async validateInputSchema(e,t,r,a){let n=t.schema?.input;if(!n)return{response:null,requiresBody:!1};if(t.validate===!1)return{response:null,requiresBody:!1};if(!Ze(n))return{response:D.internalServerError("Invalid route schema configuration",t.responseContentType),requiresBody:!1};let o=this.isDevelopmentMode(),i=await this.buildInputValidationPayload(e,t,r,{includeBody:a?.includeBody});try{let d=await qe(n,i);if(d.success===!1){if(this.shouldDeferBodyValidation(d.issues,e,a))return{response:null,requiresBody:!0};let l=xe(d.issues,o);return{response:_(422,ve("input",l),t.responseContentType),requiresBody:!1}}return this.applyValidatedInput(e,d.value),{response:null,requiresBody:!1}}catch(d){let l=Ke(d);if(l){if(this.shouldDeferBodyValidation(l,e,a))return{response:null,requiresBody:!0};let c=xe(l,o);return{response:_(422,ve("input",c),t.responseContentType),requiresBody:!1}}return{response:D.internalServerError(d instanceof Error?d.message:"Validation failed",t.responseContentType),requiresBody:!1}}}getOrCreateMethodMap(e){let t=this.routeTable[e];if(t instanceof Response)throw new Error(`Cannot register method route for path "${e}" because a static route already exists.`);if(t)return t;let r=Object.create(null);return this.routeTable[e]=r,this.addRouteMatcher(e),r}addRouteMatcher(e){if(this.routeMatchers.some((t)=>t.path===e))return;this.routeMatchers.push({path:e,regex:ge(e),specificity:this.routeSpecificityScore(e)}),this.routeMatchers.sort((t,r)=>{if(t.specificity!==r.specificity)return r.specificity-t.specificity;return t.path.localeCompare(r.path)})}removeRouteMatcher(e){this.routeMatchers=this.routeMatchers.filter((t)=>t.path!==e)}static parseQuery(e){let t={};for(let[r,a]of e.searchParams)if(r in t){let n=t[r];if(Array.isArray(n))n.push(a);else t[r]=[n,a]}else t[r]=a;return t}static parseCookies(e){let t={};if(!e)return t;for(let r of e.split(";")){let a=r.indexOf("=");if(a>0)t[r.slice(0,a).trim()]=r.slice(a+1).trim()}return t}routeSpecificityScore(e){let o=e.split("/").filter(Boolean),i=0;for(let d of o)if(d.includes("*"))i+=1;else if(d.startsWith(":"))i+=10;else i+=1000;if(i+=e.length,!e.includes(":")&&!e.includes("*"))i+=1e4;return i}applyCorsResponse(e,t){let r=this.corsHeadersEntries;if(r){for(let[n,o]of r)e.headers.set(n,o);return e}let a=this.corsHandler;if(a)return a(e,t);return e}}var Se=require("fs"),gt=require("path");function et(e,t){if(!e){if(typeof t.origin==="string"){if(t.origin==="*"&&t.credentials)return null;return t.origin}return null}if(typeof t.origin==="string"){if(t.origin==="*")return t.credentials?e:"*";return t.origin===e?e:null}if(Array.isArray(t.origin))return t.origin.includes(e)?e:null;if(typeof t.origin==="function")return t.origin(e)?e:null;return null}function tt(e){return typeof e.origin==="string"&&e.origin==="*"&&e.credentials||Array.isArray(e.origin)||typeof e.origin==="function"}function rt(e,t,r){let a={};if(e){if(a["access-control-allow-origin"]=e,a["access-control-allow-methods"]=t.allowMethods,a["access-control-allow-headers"]=t.allowHeaders,a["access-control-expose-headers"]=t.exposeHeaders,a["access-control-max-age"]=String(t.maxAge),t.credentials)a["access-control-allow-credentials"]="true";if(r)a.vary="Origin"}return a}function wr(e,t){if(!e)return t;let r=e.split(",").map((n)=>n.trim()).filter(Boolean);if(!r.map((n)=>n.toLowerCase()).includes(t.toLowerCase()))r.push(t);return r.join(", ")}function at(e){return{preflight(t){let r=t.headers.get("origin")??void 0,a=et(r,e),n=Boolean(r&&a&&tt(e));return new Response(null,{status:204,headers:rt(a,e,n)})},corsify(t,r){let a=r.headers.get("origin")??void 0,n=et(a,e);if(!n)return t;let o=Boolean(a&&tt(e)),i=rt(n,e,o);for(let[d,l]of Object.entries(i)){if(d==="vary"){t.headers.set("vary",wr(t.headers.get("vary"),l));continue}t.headers.set(d,l)}return t}}}function nt(e,t,r,a,n,o,i,d,l){let c=JSON.stringify(e).replace(/<\/script/gi,"<\\/script"),m=JSON.stringify(t),s=JSON.stringify(r),p=JSON.stringify(a),h=JSON.stringify(n),u=JSON.stringify(o),w=JSON.stringify(i),R=JSON.stringify(d),E=JSON.stringify(l);return`<!DOCTYPE html>
210
+ <html lang="en">
211
+ <head>
212
+ <meta charset="UTF-8">
213
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
214
+ <title>Vector API Documentation</title>
215
+ <link rel="apple-touch-icon" sizes="180x180" href=${u}>
216
+ <link rel="icon" type="image/png" sizes="32x32" href=${w}>
217
+ <link rel="icon" type="image/png" sizes="16x16" href=${R}>
218
+ <link rel="manifest" href=${E}>
219
+ <script>
220
+ if (localStorage.getItem('theme') === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
221
+ document.documentElement.classList.add('dark');
222
+ } else {
223
+ document.documentElement.classList.remove('dark');
224
+ }
225
+ </script>
226
+ <script src=${s}></script>
227
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
228
+ <script>
229
+ tailwind.config = {
230
+ darkMode: 'class',
231
+ theme: {
232
+ extend: {
233
+ colors: {
234
+ brand: {
235
+ DEFAULT: '#00A1FF',
236
+ mint: '#00FF8F',
237
+ soft: '#E4F5FF',
238
+ deep: '#007BC5',
239
+ },
240
+ dark: { bg: '#0A0A0A', surface: '#111111', border: '#1F1F1F', text: '#EDEDED' },
241
+ light: { bg: '#FFFFFF', surface: '#F9F9F9', border: '#E5E5E5', text: '#111111' }
242
+ },
243
+ fontFamily: {
244
+ sans: ['Inter', 'sans-serif'],
245
+ mono: ['JetBrains Mono', 'monospace'],
246
+ }
247
+ }
248
+ }
249
+ };
250
+ </script>
251
+ <style>
252
+ :root {
253
+ --motion-fast: 180ms;
254
+ --motion-base: 280ms;
255
+ --motion-slow: 420ms;
256
+ --motion-ease: cubic-bezier(0.22, 1, 0.36, 1);
257
+ }
258
+ ::-webkit-scrollbar { width: 8px; height: 8px; }
259
+ ::-webkit-scrollbar-track { background: transparent; }
260
+ ::-webkit-scrollbar-thumb { background: #333; border-radius: 4px; }
261
+ body { transition: background-color 150ms ease, color 150ms ease; }
262
+ #sidebar-nav a,
263
+ #send-btn,
264
+ #copy-curl,
265
+ #add-header-btn,
266
+ #expand-body-btn,
267
+ #expand-response-btn,
268
+ #expand-close,
269
+ #expand-apply {
270
+ transition:
271
+ transform var(--motion-fast) var(--motion-ease),
272
+ opacity var(--motion-fast) var(--motion-ease),
273
+ border-color var(--motion-fast) var(--motion-ease),
274
+ background-color var(--motion-fast) var(--motion-ease),
275
+ color var(--motion-fast) var(--motion-ease);
276
+ will-change: transform, opacity;
277
+ }
278
+ #sidebar-nav a:hover,
279
+ #send-btn:hover,
280
+ #add-header-btn:hover,
281
+ #expand-body-btn:hover,
282
+ #expand-response-btn:hover {
283
+ transform: translateY(-1px);
284
+ }
285
+ #endpoint-card {
286
+ transition:
287
+ box-shadow var(--motion-base) var(--motion-ease),
288
+ transform var(--motion-base) var(--motion-ease),
289
+ opacity var(--motion-base) var(--motion-ease);
290
+ }
291
+ .enter-fade-up {
292
+ animation: enterFadeUp var(--motion-base) var(--motion-ease) both;
293
+ }
294
+ .enter-stagger {
295
+ animation: enterStagger var(--motion-base) var(--motion-ease) both;
296
+ animation-delay: var(--stagger-delay, 0ms);
297
+ }
298
+ @keyframes enterFadeUp {
299
+ from { opacity: 0; transform: translateY(8px); }
300
+ to { opacity: 1; transform: translateY(0); }
301
+ }
302
+ @keyframes enterStagger {
303
+ from { opacity: 0; transform: translateX(-6px); }
304
+ to { opacity: 1; transform: translateX(0); }
305
+ }
306
+ @keyframes spin {
307
+ to { transform: rotate(360deg); }
308
+ }
309
+ .button-spinner {
310
+ display: inline-block;
311
+ width: 0.875rem;
312
+ height: 0.875rem;
313
+ border: 2px solid currentColor;
314
+ border-right-color: transparent;
315
+ border-radius: 9999px;
316
+ animation: spin 700ms linear infinite;
317
+ }
318
+ @media (prefers-reduced-motion: reduce) {
319
+ *, *::before, *::after {
320
+ animation: none !important;
321
+ transition: none !important;
322
+ }
323
+ }
324
+ .json-key { color: #007bc5; }
325
+ .json-string { color: #334155; }
326
+ .json-number { color: #00a1ff; }
327
+ .json-boolean { color: #475569; }
328
+ .json-null { color: #64748b; }
329
+ .dark .json-key { color: #7dc9ff; }
330
+ .dark .json-string { color: #d1d9e6; }
331
+ .dark .json-number { color: #7dc9ff; }
332
+ .dark .json-boolean { color: #93a4bf; }
333
+ .dark .json-null { color: #7c8ba3; }
334
+ .param-row {
335
+ --param-row-bg-rgb: 255 255 255;
336
+ }
337
+ .dark .param-row {
338
+ --param-row-bg-rgb: 10 10 10;
339
+ }
340
+ .param-row-head {
341
+ display: grid;
342
+ grid-template-columns: minmax(0, 1fr) auto;
343
+ align-items: center;
344
+ gap: 0.5rem;
345
+ min-width: 0;
346
+ width: 100%;
347
+ }
348
+ .param-row-main {
349
+ min-width: 0;
350
+ display: flex;
351
+ align-items: center;
352
+ gap: 0.4rem;
353
+ overflow: hidden;
354
+ }
355
+ .param-tooltip-trigger {
356
+ border: 0;
357
+ margin: 0;
358
+ padding: 0;
359
+ background: transparent;
360
+ color: inherit;
361
+ cursor: pointer;
362
+ font: inherit;
363
+ text-align: left;
364
+ min-width: 0;
365
+ }
366
+ .param-tooltip-trigger:focus-visible {
367
+ outline: 2px solid rgba(0, 161, 255, 0.65);
368
+ outline-offset: 2px;
369
+ border-radius: 0.375rem;
370
+ }
371
+ .param-name-trigger {
372
+ min-width: 0;
373
+ flex: 1 1 auto;
374
+ overflow: hidden;
375
+ }
376
+ .param-name-text {
377
+ display: block;
378
+ max-width: 100%;
379
+ overflow: hidden;
380
+ text-overflow: ellipsis;
381
+ white-space: nowrap;
382
+ mask-image: linear-gradient(to right, #000 0%, #000 calc(100% - 18px), transparent 100%);
383
+ -webkit-mask-image: linear-gradient(to right, #000 0%, #000 calc(100% - 18px), transparent 100%);
384
+ }
385
+ .param-type-fade {
386
+ position: relative;
387
+ z-index: 1;
388
+ display: block;
389
+ max-width: none;
390
+ overflow: visible;
391
+ text-overflow: clip;
392
+ padding-left: 1.25rem;
393
+ white-space: nowrap;
394
+ text-align: left;
395
+ justify-self: end;
396
+ background: linear-gradient(
397
+ 90deg,
398
+ rgba(var(--param-row-bg-rgb), 0) 0%,
399
+ rgba(var(--param-row-bg-rgb), 0.76) 36%,
400
+ rgba(var(--param-row-bg-rgb), 0.94) 68%,
401
+ rgba(var(--param-row-bg-rgb), 1) 100%
402
+ );
403
+ }
404
+ #param-value-tooltip {
405
+ position: fixed;
406
+ top: 0;
407
+ left: 0;
408
+ z-index: 70;
409
+ width: min(42rem, calc(100vw - 0.75rem));
410
+ border-radius: 0.5rem;
411
+ border: 1px solid rgba(15, 23, 42, 0.12);
412
+ background: rgba(255, 255, 255, 0.92);
413
+ color: #111111;
414
+ box-shadow: 0 10px 20px rgba(15, 23, 42, 0.14);
415
+ backdrop-filter: blur(12px) saturate(145%);
416
+ -webkit-backdrop-filter: blur(12px) saturate(145%);
417
+ padding: 0.4rem 0.6rem;
418
+ opacity: 0;
419
+ pointer-events: none;
420
+ transform: translateY(6px) scale(0.98);
421
+ transition:
422
+ opacity var(--motion-fast) var(--motion-ease),
423
+ transform var(--motion-fast) var(--motion-ease);
424
+ }
425
+ #param-value-tooltip.is-visible {
426
+ opacity: 1;
427
+ pointer-events: auto;
428
+ transform: translateY(0) scale(1);
429
+ }
430
+ .dark #param-value-tooltip {
431
+ border-color: rgba(148, 163, 184, 0.24);
432
+ background: rgba(17, 17, 17, 0.9);
433
+ color: #ededed;
434
+ box-shadow: 0 14px 30px rgba(0, 0, 0, 0.45);
435
+ }
436
+ #param-tooltip-line {
437
+ margin: 0;
438
+ font-size: 11px;
439
+ line-height: 1.3;
440
+ font-family: "JetBrains Mono", monospace;
441
+ white-space: normal;
442
+ word-break: break-word;
443
+ }
444
+ #param-tooltip-description {
445
+ margin: 0.2rem 0 0;
446
+ font-size: 11px;
447
+ line-height: 1.3;
448
+ opacity: 0.8;
449
+ white-space: normal;
450
+ word-break: break-word;
451
+ }
452
+ </style>
453
+ </head>
454
+ <body class="bg-light-bg text-light-text dark:bg-dark-bg dark:text-dark-text font-sans antialiased flex h-screen overflow-hidden">
455
+ <div id="mobile-backdrop" class="fixed inset-0 z-30 bg-black/40 opacity-0 pointer-events-none transition-opacity duration-300 md:hidden"></div>
456
+ <aside id="docs-sidebar" class="fixed inset-y-0 left-0 z-40 w-72 md:w-64 border-r border-light-border dark:border-dark-border bg-light-surface dark:bg-dark-surface flex flex-col flex-shrink-0 transition-transform duration-300 ease-out -translate-x-full md:translate-x-0 md:static md:z-auto transition-colors duration-150">
457
+ <div class="h-14 flex items-center px-5 border-b border-light-border dark:border-dark-border">
458
+ <div class="flex items-center">
459
+ <img src=${p} alt="Vector" class="h-6 w-auto block dark:hidden" />
460
+ <img src=${h} alt="Vector" class="h-6 w-auto hidden dark:block" />
461
+ </div>
462
+ <button id="sidebar-close" class="ml-auto p-1.5 rounded-full border border-light-border dark:border-dark-border bg-light-bg/90 dark:bg-dark-bg/90 opacity-90 hover:opacity-100 transition md:hidden" aria-label="Close Menu" title="Close Menu">
463
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
464
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
465
+ </svg>
466
+ </button>
467
+ </div>
468
+ <div class="p-4">
469
+ <div class="relative">
470
+ <svg class="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 opacity-60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
471
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
472
+ </svg>
473
+ <input
474
+ id="sidebar-search"
475
+ type="text"
476
+ placeholder="Search routes..."
477
+ class="w-full pl-9 pr-3 py-2 text-sm rounded-md border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg focus:outline-none focus:border-brand dark:focus:border-brand transition-colors"
478
+ />
479
+ </div>
480
+ </div>
481
+ <div id="auth-panel" class="border-b border-light-border dark:border-dark-border">
482
+ <button id="auth-toggle" class="w-full flex items-center justify-between px-4 py-2.5 text-xs font-semibold uppercase tracking-wider opacity-60 hover:opacity-100 transition-opacity">
483
+ <span class="flex items-center gap-1.5">
484
+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path></svg>
485
+ Auth
486
+ </span>
487
+ <svg id="auth-chevron" class="w-3.5 h-3.5 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
488
+ </button>
489
+ <div id="auth-fields" class="px-4 pb-3 space-y-2"></div>
490
+ </div>
491
+ <nav class="flex-1 overflow-y-auto px-3 py-2 space-y-6 text-sm" id="sidebar-nav"></nav>
492
+ </aside>
493
+
494
+ <main class="flex-1 flex flex-col min-w-0 relative">
495
+ <header class="h-14 flex items-center justify-between px-6 border-b border-light-border dark:border-dark-border lg:border-none lg:bg-transparent absolute top-0 w-full z-10 bg-light-bg/80 dark:bg-dark-bg/80 backdrop-blur-sm transition-colors duration-150">
496
+ <div class="md:hidden flex items-center gap-2">
497
+ <button id="sidebar-open" class="p-1.5 rounded-full border border-light-border dark:border-dark-border bg-light-bg/90 dark:bg-dark-bg/90 opacity-90 hover:opacity-100 transition" aria-label="Open Menu" title="Open Menu">
498
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
499
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
500
+ </svg>
501
+ </button>
502
+ <img src=${p} alt="Vector" class="h-5 w-auto block dark:hidden" />
503
+ <img src=${h} alt="Vector" class="h-5 w-auto hidden dark:block" />
504
+ </div>
505
+ <div class="flex-1"></div>
506
+ <button id="theme-toggle" class="p-2 rounded-md hover:bg-black/5 dark:hover:bg-white/5 transition-colors" aria-label="Toggle Dark Mode">
507
+ <svg class="w-5 h-5 hidden dark:block text-dark-text" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path></svg>
508
+ <svg class="w-5 h-5 block dark:hidden text-light-text" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path></svg>
509
+ </button>
510
+ </header>
511
+
512
+ <div class="flex-1 overflow-y-auto pt-14 pb-24">
513
+ <div class="max-w-[860px] mx-auto px-6 py-12 lg:py-16">
514
+ <div class="mb-12">
515
+ <h1 class="text-4xl font-bold tracking-tight mb-4" id="tag-title">API</h1>
516
+ <p class="text-lg opacity-80 max-w-2xl leading-relaxed" id="tag-description">Interactive API documentation.</p>
517
+ </div>
518
+ <hr class="border-t border-light-border dark:border-dark-border mb-12">
519
+ <div class="mb-20" id="endpoint-card">
520
+ <div class="flex items-center gap-3 mb-4">
521
+ <span id="endpoint-method" class="px-2.5 py-0.5 rounded-full text-xs font-mono font-medium"></span>
522
+ <h2 class="text-xl font-semibold tracking-tight" id="endpoint-title">Operation</h2>
523
+ </div>
524
+ <div id="deprecated-banner" class="hidden mb-4 px-3 py-2 rounded border border-amber-300 dark:border-amber-700 bg-amber-50 dark:bg-amber-900/20 text-amber-700 dark:text-amber-400 text-xs font-medium">
525
+ ! This operation is deprecated
526
+ </div>
527
+ <p class="text-sm opacity-80 mb-8 font-mono" id="endpoint-path">/</p>
528
+ <div class="grid grid-cols-1 lg:grid-cols-12 gap-10">
529
+ <div class="lg:col-span-5 space-y-8" id="params-column"></div>
530
+ <div class="lg:col-span-7">
531
+ <div class="rounded-lg border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg overflow-hidden group">
532
+ <div class="flex items-center justify-between px-4 py-2 border-b border-light-border dark:border-dark-border bg-light-surface dark:bg-dark-surface">
533
+ <span class="text-xs font-mono text-light-text/70 dark:text-dark-text/70">cURL</span>
534
+ <button class="text-xs text-light-text/50 hover:text-light-text dark:text-dark-text/50 dark:hover:text-dark-text transition-colors" id="copy-curl">Copy</button>
535
+ </div>
536
+ <pre class="p-4 text-sm font-mono text-light-text dark:text-dark-text overflow-x-auto leading-relaxed"><code id="curl-code"></code></pre>
537
+ </div>
538
+ <div class="mt-4 p-4 rounded-lg border border-light-border dark:border-dark-border bg-light-surface dark:bg-dark-surface">
539
+ <div class="flex items-center justify-between mb-3">
540
+ <h4 class="text-sm font-medium">Try it out</h4>
541
+ <button id="send-btn" class="px-4 py-1.5 bg-brand text-white text-sm font-semibold rounded hover:bg-brand-deep transition-colors">
542
+ <span class="inline-flex items-center gap-2">
543
+ <span id="send-btn-spinner" class="button-spinner hidden" aria-hidden="true"></span>
544
+ <span id="send-btn-label">Submit</span>
545
+ </span>
546
+ </button>
547
+ </div>
548
+ <div class="space-y-4">
549
+ <div>
550
+ <div id="request-param-inputs" class="space-y-3"></div>
551
+ </div>
552
+
553
+ <div>
554
+ <div class="flex items-center justify-between mb-2">
555
+ <p class="text-xs font-semibold uppercase tracking-wider opacity-60">Headers</p>
556
+ <button id="add-header-btn" class="p-1.5 rounded-full border border-light-border dark:border-dark-border bg-light-bg/90 dark:bg-dark-bg/90 opacity-90 hover:opacity-100 hover:border-brand/60 transition-colors" aria-label="Add Header" title="Add Header">
557
+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
558
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v14m-7-7h14"></path>
559
+ </svg>
560
+ </button>
561
+ </div>
562
+ <div id="header-inputs" class="space-y-2"></div>
563
+ </div>
564
+
565
+ <div id="request-body-section">
566
+ <div class="flex items-center justify-between mb-2">
567
+ <p class="text-xs font-semibold uppercase tracking-wider opacity-60">Request Body</p>
568
+ </div>
569
+ <div class="relative h-40 rounded border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg overflow-hidden">
570
+ <pre id="body-highlight" class="absolute inset-0 m-0 p-3 pr-11 text-xs font-mono leading-5 overflow-auto whitespace-pre-wrap break-words pointer-events-none"></pre>
571
+ <textarea id="body-input" class="absolute inset-0 w-full h-full p-3 pr-11 text-xs font-mono leading-5 bg-transparent text-transparent caret-black dark:caret-white resize-none focus:outline-none overflow-auto placeholder:text-light-text/50 dark:placeholder:text-dark-text/40" placeholder='{"key":"value"}' spellcheck="false" autocapitalize="off" autocorrect="off"></textarea>
572
+ <button id="expand-body-btn" class="absolute bottom-2 right-2 p-1.5 rounded-full border border-light-border dark:border-dark-border bg-light-surface/95 dark:bg-dark-surface/95 opacity-90 hover:opacity-100 hover:border-brand/60 transition-colors" aria-label="Expand Request Body" title="Expand Request Body">
573
+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
574
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 9V4h5M20 15v5h-5M15 4h5v5M9 20H4v-5"></path>
575
+ </svg>
576
+ </button>
577
+ </div>
578
+ </div>
579
+
580
+ <div id="response-section">
581
+ <div class="flex items-center justify-between mb-2">
582
+ <p class="text-xs font-semibold uppercase tracking-wider opacity-60">Response</p>
583
+ </div>
584
+ <div class="relative">
585
+ <pre id="result" class="p-3 pr-11 text-xs font-mono rounded border border-light-border dark:border-dark-border overflow-x-auto min-h-[140px]"></pre>
586
+ <button id="expand-response-btn" class="absolute bottom-2 right-2 p-1.5 rounded-full border border-light-border dark:border-dark-border bg-light-surface/95 dark:bg-dark-surface/95 opacity-90 hover:opacity-100 hover:border-brand/60 transition-colors" aria-label="Expand Response" title="Expand Response">
587
+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
588
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 9V4h5M20 15v5h-5M15 4h5v5M9 20H4v-5"></path>
589
+ </svg>
590
+ </button>
591
+ </div>
592
+ </div>
593
+ </div>
594
+ </div>
595
+ </div>
596
+ </div>
597
+ </div>
598
+ </div>
599
+ </div>
600
+ </main>
601
+
602
+ <div id="expand-modal" class="fixed inset-0 z-50 hidden items-center justify-center bg-black/60 p-4">
603
+ <div class="w-full max-w-5xl rounded-lg border border-light-border dark:border-dark-border bg-light-surface dark:bg-dark-surface p-4">
604
+ <div class="flex items-center justify-between mb-3">
605
+ <h3 id="expand-modal-title" class="text-sm font-semibold">Expanded View</h3>
606
+ <div class="flex items-center gap-2">
607
+ <button id="expand-apply" class="hidden text-sm px-3 py-1.5 rounded bg-brand text-white font-semibold hover:bg-brand-deep transition-colors">Apply</button>
608
+ <button id="expand-close" class="p-1.5 rounded-full border border-light-border dark:border-dark-border bg-light-bg/90 dark:bg-dark-bg/90 opacity-90 hover:opacity-100 hover:border-brand/60 transition-colors" aria-label="Close Modal" title="Close Modal">
609
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
610
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
611
+ </svg>
612
+ </button>
613
+ </div>
614
+ </div>
615
+ <div id="expand-editor-shell" class="hidden relative w-full h-[70vh] rounded border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg overflow-hidden">
616
+ <pre id="expand-editor-highlight" class="absolute inset-0 m-0 p-3 text-sm font-mono leading-6 overflow-auto whitespace-pre-wrap break-words pointer-events-none"></pre>
617
+ <textarea id="expand-editor" class="absolute inset-0 w-full h-full p-3 text-sm font-mono leading-6 bg-transparent text-transparent caret-black dark:caret-white resize-none focus:outline-none overflow-auto" spellcheck="false" autocapitalize="off" autocorrect="off"></textarea>
618
+ </div>
619
+ <pre id="expand-viewer" class="hidden w-full h-[70vh] text-sm p-3 rounded border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg overflow-auto font-mono"></pre>
620
+ </div>
621
+ </div>
622
+ <div id="param-value-tooltip" aria-hidden="true" role="tooltip">
623
+ <p id="param-tooltip-line"></p>
624
+ <p id="param-tooltip-description" class="hidden"></p>
625
+ </div>
626
+
627
+ <script>
628
+ const spec = ${c};
629
+ const openapiPath = ${m};
630
+ const methodBadgeDefault = "bg-black/5 text-light-text/80 dark:bg-white/10 dark:text-dark-text/80";
631
+ const methodBadge = {
632
+ GET: "bg-brand-soft text-brand-deep dark:bg-brand/20 dark:text-brand",
633
+ POST: "bg-brand-soft text-brand-deep dark:bg-brand/20 dark:text-brand",
634
+ PUT: "bg-brand-soft text-brand-deep dark:bg-brand/20 dark:text-brand",
635
+ PATCH: "bg-brand-soft text-brand-deep dark:bg-brand/20 dark:text-brand",
636
+ DELETE: "bg-brand-soft text-brand-deep dark:bg-brand/20 dark:text-brand",
637
+ };
638
+
639
+ function getOperations() {
640
+ const httpMethods = new Set([
641
+ "get",
642
+ "post",
643
+ "put",
644
+ "patch",
645
+ "delete",
646
+ "head",
647
+ "options",
648
+ ]);
649
+
650
+ const humanizePath = (path) =>
651
+ path
652
+ .replace(/^\\/+/, "")
653
+ .replace(/[{}]/g, "")
654
+ .replace(/[\\/_]+/g, " ")
655
+ .trim() || "root";
656
+
657
+ const toTitleCase = (value) =>
658
+ value.replace(/\\w\\S*/g, (word) => word.charAt(0).toUpperCase() + word.slice(1));
659
+
660
+ const getDisplayName = (op, method, path) => {
661
+ if (typeof op.summary === "string" && op.summary.trim()) {
662
+ return op.summary.trim();
663
+ }
664
+
665
+ if (typeof op.operationId === "string" && op.operationId.trim()) {
666
+ const withoutPrefix = op.operationId.replace(
667
+ new RegExp("^" + method + "_+", "i"),
668
+ "",
669
+ );
670
+ const readable = withoutPrefix.replace(/_+/g, " ").trim();
671
+ if (readable) return toTitleCase(readable);
672
+ }
673
+
674
+ return toTitleCase(humanizePath(path));
675
+ };
676
+
677
+ const ops = [];
678
+ const paths = spec.paths || {};
679
+ for (const path of Object.keys(paths)) {
680
+ const methods = paths[path] || {};
681
+ for (const method of Object.keys(methods)) {
682
+ if (!httpMethods.has(method)) continue;
683
+ const op = methods[method];
684
+ ops.push({
685
+ path,
686
+ method: method.toUpperCase(),
687
+ operation: op,
688
+ tag: (op.tags && op.tags[0]) || "default",
689
+ name: getDisplayName(op, method, path),
690
+ });
691
+ }
692
+ }
693
+ return ops;
694
+ }
695
+
696
+ const AUTH_STATE_KEY = "vector-docs-auth-v1";
697
+ const AUTH_SELECTION_KEY = "vector-docs-auth-selection-v1";
698
+ const HEADERS_STATE_KEY = "vector-docs-headers-v1";
699
+
700
+ function loadSavedHeaders() {
701
+ try {
702
+ const raw = localStorage.getItem(HEADERS_STATE_KEY);
703
+ if (raw) {
704
+ const parsed = JSON.parse(raw);
705
+ if (Array.isArray(parsed) && parsed.length > 0) return parsed;
706
+ }
707
+ } catch {}
708
+ return [{ key: "", value: "" }];
709
+ }
710
+
711
+ function saveHeaders() {
712
+ try { localStorage.setItem(HEADERS_STATE_KEY, JSON.stringify(requestHeaders)); } catch {}
713
+ }
714
+
715
+ function loadAuthState() {
716
+ try {
717
+ const raw = localStorage.getItem(AUTH_STATE_KEY);
718
+ if (raw) return JSON.parse(raw);
719
+ } catch {}
720
+ return {};
721
+ }
722
+
723
+ function saveAuthState() {
724
+ try { localStorage.setItem(AUTH_STATE_KEY, JSON.stringify(authState)); } catch {}
725
+ }
726
+
727
+ function loadAuthSelectionState() {
728
+ try {
729
+ const raw = localStorage.getItem(AUTH_SELECTION_KEY);
730
+ if (raw) {
731
+ const parsed = JSON.parse(raw);
732
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
733
+ return parsed;
734
+ }
735
+ }
736
+ } catch {}
737
+ return {};
738
+ }
739
+
740
+ function saveAuthSelectionState() {
741
+ try { localStorage.setItem(AUTH_SELECTION_KEY, JSON.stringify(authSelectionState)); } catch {}
742
+ }
743
+
744
+ const authSchemes = (spec.components && spec.components.securitySchemes) || {};
745
+ let authState = loadAuthState();
746
+ let authSelectionState = loadAuthSelectionState();
747
+
748
+ const operations = getOperations();
749
+ let selected = operations[0] || null;
750
+ const operationParamValues = new Map();
751
+ const operationBodyDrafts = new Map();
752
+ const requestHeaders = loadSavedHeaders();
753
+ let expandModalMode = null;
754
+ let isMobileSidebarOpen = false;
755
+ let sidebarSearchQuery = "";
756
+ const paramTooltipRoot = document.getElementById("param-value-tooltip");
757
+ const paramTooltipLine = document.getElementById("param-tooltip-line");
758
+ const paramTooltipDescription = document.getElementById("param-tooltip-description");
759
+ let activeParamTooltipTrigger = null;
760
+ let paramTooltipHideTimer = null;
761
+
762
+ function setMobileSidebarOpen(open) {
763
+ const sidebar = document.getElementById("docs-sidebar");
764
+ const backdrop = document.getElementById("mobile-backdrop");
765
+ const openBtn = document.getElementById("sidebar-open");
766
+ if (!sidebar || !backdrop || !openBtn) return;
767
+
768
+ isMobileSidebarOpen = open;
769
+ sidebar.classList.toggle("-translate-x-full", !open);
770
+ backdrop.classList.toggle("opacity-0", !open);
771
+ backdrop.classList.toggle("pointer-events-none", !open);
772
+ openBtn.setAttribute("aria-expanded", open ? "true" : "false");
773
+ document.body.classList.toggle("overflow-hidden", open);
774
+ }
775
+
776
+ function getOperationKey(op) {
777
+ return op.method + " " + op.path;
778
+ }
779
+
780
+ function getOpHash(op) {
781
+ var tag = op.tag || "default";
782
+ var id = (op.operation && op.operation.operationId)
783
+ ? op.operation.operationId
784
+ : op.method.toLowerCase() + "_" + op.path.split("/").filter(Boolean).join("_").replace(/[{}]/g, "");
785
+ return "#/" + encodeURIComponent(tag) + "/" + encodeURIComponent(id);
786
+ }
787
+
788
+ function findOpByHash(hash) {
789
+ if (!hash || hash.length <= 1) return null;
790
+ var parts = hash.slice(1).split("/").filter(Boolean);
791
+ if (parts.length < 2) return null;
792
+ var hashTag = decodeURIComponent(parts[0]);
793
+ var hashId = decodeURIComponent(parts[1]);
794
+ return operations.find(function(op) {
795
+ if (op.tag !== hashTag) return false;
796
+ var id = (op.operation && op.operation.operationId)
797
+ ? op.operation.operationId
798
+ : op.method.toLowerCase() + "_" + op.path.split("/").filter(Boolean).join("_").replace(/[{}]/g, "");
799
+ return id === hashId;
800
+ }) || null;
801
+ }
802
+
803
+ function getOperationParameterGroups(op) {
804
+ const params =
805
+ op &&
806
+ op.operation &&
807
+ Array.isArray(op.operation.parameters)
808
+ ? op.operation.parameters
809
+ : [];
810
+
811
+ return {
812
+ all: params,
813
+ path: params.filter((p) => p.in === "path"),
814
+ query: params.filter((p) => p.in === "query"),
815
+ headers: params.filter((p) => p.in === "header"),
816
+ };
817
+ }
818
+
819
+ function getParameterValues(op) {
820
+ const key = getOperationKey(op);
821
+ if (!operationParamValues.has(key)) {
822
+ operationParamValues.set(key, {});
823
+ }
824
+ return operationParamValues.get(key);
825
+ }
826
+
827
+ function getBodyDraft(op) {
828
+ const key = getOperationKey(op);
829
+ return operationBodyDrafts.get(key);
830
+ }
831
+
832
+ function setBodyDraft(op, bodyValue) {
833
+ const key = getOperationKey(op);
834
+ operationBodyDrafts.set(key, bodyValue);
835
+ }
836
+
837
+ function resolvePath(pathTemplate, pathParams, values) {
838
+ let resolved = pathTemplate;
839
+ for (const param of pathParams) {
840
+ const rawValue = values[param.name];
841
+ if (rawValue === undefined || rawValue === null || rawValue === "") {
842
+ continue;
843
+ }
844
+ const placeholder = "{" + param.name + "}";
845
+ resolved = resolved
846
+ .split(placeholder)
847
+ .join(encodeURIComponent(String(rawValue)));
848
+ }
849
+ return resolved;
850
+ }
851
+
852
+ function buildRequestPath(op, pathParams, queryParams, values, extraQuery) {
853
+ const resolvedPath = resolvePath(op.path, pathParams, values);
854
+ const query = new URLSearchParams();
855
+
856
+ for (const param of queryParams) {
857
+ const rawValue = values[param.name];
858
+ if (rawValue === undefined || rawValue === null || rawValue === "") {
859
+ continue;
860
+ }
861
+ query.append(param.name, String(rawValue));
862
+ }
863
+
864
+ if (extraQuery) {
865
+ for (const key of Object.keys(extraQuery)) {
866
+ const val = extraQuery[key];
867
+ if (val) query.set(key, String(val));
868
+ }
869
+ }
870
+
871
+ const queryString = query.toString();
872
+ return queryString ? resolvedPath + "?" + queryString : resolvedPath;
873
+ }
874
+
875
+ function schemaDefaultValue(schema) {
876
+ if (!schema || typeof schema !== "object") return null;
877
+ if (schema.default !== undefined) return schema.default;
878
+ if (schema.example !== undefined) return schema.example;
879
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum[0];
880
+ if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
881
+ return schemaDefaultValue(schema.oneOf[0]);
882
+ }
883
+ if (Array.isArray(schema.anyOf) && schema.anyOf.length > 0) {
884
+ return schemaDefaultValue(schema.anyOf[0]);
885
+ }
886
+ if (Array.isArray(schema.allOf) && schema.allOf.length > 0) {
887
+ return schemaDefaultValue(schema.allOf[0]);
888
+ }
889
+
890
+ switch (schema.type) {
891
+ case "string":
892
+ return "";
893
+ case "number":
894
+ case "integer":
895
+ return 0;
896
+ case "boolean":
897
+ return false;
898
+ case "array":
899
+ return [];
900
+ case "object": {
901
+ const required = Array.isArray(schema.required) ? schema.required : [];
902
+ const properties = schema.properties && typeof schema.properties === "object"
903
+ ? schema.properties
904
+ : {};
905
+ const obj = {};
906
+ for (const fieldName of required) {
907
+ obj[fieldName] = schemaDefaultValue(properties[fieldName]);
908
+ }
909
+ return obj;
910
+ }
911
+ default:
912
+ return null;
913
+ }
914
+ }
915
+
916
+ function buildRequiredBodyPrefill(schema) {
917
+ if (!schema || typeof schema !== "object") return "";
918
+ const prefillValue = schemaDefaultValue(schema);
919
+ if (
920
+ prefillValue &&
921
+ typeof prefillValue === "object" &&
922
+ !Array.isArray(prefillValue) &&
923
+ Object.keys(prefillValue).length === 0
924
+ ) {
925
+ return "";
926
+ }
927
+ try {
928
+ return JSON.stringify(prefillValue, null, 2);
929
+ } catch {
930
+ return "";
931
+ }
932
+ }
933
+
934
+ function hasMeaningfulRequestBodySchema(schema) {
935
+ if (!schema || typeof schema !== "object") return false;
936
+ if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) return true;
937
+ if (Array.isArray(schema.anyOf) && schema.anyOf.length > 0) return true;
938
+ if (Array.isArray(schema.allOf) && schema.allOf.length > 0) return true;
939
+ if (schema.type && schema.type !== "object") return true;
940
+ if (schema.additionalProperties !== undefined) return true;
941
+ if (Array.isArray(schema.required) && schema.required.length > 0) return true;
942
+ if (schema.properties && typeof schema.properties === "object") {
943
+ return Object.keys(schema.properties).length > 0;
944
+ }
945
+ return false;
946
+ }
947
+
948
+ function renderSidebar() {
949
+ const nav = document.getElementById("sidebar-nav");
950
+ const groups = new Map();
951
+ const query = sidebarSearchQuery.trim().toLowerCase();
952
+ const visibleOps = query
953
+ ? operations.filter((op) => {
954
+ const haystack = [
955
+ op.name,
956
+ op.path,
957
+ op.method,
958
+ op.tag,
959
+ ]
960
+ .join(" ")
961
+ .toLowerCase();
962
+ return haystack.includes(query);
963
+ })
964
+ : operations;
965
+
966
+ for (const op of visibleOps) {
967
+ if (!groups.has(op.tag)) groups.set(op.tag, []);
968
+ groups.get(op.tag).push(op);
969
+ }
970
+ nav.innerHTML = "";
971
+ if (visibleOps.length === 0) {
972
+ nav.innerHTML =
973
+ '<p class="px-2 text-xs opacity-60">No routes match your search.</p>';
974
+ return;
975
+ }
976
+ for (const [tag, ops] of groups.entries()) {
977
+ ops.sort((a, b) => {
978
+ const byName = a.name.localeCompare(b.name, undefined, { sensitivity: "base" });
979
+ if (byName !== 0) return byName;
980
+
981
+ const byPath = a.path.localeCompare(b.path, undefined, { sensitivity: "base" });
982
+ if (byPath !== 0) return byPath;
983
+
984
+ return a.method.localeCompare(b.method, undefined, { sensitivity: "base" });
985
+ });
986
+
987
+ const block = document.createElement("div");
988
+ block.innerHTML = '<h3 class="px-2 mb-2 font-semibold text-xs uppercase tracking-wider opacity-50"></h3><ul class="space-y-0.5"></ul>';
989
+ block.querySelector("h3").textContent = tag;
990
+ const list = block.querySelector("ul");
991
+ for (const op of ops) {
992
+ const li = document.createElement("li");
993
+ li.className = "enter-stagger";
994
+ li.style.setProperty("--stagger-delay", String(Math.min(list.children.length * 22, 180)) + "ms");
995
+ const a = document.createElement("a");
996
+ a.href = "#";
997
+ a.className = op === selected
998
+ ? "block px-2 py-1.5 rounded-md bg-brand-soft/70 dark:bg-brand/20 text-brand-deep dark:text-brand font-medium transition-colors"
999
+ : "block px-2 py-1.5 rounded-md hover:bg-black/5 dark:hover:bg-white/5 transition-colors";
1000
+
1001
+ const row = document.createElement("span");
1002
+ row.className = "flex items-center gap-2";
1003
+
1004
+ const method = document.createElement("span");
1005
+ method.className = "px-1.5 py-0.5 rounded text-[10px] font-mono font-semibold " + (methodBadge[op.method] || methodBadgeDefault);
1006
+ method.textContent = op.method;
1007
+
1008
+ const name = document.createElement("span");
1009
+ name.textContent = op.name;
1010
+ if (op.operation && op.operation.deprecated) {
1011
+ name.style.textDecoration = "line-through";
1012
+ name.style.opacity = "0.5";
1013
+ }
1014
+
1015
+ row.appendChild(method);
1016
+ row.appendChild(name);
1017
+ if (op.operation && op.operation.deprecated) {
1018
+ const badge = document.createElement("span");
1019
+ badge.className = "text-[9px] px-1 py-0.5 rounded bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-500 font-semibold shrink-0";
1020
+ badge.textContent = "deprecated";
1021
+ row.appendChild(badge);
1022
+ }
1023
+ a.appendChild(row);
1024
+
1025
+ a.onclick = (e) => {
1026
+ e.preventDefault();
1027
+ selected = op;
1028
+ history.pushState(null, "", getOpHash(op));
1029
+ renderSidebar();
1030
+ renderEndpoint();
1031
+ if (window.innerWidth < 768) {
1032
+ setMobileSidebarOpen(false);
1033
+ }
1034
+ };
1035
+ li.appendChild(a);
1036
+ list.appendChild(li);
1037
+ }
1038
+ nav.appendChild(block);
1039
+ }
1040
+ }
1041
+
1042
+ function hideParamTooltip() {
1043
+ if (!paramTooltipRoot) return;
1044
+ if (paramTooltipHideTimer) {
1045
+ window.clearTimeout(paramTooltipHideTimer);
1046
+ paramTooltipHideTimer = null;
1047
+ }
1048
+ paramTooltipRoot.classList.remove("is-visible");
1049
+ paramTooltipRoot.setAttribute("aria-hidden", "true");
1050
+ if (activeParamTooltipTrigger) {
1051
+ activeParamTooltipTrigger.setAttribute("aria-expanded", "false");
1052
+ }
1053
+ activeParamTooltipTrigger = null;
1054
+ }
1055
+
1056
+ function scheduleParamTooltipHide() {
1057
+ if (paramTooltipHideTimer) {
1058
+ window.clearTimeout(paramTooltipHideTimer);
1059
+ }
1060
+ paramTooltipHideTimer = window.setTimeout(() => {
1061
+ hideParamTooltip();
1062
+ }, 95);
1063
+ }
1064
+
1065
+ function positionParamTooltip(trigger) {
1066
+ if (!paramTooltipRoot || !trigger) return;
1067
+ const viewportPadding = 8;
1068
+ const spacing = 10;
1069
+ const triggerRect = trigger.getBoundingClientRect();
1070
+ const tooltipRect = paramTooltipRoot.getBoundingClientRect();
1071
+ let left = triggerRect.left + (triggerRect.width / 2) - (tooltipRect.width / 2);
1072
+ left = Math.max(viewportPadding, Math.min(left, window.innerWidth - tooltipRect.width - viewportPadding));
1073
+ let top = triggerRect.top - tooltipRect.height - spacing;
1074
+ if (top < viewportPadding) {
1075
+ top = triggerRect.bottom + spacing;
1076
+ }
1077
+ if (top + tooltipRect.height > window.innerHeight - viewportPadding) {
1078
+ top = window.innerHeight - tooltipRect.height - viewportPadding;
1079
+ }
1080
+ paramTooltipRoot.style.left = Math.round(left) + "px";
1081
+ paramTooltipRoot.style.top = Math.round(top) + "px";
1082
+ }
1083
+
1084
+ function showParamTooltip(trigger) {
1085
+ if (
1086
+ !paramTooltipRoot ||
1087
+ !paramTooltipLine ||
1088
+ !paramTooltipDescription ||
1089
+ !trigger
1090
+ ) {
1091
+ return;
1092
+ }
1093
+ if (paramTooltipHideTimer) {
1094
+ window.clearTimeout(paramTooltipHideTimer);
1095
+ paramTooltipHideTimer = null;
1096
+ }
1097
+ const label = trigger.getAttribute("data-param-tooltip-label") || "Value";
1098
+ const value = trigger.getAttribute("data-param-tooltip-value") || "";
1099
+ const related = trigger.getAttribute("data-param-tooltip-related") || "";
1100
+ const description = trigger.getAttribute("data-param-tooltip-description") || "";
1101
+ if (activeParamTooltipTrigger && activeParamTooltipTrigger !== trigger) {
1102
+ activeParamTooltipTrigger.setAttribute("aria-expanded", "false");
1103
+ }
1104
+ activeParamTooltipTrigger = trigger;
1105
+ activeParamTooltipTrigger.setAttribute("aria-expanded", "true");
1106
+ const pathLabel = related ? " | path: " + related : "";
1107
+ paramTooltipLine.textContent = label + ": " + value + pathLabel;
1108
+ if (description.trim()) {
1109
+ paramTooltipDescription.textContent = description;
1110
+ paramTooltipDescription.classList.remove("hidden");
1111
+ } else {
1112
+ paramTooltipDescription.textContent = "";
1113
+ paramTooltipDescription.classList.add("hidden");
1114
+ }
1115
+ paramTooltipRoot.classList.add("is-visible");
1116
+ paramTooltipRoot.setAttribute("aria-hidden", "false");
1117
+ positionParamTooltip(trigger);
1118
+ }
1119
+
1120
+ function registerParamTooltipTargets(scope) {
1121
+ if (!scope) return;
1122
+ const targets = scope.querySelectorAll("[data-param-tooltip-value]");
1123
+ for (const target of targets) {
1124
+ target.addEventListener("click", (event) => {
1125
+ event.preventDefault();
1126
+ if (
1127
+ activeParamTooltipTrigger === target &&
1128
+ paramTooltipRoot &&
1129
+ paramTooltipRoot.classList.contains("is-visible")
1130
+ ) {
1131
+ hideParamTooltip();
1132
+ return;
1133
+ }
1134
+ showParamTooltip(target);
1135
+ });
1136
+ target.addEventListener("mouseenter", () => {
1137
+ showParamTooltip(target);
1138
+ });
1139
+ target.addEventListener("mouseleave", (event) => {
1140
+ const related = event.relatedTarget;
1141
+ if (paramTooltipRoot && related && paramTooltipRoot.contains(related)) return;
1142
+ scheduleParamTooltipHide();
1143
+ });
1144
+ target.addEventListener("focus", () => {
1145
+ showParamTooltip(target);
1146
+ });
1147
+ target.addEventListener("blur", (event) => {
1148
+ const related = event.relatedTarget;
1149
+ if (paramTooltipRoot && related && paramTooltipRoot.contains(related)) return;
1150
+ scheduleParamTooltipHide();
1151
+ });
1152
+ }
1153
+ }
1154
+
1155
+ function renderParamSection(title, params) {
1156
+ if (!params.length) return "";
1157
+ let rows = "";
1158
+ for (const p of params) {
1159
+ const schema = resolveSchemaRef(p.schema || {});
1160
+ const typeRaw = getSchemaTypeLabel(schema);
1161
+ const type = escapeHtml(typeRaw);
1162
+ const nameRaw = p.name || "";
1163
+ const name = escapeHtml(nameRaw);
1164
+ const tooltipName = escapeHtmlAttribute(nameRaw);
1165
+ const tooltipType = escapeHtmlAttribute(typeRaw);
1166
+ const tooltipDescription = (typeof p.description === "string" && p.description.trim())
1167
+ ? escapeHtmlAttribute(p.description.trim())
1168
+ : (typeof schema.description === "string" && schema.description.trim())
1169
+ ? escapeHtmlAttribute(schema.description.trim())
1170
+ : "";
1171
+ const desc = (typeof p.description === "string" && p.description.trim())
1172
+ ? '<p class="text-xs opacity-60 mt-0.5 leading-snug">' + renderMarkdown(p.description.trim()) + '</p>'
1173
+ : "";
1174
+ const extra = buildSchemaExtra(schema);
1175
+ rows +=
1176
+ '<div class="param-row py-2 border-b border-light-border/50 dark:border-dark-border/50">' +
1177
+ '<div class="param-row-head">' +
1178
+ '<div class="param-row-main">' +
1179
+ '<button type="button" class="param-tooltip-trigger param-name-trigger" data-param-tooltip-label="Parameter" data-param-tooltip-value="' +
1180
+ tooltipName +
1181
+ '" data-param-tooltip-description="' +
1182
+ tooltipDescription +
1183
+ '" aria-expanded="false">' +
1184
+ '<code class="text-sm font-mono param-name-text">' +
1185
+ name +
1186
+ "</code></button>" +
1187
+ '<span class="text-xs text-brand shrink-0">' +
1188
+ (p.required ? "required" : "optional") +
1189
+ "</span></div>" +
1190
+ '<button type="button" class="param-tooltip-trigger param-type-fade text-xs font-mono opacity-60" data-param-tooltip-label="Type" data-param-tooltip-value="' +
1191
+ tooltipType +
1192
+ '" data-param-tooltip-description="' +
1193
+ tooltipDescription +
1194
+ '" aria-expanded="false">' +
1195
+ type +
1196
+ "</button></div>" +
1197
+ desc +
1198
+ extra +
1199
+ "</div>";
1200
+ }
1201
+ return '<div><h3 class="text-sm font-semibold mb-3 flex items-center border-b border-light-border dark:border-dark-border pb-2">' + escapeHtml(title) + "</h3>" + rows + "</div>";
1202
+ }
1203
+
1204
+ function getSchemaTypeLabel(schema) {
1205
+ const resolved = resolveSchemaRef(schema);
1206
+ if (!resolved || typeof resolved !== "object") return "unknown";
1207
+ if (Array.isArray(resolved.type)) return resolved.type.join(" | ");
1208
+ if (resolved.type) return String(resolved.type);
1209
+ if (resolved.properties) return "object";
1210
+ if (resolved.items) return "array";
1211
+ if (Array.isArray(resolved.oneOf)) return "oneOf";
1212
+ if (Array.isArray(resolved.anyOf)) return "anyOf";
1213
+ if (Array.isArray(resolved.allOf)) return "allOf";
1214
+ return "unknown";
1215
+ }
1216
+
1217
+ function buildSchemaExtra(schema) {
1218
+ const resolved = resolveSchemaRef(schema);
1219
+ if (!resolved || typeof resolved !== "object") return "";
1220
+ const chips = [];
1221
+ if (resolved.format) chips.push(escapeHtml(String(resolved.format)));
1222
+ if (Array.isArray(resolved.enum) && resolved.enum.length > 0) {
1223
+ const shown = resolved.enum.slice(0, 5).map(function(v) { return escapeHtml(JSON.stringify(v)); });
1224
+ chips.push(shown.join(" | ") + (resolved.enum.length > 5 ? " \u2026" : ""));
1225
+ }
1226
+ if (resolved.minimum !== undefined) chips.push("min: " + resolved.minimum);
1227
+ if (resolved.maximum !== undefined) chips.push("max: " + resolved.maximum);
1228
+ if (typeof resolved.exclusiveMinimum === "number") chips.push("&gt;" + resolved.exclusiveMinimum);
1229
+ if (typeof resolved.exclusiveMaximum === "number") chips.push("&lt;" + resolved.exclusiveMaximum);
1230
+ if (resolved.minLength !== undefined) chips.push("minLen: " + resolved.minLength);
1231
+ if (resolved.maxLength !== undefined) chips.push("maxLen: " + resolved.maxLength);
1232
+ if (resolved.minItems !== undefined) chips.push("minItems: " + resolved.minItems);
1233
+ if (resolved.maxItems !== undefined) chips.push("maxItems: " + resolved.maxItems);
1234
+ if (resolved.uniqueItems) chips.push("unique");
1235
+ if (resolved.pattern) chips.push("/" + escapeHtml(String(resolved.pattern)) + "/");
1236
+ if (!chips.length) return "";
1237
+ return '<div class="flex flex-wrap gap-1 mt-1.5">' +
1238
+ chips.map(function(c) {
1239
+ return '<span class="text-[10px] px-1.5 py-0.5 rounded bg-black/5 dark:bg-white/5 font-mono opacity-80">' + c + '</span>';
1240
+ }).join("") +
1241
+ '</div>';
1242
+ }
1243
+
1244
+ function resolveSchemaRef(schema, visitedRefs) {
1245
+ if (!schema || typeof schema !== "object") return schema;
1246
+ const ref = typeof schema.$ref === "string" ? schema.$ref : "";
1247
+ if (!ref || !ref.startsWith("#/components/schemas/")) {
1248
+ return schema;
1249
+ }
1250
+
1251
+ const seen = visitedRefs || new Set();
1252
+ if (seen.has(ref)) return schema;
1253
+ seen.add(ref);
1254
+
1255
+ const parts = ref.split("/");
1256
+ const schemaName = parts[parts.length - 1];
1257
+ const referenced = spec && spec.components && spec.components.schemas && spec.components.schemas[schemaName];
1258
+ if (!referenced || typeof referenced !== "object") return schema;
1259
+
1260
+ const merged = Object.assign({}, referenced, schema);
1261
+ delete merged.$ref;
1262
+ return resolveSchemaRef(merged, seen);
1263
+ }
1264
+
1265
+ function buildSchemaChildren(schema) {
1266
+ const resolved = resolveSchemaRef(schema);
1267
+ if (!resolved || typeof resolved !== "object") return [];
1268
+
1269
+ const children = [];
1270
+
1271
+ if (resolved.properties && typeof resolved.properties === "object") {
1272
+ const requiredSet = new Set(
1273
+ Array.isArray(resolved.required) ? resolved.required : [],
1274
+ );
1275
+ for (const [name, childSchema] of Object.entries(resolved.properties)) {
1276
+ const childDef = childSchema || {};
1277
+ const isArrayType = Array.isArray(childDef.type)
1278
+ ? childDef.type.includes("array")
1279
+ : childDef.type === "array";
1280
+ const isArrayLike = isArrayType || childDef.items !== undefined;
1281
+ children.push({
1282
+ name: isArrayLike ? (name + "[]") : name,
1283
+ schema: childDef,
1284
+ required: requiredSet.has(name),
1285
+ });
1286
+ }
1287
+ }
1288
+
1289
+ if (resolved.items) {
1290
+ children.push({
1291
+ name: getArrayItemNodeName(resolved.items),
1292
+ schema: resolved.items,
1293
+ required: true,
1294
+ });
1295
+ }
1296
+
1297
+ return children;
1298
+ }
1299
+
1300
+ function getArrayItemNodeName(itemSchema) {
1301
+ if (!itemSchema || typeof itemSchema !== "object") return "item";
1302
+ const title =
1303
+ typeof itemSchema.title === "string" && itemSchema.title.trim()
1304
+ ? itemSchema.title.trim()
1305
+ : "";
1306
+ if (title) return title;
1307
+
1308
+ const ref =
1309
+ typeof itemSchema.$ref === "string" && itemSchema.$ref.trim()
1310
+ ? itemSchema.$ref.trim()
1311
+ : "";
1312
+ if (ref) {
1313
+ const parts = ref.split("/").filter(Boolean);
1314
+ const last = parts[parts.length - 1];
1315
+ if (last) return last;
1316
+ }
1317
+
1318
+ const typeLabel = getSchemaTypeLabel(itemSchema);
1319
+ if (typeLabel && typeLabel !== "unknown") return typeLabel;
1320
+ return "type";
1321
+ }
1322
+
1323
+ function renderSchemaFieldNode(field, depth, parentPath) {
1324
+ const schema = resolveSchemaRef(field.schema || {});
1325
+ const nameRaw = field.name || "field";
1326
+ const name = escapeHtml(nameRaw);
1327
+ const requiredLabel = field.required ? "required" : "optional";
1328
+ const typeRaw = getSchemaTypeLabel(schema);
1329
+ const type = escapeHtml(typeRaw);
1330
+ const tooltipName = escapeHtmlAttribute(nameRaw);
1331
+ const tooltipType = escapeHtmlAttribute(typeRaw);
1332
+ const fieldPath = parentPath ? (parentPath + "." + nameRaw) : nameRaw;
1333
+ const tooltipPath = escapeHtmlAttribute(fieldPath);
1334
+ const tooltipDescription = (typeof schema.description === "string" && schema.description.trim())
1335
+ ? escapeHtmlAttribute(schema.description.trim())
1336
+ : "";
1337
+ const children = buildSchemaChildren(schema);
1338
+ const padding = depth * 14;
1339
+ const extra = buildSchemaExtra(schema);
1340
+
1341
+ if (!children.length) {
1342
+ return (
1343
+ '<div class="param-row py-2 border-b border-light-border/50 dark:border-dark-border/50" style="padding-left:' +
1344
+ padding +
1345
+ 'px"><div class="param-row-head"><div class="param-row-main">' +
1346
+ '<button type="button" class="param-tooltip-trigger param-name-trigger" data-param-tooltip-label="Field" data-param-tooltip-value="' +
1347
+ tooltipName +
1348
+ '" data-param-tooltip-related="' +
1349
+ tooltipPath +
1350
+ '" data-param-tooltip-description="' +
1351
+ tooltipDescription +
1352
+ '" aria-expanded="false"><code class="text-sm font-mono param-name-text">' +
1353
+ name +
1354
+ '</code></button><span class="text-xs text-brand shrink-0">' +
1355
+ requiredLabel +
1356
+ '</span></div><button type="button" class="param-tooltip-trigger param-type-fade text-xs font-mono opacity-60" data-param-tooltip-label="Type" data-param-tooltip-value="' +
1357
+ tooltipType +
1358
+ '" data-param-tooltip-description="' +
1359
+ tooltipDescription +
1360
+ '" aria-expanded="false">' +
1361
+ type +
1362
+ "</button></div>" + extra + "</div>"
1363
+ );
1364
+ }
1365
+
1366
+ let nested = "";
1367
+ for (const child of children) {
1368
+ nested += renderSchemaFieldNode(child, depth + 1, fieldPath);
1369
+ }
1370
+
1371
+ return (
1372
+ '<details open>' +
1373
+ '<summary class="list-none cursor-pointer py-2 border-b border-light-border/50 dark:border-dark-border/50" style="padding-left:' +
1374
+ padding +
1375
+ 'px"><div class="param-row-head"><div class="param-row-main"><span class="text-xs opacity-70 shrink-0">\u25BE</span>' +
1376
+ '<button type="button" class="param-tooltip-trigger param-name-trigger" data-param-tooltip-label="Field" data-param-tooltip-value="' +
1377
+ tooltipName +
1378
+ '" data-param-tooltip-related="' +
1379
+ tooltipPath +
1380
+ '" data-param-tooltip-description="' +
1381
+ tooltipDescription +
1382
+ '" aria-expanded="false"><code class="text-sm font-mono param-name-text">' +
1383
+ name +
1384
+ '</code></button><span class="text-xs text-brand shrink-0">' +
1385
+ requiredLabel +
1386
+ '</span></div><button type="button" class="param-tooltip-trigger param-type-fade text-xs font-mono opacity-60" data-param-tooltip-label="Type" data-param-tooltip-value="' +
1387
+ tooltipType +
1388
+ '" data-param-tooltip-description="' +
1389
+ tooltipDescription +
1390
+ '" aria-expanded="false">' +
1391
+ type +
1392
+ "</button></div>" + extra + "</summary>" +
1393
+ "<div>" +
1394
+ nested +
1395
+ "</div></details>"
1396
+ );
1397
+ }
1398
+
1399
+ function renderRequestBodySchemaSection(schema) {
1400
+ if (!schema || typeof schema !== "object") return "";
1401
+ const rootChildren = buildSchemaChildren(schema);
1402
+ if (!rootChildren.length) return "";
1403
+
1404
+ let rows = "";
1405
+ for (const child of rootChildren) {
1406
+ rows += renderSchemaFieldNode(child, 0, "");
1407
+ }
1408
+
1409
+ return (
1410
+ '<div><h3 class="text-sm font-semibold mb-3 flex items-center border-b border-light-border dark:border-dark-border pb-2">Request Body</h3>' +
1411
+ rows +
1412
+ "</div>"
1413
+ );
1414
+ }
1415
+
1416
+ function renderResponseSchemasSection(responses) {
1417
+ if (!responses || typeof responses !== "object") return "";
1418
+
1419
+ const statusCodes = Object.keys(responses).sort((a, b) => {
1420
+ const aNum = Number(a);
1421
+ const bNum = Number(b);
1422
+ if (Number.isInteger(aNum) && Number.isInteger(bNum)) return aNum - bNum;
1423
+ if (Number.isInteger(aNum)) return -1;
1424
+ if (Number.isInteger(bNum)) return 1;
1425
+ return a.localeCompare(b);
1426
+ });
1427
+
1428
+ let sections = "";
1429
+ for (const statusCode of statusCodes) {
1430
+ const responseDef = responses[statusCode];
1431
+ if (!responseDef || typeof responseDef !== "object") continue;
1432
+
1433
+ const responseDesc = (typeof responseDef.description === "string" && responseDef.description.trim())
1434
+ ? responseDef.description.trim()
1435
+ : "";
1436
+
1437
+ const jsonSchema =
1438
+ responseDef.content &&
1439
+ responseDef.content["application/json"] &&
1440
+ responseDef.content["application/json"].schema;
1441
+
1442
+ let rows = "";
1443
+ if (jsonSchema && typeof jsonSchema === "object") {
1444
+ const rootChildren = buildSchemaChildren(jsonSchema);
1445
+ for (const child of rootChildren) {
1446
+ rows += renderSchemaFieldNode(child, 0, "");
1447
+ }
1448
+ }
1449
+
1450
+ if (!responseDesc && !rows) continue;
1451
+
1452
+ const descHtml = responseDesc
1453
+ ? ' <span class="normal-case font-sans opacity-70 ml-1">\u2014 ' + escapeHtml(responseDesc) + '</span>'
1454
+ : "";
1455
+ const contentHtml = rows || '<p class="text-xs opacity-60 mt-1">No schema fields</p>';
1456
+
1457
+ sections +=
1458
+ '<details class="mb-4">' +
1459
+ '<summary class="list-none cursor-pointer">' +
1460
+ '<h4 class="text-xs font-mono uppercase tracking-wider opacity-70 mb-2">Status ' +
1461
+ escapeHtml(statusCode) +
1462
+ descHtml +
1463
+ "</h4>" +
1464
+ "</summary>" +
1465
+ contentHtml +
1466
+ "</details>";
1467
+ }
1468
+
1469
+ if (!sections) return "";
1470
+
1471
+ return (
1472
+ '<div><h3 class="text-sm font-semibold mb-3 flex items-center border-b border-light-border dark:border-dark-border pb-2">Response Schemas</h3>' +
1473
+ sections +
1474
+ "</div>"
1475
+ );
1476
+ }
1477
+
1478
+ function renderTryItParameterInputs(pathParams, queryParams) {
1479
+ const container = document.getElementById("request-param-inputs");
1480
+ if (!container || !selected) return;
1481
+
1482
+ const values = getParameterValues(selected);
1483
+ container.innerHTML = "";
1484
+
1485
+ const sections = [
1486
+ { title: "Path Values", params: pathParams },
1487
+ { title: "Query Values", params: queryParams },
1488
+ ];
1489
+
1490
+ for (const section of sections) {
1491
+ if (!section.params.length) continue;
1492
+
1493
+ const group = document.createElement("div");
1494
+ group.className = "space-y-2";
1495
+
1496
+ const title = document.createElement("p");
1497
+ title.className = "text-xs font-semibold uppercase tracking-wider opacity-60";
1498
+ title.textContent = section.title;
1499
+ group.appendChild(title);
1500
+
1501
+ for (const param of section.params) {
1502
+ const field = document.createElement("div");
1503
+ field.className = "space-y-1";
1504
+
1505
+ const label = document.createElement("label");
1506
+ label.className = "text-xs opacity-80 flex items-center gap-2";
1507
+
1508
+ const labelName = document.createElement("span");
1509
+ labelName.className = "font-mono";
1510
+ labelName.textContent = param.name;
1511
+
1512
+ const required = document.createElement("span");
1513
+ required.className = "text-[10px] text-brand";
1514
+ required.textContent = param.required ? "required" : "optional";
1515
+
1516
+ label.appendChild(labelName);
1517
+ label.appendChild(required);
1518
+
1519
+ const input = document.createElement("input");
1520
+ input.type = "text";
1521
+ input.value = values[param.name] || "";
1522
+ input.placeholder =
1523
+ section.title === "Path Values" ? param.name : "optional";
1524
+ input.className =
1525
+ "w-full text-sm px-3 py-2 rounded border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg focus:outline-none focus:border-brand dark:focus:border-brand transition-colors font-mono";
1526
+
1527
+ input.addEventListener("input", () => {
1528
+ values[param.name] = input.value;
1529
+ updateRequestPreview();
1530
+ });
1531
+
1532
+ field.appendChild(label);
1533
+ field.appendChild(input);
1534
+ group.appendChild(field);
1535
+ }
1536
+
1537
+ container.appendChild(group);
1538
+ }
1539
+ }
1540
+
1541
+ function renderHeaderInputs() {
1542
+ const container = document.getElementById("header-inputs");
1543
+ if (!container) return;
1544
+
1545
+ container.innerHTML = "";
1546
+ requestHeaders.forEach((entry, index) => {
1547
+ const row = document.createElement("div");
1548
+ row.className = "grid grid-cols-[1fr_1fr_auto] gap-2";
1549
+
1550
+ const keyInput = document.createElement("input");
1551
+ keyInput.type = "text";
1552
+ keyInput.value = entry.key || "";
1553
+ keyInput.placeholder = "Header";
1554
+ keyInput.className =
1555
+ "w-full text-xs px-2.5 py-2 rounded border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg focus:outline-none focus:border-brand dark:focus:border-brand transition-colors font-mono";
1556
+ keyInput.addEventListener("input", () => {
1557
+ entry.key = keyInput.value;
1558
+ saveHeaders();
1559
+ updateRequestPreview();
1560
+ });
1561
+
1562
+ const valueInput = document.createElement("input");
1563
+ valueInput.type = "text";
1564
+ valueInput.value = entry.value || "";
1565
+ valueInput.placeholder =
1566
+ String(entry.key || "").toLowerCase() === "authorization"
1567
+ ? "Bearer token"
1568
+ : "Value";
1569
+ valueInput.className =
1570
+ "w-full text-xs px-2.5 py-2 rounded border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg focus:outline-none focus:border-brand dark:focus:border-brand transition-colors font-mono";
1571
+ valueInput.addEventListener("input", () => {
1572
+ entry.value = valueInput.value;
1573
+ saveHeaders();
1574
+ updateRequestPreview();
1575
+ });
1576
+
1577
+ const removeButton = document.createElement("button");
1578
+ removeButton.type = "button";
1579
+ removeButton.className =
1580
+ "p-1.5 rounded-full border border-light-border dark:border-dark-border bg-light-bg/90 dark:bg-dark-bg/90 opacity-90 hover:opacity-100 hover:border-brand/60 transition-colors";
1581
+ removeButton.setAttribute("aria-label", "Remove Header");
1582
+ removeButton.setAttribute("title", "Remove Header");
1583
+ removeButton.innerHTML =
1584
+ '<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 12h12"></path></svg>';
1585
+ removeButton.addEventListener("click", () => {
1586
+ requestHeaders.splice(index, 1);
1587
+ saveHeaders();
1588
+ renderHeaderInputs();
1589
+ updateRequestPreview();
1590
+ });
1591
+
1592
+ row.appendChild(keyInput);
1593
+ row.appendChild(valueInput);
1594
+ row.appendChild(removeButton);
1595
+ container.appendChild(row);
1596
+ });
1597
+ }
1598
+
1599
+ function hasHeaderName(headers, expectedName) {
1600
+ const target = expectedName.toLowerCase();
1601
+ return Object.keys(headers).some((key) => key.toLowerCase() === target);
1602
+ }
1603
+
1604
+ function buildCookieHeaderValue(cookieValues) {
1605
+ const entries = Object.entries(cookieValues);
1606
+ if (!entries.length) return "";
1607
+ return entries
1608
+ .map(([name, value]) => String(name) + "=" + encodeURIComponent(String(value)))
1609
+ .join("; ");
1610
+ }
1611
+
1612
+ function getRequestHeadersObject(op) {
1613
+ const auth = getAuthHeaders(op);
1614
+ const authCookies = getAuthCookieParams(op);
1615
+ if (Object.keys(authCookies).length > 0) {
1616
+ const cookieHeader = buildCookieHeaderValue(authCookies);
1617
+ if (cookieHeader) {
1618
+ auth["Cookie"] = cookieHeader;
1619
+ }
1620
+ }
1621
+ const manual = {};
1622
+ for (const entry of requestHeaders) {
1623
+ const key = String(entry.key || "").trim();
1624
+ const value = String(entry.value || "").trim();
1625
+ if (!key || !value) continue;
1626
+ manual[key] = value;
1627
+ }
1628
+ // Auth provides defaults; manual headers win on conflict
1629
+ return Object.assign({}, auth, manual);
1630
+ }
1631
+
1632
+ function buildCurl(op, headers, body, requestPath) {
1633
+ const url = window.location.origin + requestPath;
1634
+ const lines = ['curl -X ' + op.method + ' "' + url + '"'];
1635
+
1636
+ for (const [name, value] of Object.entries(headers)) {
1637
+ const safeName = String(name).replace(/"/g, '\\"');
1638
+ const safeValue = String(value).replace(/"/g, '\\"');
1639
+ lines.push(' -H "' + safeName + ": " + safeValue + '"');
1640
+ }
1641
+
1642
+ if (body) {
1643
+ lines.push(" -d '" + body.replace(/'/g, "'\\\\''") + "'");
1644
+ }
1645
+
1646
+ return lines.join(" \\\\\\n");
1647
+ }
1648
+
1649
+ function formatBodyJsonInput() {
1650
+ const bodyInput = document.getElementById("body-input");
1651
+ if (!bodyInput) return;
1652
+ const current = bodyInput.value.trim();
1653
+ if (!current) return;
1654
+ try {
1655
+ bodyInput.value = JSON.stringify(JSON.parse(current), null, 2);
1656
+ } catch {}
1657
+ }
1658
+
1659
+ function escapeHtml(value) {
1660
+ return String(value)
1661
+ .replace(/&/g, "&amp;")
1662
+ .replace(/</g, "&lt;")
1663
+ .replace(/>/g, "&gt;");
1664
+ }
1665
+
1666
+ function escapeHtmlAttribute(value) {
1667
+ return String(value)
1668
+ .replace(/&/g, "&amp;")
1669
+ .replace(/</g, "&lt;")
1670
+ .replace(/>/g, "&gt;")
1671
+ .replace(/"/g, "&quot;")
1672
+ .replace(/'/g, "&#39;");
1673
+ }
1674
+
1675
+ function renderMarkdown(text) {
1676
+ if (!text || typeof text !== "string") return "";
1677
+ var s = escapeHtml(text);
1678
+ // inline code \u2014 process first to protect content inside backticks
1679
+ s = s.replace(/\`([^\`\\n]+)\`/g, '<code class="text-xs font-mono bg-black/5 dark:bg-white/5 px-1 py-0.5 rounded">$1</code>');
1680
+ // bold **text**
1681
+ s = s.replace(/\\*\\*([^*\\n]+)\\*\\*/g, '<strong>$1</strong>');
1682
+ // italic *text*
1683
+ s = s.replace(/\\*([^*\\n]+)\\*/g, '<em>$1</em>');
1684
+ // links [text](url)
1685
+ s = s.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, function(m, txt, url) {
1686
+ var lc = url.toLowerCase().replace(/\\s/g, "");
1687
+ if (lc.indexOf("javascript:") === 0 || lc.indexOf("data:") === 0 || lc.indexOf("vbscript:") === 0) return txt;
1688
+ return '<a href="' + url.replace(/"/g, '&quot;') + '" target="_blank" rel="noopener noreferrer" class="text-brand hover:underline">' + txt + '</a>';
1689
+ });
1690
+ return s;
1691
+ }
1692
+
1693
+ function toPrettyJson(value) {
1694
+ const trimmed = (value || "").trim();
1695
+ if (!trimmed) return null;
1696
+ try {
1697
+ return JSON.stringify(JSON.parse(trimmed), null, 2);
1698
+ } catch {
1699
+ return null;
1700
+ }
1701
+ }
1702
+
1703
+ function highlightJson(jsonText) {
1704
+ const escaped = escapeHtml(jsonText);
1705
+ return escaped.replace(
1706
+ /("(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\"])*"(\\s*:)?|\\btrue\\b|\\bfalse\\b|\\bnull\\b|-?\\d+(?:\\.\\d+)?(?:[eE][+\\-]?\\d+)?)/g,
1707
+ (match) => {
1708
+ let cls = "json-number";
1709
+ if (match.startsWith('"')) {
1710
+ cls = match.endsWith(":") ? "json-key" : "json-string";
1711
+ } else if (match === "true" || match === "false") {
1712
+ cls = "json-boolean";
1713
+ } else if (match === "null") {
1714
+ cls = "json-null";
1715
+ }
1716
+ return '<span class="' + cls + '">' + match + "</span>";
1717
+ },
1718
+ );
1719
+ }
1720
+
1721
+ function updateBodyJsonPresentation() {
1722
+ const bodyInput = document.getElementById("body-input");
1723
+ const highlight = document.getElementById("body-highlight");
1724
+ const bodySection = document.getElementById("request-body-section");
1725
+
1726
+ if (!bodyInput || !highlight || !bodySection) return;
1727
+ if (bodySection.classList.contains("hidden")) {
1728
+ highlight.innerHTML = "";
1729
+ return;
1730
+ }
1731
+
1732
+ const raw = bodyInput.value || "";
1733
+ if (!raw.trim()) {
1734
+ const placeholder = bodyInput.getAttribute("placeholder") || "";
1735
+ highlight.innerHTML = '<span class="opacity-40">' + escapeHtml(placeholder) + "</span>";
1736
+ return;
1737
+ }
1738
+
1739
+ const prettyJson = toPrettyJson(raw);
1740
+ if (!prettyJson) {
1741
+ highlight.innerHTML = escapeHtml(raw);
1742
+ return;
1743
+ }
1744
+
1745
+ highlight.innerHTML = highlightJson(raw);
1746
+ }
1747
+
1748
+ function syncBodyEditorScroll() {
1749
+ const bodyInput = document.getElementById("body-input");
1750
+ const highlight = document.getElementById("body-highlight");
1751
+ if (!bodyInput || !highlight) return;
1752
+ highlight.scrollTop = bodyInput.scrollTop;
1753
+ highlight.scrollLeft = bodyInput.scrollLeft;
1754
+ }
1755
+
1756
+ function updateExpandEditorPresentation() {
1757
+ const editor = document.getElementById("expand-editor");
1758
+ const highlight = document.getElementById("expand-editor-highlight");
1759
+ if (!editor || !highlight) return;
1760
+ const raw = editor.value || "";
1761
+ if (!raw.trim()) {
1762
+ highlight.innerHTML = "";
1763
+ return;
1764
+ }
1765
+ const prettyJson = toPrettyJson(raw);
1766
+ highlight.innerHTML = prettyJson ? highlightJson(raw) : escapeHtml(raw);
1767
+ }
1768
+
1769
+ function syncExpandEditorScroll() {
1770
+ const editor = document.getElementById("expand-editor");
1771
+ const highlight = document.getElementById("expand-editor-highlight");
1772
+ if (!editor || !highlight) return;
1773
+ highlight.scrollTop = editor.scrollTop;
1774
+ highlight.scrollLeft = editor.scrollLeft;
1775
+ }
1776
+
1777
+ function formatResponseText(responseText) {
1778
+ const trimmed = (responseText || "").trim();
1779
+ if (!trimmed) return { text: "(empty)", isJson: false };
1780
+ try {
1781
+ return {
1782
+ text: JSON.stringify(JSON.parse(trimmed), null, 2),
1783
+ isJson: true,
1784
+ };
1785
+ } catch {
1786
+ return {
1787
+ text: responseText,
1788
+ isJson: false,
1789
+ };
1790
+ }
1791
+ }
1792
+
1793
+ function setResponseContent(headerText, bodyText, isJson) {
1794
+ const result = document.getElementById("result");
1795
+ if (!result) return;
1796
+ const fullText = String(headerText || "") + String(bodyText || "");
1797
+ result.dataset.raw = fullText;
1798
+ result.dataset.header = String(headerText || "");
1799
+ result.dataset.body = String(bodyText || "");
1800
+ result.dataset.isJson = isJson ? "true" : "false";
1801
+ if (isJson) {
1802
+ result.innerHTML = escapeHtml(String(headerText || "")) + highlightJson(String(bodyText || ""));
1803
+ } else {
1804
+ result.textContent = fullText;
1805
+ }
1806
+ }
1807
+
1808
+ function setSubmitLoading(isLoading) {
1809
+ const sendButton = document.getElementById("send-btn");
1810
+ const spinner = document.getElementById("send-btn-spinner");
1811
+ const label = document.getElementById("send-btn-label");
1812
+ if (!sendButton) return;
1813
+
1814
+ sendButton.disabled = isLoading;
1815
+ sendButton.classList.toggle("opacity-80", isLoading);
1816
+ sendButton.classList.toggle("cursor-wait", isLoading);
1817
+ if (spinner) spinner.classList.toggle("hidden", !isLoading);
1818
+ if (label) label.textContent = isLoading ? "Sending..." : "Submit";
1819
+ }
1820
+
1821
+ function updateRequestPreview() {
1822
+ if (!selected) return;
1823
+
1824
+ const { path, query } = getOperationParameterGroups(selected);
1825
+ const values = getParameterValues(selected);
1826
+ const requestPath = buildRequestPath(selected, path, query, values, getAuthQueryParams(selected));
1827
+ const bodyInput = document.getElementById("body-input");
1828
+ const body = bodyInput ? bodyInput.value.trim() : "";
1829
+ const headers = getRequestHeadersObject(selected);
1830
+ if (body && !hasHeaderName(headers, "Content-Type")) {
1831
+ headers["Content-Type"] = "application/json";
1832
+ }
1833
+
1834
+ document.getElementById("endpoint-path").textContent = requestPath;
1835
+ document.getElementById("curl-code").textContent = buildCurl(
1836
+ selected,
1837
+ headers,
1838
+ body,
1839
+ requestPath,
1840
+ );
1841
+ }
1842
+
1843
+ function renderEndpoint() {
1844
+ if (!selected) return;
1845
+ const endpointCard = document.getElementById("endpoint-card");
1846
+ if (endpointCard) {
1847
+ endpointCard.classList.remove("enter-fade-up");
1848
+ // Restart CSS animation for each operation switch
1849
+ void endpointCard.offsetWidth;
1850
+ endpointCard.classList.add("enter-fade-up");
1851
+ }
1852
+
1853
+ const op = selected.operation || {};
1854
+ const reqSchema = op.requestBody && op.requestBody.content && op.requestBody.content["application/json"] && op.requestBody.content["application/json"].schema;
1855
+ const requestBodySection = document.getElementById("request-body-section");
1856
+ const bodyInput = document.getElementById("body-input");
1857
+ const expandBodyBtn = document.getElementById("expand-body-btn");
1858
+ const supportsBody = hasMeaningfulRequestBodySchema(reqSchema);
1859
+
1860
+ if (requestBodySection) {
1861
+ requestBodySection.classList.toggle("hidden", !supportsBody);
1862
+ }
1863
+ if (supportsBody && bodyInput) {
1864
+ const existingDraft = getBodyDraft(selected);
1865
+ if (typeof existingDraft === "string") {
1866
+ bodyInput.value = existingDraft;
1867
+ } else {
1868
+ const prefill = buildRequiredBodyPrefill(reqSchema);
1869
+ bodyInput.value = prefill;
1870
+ setBodyDraft(selected, prefill);
1871
+ }
1872
+ } else if (!supportsBody && bodyInput) {
1873
+ bodyInput.value = "";
1874
+ }
1875
+ if (expandBodyBtn) {
1876
+ expandBodyBtn.disabled = !supportsBody;
1877
+ }
1878
+ setResponseContent("", "", false);
1879
+
1880
+ const deprecatedBanner = document.getElementById("deprecated-banner");
1881
+ if (deprecatedBanner) {
1882
+ deprecatedBanner.classList.toggle("hidden", !op.deprecated);
1883
+ }
1884
+
1885
+ document.getElementById("tag-title").textContent = selected.tag;
1886
+ document.getElementById("tag-description").innerHTML = op.description ? renderMarkdown(op.description) : "Interactive API documentation.";
1887
+ const methodNode = document.getElementById("endpoint-method");
1888
+ methodNode.textContent = selected.method;
1889
+ methodNode.className = "px-2.5 py-0.5 rounded-full text-xs font-mono font-medium " + (methodBadge[selected.method] || methodBadgeDefault);
1890
+ document.getElementById("endpoint-title").textContent = selected.name;
1891
+ document.getElementById("endpoint-path").textContent = selected.path;
1892
+
1893
+ const { all: params, query, path, headers } =
1894
+ getOperationParameterGroups(selected);
1895
+
1896
+ let html = "";
1897
+ html += renderParamSection("Path Parameters", path);
1898
+ html += renderParamSection("Query Parameters", query);
1899
+ html += renderParamSection("Header Parameters", headers);
1900
+
1901
+ html += renderRequestBodySchemaSection(reqSchema);
1902
+ html += renderResponseSchemasSection(op.responses);
1903
+ const paramsColumn = document.getElementById("params-column");
1904
+ if (paramsColumn) {
1905
+ hideParamTooltip();
1906
+ paramsColumn.innerHTML = html || '<div class="text-sm opacity-70">No parameters</div>';
1907
+ registerParamTooltipTargets(paramsColumn);
1908
+ }
1909
+ renderAuthPanel();
1910
+ renderTryItParameterInputs(path, query);
1911
+ renderHeaderInputs();
1912
+ updateRequestPreview();
1913
+ updateBodyJsonPresentation();
1914
+ syncBodyEditorScroll();
1915
+ }
1916
+
1917
+ document.getElementById("copy-curl").addEventListener("click", async () => {
1918
+ try { await navigator.clipboard.writeText(document.getElementById("curl-code").textContent || ""); } catch {}
1919
+ });
1920
+ if (paramTooltipRoot) {
1921
+ paramTooltipRoot.addEventListener("mouseenter", () => {
1922
+ if (paramTooltipHideTimer) {
1923
+ window.clearTimeout(paramTooltipHideTimer);
1924
+ paramTooltipHideTimer = null;
1925
+ }
1926
+ });
1927
+ paramTooltipRoot.addEventListener("mouseleave", () => {
1928
+ scheduleParamTooltipHide();
1929
+ });
1930
+ }
1931
+ document.addEventListener("pointerdown", (event) => {
1932
+ if (!paramTooltipRoot) return;
1933
+ const target = event.target;
1934
+ if (target && paramTooltipRoot.contains(target)) return;
1935
+ if (target && target.closest && target.closest("[data-param-tooltip-value]")) return;
1936
+ hideParamTooltip();
1937
+ });
1938
+ document.getElementById("sidebar-search").addEventListener("input", (event) => {
1939
+ sidebarSearchQuery = event.currentTarget.value || "";
1940
+ renderSidebar();
1941
+ });
1942
+
1943
+ document.getElementById("send-btn").addEventListener("click", async () => {
1944
+ if (!selected) return;
1945
+ const { path, query } = getOperationParameterGroups(selected);
1946
+ const values = getParameterValues(selected);
1947
+ const missingPathParams = path.filter((param) => {
1948
+ if (param.required === false) return false;
1949
+ const value = values[param.name];
1950
+ return value === undefined || value === null || String(value).trim() === "";
1951
+ });
1952
+
1953
+ if (missingPathParams.length > 0) {
1954
+ setResponseContent(
1955
+ "",
1956
+ "Missing required path parameter(s): " +
1957
+ missingPathParams.map((param) => param.name).join(", "),
1958
+ false,
1959
+ );
1960
+ return;
1961
+ }
1962
+
1963
+ const requestPath = buildRequestPath(selected, path, query, values, getAuthQueryParams(selected));
1964
+ formatBodyJsonInput();
1965
+ updateBodyJsonPresentation();
1966
+ const op = selected.operation || {};
1967
+ const reqSchema = op.requestBody && op.requestBody.content && op.requestBody.content["application/json"] && op.requestBody.content["application/json"].schema;
1968
+ const supportsBody = hasMeaningfulRequestBodySchema(reqSchema);
1969
+ const bodyInput = document.getElementById("body-input");
1970
+ const body =
1971
+ supportsBody && bodyInput ? bodyInput.value.trim() : "";
1972
+ const headers = getRequestHeadersObject(selected);
1973
+ if (body && !hasHeaderName(headers, "Content-Type")) {
1974
+ headers["Content-Type"] = "application/json";
1975
+ }
1976
+
1977
+ setSubmitLoading(true);
1978
+ try {
1979
+ const requestStart = performance.now();
1980
+ applyAuthCookies(selected);
1981
+ const response = await fetch(requestPath, {
1982
+ method: selected.method,
1983
+ headers,
1984
+ body: body || undefined,
1985
+ credentials: "same-origin",
1986
+ });
1987
+ const text = await response.text();
1988
+ const responseTimeMs = Math.round(performance.now() - requestStart);
1989
+ const contentType = response.headers.get("content-type") || "unknown";
1990
+ const formattedResponse = formatResponseText(text);
1991
+ const headerText =
1992
+ "Status: " + response.status + " " + response.statusText + "\\n" +
1993
+ "Content-Type: " + contentType + "\\n" +
1994
+ "Response Time: " + responseTimeMs + " ms\\n\\n";
1995
+ setResponseContent(
1996
+ headerText,
1997
+ formattedResponse.text,
1998
+ formattedResponse.isJson,
1999
+ );
2000
+ } catch (error) {
2001
+ setResponseContent("", "Request failed: " + String(error), false);
2002
+ } finally {
2003
+ setSubmitLoading(false);
2004
+ }
2005
+ });
2006
+
2007
+ function openExpandModal(mode) {
2008
+ const modal = document.getElementById("expand-modal");
2009
+ const title = document.getElementById("expand-modal-title");
2010
+ const editorShell = document.getElementById("expand-editor-shell");
2011
+ const editor = document.getElementById("expand-editor");
2012
+ const viewer = document.getElementById("expand-viewer");
2013
+ const apply = document.getElementById("expand-apply");
2014
+ const bodyInput = document.getElementById("body-input");
2015
+ const result = document.getElementById("result");
2016
+ if (!modal || !title || !editorShell || !editor || !viewer || !apply) return;
2017
+
2018
+ expandModalMode = mode;
2019
+ modal.classList.remove("hidden");
2020
+ modal.classList.add("flex");
2021
+
2022
+ if (mode === "body") {
2023
+ title.textContent = "Request Body";
2024
+ editorShell.classList.remove("hidden");
2025
+ viewer.classList.add("hidden");
2026
+ apply.classList.remove("hidden");
2027
+ editor.value = bodyInput ? bodyInput.value : "";
2028
+ updateExpandEditorPresentation();
2029
+ syncExpandEditorScroll();
2030
+ } else {
2031
+ title.textContent = "Response";
2032
+ viewer.classList.remove("hidden");
2033
+ editorShell.classList.add("hidden");
2034
+ apply.classList.add("hidden");
2035
+ const hasResponse = Boolean(result && result.dataset && result.dataset.raw);
2036
+ if (!hasResponse) {
2037
+ viewer.textContent = "(empty response yet)";
2038
+ return;
2039
+ }
2040
+
2041
+ const header = result.dataset.header || "";
2042
+ const body = result.dataset.body || "";
2043
+ const isJson = result.dataset.isJson === "true";
2044
+ if (isJson) {
2045
+ viewer.innerHTML = escapeHtml(header) + highlightJson(body);
2046
+ } else {
2047
+ viewer.textContent = result.dataset.raw || "(empty response yet)";
2048
+ }
2049
+ }
2050
+ }
2051
+
2052
+ function closeExpandModal() {
2053
+ const modal = document.getElementById("expand-modal");
2054
+ if (!modal) return;
2055
+ modal.classList.add("hidden");
2056
+ modal.classList.remove("flex");
2057
+ expandModalMode = null;
2058
+ }
2059
+
2060
+ document.getElementById("add-header-btn").addEventListener("click", () => {
2061
+ requestHeaders.push({ key: "", value: "" });
2062
+ saveHeaders();
2063
+ renderHeaderInputs();
2064
+ updateRequestPreview();
2065
+ });
2066
+ document.getElementById("body-input").addEventListener("input", () => {
2067
+ if (selected) {
2068
+ setBodyDraft(selected, document.getElementById("body-input").value);
2069
+ }
2070
+ updateRequestPreview();
2071
+ updateBodyJsonPresentation();
2072
+ syncBodyEditorScroll();
2073
+ });
2074
+ document.getElementById("body-input").addEventListener("scroll", () => {
2075
+ syncBodyEditorScroll();
2076
+ });
2077
+ document.getElementById("body-input").addEventListener("keydown", (event) => {
2078
+ if (event.key !== "Tab") return;
2079
+ event.preventDefault();
2080
+ const input = event.currentTarget;
2081
+ const start = input.selectionStart;
2082
+ const end = input.selectionEnd;
2083
+ const value = input.value;
2084
+ const tab = " ";
2085
+ input.value = value.slice(0, start) + tab + value.slice(end);
2086
+ input.selectionStart = input.selectionEnd = start + tab.length;
2087
+ if (selected) {
2088
+ setBodyDraft(selected, input.value);
2089
+ }
2090
+ updateRequestPreview();
2091
+ updateBodyJsonPresentation();
2092
+ syncBodyEditorScroll();
2093
+ });
2094
+ document.getElementById("body-input").addEventListener("blur", () => {
2095
+ formatBodyJsonInput();
2096
+ if (selected) {
2097
+ setBodyDraft(selected, document.getElementById("body-input").value);
2098
+ }
2099
+ updateRequestPreview();
2100
+ updateBodyJsonPresentation();
2101
+ syncBodyEditorScroll();
2102
+ });
2103
+ document.getElementById("expand-editor").addEventListener("input", () => {
2104
+ updateExpandEditorPresentation();
2105
+ syncExpandEditorScroll();
2106
+ });
2107
+ document.getElementById("expand-editor").addEventListener("scroll", () => {
2108
+ syncExpandEditorScroll();
2109
+ });
2110
+ document.getElementById("expand-editor").addEventListener("keydown", (event) => {
2111
+ if (event.key !== "Tab") return;
2112
+ event.preventDefault();
2113
+ const editor = event.currentTarget;
2114
+ const start = editor.selectionStart;
2115
+ const end = editor.selectionEnd;
2116
+ const value = editor.value;
2117
+ const tab = " ";
2118
+ editor.value = value.slice(0, start) + tab + value.slice(end);
2119
+ editor.selectionStart = editor.selectionEnd = start + tab.length;
2120
+ updateExpandEditorPresentation();
2121
+ syncExpandEditorScroll();
2122
+ });
2123
+ document.getElementById("expand-editor").addEventListener("blur", () => {
2124
+ const editor = document.getElementById("expand-editor");
2125
+ const current = editor.value.trim();
2126
+ if (current) {
2127
+ try {
2128
+ editor.value = JSON.stringify(JSON.parse(current), null, 2);
2129
+ } catch {}
2130
+ }
2131
+ updateExpandEditorPresentation();
2132
+ syncExpandEditorScroll();
2133
+ });
2134
+ document.getElementById("expand-body-btn").addEventListener("click", () => {
2135
+ openExpandModal("body");
2136
+ });
2137
+ document.getElementById("expand-response-btn").addEventListener("click", () => {
2138
+ openExpandModal("response");
2139
+ });
2140
+ document.getElementById("expand-close").addEventListener("click", closeExpandModal);
2141
+ document.getElementById("expand-apply").addEventListener("click", () => {
2142
+ if (expandModalMode !== "body") {
2143
+ closeExpandModal();
2144
+ return;
2145
+ }
2146
+
2147
+ const editor = document.getElementById("expand-editor");
2148
+ const bodyInput = document.getElementById("body-input");
2149
+ if (editor && bodyInput) {
2150
+ bodyInput.value = editor.value;
2151
+ formatBodyJsonInput();
2152
+ if (selected) {
2153
+ setBodyDraft(selected, bodyInput.value);
2154
+ }
2155
+ updateRequestPreview();
2156
+ updateBodyJsonPresentation();
2157
+ syncBodyEditorScroll();
2158
+ }
2159
+ closeExpandModal();
2160
+ });
2161
+ document.getElementById("expand-modal").addEventListener("click", (event) => {
2162
+ if (event.target === event.currentTarget) {
2163
+ closeExpandModal();
2164
+ }
2165
+ });
2166
+ document.getElementById("sidebar-open").addEventListener("click", () => {
2167
+ setMobileSidebarOpen(true);
2168
+ });
2169
+ document.getElementById("sidebar-close").addEventListener("click", () => {
2170
+ setMobileSidebarOpen(false);
2171
+ });
2172
+ document.getElementById("mobile-backdrop").addEventListener("click", () => {
2173
+ setMobileSidebarOpen(false);
2174
+ });
2175
+ window.addEventListener("resize", () => {
2176
+ if (activeParamTooltipTrigger) {
2177
+ positionParamTooltip(activeParamTooltipTrigger);
2178
+ }
2179
+ if (window.innerWidth >= 768 && isMobileSidebarOpen) {
2180
+ setMobileSidebarOpen(false);
2181
+ }
2182
+ });
2183
+ window.addEventListener("scroll", () => {
2184
+ if (activeParamTooltipTrigger) {
2185
+ positionParamTooltip(activeParamTooltipTrigger);
2186
+ }
2187
+ }, true);
2188
+ document.addEventListener("keydown", (event) => {
2189
+ if (event.key === "Escape") {
2190
+ hideParamTooltip();
2191
+ if (isMobileSidebarOpen) {
2192
+ setMobileSidebarOpen(false);
2193
+ }
2194
+ closeExpandModal();
2195
+ }
2196
+ });
2197
+
2198
+ const themeToggleBtn = document.getElementById('theme-toggle');
2199
+ const htmlElement = document.documentElement;
2200
+ themeToggleBtn.addEventListener('click', () => {
2201
+ htmlElement.classList.toggle('dark');
2202
+ if (htmlElement.classList.contains('dark')) {
2203
+ localStorage.setItem('theme', 'dark');
2204
+ } else {
2205
+ localStorage.setItem('theme', 'light');
2206
+ }
2207
+ });
2208
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
2209
+ if (!('theme' in localStorage)) {
2210
+ if (e.matches) htmlElement.classList.add('dark');
2211
+ else htmlElement.classList.remove('dark');
2212
+ }
2213
+ });
2214
+
2215
+ function getOperationSecurityRequirements(op) {
2216
+ const operationSecurity = op && op.operation && Array.isArray(op.operation.security)
2217
+ ? op.operation.security
2218
+ : null;
2219
+ if (operationSecurity) {
2220
+ return operationSecurity;
2221
+ }
2222
+ return Array.isArray(spec.security) ? spec.security : [];
2223
+ }
2224
+
2225
+ function getAuthSelectionKeyForOperation(op) {
2226
+ if (!op) return "";
2227
+ return getOperationKey(op);
2228
+ }
2229
+
2230
+ function getAuthSchemeOptionsForOperation(op) {
2231
+ const requirements = getOperationSecurityRequirements(op).filter((requirement) =>
2232
+ requirement && typeof requirement === "object" && !Array.isArray(requirement)
2233
+ );
2234
+ if (!requirements.length) return [];
2235
+
2236
+ const seen = new Set();
2237
+ const options = [];
2238
+ for (const requirement of requirements) {
2239
+ for (const schemeName of Object.keys(requirement)) {
2240
+ if (!Object.prototype.hasOwnProperty.call(authSchemes, schemeName)) continue;
2241
+ if (seen.has(schemeName)) continue;
2242
+ seen.add(schemeName);
2243
+ options.push(schemeName);
2244
+ }
2245
+ }
2246
+ return options;
2247
+ }
2248
+
2249
+ function getSelectedAuthSchemeForOperation(op) {
2250
+ const selectionKey = getAuthSelectionKeyForOperation(op);
2251
+ if (!selectionKey) return null;
2252
+
2253
+ const selectedScheme = authSelectionState[selectionKey];
2254
+ if (!selectedScheme || typeof selectedScheme !== "string") return null;
2255
+
2256
+ const options = Object.keys(authSchemes);
2257
+ if (!options.includes(selectedScheme)) {
2258
+ delete authSelectionState[selectionKey];
2259
+ saveAuthSelectionState();
2260
+ return null;
2261
+ }
2262
+
2263
+ return selectedScheme;
2264
+ }
2265
+
2266
+ function setSelectedAuthSchemeForOperation(op, schemeName) {
2267
+ const selectionKey = getAuthSelectionKeyForOperation(op);
2268
+ if (!selectionKey) return;
2269
+
2270
+ if (!schemeName) {
2271
+ delete authSelectionState[selectionKey];
2272
+ } else {
2273
+ authSelectionState[selectionKey] = schemeName;
2274
+ }
2275
+ saveAuthSelectionState();
2276
+ }
2277
+
2278
+ function hasAuthStateForScheme(schemeName) {
2279
+ const scheme = authSchemes[schemeName];
2280
+ if (!scheme) return false;
2281
+
2282
+ const state = authState[schemeName] || {};
2283
+ const type = (scheme.type || "").toLowerCase();
2284
+ const httpScheme = (scheme.scheme || "").toLowerCase();
2285
+
2286
+ if (type === "http" && httpScheme === "basic") {
2287
+ return Boolean(state.username && state.password);
2288
+ }
2289
+ if (type === "http") {
2290
+ return Boolean(state.token);
2291
+ }
2292
+ if (type === "apikey") {
2293
+ return Boolean(state.value);
2294
+ }
2295
+ if (type === "oauth2" || type === "openidconnect") {
2296
+ return Boolean(state.token);
2297
+ }
2298
+
2299
+ return false;
2300
+ }
2301
+
2302
+ function chooseOperationSecurityRequirement(op) {
2303
+ const requirements = getOperationSecurityRequirements(op).filter((requirement) =>
2304
+ requirement && typeof requirement === "object" && !Array.isArray(requirement)
2305
+ );
2306
+ if (!requirements.length) return null;
2307
+
2308
+ const selectedScheme = getSelectedAuthSchemeForOperation(op);
2309
+ if (selectedScheme) {
2310
+ const selectedRequirement = requirements.find((requirement) =>
2311
+ Object.prototype.hasOwnProperty.call(requirement, selectedScheme)
2312
+ );
2313
+ if (selectedRequirement) return selectedRequirement;
2314
+ }
2315
+
2316
+ let bestRequirement = null;
2317
+ let bestScore = -1;
2318
+
2319
+ for (const requirement of requirements) {
2320
+ const schemeNames = Object.keys(requirement).filter((schemeName) =>
2321
+ Object.prototype.hasOwnProperty.call(authSchemes, schemeName)
2322
+ );
2323
+ if (!schemeNames.length) continue;
2324
+
2325
+ const providedCount = schemeNames.filter((schemeName) => hasAuthStateForScheme(schemeName)).length;
2326
+ const isComplete = providedCount === schemeNames.length;
2327
+ const score = isComplete ? 1000 + providedCount : providedCount;
2328
+
2329
+ if (score > bestScore) {
2330
+ bestScore = score;
2331
+ bestRequirement = requirement;
2332
+ }
2333
+ }
2334
+
2335
+ return bestRequirement || requirements[0];
2336
+ }
2337
+
2338
+ function getAuthSchemeNamesForOperation(op) {
2339
+ const schemeNames = Object.keys(authSchemes);
2340
+ if (!schemeNames.length) return [];
2341
+
2342
+ const selectedScheme = getSelectedAuthSchemeForOperation(op);
2343
+ if (selectedScheme) {
2344
+ const requirement = chooseOperationSecurityRequirement(op);
2345
+ if (requirement && Object.prototype.hasOwnProperty.call(requirement, selectedScheme)) {
2346
+ return Object.keys(requirement).filter((schemeName) =>
2347
+ Object.prototype.hasOwnProperty.call(authSchemes, schemeName)
2348
+ );
2349
+ }
2350
+ return [selectedScheme];
2351
+ }
2352
+
2353
+ const requirement = chooseOperationSecurityRequirement(op);
2354
+ if (!requirement) return [];
2355
+
2356
+ return Object.keys(requirement).filter((schemeName) =>
2357
+ Object.prototype.hasOwnProperty.call(authSchemes, schemeName)
2358
+ );
2359
+ }
2360
+
2361
+ function getAuthHeaders(op) {
2362
+ const headers = {};
2363
+ const schemeNames = getAuthSchemeNamesForOperation(op);
2364
+ const allSchemeNames = Object.keys(authSchemes);
2365
+
2366
+ if (!allSchemeNames.length) {
2367
+ const state = authState["__default__"] || {};
2368
+ if (state.token) headers["Authorization"] = "Bearer " + state.token;
2369
+ return headers;
2370
+ }
2371
+ if (!schemeNames.length) return headers;
2372
+
2373
+ for (const schemeName of schemeNames) {
2374
+ const scheme = authSchemes[schemeName];
2375
+ const state = authState[schemeName] || {};
2376
+ const type = (scheme.type || "").toLowerCase();
2377
+ const httpScheme = (scheme.scheme || "").toLowerCase();
2378
+
2379
+ if (type === "http" && httpScheme === "basic") {
2380
+ if (state.username && state.password) {
2381
+ try {
2382
+ headers["Authorization"] = "Basic " + btoa(state.username + ":" + state.password);
2383
+ } catch {}
2384
+ }
2385
+ } else if (type === "http") {
2386
+ if (state.token) headers["Authorization"] = "Bearer " + state.token;
2387
+ } else if (type === "apikey" && (scheme.in || "").toLowerCase() === "header") {
2388
+ if (state.value && scheme.name) headers[scheme.name] = state.value;
2389
+ } else if (type === "oauth2" || type === "openidconnect") {
2390
+ if (state.token) headers["Authorization"] = "Bearer " + state.token;
2391
+ }
2392
+ }
2393
+ return headers;
2394
+ }
2395
+
2396
+ function getAuthQueryParams(op) {
2397
+ const params = {};
2398
+ for (const schemeName of getAuthSchemeNamesForOperation(op)) {
2399
+ const scheme = authSchemes[schemeName];
2400
+ if ((scheme.type || "").toLowerCase() === "apikey" && (scheme.in || "").toLowerCase() === "query") {
2401
+ const state = authState[schemeName] || {};
2402
+ if (state.value && scheme.name) params[scheme.name] = state.value;
2403
+ }
2404
+ }
2405
+ return params;
2406
+ }
2407
+
2408
+ function getAuthCookieParams(op) {
2409
+ const cookies = {};
2410
+ for (const schemeName of getAuthSchemeNamesForOperation(op)) {
2411
+ const scheme = authSchemes[schemeName];
2412
+ if ((scheme.type || "").toLowerCase() !== "apikey") continue;
2413
+ if ((scheme.in || "").toLowerCase() !== "cookie") continue;
2414
+ const state = authState[schemeName] || {};
2415
+ if (state.value && scheme.name) {
2416
+ cookies[scheme.name] = state.value;
2417
+ }
2418
+ }
2419
+ return cookies;
2420
+ }
2421
+
2422
+ function applyAuthCookies(op) {
2423
+ const cookies = getAuthCookieParams(op);
2424
+ for (const [name, value] of Object.entries(cookies)) {
2425
+ try {
2426
+ document.cookie = encodeURIComponent(String(name)) + "=" + encodeURIComponent(String(value)) + "; path=/";
2427
+ } catch {}
2428
+ }
2429
+ }
2430
+
2431
+ function renderAuthPanel() {
2432
+ const fields = document.getElementById("auth-fields");
2433
+ if (!fields) return;
2434
+ fields.innerHTML = "";
2435
+
2436
+ const schemeNames = Object.keys(authSchemes);
2437
+ const op = selected;
2438
+ const operationSchemeOptions = op ? getAuthSchemeOptionsForOperation(op) : [];
2439
+ const availableSchemeOptions = Object.keys(authSchemes);
2440
+ const selectedScheme = op ? getSelectedAuthSchemeForOperation(op) : null;
2441
+
2442
+ function getAuthSchemeDisplayLabel(schemeName) {
2443
+ const scheme = authSchemes[schemeName] || {};
2444
+ const type = (scheme.type || "").toLowerCase();
2445
+ const httpScheme = (scheme.scheme || "").toLowerCase();
2446
+ const location = (scheme.in || "").toLowerCase();
2447
+
2448
+ if (type === "http" && httpScheme === "basic") return "HTTP Basic";
2449
+ if (type === "http" && httpScheme === "bearer") return "HTTP Bearer";
2450
+ if (type === "http" && httpScheme === "digest") return "HTTP Digest";
2451
+ if (type === "http") return "HTTP " + (httpScheme || "Token");
2452
+ if (type === "apikey") return "API Key" + (location ? " (" + location + ")" : "");
2453
+ if (type === "oauth2") return "OAuth 2.0";
2454
+ if (type === "openidconnect") return "OpenID Connect";
2455
+ if (type === "mutualtls") return "Mutual TLS";
2456
+ return schemeName;
2457
+ }
2458
+
2459
+ function makeInput(placeholder, value, onInput, type) {
2460
+ const inp = document.createElement("input");
2461
+ inp.type = type || "text";
2462
+ inp.value = value || "";
2463
+ inp.placeholder = placeholder;
2464
+ inp.className = "w-full text-xs px-2.5 py-2 rounded-md border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg focus:outline-none focus:border-brand dark:focus:border-brand transition-colors font-mono";
2465
+ inp.addEventListener("input", onInput);
2466
+ return inp;
2467
+ }
2468
+
2469
+ function makeLabel(text, small) {
2470
+ const el = document.createElement("p");
2471
+ el.className = small
2472
+ ? "text-[10px] font-medium uppercase tracking-wider opacity-55"
2473
+ : "text-[10px] font-semibold uppercase tracking-wider opacity-55";
2474
+ el.textContent = text;
2475
+ return el;
2476
+ }
2477
+
2478
+ function makeField(label, input) {
2479
+ const wrapper = document.createElement("div");
2480
+ wrapper.className = "space-y-1";
2481
+ wrapper.appendChild(makeLabel(label, true));
2482
+ wrapper.appendChild(input);
2483
+ return wrapper;
2484
+ }
2485
+
2486
+ function makeSchemeCard(title, subtitle) {
2487
+ const card = document.createElement("div");
2488
+ card.className = "space-y-2 rounded-md border border-light-border dark:border-dark-border bg-light-bg/40 dark:bg-dark-bg/40 p-2.5";
2489
+
2490
+ const titleRow = document.createElement("div");
2491
+ titleRow.className = "flex items-center justify-between gap-2";
2492
+
2493
+ const heading = document.createElement("p");
2494
+ heading.className = "text-[11px] font-semibold tracking-wide";
2495
+ heading.textContent = title;
2496
+ titleRow.appendChild(heading);
2497
+
2498
+ if (subtitle) {
2499
+ const note = document.createElement("span");
2500
+ note.className = "text-[10px] opacity-60 font-mono";
2501
+ note.textContent = subtitle;
2502
+ titleRow.appendChild(note);
2503
+ }
2504
+
2505
+ card.appendChild(titleRow);
2506
+ return card;
2507
+ }
2508
+
2509
+ if (!schemeNames.length) {
2510
+ if (!authState["__default__"]) authState["__default__"] = {};
2511
+ const defaultCard = makeSchemeCard("Default Auth", "bearer");
2512
+ defaultCard.appendChild(makeField("Token", makeInput("Enter token\u2026", authState["__default__"].token, function(e) {
2513
+ authState["__default__"].token = e.target.value;
2514
+ saveAuthState();
2515
+ updateRequestPreview();
2516
+ })));
2517
+ fields.appendChild(defaultCard);
2518
+ return;
2519
+ }
2520
+
2521
+ if (op && availableSchemeOptions.length > 0) {
2522
+ const selectorWrap = document.createElement("div");
2523
+ selectorWrap.className = "space-y-1";
2524
+ selectorWrap.appendChild(makeLabel("Auth Type"));
2525
+ const select = document.createElement("select");
2526
+ select.className = "w-full text-xs px-2.5 py-2 rounded-md border border-light-border dark:border-dark-border bg-light-bg dark:bg-dark-bg focus:outline-none focus:border-brand dark:focus:border-brand transition-colors font-mono";
2527
+
2528
+ const autoOption = document.createElement("option");
2529
+ autoOption.value = "";
2530
+ autoOption.textContent = "Auto";
2531
+ select.appendChild(autoOption);
2532
+
2533
+ for (const schemeName of availableSchemeOptions) {
2534
+ const option = document.createElement("option");
2535
+ option.value = schemeName;
2536
+ const isOperationScheme = operationSchemeOptions.includes(schemeName);
2537
+ const label = getAuthSchemeDisplayLabel(schemeName);
2538
+ option.textContent = isOperationScheme
2539
+ ? label
2540
+ : (label + " \u2022 override");
2541
+ select.appendChild(option);
2542
+ }
2543
+
2544
+ select.value = selectedScheme || "";
2545
+ select.addEventListener("change", function(e) {
2546
+ setSelectedAuthSchemeForOperation(op, e.target.value || "");
2547
+ renderAuthPanel();
2548
+ updateRequestPreview();
2549
+ });
2550
+ selectorWrap.appendChild(select);
2551
+ fields.appendChild(selectorWrap);
2552
+ }
2553
+
2554
+ const schemesToRender = selectedScheme
2555
+ ? [selectedScheme]
2556
+ : (operationSchemeOptions.length ? operationSchemeOptions : schemeNames);
2557
+
2558
+ for (const schemeName of schemesToRender) {
2559
+ const scheme = authSchemes[schemeName];
2560
+ if (!authState[schemeName]) authState[schemeName] = {};
2561
+ const state = authState[schemeName];
2562
+ const type = (scheme.type || "").toLowerCase();
2563
+ const httpScheme = (scheme.scheme || "").toLowerCase();
2564
+ const card = makeSchemeCard(getAuthSchemeDisplayLabel(schemeName), schemeName);
2565
+
2566
+ if (type === "http" && httpScheme === "basic") {
2567
+ card.appendChild(makeField("Username", makeInput("Username", state.username, function(e) {
2568
+ authState[schemeName].username = e.target.value;
2569
+ saveAuthState();
2570
+ updateRequestPreview();
2571
+ })));
2572
+ card.appendChild(makeField("Password", makeInput("Password", state.password, function(e) {
2573
+ authState[schemeName].password = e.target.value;
2574
+ saveAuthState();
2575
+ updateRequestPreview();
2576
+ }, "password")));
2577
+ } else if (type === "apikey") {
2578
+ const paramName = scheme.name || "key";
2579
+ const location = (scheme.in || "header").toLowerCase();
2580
+ card.appendChild(makeField("API Key", makeInput(paramName + " (" + location + ")", state.value, function(e) {
2581
+ authState[schemeName].value = e.target.value;
2582
+ saveAuthState();
2583
+ updateRequestPreview();
2584
+ })));
2585
+ } else if (type === "oauth2") {
2586
+ card.appendChild(makeField("Access Token", makeInput("OAuth2 access token\u2026", state.token, function(e) {
2587
+ authState[schemeName].token = e.target.value;
2588
+ saveAuthState();
2589
+ updateRequestPreview();
2590
+ })));
2591
+ } else if (type === "openidconnect") {
2592
+ card.appendChild(makeField("ID Token / Access Token", makeInput("OpenID Connect token\u2026", state.token, function(e) {
2593
+ authState[schemeName].token = e.target.value;
2594
+ saveAuthState();
2595
+ updateRequestPreview();
2596
+ })));
2597
+ } else if (type === "http" && httpScheme === "digest") {
2598
+ card.appendChild(makeField("Digest Credential", makeInput("Digest token\u2026", state.token, function(e) {
2599
+ authState[schemeName].token = e.target.value;
2600
+ saveAuthState();
2601
+ updateRequestPreview();
2602
+ })));
2603
+ } else if (type === "http" && httpScheme === "bearer") {
2604
+ card.appendChild(makeField("Bearer Token", makeInput("Bearer token\u2026", state.token, function(e) {
2605
+ authState[schemeName].token = e.target.value;
2606
+ saveAuthState();
2607
+ updateRequestPreview();
2608
+ })));
2609
+ } else if (type === "mutualtls") {
2610
+ const hint = document.createElement("p");
2611
+ hint.className = "text-xs opacity-70 leading-relaxed";
2612
+ hint.textContent = "Configured by your client certificate. No token input required.";
2613
+ card.appendChild(hint);
2614
+ } else {
2615
+ card.appendChild(makeField("Token", makeInput("Token\u2026", state.token, function(e) {
2616
+ authState[schemeName].token = e.target.value;
2617
+ saveAuthState();
2618
+ updateRequestPreview();
2619
+ })));
2620
+ }
2621
+ fields.appendChild(card);
2622
+ }
2623
+ }
2624
+
2625
+ let authPanelOpen = true;
2626
+ document.getElementById("auth-toggle").addEventListener("click", function() {
2627
+ authPanelOpen = !authPanelOpen;
2628
+ const fieldsEl = document.getElementById("auth-fields");
2629
+ const chevron = document.getElementById("auth-chevron");
2630
+ if (fieldsEl) fieldsEl.classList.toggle("hidden", !authPanelOpen);
2631
+ if (chevron) chevron.style.transform = authPanelOpen ? "" : "rotate(-90deg)";
2632
+ });
2633
+
2634
+ // Restore selected operation from URL hash, or set hash for the default selection
2635
+ var initMatch = findOpByHash(window.location.hash);
2636
+ if (initMatch) {
2637
+ selected = initMatch;
2638
+ } else if (selected) {
2639
+ history.replaceState(null, "", getOpHash(selected));
2640
+ }
2641
+
2642
+ window.addEventListener("popstate", function() {
2643
+ var match = findOpByHash(window.location.hash);
2644
+ if (match) {
2645
+ selected = match;
2646
+ renderSidebar();
2647
+ renderEndpoint();
2648
+ }
2649
+ });
2650
+
2651
+ setMobileSidebarOpen(false);
2652
+ renderAuthPanel();
2653
+ renderSidebar();
2654
+ renderEndpoint();
2655
+ </script>
2656
+ </body>
2657
+ </html>`}var xr=new Set(Object.values(G)),vr={ApiKey:"apiKeyAuth",HttpBasic:"basicAuth",HttpBearer:"bearerAuth",HttpDigest:"digestAuth",OAuth2:"oauth2Auth",OpenIdConnect:"openIdConnectAuth",MutualTls:"mutualTlsAuth"};function Er(e){return typeof e==="string"&&xr.has(e)}function kr(e,t){if(e===void 0||e===!1||e===null)return null;if(e===!0)return t;if(Er(e))return e;return t}function ot(e,t){let r=t?.securitySchemeNames?.[e];if(typeof r==="string"&&r.trim().length>0)return r.trim();return vr[e]}function Br(e){switch(e){case"ApiKey":return{type:"apiKey",name:"X-API-Key",in:"header"};case"HttpBasic":return{type:"http",scheme:"basic"};case"HttpBearer":return{type:"http",scheme:"bearer",bearerFormat:"JWT"};case"HttpDigest":return{type:"http",scheme:"digest"};case"OAuth2":return{type:"oauth2",flows:{authorizationCode:{authorizationUrl:"https://example.com/oauth/authorize",tokenUrl:"https://example.com/oauth/token",scopes:{}}}};case"OpenIdConnect":return{type:"openIdConnect",openIdConnectUrl:"https://example.com/.well-known/openid-configuration"};case"MutualTls":return{type:"mutualTLS"};default:return e}}function Ir(e,t){let r=Br(e),a=t?.securitySchemes?.[e];if(!a)return r;let n={...r,...a};if(x(r.flows)&&x(a.flows))n.flows={...r.flows,...a.flows};return n}function Be(e){let t=e?.["~standard"],r=t?.jsonSchema;return!!t&&typeof t==="object"&&t.version===1&&!!r&&typeof r.input==="function"&&typeof r.output==="function"}function lt(e){let t=0,r=[];return{openapiPath:e.split("/").map((n)=>{let o=/^:([A-Za-z0-9_]+)\+$/.exec(n);if(o?.[1])return r.push(o[1]),`{${o[1]}}`;let i=/^:([A-Za-z0-9_]+)$/.exec(n);if(i?.[1])return r.push(i[1]),`{${i[1]}}`;if(n==="*"){t+=1;let d=t===1?"wildcard":`wildcard${t}`;return r.push(d),`{${d}}`}return n}).join("/"),pathParamNames:r}}function Tr(e){return lt(e).openapiPath}function Cr(e,t){return`${e.toLowerCase()}_${t}`.replace(/[:{}]/g,"").replace(/[^A-Za-z0-9_]+/g,"_").replace(/^_+|_+$/g,"")||`${e.toLowerCase()}_operation`}function Lr(e){let t=e.split("/").filter(Boolean);for(let r of t)if(!r.startsWith(":")&&r!=="*")return r.toLowerCase();return"default"}function Nr(e){return lt(e).pathParamNames}function Ar(e,t){let r=new Set((e.parameters||[]).filter((a)=>a.in==="path").map((a)=>String(a.name)));for(let a of Nr(t)){if(r.has(a))continue;(e.parameters||=[]).push({name:a,in:"path",required:!0,schema:{type:"string"}})}}function Sr(e){let t=Number(e);if(!Number.isInteger(t))return!1;return t>=100&&t<200||t===204||t===205||t===304}function Rr(e){let t={"100":"Continue","101":"Switching Protocols","102":"Processing","103":"Early Hints","200":"OK","201":"Created","202":"Accepted","203":"Non-Authoritative Information","204":"No Content","205":"Reset Content","206":"Partial Content","207":"Multi-Status","208":"Already Reported","226":"IM Used","300":"Multiple Choices","301":"Moved Permanently","302":"Found","303":"See Other","304":"Not Modified","305":"Use Proxy","307":"Temporary Redirect","308":"Permanent Redirect","400":"Bad Request","401":"Unauthorized","402":"Payment Required","403":"Forbidden","404":"Not Found","405":"Method Not Allowed","406":"Not Acceptable","407":"Proxy Authentication Required","408":"Request Timeout","409":"Conflict","410":"Gone","411":"Length Required","412":"Precondition Failed","413":"Payload Too Large","414":"URI Too Long","415":"Unsupported Media Type","416":"Range Not Satisfiable","417":"Expectation Failed","418":"I'm a teapot","421":"Misdirected Request","422":"Unprocessable Content","423":"Locked","424":"Failed Dependency","425":"Too Early","426":"Upgrade Required","428":"Precondition Required","429":"Too Many Requests","431":"Request Header Fields Too Large","451":"Unavailable For Legal Reasons","500":"Internal Server Error","501":"Not Implemented","502":"Bad Gateway","503":"Service Unavailable","504":"Gateway Timeout","505":"HTTP Version Not Supported","506":"Variant Also Negotiates","507":"Insufficient Storage","508":"Loop Detected","510":"Not Extended","511":"Network Authentication Required"};if(t[e])return t[e];let r=Number(e);if(Number.isInteger(r)&&r>=100&&r<200)return"Informational Response";if(Number.isInteger(r)&&r>=200&&r<300)return"Successful Response";if(Number.isInteger(r)&&r>=300&&r<400)return"Redirection";if(Number.isInteger(r)&&r>=400&&r<500)return"Client Error";if(Number.isInteger(r)&&r>=500&&r<600)return"Server Error";return"OK"}function Hr(e,t,r,a){if(!Be(t)){let n=oe(t);return Ee(n)?null:n}try{return t["~standard"].jsonSchema.input({target:r})}catch(n){let o=st(t,"input",r,n,e,void 0,a);if(o)return o;a.push(`[OpenAPI] Failed input schema conversion for ${e}: ${n instanceof Error?n.message:String(n)}. Falling back to a permissive JSON Schema.`);let i=oe(t);return Ee(i)?null:i}}function dt(e,t,r,a,n){if(!Be(r)){let o=oe(r);return Ee(o)?null:o}try{return r["~standard"].jsonSchema.output({target:a})}catch(o){let i=st(r,"output",a,o,e,t,n);if(i)return i;return n.push(`[OpenAPI] Failed output schema conversion for ${e} (${t}): ${o instanceof Error?o.message:String(o)}. Falling back to a permissive JSON Schema.`),oe(r)}}function x(e){return!!e&&typeof e==="object"&&!Array.isArray(e)}function Ee(e){return x(e)&&Object.keys(e).length===0}function st(e,t,r,a,n,o,i){if(!Be(e))return null;let d=a instanceof Error?a.message:String(a);if(!(r==="openapi-3.0"&&d.includes("target 'openapi-3.0' is not supported")&&d.includes("draft-2020-12")&&d.includes("draft-07")))return null;try{let c=e["~standard"].jsonSchema[t]({target:"draft-07"});return i.push(t==="input"?`[OpenAPI] ${n} converter does not support openapi-3.0 target; using draft-07 conversion output.`:`[OpenAPI] ${n} (${o}) converter does not support openapi-3.0 target; using draft-07 conversion output.`),c}catch{return null}}function Ie(e){if(!e||typeof e!=="object")return null;let t=e;if(x(t._def))return t._def;if(x(t._zod)&&x(t._zod.def))return t._zod.def;if(t.kind==="schema"&&typeof t.type==="string")return t;return null}function ct(e){if(!e)return null;let t=e.typeName;if(typeof t==="string")return t;let r=e.type;if(typeof r==="string")return r;return null}function ke(e){let t=["innerType","schema","type","out","in","left","right","wrapped","element"];for(let r of t)if(r in e)return e[r];return}function Or(e,t){for(let r of t){let a=e[r];if(a&&typeof a==="object"&&!Array.isArray(a))return a}return}function Dr(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("optional")||t.includes("default")||t.includes("catch")}function jr(e){let t=e,r=!1,a=0;while(a<8){a+=1;let n=Ie(t),o=ct(n);if(!n||!Dr(o))break;r=!0;let i=ke(n);if(!i)break;t=i}return{schema:t,optional:r}}function $r(e){let t=e.entries;if(x(t))return t;let r=e.shape;if(typeof r==="function")try{let a=r();return x(a)?a:{}}catch{return{}}return x(r)?r:{}}function it(e){let t=e.values;if(Array.isArray(t))return t;if(t&&typeof t==="object")return Object.values(t);let r=e.entries;if(r&&typeof r==="object")return Object.values(r);let a=e.enum;if(a&&typeof a==="object")return Object.values(a);let n=e.options;if(Array.isArray(n))return n.map((o)=>{if(o&&typeof o==="object"&&"unit"in o)return o.unit;return o}).filter((o)=>o!==void 0);return[]}function _r(e){let t=e.toLowerCase();if(t.includes("string"))return{type:"string"};if(t.includes("number"))return{type:"number"};if(t.includes("boolean"))return{type:"boolean"};if(t.includes("bigint"))return{type:"string"};if(t==="null"||t.includes("zodnull"))return{type:"null"};if(t.includes("any")||t.includes("unknown")||t.includes("never"))return{};if(t.includes("date"))return{type:"string",format:"date-time"};if(t.includes("custom"))return{type:"object",additionalProperties:!0};return null}function I(e,t=new WeakSet){if(!e||typeof e!=="object")return{};if(t.has(e))return{};t.add(e);let r=Ie(e),a=ct(r);if(!r||!a)return{};let n=_r(a);if(n)return n;let o=a.toLowerCase();if(o.includes("object")){let d=$r(r),l={},c=[];for(let[s,p]of Object.entries(d)){let h=jr(p);if(l[s]=I(h.schema,t),!h.optional)c.push(s)}let m={type:"object",properties:l,additionalProperties:!0};if(c.length>0)m.required=c;return m}if(o.includes("array")){let d=Or(r,["element","items","innerType","type"])??{};return{type:"array",items:I(d,t)}}if(o.includes("record")){let d=r.valueType??r.valueSchema;return{type:"object",additionalProperties:d?I(d,t):!0}}if(o.includes("tuple")){let l=(Array.isArray(r.items)?r.items:[]).map((c)=>I(c,t));return{type:"array",prefixItems:l,minItems:l.length,maxItems:l.length}}if(o.includes("union")){let d=r.options??r.schemas??[];if(!Array.isArray(d)||d.length===0)return{};return{anyOf:d.map((l)=>I(l,t))}}if(o.includes("intersection")){let{left:d,right:l}=r;if(!d||!l)return{};return{allOf:[I(d,t),I(l,t)]}}if(o.includes("enum")){let d=it(r);if(d.length>0){let l=d.every((s)=>typeof s==="string"),c=d.every((s)=>typeof s==="number"),m=d.every((s)=>typeof s==="boolean");if(l)return{type:"string",enum:d};if(c)return{type:"number",enum:d};if(m)return{type:"boolean",enum:d};return{enum:d}}return{}}if(o.includes("picklist")){let d=it(r);if(d.length>0){if(d.every((c)=>typeof c==="string"))return{type:"string",enum:d};return{enum:d}}return{}}if(o.includes("literal")){let d=r.value;if(d===void 0)return{};let l=d===null?"null":typeof d;if(l==="string"||l==="number"||l==="boolean"||l==="null")return{type:l,const:d};return{const:d}}if(o.includes("nullable")){let d=ke(r);if(!d)return{};return{anyOf:[I(d,t),{type:"null"}]}}if(o.includes("lazy")){let d=r.getter;if(typeof d!=="function")return{};try{return I(d(),t)}catch{return{}}}let i=ke(r);if(i)return I(i,t);return{}}function oe(e){if(!Ie(e))return{};return I(e)}function Ur(e,t){if(!x(t))return;if(t.type!=="object"||!x(t.properties)){e.requestBody={required:!0,content:{"application/json":{schema:t}}};return}let r=new Set(Array.isArray(t.required)?t.required:[]),a=t.properties,n=Array.isArray(e.parameters)?e.parameters:[],o=[{key:"params",in:"path"},{key:"query",in:"query"},{key:"headers",in:"header"},{key:"cookies",in:"cookie"}];for(let d of o){let l=a[d.key];if(!x(l))continue;if(l.type!=="object"||!x(l.properties))continue;let c=new Set(Array.isArray(l.required)?l.required:[]);for(let[m,s]of Object.entries(l.properties))n.push({name:m,in:d.in,required:d.in==="path"?!0:c.has(m),schema:x(s)?s:{}})}if(n.length>0){let d=new Map;for(let l of n)d.set(`${l.in}:${l.name}`,l);e.parameters=[...d.values()]}let i=a.body;if(i)e.requestBody={required:r.has("body"),content:{"application/json":{schema:x(i)?i:{}}}}}function Mr(e,t,r,a,n){let o=r.output;if(!o){e.responses={200:{description:"OK"}};return}let i={};if(typeof o==="object"&&o!==null&&"~standard"in o){let d=dt(t,"200",o,a,n);if(d)i["200"]={description:"OK",content:{"application/json":{schema:d}}};else i["200"]={description:"OK"}}else for(let[d,l]of Object.entries(o)){let c=String(d),m=dt(t,c,l,a,n),s=Rr(c);if(m&&!Sr(c))i[c]={description:s,content:{"application/json":{schema:m}}};else i[c]={description:s}}if(Object.keys(i).length===0)i["200"]={description:"OK"};e.responses=i}function pt(e,t){let r=[],a={},n="HttpBearer",o=new Set;for(let l of e){if(l.options.expose===!1)continue;if(!l.method||!l.path)continue;let c=l.method.toLowerCase();if(c==="options")continue;let m=Tr(l.path),s={operationId:Cr(c,m),tags:[l.options.schema?.tag||Lr(l.path)]};if(typeof l.options.schema?.summary==="string"&&l.options.schema.summary.trim())s.summary=l.options.schema.summary.trim();let p=typeof l.options.schema?.description==="string"&&l.options.schema.description.trim()?l.options.schema.description.trim():typeof l.options.schema?.descrition==="string"&&l.options.schema.descrition.trim()?l.options.schema.descrition.trim():void 0;if(p)s.description=p;if(l.options.deprecated===!0)s.deprecated=!0;let h=kr(l.options.auth,n);if(h){o.add(h);let w=ot(h,t.auth);s.security=[{[w]:[]}]}let u=Hr(l.path,l.options.schema?.input,t.target,r);if(u){if(!s.summary&&typeof u.title==="string"&&u.title.trim())s.summary=u.title.trim();if(!s.description&&typeof u.description==="string"&&u.description.trim())s.description=u.description.trim();Ur(s,u)}if(Ar(s,l.path),Mr(s,l.path,l.options.schema||{},t.target,r),!s.summary||!s.description){let w=Object.values(s.responses||{});for(let R of w){let E=R?.content?.["application/json"]?.schema;if(!E||typeof E!=="object")continue;if(!s.summary&&typeof E.title==="string"&&E.title.trim())s.summary=E.title.trim();if(!s.description&&typeof E.description==="string"&&E.description.trim())s.description=E.description.trim();if(s.summary&&s.description)break}}a[m]||={},a[m][c]=s}let d={openapi:t.target==="openapi-3.0"?"3.0.3":"3.1.0",info:{title:t.info?.title||"Vector API",version:t.info?.version||"1.0.0",...t.info?.description?{description:t.info.description}:{}},paths:a};if(o.size>0){let l={};for(let c of o){let m=ot(c,t.auth);l[m]=Ir(c,t.auth)}d.components={securitySchemes:l}}return{document:d,warnings:r}}var Te="/_vector/openapi/tailwindcdn.js",Ce="/_vector/openapi/logo_dark.svg",Le="/_vector/openapi/logo_white.svg",yt="/_vector/openapi/favicon/apple-touch-icon.png",wt="/_vector/openapi/favicon/favicon-32x32.png",xt="/_vector/openapi/favicon/favicon-16x16.png",Pr="/_vector/openapi/favicon/favicon.ico",vt="/_vector/openapi/favicon/site.webmanifest",zr="/_vector/openapi/favicon/android-chrome-192x192.png",Jr="/_vector/openapi/favicon/android-chrome-512x512.png",Fr=["../openapi/assets/tailwindcdn.js","../src/openapi/assets/tailwindcdn.js","../../src/openapi/assets/tailwindcdn.js"],Gr=["../openapi/assets/logo_dark.svg","../src/openapi/assets/logo_dark.svg","../../src/openapi/assets/logo_dark.svg"],Yr=["../openapi/assets/logo_white.svg","../src/openapi/assets/logo_white.svg","../../src/openapi/assets/logo_white.svg"],Qr=["src/openapi/assets/tailwindcdn.js","openapi/assets/tailwindcdn.js","dist/openapi/assets/tailwindcdn.js"],Vr=["src/openapi/assets/logo_dark.svg","openapi/assets/logo_dark.svg","dist/openapi/assets/logo_dark.svg"],Wr=["src/openapi/assets/logo_white.svg","openapi/assets/logo_white.svg","dist/openapi/assets/logo_white.svg"],U=["../openapi/assets/favicon","../src/openapi/assets/favicon","../../src/openapi/assets/favicon"],M=["src/openapi/assets/favicon","openapi/assets/favicon","dist/openapi/assets/favicon"],Xr="/* OpenAPI docs runtime asset missing: tailwind disabled */";function v(e,t){return e.map((r)=>`${r}/${t}`)}function L(e,t){for(let a of e)try{let n=new URL(a,import.meta.url);if(Se.existsSync(n))return Bun.file(n)}catch{}let r=process.cwd();for(let a of t){let n=gt.join(r,a);if(Se.existsSync(n))return Bun.file(n)}return null}var mt=L(Fr,Qr),bt=L(Gr,Vr),ut=L(Yr,Wr),Zr=L(v(U,"apple-touch-icon.png"),v(M,"apple-touch-icon.png")),qr=L(v(U,"favicon-32x32.png"),v(M,"favicon-32x32.png")),Kr=L(v(U,"favicon-16x16.png"),v(M,"favicon-16x16.png")),ea=L(v(U,"favicon.ico"),v(M,"favicon.ico")),ta=L(v(U,"site.webmanifest"),v(M,"site.webmanifest")),ra=L(v(U,"android-chrome-192x192.png"),v(M,"android-chrome-192x192.png")),aa=L(v(U,"android-chrome-512x512.png"),v(M,"android-chrome-512x512.png")),ht=[{path:yt,file:Zr,contentType:"image/png",filename:"apple-touch-icon.png"},{path:wt,file:qr,contentType:"image/png",filename:"favicon-32x32.png"},{path:xt,file:Kr,contentType:"image/png",filename:"favicon-16x16.png"},{path:Pr,file:ea,contentType:"image/x-icon",filename:"favicon.ico"},{path:vt,file:ta,contentType:"application/manifest+json; charset=utf-8",filename:"site.webmanifest"},{path:zr,file:ra,contentType:"image/png",filename:"android-chrome-192x192.png"},{path:Jr,file:aa,contentType:"image/png",filename:"android-chrome-512x512.png"}],Ne="public, max-age=0, must-revalidate",K="public, max-age=31536000, immutable",Ae="no-store",na=3000;function ft(e){if(e===void 0)return na;let t=Number(e);if(!Number.isInteger(t)||t<0||t>65535)throw new Error(`Invalid port: ${String(e)}. Port must be an integer between 0 and 65535.`);return t}function oa(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function da(e){let t="^";for(let r of e){if(r==="*"){t+=".*";continue}t+=oa(r)}return t+="$",new RegExp(t)}function ia(e,t){if(!t.includes("*"))return e===t;return da(t).test(e)}class Re{server=null;router;config;openapiConfig;openapiDocCache=null;openapiDocsHtmlCache=null;openapiWarningsLogged=!1;openapiTailwindMissingLogged=!1;openapiLogoDarkMissingLogged=!1;openapiLogoWhiteMissingLogged=!1;corsHandler=null;corsHeadersEntries=null;constructor(e,t){if(this.router=e,this.config=t,this.openapiConfig=this.normalizeOpenAPIConfig(t.openapi,t.development),t.cors){let r=this.normalizeCorsOptions(t.cors),{preflight:a,corsify:n}=at(r);if(this.corsHandler={preflight:a,corsify:n},typeof r.origin==="string"&&(r.origin!=="*"||!r.credentials)){let i={"access-control-allow-origin":r.origin,"access-control-allow-methods":r.allowMethods,"access-control-allow-headers":r.allowHeaders,"access-control-expose-headers":r.exposeHeaders,"access-control-max-age":String(r.maxAge)};if(r.credentials)i["access-control-allow-credentials"]="true";this.corsHeadersEntries=Object.entries(i)}this.router.setCorsHeaders(this.corsHeadersEntries),this.router.setCorsHandler(this.corsHeadersEntries?null:this.corsHandler.corsify)}}setCheckpointGateway(e){this.router.setCheckpointGateway(e)}normalizeOpenAPIConfig(e,t){let a=t!==!1&&!0;if(e===!1)return{enabled:!1,path:"/openapi.json",target:"openapi-3.0",docs:{enabled:!1,path:"/docs"}};if(e===!0)return{enabled:!0,path:"/openapi.json",target:"openapi-3.0",docs:{enabled:!1,path:"/docs"}};let n=e||{},o=n.docs,i=typeof o==="boolean"?{enabled:o,path:"/docs",exposePaths:void 0}:{enabled:o?.enabled===!0,path:o?.path||"/docs",exposePaths:Array.isArray(o?.exposePaths)?o.exposePaths.map((d)=>typeof d==="string"?d.trim():"").filter((d)=>d.length>0):void 0};return{enabled:n.enabled??a,path:n.path||"/openapi.json",target:n.target||"openapi-3.0",docs:i,info:n.info,auth:n.auth}}isDocsReservedPath(e){return e===this.openapiConfig.path||this.openapiConfig.docs.enabled&&e===this.openapiConfig.docs.path}shouldLogOpenAPIConversionWarnings(){if(this.config.development===!1)return!1;let r=process.env.LOG_LEVEL;return typeof r==="string"&&r.toLowerCase()==="debug"}getOpenAPIDocument(){if(this.openapiDocCache)return this.openapiDocCache;let e=this.router.getRouteDefinitions().filter((r)=>!this.isDocsReservedPath(r.path)),t=pt(e,{target:this.openapiConfig.target,info:this.openapiConfig.info,auth:this.openapiConfig.auth});if(!this.openapiWarningsLogged&&t.warnings.length>0){if(this.shouldLogOpenAPIConversionWarnings())for(let r of t.warnings)console.warn(r);this.openapiWarningsLogged=!0}return this.openapiDocCache=t.document,this.openapiDocCache}getOpenAPIDocumentForDocs(){let e=this.openapiConfig.docs.exposePaths,t=this.getOpenAPIDocument();if(!Array.isArray(e)||e.length===0)return t;let r=t.paths&&typeof t.paths==="object"&&!Array.isArray(t.paths)?t.paths:{},a={};for(let[n,o]of Object.entries(r))if(e.some((i)=>ia(n,i)))a[n]=o;return{...t,paths:a}}getOpenAPIDocsHtmlCacheEntry(){if(this.openapiDocsHtmlCache)return this.openapiDocsHtmlCache;let e=nt(this.getOpenAPIDocumentForDocs(),this.openapiConfig.path,Te,Ce,Le,yt,wt,xt,vt),t=Bun.gzipSync(e),r=`"${Bun.hash(e).toString(16)}"`;return this.openapiDocsHtmlCache={html:e,gzip:t,etag:r},this.openapiDocsHtmlCache}requestAcceptsGzip(e){let t=e.headers.get("accept-encoding");return Boolean(t&&/\bgzip\b/i.test(t))}validateReservedOpenAPIPaths(){if(!this.openapiConfig.enabled)return;let e=new Set([this.openapiConfig.path]);if(this.openapiConfig.docs.enabled){e.add(this.openapiConfig.docs.path),e.add(Te),e.add(Ce),e.add(Le);for(let n of ht)e.add(n.path)}let t=this.router.getRouteDefinitions().filter((n)=>e.has(n.path)).map((n)=>`${n.method} ${n.path}`),r=Object.entries(this.router.getRouteTable()).filter(([n,o])=>e.has(n)&&o instanceof Response).map(([n])=>`STATIC ${n}`),a=[...t,...r];if(a.length>0)throw new Error(`OpenAPI reserved path conflict: ${a.join(", ")}. Change your route path(s) or reconfigure openapi.path/docs.path.`)}tryHandleOpenAPIRequest(e){if(!this.openapiConfig.enabled||e.method!=="GET")return null;let t=new URL(e.url).pathname;if(t===this.openapiConfig.path)return Response.json(this.getOpenAPIDocument());if(this.openapiConfig.docs.enabled&&t===this.openapiConfig.docs.path){let{html:r,gzip:a,etag:n}=this.getOpenAPIDocsHtmlCacheEntry();if(e.headers.get("if-none-match")===n)return new Response(null,{status:304,headers:{etag:n,"cache-control":Ne,vary:"accept-encoding"}});if(this.requestAcceptsGzip(e))return new Response(a,{status:200,headers:{"content-type":"text/html; charset=utf-8","content-encoding":"gzip",etag:n,"cache-control":Ne,vary:"accept-encoding"}});return new Response(r,{status:200,headers:{"content-type":"text/html; charset=utf-8",etag:n,"cache-control":Ne,vary:"accept-encoding"}})}if(this.openapiConfig.docs.enabled&&t===Te){if(!mt){if(!this.openapiTailwindMissingLogged)this.openapiTailwindMissingLogged=!0,console.warn('[OpenAPI] Missing docs runtime asset "tailwindcdn.js". Serving inline fallback script instead.');return new Response(Xr,{status:200,headers:{"content-type":"application/javascript; charset=utf-8","cache-control":K}})}return new Response(mt,{status:200,headers:{"content-type":"application/javascript; charset=utf-8","cache-control":K}})}if(this.openapiConfig.docs.enabled&&t===Ce){if(!bt){if(!this.openapiLogoDarkMissingLogged)this.openapiLogoDarkMissingLogged=!0,console.warn('[OpenAPI] Missing docs runtime asset "logo_dark.svg".');return new Response("OpenAPI docs runtime asset missing: logo_dark.svg",{status:404,headers:{"content-type":"text/plain; charset=utf-8","cache-control":Ae}})}return new Response(bt,{status:200,headers:{"content-type":"image/svg+xml; charset=utf-8","cache-control":K}})}if(this.openapiConfig.docs.enabled&&t===Le){if(!ut){if(!this.openapiLogoWhiteMissingLogged)this.openapiLogoWhiteMissingLogged=!0,console.warn('[OpenAPI] Missing docs runtime asset "logo_white.svg".');return new Response("OpenAPI docs runtime asset missing: logo_white.svg",{status:404,headers:{"content-type":"text/plain; charset=utf-8","cache-control":Ae}})}return new Response(ut,{status:200,headers:{"content-type":"image/svg+xml; charset=utf-8","cache-control":K}})}if(this.openapiConfig.docs.enabled){let r=ht.find((a)=>a.path===t);if(r){if(!r.file)return new Response(`OpenAPI docs runtime asset missing: ${r.filename}`,{status:404,headers:{"content-type":"text/plain; charset=utf-8","cache-control":Ae}});return new Response(r.file,{status:200,headers:{"content-type":r.contentType,"cache-control":K}})}}return null}normalizeCorsOptions(e){return{origin:e.origin||"*",credentials:e.credentials!==!1,allowHeaders:Array.isArray(e.allowHeaders)?e.allowHeaders.join(", "):e.allowHeaders||"Content-Type, Authorization",allowMethods:Array.isArray(e.allowMethods)?e.allowMethods.join(", "):e.allowMethods||"GET, POST, PUT, PATCH, DELETE, OPTIONS",exposeHeaders:Array.isArray(e.exposeHeaders)?e.exposeHeaders.join(", "):e.exposeHeaders||"Authorization",maxAge:e.maxAge||86400}}applyCors(e,t){if(this.corsHeadersEntries){for(let[r,a]of this.corsHeadersEntries)e.headers.set(r,a);return e}if(this.corsHandler&&t)return this.corsHandler.corsify(e,t);return e}async start(){let e=ft(this.config.port),t=this.config.hostname||"localhost";this.validateReservedOpenAPIPaths();let r=async(a)=>{try{if(this.corsHandler&&a.method==="OPTIONS")return this.corsHandler.preflight(a);let n=this.tryHandleOpenAPIRequest(a);if(n)return this.applyCors(n,a);return await this.router.handle(a)}catch(n){return console.error("Server error:",n),this.applyCors(new Response("Internal Server Error",{status:500}),a)}};try{if(this.server=Bun.serve({port:e,hostname:t,reusePort:this.config.reusePort!==!1,fetch:r,idleTimeout:this.config.idleTimeout??60,error:(a,n)=>{return console.error("[ERROR] Server error:",a),this.applyCors(new Response("Internal Server Error",{status:500}),n)}}),!this.server||!this.server.port)throw new Error(`Failed to start server on ${t}:${e} - server object is invalid`);return this.server}catch(a){if(a.code==="EADDRINUSE"||a.message?.includes("address already in use"))a.message=`Port ${e} is already in use`,a.port=e;else if(a.code==="EACCES"||a.message?.includes("permission denied"))a.message=`Permission denied to bind to port ${e}`,a.port=e;else if(a.message?.includes("EADDRNOTAVAIL"))a.message=`Cannot bind to hostname ${t}`,a.hostname=t;throw a}}stop(){if(this.server)this.server.stop(),this.server=null,this.openapiDocCache=null,this.openapiDocsHtmlCache=null,this.openapiWarningsLogged=!1,console.log("Server stopped")}getServer(){return this.server}getPort(){return this.server?.port??ft(this.config.port)}getHostname(){return this.server?.hostname||this.config.hostname||"localhost"}getUrl(){let e=this.getPort();return`http://${this.getHostname()}:${e}`}}class z{static instance;router;server=null;middlewareManager;authManager;cacheManager;config={};routeScanner=null;routeGenerator=null;_protectedHandler=null;_cacheHandler=null;shutdownPromise=null;checkpointProcessManager=null;constructor(){this.middlewareManager=new ae,this.authManager=new be,this.cacheManager=new ue,this.router=new q(this.middlewareManager,this.authManager,this.cacheManager)}static getInstance(){if(!z.instance)z.instance=new z;return z.instance}setProtectedHandler(e){if(this._protectedHandler=e,e){this.authManager.setProtectedHandler(e);return}this.authManager.clearProtectedHandler()}getProtectedHandler(){return this._protectedHandler}setCacheHandler(e){if(this._cacheHandler=e,e){this.cacheManager.setCacheHandler(e);return}this.cacheManager.clearCacheHandler()}getCacheHandler(){return this._cacheHandler}addRoute(e,t){this.router.route(e,t)}async startServer(e){if(this.checkpointProcessManager)await this.checkpointProcessManager.stopAll(),this.checkpointProcessManager=null;this.config={...this.config,...e};let t={...this.config.defaults?.route};if(this.router.setRouteBooleanDefaults(t),this.router.setDevelopmentMode(this.config.development),this.middlewareManager.clear(),this.config.autoDiscover!==!1)this.router.clearRoutes();if(e?.before)this.middlewareManager.addBefore(...e.before);if(e?.finally)this.middlewareManager.addFinally(...e.finally);if(typeof this.config.startup==="function")await this.config.startup();if(this.config.autoDiscover!==!1)await this.discoverRoutes();this.server=new Re(this.router,this.config);let r=await this.server.start();if(this.config.checkpoint&&this.config.checkpoint.enabled!==!1)await this.enableCheckpointGateway(this.config.checkpoint);return r}async discoverRoutes(){let e=this.config.routesDir||"./routes",t=this.config.routeExcludePatterns;if(this.routeScanner=new re(e,t),!this.routeGenerator)this.routeGenerator=new fe;try{let r=await this.routeScanner.scan();if(r.length>0){if(this.config.development)await this.routeGenerator.generate(r);for(let a of r)try{let o=await import(`${ne(a.path)}?t=${Date.now()}`),i=a.name==="default"?o.default:o[a.name];if(i){if(this.isRouteDefinition(i))this.router.route(i.options,i.handler),this.logRouteLoaded(i.options);else if(this.isRouteEntry(i))this.router.addRoute(i),this.logRouteLoaded(i);else if(typeof i==="function")this.router.route(a.options,i),this.logRouteLoaded(a.options)}}catch(n){console.error(`Failed to load route ${a.name} from ${a.path}:`,n)}}}catch(r){if(r.code!=="ENOENT"&&r.code!=="ENOTDIR")console.error("Failed to discover routes:",r)}}async loadRoute(e){if(typeof e==="function"){let t=e();if(this.isRouteEntry(t))this.router.addRoute(t)}else if(e&&typeof e==="object"){for(let[,t]of Object.entries(e))if(typeof t==="function"){let r=t();if(this.isRouteEntry(r))this.router.addRoute(r)}}}isRouteEntry(e){if(!Array.isArray(e)||e.length<3)return!1;let[t,r,a,n]=e;return typeof t==="string"&&r instanceof RegExp&&Array.isArray(a)&&a.length>0&&a.every((o)=>typeof o==="function")&&(n===void 0||typeof n==="string")}isRouteDefinition(e){return e!==null&&typeof e==="object"&&"entry"in e&&"options"in e&&"handler"in e&&typeof e.handler==="function"}logRouteLoaded(e){}async enableCheckpointGateway(e){if(!this.server)throw new Error("Cannot enable checkpoint gateway before server is started. Call startServer() first.");let{CheckpointManager:t}=await Promise.resolve().then(() => (Vt(),Qt)),{CheckpointProcessManager:r}=await Promise.resolve().then(() => (rr(),tr)),{CheckpointResolver:a}=await Promise.resolve().then(() => nr),{CheckpointForwarder:n}=await Promise.resolve().then(() => dr),{CheckpointGateway:o}=await Promise.resolve().then(() => lr);if(this.checkpointProcessManager)await this.checkpointProcessManager.stopAll(),this.checkpointProcessManager=null;let i=new t(e),d=new r({idleTimeoutMs:e?.idleTimeoutMs});this.checkpointProcessManager=d;let l=new a(i,d,{versionHeader:e?.versionHeader,cacheKeyOverride:e?.cacheKeyOverride}),c=new n,m=new o(l,c);this.server.setCheckpointGateway(m);let s=await i.getActive();if(s)try{let p=await i.readManifest(s.version);await d.spawn(p,i.getStorageDir())}catch(p){console.error(`[Checkpoint] Failed to start active checkpoint ${s.version}:`,p)}}stop(){if(this.server)this.server.stop(),this.server=null}async shutdown(){if(this.shutdownPromise)return this.shutdownPromise;this.shutdownPromise=(async()=>{if(this.stop(),this.checkpointProcessManager)await this.checkpointProcessManager.stopAll(),this.checkpointProcessManager=null;if(typeof this.config.shutdown==="function")await this.config.shutdown()})();try{await this.shutdownPromise}finally{this.shutdownPromise=null}}getServer(){return this.server}getRouter(){return this.router}getCacheManager(){return this.cacheManager}getAuthManager(){return this.authManager}static resetInstance(){z.instance=null}}var Ge=z.getInstance;function Ye(e,t){return{entry:{method:e.method.toUpperCase(),path:e.path},options:e,handler:t}}function sr(e,t){return Ye({...e,deprecated:!0},t)}function Da(e){let t=e??null;try{return JSON.stringify(t)}catch(r){if(r instanceof TypeError&&/\bbigint\b/i.test(r.message))return JSON.stringify(t,(a,n)=>typeof n==="bigint"?n.toString():n);throw r}}function ja(e){return(e.split(";",1)[0]??e).trim().toLowerCase()===W.JSON}function $a(e){let t=[`${e.name}=${e.value}`];if(e.maxAge!==void 0&&Number.isFinite(e.maxAge))t.push(`Max-Age=${Math.trunc(e.maxAge)}`);if(e.domain)t.push(`Domain=${e.domain}`);if(e.path)t.push(`Path=${e.path}`);if(e.expires!==void 0){let r=e.expires instanceof Date?e.expires:new Date(e.expires);if(!Number.isNaN(r.getTime()))t.push(`Expires=${r.toUTCString()}`)}if(e.httpOnly)t.push("HttpOnly");if(e.secure)t.push("Secure");if(e.sameSite)t.push(`SameSite=${e.sameSite}`);if(e.partitioned)t.push("Partitioned");if(e.priority)t.push(`Priority=${e.priority}`);return t.join("; ")}function _a(e,t){if(!t||t.length===0)return;for(let r of t)e.append("set-cookie",typeof r==="string"?r:$a(r))}function b(e,t,r){let a={error:!0,message:t,statusCode:e,timestamp:new Date().toISOString()};return _(e,a,r)}var D={badRequest:(e="Bad Request",t)=>b(O.BAD_REQUEST,e,t),unauthorized:(e="Unauthorized",t)=>b(O.UNAUTHORIZED,e,t),paymentRequired:(e="Payment Required",t)=>b(402,e,t),forbidden:(e="Forbidden",t)=>b(O.FORBIDDEN,e,t),notFound:(e="Not Found",t)=>b(O.NOT_FOUND,e,t),methodNotAllowed:(e="Method Not Allowed",t)=>b(405,e,t),notAcceptable:(e="Not Acceptable",t)=>b(406,e,t),requestTimeout:(e="Request Timeout",t)=>b(408,e,t),conflict:(e="Conflict",t)=>b(O.CONFLICT,e,t),gone:(e="Gone",t)=>b(410,e,t),lengthRequired:(e="Length Required",t)=>b(411,e,t),preconditionFailed:(e="Precondition Failed",t)=>b(412,e,t),payloadTooLarge:(e="Payload Too Large",t)=>b(413,e,t),uriTooLong:(e="URI Too Long",t)=>b(414,e,t),unsupportedMediaType:(e="Unsupported Media Type",t)=>b(415,e,t),rangeNotSatisfiable:(e="Range Not Satisfiable",t)=>b(416,e,t),expectationFailed:(e="Expectation Failed",t)=>b(417,e,t),imATeapot:(e="I'm a teapot",t)=>b(418,e,t),misdirectedRequest:(e="Misdirected Request",t)=>b(421,e,t),unprocessableEntity:(e="Unprocessable Entity",t)=>b(O.UNPROCESSABLE_ENTITY,e,t),locked:(e="Locked",t)=>b(423,e,t),failedDependency:(e="Failed Dependency",t)=>b(424,e,t),tooEarly:(e="Too Early",t)=>b(425,e,t),upgradeRequired:(e="Upgrade Required",t)=>b(426,e,t),preconditionRequired:(e="Precondition Required",t)=>b(428,e,t),tooManyRequests:(e="Too Many Requests",t)=>b(429,e,t),requestHeaderFieldsTooLarge:(e="Request Header Fields Too Large",t)=>b(431,e,t),unavailableForLegalReasons:(e="Unavailable For Legal Reasons",t)=>b(451,e,t),internalServerError:(e="Internal Server Error",t)=>b(O.INTERNAL_SERVER_ERROR,e,t),notImplemented:(e="Not Implemented",t)=>b(501,e,t),badGateway:(e="Bad Gateway",t)=>b(502,e,t),serviceUnavailable:(e="Service Unavailable",t)=>b(503,e,t),gatewayTimeout:(e="Gateway Timeout",t)=>b(504,e,t),httpVersionNotSupported:(e="HTTP Version Not Supported",t)=>b(505,e,t),variantAlsoNegotiates:(e="Variant Also Negotiates",t)=>b(506,e,t),insufficientStorage:(e="Insufficient Storage",t)=>b(507,e,t),loopDetected:(e="Loop Detected",t)=>b(508,e,t),notExtended:(e="Not Extended",t)=>b(510,e,t),networkAuthenticationRequired:(e="Network Authentication Required",t)=>b(511,e,t),invalidArgument:(e="Invalid Argument",t)=>b(O.UNPROCESSABLE_ENTITY,e,t),rateLimitExceeded:(e="Rate Limit Exceeded",t)=>b(429,e,t),maintenance:(e="Service Under Maintenance",t)=>b(503,e,t),custom:(e,t,r)=>b(e,t,r)};function _(e,t,r=W.JSON){let a=typeof r==="string"?{contentType:r}:r??{},n=new Headers(a.headers),o=a.contentType??n.get("content-type")??W.JSON;if(a.contentType||!n.has("content-type"))n.set("content-type",o);_a(n,a.cookies);let i=ja(o)?Da(t):t;return new Response(i,{status:e,statusText:a.statusText,headers:n})}var cr=require("fs"),pe=require("path");class Qe{configPath;config=null;configSource="default";constructor(e){let t=e||"vector.config.ts";this.configPath=pe.isAbsolute(t)?t:pe.resolve(process.cwd(),t)}async load(){if(cr.existsSync(this.configPath))try{let t=await import(`${ne(this.configPath)}?t=${Date.now()}`);this.config=t.default||t,this.configSource="user"}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[vector] Failed to load config from ${this.configPath}: ${t}`),console.error("[vector] Server is using default configuration. Fix your config file and restart."),this.config={}}else this.config={};return await this.buildLegacyConfig()}getConfigSource(){return this.configSource}async buildLegacyConfig(){let e={};if(this.config)e.port=this.normalizePort(this.config.port),e.hostname=this.config.hostname,e.reusePort=this.config.reusePort,e.development=this.config.development,e.routesDir=this.config.routesDir||"./routes",e.routeExcludePatterns=this.config.routeExcludePatterns,e.idleTimeout=this.config.idleTimeout,e.defaults=this.config.defaults,e.openapi=this.config.openapi,e.startup=this.config.startup,e.shutdown=this.config.shutdown,e.checkpoint=this.config.checkpoint;if(e.autoDiscover=!0,this.config?.cors)if(typeof this.config.cors==="boolean")e.cors=this.config.cors?{origin:"*",credentials:!0,allowHeaders:"Content-Type, Authorization",allowMethods:"GET, POST, PUT, PATCH, DELETE, OPTIONS",exposeHeaders:"Authorization",maxAge:86400}:void 0;else e.cors=this.config.cors;if(this.config?.before)e.before=this.config.before;if(this.config?.after)e.finally=this.config.after;return e}normalizePort(e){if(e===void 0)return;return Number(e)}async loadAuthHandler(){return this.config?.auth||null}async loadCacheHandler(){return this.config?.cache||null}getConfig(){return this.config}}async function pr(e={}){let t=new Qe(e.configPath),r=await t.load(),a=t.getConfigSource(),n={...r};if(e.mutateConfig)n=await e.mutateConfig(n,{configSource:a});if(e.config)n={...n,...e.config};if(e.autoDiscover!==void 0)n.autoDiscover=e.autoDiscover;let o=Ge(),i=e.protectedHandler!==void 0?e.protectedHandler:await t.loadAuthHandler(),d=e.cacheHandler!==void 0?e.cacheHandler:await t.loadCacheHandler();o.setProtectedHandler(i??null),o.setCacheHandler(d??null);let l=await o.startServer(n),c={...n,port:l.port??n.port??F.PORT,hostname:l.hostname||n.hostname||F.HOSTNAME,reusePort:n.reusePort!==!1,idleTimeout:n.idleTimeout??60};return{server:l,config:c,stop:()=>o.stop(),shutdown:()=>o.shutdown()}}})