@dooboostore/simple-boot-http-server 1.0.27 → 1.0.28

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 (49) hide show
  1. package/README.md +44 -9
  2. package/dist/cjs/SimpleBootHttpServer.js +15 -2
  3. package/dist/cjs/SimpleBootHttpServer.js.map +2 -2
  4. package/dist/cjs/decorators/MethodMapping.js.map +2 -2
  5. package/dist/cjs/models/RequestResponse.js +52 -0
  6. package/dist/cjs/models/RequestResponse.js.map +3 -3
  7. package/dist/cjs/proxy/RequestResponseInjectProxy.js +35 -0
  8. package/dist/cjs/proxy/RequestResponseInjectProxy.js.map +7 -0
  9. package/dist/cjs/proxy/SymbolIntentApiServiceProxy.js +1 -1
  10. package/dist/cjs/proxy/SymbolIntentApiServiceProxy.js.map +2 -2
  11. package/dist/cjs/proxy/index.js +3 -1
  12. package/dist/cjs/proxy/index.js.map +2 -2
  13. package/dist/cjs/resolvers/Resolver.js.map +1 -1
  14. package/dist/esm/SimpleBootHttpServer.js +16 -3
  15. package/dist/esm/SimpleBootHttpServer.js.map +2 -2
  16. package/dist/esm/decorators/MethodMapping.js.map +2 -2
  17. package/dist/esm/models/RequestResponse.js +52 -0
  18. package/dist/esm/models/RequestResponse.js.map +2 -2
  19. package/dist/esm/proxy/RequestResponseInjectProxy.js +12 -0
  20. package/dist/esm/proxy/RequestResponseInjectProxy.js.map +7 -0
  21. package/dist/esm/proxy/SymbolIntentApiServiceProxy.js +1 -1
  22. package/dist/esm/proxy/SymbolIntentApiServiceProxy.js.map +2 -2
  23. package/dist/esm/proxy/index.js +1 -0
  24. package/dist/esm/proxy/index.js.map +2 -2
  25. package/dist/esm-bundle/dooboostore-simple-boot-http-server.esm.js +295 -252
  26. package/dist/esm-bundle/dooboostore-simple-boot-http-server.esm.js.map +4 -4
  27. package/dist/types/SimpleBootHttpServer.d.ts.map +1 -1
  28. package/dist/types/decorators/MethodMapping.d.ts +13 -16
  29. package/dist/types/decorators/MethodMapping.d.ts.map +1 -1
  30. package/dist/types/models/RequestResponse.d.ts +9 -0
  31. package/dist/types/models/RequestResponse.d.ts.map +1 -1
  32. package/dist/types/proxy/RequestResponseInjectProxy.d.ts +22 -0
  33. package/dist/types/proxy/RequestResponseInjectProxy.d.ts.map +1 -0
  34. package/dist/types/proxy/index.d.ts +1 -0
  35. package/dist/types/proxy/index.d.ts.map +1 -1
  36. package/dist/types/resolvers/Resolver.d.ts +2 -1
  37. package/dist/types/resolvers/Resolver.d.ts.map +1 -1
  38. package/dist/umd-bundle/dooboostore-simple-boot-http-server.umd.js +295 -252
  39. package/dist/umd-bundle/dooboostore-simple-boot-http-server.umd.js.map +4 -4
  40. package/dist/umd-bundle/websocket-client.umd.js +106 -140
  41. package/dist/umd-bundle/websocket-client.umd.js.map +2 -2
  42. package/package.json +7 -7
  43. package/src/SimpleBootHttpServer.ts +19 -3
  44. package/src/decorators/MethodMapping.ts +151 -159
  45. package/src/models/RequestResponse.ts +50 -0
  46. package/src/proxy/RequestResponseInjectProxy.ts +30 -0
  47. package/src/proxy/SymbolIntentApiServiceProxy.ts +1 -1
  48. package/src/proxy/index.ts +1 -0
  49. package/src/resolvers/Resolver.ts +2 -1
@@ -14366,6 +14366,12 @@ var ValidUtils;
14366
14366
  return false;
14367
14367
  }
14368
14368
  };
14369
+ ValidUtils22.isGenerator = (value) => {
14370
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.iterator] === "function";
14371
+ };
14372
+ ValidUtils22.isAsyncGenerator = (value) => {
14373
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.asyncIterator] === "function";
14374
+ };
14369
14375
  ValidUtils22.isFrozen = (obj) => {
14370
14376
  return Object.isFrozen(obj);
14371
14377
  };
