@cartanova/qgrid-cli 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/bundle/dist/application/qgrid/pool.js +15 -6
  2. package/bundle/dist/application/qgrid/qgrid.frame.js +17 -22
  3. package/bundle/dist/application/qgrid/qgrid.types.js +5 -2
  4. package/bundle/dist/application/request-log/request-log.model.js +2 -2
  5. package/bundle/dist/sonamu.config.js +5 -2
  6. package/bundle/src/application/qgrid/pool.ts +17 -7
  7. package/bundle/src/application/qgrid/qgrid.frame.ts +18 -25
  8. package/bundle/src/application/qgrid/qgrid.types.ts +1 -1
  9. package/bundle/src/application/request-log/request-log.model.ts +2 -2
  10. package/bundle/src/sonamu.config.ts +1 -1
  11. package/bundle/web-dist/{web-dist/client/assets/index-DlPchHBY.js → client/assets/index-C0m8rRjO.js} +2 -2
  12. package/bundle/web-dist/client/assets/{routes-CagDz23B.js → routes-B1eOXnpo.js} +1 -1
  13. package/bundle/web-dist/client/assets/{show-aXUGa0gm.js → show-BztN6MXO.js} +1 -1
  14. package/bundle/web-dist/client/assets/tokens-rR2_-Pte.js +1 -0
  15. package/bundle/web-dist/client/index.html +1 -1
  16. package/bundle/web-dist/server/assets/{tokens-JH6FsnWZ.js → tokens-ARL5AOAh.js} +4 -1
  17. package/bundle/web-dist/server/entry-server.generated.js +1 -1
  18. package/dist/cli.js +34 -25
  19. package/package.json +11 -11
  20. package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +0 -9
  21. package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +0 -6
  22. package/bundle/dist/dist/_virtual/_rolldown/runtime.js +0 -15
  23. package/bundle/dist/dist/application/qgrid/oauth.js +0 -140
  24. package/bundle/dist/dist/application/qgrid/pool.js +0 -100
  25. package/bundle/dist/dist/application/qgrid/qgrid.frame.js +0 -280
  26. package/bundle/dist/dist/application/qgrid/qgrid.types.js +0 -79
  27. package/bundle/dist/dist/application/qgrid/worker.js +0 -183
  28. package/bundle/dist/dist/application/queries.generated.js +0 -31
  29. package/bundle/dist/dist/application/request-log/request-log.model.js +0 -113
  30. package/bundle/dist/dist/application/request-log/request-log.types.js +0 -13
  31. package/bundle/dist/dist/application/sonamu.generated.js +0 -99
  32. package/bundle/dist/dist/application/sonamu.generated.sso.js +0 -34
  33. package/bundle/dist/dist/application/token/token.model.js +0 -157
  34. package/bundle/dist/dist/application/token/token.types.js +0 -22
  35. package/bundle/dist/dist/i18n/en.js +0 -63
  36. package/bundle/dist/dist/i18n/ko.js +0 -62
  37. package/bundle/dist/dist/i18n/sd.generated.js +0 -272
  38. package/bundle/dist/dist/index.js +0 -11
  39. package/bundle/dist/dist/migrations/20260410171405_create__request_logs.js +0 -26
  40. package/bundle/dist/dist/migrations/20260410171406_create__tokens.js +0 -24
  41. package/bundle/dist/dist/migrations/20260411120624_alter_tokens_alter2.js +0 -16
  42. package/bundle/dist/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -155
  43. package/bundle/dist/dist/node_modules/.pnpm/@vitest_expect@4.1.2/node_modules/@vitest/expect/dist/index.js +0 -1484
  44. package/bundle/dist/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.2/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  45. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2746
  46. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/index.js +0 -8
  47. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/utils.js +0 -8
  48. package/bundle/dist/dist/node_modules/.pnpm/@vitest_snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js +0 -662
  49. package/bundle/dist/dist/node_modules/.pnpm/@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js +0 -386
  50. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -82
  51. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/constants.js +0 -48
  52. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/diff.js +0 -1307
  53. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/display.js +0 -558
  54. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js +0 -33
  55. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js +0 -226
  56. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js +0 -27
  57. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/serialize.js +0 -77
  58. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js +0 -374
  59. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js +0 -37
  60. package/bundle/dist/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2886
  61. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
  62. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
  63. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
  64. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
  65. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
  66. package/bundle/dist/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1127
  67. package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
  68. package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
  69. package/bundle/dist/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -506
  70. package/bundle/dist/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -86
  71. package/bundle/dist/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.9.2_@emnapi_runtime@1.9.2_@types_node@25.0.7_esbuild@0.27.4_jiti@2.6.1_sass@1.98.0_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js +0 -426
  72. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -6
  73. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
  74. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
  75. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
  76. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/index.DOa3dzoN.js +0 -16
  77. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -59
  78. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/test.p_J6dB8a.js +0 -2910
  79. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -44
  80. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/index.js +0 -28
  81. package/bundle/dist/dist/sonamu.config.js +0 -196
  82. package/bundle/dist/dist/testing/fixture.js +0 -8
  83. package/bundle/dist/dist/testing/global.js +0 -9
  84. package/bundle/dist/dist/testing/setup-mocks.js +0 -17
  85. package/bundle/dist/dist/utils/subset-loaders.js +0 -12
  86. package/bundle/src/src/application/qgrid/oauth.ts +0 -181
  87. package/bundle/src/src/application/qgrid/pool.ts +0 -132
  88. package/bundle/src/src/application/qgrid/qgrid.frame.ts +0 -275
  89. package/bundle/src/src/application/qgrid/qgrid.types.ts +0 -117
  90. package/bundle/src/src/application/qgrid/worker.ts +0 -234
  91. package/bundle/src/src/application/queries.generated.ts +0 -59
  92. package/bundle/src/src/application/request-log/request-log.entity.json +0 -75
  93. package/bundle/src/src/application/request-log/request-log.model.ts +0 -155
  94. package/bundle/src/src/application/request-log/request-log.types.ts +0 -15
  95. package/bundle/src/src/application/sonamu.generated.http +0 -187
  96. package/bundle/src/src/application/sonamu.generated.sso.ts +0 -66
  97. package/bundle/src/src/application/sonamu.generated.ts +0 -135
  98. package/bundle/src/src/application/token/token.entity.json +0 -37
  99. package/bundle/src/src/application/token/token.model.ts +0 -160
  100. package/bundle/src/src/application/token/token.types.ts +0 -26
  101. package/bundle/src/src/i18n/en.ts +0 -59
  102. package/bundle/src/src/i18n/ko.ts +0 -59
  103. package/bundle/src/src/i18n/sd.generated.ts +0 -384
  104. package/bundle/src/src/index.ts +0 -6
  105. package/bundle/src/src/migrations/20260410171405_create__request_logs.ts +0 -23
  106. package/bundle/src/src/migrations/20260410171406_create__tokens.ts +0 -21
  107. package/bundle/src/src/migrations/20260411120624_alter_tokens_alter2.ts +0 -15
  108. package/bundle/src/src/sonamu.config.ts +0 -248
  109. package/bundle/src/src/testing/fixture.ts +0 -6
  110. package/bundle/src/src/testing/global.ts +0 -6
  111. package/bundle/src/src/testing/setup-mocks.ts +0 -44
  112. package/bundle/src/src/typings/fastify.d.ts +0 -8
  113. package/bundle/src/src/typings/sonamu.d.ts +0 -17
  114. package/bundle/src/src/utils/subset-loaders.ts +0 -11
  115. package/bundle/web-dist/client/assets/index-DlPchHBY.js +0 -116
  116. package/bundle/web-dist/client/assets/tokens-DRkXtZ3Q.js +0 -1
  117. package/bundle/web-dist/web-dist/client/assets/index-vZsvyuFn.css +0 -1
  118. package/bundle/web-dist/web-dist/client/assets/rolldown-runtime-Dw2cE7zH.js +0 -1
  119. package/bundle/web-dist/web-dist/client/assets/routes-CagDz23B.js +0 -1
  120. package/bundle/web-dist/web-dist/client/assets/sd.generated-BrQoQXvv.js +0 -47
  121. package/bundle/web-dist/web-dist/client/assets/services.generated-BspO2L0j.js +0 -1
  122. package/bundle/web-dist/web-dist/client/assets/show-aXUGa0gm.js +0 -29
  123. package/bundle/web-dist/web-dist/client/assets/tokens-DRkXtZ3Q.js +0 -1
  124. package/bundle/web-dist/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
  125. package/bundle/web-dist/web-dist/client/assets/vendor-tanstack-CUxlo6YN.js +0 -1
  126. package/bundle/web-dist/web-dist/client/index.html +0 -18
  127. package/bundle/web-dist/web-dist/server/assets/react-dom-CGIzOSuj.js +0 -335
  128. package/bundle/web-dist/web-dist/server/assets/routes-ClzReRep.js +0 -490
  129. package/bundle/web-dist/web-dist/server/assets/sd.generated-BnonqqKr.js +0 -21694
  130. package/bundle/web-dist/web-dist/server/assets/services.generated-D5ABD5fr.js +0 -836
  131. package/bundle/web-dist/web-dist/server/assets/show-C9pcdSxc.js +0 -23364
  132. package/bundle/web-dist/web-dist/server/assets/tokens-JH6FsnWZ.js +0 -860
  133. package/bundle/web-dist/web-dist/server/entry-server.generated.js +0 -44646
