@cartanova/qgrid-cli 1.0.4 → 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 +10 -10
  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,44 +0,0 @@
1
- import { getSafeTimers } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js";
2
- //#region ../../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
3
- const NAME_WORKER_STATE = "__vitest_worker__";
4
- function getWorkerState() {
5
- const workerState = globalThis[NAME_WORKER_STATE];
6
- if (!workerState) throw new Error("Vitest failed to access its internal state.\n\nOne of the following is possible:\n- \"vitest\" is imported directly without running \"vitest\" command\n- \"vitest\" is imported inside \"globalSetup\" (to fix this, use \"setupFiles\" instead, because \"globalSetup\" runs in a different context)\n- \"vitest\" is imported inside Vite / Vitest config file\n- Otherwise, it might be a Vitest bug. Please report it to https://github.com/vitest-dev/vitest/issues\n");
7
- return workerState;
8
- }
9
- function isChildProcess() {
10
- return typeof process !== "undefined" && !!process.send;
11
- }
12
- function resetModules(modules, resetMocks = false) {
13
- const skipPaths = [
14
- /\/vitest\/dist\//,
15
- /vitest-virtual-\w+\/dist/,
16
- /@vitest\/dist/,
17
- ...!resetMocks ? [/^mock:/] : []
18
- ];
19
- modules.idToModuleMap.forEach((node, path) => {
20
- if (skipPaths.some((re) => re.test(path))) return;
21
- node.promise = void 0;
22
- node.exports = void 0;
23
- node.evaluated = false;
24
- node.importers.clear();
25
- });
26
- }
27
- function waitNextTick() {
28
- const { setTimeout } = getSafeTimers();
29
- return new Promise((resolve) => setTimeout(resolve, 0));
30
- }
31
- async function waitForImportsToResolve() {
32
- await waitNextTick();
33
- const state = getWorkerState();
34
- const promises = [];
35
- const resolvingCount = state.resolvingModules.size;
36
- for (const [_, mod] of state.evaluatedModules.idToModuleMap) if (mod.promise && !mod.evaluated) promises.push(mod.promise);
37
- if (!promises.length && !resolvingCount) return;
38
- await Promise.allSettled(promises);
39
- await waitForImportsToResolve();
40
- }
41
- //#endregion
42
- export { getWorkerState, isChildProcess, resetModules, waitForImportsToResolve };
43
-
44
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuQlg1Rmc4QzQuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzLy5wbnBtL3ZpdGVzdEA0LjEuMl9Ab3BlbnRlbGVtZXRyeSthcGlAMS45LjBfQHR5cGVzK25vZGVAMjUuMC43X3ZpdGVAOC4wLjNfQGVtbmFwaStjb3JlQDEuOS4yX19iYjMxMDg3Mjc4Zjk3YTM5YjMxYjkyMDEwYmVhYjk4MC9ub2RlX21vZHVsZXMvdml0ZXN0L2Rpc3QvY2h1bmtzL3V0aWxzLkJYNUZnOEM0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGdldFNhZmVUaW1lcnMgfSBmcm9tICdAdml0ZXN0L3V0aWxzL3RpbWVycyc7XG5cbmNvbnN0IE5BTUVfV09SS0VSX1NUQVRFID0gXCJfX3ZpdGVzdF93b3JrZXJfX1wiO1xuY2xhc3MgRW52aXJvbm1lbnRUZWFyZG93bkVycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHRuYW1lID0gXCJFbnZpcm9ubWVudFRlYXJkb3duRXJyb3JcIjtcbn1cbmZ1bmN0aW9uIGdldFdvcmtlclN0YXRlKCkge1xuXHQvLyBAdHMtZXhwZWN0LWVycm9yIHVudHlwZWQgZ2xvYmFsXG5cdGNvbnN0IHdvcmtlclN0YXRlID0gZ2xvYmFsVGhpc1tOQU1FX1dPUktFUl9TVEFURV07XG5cdGlmICghd29ya2VyU3RhdGUpIHRocm93IG5ldyBFcnJvcihcIlZpdGVzdCBmYWlsZWQgdG8gYWNjZXNzIGl0cyBpbnRlcm5hbCBzdGF0ZS5cXG5cXG5PbmUgb2YgdGhlIGZvbGxvd2luZyBpcyBwb3NzaWJsZTpcXG4tIFxcXCJ2aXRlc3RcXFwiIGlzIGltcG9ydGVkIGRpcmVjdGx5IHdpdGhvdXQgcnVubmluZyBcXFwidml0ZXN0XFxcIiBjb21tYW5kXFxuLSBcXFwidml0ZXN0XFxcIiBpcyBpbXBvcnRlZCBpbnNpZGUgXFxcImdsb2JhbFNldHVwXFxcIiAodG8gZml4IHRoaXMsIHVzZSBcXFwic2V0dXBGaWxlc1xcXCIgaW5zdGVhZCwgYmVjYXVzZSBcXFwiZ2xvYmFsU2V0dXBcXFwiIHJ1bnMgaW4gYSBkaWZmZXJlbnQgY29udGV4dClcXG4tIFxcXCJ2aXRlc3RcXFwiIGlzIGltcG9ydGVkIGluc2lkZSBWaXRlIC8gVml0ZXN0IGNvbmZpZyBmaWxlXFxuLSBPdGhlcndpc2UsIGl0IG1pZ2h0IGJlIGEgVml0ZXN0IGJ1Zy4gUGxlYXNlIHJlcG9ydCBpdCB0byBodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvaXNzdWVzXFxuXCIpO1xuXHRyZXR1cm4gd29ya2VyU3RhdGU7XG59XG5mdW5jdGlvbiBnZXRTYWZlV29ya2VyU3RhdGUoKSB7XG5cdC8vIEB0cy1leHBlY3QtZXJyb3IgdW50eXBlZCBnbG9iYWxcblx0cmV0dXJuIGdsb2JhbFRoaXNbTkFNRV9XT1JLRVJfU1RBVEVdO1xufVxuZnVuY3Rpb24gcHJvdmlkZVdvcmtlclN0YXRlKGNvbnRleHQsIHN0YXRlKSB7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb250ZXh0LCBOQU1FX1dPUktFUl9TVEFURSwge1xuXHRcdHZhbHVlOiBzdGF0ZSxcblx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cdFx0d3JpdGFibGU6IHRydWUsXG5cdFx0ZW51bWVyYWJsZTogZmFsc2Vcblx0fSk7XG5cdHJldHVybiBzdGF0ZTtcbn1cbmZ1bmN0aW9uIGlzQ2hpbGRQcm9jZXNzKCkge1xuXHRyZXR1cm4gdHlwZW9mIHByb2Nlc3MgIT09IFwidW5kZWZpbmVkXCIgJiYgISFwcm9jZXNzLnNlbmQ7XG59XG5mdW5jdGlvbiByZXNldE1vZHVsZXMobW9kdWxlcywgcmVzZXRNb2NrcyA9IGZhbHNlKSB7XG5cdGNvbnN0IHNraXBQYXRocyA9IFtcblx0XHQvXFwvdml0ZXN0XFwvZGlzdFxcLy8sXG5cdFx0L3ZpdGVzdC12aXJ0dWFsLVxcdytcXC9kaXN0Lyxcblx0XHQvQHZpdGVzdFxcL2Rpc3QvLFxuXHRcdC4uLiFyZXNldE1vY2tzID8gWy9ebW9jazovXSA6IFtdXG5cdF07XG5cdG1vZHVsZXMuaWRUb01vZHVsZU1hcC5mb3JFYWNoKChub2RlLCBwYXRoKSA9PiB7XG5cdFx0aWYgKHNraXBQYXRocy5zb21lKChyZSkgPT4gcmUudGVzdChwYXRoKSkpIHJldHVybjtcblx0XHRub2RlLnByb21pc2UgPSB2b2lkIDA7XG5cdFx0bm9kZS5leHBvcnRzID0gdm9pZCAwO1xuXHRcdG5vZGUuZXZhbHVhdGVkID0gZmFsc2U7XG5cdFx0bm9kZS5pbXBvcnRlcnMuY2xlYXIoKTtcblx0fSk7XG59XG5mdW5jdGlvbiB3YWl0TmV4dFRpY2soKSB7XG5cdGNvbnN0IHsgc2V0VGltZW91dCB9ID0gZ2V0U2FmZVRpbWVycygpO1xuXHRyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMCkpO1xufVxuYXN5bmMgZnVuY3Rpb24gd2FpdEZvckltcG9ydHNUb1Jlc29sdmUoKSB7XG5cdGF3YWl0IHdhaXROZXh0VGljaygpO1xuXHRjb25zdCBzdGF0ZSA9IGdldFdvcmtlclN0YXRlKCk7XG5cdGNvbnN0IHByb21pc2VzID0gW107XG5cdGNvbnN0IHJlc29sdmluZ0NvdW50ID0gc3RhdGUucmVzb2x2aW5nTW9kdWxlcy5zaXplO1xuXHRmb3IgKGNvbnN0IFtfLCBtb2RdIG9mIHN0YXRlLmV2YWx1YXRlZE1vZHVsZXMuaWRUb01vZHVsZU1hcCkgaWYgKG1vZC5wcm9taXNlICYmICFtb2QuZXZhbHVhdGVkKSBwcm9taXNlcy5wdXNoKG1vZC5wcm9taXNlKTtcblx0aWYgKCFwcm9taXNlcy5sZW5ndGggJiYgIXJlc29sdmluZ0NvdW50KSByZXR1cm47XG5cdGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChwcm9taXNlcyk7XG5cdGF3YWl0IHdhaXRGb3JJbXBvcnRzVG9SZXNvbHZlKCk7XG59XG5cbmV4cG9ydCB7IEVudmlyb25tZW50VGVhcmRvd25FcnJvciBhcyBFLCBnZXRTYWZlV29ya2VyU3RhdGUgYXMgYSwgZ2V0V29ya2VyU3RhdGUgYXMgZywgaXNDaGlsZFByb2Nlc3MgYXMgaSwgcHJvdmlkZVdvcmtlclN0YXRlIGFzIHAsIHJlc2V0TW9kdWxlcyBhcyByLCB3YWl0Rm9ySW1wb3J0c1RvUmVzb2x2ZSBhcyB3IH07XG4iXSwieF9nb29nbGVfaWdub3JlTGlzdCI6WzBdLCJtYXBwaW5ncyI6Ijs7QUFFQSxNQUFNLG9CQUFvQjtBQUkxQixTQUFTLGlCQUFpQjtDQUV6QixNQUFNLGNBQWMsV0FBVztBQUMvQixLQUFJLENBQUMsWUFBYSxPQUFNLElBQUksTUFBTSw4Y0FBOGM7QUFDaGYsUUFBTzs7QUFlUixTQUFTLGlCQUFpQjtBQUN6QixRQUFPLE9BQU8sWUFBWSxlQUFlLENBQUMsQ0FBQyxRQUFROztBQUVwRCxTQUFTLGFBQWEsU0FBUyxhQUFhLE9BQU87Q0FDbEQsTUFBTSxZQUFZO0VBQ2pCO0VBQ0E7RUFDQTtFQUNBLEdBQUcsQ0FBQyxhQUFhLENBQUMsU0FBUyxHQUFHLEVBQUU7RUFDaEM7QUFDRCxTQUFRLGNBQWMsU0FBUyxNQUFNLFNBQVM7QUFDN0MsTUFBSSxVQUFVLE1BQU0sT0FBTyxHQUFHLEtBQUssS0FBSyxDQUFDLENBQUU7QUFDM0MsT0FBSyxVQUFVLEtBQUs7QUFDcEIsT0FBSyxVQUFVLEtBQUs7QUFDcEIsT0FBSyxZQUFZO0FBQ2pCLE9BQUssVUFBVSxPQUFPO0dBQ3JCOztBQUVILFNBQVMsZUFBZTtDQUN2QixNQUFNLEVBQUUsZUFBZSxlQUFlO0FBQ3RDLFFBQU8sSUFBSSxTQUFTLFlBQVksV0FBVyxTQUFTLEVBQUUsQ0FBQzs7QUFFeEQsZUFBZSwwQkFBMEI7QUFDeEMsT0FBTSxjQUFjO0NBQ3BCLE1BQU0sUUFBUSxnQkFBZ0I7Q0FDOUIsTUFBTSxXQUFXLEVBQUU7Q0FDbkIsTUFBTSxpQkFBaUIsTUFBTSxpQkFBaUI7QUFDOUMsTUFBSyxNQUFNLENBQUMsR0FBRyxRQUFRLE1BQU0saUJBQWlCLGNBQWUsS0FBSSxJQUFJLFdBQVcsQ0FBQyxJQUFJLFVBQVcsVUFBUyxLQUFLLElBQUksUUFBUTtBQUMxSCxLQUFJLENBQUMsU0FBUyxVQUFVLENBQUMsZUFBZ0I7QUFDekMsT0FBTSxRQUFRLFdBQVcsU0FBUztBQUNsQyxPQUFNLHlCQUF5QiJ9
@@ -1,28 +0,0 @@
1
- import "../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js";
2
- import "../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js";
3
- import "../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js";
4
- import "../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js";
5
- import "../../../../pathe@2.0.3/node_modules/pathe/dist/index.js";
6
- import "../../../../@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/chunk-artifact.js";
7
- import "../../../../@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/index.js";
8
- import "../../../../@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/utils.js";
9
- import "./chunks/utils.BX5Fg8C4.js";
10
- import "./chunks/benchmark.CX_oY03V.js";
11
- import "../../../../@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js";
12
- import "../../../../chai@6.2.2/node_modules/chai/index.js";
13
- import "../../../../@vitest_expect@4.1.2/node_modules/@vitest/expect/dist/index.js";
14
- import "../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js";
15
- import "../../../../@vitest_snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js";
16
- import "./chunks/_commonjsHelpers.D26ty3Ew.js";
17
- import "./chunks/index.Chj8NDwU.js";
18
- import "./chunks/rpc.MzXet3jl.js";
19
- import "./chunks/test.p_J6dB8a.js";
20
- import "../../../../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";
21
- import "./chunks/evaluatedModules.Dg1zASAC.js";
22
- import { require_dist } from "../../../../expect-type@1.3.0/node_modules/expect-type/dist/index.js";
23
- import "./chunks/index.DOa3dzoN.js";
24
- require_dist();
25
- //#endregion
26
- export {};
27
-
28
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzLy5wbnBtL3ZpdGVzdEA0LjEuMl9Ab3BlbnRlbGVtZXRyeSthcGlAMS45LjBfQHR5cGVzK25vZGVAMjUuMC43X3ZpdGVAOC4wLjNfQGVtbmFwaStjb3JlQDEuOS4yX19iYjMxMDg3Mjc4Zjk3YTM5YjMxYjkyMDEwYmVhYjk4MC9ub2RlX21vZHVsZXMvdml0ZXN0L2Rpc3QvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgTiBhcyBCZW5jaG1hcmtSdW5uZXIsIFQgYXMgVGVzdFJ1bm5lciwgYSBhcyBhc3NlcnQsIGMgYXMgY3JlYXRlRXhwZWN0LCBnIGFzIGV4cGVjdCwgaSBhcyBpbmplY3QsIHMgYXMgc2hvdWxkLCB2IGFzIHZpLCBiIGFzIHZpdGVzdCB9IGZyb20gJy4vY2h1bmtzL3Rlc3QucF9KNmRCOGEuanMnO1xuZXhwb3J0IHsgYiBhcyBiZW5jaCB9IGZyb20gJy4vY2h1bmtzL2JlbmNobWFyay5DWF9vWTAzVi5qcyc7XG5leHBvcnQgeyBWIGFzIEV2YWx1YXRlZE1vZHVsZXMgfSBmcm9tICcuL2NodW5rcy9ldmFsdWF0ZWRNb2R1bGVzLkRnMXpBU0FDLmpzJztcbmV4cG9ydCB7IGEgYXMgYXNzZXJ0VHlwZSB9IGZyb20gJy4vY2h1bmtzL2luZGV4LkRPYTNkem9OLmpzJztcbmV4cG9ydCB7IGV4cGVjdFR5cGVPZiB9IGZyb20gJ2V4cGVjdC10eXBlJztcbmV4cG9ydCB7IGFmdGVyQWxsLCBhZnRlckVhY2gsIGFyb3VuZEFsbCwgYXJvdW5kRWFjaCwgYmVmb3JlQWxsLCBiZWZvcmVFYWNoLCBkZXNjcmliZSwgaXQsIG9uVGVzdEZhaWxlZCwgb25UZXN0RmluaXNoZWQsIHJlY29yZEFydGlmYWN0LCBzdWl0ZSwgdGVzdCB9IGZyb20gJ0B2aXRlc3QvcnVubmVyJztcbmV4cG9ydCB7IGNoYWkgfSBmcm9tICdAdml0ZXN0L2V4cGVjdCc7XG5pbXBvcnQgJ0B2aXRlc3QvdXRpbHMvaGVscGVycyc7XG5pbXBvcnQgJ0B2aXRlc3QvdXRpbHMvdGltZXJzJztcbmltcG9ydCAnLi9jaHVua3MvdXRpbHMuQlg1Rmc4QzQuanMnO1xuaW1wb3J0ICdAdml0ZXN0L3J1bm5lci91dGlscyc7XG5pbXBvcnQgJ0B2aXRlc3QvdXRpbHMvZXJyb3InO1xuaW1wb3J0ICdwYXRoZSc7XG5pbXBvcnQgJ0B2aXRlc3Qvc25hcHNob3QnO1xuaW1wb3J0ICdAdml0ZXN0L3NweSc7XG5pbXBvcnQgJ0B2aXRlc3QvdXRpbHMvb2Zmc2V0JztcbmltcG9ydCAnQHZpdGVzdC91dGlscy9zb3VyY2UtbWFwJztcbmltcG9ydCAnLi9jaHVua3MvX2NvbW1vbmpzSGVscGVycy5EMjZ0eTNFdy5qcyc7XG5pbXBvcnQgJy4vY2h1bmtzL3JwYy5NelhldDNqbC5qcyc7XG5pbXBvcnQgJy4vY2h1bmtzL2luZGV4LkNoajhORHdVLmpzJztcbmltcG9ydCAndml0ZS9tb2R1bGUtcnVubmVyJztcbiJdLCJ4X2dvb2dsZV9pZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiIn0=
@@ -1,196 +0,0 @@
1
- import "./_virtual/_rolldown/runtime.js";
2
- import { CachePresets, defineConfig } from "sonamu";
3
- import path from "path";
4
- import { getConsoleSink } from "@logtape/logtape";
5
- import { getPrettyFormatter } from "@logtape/pretty";
6
- import dotenv from "dotenv";
7
- import { drivers, store } from "sonamu/cache";
8
- import { drivers as drivers$1 } from "sonamu/storage";
9
- //#region src/sonamu.config.ts
10
- dotenv.config({ path: path.join(import.meta.dirname, "../.env") });
11
- const host = process.env.HOST ?? "localhost";
12
- const port = Number(process.env.PORT ?? 44900);
13
- var sonamu_config_default = defineConfig({
14
- projectName: process.env.PROJECT_NAME ?? "SonamuProject",
15
- database: {
16
- name: process.env.QGRID_DB_NAME ?? "qgrid",
17
- defaultOptions: { connection: {
18
- host: process.env.QGRID_DB_HOST ?? "localhost",
19
- port: Number(process.env.QGRID_DB_PORT ?? 44901),
20
- user: process.env.QGRID_DB_USER ?? "postgres",
21
- password: process.env.QGRID_DB_PASSWORD ?? "postgres"
22
- } },
23
- environments: {
24
- production: { connection: {
25
- host: process.env.DEV0_DB_HOST,
26
- port: Number(process.env.DEV0_DB_PORT),
27
- database: process.env.DATABASE_NAME,
28
- user: process.env.DEV0_DB_USER,
29
- password: process.env.DEV0_DB_PASSWORD
30
- } },
31
- fixture: { connection: {
32
- host: process.env.DEV0_DB_HOST,
33
- port: Number(process.env.DEV0_DB_PORT),
34
- database: process.env.DATABASE_NAME,
35
- user: process.env.DEV0_DB_USER,
36
- password: process.env.DEV0_DB_PASSWORD
37
- } }
38
- }
39
- },
40
- api: {
41
- dir: "api",
42
- timezone: "Asia/Seoul",
43
- route: { prefix: "/api" }
44
- },
45
- i18n: {
46
- defaultLocale: "ko",
47
- supportedLocales: ["ko", "en"]
48
- },
49
- sync: { targets: ["web"] },
50
- slackConfirm: process.env.SLACK_BOT_TOKEN && process.env.SLACK_CHANNEL_ID ? {
51
- targets: ["development_master", "production_master"],
52
- botToken: process.env.SLACK_BOT_TOKEN ?? "",
53
- channelId: process.env.SLACK_CHANNEL_ID ?? ""
54
- } : void 0,
55
- test: {
56
- parallel: true,
57
- maxWorkers: 4,
58
- devRunner: { enabled: true }
59
- },
60
- logging: {
61
- sinks: { console: getConsoleSink({ formatter: getPrettyFormatter({
62
- timestamp: "time",
63
- categoryWidth: 20,
64
- categoryTruncate: "middle"
65
- }) }) },
66
- loggers: [{
67
- category: ["sonamu"],
68
- sinks: ["console"],
69
- lowestLevel: process.env.NODE_ENV === "test" ? "warning" : "debug"
70
- }]
71
- },
72
- server: {
73
- listen: {
74
- port,
75
- host
76
- },
77
- plugins: {
78
- formbody: true,
79
- qs: true,
80
- multipart: { limits: { fileSize: 1024 * 1024 * 30 } },
81
- static: {
82
- root: path.join(import.meta.dirname, "/../", "public"),
83
- prefix: "/api/public"
84
- },
85
- custom: (server) => {
86
- server.get("/callback", async (request, reply) => {
87
- const { code, state } = request.query;
88
- if (!code || !state) return reply.redirect("/?oauth=error&reason=missing_params");
89
- try {
90
- const { QgridFrame } = await import("./application/qgrid/qgrid.frame.js");
91
- await QgridFrame.handleOAuthCallback(code, state, reply);
92
- } catch (e) {
93
- return reply.redirect(`/?oauth=error&reason=${encodeURIComponent(e.message)}`);
94
- }
95
- });
96
- }
97
- },
98
- apiConfig: {
99
- contextProvider: (defaultContext, request) => {
100
- return {
101
- ...defaultContext,
102
- ip: request.ip,
103
- body: request.body
104
- };
105
- },
106
- guardHandler: (_guard, _request, _api) => {
107
- if (_guard === "user") console.log("user guard");
108
- console.log("NOTHING YET");
109
- },
110
- cacheControlHandler: (req) => {
111
- switch (req.type) {
112
- case "assets":
113
- if (req.path.match(/-[a-f0-9]+\./)) return CachePresets.immutable;
114
- return CachePresets.longLived;
115
- case "api":
116
- if (req.method === "GET") {
117
- if (req.path.startsWith("/api/static-data")) return CachePresets.shortLived;
118
- if (req.path.startsWith("/api/terms")) return CachePresets.mediumLived;
119
- }
120
- return CachePresets.noCache;
121
- case "ssr": return CachePresets.ssr;
122
- case "csr": return CachePresets.shortLived;
123
- }
124
- }
125
- },
126
- storage: { drivers: {
127
- fs: drivers$1.fs({
128
- location: path.join(import.meta.dirname, "/../public/uploaded"),
129
- visibility: "public",
130
- urlBuilder: {
131
- async generateURL(key) {
132
- return `/api/public/uploaded/${key}`;
133
- },
134
- async generateSignedURL(key) {
135
- return `/api/public/uploaded/${key}`;
136
- }
137
- }
138
- }),
139
- s3: drivers$1.s3({
140
- credentials: {
141
- accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? "",
142
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? ""
143
- },
144
- region: process.env.S3_REGION ?? "ap-northeast-2",
145
- bucket: process.env.S3_BUCKET ?? "sonamu_default_bucket",
146
- visibility: "private"
147
- })
148
- } },
149
- cache: {
150
- default: "main",
151
- stores: { main: store().useL1Layer(drivers.memory({ maxSize: "50mb" })) },
152
- ttl: "5m",
153
- prefix: ""
154
- },
155
- lifecycle: {
156
- onStart: async () => {
157
- try {
158
- const { TokenModel } = await import("./application/token/token.model.js");
159
- const knex = TokenModel.getDB("w");
160
- const migrationsDir = path.join(import.meta.dirname, "../src/migrations");
161
- const [batch, log] = await knex.migrate.latest({ directory: migrationsDir });
162
- if (log.length > 0) {
163
- console.log(`✓ Migration: ${log.length} applied (batch ${batch})`);
164
- log.forEach((name) => console.log(` ✓ ${name}`));
165
- }
166
- } catch (e) {
167
- console.warn(`⚠ Migration skipped: ${e.message}`);
168
- }
169
- const { initPool } = await import("./application/qgrid/pool.js");
170
- try {
171
- const { TokenModel } = await import("./application/token/token.model.js");
172
- const pool = initPool((await TokenModel.findActive("A")).map((e) => e.token));
173
- console.log(`🌲 Server listening on http://${host}:${port} (${pool.workers.size} tokens loaded)`);
174
- } catch (e) {
175
- console.warn(`⚠ Pool init failed: ${e.message}`);
176
- initPool([]);
177
- console.log(`🌲 Server listening on http://${host}:${port} (no tokens)`);
178
- }
179
- },
180
- onShutdown: () => {
181
- console.log("graceful shutdown");
182
- },
183
- onError: (error, _request, reply) => {
184
- console.error(error);
185
- reply.status(500).send({
186
- name: error.name,
187
- message: error.message
188
- });
189
- }
190
- }
191
- }
192
- });
193
- //#endregion
194
- export { sonamu_config_default as default };
195
-
196
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29uYW11LmNvbmZpZy5qcyIsIm5hbWVzIjpbImRyaXZlcnMiLCJjYWNoZURyaXZlcnMiXSwic291cmNlcyI6WyIuLi9zcmMvc29uYW11LmNvbmZpZy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG5pbXBvcnQgeyBnZXRDb25zb2xlU2luayB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5pbXBvcnQgeyBnZXRQcmV0dHlGb3JtYXR0ZXIgfSBmcm9tIFwiQGxvZ3RhcGUvcHJldHR5XCI7XG5pbXBvcnQgZG90ZW52IGZyb20gXCJkb3RlbnZcIjtcbmltcG9ydCB7IENhY2hlUHJlc2V0cywgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInNvbmFtdVwiO1xuaW1wb3J0IHsgZHJpdmVycyBhcyBjYWNoZURyaXZlcnMsIHN0b3JlIH0gZnJvbSBcInNvbmFtdS9jYWNoZVwiO1xuaW1wb3J0IHsgZHJpdmVycyB9IGZyb20gXCJzb25hbXUvc3RvcmFnZVwiO1xuXG5kb3RlbnYuY29uZmlnKHsgcGF0aDogcGF0aC5qb2luKGltcG9ydC5tZXRhLmRpcm5hbWUsIFwiLi4vLmVudlwiKSB9KTtcblxuY29uc3QgaG9zdCA9IHByb2Nlc3MuZW52LkhPU1QgPz8gXCJsb2NhbGhvc3RcIjtcbmNvbnN0IHBvcnQgPSBOdW1iZXIocHJvY2Vzcy5lbnYuUE9SVCA/PyA0NDkwMCk7XG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIHByb2plY3ROYW1lOiBwcm9jZXNzLmVudi5QUk9KRUNUX05BTUUgPz8gXCJTb25hbXVQcm9qZWN0XCIsXG4gIGRhdGFiYXNlOiB7XG4gICAgbmFtZTogcHJvY2Vzcy5lbnYuUUdSSURfREJfTkFNRSA/PyBcInFncmlkXCIsXG4gICAgZGVmYXVsdE9wdGlvbnM6IHtcbiAgICAgIGNvbm5lY3Rpb246IHtcbiAgICAgICAgaG9zdDogcHJvY2Vzcy5lbnYuUUdSSURfREJfSE9TVCA/PyBcImxvY2FsaG9zdFwiLFxuICAgICAgICBwb3J0OiBOdW1iZXIocHJvY2Vzcy5lbnYuUUdSSURfREJfUE9SVCA/PyA0NDkwMSksXG4gICAgICAgIHVzZXI6IHByb2Nlc3MuZW52LlFHUklEX0RCX1VTRVIgPz8gXCJwb3N0Z3Jlc1wiLFxuICAgICAgICBwYXNzd29yZDogcHJvY2Vzcy5lbnYuUUdSSURfREJfUEFTU1dPUkQgPz8gXCJwb3N0Z3Jlc1wiLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGVudmlyb25tZW50czoge1xuICAgICAgcHJvZHVjdGlvbjoge1xuICAgICAgICBjb25uZWN0aW9uOiB7XG4gICAgICAgICAgaG9zdDogcHJvY2Vzcy5lbnYuREVWMF9EQl9IT1NULFxuICAgICAgICAgIHBvcnQ6IE51bWJlcihwcm9jZXNzLmVudi5ERVYwX0RCX1BPUlQpLFxuICAgICAgICAgIGRhdGFiYXNlOiBwcm9jZXNzLmVudi5EQVRBQkFTRV9OQU1FLFxuICAgICAgICAgIHVzZXI6IHByb2Nlc3MuZW52LkRFVjBfREJfVVNFUixcbiAgICAgICAgICBwYXNzd29yZDogcHJvY2Vzcy5lbnYuREVWMF9EQl9QQVNTV09SRCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBmaXh0dXJlOiB7XG4gICAgICAgIGNvbm5lY3Rpb246IHtcbiAgICAgICAgICBob3N0OiBwcm9jZXNzLmVudi5ERVYwX0RCX0hPU1QsXG4gICAgICAgICAgcG9ydDogTnVtYmVyKHByb2Nlc3MuZW52LkRFVjBfREJfUE9SVCksXG4gICAgICAgICAgZGF0YWJhc2U6IHByb2Nlc3MuZW52LkRBVEFCQVNFX05BTUUsXG4gICAgICAgICAgdXNlcjogcHJvY2Vzcy5lbnYuREVWMF9EQl9VU0VSLFxuICAgICAgICAgIHBhc3N3b3JkOiBwcm9jZXNzLmVudi5ERVYwX0RCX1BBU1NXT1JELFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9LFxuICBhcGk6IHtcbiAgICBkaXI6IFwiYXBpXCIsXG4gICAgdGltZXpvbmU6IFwiQXNpYS9TZW91bFwiLFxuICAgIHJvdXRlOiB7XG4gICAgICBwcmVmaXg6IFwiL2FwaVwiLFxuICAgIH0sXG4gIH0sXG4gIGkxOG46IHtcbiAgICBkZWZhdWx0TG9jYWxlOiBcImtvXCIsXG4gICAgc3VwcG9ydGVkTG9jYWxlczogW1wia29cIiwgXCJlblwiXSxcbiAgfSxcbiAgc3luYzoge1xuICAgIHRhcmdldHM6IFtcIndlYlwiXSxcbiAgfSxcbiAgc2xhY2tDb25maXJtOlxuICAgIHByb2Nlc3MuZW52LlNMQUNLX0JPVF9UT0tFTiAmJiBwcm9jZXNzLmVudi5TTEFDS19DSEFOTkVMX0lEXG4gICAgICA/IHtcbiAgICAgICAgICB0YXJnZXRzOiBbXCJkZXZlbG9wbWVudF9tYXN0ZXJcIiwgXCJwcm9kdWN0aW9uX21hc3RlclwiXSxcbiAgICAgICAgICBib3RUb2tlbjogcHJvY2Vzcy5lbnYuU0xBQ0tfQk9UX1RPS0VOID8/IFwiXCIsXG4gICAgICAgICAgY2hhbm5lbElkOiBwcm9jZXNzLmVudi5TTEFDS19DSEFOTkVMX0lEID8/IFwiXCIsXG4gICAgICAgIH1cbiAgICAgIDogdW5kZWZpbmVkLFxuICB0ZXN0OiB7XG4gICAgcGFyYWxsZWw6IHRydWUsXG4gICAgbWF4V29ya2VyczogNCxcbiAgICBkZXZSdW5uZXI6IHsgZW5hYmxlZDogdHJ1ZSB9LFxuICB9LFxuICBsb2dnaW5nOiB7XG4gICAgc2lua3M6IHtcbiAgICAgIGNvbnNvbGU6IGdldENvbnNvbGVTaW5rKHtcbiAgICAgICAgZm9ybWF0dGVyOiBnZXRQcmV0dHlGb3JtYXR0ZXIoe1xuICAgICAgICAgIHRpbWVzdGFtcDogXCJ0aW1lXCIsXG4gICAgICAgICAgY2F0ZWdvcnlXaWR0aDogMjAsXG4gICAgICAgICAgY2F0ZWdvcnlUcnVuY2F0ZTogXCJtaWRkbGVcIixcbiAgICAgICAgfSksXG4gICAgICB9KSxcbiAgICB9LFxuICAgIGxvZ2dlcnM6IFtcbiAgICAgIHtcbiAgICAgICAgY2F0ZWdvcnk6IFtcInNvbmFtdVwiXSxcbiAgICAgICAgc2lua3M6IFtcImNvbnNvbGVcIl0sXG4gICAgICAgIGxvd2VzdExldmVsOiBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJ0ZXN0XCIgPyBcIndhcm5pbmdcIiA6IFwiZGVidWdcIixcbiAgICAgIH0sXG4gICAgXSxcbiAgfSxcbiAgc2VydmVyOiB7XG4gICAgbGlzdGVuOiB7IHBvcnQsIGhvc3QgfSxcbiAgICBwbHVnaW5zOiB7XG4gICAgICBmb3JtYm9keTogdHJ1ZSxcbiAgICAgIHFzOiB0cnVlLFxuICAgICAgbXVsdGlwYXJ0OiB7IGxpbWl0czogeyBmaWxlU2l6ZTogMTAyNCAqIDEwMjQgKiAzMCB9IH0sXG4gICAgICBzdGF0aWM6IHtcbiAgICAgICAgcm9vdDogcGF0aC5qb2luKGltcG9ydC5tZXRhLmRpcm5hbWUsIFwiLy4uL1wiLCBcInB1YmxpY1wiKSxcbiAgICAgICAgcHJlZml4OiBcIi9hcGkvcHVibGljXCIsXG4gICAgICB9LFxuICAgICAgY3VzdG9tOiAoc2VydmVyKSA9PiB7XG4gICAgICAgIC8vIE9BdXRoIOy9nOuwsSDigJQgQW50aHJvcGlj7J20IC9jYWxsYmFja+ycvOuhnCDrpqzri6TsnbTroIntirhcbiAgICAgICAgc2VydmVyLmdldChcIi9jYWxsYmFja1wiLCBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGNvZGUsIHN0YXRlIH0gPSByZXF1ZXN0LnF1ZXJ5IGFzIHsgY29kZT86IHN0cmluZzsgc3RhdGU/OiBzdHJpbmcgfTtcbiAgICAgICAgICBpZiAoIWNvZGUgfHwgIXN0YXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVwbHkucmVkaXJlY3QoXCIvP29hdXRoPWVycm9yJnJlYXNvbj1taXNzaW5nX3BhcmFtc1wiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gRnJhbWXsnZggb2F1dGhDYWxsYmFja+ycvOuhnCDsnITsnoRcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgeyBRZ3JpZEZyYW1lIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2FwcGxpY2F0aW9uL3FncmlkL3FncmlkLmZyYW1lXCIpO1xuICAgICAgICAgICAgYXdhaXQgUWdyaWRGcmFtZS5oYW5kbGVPQXV0aENhbGxiYWNrKGNvZGUsIHN0YXRlLCByZXBseSk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlcGx5LnJlZGlyZWN0KFxuICAgICAgICAgICAgICBgLz9vYXV0aD1lcnJvciZyZWFzb249JHtlbmNvZGVVUklDb21wb25lbnQoKGUgYXMgRXJyb3IpLm1lc3NhZ2UpfWAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgIH0sXG4gICAgYXBpQ29uZmlnOiB7XG4gICAgICBjb250ZXh0UHJvdmlkZXI6IChkZWZhdWx0Q29udGV4dCwgcmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLmRlZmF1bHRDb250ZXh0LFxuICAgICAgICAgIGlwOiByZXF1ZXN0LmlwLFxuICAgICAgICAgIGJvZHk6IHJlcXVlc3QuYm9keSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBndWFyZEhhbmRsZXI6IChfZ3VhcmQsIF9yZXF1ZXN0LCBfYXBpKSA9PiB7XG4gICAgICAgIGlmIChfZ3VhcmQgPT09IFwidXNlclwiKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJ1c2VyIGd1YXJkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKFwiTk9USElORyBZRVRcIik7XG4gICAgICB9LFxuICAgICAgY2FjaGVDb250cm9sSGFuZGxlcjogKHJlcSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlcS50eXBlKSB7XG4gICAgICAgICAgY2FzZSBcImFzc2V0c1wiOlxuICAgICAgICAgICAgLy8gSGFzaCDtj6ztlajrkJwg7YyM7J28OiDsmIHqtawg7LqQ7IucXG4gICAgICAgICAgICBpZiAocmVxLnBhdGgubWF0Y2goLy1bYS1mMC05XStcXC4vKSkge1xuICAgICAgICAgICAgICByZXR1cm4gQ2FjaGVQcmVzZXRzLmltbXV0YWJsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBDYWNoZVByZXNldHMubG9uZ0xpdmVkO1xuXG4gICAgICAgICAgY2FzZSBcImFwaVwiOlxuICAgICAgICAgICAgLy8gR0VUIOyalOyyreunjCDsupDsi7Eg6rOg66CkXG4gICAgICAgICAgICBpZiAocmVxLm1ldGhvZCA9PT0gXCJHRVRcIikge1xuICAgICAgICAgICAgICAvLyDtirnsoJUg6rK966Gc64qUIOynp+ydgCDsupDsi5xcbiAgICAgICAgICAgICAgaWYgKHJlcS5wYXRoLnN0YXJ0c1dpdGgoXCIvYXBpL3N0YXRpYy1kYXRhXCIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIENhY2hlUHJlc2V0cy5zaG9ydExpdmVkO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChyZXEucGF0aC5zdGFydHNXaXRoKFwiL2FwaS90ZXJtc1wiKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBDYWNoZVByZXNldHMubWVkaXVtTGl2ZWQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIOq4sOuzuDog7LqQ7IucIOyXhuydjFxuICAgICAgICAgICAgcmV0dXJuIENhY2hlUHJlc2V0cy5ub0NhY2hlO1xuXG4gICAgICAgICAgY2FzZSBcInNzclwiOlxuICAgICAgICAgICAgLy8gU1NSIO2OmOydtOyngDogMTDstIgg7LqQ7IucXG4gICAgICAgICAgICByZXR1cm4gQ2FjaGVQcmVzZXRzLnNzcjtcblxuICAgICAgICAgIGNhc2UgXCJjc3JcIjpcbiAgICAgICAgICAgIC8vIENTUiBmYWxsYmFjayAoaW5kZXguaHRtbCk6IDHrtoQg7LqQ7IucXG4gICAgICAgICAgICByZXR1cm4gQ2FjaGVQcmVzZXRzLnNob3J0TGl2ZWQ7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICBzdG9yYWdlOiB7XG4gICAgICBkcml2ZXJzOiB7XG4gICAgICAgIGZzOiBkcml2ZXJzLmZzKHtcbiAgICAgICAgICBsb2NhdGlvbjogcGF0aC5qb2luKGltcG9ydC5tZXRhLmRpcm5hbWUsIFwiLy4uL3B1YmxpYy91cGxvYWRlZFwiKSxcbiAgICAgICAgICB2aXNpYmlsaXR5OiBcInB1YmxpY1wiLFxuICAgICAgICAgIHVybEJ1aWxkZXI6IHtcbiAgICAgICAgICAgIGFzeW5jIGdlbmVyYXRlVVJMKGtleSkge1xuICAgICAgICAgICAgICByZXR1cm4gYC9hcGkvcHVibGljL3VwbG9hZGVkLyR7a2V5fWA7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYXN5bmMgZ2VuZXJhdGVTaWduZWRVUkwoa2V5KSB7XG4gICAgICAgICAgICAgIHJldHVybiBgL2FwaS9wdWJsaWMvdXBsb2FkZWQvJHtrZXl9YDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICAgIHMzOiBkcml2ZXJzLnMzKHtcbiAgICAgICAgICBjcmVkZW50aWFsczoge1xuICAgICAgICAgICAgYWNjZXNzS2V5SWQ6IHByb2Nlc3MuZW52LkFXU19BQ0NFU1NfS0VZX0lEID8/IFwiXCIsXG4gICAgICAgICAgICBzZWNyZXRBY2Nlc3NLZXk6IHByb2Nlc3MuZW52LkFXU19TRUNSRVRfQUNDRVNTX0tFWSA/PyBcIlwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVnaW9uOiBwcm9jZXNzLmVudi5TM19SRUdJT04gPz8gXCJhcC1ub3J0aGVhc3QtMlwiLFxuICAgICAgICAgIGJ1Y2tldDogcHJvY2Vzcy5lbnYuUzNfQlVDS0VUID8/IFwic29uYW11X2RlZmF1bHRfYnVja2V0XCIsXG4gICAgICAgICAgdmlzaWJpbGl0eTogXCJwcml2YXRlXCIsXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGNhY2hlOiB7XG4gICAgICBkZWZhdWx0OiBcIm1haW5cIixcbiAgICAgIHN0b3Jlczoge1xuICAgICAgICBtYWluOiBzdG9yZSgpLnVzZUwxTGF5ZXIoY2FjaGVEcml2ZXJzLm1lbW9yeSh7IG1heFNpemU6IFwiNTBtYlwiIH0pKSxcbiAgICAgIH0sXG4gICAgICB0dGw6IFwiNW1cIixcbiAgICAgIHByZWZpeDogXCJcIixcbiAgICB9LFxuICAgIGxpZmVjeWNsZToge1xuICAgICAgb25TdGFydDogYXN5bmMgKCkgPT4ge1xuICAgICAgICAvLyBEQiDrp4jsnbTqt7jroIjsnbTshZgg7J6Q64+ZIOyLpO2WiSAo7YWM7J2067iUIOyXhuycvOuptCDsg53shLEpXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBUb2tlbk1vZGVsIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2FwcGxpY2F0aW9uL3Rva2VuL3Rva2VuLm1vZGVsXCIpO1xuICAgICAgICAgIGNvbnN0IGtuZXggPSBUb2tlbk1vZGVsLmdldERCKFwid1wiKTtcbiAgICAgICAgICBjb25zdCBtaWdyYXRpb25zRGlyID0gcGF0aC5qb2luKGltcG9ydC5tZXRhLmRpcm5hbWUsIFwiLi4vc3JjL21pZ3JhdGlvbnNcIik7XG4gICAgICAgICAgY29uc3QgW2JhdGNoLCBsb2ddID0gYXdhaXQga25leC5taWdyYXRlLmxhdGVzdCh7XG4gICAgICAgICAgICBkaXJlY3Rvcnk6IG1pZ3JhdGlvbnNEaXIsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKGxvZy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhg4pyTIE1pZ3JhdGlvbjogJHtsb2cubGVuZ3RofSBhcHBsaWVkIChiYXRjaCAke2JhdGNofSlgKTtcbiAgICAgICAgICAgIGxvZy5mb3JFYWNoKChuYW1lOiBzdHJpbmcpID0+IGNvbnNvbGUubG9nKGAgIOKckyAke25hbWV9YCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUud2Fybihg4pqgIE1pZ3JhdGlvbiBza2lwcGVkOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUG9vbCDstIjquLDtmZRcbiAgICAgICAgY29uc3QgeyBpbml0UG9vbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9hcHBsaWNhdGlvbi9xZ3JpZC9wb29sXCIpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHsgVG9rZW5Nb2RlbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiKTtcbiAgICAgICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kQWN0aXZlKFwiQVwiKTtcbiAgICAgICAgICBjb25zdCB0b2tlbnMgPSBlbnRyaWVzLm1hcCgoZSkgPT4gZS50b2tlbik7XG4gICAgICAgICAgY29uc3QgcG9vbCA9IGluaXRQb29sKHRva2Vucyk7XG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICBg8J+MsiBTZXJ2ZXIgbGlzdGVuaW5nIG9uIGh0dHA6Ly8ke2hvc3R9OiR7cG9ydH0gKCR7cG9vbC53b3JrZXJzLnNpemV9IHRva2VucyBsb2FkZWQpYCxcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKGDimqAgUG9vbCBpbml0IGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgICAgICBpbml0UG9vbChbXSk7XG4gICAgICAgICAgY29uc29sZS5sb2coYPCfjLIgU2VydmVyIGxpc3RlbmluZyBvbiBodHRwOi8vJHtob3N0fToke3BvcnR9IChubyB0b2tlbnMpYCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBvblNodXRkb3duOiAoKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiZ3JhY2VmdWwgc2h1dGRvd25cIik7XG4gICAgICB9LFxuICAgICAgb25FcnJvcjogKGVycm9yLCBfcmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgIHJlcGx5LnN0YXR1cyg1MDApLnNlbmQoe1xuICAgICAgICAgIG5hbWU6IGVycm9yLm5hbWUsXG4gICAgICAgICAgbWVzc2FnZTogZXJyb3IubWVzc2FnZSxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgIH0sXG4gIH0sXG59KTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBU0EsT0FBTyxPQUFPLEVBQUUsTUFBTSxLQUFLLEtBQUssT0FBTyxLQUFLLFNBQVMsVUFBVSxFQUFFLENBQUM7QUFFbEUsTUFBTSxPQUFPLFFBQVEsSUFBSSxRQUFRO0FBQ2pDLE1BQU0sT0FBTyxPQUFPLFFBQVEsSUFBSSxRQUFRLE1BQU07QUFFOUMsSUFBQSx3QkFBZSxhQUFhO0NBQzFCLGFBQWEsUUFBUSxJQUFJLGdCQUFnQjtDQUN6QyxVQUFVO0VBQ1IsTUFBTSxRQUFRLElBQUksaUJBQWlCO0VBQ25DLGdCQUFnQixFQUNkLFlBQVk7R0FDVixNQUFNLFFBQVEsSUFBSSxpQkFBaUI7R0FDbkMsTUFBTSxPQUFPLFFBQVEsSUFBSSxpQkFBaUIsTUFBTTtHQUNoRCxNQUFNLFFBQVEsSUFBSSxpQkFBaUI7R0FDbkMsVUFBVSxRQUFRLElBQUkscUJBQXFCO0dBQzVDLEVBQ0Y7RUFDRCxjQUFjO0dBQ1osWUFBWSxFQUNWLFlBQVk7SUFDVixNQUFNLFFBQVEsSUFBSTtJQUNsQixNQUFNLE9BQU8sUUFBUSxJQUFJLGFBQWE7SUFDdEMsVUFBVSxRQUFRLElBQUk7SUFDdEIsTUFBTSxRQUFRLElBQUk7SUFDbEIsVUFBVSxRQUFRLElBQUk7SUFDdkIsRUFDRjtHQUNELFNBQVMsRUFDUCxZQUFZO0lBQ1YsTUFBTSxRQUFRLElBQUk7SUFDbEIsTUFBTSxPQUFPLFFBQVEsSUFBSSxhQUFhO0lBQ3RDLFVBQVUsUUFBUSxJQUFJO0lBQ3RCLE1BQU0sUUFBUSxJQUFJO0lBQ2xCLFVBQVUsUUFBUSxJQUFJO0lBQ3ZCLEVBQ0Y7R0FDRjtFQUNGO0NBQ0QsS0FBSztFQUNILEtBQUs7RUFDTCxVQUFV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
@@ -1,8 +0,0 @@
1
- import "../_virtual/_rolldown/runtime.js";
2
- import { createFixtureLoader } from "sonamu/test";
3
- //#region src/testing/fixture.ts
4
- const loadFixtures = createFixtureLoader({ fixture01: async () => {} });
5
- //#endregion
6
- export { loadFixtures };
7
-
8
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZS5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdGluZy9maXh0dXJlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZUZpeHR1cmVMb2FkZXIgfSBmcm9tIFwic29uYW11L3Rlc3RcIjtcblxuZXhwb3J0IGNvbnN0IGxvYWRGaXh0dXJlcyA9IGNyZWF0ZUZpeHR1cmVMb2FkZXIoe1xuICAvLyBEZWZpbmUgeW91ciBmaXh0dXJlcy4uLlxuICBmaXh0dXJlMDE6IGFzeW5jICgpID0+IHt9LFxufSk7XG4iXSwibWFwcGluZ3MiOiI7OztBQUVBLE1BQWEsZUFBZSxvQkFBb0IsRUFFOUMsV0FBVyxZQUFZLElBQ3hCLENBQUMifQ==
@@ -1,9 +0,0 @@
1
- import "../_virtual/_rolldown/runtime.js";
2
- import dotenv from "dotenv";
3
- import { setup } from "sonamu/test";
4
- //#region src/testing/global.ts
5
- dotenv.config();
6
- //#endregion
7
- export { setup };
8
-
9
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2xvYmFsLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0aW5nL2dsb2JhbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZG90ZW52IGZyb20gXCJkb3RlbnZcIjtcblxuZG90ZW52LmNvbmZpZygpO1xuXG4vLyBzb25hbXUuY29uZmlnLnRz7J2YIHRlc3Qg7ISk7KCV7J2EIOq4sOuwmOycvOuhnCDrs5HroKwg7YWM7Iqk7Yq4IO2ZmOqyveydhCDqtazshLHtlanri4jri6QuXG5leHBvcnQgeyBzZXR1cCB9IGZyb20gXCJzb25hbXUvdGVzdFwiO1xuIl0sIm1hcHBpbmdzIjoiOzs7O0FBRUEsT0FBTyxRQUFRIn0=
@@ -1,17 +0,0 @@
1
- import "../_virtual/_rolldown/runtime.js";
2
- import { vi } from "../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";
3
- import "../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";
4
- //#region src/testing/setup-mocks.ts
5
- vi.mock("fs/promises", async (importOriginal) => {
6
- const actual = await importOriginal();
7
- return {
8
- ...actual,
9
- access: vi.fn((path, mode) => {
10
- return actual.access(path, mode);
11
- })
12
- };
13
- });
14
- //#endregion
15
- export {};
16
-
17
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0dXAtbW9ja3MuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3Rpbmcvc2V0dXAtbW9ja3MudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBQYXRoTGlrZSB9IGZyb20gXCJmc1wiO1xuXG4vLyBpbXBvcnQgeyBOYWl0ZSB9IGZyb20gXCJzb25hbXVcIjtcbmltcG9ydCB7IHZpIH0gZnJvbSBcInZpdGVzdFwiO1xuXG4vLyBHbG9iYWxNb2NrOiBmcy9wcm9taXNlcyAo7IKs7JqpIOyYiOyLnCAtIO2VhOyalOyLnCDtmZzshLHtmZQpXG52aS5tb2NrKFwiZnMvcHJvbWlzZXNcIiwgYXN5bmMgKGltcG9ydE9yaWdpbmFsKSA9PiB7XG4gIGNvbnN0IGFjdHVhbCA9IChhd2FpdCBpbXBvcnRPcmlnaW5hbCgpKSBhcyB0eXBlb2YgaW1wb3J0KFwiZnMvcHJvbWlzZXNcIik7XG4gIHJldHVybiB7XG4gICAgLi4uYWN0dWFsLFxuICAgIGFjY2VzczogdmkuZm4oKHBhdGg6IFBhdGhMaWtlLCBtb2RlPzogbnVtYmVyKSA9PiB7XG4gICAgICAvLyBjb25zdCB2ZnMgPSBOYWl0ZS5nZXQoXCJtb2NrOmZzL3Byb21pc2VzOnZpcnR1YWxGaWxlU3lzdGVtXCIpLnJlc3VsdCgpO1xuICAgICAgLy8gaWYgKHZmcy5zb21lKCh2KSA9PiB2ID09PSBwYXRoKSkge1xuICAgICAgLy8gICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAvLyB9XG5cbiAgICAgIHJldHVybiBhY3R1YWwuYWNjZXNzKHBhdGgsIG1vZGUpO1xuICAgIH0pLFxuICAgIC8vIG1rZGlyOiB2aS5mbihcbiAgICAvLyAgIGFzeW5jIChcbiAgICAvLyAgICAgcGF0aDogUGF0aExpa2UsXG4gICAgLy8gICAgIG9wdGlvbnM/OiBNYWtlRGlyZWN0b3J5T3B0aW9ucyB8IE1vZGUgfCBudWxsLFxuICAgIC8vICAgKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+ID0+IHtcbiAgICAvLyAgICAgLy8gTmFpdGUudChcImZzOm1rZGlyXCIsIHsgcGF0aCwgb3B0aW9ucyB9KTtcbiAgICAvLyAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSBcIm9iamVjdFwiICYmIG9wdGlvbnM/LnJlY3Vyc2l2ZSkge1xuICAgIC8vICAgICAgIHJldHVybiB0eXBlb2YgcGF0aCA9PT0gXCJzdHJpbmdcIiA/IHBhdGggOiBwYXRoLnRvU3RyaW5nKCk7XG4gICAgLy8gICAgIH1cbiAgICAvLyAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAvLyAgIH0sXG4gICAgLy8gKSxcbiAgICAvLyB3cml0ZUZpbGU6IHZpLmZuKChwYXRoOiBQYXRoTGlrZSB8IEZpbGVIYW5kbGUsIGRhdGE6IHN0cmluZyB8IEJ1ZmZlciB8IFVpbnQ4QXJyYXkpID0+IHtcbiAgICAvLyAgIGNvbnN0IGZpbGVQYXRoID0gdHlwZW9mIHBhdGggPT09IFwic3RyaW5nXCIgPyBwYXRoIDogcGF0aC50b1N0cmluZygpO1xuXG4gICAgLy8gICAvLyBOYWl0ZS50KGBmcy9wcm9taXNlczp3cml0ZUZpbGVgLCB7IHBhdGg6IGZpbGVQYXRoLCBkYXRhIH0pO1xuICAgIC8vIH0pLFxuICAgIC8vIHJtOiB2aS5mbihhc3luYyAocGF0aDogUGF0aExpa2UsIG9wdGlvbnM/OiBSbU9wdGlvbnMpID0+IHtcbiAgICAvLyAgIGNvbnN0IGZpbGVQYXRoID0gdHlwZW9mIHBhdGggPT09IFwic3RyaW5nXCIgPyBwYXRoIDogcGF0aC50b1N0cmluZygpO1xuXG4gICAgLy8gICAvLyBOYWl0ZS50KGBmcy9wcm9taXNlczpybWAsIHsgcGF0aDogZmlsZVBhdGgsIG9wdGlvbnMgfSk7XG4gICAgLy8gICAvLyDsi6TsoJwg7IKt7KCc7ZWY7KeAIOyViuqzoCDquLDroZ3rp4wg7ZWoXG4gICAgLy8gICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgLy8gfSksXG4gIH07XG59KTtcbiJdLCJtYXBwaW5ncyI6Ijs7OztBQU1BLEdBQUcsS0FBSyxlQUFlLE9BQU8sbUJBQW1CO0NBQy9DLE1BQU0sU0FBVSxNQUFNLGdCQUFnQjtBQUN0QyxRQUFPO0VBQ0wsR0FBRztFQUNILFFBQVEsR0FBRyxJQUFJLE1BQWdCLFNBQWtCO0FBTS9DLFVBQU8sT0FBTyxPQUFPLE1BQU0sS0FBSztJQUNoQztFQXlCSDtFQUNEIn0=
@@ -1,12 +0,0 @@
1
- import "../_virtual/_rolldown/runtime.js";
2
- //#region src/utils/subset-loaders.ts
3
- function getSubsetLoaders(subsets, subsetQueries) {
4
- return subsets.reduce((acc, subset) => {
5
- acc[subset] = subsetQueries[subset]?.loaders ?? [];
6
- return acc;
7
- }, {});
8
- }
9
- //#endregion
10
- export { getSubsetLoaders };
11
-
12
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Vic2V0LWxvYWRlcnMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3N1YnNldC1sb2FkZXJzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU3Vic2V0UXVlcnkgfSBmcm9tIFwic29uYW11XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdWJzZXRMb2FkZXJzKHN1YnNldHM6IHN0cmluZ1tdLCBzdWJzZXRRdWVyaWVzOiBSZWNvcmQ8c3RyaW5nLCBTdWJzZXRRdWVyeT4pIHtcbiAgcmV0dXJuIHN1YnNldHMucmVkdWNlKFxuICAgIChhY2MsIHN1YnNldCkgPT4ge1xuICAgICAgYWNjW3N1YnNldF0gPSBzdWJzZXRRdWVyaWVzW3N1YnNldF0/LmxvYWRlcnMgPz8gW107XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sXG4gICAge30gYXMgUmVjb3JkPHN0cmluZywgU3Vic2V0UXVlcnlbXCJsb2FkZXJzXCJdPixcbiAgKTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7QUFFQSxTQUFnQixpQkFBaUIsU0FBbUIsZUFBNEM7QUFDOUYsUUFBTyxRQUFRLFFBQ1osS0FBSyxXQUFXO0FBQ2YsTUFBSSxVQUFVLGNBQWMsU0FBUyxXQUFXLEVBQUU7QUFDbEQsU0FBTztJQUVULEVBQUUsQ0FDSCJ9
@@ -1,181 +0,0 @@
1
- /**
2
- * OAuth 유틸 — Claude Code 소스의 OAuth 플로우 그대로 재현
3
- */
4
- import { createHash, randomBytes } from "node:crypto";
5
-
6
- import type { UsageResponse } from "./qgrid.types";
7
-
8
- const CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
9
- const AUTHORIZE_URL = "https://claude.com/cai/oauth/authorize";
10
- const TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
11
-
12
- // login 시 사용 (authorize URL)
13
- const ALL_SCOPES = [
14
- "org:create_api_key",
15
- "user:profile",
16
- "user:inference",
17
- "user:sessions:claude_code",
18
- "user:mcp_servers",
19
- "user:file_upload",
20
- ];
21
-
22
- // refresh 시 사용 (org:create_api_key 제외)
23
- const REFRESH_SCOPES = [
24
- "user:profile",
25
- "user:inference",
26
- "user:sessions:claude_code",
27
- "user:mcp_servers",
28
- "user:file_upload",
29
- ];
30
-
31
- function base64URLEncode(buffer: Buffer): string {
32
- return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
33
- }
34
-
35
- export function generatePKCE(): { codeVerifier: string; codeChallenge: string; state: string } {
36
- const codeVerifier = base64URLEncode(randomBytes(32));
37
- const codeChallenge = base64URLEncode(createHash("sha256").update(codeVerifier).digest());
38
- const state = base64URLEncode(randomBytes(32));
39
- return { codeVerifier, codeChallenge, state };
40
- }
41
-
42
- export function buildAuthUrl(codeChallenge: string, state: string, redirectUri: string): string {
43
- const url = new URL(AUTHORIZE_URL);
44
- url.searchParams.append("code", "true");
45
- url.searchParams.append("client_id", CLIENT_ID);
46
- url.searchParams.append("response_type", "code");
47
- url.searchParams.append("redirect_uri", redirectUri);
48
- url.searchParams.append("scope", ALL_SCOPES.join(" "));
49
- url.searchParams.append("code_challenge", codeChallenge);
50
- url.searchParams.append("code_challenge_method", "S256");
51
- url.searchParams.append("state", state);
52
- return url.toString();
53
- }
54
-
55
- export type OAuthTokens = {
56
- accessToken: string;
57
- refreshToken: string;
58
- expiresAt: number;
59
- scope: string;
60
- accountUuid?: string;
61
- emailAddress?: string;
62
- };
63
-
64
- export async function exchangeCodeForTokens(
65
- code: string,
66
- codeVerifier: string,
67
- state: string,
68
- redirectUri: string,
69
- ): Promise<OAuthTokens> {
70
- const res = await fetch(TOKEN_URL, {
71
- method: "POST",
72
- headers: { "Content-Type": "application/json" },
73
- body: JSON.stringify({
74
- grant_type: "authorization_code",
75
- code,
76
- redirect_uri: redirectUri,
77
- client_id: CLIENT_ID,
78
- code_verifier: codeVerifier,
79
- state,
80
- }),
81
- });
82
- if (!res.ok) {
83
- const text = await res.text();
84
- throw new Error(`Token exchange failed (${res.status}): ${text}`);
85
- }
86
-
87
- const data = (await res.json()) as {
88
- access_token: string;
89
- refresh_token: string;
90
- expires_in: number;
91
- scope: string;
92
- account?: { uuid: string; email_address: string };
93
- };
94
-
95
- return {
96
- accessToken: data.access_token,
97
- refreshToken: data.refresh_token,
98
- expiresAt: Date.now() + data.expires_in * 1000,
99
- scope: data.scope,
100
- accountUuid: data.account?.uuid,
101
- emailAddress: data.account?.email_address,
102
- };
103
- }
104
-
105
- export async function refreshAccessToken(refreshToken: string): Promise<OAuthTokens> {
106
- const res = await fetch(TOKEN_URL, {
107
- method: "POST",
108
- headers: { "Content-Type": "application/json" },
109
- body: JSON.stringify({
110
- grant_type: "refresh_token",
111
- refresh_token: refreshToken,
112
- client_id: CLIENT_ID,
113
- scope: REFRESH_SCOPES.join(" "),
114
- }),
115
- });
116
- if (!res.ok) {
117
- const text = await res.text();
118
- throw new Error(`Token refresh failed (${res.status}): ${text}`);
119
- }
120
- const data = (await res.json()) as {
121
- access_token: string;
122
- refresh_token: string;
123
- expires_in: number;
124
- scope: string;
125
- };
126
-
127
- return {
128
- accessToken: data.access_token,
129
- refreshToken: data.refresh_token ?? refreshToken,
130
- expiresAt: Date.now() + data.expires_in * 1000,
131
- scope: data.scope,
132
- };
133
- }
134
-
135
- const usageCache: Record<string, { data: UsageResponse; cachedAt: number }> = {};
136
- const USAGE_API_CACHE_TTL = 60_000; // 1분
137
-
138
- export async function fetchUsage(accessToken: string): Promise<UsageResponse> {
139
- const cacheKey = accessToken.slice(-10);
140
- const cached = usageCache[cacheKey];
141
- if (cached && Date.now() - cached.cachedAt < USAGE_API_CACHE_TTL) {
142
- console.log(`[usage] cache hit: ${cacheKey}`);
143
- return cached.data;
144
- }
145
-
146
- const res = await fetch("https://api.anthropic.com/api/oauth/usage", {
147
- headers: {
148
- Authorization: `Bearer ${accessToken}`,
149
- "Content-Type": "application/json",
150
- "anthropic-beta": "oauth-2025-04-20",
151
- },
152
- signal: AbortSignal.timeout(5000),
153
- });
154
- if (!res.ok) {
155
- const text = await res.text();
156
-
157
- // 파싱 시도해서 에러 메시지 추출
158
- let errorMessage = `Error ${res.status}`;
159
- try {
160
- const parsed = JSON.parse(text);
161
- errorMessage = parsed.error?.message ?? errorMessage;
162
- } catch {
163
- // 파싱 안 되면 기본 메시지
164
- }
165
-
166
- console.warn(`[usage] ${res.status}: ${errorMessage}`);
167
-
168
- // 이전 성공 캐시 있으면 유지
169
- if (cached?.data && !cached.data.error) return cached.data;
170
-
171
- // 실패도 캐시 (반복 호출 방지)
172
- const errorResult = { error: errorMessage };
173
- usageCache[cacheKey] = { data: errorResult, cachedAt: Date.now() };
174
- return errorResult;
175
- }
176
-
177
- const data = (await res.json()) as UsageResponse;
178
- // cache invalidate
179
- usageCache[cacheKey] = { data, cachedAt: Date.now() };
180
- return data;
181
- }