@@ -18810,87 +18816,64 @@ var throttle = (fn, delay) => {
18810
18816
  // ../core/dist/esm/promise/AbortablePromise.js
18811
18817
  var AbortablePromise = class _AbortablePromise {
18812
18818
  constructor(executor, signal) {
18813
- this.steps = [];
18814
- this.initialExecutor = executor;
18815
18819
  this.signal = signal;
18820
+ if (typeof executor !== "function") {
18821
+ this.source = Promise.resolve(executor);
18822
+ } else if (signal?.aborted) {
18823
+ this.source = Promise.reject(signal.reason);
18824
+ } else {
18825
+ this.source = Promise.resolve().then(executor);
18826
+ }
18827
+ }
18828
+ /**
18829
+ * source 를 abort 와 경쟁시킨 promise. 실제로 소비될 때(then/toPromise) 한 번만 만든다 —
18830
+ * await 는 then() 이 돌려준 새 인스턴스를 버리므로, 미리 만들면 아무도 안 받는 reject 가 unhandled 로 남는다.
18831
+ */
18832
+ get promise() {
18833
+ if (this.guarded) return this.guarded;
18834
+ const signal = this.signal;
18835
+ if (!signal) return this.guarded = this.source;
18836
+ if (signal.aborted) {
18837
+ this.source.catch(() => {
18838
+ });
18839
+ return this.guarded = Promise.reject(signal.reason);
18840
+ }
18841
+ return this.guarded = new Promise((resolve2, reject) => {
18842
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
18843
+ const onAbort = () => reject(signal.reason);
18844
+ signal.addEventListener("abort", onAbort, { once: true });
18845
+ this.source.then(
18846
+ (value) => {
18847
+ cleanup();
18848
+ resolve2(value);
18849
+ },
18850
+ (reason) => {
18851
+ cleanup();
18852
+ reject(reason);
18853
+ }
18854
+ );
18855
+ });
18816
18856
  }
18817
18857
  then(onfulfilled, onrejected) {
18818
- const newPromise = new _AbortablePromise(
18819
- this.initialExecutor,
18820
- this.signal
18858
+ const signal = this.signal;
18859
+ const next = this.promise.then(
18860
+ onfulfilled ? (value) => {
18861
+ if (signal?.aborted) throw signal.reason;
18862
+ return onfulfilled(value);
18863
+ } : void 0,
18864
+ onrejected
18821
18865
  );
18822
- newPromise.steps = [...this.steps];
18823
- if (onfulfilled) {
18824
- newPromise.steps.push(onfulfilled);
18825
- }
18826
- if (onrejected) {
18827
- newPromise.errorHandler = onrejected;
18828
- } else if (this.errorHandler) {
18829
- newPromise.errorHandler = this.errorHandler;
18830
- }
18831
- return newPromise;
18866
+ return new _AbortablePromise(next, signal);
18832
18867
  }
18833
18868
  catch(onrejected) {
18834
18869
  return this.then(void 0, onrejected);
18835
18870
  }
18836
18871
  finally(onfinally) {
18837
- return this.then(
18838
- (value) => {
18839
- onfinally?.();
18840
- return value;
18841
- },
18842
- (reason) => {
18843
- onfinally?.();
18844
- throw reason;
18845
- }
18846
- );
18872
+ return new _AbortablePromise(this.promise.finally(onfinally), this.signal);
18847
18873
  }
18848
- async execute() {
18849
- try {
18850
- if (this.signal?.aborted) {
18851
- throw new Error(this.signal.reason || "Aborted");
18852
- }
18853
- const abortPromise = new Promise((_, reject) => {
18854
- if (this.signal?.aborted) {
18855
- return reject(new Error(this.signal.reason || "Aborted"));
18856
- }
18857
- const callback = (e) => {
18858
- const target = e.target;
18859
- this.signal?.removeEventListener("abort", callback);
18860
- reject(new Error(target.reason || "Aborted"));
18861
- };
18862
- this.signal?.addEventListener("abort", callback, { once: true });
18863
- });
18864
- const pipelineRunner = async () => {
18865
- let lastResult;
18866
- if (typeof this.initialExecutor === "function") {
18867
- if (this.signal?.aborted) {
18868
- throw new Error(this.signal.reason || "Aborted");
18869
- }
18870
- lastResult = await this.initialExecutor();
18871
- } else {
18872
- lastResult = await this.initialExecutor;
18873
- }
18874
- for (let i = 0; i < this.steps.length; i++) {
18875
- if (this.signal?.aborted) {
18876
- throw new Error(this.signal.reason || "Aborted");
18877
- }
18878
- const step = this.steps[i];
18879
- lastResult = await step(lastResult);
18880
- }
18881
- return lastResult;
18882
- };
18883
- return await Promise.race([pipelineRunner(), abortPromise]);
18884
- } catch (error) {
18885
- if (this.errorHandler) {
18886
- return await this.errorHandler(error);
18887
- }
18888
- throw error;
18889
- }
18890
- }
18891
- // Convert to native Promise
18874
+ // 네이티브 Promise 로 변환 (그냥 await 해도 된다)
18892
18875
  toPromise() {
18893
- return this.execute();
18876
+ return this.promise;
18894
18877
  }
18895
18878
  };
18896
18879
 
@@ -19763,11 +19746,15 @@ var Fetcher = class {
19763
19746
  resolve2(gdata);
19764
19747
  }).catch(async (e) => {
19765
19748
  this.error(config, pipe, e);
19766
- config?.error?.();
19749
+ config?.error?.(e);
19767
19750
  if (config?.errorTransform) {
19768
19751
  e = await config.errorTransform(e);
19769
19752
  }
19770
- e = await this.errorTransform(e);
19753
+ try {
19754
+ e = await this.errorTransform(e);
19755
+ } catch (ee) {
19756
+ e = ee;
19757
+ }
19771
19758
  reject(e);
19772
19759
  }).finally(() => {
19773
19760
  this.finally(config, pipe);
@@ -19784,41 +19771,30 @@ var isHttpResponseError = (data) => {
19784
19771
  return data instanceof HttpResponseError;
19785
19772
  };
19786
19773
  var HttpFetcher = class extends Fetcher {
19774
+ // get/post/put/patch/head/delete가 전부 config.config.fetch.method를 세팅하려고 caller가
19775
+ // 넘긴 config(.fetch) 객체를 직접 mutate했다 - 같은 config 객체를 여러 호출이 공유하면
19776
+ // (예: Promise.all로 동시에 get/post) 서로의 method를 덮어쓰는 레이스가 생겼다. caller의
19777
+ // 객체는 절대 건드리지 않고, 얕은 복사본 위에 method만 얹어서 반환한다.
19778
+ withMethod(config, method) {
19779
+ return { ...config, config: { ...config.config, fetch: { ...config.config?.fetch, method } } };
19780
+ }
19787
19781
  get(config) {
19788
- config.config ?? (config.config = {});
19789
- config.config.fetch = config.config?.fetch ?? {};
19790
- config.config.fetch.method = "GET";
19791
- return this.fetch(config);
19782
+ return this.fetch(this.withMethod(config, "GET"));
19792
19783
  }
19793
19784
  post(config) {
19794
- config.config ?? (config.config = {});
19795
- config.config.fetch = config.config?.fetch ?? {};
19796
- config.config.fetch.method = "POST";
19797
- return this.fetch(config);
19785
+ return this.fetch(this.withMethod(config, "POST"));
19798
19786
  }
19799
19787
  patch(config) {
19800
- config.config ?? (config.config = {});
19801
- config.config.fetch = config.config?.fetch ?? {};
19802
- config.config.fetch.method = "PATCH";
19803
- return this.fetch(config);
19788
+ return this.fetch(this.withMethod(config, "PATCH"));
19804
19789
  }
19805
19790
  put(config) {
19806
- config.config ?? (config.config = {});
19807
- config.config.fetch = config.config?.fetch ?? {};
19808
- config.config.fetch.method = "PUT";
19809
- return this.fetch(config);
19791
+ return this.fetch(this.withMethod(config, "PUT"));
19810
19792
  }
19811
19793
  head(config) {
19812
- config.config ?? (config.config = {});
19813
- config.config.fetch = config.config?.fetch ?? {};
19814
- config.config.fetch.method = "HEAD";
19815
- return this.fetch(config);
19794
+ return this.fetch(this.withMethod(config, "HEAD"));
19816
19795
  }
19817
19796
  delete(config) {
19818
- config.config ?? (config.config = {});
19819
- config.config.fetch = config.config?.fetch ?? {};
19820
- config.config.fetch.method = "DELETE";
19821
- return this.fetch(config);
19797
+ return this.fetch(this.withMethod(config, "DELETE"));
19822
19798
  }
19823
19799
  async beforeProxyFetch(config) {
19824
19800
  return config;
@@ -19855,7 +19831,7 @@ var HttpFetcher = class extends Fetcher {
19855
19831
  }
19856
19832
  } else {
19857
19833
  httpResponseError.body = e;
19858
- httpResponseError.message = e.message;
19834
+ httpResponseError.message = e?.message;
19859
19835
  }
19860
19836
  return httpResponseError;
19861
19837
  }
@@ -19865,7 +19841,7 @@ var HttpFetcher = class extends Fetcher {
19865
19841
  if (!(target instanceof URL) && typeof target !== "string") {
19866
19842
  const searchParams = ConvertUtils.toURLSearchParams(target.searchParams ?? {});
19867
19843
  try {
19868
- const url = typeof target.url === "string" ? new URL(target.url) : target.url;
19844
+ const url = new URL(target.url);
19869
19845
  searchParams.forEach((value, key) => {
19870
19846
  url.searchParams.append(key, value);
19871
19847
  });
@@ -19880,43 +19856,30 @@ var HttpFetcher = class extends Fetcher {
19880
19856
  }
19881
19857
  }
19882
19858
  const beforeProxyData = { requestInfo: target, init: config?.fetch };
19883
- let beforeData = config?.beforeProxyFetch ? await config?.beforeProxyFetch(config) : beforeProxyData.requestInfo;
19884
- beforeData = config?.skipGlobalBeforeProxyFetch ? beforeProxyData : await this.beforeProxyFetch(beforeProxyData);
19859
+ let beforeData = config?.beforeProxyFetch ? await config?.beforeProxyFetch(beforeProxyData) : beforeProxyData;
19860
+ beforeData = config?.skipGlobalBeforeProxyFetch ? beforeData : await this.beforeProxyFetch(beforeData);
19885
19861
  target = beforeData.requestInfo;
19886
19862
  if (beforeData.init) {
19887
19863
  config ?? (config = {});
19888
19864
  config.fetch = beforeData.init;
19889
19865
  }
19890
- let abortedTimeout;
19866
+ let requestInit = config?.fetch;
19891
19867
  if (config?.fetch && "timeout" in config.fetch) {
19892
- const abortController = new AbortController();
19893
- abortedTimeout = setTimeout(() => {
19894
- if (config?.fetch?.signal) {
19895
- const inputSignal = config.fetch.signal;
19896
- const listener = () => {
19897
- if (!abortController.signal.aborted) {
19898
- abortController.abort();
19899
- }
19900
- inputSignal.removeEventListener("abort", listener);
19901
- };
19902
- inputSignal.addEventListener("abort", listener);
19903
- }
19904
- if (!abortController.signal.aborted) {
19905
- abortController.abort();
19906
- }
19907
- }, config.fetch.timeout);
19908
- config.fetch.signal = abortController.signal;
19868
+ const timeoutSignal = AbortSignal.timeout(config.fetch.timeout);
19869
+ const signal = config.fetch.signal ? AbortSignal.any([timeoutSignal, config.fetch.signal]) : timeoutSignal;
19870
+ requestInit = { ...config.fetch, signal };
19909
19871
  }
19910
- this.beforeFetch({ target, requestInit: config?.fetch });
19911
- return (config.fetcher ?? fetch)(target, config?.fetch).then(async (it) => {
19912
- this.afterFetch({ target, requestInit: config?.fetch }, it);
19872
+ this.beforeFetch({ target, requestInit });
19873
+ return (config.fetcher ?? fetch)(target, requestInit).then(async (it) => {
19874
+ this.afterFetch({ target, requestInit }, it);
19913
19875
  const afterProxyData = {
19914
- fetch: { target, requestInit: config.fetch },
19876
+ fetch: { target, requestInit },
19915
19877
  config: beforeData,
19916
19878
  response: it
19917
19879
  };
19918
- it = config?.afterProxyFetch ? await config.afterProxyFetch(afterProxyData) : it;
19919
- it = config?.skipGlobalAfterProxyFetch ? it : await this.afterProxyFetch(afterProxyData);
19880
+ afterProxyData.response = config?.afterProxyFetch ? await config.afterProxyFetch(afterProxyData) : it;
19881
+ afterProxyData.response = config?.skipGlobalAfterProxyFetch ? afterProxyData.response : await this.afterProxyFetch(afterProxyData);
19882
+ it = afterProxyData.response;
19920
19883
  config?.fetchResponseAfterCallBack?.(it, config);
19921
19884
  if (!config?.allowedResponseNotOk && !it.ok) {
19922
19885
  throw it;
@@ -19926,30 +19889,31 @@ var HttpFetcher = class extends Fetcher {
19926
19889
  throw data;
19927
19890
  }
19928
19891
  return it;
19929
- }).finally(() => {
19930
- if (abortedTimeout) {
19931
- clearTimeout(abortedTimeout);
19932
- }
19933
19892
  });
19934
19893
  }
19935
19894
  };
19936
19895
 
19937
19896
  // ../core/dist/esm/fetch/HttpJsonFetcher.js
19938
19897
  var HttpJsonFetcher = class extends HttpFetcher {
19898
+ // config.config/config.config.fetch를 직접 mutate하면(예전처럼) 같은 config 객체를 여러
19899
+ // postJson/patchJson/putJson 호출이 동시에 공유할 때 서로의 headers/body를 덮어쓰는 레이스가
19900
+ // 생긴다(HttpFetcher.get/post의 method 레이스랑 같은 문제). caller의 객체는 안 건드리고,
19901
+ // 얕은 복사본을 만들어서 새 config 객체를 리턴한다.
19939
19902
  updateJsonFetchConfigAndData(config) {
19940
- var _a4, _b3;
19941
19903
  const headers = {
19942
19904
  "Content-Type": "application/json",
19943
19905
  Accept: "application/json, text/plain, */*"
19944
19906
  };
19945
- config.config ?? (config.config = {});
19946
- (_a4 = config.config).fetch ?? (_a4.fetch = {});
19947
- (_b3 = config.config.fetch).headers ?? (_b3.headers = {});
19948
- config.config.fetch.headers = { ...headers, ...config.config.fetch?.headers };
19949
- if (config.config?.fetch?.body && typeof config.config?.fetch?.body !== "string") {
19950
- config.config.fetch.body = JSON.stringify(config.config.fetch.body);
19907
+ const fetchInit = { ...config.config?.fetch };
19908
+ const merged = new Headers(headers);
19909
+ if (fetchInit.headers) {
19910
+ new Headers(fetchInit.headers).forEach((value, key) => merged.set(key, value));
19951
19911
  }
19952
- return config;
19912
+ fetchInit.headers = merged;
19913
+ if (fetchInit.body && typeof fetchInit.body !== "string") {
19914
+ fetchInit.body = JSON.stringify(fetchInit.body);
19915
+ }
19916
+ return { ...config, config: { ...config.config, fetch: fetchInit } };
19953
19917
  }
19954
19918
  get(config) {
19955
19919
  return super.get(config);
@@ -21773,12 +21737,13 @@ var ReflectUtils;
21773
21737
  ReflectUtils2.findMetadata = (metadataKey, target, propertyKey) => {
21774
21738
  if (target == null) return void 0;
21775
21739
  let searchTarget = typeof target === "object" && typeof target !== "function" ? target.constructor : target;
21776
- while (searchTarget && searchTarget !== Object) {
21740
+ const seen = /* @__PURE__ */ new Set();
21741
+ while (searchTarget && searchTarget !== Object && !seen.has(searchTarget)) {
21742
+ seen.add(searchTarget);
21777
21743
  const data = propertyKey ? Reflect.getOwnMetadata(metadataKey, searchTarget, propertyKey) : Reflect.getOwnMetadata(metadataKey, searchTarget);
21778
21744
  if (data !== void 0) return data;
21779
21745
  const proto = Object.getPrototypeOf(searchTarget);
21780
21746
  searchTarget = proto && typeof proto === "function" ? proto : proto?.constructor || null;
21781
- if (searchTarget === target) break;
21782
21747
  }
21783
21748
  return void 0;
21784
21749
  };
@@ -21786,12 +21751,13 @@ var ReflectUtils;
21786
21751
  const results = [];
21787
21752
  if (target == null) return results;
21788
21753
  let searchTarget = typeof target === "object" && typeof target !== "function" ? target.constructor : target;
21789
- while (searchTarget && searchTarget !== Object) {
21754
+ const seen = /* @__PURE__ */ new Set();
21755
+ while (searchTarget && searchTarget !== Object && !seen.has(searchTarget)) {
21756
+ seen.add(searchTarget);
21790
21757
  const data = propertyKey ? Reflect.getOwnMetadata(metadataKey, searchTarget, propertyKey) : Reflect.getOwnMetadata(metadataKey, searchTarget);
21791
21758
  if (data !== void 0) results.unshift(data);
21792
21759
  const proto = Object.getPrototypeOf(searchTarget);
21793
21760
  searchTarget = proto && typeof proto === "function" ? proto : proto?.constructor || null;
21794
- if (searchTarget === target) break;
21795
21761
  }
21796
21762
  return results;
21797
21763
  };
@@ -25038,7 +25004,16 @@ var SimAtomic = class {
25038
25004
  }
25039
25005
  if (!this.value) {
25040
25006
  if (typeof this.type.targetKeyType === "symbol") {
25041
- this.value = this.simstanceManager.findFirstSim(this.type.targetKeyType)?.getValue();
25007
+ const stored = this.simstanceManager.getStoreSet(this.type.targetKeyType);
25008
+ if (ValidUtils.isArrowFunction(stored?.instance)) {
25009
+ const fresh = stored.instance();
25010
+ if (this.getConfig()?.scope === Lifecycle.Singleton) {
25011
+ this.simstanceManager.setStoreSet(this.type.targetKeyType, fresh, stored.type);
25012
+ this.value = fresh;
25013
+ }
25014
+ return fresh;
25015
+ }
25016
+ this.value = stored?.instance;
25042
25017
  } else {
25043
25018
  this.value = this.simstanceManager.getOrNewSim({ target: this.type.targetKeyType, originTypeTarget: this.type.originalType, newInstanceCarrier: config?.newInstanceCarrier });
25044
25019
  }
@@ -25593,7 +25568,7 @@ var SimstanceManager = class _SimstanceManager {
25593
25568
  registerStore(targetKey, regTyps) {
25594
25569
  const itemMap = this.storage.get(targetKey) ?? /* @__PURE__ */ new Map();
25595
25570
  regTyps.forEach((it) => {
25596
- const { type, value } = typeof it === "object" ? { type: it.constructor, value: it } : { type: it, value: void 0 };
25571
+ const { type, value } = ValidUtils.isArrowFunction(it) ? { type: it, value: it } : typeof it === "object" ? { type: it.constructor, value: it } : { type: it, value: void 0 };
25597
25572
  if (!itemMap.has(type) || value !== void 0 && itemMap.get(type) === void 0) {
25598
25573
  itemMap.set(type, value);
25599
25574
  }
@@ -25846,9 +25821,16 @@ var SimstanceManager = class _SimstanceManager {
25846
25821
  }
25847
25822
  run(otherInstanceSim = /* @__PURE__ */ new Map()) {
25848
25823
  for (const [k, v] of Array.from(otherInstanceSim.entries())) {
25849
- const storageKey = typeof k === "object" && k !== null && "type" in k ? k.type : k;
25850
- this.registerStore(storageKey, /* @__PURE__ */ new Set([v]));
25851
- if (typeof k === "object" && k !== null && "symbol" in k && k.symbol) {
25824
+ const hasType = typeof k === "object" && k !== null && "type" in k;
25825
+ const hasSymbol = typeof k === "object" && k !== null && !!k.symbol;
25826
+ const storageKey = hasType ? k.type : k;
25827
+ if (hasType || !hasSymbol) {
25828
+ this.registerStore(storageKey, /* @__PURE__ */ new Set([v]));
25829
+ }
25830
+ if (hasSymbol) {
25831
+ if (!ReflectUtils.getMetadata(SimMetadataKey, v)) {
25832
+ ReflectUtils.defineMetadata(SimMetadataKey, { ...k, scope: k.scope ?? Lifecycle.Singleton }, v);
25833
+ }
25852
25834
  this.registerStore(k.symbol, /* @__PURE__ */ new Set([v]));
25853
25835
  }
25854
25836
  }
@@ -27977,7 +27959,7 @@ var createHandler = (apiService) => {
27977
27959
  fetch: {
27978
27960
  credentials: "include",
27979
27961
  headers,
27980
- body: ConvertUtils.toFormData(userConfig?.body)
27962
+ body: userConfig?.body ? ConvertUtils.toFormData(userConfig.body) : void 0
27981
27963
  }
27982
27964
  }
27983
27965
  });
@@ -28290,6 +28272,16 @@ var createTopicHandler = (apiService) => {
28290
28272
  };
28291
28273
  };
28292
28274
 
28275
+ // src/proxy/RequestResponseInjectProxy.ts
28276
+ var injectRequestResponse = (sim2, rr) => new Proxy(sim2, {
28277
+ get(target, prop) {
28278
+ const value = target[prop];
28279
+ if (prop === "constructor" || typeof value !== "function") return value;
28280
+ if (!rr) return value.bind(target);
28281
+ return (...args) => value.apply(target, [...args, rr]);
28282
+ }
28283
+ });
28284
+
28293
28285
  // src/inject/InjectSituationType.ts
28294
28286
  var InjectSituationType2;
28295
28287
  ((InjectSituationType3) => {
@@ -28314,6 +28306,7 @@ var ReqHeader = class {
28314
28306
 
28315
28307
  // src/models/RequestResponse.ts
28316
28308
  var import_node_gzip = __toESM(require_dist(), 1);
28309
+ import { createGzip, constants as zlibConstants } from "zlib";
28317
28310
  import { Blob as Blob3 } from "node:buffer";
28318
28311
  var RequestResponse = class _RequestResponse {
28319
28312
  constructor(req, res, config) {
@@ -28752,6 +28745,57 @@ var RequestResponse = class _RequestResponse {
28752
28745
  this.createRequestResponseChain(this.res.writeHead(statusCode, headers));
28753
28746
  this.res.end();
28754
28747
  }
28748
+ /**
28749
+ * 헤더를 즉시 보내고, source 가 내놓는 값을 하나씩 바로 body 에 쓴 뒤 end.
28750
+ * (SSE / 스트리밍 응답용. resWrite 는 버퍼링 후 resEnd 에서 한 번에 보내므로 스트리밍 불가)
28751
+ * - 문자열/Buffer 는 그대로, 그 외는 JSON.stringify
28752
+ * - Accept-Encoding 에 gzip 이 있으면 gzip 스트림으로 압축하고, 청크마다 Z_SYNC_FLUSH 로 바로 내보낸다
28753
+ * (flush 없이 쓰면 zlib 내부 버퍼에 모였다가 늦게 나가서 SSE 실시간성이 깨짐)
28754
+ * - 클라이언트가 끊으면 source.return() 으로 제너레이터를 종료시켜 finally 가 돌게 한다
28755
+ */
28756
+ async resStream(source) {
28757
+ const res = this.res;
28758
+ const gz = this.reqHeaderFirst(HttpHeaders.AcceptEncoding)?.includes("gzip") ? createGzip() : void 0;
28759
+ if (gz) {
28760
+ res.setHeader(HttpHeaders.ContentEncoding, "gzip");
28761
+ res.removeHeader(HttpHeaders.ContentLength);
28762
+ gz.pipe(res);
28763
+ }
28764
+ const out = gz ?? res;
28765
+ res.flushHeaders();
28766
+ let closed = false;
28767
+ const onClose = () => {
28768
+ closed = true;
28769
+ source.return?.();
28770
+ };
28771
+ res.once("close", onClose);
28772
+ try {
28773
+ for await (const chunk of source) {
28774
+ if (closed) break;
28775
+ const data = typeof chunk === "string" || Buffer2.isBuffer(chunk) ? chunk : JSON.stringify(chunk);
28776
+ const ok = out.write(data);
28777
+ gz?.flush(zlibConstants.Z_SYNC_FLUSH);
28778
+ if (!ok) await new Promise((resolve2) => {
28779
+ out.once("drain", resolve2);
28780
+ res.once("close", resolve2);
28781
+ });
28782
+ }
28783
+ } catch (e) {
28784
+ if (!closed) throw e;
28785
+ } finally {
28786
+ res.off("close", onClose);
28787
+ if (closed) {
28788
+ gz?.destroy();
28789
+ } else if (!res.writableEnded) {
28790
+ const finished = new Promise((resolve2) => {
28791
+ res.once("finish", resolve2);
28792
+ res.once("close", resolve2);
28793
+ });
28794
+ out.end();
28795
+ await finished;
28796
+ }
28797
+ }
28798
+ }
28755
28799
  resIsDone() {
28756
28800
  return this.res.finished || this.res.writableEnded || this.res.headersSent;
28757
28801
  }
@@ -29099,6 +29143,11 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29099
29143
  otherStorage.set(RequestResponse, rr);
29100
29144
  otherStorage.set(IncomingMessage, req);
29101
29145
  otherStorage.set(ServerResponse, res);
29146
+ const abortController = new AbortController();
29147
+ res.once("close", () => {
29148
+ if (!res.writableFinished) abortController.abort();
29149
+ });
29150
+ otherStorage.set(AbortSignal, abortController.signal);
29102
29151
  try {
29103
29152
  transactionManager?.try();
29104
29153
  if (this.option.requestEndPoints) {
@@ -29256,11 +29305,19 @@ var SimpleBootHttpServer = class _SimpleBootHttpServer extends SimpleApplication
29256
29305
  targetKey: it.propertyKey
29257
29306
  }, otherStorage);
29258
29307
  const resConfig = it.config?.res;
29259
- if (resConfig?.manual === true) {
29308
+ if (resConfig === "manual") {
29309
+ } else if (ValidUtils.isGenerator(data) || ValidUtils.isAsyncGenerator(data)) {
29310
+ const headers = resConfig?.header ?? {};
29311
+ if (resConfig?.contentType) {
29312
+ headers[HttpHeaders.ContentType] = resConfig.contentType;
29313
+ }
29314
+ rr.resSetHeaders(headers);
29315
+ rr.resSetStatusCode(resConfig?.status ?? 200 /* Ok */);
29316
+ await rr.resStream(data);
29260
29317
  } else {
29261
29318
  if (it.config?.resolver) {
29262
29319
  const execute = typeof it.config.resolver === "function" ? this.simstanceManager.getOrNewSim({ target: it.config.resolver }) : it.config.resolver;
29263
- data = await execute?.resolve?.(data, rr);
29320
+ data = await execute?.resolve?.(data, rr, resConfig);
29264
29321
  }
29265
29322
  const status = resConfig?.status ?? 200 /* Ok */;
29266
29323
  const headers = resConfig?.header ?? {};
@@ -29572,7 +29629,7 @@ var ElementUtils;
29572
29629
  var ElementApply = class _ElementApply {
29573
29630
  constructor(el, config) {
29574
29631
  this.el = el;
29575
- this.window = this.el.ownerDocument.defaultView;
29632
+ this.window = this.el.ownerDocument.defaultView ?? globalThis;
29576
29633
  this.document = this.el.ownerDocument;
29577
29634
  this.id = config?.id ?? el.id;
29578
29635
  this.variableWrap = config?.variableWrap ?? { start: "@", end: "@" };
@@ -29595,6 +29652,8 @@ var ElementApply = class _ElementApply {
29595
29652
  let match;
29596
29653
  while ((match = regex.exec(script)) !== null) {
29597
29654
  variables.push(match[1]);
29655
+ const root = match[1].split(/[.[(]/)[0].trim();
29656
+ if (root && root !== match[1]) variables.push(root);
29598
29657
  }
29599
29658
  return variables;
29600
29659
  }
@@ -29699,10 +29758,15 @@ var ElementApply = class _ElementApply {
29699
29758
  type.variables.forEach((v) => variables.add(v));
29700
29759
  });
29701
29760
  }
29761
+ const bind = config?.bind;
29762
+ const fromBind = (key) => bind != null && typeof key === "string" && !(key in (config?.context ?? {})) && _ElementApply.isUserMember(bind, key);
29702
29763
  const context = new Proxy(config?.context ?? {}, {
29764
+ has(target, key) {
29765
+ return key in target || fromBind(key);
29766
+ },
29703
29767
  get(target, key) {
29704
- const value = target[key];
29705
- return typeof value === "function" ? value.bind(config?.bind ?? target) : value;
29768
+ const value = key in target ? target[key] : fromBind(key) ? bind[key] : void 0;
29769
+ return typeof value === "function" ? value.bind(bind ?? target) : value;
29706
29770
  }
29707
29771
  });
29708
29772
  if (!config?.targetVariableName || config?.targetVariableName && variables.has(config?.targetVariableName)) {
@@ -29727,7 +29791,6 @@ var ElementApply = class _ElementApply {
29727
29791
  }
29728
29792
  }
29729
29793
  `)(context).bind(it.node);
29730
- console.log("------------------->", it, tit);
29731
29794
  if (tit.type === "attribute" && !config?.exclude?.attribute) {
29732
29795
  it.node.setAttribute(tit.name, data());
29733
29796
  } else if (tit.type === "property" && !config?.exclude?.property) {
@@ -29747,6 +29810,15 @@ var ElementApply = class _ElementApply {
29747
29810
  }
29748
29811
  }
29749
29812
  }
29813
+ /** key 가 네이티브(DOM/내장) prototype 이 아니라 사용자 클래스나 인스턴스에 정의돼 있으면 true */
29814
+ static isUserMember(obj, key) {
29815
+ for (let p = obj; p; p = Object.getPrototypeOf(p)) {
29816
+ if (!Object.prototype.hasOwnProperty.call(p, key)) continue;
29817
+ const ctor = p === obj ? null : p.constructor;
29818
+ return !(typeof ctor === "function" && /\[native code\]/.test(Function.prototype.toString.call(ctor)));
29819
+ }
29820
+ return false;
29821
+ }
29750
29822
  removeAllEventListener() {
29751
29823
  const m = this.findAllTarget().filter((it) => it.nodeType === "element").flatMap((it) => it.types.map((sit) => ({ ...sit, node: it.node })).filter((it2) => it2.type === "event"));
29752
29824
  m.forEach((tit) => {
@@ -30124,15 +30196,21 @@ var NodeSlot = class _NodeSlot {
30124
30196
  const slots = this.findSlots();
30125
30197
  return slots.map((s) => s.nodes());
30126
30198
  }
30127
- append(...args) {
30128
- let targetId;
30129
- let items = [];
30130
- if (typeof args[0] === "string" && args.length > 1) {
30131
- targetId = args[0];
30132
- items = args.slice(1);
30133
- } else {
30134
- items = args;
30199
+ /**
30200
+ * Shared disambiguation for the `(...items)` / `(targetId, ...items)` overload pair.
30201
+ * Items are always Node instances (or strings meant as literal content) coming from
30202
+ * callers; a leading string is therefore always treated as `targetId`, even when no
30203
+ * items follow — this avoids misclassifying `targetId` itself as content when the
30204
+ * caller has zero items to insert (e.g. a decorated method returning undefined).
30205
+ */
30206
+ static parseTargetArgs(args) {
30207
+ if (typeof args[0] === "string") {
30208
+ return { targetId: args[0], items: args.slice(1) };
30135
30209
  }
30210
+ return { targetId: void 0, items: args };
30211
+ }
30212
+ append(...args) {
30213
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30136
30214
  if (!items || items.length === 0) return;
30137
30215
  const slots = this.findSlots(targetId);
30138
30216
  if (!slots || slots.length === 0) return;
@@ -30141,38 +30219,17 @@ var NodeSlot = class _NodeSlot {
30141
30219
  }
30142
30220
  }
30143
30221
  appendHtml(...args) {
30144
- let targetId;
30145
- let items = [];
30146
- if (typeof args[0] === "string" && args.length > 1) {
30147
- targetId = args[0];
30148
- items = args.slice(1);
30149
- } else {
30150
- items = args;
30151
- }
30222
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30152
30223
  const slots = this.findSlots(targetId);
30153
30224
  for (const s of slots) s.appendHtml(...items);
30154
30225
  }
30155
30226
  appendText(...args) {
30156
- let targetId;
30157
- let items = [];
30158
- if (typeof args[0] === "string" && args.length > 1) {
30159
- targetId = args[0];
30160
- items = args.slice(1);
30161
- } else {
30162
- items = args;
30163
- }
30227
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30164
30228
  const slots = this.findSlots(targetId);
30165
30229
  for (const s of slots) s.appendText(...items);
30166
30230
  }
30167
30231
  appendCopy(...args) {
30168
- let targetId;
30169
- let items = [];
30170
- if (typeof args[0] === "string" && args.length > 1) {
30171
- targetId = args[0];
30172
- items = args.slice(1);
30173
- } else {
30174
- items = args;
30175
- }
30232
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30176
30233
  if (!items || items.length === 0) return;
30177
30234
  const slots = this.findSlots(targetId);
30178
30235
  if (!slots || slots.length === 0) return;
@@ -30181,14 +30238,7 @@ var NodeSlot = class _NodeSlot {
30181
30238
  }
30182
30239
  }
30183
30240
  prepend(...args) {
30184
- let targetId;
30185
- let items = [];
30186
- if (typeof args[0] === "string" && args.length > 1) {
30187
- targetId = args[0];
30188
- items = args.slice(1);
30189
- } else {
30190
- items = args;
30191
- }
30241
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30192
30242
  if (!items || items.length === 0) return;
30193
30243
  const slots = this.findSlots(targetId);
30194
30244
  if (!slots || slots.length === 0) return;
@@ -30197,38 +30247,17 @@ var NodeSlot = class _NodeSlot {
30197
30247
  }
30198
30248
  }
30199
30249
  prependHtml(...args) {
30200
- let targetId;
30201
- let items = [];
30202
- if (typeof args[0] === "string" && args.length > 1) {
30203
- targetId = args[0];
30204
- items = args.slice(1);
30205
- } else {
30206
- items = args;
30207
- }
30250
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30208
30251
  const slots = this.findSlots(targetId);
30209
30252
  for (const s of slots) s.prependHtml(...items);
30210
30253
  }
30211
30254
  prependText(...args) {
30212
- let targetId;
30213
- let items = [];
30214
- if (typeof args[0] === "string" && args.length > 1) {
30215
- targetId = args[0];
30216
- items = args.slice(1);
30217
- } else {
30218
- items = args;
30219
- }
30255
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30220
30256
  const slots = this.findSlots(targetId);
30221
30257
  for (const s of slots) s.prependText(...items);
30222
30258
  }
30223
30259
  prependCopy(...args) {
30224
- let targetId;
30225
- let items = [];
30226
- if (typeof args[0] === "string" && args.length > 1) {
30227
- targetId = args[0];
30228
- items = args.slice(1);
30229
- } else {
30230
- items = args;
30231
- }
30260
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30232
30261
  if (!items || items.length === 0) return;
30233
30262
  const slots = this.findSlots(targetId);
30234
30263
  if (!slots || slots.length === 0) return;
@@ -30248,14 +30277,7 @@ var NodeSlot = class _NodeSlot {
30248
30277
  }
30249
30278
  }
30250
30279
  replaceChildren(...args) {
30251
- let targetId;
30252
- let items = [];
30253
- if (typeof args[0] === "string" && args.length > 1) {
30254
- targetId = args[0];
30255
- items = args.slice(1);
30256
- } else {
30257
- items = args;
30258
- }
30280
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30259
30281
  const slots = this.findSlots(targetId);
30260
30282
  if (!slots || slots.length === 0) return;
30261
30283
  for (const s of slots) {
@@ -30263,14 +30285,7 @@ var NodeSlot = class _NodeSlot {
30263
30285
  }
30264
30286
  }
30265
30287
  replaceChildrenHtml(...args) {
30266
- let targetId;
30267
- let items = [];
30268
- if (typeof args[0] === "string" && args.length > 1) {
30269
- targetId = args[0];
30270
- items = args.slice(1);
30271
- } else {
30272
- items = args;
30273
- }
30288
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30274
30289
  const slots = this.findSlots(targetId);
30275
30290
  if (!slots || slots.length === 0) return;
30276
30291
  for (const s of slots) {
@@ -30278,14 +30293,7 @@ var NodeSlot = class _NodeSlot {
30278
30293
  }
30279
30294
  }
30280
30295
  replaceChildrenText(...args) {
30281
- let targetId;
30282
- let items = [];
30283
- if (typeof args[0] === "string" && args.length > 1) {
30284
- targetId = args[0];
30285
- items = args.slice(1);
30286
- } else {
30287
- items = args;
30288
- }
30296
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
30289
30297
  const slots = this.findSlots(targetId);
30290
30298
  if (!slots || slots.length === 0) return;
30291
30299
  for (const s of slots) {
@@ -30976,6 +30984,7 @@ var LocationUtils;
30976
30984
  var ROUTER_NO_EVENT_MARKER = "__ROUTER_NO_EVENT__";
30977
30985
  var Router2 = class {
30978
30986
  constructor(config) {
30987
+ this.leaveGuards = /* @__PURE__ */ new Set();
30979
30988
  this._config = config;
30980
30989
  let routeData;
30981
30990
  if (config?.firstUrl) {
@@ -30996,13 +31005,39 @@ var Router2 = class {
30996
31005
  this.behaviorSubject = new BehaviorSubject(routeData);
30997
31006
  }
30998
31007
  this.config.window.addEventListener("popstate", (event) => {
30999
- const routeData2 = { ...this.getRouteData(), triggerPoint: "end" };
31000
- this.behaviorSubject.next(routeData2);
31008
+ const publish = () => this.behaviorSubject.next({ ...this.getRouteData(), triggerPoint: "end" });
31009
+ if (!this.leaveGuards.size) return publish();
31010
+ const from = this.value;
31011
+ void this.canLeave(this.getRouteData(), from).then((ok) => {
31012
+ if (ok) publish();
31013
+ else this.config.window.history?.pushState(from.data ?? null, "", from.url);
31014
+ });
31001
31015
  });
31002
31016
  }
31003
31017
  get value() {
31004
31018
  return this.behaviorSubject.getValue();
31005
31019
  }
31020
+ /**
31021
+ * 이동 전 가드 등록. go() 와 뒤로/앞으로 가기(popstate)에 적용된다 (pushState/replaceState 직접 호출은 제외).
31022
+ * 리턴한 함수를 부르면 해제된다.
31023
+ */
31024
+ addLeaveGuard(guard) {
31025
+ this.leaveGuards.add(guard);
31026
+ return () => {
31027
+ this.leaveGuards.delete(guard);
31028
+ };
31029
+ }
31030
+ /** 가드가 하나라도 있는지 (없으면 호출자가 동기로 진행해도 된다) */
31031
+ get hasLeaveGuards() {
31032
+ return this.leaveGuards.size > 0;
31033
+ }
31034
+ /** 등록된 가드를 순서대로 평가. 하나라도 false 면 false */
31035
+ async canLeave(to, from) {
31036
+ for (const guard of [...this.leaveGuards]) {
31037
+ if (await guard(to, from) === false) return false;
31038
+ }
31039
+ return true;
31040
+ }
31006
31041
  get observable() {
31007
31042
  return this.behaviorSubject.asObservable();
31008
31043
  }
@@ -31133,17 +31168,24 @@ var Router2 = class {
31133
31168
  if (typeof config === "string") {
31134
31169
  config = { path: config };
31135
31170
  }
31136
- if (config?.replace) {
31137
- this.replace(config.path, config.state);
31138
- } else {
31139
- this.push(config.path, config.state);
31140
- }
31141
- if (config.scrollToTop !== false) {
31142
- try {
31143
- this._config.window?.scrollTo?.(0, 0);
31144
- } catch (e) {
31171
+ const target = config;
31172
+ const navigate = () => {
31173
+ if (target?.replace) {
31174
+ this.replace(target.path, target.state);
31175
+ } else {
31176
+ this.push(target.path, target.state);
31145
31177
  }
31146
- }
31178
+ if (target.scrollToTop !== false) {
31179
+ try {
31180
+ this._config.window?.scrollTo?.(0, 0);
31181
+ } catch (e) {
31182
+ }
31183
+ }
31184
+ };
31185
+ if (!this.leaveGuards.size) return navigate();
31186
+ return this.canLeave(this.getRouteData({ pathOrUrl: this.toUrl(target.path) }), this.value).then((ok) => {
31187
+ if (ok) navigate();
31188
+ });
31147
31189
  }
31148
31190
  toUrl(data) {
31149
31191
  let targetPath;
@@ -38403,6 +38445,7 @@ export {
38403
38445
  getUrlMapping,
38404
38446
  getUrlMappings,
38405
38447
  headMethod,
38448
+ injectRequestResponse,
38406
38449
  isDataDist,
38407
38450
  isPathDist,
38408
38451
  makeIntentHeaderBySymbolFor,