@@ -1,140 +0,0 @@
1
- import "../../_virtual/_rolldown/runtime.js";
2
- import { createHash, randomBytes } from "node:crypto";
3
- //#region src/application/qgrid/oauth.ts
4
- /**
5
- * OAuth 유틸 — Claude Code 소스의 OAuth 플로우 그대로 재현
6
- */
7
- const CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
8
- const AUTHORIZE_URL = "https://claude.com/cai/oauth/authorize";
9
- const TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
10
- const ALL_SCOPES = [
11
- "org:create_api_key",
12
- "user:profile",
13
- "user:inference",
14
- "user:sessions:claude_code",
15
- "user:mcp_servers",
16
- "user:file_upload"
17
- ];
18
- const REFRESH_SCOPES = [
19
- "user:profile",
20
- "user:inference",
21
- "user:sessions:claude_code",
22
- "user:mcp_servers",
23
- "user:file_upload"
24
- ];
25
- function base64URLEncode(buffer) {
26
- return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
27
- }
28
- function generatePKCE() {
29
- const codeVerifier = base64URLEncode(randomBytes(32));
30
- return {
31
- codeVerifier,
32
- codeChallenge: base64URLEncode(createHash("sha256").update(codeVerifier).digest()),
33
- state: base64URLEncode(randomBytes(32))
34
- };
35
- }
36
- function buildAuthUrl(codeChallenge, state, redirectUri) {
37
- const url = new URL(AUTHORIZE_URL);
38
- url.searchParams.append("code", "true");
39
- url.searchParams.append("client_id", CLIENT_ID);
40
- url.searchParams.append("response_type", "code");
41
- url.searchParams.append("redirect_uri", redirectUri);
42
- url.searchParams.append("scope", ALL_SCOPES.join(" "));
43
- url.searchParams.append("code_challenge", codeChallenge);
44
- url.searchParams.append("code_challenge_method", "S256");
45
- url.searchParams.append("state", state);
46
- return url.toString();
47
- }
48
- async function exchangeCodeForTokens(code, codeVerifier, state, redirectUri) {
49
- const res = await fetch(TOKEN_URL, {
50
- method: "POST",
51
- headers: { "Content-Type": "application/json" },
52
- body: JSON.stringify({
53
- grant_type: "authorization_code",
54
- code,
55
- redirect_uri: redirectUri,
56
- client_id: CLIENT_ID,
57
- code_verifier: codeVerifier,
58
- state
59
- })
60
- });
61
- if (!res.ok) {
62
- const text = await res.text();
63
- throw new Error(`Token exchange failed (${res.status}): ${text}`);
64
- }
65
- const data = await res.json();
66
- return {
67
- accessToken: data.access_token,
68
- refreshToken: data.refresh_token,
69
- expiresAt: Date.now() + data.expires_in * 1e3,
70
- scope: data.scope,
71
- accountUuid: data.account?.uuid,
72
- emailAddress: data.account?.email_address
73
- };
74
- }
75
- async function refreshAccessToken(refreshToken) {
76
- const res = await fetch(TOKEN_URL, {
77
- method: "POST",
78
- headers: { "Content-Type": "application/json" },
79
- body: JSON.stringify({
80
- grant_type: "refresh_token",
81
- refresh_token: refreshToken,
82
- client_id: CLIENT_ID,
83
- scope: REFRESH_SCOPES.join(" ")
84
- })
85
- });
86
- if (!res.ok) {
87
- const text = await res.text();
88
- throw new Error(`Token refresh failed (${res.status}): ${text}`);
89
- }
90
- const data = await res.json();
91
- return {
92
- accessToken: data.access_token,
93
- refreshToken: data.refresh_token ?? refreshToken,
94
- expiresAt: Date.now() + data.expires_in * 1e3,
95
- scope: data.scope
96
- };
97
- }
98
- const usageCache = {};
99
- const USAGE_API_CACHE_TTL = 6e4;
100
- async function fetchUsage(accessToken) {
101
- const cacheKey = accessToken.slice(-10);
102
- const cached = usageCache[cacheKey];
103
- if (cached && Date.now() - cached.cachedAt < USAGE_API_CACHE_TTL) {
104
- console.log(`[usage] cache hit: ${cacheKey}`);
105
- return cached.data;
106
- }
107
- const res = await fetch("https://api.anthropic.com/api/oauth/usage", {
108
- headers: {
109
- Authorization: `Bearer ${accessToken}`,
110
- "Content-Type": "application/json",
111
- "anthropic-beta": "oauth-2025-04-20"
112
- },
113
- signal: AbortSignal.timeout(5e3)
114
- });
115
- if (!res.ok) {
116
- const text = await res.text();
117
- let errorMessage = `Error ${res.status}`;
118
- try {
119
- errorMessage = JSON.parse(text).error?.message ?? errorMessage;
120
- } catch {}
121
- console.warn(`[usage] ${res.status}: ${errorMessage}`);
122
- if (cached?.data && !cached.data.error) return cached.data;
123
- const errorResult = { error: errorMessage };
124
- usageCache[cacheKey] = {
125
- data: errorResult,
126
- cachedAt: Date.now()
127
- };
128
- return errorResult;
129
- }
130
- const data = await res.json();
131
- usageCache[cacheKey] = {
132
- data,
133
- cachedAt: Date.now()
134
- };
135
- return data;
136
- }
137
- //#endregion
138
- export { buildAuthUrl, exchangeCodeForTokens, fetchUsage, generatePKCE, refreshAccessToken };
139
-
140
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2F1dGguanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcGxpY2F0aW9uL3FncmlkL29hdXRoLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT0F1dGgg7Jyg7Yu4IOKAlCBDbGF1ZGUgQ29kZSDshozsiqTsnZggT0F1dGgg7ZSM66Gc7JqwIOq3uOuMgOuhnCDsnqztmIRcbiAqL1xuaW1wb3J0IHsgY3JlYXRlSGFzaCwgcmFuZG9tQnl0ZXMgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcblxuaW1wb3J0IHR5cGUgeyBVc2FnZVJlc3BvbnNlIH0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcblxuY29uc3QgQ0xJRU5UX0lEID0gXCI5ZDFjMjUwYS1lNjFiLTQ0ZDktODhlZC01OTQ0ZDE5NjJmNWVcIjtcbmNvbnN0IEFVVEhPUklaRV9VUkwgPSBcImh0dHBzOi8vY2xhdWRlLmNvbS9jYWkvb2F1dGgvYXV0aG9yaXplXCI7XG5jb25zdCBUT0tFTl9VUkwgPSBcImh0dHBzOi8vcGxhdGZvcm0uY2xhdWRlLmNvbS92MS9vYXV0aC90b2tlblwiO1xuXG4vLyBsb2dpbiDsi5wg7IKs7JqpIChhdXRob3JpemUgVVJMKVxuY29uc3QgQUxMX1NDT1BFUyA9IFtcbiAgXCJvcmc6Y3JlYXRlX2FwaV9rZXlcIixcbiAgXCJ1c2VyOnByb2ZpbGVcIixcbiAgXCJ1c2VyOmluZmVyZW5jZVwiLFxuICBcInVzZXI6c2Vzc2lvbnM6Y2xhdWRlX2NvZGVcIixcbiAgXCJ1c2VyOm1jcF9zZXJ2ZXJzXCIsXG4gIFwidXNlcjpmaWxlX3VwbG9hZFwiLFxuXTtcblxuLy8gcmVmcmVzaCDsi5wg7IKs7JqpIChvcmc6Y3JlYXRlX2FwaV9rZXkg7KCc7Jm4KVxuY29uc3QgUkVGUkVTSF9TQ09QRVMgPSBbXG4gIFwidXNlcjpwcm9maWxlXCIsXG4gIFwidXNlcjppbmZlcmVuY2VcIixcbiAgXCJ1c2VyOnNlc3Npb25zOmNsYXVkZV9jb2RlXCIsXG4gIFwidXNlcjptY3Bfc2VydmVyc1wiLFxuICBcInVzZXI6ZmlsZV91cGxvYWRcIixcbl07XG5cbmZ1bmN0aW9uIGJhc2U2NFVSTEVuY29kZShidWZmZXI6IEJ1ZmZlcik6IHN0cmluZyB7XG4gIHJldHVybiBidWZmZXIudG9TdHJpbmcoXCJiYXNlNjRcIikucmVwbGFjZSgvXFwrL2csIFwiLVwiKS5yZXBsYWNlKC9cXC8vZywgXCJfXCIpLnJlcGxhY2UoLz0vZywgXCJcIik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVBLQ0UoKTogeyBjb2RlVmVyaWZpZXI6IHN0cmluZzsgY29kZUNoYWxsZW5nZTogc3RyaW5nOyBzdGF0ZTogc3RyaW5nIH0ge1xuICBjb25zdCBjb2RlVmVyaWZpZXIgPSBiYXNlNjRVUkxFbmNvZGUocmFuZG9tQnl0ZXMoMzIpKTtcbiAgY29uc3QgY29kZUNoYWxsZW5nZSA9IGJhc2U2NFVSTEVuY29kZShjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShjb2RlVmVyaWZpZXIpLmRpZ2VzdCgpKTtcbiAgY29uc3Qgc3RhdGUgPSBiYXNlNjRVUkxFbmNvZGUocmFuZG9tQnl0ZXMoMzIpKTtcbiAgcmV0dXJuIHsgY29kZVZlcmlmaWVyLCBjb2RlQ2hhbGxlbmdlLCBzdGF0ZSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRBdXRoVXJsKGNvZGVDaGFsbGVuZ2U6IHN0cmluZywgc3RhdGU6IHN0cmluZywgcmVkaXJlY3RVcmk6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHVybCA9IG5ldyBVUkwoQVVUSE9SSVpFX1VSTCk7XG4gIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiY29kZVwiLCBcInRydWVcIik7XG4gIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiY2xpZW50X2lkXCIsIENMSUVOVF9JRCk7XG4gIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwicmVzcG9uc2VfdHlwZVwiLCBcImNvZGVcIik7XG4gIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwicmVkaXJlY3RfdXJpXCIsIHJlZGlyZWN0VXJpKTtcbiAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJzY29wZVwiLCBBTExfU0NPUEVTLmpvaW4oXCIgXCIpKTtcbiAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJjb2RlX2NoYWxsZW5nZVwiLCBjb2RlQ2hhbGxlbmdlKTtcbiAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJjb2RlX2NoYWxsZW5nZV9tZXRob2RcIiwgXCJTMjU2XCIpO1xuICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcInN0YXRlXCIsIHN0YXRlKTtcbiAgcmV0dXJuIHVybC50b1N0cmluZygpO1xufVxuXG5leHBvcnQgdHlwZSBPQXV0aFRva2VucyA9IHtcbiAgYWNjZXNzVG9rZW46IHN0cmluZztcbiAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gIGV4cGlyZXNBdDogbnVtYmVyO1xuICBzY29wZTogc3RyaW5nO1xuICBhY2NvdW50VXVpZD86IHN0cmluZztcbiAgZW1haWxBZGRyZXNzPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4Y2hhbmdlQ29kZUZvclRva2VucyhcbiAgY29kZTogc3RyaW5nLFxuICBjb2RlVmVyaWZpZXI6IHN0cmluZyxcbiAgc3RhdGU6IHN0cmluZyxcbiAgcmVkaXJlY3RVcmk6IHN0cmluZyxcbik6IFByb21pc2U8T0F1dGhUb2tlbnM+IHtcbiAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2goVE9LRU5fVVJMLCB7XG4gICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICBoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0sXG4gICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgZ3JhbnRfdHlwZTogXCJhdXRob3JpemF0aW9uX2NvZGVcIixcbiAgICAgIGNvZGUsXG4gICAgICByZWRpcmVjdF91cmk6IHJlZGlyZWN0VXJpLFxuICAgICAgY2xpZW50X2lkOiBDTElFTlRfSUQsXG4gICAgICBjb2RlX3ZlcmlmaWVyOiBjb2RlVmVyaWZpZXIsXG4gICAgICBzdGF0ZSxcbiAgICB9KSxcbiAgfSk7XG4gIGlmICghcmVzLm9rKSB7XG4gICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlcy50ZXh0KCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBUb2tlbiBleGNoYW5nZSBmYWlsZWQgKCR7cmVzLnN0YXR1c30pOiAke3RleHR9YCk7XG4gIH1cblxuICBjb25zdCBkYXRhID0gKGF3YWl0IHJlcy5qc29uKCkpIGFzIHtcbiAgICBhY2Nlc3NfdG9rZW46IHN0cmluZztcbiAgICByZWZyZXNoX3Rva2VuOiBzdHJpbmc7XG4gICAgZXhwaXJlc19pbjogbnVtYmVyO1xuICAgIHNjb3BlOiBzdHJpbmc7XG4gICAgYWNjb3VudD86IHsgdXVpZDogc3RyaW5nOyBlbWFpbF9hZGRyZXNzOiBzdHJpbmcgfTtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIGFjY2Vzc1Rva2VuOiBkYXRhLmFjY2Vzc190b2tlbixcbiAgICByZWZyZXNoVG9rZW46IGRhdGEucmVmcmVzaF90b2tlbixcbiAgICBleHBpcmVzQXQ6IERhdGUubm93KCkgKyBkYXRhLmV4cGlyZXNfaW4gKiAxMDAwLFxuICAgIHNjb3BlOiBkYXRhLnNjb3BlLFxuICAgIGFjY291bnRVdWlkOiBkYXRhLmFjY291bnQ/LnV1aWQsXG4gICAgZW1haWxBZGRyZXNzOiBkYXRhLmFjY291bnQ/LmVtYWlsX2FkZHJlc3MsXG4gIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWZyZXNoQWNjZXNzVG9rZW4ocmVmcmVzaFRva2VuOiBzdHJpbmcpOiBQcm9taXNlPE9BdXRoVG9rZW5zPiB7XG4gIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKFRPS0VOX1VSTCwge1xuICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgaGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIGdyYW50X3R5cGU6IFwicmVmcmVzaF90b2tlblwiLFxuICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuLFxuICAgICAgY2xpZW50X2lkOiBDTElFTlRfSUQsXG4gICAgICBzY29wZTogUkVGUkVTSF9TQ09QRVMuam9pbihcIiBcIiksXG4gICAgfSksXG4gIH0pO1xuICBpZiAoIXJlcy5vaykge1xuICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4gcmVmcmVzaCBmYWlsZWQgKCR7cmVzLnN0YXR1c30pOiAke3RleHR9YCk7XG4gIH1cbiAgY29uc3QgZGF0YSA9IChhd2FpdCByZXMuanNvbigpKSBhcyB7XG4gICAgYWNjZXNzX3Rva2VuOiBzdHJpbmc7XG4gICAgcmVmcmVzaF90b2tlbjogc3RyaW5nO1xuICAgIGV4cGlyZXNfaW46IG51bWJlcjtcbiAgICBzY29wZTogc3RyaW5nO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgYWNjZXNzVG9rZW46IGRhdGEuYWNjZXNzX3Rva2VuLFxuICAgIHJlZnJlc2hUb2tlbjogZGF0YS5yZWZyZXNoX3Rva2VuID8/IHJlZnJlc2hUb2tlbixcbiAgICBleHBpcmVzQXQ6IERhdGUubm93KCkgKyBkYXRhLmV4cGlyZXNfaW4gKiAxMDAwLFxuICAgIHNjb3BlOiBkYXRhLnNjb3BlLFxuICB9O1xufVxuXG5jb25zdCB1c2FnZUNhY2hlOiBSZWNvcmQ8c3RyaW5nLCB7IGRhdGE6IFVzYWdlUmVzcG9uc2U7IGNhY2hlZEF0OiBudW1iZXIgfT4gPSB7fTtcbmNvbnN0IFVTQUdFX0FQSV9DQUNIRV9UVEwgPSA2MF8wMDA7IC8vIDHrtoRcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoVXNhZ2UoYWNjZXNzVG9rZW46IHN0cmluZyk6IFByb21pc2U8VXNhZ2VSZXNwb25zZT4ge1xuICBjb25zdCBjYWNoZUtleSA9IGFjY2Vzc1Rva2VuLnNsaWNlKC0xMCk7XG4gIGNvbnN0IGNhY2hlZCA9IHVzYWdlQ2FjaGVbY2FjaGVLZXldO1xuICBpZiAoY2FjaGVkICYmIERhdGUubm93KCkgLSBjYWNoZWQuY2FjaGVkQXQgPCBVU0FHRV9BUElfQ0FDSEVfVFRMKSB7XG4gICAgY29uc29sZS5sb2coYFt1c2FnZV0gY2FjaGUgaGl0OiAke2NhY2hlS2V5fWApO1xuICAgIHJldHVybiBjYWNoZWQuZGF0YTtcbiAgfVxuXG4gIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKFwiaHR0cHM6Ly9hcGkuYW50aHJvcGljLmNvbS9hcGkvb2F1dGgvdXNhZ2VcIiwge1xuICAgIGhlYWRlcnM6IHtcbiAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHthY2Nlc3NUb2tlbn1gLFxuICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICBcImFudGhyb3BpYy1iZXRhXCI6IFwib2F1dGgtMjAyNS0wNC0yMFwiLFxuICAgIH0sXG4gICAgc2lnbmFsOiBBYm9ydFNpZ25hbC50aW1lb3V0KDUwMDApLFxuICB9KTtcbiAgaWYgKCFyZXMub2spIHtcbiAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzLnRleHQoKTtcblxuICAgIC8vIO2MjOyLsSDsi5zrj4TtlbTshJwg7JeQ65+sIOuplOyLnOyngCDstpTstpxcbiAgICBsZXQgZXJyb3JNZXNzYWdlID0gYEVycm9yICR7cmVzLnN0YXR1c31gO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHRleHQpO1xuICAgICAgZXJyb3JNZXNzYWdlID0gcGFyc2VkLmVycm9yPy5tZXNzYWdlID8/IGVycm9yTWVzc2FnZTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIO2MjOyLsSDslYgg65CY66m0IOq4sOuzuCDrqZTsi5zsp4BcbiAgICB9XG5cbiAgICBjb25zb2xlLndhcm4oYFt1c2FnZV0gJHtyZXMuc3RhdHVzfTogJHtlcnJvck1lc3NhZ2V9YCk7XG5cbiAgICAvLyDsnbTsoIQg7ISx6rO1IOy6kOyLnCDsnojsnLzrqbQg7Jyg7KeAXG4gICAgaWYgKGNhY2hlZD8uZGF0YSAmJiAhY2FjaGVkLmRhdGEuZXJyb3IpIHJldHVybiBjYWNoZWQuZGF0YTtcblxuICAgIC8vIOyLpO2MqOuPhCDsupDsi5wgKOuwmOuztSDtmLjstpwg67Cp7KeAKVxuICAgIGNvbnN0IGVycm9yUmVzdWx0ID0geyBlcnJvcjogZXJyb3JNZXNzYWdlIH07XG4gICAgdXNhZ2VDYWNoZVtjYWNoZUtleV0gPSB7IGRhdGE6IGVycm9yUmVzdWx0LCBjYWNoZWRBdDogRGF0ZS5ub3coKSB9O1xuICAgIHJldHVybiBlcnJvclJlc3VsdDtcbiAgfVxuXG4gIGNvbnN0IGRhdGEgPSAoYXdhaXQgcmVzLmpzb24oKSkgYXMgVXNhZ2VSZXNwb25zZTtcbiAgLy8gY2FjaGUgaW52YWxpZGF0ZVxuICB1c2FnZUNhY2hlW2NhY2hlS2V5XSA9IHsgZGF0YSwgY2FjaGVkQXQ6IERhdGUubm93KCkgfTtcbiAgcmV0dXJuIGRhdGE7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQU9BLE1BQU0sWUFBWTtBQUNsQixNQUFNLGdCQUFnQjtBQUN0QixNQUFNLFlBQVk7QUFHbEIsTUFBTSxhQUFhO0NBQ2pCO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNEO0FBR0QsTUFBTSxpQkFBaUI7Q0FDckI7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNEO0FBRUQsU0FBUyxnQkFBZ0IsUUFBd0I7QUFDL0MsUUFBTyxPQUFPLFNBQVMsU0FBUyxDQUFDLFFBQVEsT0FBTyxJQUFJLENBQUMsUUFBUSxPQUFPLElBQUksQ0FBQyxRQUFRLE1BQU0sR0FBRzs7QUFHNUYsU0FBZ0IsZUFBK0U7Q0FDN0YsTUFBTSxlQUFlLGdCQUFnQixZQUFZLEdBQUcsQ0FBQztBQUdyRCxRQUFPO0VBQUU7RUFBYyxlQUZELGdCQUFnQixXQUFXLFNBQVMsQ0FBQyxPQUFPLGFBQWEsQ0FBQyxRQUFRLENBQUM7RUFFbkQsT0FEeEIsZ0JBQWdCLFlBQVksR0FBRyxDQUFDO0VBQ0Q7O0FBRy9DLFNBQWdCLGFBQWEsZUFB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
@@ -1,100 +0,0 @@
1
- import "../../_virtual/_rolldown/runtime.js";
2
- import { QuotaError } from "./qgrid.types.js";
3
- import { Worker } from "./worker.js";
4
- //#region src/application/qgrid/pool.ts
5
- var ClaudePool = class {
6
- workers = /* @__PURE__ */ new Map();
7
- quotaExhausted = /* @__PURE__ */ new Set();
8
- requestCounts = /* @__PURE__ */ new Map();
9
- lastUsedToken = "";
10
- size;
11
- model;
12
- timeout;
13
- cwd;
14
- maxCalls;
15
- constructor(config) {
16
- this.size = config.size ?? 3;
17
- this.model = config.model ?? "sonnet";
18
- this.timeout = config.timeout ?? 3e5;
19
- this.cwd = config.cwd ?? "/tmp/qgrid";
20
- this.maxCalls = config.maxCalls ?? 500;
21
- config.tokens.forEach((token) => {
22
- this.createWorkers(token);
23
- });
24
- }
25
- getStats(tokenNames) {
26
- return [...this.workers.keys()].map((token) => ({
27
- token,
28
- name: tokenNames?.get(token) ?? "Unknown Key",
29
- requests: this.requestCounts.get(token) ?? 0,
30
- active: !this.quotaExhausted.has(token)
31
- }));
32
- }
33
- selectWorker() {
34
- const candidates = [...this.workers.entries()].filter(([token]) => !this.quotaExhausted.has(token)).flatMap(([, workers]) => workers);
35
- if (candidates.length === 0) return null;
36
- return candidates.reduce((best, w) => w.getQueueDepth() < best.getQueueDepth() ? w : best);
37
- }
38
- async query(input, timeoutMs) {
39
- const triedTokens = /* @__PURE__ */ new Set();
40
- while (true) {
41
- const worker = this.selectWorker();
42
- if (!worker) throw new QuotaError("All tokens exhausted");
43
- if (triedTokens.has(worker.tokenId)) throw new QuotaError("All tokens exhausted");
44
- try {
45
- const result = await worker.query(input, timeoutMs);
46
- this.lastUsedToken = worker.tokenId;
47
- this.requestCounts.set(worker.tokenId, (this.requestCounts.get(worker.tokenId) ?? 0) + 1);
48
- return result;
49
- } catch (err) {
50
- if (err instanceof QuotaError) {
51
- this.quotaExhausted.add(worker.tokenId);
52
- triedTokens.add(worker.tokenId);
53
- continue;
54
- }
55
- throw err;
56
- }
57
- }
58
- }
59
- kill() {
60
- [...this.workers.values()].flat().forEach((w) => {
61
- w.kill();
62
- });
63
- }
64
- createWorkers(token) {
65
- if (this.workers.has(token)) return;
66
- const workerConfig = {
67
- token,
68
- model: this.model,
69
- timeout: this.timeout,
70
- cwd: this.cwd,
71
- maxCalls: this.maxCalls
72
- };
73
- const workers = Array.from({ length: this.size }, () => new Worker(workerConfig));
74
- this.workers.set(token, workers);
75
- this.requestCounts.set(token, 0);
76
- }
77
- destroyWorkers(token) {
78
- const workers = this.workers.get(token);
79
- if (!workers) return;
80
- workers.forEach((w) => {
81
- w.kill();
82
- });
83
- this.workers.delete(token);
84
- this.quotaExhausted.delete(token);
85
- this.requestCounts.delete(token);
86
- }
87
- };
88
- let pool = null;
89
- function initPool(tokens) {
90
- pool = new ClaudePool({ tokens });
91
- return pool;
92
- }
93
- function getPool() {
94
- if (!pool) throw new Error("Pool not initialized. Call initPool() first.");
95
- return pool;
96
- }
97
- //#endregion
98
- export { ClaudePool, getPool, initPool };
99
-
100
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9vbC5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcG9vbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENsYXVkZVBvb2wg4oCUIOupgO2LsCDthqDtgbAg7ZSE66Gc7IS47IqkIO2SgC5cbiAqXG4gKiAyLWxheWVyIOyVhO2CpO2FjeyymDogQ2xhdWRlUG9vbCDihpIgV29ya2VyIChmbGF0KVxuICogLSBNYXA8dG9rZW4sIFdvcmtlcltdPuuhnCDthqDtgbDrs4Qg7JuM7LukIOq0gOumrCAo7JuQ67O4IO2GoO2BsOydtCDtgqQpXG4gKiAtIGxlYXN0LXF1ZXVlLWRlcHRoIOudvOyasO2MhVxuICogLSDtiKzrqoXtlZwg7L+87YSwIGZhaWxvdmVyIChRdW90YUVycm9yIOyLnCDri6Trpbgg7Yag7YGw7Jy866GcIOyekOuPmSDsnqzsi5zrj4QpXG4gKiAtIOybjOy7pCDqtIDrpqzrp4wg64u064u5IChEQiDsnZjsobQg7JeG7J2MKVxuICovXG5pbXBvcnQgdHlwZSB7IENsaVJlc3VsdCwgUG9vbENvbmZpZywgUXVlcnlJbnB1dCwgVG9rZW5TdGF0cyB9IGZyb20gXCIuL3FncmlkLnR5cGVzXCI7XG5pbXBvcnQgeyBRdW90YUVycm9yIH0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcbmltcG9ydCB7IFdvcmtlciwgdHlwZSBXb3JrZXJDb25maWcgfSBmcm9tIFwiLi93b3JrZXJcIjtcblxuZXhwb3J0IGNsYXNzIENsYXVkZVBvb2wge1xuICB3b3JrZXJzID0gbmV3IE1hcDxzdHJpbmcsIFdvcmtlcltdPigpO1xuICBxdW90YUV4aGF1c3RlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICByZXF1ZXN0Q291bnRzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgbGFzdFVzZWRUb2tlbiA9IFwiXCI7XG4gIHNpemU6IG51bWJlcjtcbiAgbW9kZWw6IHN0cmluZztcbiAgdGltZW91dDogbnVtYmVyO1xuICBjd2Q6IHN0cmluZztcbiAgbWF4Q2FsbHM6IG51bWJlcjtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFBvb2xDb25maWcpIHtcbiAgICB0aGlzLnNpemUgPSBjb25maWcuc2l6ZSA/PyAzO1xuICAgIHRoaXMubW9kZWwgPSBjb25maWcubW9kZWwgPz8gXCJzb25uZXRcIjtcbiAgICB0aGlzLnRpbWVvdXQgPSBjb25maWcudGltZW91dCA/PyAzMDBfMDAwO1xuICAgIHRoaXMuY3dkID0gY29uZmlnLmN3ZCA/PyBcIi90bXAvcWdyaWRcIjtcbiAgICB0aGlzLm1heENhbGxzID0gY29uZmlnLm1heENhbGxzID8/IDUwMDtcblxuICAgIGNvbmZpZy50b2tlbnMuZm9yRWFjaCgodG9rZW4pID0+IHtcbiAgICAgIHRoaXMuY3JlYXRlV29ya2Vycyh0b2tlbik7XG4gICAgfSk7XG4gIH1cblxuICBnZXRTdGF0cyh0b2tlbk5hbWVzPzogTWFwPHN0cmluZywgc3RyaW5nPik6IFRva2VuU3RhdHNbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlcnMua2V5cygpXS5tYXAoKHRva2VuKSA9PiAoe1xuICAgICAgdG9rZW4sXG4gICAgICBuYW1lOiB0b2tlbk5hbWVzPy5nZXQodG9rZW4pID8/IFwiVW5rbm93biBLZXlcIixcbiAgICAgIHJlcXVlc3RzOiB0aGlzLnJlcXVlc3RDb3VudHMuZ2V0KHRva2VuKSA/PyAwLFxuICAgICAgYWN0aXZlOiAhdGhpcy5xdW90YUV4aGF1c3RlZC5oYXModG9rZW4pLFxuICAgIH0pKTtcbiAgfVxuXG4gIHNlbGVjdFdvcmtlcigpOiBXb3JrZXIgfCBudWxsIHtcbiAgICBjb25zdCBjYW5kaWRhdGVzID0gWy4uLnRoaXMud29ya2Vycy5lbnRyaWVzKCldXG4gICAgICAuZmlsdGVyKChbdG9rZW5dKSA9PiAhdGhpcy5xdW90YUV4aGF1c3RlZC5oYXModG9rZW4pKVxuICAgICAgLmZsYXRNYXAoKFssIHdvcmtlcnNdKSA9PiB3b3JrZXJzKTtcblxuICAgIGlmIChjYW5kaWRhdGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG5cbiAgICByZXR1cm4gY2FuZGlkYXRlcy5yZWR1Y2UoKGJlc3QsIHcpID0+ICh3LmdldFF1ZXVlRGVwdGgoKSA8IGJlc3QuZ2V0UXVldWVEZXB0aCgpID8gdyA6IGJlc3QpKTtcbiAgfVxuXG4gIGFzeW5jIHF1ZXJ5KGlucHV0OiBRdWVyeUlucHV0LCB0aW1lb3V0TXM/OiBudW1iZXIpOiBQcm9taXNlPENsaVJlc3VsdD4ge1xuICAgIGNvbnN0IHRyaWVkVG9rZW5zID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3Qgd29ya2VyID0gdGhpcy5zZWxlY3RXb3JrZXIoKTtcbiAgICAgIGlmICghd29ya2VyKSB7XG4gICAgICAgIHRocm93IG5ldyBRdW90YUVycm9yKFwiQWxsIHRva2VucyBleGhhdXN0ZWRcIik7XG4gICAgICB9XG5cbiAgICAgIGlmICh0cmllZFRva2Vucy5oYXMod29ya2VyLnRva2VuSWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBRdW90YUVycm9yKFwiQWxsIHRva2VucyBleGhhdXN0ZWRcIik7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmtlci5xdWVyeShpbnB1dCwgdGltZW91dE1zKTtcbiAgICAgICAgdGhpcy5sYXN0VXNlZFRva2VuID0gd29ya2VyLnRva2VuSWQ7XG4gICAgICAgIHRoaXMucmVxdWVzdENvdW50cy5zZXQod29ya2VyLnRva2VuSWQsICh0aGlzLnJlcXVlc3RDb3VudHMuZ2V0KHdvcmtlci50b2tlbklkKSA/PyAwKSArIDEpO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIFF1b3RhRXJyb3IpIHtcbiAgICAgICAgICB0aGlzLnF1b3RhRXhoYXVzdGVkLmFkZCh3b3JrZXIudG9rZW5JZCk7XG4gICAgICAgICAgdHJpZWRUb2tlbnMuYWRkKHdvcmtlci50b2tlbklkKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAga2lsbCgpOiB2b2lkIHtcbiAgICBbLi4udGhpcy53b3JrZXJzLnZhbHVlcygpXS5mbGF0KCkuZm9yRWFjaCgodykgPT4ge1xuICAgICAgdy5raWxsKCk7XG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVXb3JrZXJzKHRva2VuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodGhpcy53b3JrZXJzLmhhcyh0b2tlbikpIHJldHVybjtcblxuICAgIGNvbnN0IHdvcmtlckNvbmZpZzogV29ya2VyQ29uZmlnID0ge1xuICAgICAgdG9rZW4sXG4gICAgICBtb2RlbDogdGhpcy5tb2RlbCxcbiAgICAgIHRpbWVvdXQ6IHRoaXMudGltZW91dCxcbiAgICAgIGN3ZDogdGhpcy5jd2QsXG4gICAgICBtYXhDYWxsczogdGhpcy5tYXhDYWxscyxcbiAgICB9O1xuXG4gICAgY29uc3Qgd29ya2VycyA9IEFycmF5LmZyb20oeyBsZW5ndGg6IHRoaXMuc2l6ZSB9LCAoKSA9PiBuZXcgV29ya2VyKHdvcmtlckNvbmZpZykpO1xuICAgIHRoaXMud29ya2Vycy5zZXQodG9rZW4sIHdvcmtlcnMpO1xuICAgIHRoaXMucmVxdWVzdENvdW50cy5zZXQodG9rZW4sIDApO1xuICB9XG5cbiAgZGVzdHJveVdvcmtlcnModG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlcnMuZ2V0KHRva2VuKTtcbiAgICBpZiAoIXdvcmtlcnMpIHJldHVybjtcblxuICAgIHdvcmtlcnMuZm9yRWFjaCgodykgPT4ge1xuICAgICAgdy5raWxsKCk7XG4gICAgfSk7XG4gICAgdGhpcy53b3JrZXJzLmRlbGV0ZSh0b2tlbik7XG4gICAgdGhpcy5xdW90YUV4aGF1c3RlZC5kZWxldGUodG9rZW4pO1xuICAgIHRoaXMucmVxdWVzdENvdW50cy5kZWxldGUodG9rZW4pO1xuICB9XG59XG5cbi8vIFBvb2wg7Iux6riA7YS0IOq0gOumrFxubGV0IHBvb2w6IENsYXVkZVBvb2wgfCBudWxsID0gbnVsbDtcblxuZXhwb3J0IGZ1bmN0aW9uIGluaXRQb29sKHRva2Vuczogc3RyaW5nW10pOiBDbGF1ZGVQb29sIHtcbiAgcG9vbCA9IG5ldyBDbGF1ZGVQb29sKHsgdG9rZW5zIH0pO1xuICByZXR1cm4gcG9vbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFBvb2woKTogQ2xhdWRlUG9vbCB7XG4gIGlmICghcG9vbCkgdGhyb3cgbmV3IEVycm9yKFwiUG9vbCBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdFBvb2woKSBmaXJzdC5cIik7XG4gIHJldHVybiBwb29sO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7O0FBYUEsSUFBYSxhQUFiLE1BQXdCO0NBQ3RCLDBCQUFVLElBQUksS0FBdUI7Q0FDckMsaUNBQWlCLElBQUksS0FBYTtDQUNsQyxnQ0FBZ0IsSUFBSSxLQUFxQjtDQUN6QyxnQkFBZ0I7Q0FDaEI7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUVBLFlBQVksUUFBb0I7QUFDOUIsT0FBSyxPQUFPLE9BQU8sUUFBUTtBQUMzQixPQUFLLFFBQVEsT0FBTyxTQUFTO0FBQzdCLE9BQUssVUFBVSxPQUFPLFdBQVc7QUFDakMsT0FBSyxNQUFNLE9BQU8sT0FBTztBQUN6QixPQUFLLFdBQVcsT0FBTyxZQUFZO0FBRW5DLFNBQU8sT0FBTyxTQUFTLFVBQVU7QUFDL0IsUUFBSyxjQUFjLE1BQU07SUFDekI7O0NBR0osU0FBUyxZQUFnRDtBQUN2RCxTQUFPLENBQUMsR0FBRyxLQUFLLFFBQVEsTUFBTSxDQUFDLENBQUMsS0FBSyxXQUFXO0dBQzlDO0dBQ0EsTUFBTSxZQUFZLElBQUksTUFBTSxJQUFJO0dBQ2hDLFVBQVUsS0FBSyxjQUFjLElBQUksTUFBTSxJQUFJO0dBQzNDLFFBQVEsQ0FBQyxLQUFLLGVBQWUsSUFBSSxNQUFNO0dBQ3hDLEVBQUU7O0NBR0wsZUFBOEI7RUFDNUIsTUFBTSxhQUFhLENBQUMsR0FBRyxLQUFLLFFBQVEsU0FBUyxDQUFDLENBQzNDLFFBQVEsQ0FBQyxXQUFXLENBQUMsS0FBSyxlQUFlLElBQUksTUFBTSxDQUFDLENBQ3BELFNBQVMsR0FBRyxhQUFhLFFBQVE7QUFFcEMsTUFBSSxXQUFXLFdBQVcsRUFBRyxRQUFPO0FBRXBDLFNBQU8sV0FBVyxRQUFRLE1BQU0sTUFBTyxFQUFFLGVBQWUsR0FBRyxLQUFLLGVBQWUsR0FBRyxJQUFJLEtBQU07O0NBRzlGLE1BQU0sTUFBTSxPQUFtQixXQUF3QztFQUNyRSxNQUFNLDhCQUFjLElBQUksS0FBYTtBQUVyQyxTQUFPLE1BQU07R0FDWCxNQUFNLFNBQVMsS0FBSyxjQUFjO0FBQ2xDLE9BQUksQ0FBQyxPQUNILE9BQU0sSUFBSSxXQUFXLHVCQUF1QjtBQUc5QyxPQUFJLFlBQVksSUFBSSxPQUFPLFFBQVEsQ0FDakMsT0FBTSxJQUFJLFdBQVcsdUJBQXVCO0FBRzlDLE9BQUk7SUFDRixNQUFNLFNBQVMsTUFBTSxPQUFPLE1BQU0sT0FBTyxVQUFVO0FBQ25ELFNBQUssZ0JBQWdCLE9BQU87QUFDNUIsU0FBSyxjQUFjLElBQUksT0FBTyxVQUFVLEtBQUssY0FBYyxJQUFJLE9BQU8sUUFBUSxJQUFJLEtBQUssRUFBRTtBQUV6RixXQUFPO1lBQ0EsS0FBSztBQUNaLFFBQUksZUFBZSxZQUFZO0FBQzdCLFVBQUssZUFBZSxJQUFJLE9BQU8sUUFBUTtBQUN2QyxpQkFBWSxJQUFJLE9BQU8sUUFBUTtBQUMvQjs7QUFFRixVQUFNOzs7O0NBS1osT0FBYTtBQUNYLEdBQUMsR0FBRyxLQUFLLFFBQVEsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsTUFBTTtBQUMvQyxLQUFFLE1BQU07SUFDUjs7Q0FHSixjQUFjLE9BQXFCO0FBQ2pDLE1BQUksS0FBSyxRQUFRLElBQUksTUFBTSxDQUFFO0VBRTdCLE1BQU0sZUFBNkI7R0FDakM7R0FDQSxPQUFPLEtBQUs7R0FDWixTQUFTLEtBQUs7R0FDZCxLQUFLLEtBQUs7R0FDVixVQUFVLEtBQUs7R0FDaEI7RUFFRCxNQUFNLFVBQVUsTUFBTSxLQUFLLEVBQUUsUUFBUSxLQUFLLE1BQU0sUUFBUSxJQUFJLE9BQU8sYUFBYSxDQUFDO0FBQ2pGLE9BQUssUUFBUSxJQUFJLE9BQU8sUUFBUTtBQUNoQyxPQUFLLGNBQWMsSUFBSSxPQUFPLEVBQUU7O0NBR2xDLGVBQWUsT0FBcUI7RUFDbEMsTUFBTSxVQUFVLEtBQUssUUFBUSxJQUFJLE1BQU07QUFDdkMsTUFBSSxDQUFDLFFBQVM7QUFFZCxVQUFRLFNBQVMsTUFBTTtBQUNyQixLQUFFLE1BQU07SUFDUjtBQUNGLE9BQUssUUFBUSxPQUFPLE1BQU07QUFDMUIsT0FBSyxlQUFlLE9BQU8sTUFBTTtBQUNqQyxPQUFLLGNBQWMsT0FBTyxNQUFNOzs7QUFLcEMsSUFBSSxPQUEwQjtBQUU5QixTQUFnQixTQUFTLFFBQThCO0FBQ3JELFFBQU8sSUFBSSxXQUFXLEVBQUUsUUFBUSxDQUFDO0FBQ2pDLFFBQU87O0FBR1QsU0FBZ0IsVUFBc0I7QUFDcEMsS0FBSSxDQUFDLEtBQU0sT0FBTSxJQUFJLE1BQU0sK0NBQStDO0FBQzFFLFFBQU8ifQ==
@@ -1,280 +0,0 @@
1
- import "../../_virtual/_rolldown/runtime.js";
2
- import { buildAuthUrl, exchangeCodeForTokens, fetchUsage, generatePKCE, refreshAccessToken } from "./oauth.js";
3
- import { getPool } from "./pool.js";
4
- import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js";
5
- import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js";
6
- import { RequestLogModel } from "../request-log/request-log.model.js";
7
- import { TokenModel } from "../token/token.model.js";
8
- import { BaseFrameClass, api } from "sonamu";
9
- //#region src/application/qgrid/qgrid.frame.ts
10
- const pendingOAuth = /* @__PURE__ */ new Map();
11
- var QgridFrameClass = class extends BaseFrameClass {
12
- constructor() {
13
- super("Qgrid");
14
- }
15
- async query(prompt, system, timeout) {
16
- const pool = getPool();
17
- const result = await pool.query({
18
- system,
19
- prompt
20
- }, timeout);
21
- TokenModel.findByToken("A", pool.lastUsedToken).then((tokenEntry) => {
22
- RequestLogModel.save([{
23
- token_name: tokenEntry?.name ?? "Unknown Key",
24
- query: system ? `[System]\n${system}\n\n[User]\n${prompt}` : prompt,
25
- response: result.text,
26
- input_tokens: result.usage.input_tokens,
27
- output_tokens: result.usage.output_tokens,
28
- cache_read_tokens: result.usage.cache_read_input_tokens,
29
- cache_creation_tokens: result.usage.cache_creation_input_tokens,
30
- duration_ms: result.durationMs
31
- }]);
32
- }).catch((e) => console.error("requestLog save failed:", e));
33
- return result;
34
- }
35
- async stats() {
36
- const pool = getPool();
37
- const entries = await TokenModel.findActive("A");
38
- const tokenNames = new Map(entries.map((e) => [e.token, e.name]));
39
- return pool.getStats(tokenNames);
40
- }
41
- async addToken(token, name, refreshToken) {
42
- await TokenModel.save([{
43
- token,
44
- name,
45
- ...refreshToken && refreshToken.length > 0 ? { refresh_token: refreshToken } : {}
46
- }]);
47
- getPool().createWorkers(token);
48
- return { added: true };
49
- }
50
- async updateToken(token, name, newToken, refreshToken) {
51
- const pool = getPool();
52
- const entry = await TokenModel.findByToken("A", token);
53
- if (!entry) return { updated: false };
54
- const hasNewToken = newToken !== void 0 && newToken.length > 0;
55
- const hasRefreshToken = refreshToken !== void 0 && refreshToken.length > 0;
56
- await TokenModel.save([{
57
- id: entry.id,
58
- token: hasNewToken ? newToken : entry.token,
59
- name: name !== void 0 ? name : entry.name,
60
- ...hasRefreshToken ? { refresh_token: refreshToken } : {}
61
- }]);
62
- if (hasNewToken) {
63
- pool.destroyWorkers(token);
64
- pool.createWorkers(newToken);
65
- }
66
- return { updated: true };
67
- }
68
- async removeToken(token) {
69
- const pool = getPool();
70
- if (!pool.workers.has(token)) return { removed: false };
71
- const entry = await TokenModel.findByToken("A", token);
72
- if (entry) await TokenModel.del([entry.id]);
73
- pool.destroyWorkers(token);
74
- return { removed: true };
75
- }
76
- /**
77
- *
78
- * @param id token_id
79
- * 토큰 활성화/비활성화 토글 (pool 워커 생성/제거 & DB의 active 필드 업데이트)
80
- *
81
- * @returns 토큰 활성화 여부
82
- */
83
- async toggleToken(id) {
84
- const pool = getPool();
85
- const entry = await TokenModel.findOne("A", { id });
86
- if (!entry) return { active: false };
87
- const newActive = !entry.active;
88
- await TokenModel.save([{
89
- id,
90
- token: entry.token,
91
- active: newActive,
92
- name: entry.name
93
- }]);
94
- if (newActive) pool.createWorkers(entry.token);
95
- else pool.destroyWorkers(entry.token);
96
- return { active: newActive };
97
- }
98
- async oauthStart(name) {
99
- const { codeVerifier, codeChallenge, state } = generatePKCE();
100
- const redirectUri = `http://localhost:${process.env.PORT ?? "44900"}/callback`;
101
- const authUrl = buildAuthUrl(codeChallenge, state, redirectUri);
102
- pendingOAuth.set(state, {
103
- codeVerifier,
104
- name,
105
- redirectUri
106
- });
107
- setTimeout(() => pendingOAuth.delete(state), 3e5);
108
- return { authUrl };
109
- }
110
- async handleOAuthCallback(code, state, reply) {
111
- const pool = getPool();
112
- const pending = pendingOAuth.get(state);
113
- if (!pending) return reply.redirect("/?oauth=error&reason=invalid_state");
114
- pendingOAuth.delete(state);
115
- try {
116
- const tokens = await exchangeCodeForTokens(code, pending.codeVerifier, state, pending.redirectUri);
117
- if (tokens.accountUuid) {
118
- const oldEntries = await TokenModel.findByAccountUuid("A", tokens.accountUuid);
119
- for (const old of oldEntries) {
120
- pool.destroyWorkers(old.token);
121
- await TokenModel.del([old.id]);
122
- }
123
- }
124
- await TokenModel.save([{
125
- token: tokens.accessToken,
126
- name: pending.name,
127
- refresh_token: tokens.refreshToken,
128
- expires_at: tokens.expiresAt ? BigInt(tokens.expiresAt) : null,
129
- account_uuid: tokens.accountUuid
130
- }]);
131
- pool.createWorkers(tokens.accessToken);
132
- return reply.redirect(`/?oauth=success&name=${encodeURIComponent(pending.name)}`);
133
- } catch (e) {
134
- return reply.redirect(`/?oauth=error&reason=${encodeURIComponent(e.message)}`);
135
- }
136
- }
137
- async usage(tokenName) {
138
- const pool = getPool();
139
- const { rows: allTokens } = await TokenModel.findMany("A");
140
- const entry = tokenName ? allTokens.find((e) => e.name === tokenName) : allTokens.findLast((e) => e.active);
141
- if (!entry) return { error: "NOT_FOUND" };
142
- let accessToken = entry.token;
143
- if (entry.expires_at && Number(entry.expires_at) < Date.now() && entry.refresh_token) try {
144
- accessToken = await this.refreshToken(pool, entry);
145
- } catch (e) {
146
- console.warn(`[usage] refresh failed for ${entry.name}: ${e.message}`);
147
- return { error: "re-login required" };
148
- }
149
- const result = await fetchUsage(accessToken);
150
- if (result.error && entry.refresh_token) try {
151
- accessToken = await this.refreshToken(pool, entry);
152
- return await fetchUsage(accessToken);
153
- } catch (e) {
154
- console.warn(`[usage] refresh failed for ${entry.name}: ${e.message}`);
155
- return { error: "re-login required" };
156
- }
157
- return result;
158
- }
159
- async refreshToken(pool, token) {
160
- if (!token.refresh_token) throw new Error("No refresh token");
161
- const refreshed = await refreshAccessToken(token.refresh_token);
162
- await TokenModel.save([{
163
- id: token.id,
164
- token: refreshed.accessToken,
165
- refresh_token: refreshed.refreshToken,
166
- expires_at: BigInt(refreshed.expiresAt),
167
- name: token.name ?? ""
168
- }]);
169
- pool.destroyWorkers(token.token);
170
- pool.createWorkers(refreshed.accessToken);
171
- return refreshed.accessToken;
172
- }
173
- async health() {
174
- const pool = getPool();
175
- return {
176
- status: "ok",
177
- workers: [...pool.workers.values()].flat().length,
178
- activeTokens: pool.workers.size - pool.quotaExhausted.size
179
- };
180
- }
181
- };
182
- __decorate([
183
- api({
184
- httpMethod: "POST",
185
- clients: ["axios", "tanstack-mutation"]
186
- }),
187
- __decorateMetadata("design:type", Function),
188
- __decorateMetadata("design:paramtypes", [
189
- String,
190
- String,
191
- Number
192
- ]),
193
- __decorateMetadata("design:returntype", Promise)
194
- ], QgridFrameClass.prototype, "query", null);
195
- __decorate([
196
- api({
197
- httpMethod: "GET",
198
- clients: ["axios", "tanstack-query"]
199
- }),
200
- __decorateMetadata("design:type", Function),
201
- __decorateMetadata("design:paramtypes", []),
202
- __decorateMetadata("design:returntype", Promise)
203
- ], QgridFrameClass.prototype, "stats", null);
204
- __decorate([
205
- api({
206
- httpMethod: "POST",
207
- clients: ["axios", "tanstack-mutation"]
208
- }),
209
- __decorateMetadata("design:type", Function),
210
- __decorateMetadata("design:paramtypes", [
211
- String,
212
- String,
213
- String
214
- ]),
215
- __decorateMetadata("design:returntype", Promise)
216
- ], QgridFrameClass.prototype, "addToken", null);
217
- __decorate([
218
- api({
219
- httpMethod: "POST",
220
- clients: ["axios", "tanstack-mutation"]
221
- }),
222
- __decorateMetadata("design:type", Function),
223
- __decorateMetadata("design:paramtypes", [
224
- String,
225
- String,
226
- String,
227
- String
228
- ]),
229
- __decorateMetadata("design:returntype", Promise)
230
- ], QgridFrameClass.prototype, "updateToken", null);
231
- __decorate([
232
- api({
233
- httpMethod: "POST",
234
- clients: ["axios", "tanstack-mutation"]
235
- }),
236
- __decorateMetadata("design:type", Function),
237
- __decorateMetadata("design:paramtypes", [String]),
238
- __decorateMetadata("design:returntype", Promise)
239
- ], QgridFrameClass.prototype, "removeToken", null);
240
- __decorate([
241
- api({
242
- httpMethod: "POST",
243
- clients: ["axios", "tanstack-mutation"]
244
- }),
245
- __decorateMetadata("design:type", Function),
246
- __decorateMetadata("design:paramtypes", [Number]),
247
- __decorateMetadata("design:returntype", Promise)
248
- ], QgridFrameClass.prototype, "toggleToken", null);
249
- __decorate([
250
- api({
251
- httpMethod: "POST",
252
- clients: ["axios", "tanstack-mutation"]
253
- }),
254
- __decorateMetadata("design:type", Function),
255
- __decorateMetadata("design:paramtypes", [String]),
256
- __decorateMetadata("design:returntype", Promise)
257
- ], QgridFrameClass.prototype, "oauthStart", null);
258
- __decorate([
259
- api({
260
- httpMethod: "GET",
261
- clients: ["axios", "tanstack-query"]
262
- }),
263
- __decorateMetadata("design:type", Function),
264
- __decorateMetadata("design:paramtypes", [String]),
265
- __decorateMetadata("design:returntype", Promise)
266
- ], QgridFrameClass.prototype, "usage", null);
267
- __decorate([
268
- api({
269
- httpMethod: "GET",
270
- clients: ["axios", "tanstack-query"]
271
- }),
272
- __decorateMetadata("design:type", Function),
273
- __decorateMetadata("design:paramtypes", []),
274
- __decorateMetadata("design:returntype", Promise)
275
- ], QgridFrameClass.prototype, "health", null);
276
- const QgridFrame = new QgridFrameClass();
277
- //#endregion
278
- export { QgridFrame };
279
-
280
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQuZnJhbWUuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcGxpY2F0aW9uL3FncmlkL3FncmlkLmZyYW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgRmFzdGlmeVJlcGx5IH0gZnJvbSBcImZhc3RpZnlcIjtcbmltcG9ydCB7IGFwaSwgQmFzZUZyYW1lQ2xhc3MgfSBmcm9tIFwic29uYW11XCI7XG5cbmltcG9ydCB7IFJlcXVlc3RMb2dNb2RlbCB9IGZyb20gXCIuLi9yZXF1ZXN0LWxvZy9yZXF1ZXN0LWxvZy5tb2RlbFwiO1xuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHR5cGUgeyBSZWZyZXNoVG9rZW5QYXJhbXMgfSBmcm9tIFwiLi4vdG9rZW4vdG9rZW4udHlwZXNcIjtcbmltcG9ydCB7XG4gIGJ1aWxkQXV0aFVybCxcbiAgZXhjaGFuZ2VDb2RlRm9yVG9rZW5zLFxuICBmZXRjaFVzYWdlLFxuICBnZW5lcmF0ZVBLQ0UsXG4gIHJlZnJlc2hBY2Nlc3NUb2tlbixcbn0gZnJvbSBcIi4vb2F1dGhcIjtcbmltcG9ydCB7IHR5cGUgQ2xhdWRlUG9vbCwgZ2V0UG9vbCB9IGZyb20gXCIuL3Bvb2xcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ2xpUmVzdWx0LFxuICBIZWFsdGhSZXNwb25zZSxcbiAgT0F1dGhTdGFydFJlc3VsdCxcbiAgVG9rZW5TdGF0cyxcbiAgVXNhZ2VSZXNwb25zZSxcbn0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcblxuLy8gUEtDRSDshLjshZgg66mU66qo66asIOyggOyepSAoc3RhdGUg4oaSIHsgY29kZVZlcmlmaWVyLCBuYW1lLCByZWRpcmVjdFVyaSB9KVxuY29uc3QgcGVuZGluZ09BdXRoID0gbmV3IE1hcDxzdHJpbmcsIHsgY29kZVZlcmlmaWVyOiBzdHJpbmc7IG5hbWU6IHN0cmluZzsgcmVkaXJlY3RVcmk6IHN0cmluZyB9PigpO1xuXG5jbGFzcyBRZ3JpZEZyYW1lQ2xhc3MgZXh0ZW5kcyBCYXNlRnJhbWVDbGFzcyB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFwiUWdyaWRcIik7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgcXVlcnkocHJvbXB0OiBzdHJpbmcsIHN5c3RlbT86IHN0cmluZywgdGltZW91dD86IG51bWJlcik6IFByb21pc2U8Q2xpUmVzdWx0PiB7XG4gICAgY29uc3QgcG9vbCA9IGdldFBvb2woKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwb29sLnF1ZXJ5KHsgc3lzdGVtLCBwcm9tcHQgfSwgdGltZW91dCk7XG5cbiAgICAvLyDroZzqt7gg6riw66GdIOyLpO2MqO2VtOuPhCDsv7zrpqwg6rKw6rO864qUIOuwmO2ZmFxuICAgIFRva2VuTW9kZWwuZmluZEJ5VG9rZW4oXCJBXCIsIHBvb2wubGFzdFVzZWRUb2tlbilcbiAgICAgIC50aGVuKCh0b2tlbkVudHJ5KSA9PiB7XG4gICAgICAgIFJlcXVlc3RMb2dNb2RlbC5zYXZlKFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0b2tlbl9uYW1lOiB0b2tlbkVudHJ5Py5uYW1lID8/IFwiVW5rbm93biBLZXlcIixcbiAgICAgICAgICAgIHF1ZXJ5OiBzeXN0ZW0gPyBgW1N5c3RlbV1cXG4ke3N5c3RlbX1cXG5cXG5bVXNlcl1cXG4ke3Byb21wdH1gIDogcHJvbXB0LFxuICAgICAgICAgICAgcmVzcG9uc2U6IHJlc3VsdC50ZXh0LFxuICAgICAgICAgICAgaW5wdXRfdG9rZW5zOiByZXN1bHQudXNhZ2UuaW5wdXRfdG9rZW5zLFxuICAgICAgICAgICAgb3V0cHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLm91dHB1dF90b2tlbnMsXG4gICAgICAgICAgICBjYWNoZV9yZWFkX3Rva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zLFxuICAgICAgICAgICAgY2FjaGVfY3JlYXRpb25fdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zLFxuICAgICAgICAgICAgZHVyYXRpb25fbXM6IHJlc3VsdC5kdXJhdGlvbk1zLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZSkgPT4gY29uc29sZS5lcnJvcihcInJlcXVlc3RMb2cgc2F2ZSBmYWlsZWQ6XCIsIGUpKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBzdGF0cygpOiBQcm9taXNlPFRva2VuU3RhdHNbXT4ge1xuICAgIGNvbnN0IHBvb2wgPSBnZXRQb29sKCk7XG4gICAgY29uc3QgZW50cmllcyA9IGF3YWl0IFRva2VuTW9kZWwuZmluZEFjdGl2ZShcIkFcIik7XG4gICAgY29uc3QgdG9rZW5OYW1lcyA9IG5ldyBNYXAoZW50cmllcy5tYXAoKGUpID0+IFtlLnRva2VuLCBlLm5hbWVdKSk7XG4gICAgcmV0dXJuIHBvb2wuZ2V0U3RhdHModG9rZW5OYW1lcyk7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgYWRkVG9rZW4odG9rZW46IHN0cmluZywgbmFtZTogc3RyaW5nLCByZWZyZXNoVG9rZW4/OiBzdHJpbmcpOiBQcm9taXNlPHsgYWRkZWQ6IGJvb2xlYW4gfT4ge1xuICAgIGF3YWl0IFRva2VuTW9kZWwuc2F2ZShbXG4gICAgICB7XG4gICAgICAgIHRva2VuLFxuICAgICAgICBuYW1lLFxuICAgICAgICAuLi4ocmVmcmVzaFRva2VuICYmIHJlZnJlc2hUb2tlbi5sZW5ndGggPiAwID8geyByZWZyZXNoX3Rva2VuOiByZWZyZXNoVG9rZW4gfSA6IHt9KSxcbiAgICAgIH0sXG4gICAgXSk7XG4gICAgZ2V0UG9vbCgpLmNyZWF0ZVdvcmtlcnModG9rZW4pO1xuICAgIHJldHVybiB7IGFkZGVkOiB0cnVlIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgdXBkYXRlVG9rZW4oXG4gICAgdG9rZW46IHN0cmluZyxcbiAgICBuYW1lPzogc3RyaW5nLFxuICAgIG5ld1Rva2VuPzogc3RyaW5nLFxuICAgIHJlZnJlc2hUb2tlbj86IHN0cmluZyxcbiAgKTogUHJvbWlzZTx7IHVwZGF0ZWQ6IGJvb2xlYW4gfT4ge1xuICAgIGNvbnN0IHBvb2wgPSBnZXRQb29sKCk7XG4gICAgY29uc3QgZW50cnkgPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRCeVRva2VuKFwiQVwiLCB0b2tlbik7XG4gICAgaWYgKCFlbnRyeSkgcmV0dXJuIHsgdXBkYXRlZDogZmFsc2UgfTtcblxuICAgIGNvbnN0IGhhc05ld1Rva2VuID0gbmV3VG9rZW4gIT09IHVuZGVmaW5lZCAmJiBuZXdUb2tlbi5sZW5ndGggPiAwO1xuICAgIGNvbnN0IGhhc1JlZnJlc2hUb2tlbiA9IHJlZnJlc2hUb2tlbiAhPT0gdW5kZWZpbmVkICYmIHJlZnJlc2hUb2tlbi5sZW5ndGggPiAwO1xuICAgIGF3YWl0IFRva2VuTW9kZWwuc2F2ZShbXG4gICAgICB7XG4gICAgICAgIGlkOiBlbnRyeS5pZCxcbiAgICAgICAgdG9rZW46IGhhc05ld1Rva2VuID8gbmV3VG9rZW4gOiBlbnRyeS50b2tlbixcbiAgICAgICAgbmFtZTogbmFtZSAhPT0gdW5kZWZpbmVkID8gbmFtZSA6IGVudHJ5Lm5hbWUsXG4gICAgICAgIC4uLihoYXNSZWZyZXNoVG9rZW4gPyB7IHJlZnJlc2hfdG9rZW46IHJlZnJlc2hUb2tlbiB9IDoge30pLFxuICAgICAgfSxcbiAgICBdKTtcblxuICAgIGlmIChoYXNOZXdUb2tlbikge1xuICAgICAgcG9vbC5kZXN0cm95V29ya2Vycyh0b2tlbik7XG4gICAgICBwb29sLmNyZWF0ZVdvcmtlcnMobmV3VG9rZW4pO1xuICAgIH1cbiAgICByZXR1cm4geyB1cGRhdGVkOiB0cnVlIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgcmVtb3ZlVG9rZW4odG9rZW46IHN0cmluZyk6IFByb21pc2U8eyByZW1vdmVkOiBib29sZWFuIH0+IHtcbiAgICBjb25zdCBwb29sID0gZ2V0UG9vbCgpO1xuICAgIGlmICghcG9vbC53b3JrZXJzLmhhcyh0b2tlbikpIHJldHVybiB7IHJlbW92ZWQ6IGZhbHNlIH07XG5cbiAgICBjb25zdCBlbnRyeSA9IGF3YWl0IFRva2VuTW9kZWwuZmluZEJ5VG9rZW4oXCJBXCIsIHRva2VuKTtcbiAgICBpZiAoZW50cnkpIGF3YWl0IFRva2VuTW9kZWwuZGVsKFtlbnRyeS5pZF0pO1xuICAgIHBvb2wuZGVzdHJveVdvcmtlcnModG9rZW4pO1xuICAgIHJldHVybiB7IHJlbW92ZWQ6IHRydWUgfTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gaWQgdG9rZW5faWRcbiAgICog7Yag7YGwIO2ZnOyEse2ZlC/ruYTtmZzshLHtmZQg7Yag6riAIChwb29sIOybjOy7pCDsg53shLEv7KCc6rGwICYgRELsnZggYWN0aXZlIO2VhOuTnCDsl4XrjbDsnbTtirgpXG4gICAqXG4gICAqIEByZXR1cm5zIO2GoO2BsCDtmZzshLHtmZQg7Jes67aAXG4gICAqL1xuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgdG9nZ2xlVG9rZW4oaWQ6IG51bWJlcik6IFByb21pc2U8eyBhY3RpdmU6IGJvb2xlYW4gfT4ge1xuICAgIGNvbnN0IHBvb2wgPSBnZXRQb29sKCk7XG4gICAgY29uc3QgZW50cnkgPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRPbmUoXCJBXCIsIHsgaWQgfSk7XG4gICAgaWYgKCFlbnRyeSkgcmV0dXJuIHsgYWN0aXZlOiBmYWxzZSB9O1xuXG4gICAgY29uc3QgbmV3QWN0aXZlID0gIWVudHJ5LmFjdGl2ZTtcbiAgICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW3sgaWQsIHRva2VuOiBlbnRyeS50b2tlbiwgYWN0aXZlOiBuZXdBY3RpdmUsIG5hbWU6IGVudHJ5Lm5hbWUgfV0pO1xuXG4gICAgLy8g7Yag7YGw7J2YIOyDiOuhnOyatCDsg4Htg5zqsIAg7Zmc7ISx7ZmU66m0L+u5hO2ZnOyEse2ZlOuptFxuICAgIGlmIChuZXdBY3RpdmUpIHtcbiAgICAgIC8vIOybjOy7pCDsg53shLFcbiAgICAgIHBvb2wuY3JlYXRlV29ya2VycyhlbnRyeS50b2tlbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIOybjOy7pCDsoJzqsbBcbiAgICAgIHBvb2wuZGVzdHJveVdvcmtlcnMoZW50cnkudG9rZW4pO1xuICAgIH1cblxuICAgIHJldHVybiB7IGFjdGl2ZTogbmV3QWN0aXZlIH07XG4gIH1cblxuICAvLyBPQXV0aCDroZzqt7jsnbg6IGF1dGhVcmwg7IOd7ISxICjtlITroaDtirjsl5DshJwg7J20IEFQSSDtmLjstpwg7ZuEIGF1dGhVcmzroZwg66as64uk7J2066CJ7Yq4KVxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgb2F1dGhTdGFydChuYW1lOiBzdHJpbmcpOiBQcm9taXNlPE9BdXRoU3RhcnRSZXN1bHQ+IHtcbiAgICBjb25zdCB7IGNvZGVWZXJpZmllciwgY29kZUNoYWxsZW5nZSwgc3RhdGUgfSA9IGdlbmVyYXRlUEtDRSgpO1xuXG4gICAgY29uc3Qgc2VydmVyUG9ydCA9IHByb2Nlc3MuZW52LlBPUlQgPz8gXCI0NDkwMFwiO1xuICAgIGNvbnN0IHJlZGlyZWN0VXJpID0gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtzZXJ2ZXJQb3J0fS9jYWxsYmFja2A7XG4gICAgY29uc3QgYXV0aFVybCA9IGJ1aWxkQXV0aFVybChjb2RlQ2hhbGxlbmdlLCBzdGF0ZSwgcmVkaXJlY3RVcmkpO1xuXG4gICAgLy8gUEtDReulvCDrqZTrqqjrpqzsl5Ag7KCA7J6lICg167aEIFRUTClcbiAgICBwZW5kaW5nT0F1dGguc2V0KHN0YXRlLCB7IGNvZGVWZXJpZmllciwgbmFtZSwgcmVkaXJlY3RVcmkgfSk7XG4gICAgc2V0VGltZW91dCgoKSA9PiBwZW5kaW5nT0F1dGguZGVsZXRlKHN0YXRlKSwgMzAwXzAwMCk7XG5cbiAgICByZXR1cm4geyBhdXRoVXJsIH07XG4gIH1cblxuICAvLyBPQXV0aCDsvZzrsLEg7LKY66asIOKAlCBzb25hbXUuY29uZmlnLnRz7J2YIGN1c3RvbSDrnbzsmrDtirjsl5DshJwg7Zi47Lac65CoXG4gIGFzeW5jIGhhbmRsZU9BdXRoQ2FsbGJhY2soY29kZTogc3RyaW5nLCBzdGF0ZTogc3RyaW5nLCByZXBseTogRmFzdGlmeVJlcGx5KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcG9vbCA9IGdldFBvb2woKTtcbiAgICBjb25zdCBwZW5kaW5nID0gcGVuZGluZ09BdXRoLmdldChzdGF0ZSk7XG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICByZXR1cm4gcmVwbHkucmVkaXJlY3QoXCIvP29hdXRoPWVycm9yJnJlYXNvbj1pbnZhbGlkX3N0YXRlXCIpO1xuICAgIH1cbiAgICBwZW5kaW5nT0F1dGguZGVsZXRlKHN0YXRlKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCBleGNoYW5nZUNvZGVGb3JUb2tlbnMoXG4gICAgICAgIGNvZGUsXG4gICAgICAgIHBlbmRpbmcuY29kZVZlcmlmaWVyLFxuICAgICAgICBzdGF0ZSxcbiAgICAgICAgcGVuZGluZy5yZWRpcmVjdFVyaSxcbiAgICAgICk7XG5cbiAgICAgIC8vIOqwmeydgCDqs4TsoJXsnZgg7J207KCEIO2GoO2BsOydtCDsnojsnLzrqbQg6rWQ7LK0XG4gICAgICBpZiAodG9rZW5zLmFjY291bnRVdWlkKSB7XG4gICAgICAgIGNvbnN0IG9sZEVudHJpZXMgPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRCeUFjY291bnRVdWlkKFwiQVwiLCB0b2tlbnMuYWNjb3VudFV1aWQpO1xuICAgICAgICBmb3IgKGNvbnN0IG9sZCBvZiBvbGRFbnRyaWVzKSB7XG4gICAgICAgICAgcG9vbC5kZXN0cm95V29ya2VycyhvbGQudG9rZW4pO1xuICAgICAgICAgIGF3YWl0IFRva2VuTW9kZWwuZGVsKFtvbGQuaWRdKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyDsg4gg7Yag7YGwIOyggOyepSArIHBvb2zsl5Ag65Ox66GdXG4gICAgICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgICAgICB7XG4gICAgICAgICAgdG9rZW46IHRva2Vucy5hY2Nlc3NUb2tlbixcbiAgICAgICAgICBuYW1lOiBwZW5kaW5nLm5hbWUsXG4gICAgICAgICAgcmVmcmVzaF90b2tlbjogdG9rZW5zLnJlZnJlc2hUb2tlbixcbiAgICAgICAgICBleHBpcmVzX2F0OiB0b2tlbnMuZXhwaXJlc0F0ID8gQmlnSW50KHRva2Vucy5leHBpcmVzQXQpIDogbnVsbCxcbiAgICAgICAgICBhY2NvdW50X3V1aWQ6IHRva2Vucy5hY2NvdW50VXVpZCxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgICAgcG9vbC5jcmVhdGVXb3JrZXJzKHRva2Vucy5hY2Nlc3NUb2tlbik7XG5cbiAgICAgIHJldHVybiByZXBseS5yZWRpcmVjdChgLz9vYXV0aD1zdWNjZXNzJm5hbWU9JHtlbmNvZGVVUklDb21wb25lbnQocGVuZGluZy5uYW1lKX1gKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gcmVwbHkucmVkaXJlY3QoYC8/b2F1dGg9ZXJyb3ImcmVhc29uPSR7ZW5jb2RlVVJJQ29tcG9uZW50KChlIGFzIEVycm9yKS5tZXNzYWdlKX1gKTtcbiAgICB9XG4gIH1cblxuICAvLyDthqDtgbAg7IKs7Jqp65+JIOyhsO2ajCAoT0F1dGggdXNhZ2UgQVBJKVxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyB1c2FnZSh0b2tlbk5hbWU/OiBzdHJpbmcpOiBQcm9taXNlPFVzYWdlUmVzcG9uc2U+IHtcbiAgICBjb25zdCBwb29sID0gZ2V0UG9vbCgpO1xuICAgIGNvbnN0IHsgcm93czogYWxsVG9rZW5zIH0gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRNYW55KFwiQVwiKTtcbiAgICBjb25zdCBlbnRyeSA9IHRva2VuTmFtZVxuICAgICAgPyBhbGxUb2tlbnMuZmluZCgoZSkgPT4gZS5uYW1lID09PSB0b2tlbk5hbWUpXG4gICAgICA6IGFsbFRva2Vucy5maW5kTGFzdCgoZSkgPT4gZS5hY3RpdmUpO1xuXG4gICAgaWYgKCFlbnRyeSkgcmV0dXJuIHsgZXJyb3I6IFwiTk9UX0ZPVU5EXCIgfTtcblxuICAgIC8vIOunjOujjCDtmZXsnbggKyByZWZyZXNoIOyLnOuPhFxuICAgIGxldCBhY2Nlc3NUb2tlbiA9IGVudHJ5LnRva2VuO1xuICAgIGNvbnN0IGlzRXhwaXJlZCA9IGVudHJ5LmV4cGlyZXNfYXQgJiYgTnVtYmVyKGVudHJ5LmV4cGlyZXNfYXQpIDwgRGF0ZS5ub3coKTtcblxuICAgIGlmIChpc0V4cGlyZWQgJiYgZW50cnkucmVmcmVzaF90b2tlbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYWNjZXNzVG9rZW4gPSBhd2FpdCB0aGlzLnJlZnJlc2hUb2tlbihwb29sLCBlbnRyeSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgW3VzYWdlXSByZWZyZXNoIGZhaWxlZCBmb3IgJHtlbnRyeS5uYW1lfTogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgICAgcmV0dXJuIHsgZXJyb3I6IFwicmUtbG9naW4gcmVxdWlyZWRcIiB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHVzYWdlIO2YuOy2nFxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZldGNoVXNhZ2UoYWNjZXNzVG9rZW4pO1xuXG4gICAgLy8g7J247KadIOyXkOufrOuptCByZWZyZXNoX3Rva2Vu7Jy866GcIOyerOyLnOuPhFxuICAgIGlmIChyZXN1bHQuZXJyb3IgJiYgZW50cnkucmVmcmVzaF90b2tlbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYWNjZXNzVG9rZW4gPSBhd2FpdCB0aGlzLnJlZnJlc2hUb2tlbihwb29sLCBlbnRyeSk7XG4gICAgICAgIHJldHVybiBhd2FpdCBmZXRjaFVzYWdlKGFjY2Vzc1Rva2VuKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBbdXNhZ2VdIHJlZnJlc2ggZmFpbGVkIGZvciAke2VudHJ5Lm5hbWV9OiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgICAgICByZXR1cm4geyBlcnJvcjogXCJyZS1sb2dpbiByZXF1aXJlZFwiIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGFzeW5jIHJlZnJlc2hUb2tlbihwb29sOiBDbGF1ZGVQb29sLCB0b2tlbjogUmVmcmVzaFRva2VuUGFyYW1zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoIXRva2VuLnJlZnJlc2hfdG9rZW4pIHRocm93IG5ldyBFcnJvcihcIk5vIHJlZnJlc2ggdG9rZW5cIik7XG4gICAgY29uc3QgcmVmcmVzaGVkID0gYXdhaXQgcmVmcmVzaEFjY2Vzc1Rva2VuKHRva2VuLnJlZnJlc2hfdG9rZW4pO1xuICAgIGF3YWl0IFRva2VuTW9kZWwuc2F2ZShbXG4gICAgICB7XG4gICAgICAgIGlkOiB0b2tlbi5pZCxcbiAgICAgICAgdG9rZW46IHJlZnJlc2hlZC5hY2Nlc3NUb2tlbixcbiAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaGVkLnJlZnJlc2hUb2tlbixcbiAgICAgICAgZXhwaXJlc19hdDogQmlnSW50KHJlZnJlc2hlZC5leHBpcmVzQXQpLFxuICAgICAgICBuYW1lOiB0b2tlbi5uYW1lID8/IFwiXCIsXG4gICAgICB9LFxuICAgIF0pO1xuICAgIHBvb2wuZGVzdHJveVdvcmtlcnModG9rZW4udG9rZW4pO1xuICAgIHBvb2wuY3JlYXRlV29ya2VycyhyZWZyZXNoZWQuYWNjZXNzVG9rZW4pO1xuICAgIHJldHVybiByZWZyZXNoZWQuYWNjZXNzVG9rZW47XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBoZWFsdGgoKTogUHJvbWlzZTxIZWFsdGhSZXNwb25zZT4ge1xuICAgIGNvbnN0IHBvb2wgPSBnZXRQb29sKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogXCJva1wiLFxuICAgICAgd29ya2VyczogWy4uLnBvb2wud29ya2Vycy52YWx1ZXMoKV0uZmxhdCgpLmxlbmd0aCxcbiAgICAgIGFjdGl2ZVRva2VuczogcG9vbC53b3JrZXJzLnNpemUgLSBwb29sLnF1b3RhRXhoYXVzdGVkLnNpemUsXG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgUWdyaWRGcmFtZSA9IG5ldyBRZ3JpZEZyYW1lQ2xhc3MoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBdUJBLE1BQU0sK0JBQWUsSUFBSSxLQUEwRTtBQUVuRyxJQUFNLGtCQUFOLGNBQThCLGVBQWU7Q0FDM0MsY0FBYztBQUNaLFFBQU0sUUFBUTs7Q0FHaEIsTUFDTSxNQUFNLFFBQWdCLFFBQWlCLFNBQXNDO0VBQ2pGLE1BQU0sT0FBTyxTQUFTO0VBQ3RCLE1BQU0sU0FB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