@dooboostore/simple-web-component 1.0.50 → 1.0.51

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 (241) hide show
  1. package/README.md +735 -354
  2. package/dist/cjs/SwcAppEngine.js.map +2 -2
  3. package/dist/cjs/decorators/addEventListener.js +64 -146
  4. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  5. package/dist/cjs/decorators/applyAttribute.js +36 -48
  6. package/dist/cjs/decorators/applyAttribute.js.map +2 -2
  7. package/dist/cjs/decorators/applyClass.js +9 -12
  8. package/dist/cjs/decorators/applyClass.js.map +2 -2
  9. package/dist/cjs/decorators/applyNode.js +14 -22
  10. package/dist/cjs/decorators/applyNode.js.map +2 -2
  11. package/dist/cjs/decorators/applyProperty.js +12 -42
  12. package/dist/cjs/decorators/applyProperty.js.map +2 -2
  13. package/dist/cjs/decorators/applySlot.js +3 -3
  14. package/dist/cjs/decorators/applySlot.js.map +2 -2
  15. package/dist/cjs/decorators/applyStyle.js +9 -12
  16. package/dist/cjs/decorators/applyStyle.js.map +2 -2
  17. package/dist/cjs/decorators/around.js +124 -0
  18. package/dist/cjs/decorators/around.js.map +7 -0
  19. package/dist/cjs/decorators/changedAttribute.js +40 -12
  20. package/dist/cjs/decorators/changedAttribute.js.map +2 -2
  21. package/dist/cjs/decorators/elementDefine.js +224 -195
  22. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  23. package/dist/cjs/decorators/emitCustomEvent.js +14 -12
  24. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  25. package/dist/cjs/decorators/eventMedia.js +36 -8
  26. package/dist/cjs/decorators/eventMedia.js.map +2 -2
  27. package/dist/cjs/decorators/fetch.js +278 -0
  28. package/dist/cjs/decorators/fetch.js.map +7 -0
  29. package/dist/cjs/decorators/index.js +5 -2
  30. package/dist/cjs/decorators/index.js.map +2 -2
  31. package/dist/cjs/decorators/intersectionObserver.js +33 -13
  32. package/dist/cjs/decorators/intersectionObserver.js.map +2 -2
  33. package/dist/cjs/decorators/lifecycles.js +11 -11
  34. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  35. package/dist/cjs/decorators/mutationObserver.js +55 -39
  36. package/dist/cjs/decorators/mutationObserver.js.map +3 -3
  37. package/dist/cjs/decorators/parameter.js +92 -9
  38. package/dist/cjs/decorators/parameter.js.map +2 -2
  39. package/dist/cjs/decorators/publishSwcAppMessage.js +2 -2
  40. package/dist/cjs/decorators/publishSwcAppMessage.js.map +2 -2
  41. package/dist/cjs/decorators/query.js +11 -5
  42. package/dist/cjs/decorators/query.js.map +2 -2
  43. package/dist/cjs/decorators/requestAnimationFrame.js +7 -16
  44. package/dist/cjs/decorators/requestAnimationFrame.js.map +2 -2
  45. package/dist/cjs/decorators/resizeObserver.js +41 -17
  46. package/dist/cjs/decorators/resizeObserver.js.map +3 -3
  47. package/dist/cjs/decorators/setInterval.js +36 -25
  48. package/dist/cjs/decorators/setInterval.js.map +2 -2
  49. package/dist/cjs/decorators/setTimeout.js +36 -25
  50. package/dist/cjs/decorators/setTimeout.js.map +2 -2
  51. package/dist/cjs/decorators/state.js +13 -10
  52. package/dist/cjs/decorators/state.js.map +2 -2
  53. package/dist/cjs/decorators/{subscribeSwcAppMessageWhileConnected.js → subscribeSwcAppMessage.js} +20 -21
  54. package/dist/cjs/decorators/subscribeSwcAppMessage.js.map +7 -0
  55. package/dist/cjs/decorators/{subscribeSwcAppRouteChangeWhileConnected.js → subscribeSwcAppRouteChange.js} +23 -19
  56. package/dist/cjs/decorators/subscribeSwcAppRouteChange.js.map +7 -0
  57. package/dist/cjs/decorators/swcAppRoute.js +149 -0
  58. package/dist/cjs/decorators/swcAppRoute.js.map +7 -0
  59. package/dist/cjs/elements/SwcApp.js +70 -0
  60. package/dist/cjs/elements/SwcApp.js.map +2 -2
  61. package/dist/cjs/elements/SwcAppMixin.js +256 -83
  62. package/dist/cjs/elements/SwcAppMixin.js.map +3 -3
  63. package/dist/cjs/types/index.js +5 -1
  64. package/dist/cjs/types/index.js.map +2 -2
  65. package/dist/cjs/utils/Utils.js +36 -15
  66. package/dist/cjs/utils/Utils.js.map +2 -2
  67. package/dist/esm/SwcAppEngine.js.map +2 -2
  68. package/dist/esm/decorators/addEventListener.js +64 -146
  69. package/dist/esm/decorators/addEventListener.js.map +2 -2
  70. package/dist/esm/decorators/applyAttribute.js +36 -48
  71. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  72. package/dist/esm/decorators/applyClass.js +9 -12
  73. package/dist/esm/decorators/applyClass.js.map +2 -2
  74. package/dist/esm/decorators/applyNode.js +15 -23
  75. package/dist/esm/decorators/applyNode.js.map +2 -2
  76. package/dist/esm/decorators/applyProperty.js +12 -42
  77. package/dist/esm/decorators/applyProperty.js.map +2 -2
  78. package/dist/esm/decorators/applySlot.js +3 -3
  79. package/dist/esm/decorators/applySlot.js.map +2 -2
  80. package/dist/esm/decorators/applyStyle.js +9 -12
  81. package/dist/esm/decorators/applyStyle.js.map +2 -2
  82. package/dist/esm/decorators/around.js +105 -0
  83. package/dist/esm/decorators/around.js.map +7 -0
  84. package/dist/esm/decorators/changedAttribute.js +40 -12
  85. package/dist/esm/decorators/changedAttribute.js.map +2 -2
  86. package/dist/esm/decorators/elementDefine.js +222 -193
  87. package/dist/esm/decorators/elementDefine.js.map +3 -3
  88. package/dist/esm/decorators/emitCustomEvent.js +15 -13
  89. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  90. package/dist/esm/decorators/eventMedia.js +36 -8
  91. package/dist/esm/decorators/eventMedia.js.map +2 -2
  92. package/dist/esm/decorators/fetch.js +259 -0
  93. package/dist/esm/decorators/fetch.js.map +7 -0
  94. package/dist/esm/decorators/index.js +5 -2
  95. package/dist/esm/decorators/index.js.map +2 -2
  96. package/dist/esm/decorators/intersectionObserver.js +33 -13
  97. package/dist/esm/decorators/intersectionObserver.js.map +2 -2
  98. package/dist/esm/decorators/lifecycles.js +11 -11
  99. package/dist/esm/decorators/lifecycles.js.map +2 -2
  100. package/dist/esm/decorators/mutationObserver.js +55 -39
  101. package/dist/esm/decorators/mutationObserver.js.map +3 -3
  102. package/dist/esm/decorators/parameter.js +92 -9
  103. package/dist/esm/decorators/parameter.js.map +2 -2
  104. package/dist/esm/decorators/publishSwcAppMessage.js +2 -2
  105. package/dist/esm/decorators/publishSwcAppMessage.js.map +2 -2
  106. package/dist/esm/decorators/query.js +11 -5
  107. package/dist/esm/decorators/query.js.map +2 -2
  108. package/dist/esm/decorators/requestAnimationFrame.js +8 -17
  109. package/dist/esm/decorators/requestAnimationFrame.js.map +2 -2
  110. package/dist/esm/decorators/resizeObserver.js +41 -17
  111. package/dist/esm/decorators/resizeObserver.js.map +2 -2
  112. package/dist/esm/decorators/setInterval.js +37 -26
  113. package/dist/esm/decorators/setInterval.js.map +2 -2
  114. package/dist/esm/decorators/setTimeout.js +37 -26
  115. package/dist/esm/decorators/setTimeout.js.map +2 -2
  116. package/dist/esm/decorators/state.js +13 -10
  117. package/dist/esm/decorators/state.js.map +2 -2
  118. package/dist/esm/decorators/subscribeSwcAppMessage.js +53 -0
  119. package/dist/esm/decorators/subscribeSwcAppMessage.js.map +7 -0
  120. package/dist/esm/decorators/{subscribeSwcAppRouteChangeWhileConnected.js → subscribeSwcAppRouteChange.js} +20 -16
  121. package/dist/esm/decorators/subscribeSwcAppRouteChange.js.map +7 -0
  122. package/dist/esm/decorators/swcAppRoute.js +130 -0
  123. package/dist/esm/decorators/swcAppRoute.js.map +7 -0
  124. package/dist/esm/elements/SwcApp.js +70 -0
  125. package/dist/esm/elements/SwcApp.js.map +2 -2
  126. package/dist/esm/elements/SwcAppMixin.js +258 -85
  127. package/dist/esm/elements/SwcAppMixin.js.map +3 -3
  128. package/dist/esm/types/index.js +5 -1
  129. package/dist/esm/types/index.js.map +2 -2
  130. package/dist/esm/utils/Utils.js +36 -15
  131. package/dist/esm/utils/Utils.js.map +2 -2
  132. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +1886 -999
  133. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  134. package/dist/types/SwcAppEngine.d.ts +1 -0
  135. package/dist/types/SwcAppEngine.d.ts.map +1 -1
  136. package/dist/types/decorators/addEventListener.d.ts +923 -960
  137. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  138. package/dist/types/decorators/applyAttribute.d.ts +26 -38
  139. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  140. package/dist/types/decorators/applyClass.d.ts +1 -3
  141. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  142. package/dist/types/decorators/applyNode.d.ts +15 -17
  143. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  144. package/dist/types/decorators/applyProperty.d.ts +25 -45
  145. package/dist/types/decorators/applyProperty.d.ts.map +1 -1
  146. package/dist/types/decorators/applyStyle.d.ts +1 -3
  147. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  148. package/dist/types/decorators/around.d.ts +87 -0
  149. package/dist/types/decorators/around.d.ts.map +1 -0
  150. package/dist/types/decorators/changedAttribute.d.ts +21 -1
  151. package/dist/types/decorators/changedAttribute.d.ts.map +1 -1
  152. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  153. package/dist/types/decorators/emitCustomEvent.d.ts +0 -1
  154. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  155. package/dist/types/decorators/eventMedia.d.ts +24 -1
  156. package/dist/types/decorators/eventMedia.d.ts.map +1 -1
  157. package/dist/types/decorators/fetch.d.ts +139 -0
  158. package/dist/types/decorators/fetch.d.ts.map +1 -0
  159. package/dist/types/decorators/index.d.ts +5 -2
  160. package/dist/types/decorators/index.d.ts.map +1 -1
  161. package/dist/types/decorators/intersectionObserver.d.ts +24 -11
  162. package/dist/types/decorators/intersectionObserver.d.ts.map +1 -1
  163. package/dist/types/decorators/lifecycles.d.ts +8 -7
  164. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  165. package/dist/types/decorators/mutationObserver.d.ts +26 -13
  166. package/dist/types/decorators/mutationObserver.d.ts.map +1 -1
  167. package/dist/types/decorators/parameter.d.ts +84 -6
  168. package/dist/types/decorators/parameter.d.ts.map +1 -1
  169. package/dist/types/decorators/publishSwcAppMessage.d.ts +0 -1
  170. package/dist/types/decorators/publishSwcAppMessage.d.ts.map +1 -1
  171. package/dist/types/decorators/query.d.ts +7 -7
  172. package/dist/types/decorators/query.d.ts.map +1 -1
  173. package/dist/types/decorators/requestAnimationFrame.d.ts +1 -1
  174. package/dist/types/decorators/requestAnimationFrame.d.ts.map +1 -1
  175. package/dist/types/decorators/resizeObserver.d.ts +26 -13
  176. package/dist/types/decorators/resizeObserver.d.ts.map +1 -1
  177. package/dist/types/decorators/setInterval.d.ts +10 -0
  178. package/dist/types/decorators/setInterval.d.ts.map +1 -1
  179. package/dist/types/decorators/setTimeout.d.ts +10 -0
  180. package/dist/types/decorators/setTimeout.d.ts.map +1 -1
  181. package/dist/types/decorators/state.d.ts.map +1 -1
  182. package/dist/types/decorators/subscribeSwcAppMessage.d.ts +44 -0
  183. package/dist/types/decorators/subscribeSwcAppMessage.d.ts.map +1 -0
  184. package/dist/types/decorators/subscribeSwcAppRouteChange.d.ts +60 -0
  185. package/dist/types/decorators/subscribeSwcAppRouteChange.d.ts.map +1 -0
  186. package/dist/types/decorators/swcAppRoute.d.ts +94 -0
  187. package/dist/types/decorators/swcAppRoute.d.ts.map +1 -0
  188. package/dist/types/elements/SwcApp.d.ts.map +1 -1
  189. package/dist/types/elements/SwcAppMixin.d.ts +423 -388
  190. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  191. package/dist/types/types/index.d.ts +43 -4
  192. package/dist/types/types/index.d.ts.map +1 -1
  193. package/dist/types/utils/Utils.d.ts +15 -5
  194. package/dist/types/utils/Utils.d.ts.map +1 -1
  195. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +1886 -999
  196. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  197. package/package.json +8 -6
  198. package/src/SwcAppEngine.ts +1 -0
  199. package/src/decorators/addEventListener.ts +102 -96
  200. package/src/decorators/applyAttribute.ts +76 -138
  201. package/src/decorators/applyClass.ts +8 -14
  202. package/src/decorators/applyNode.ts +33 -41
  203. package/src/decorators/applyProperty.ts +51 -99
  204. package/src/decorators/applySlot.ts +3 -3
  205. package/src/decorators/applyStyle.ts +8 -14
  206. package/src/decorators/around.ts +196 -0
  207. package/src/decorators/changedAttribute.ts +39 -15
  208. package/src/decorators/elementDefine.ts +270 -219
  209. package/src/decorators/emitCustomEvent.ts +17 -13
  210. package/src/decorators/eventMedia.ts +50 -9
  211. package/src/decorators/fetch.ts +454 -0
  212. package/src/decorators/index.ts +5 -2
  213. package/src/decorators/intersectionObserver.ts +38 -24
  214. package/src/decorators/lifecycles.ts +24 -22
  215. package/src/decorators/mutationObserver.ts +71 -52
  216. package/src/decorators/parameter.ts +145 -14
  217. package/src/decorators/publishSwcAppMessage.ts +3 -4
  218. package/src/decorators/query.ts +22 -14
  219. package/src/decorators/requestAnimationFrame.ts +10 -19
  220. package/src/decorators/resizeObserver.ts +50 -29
  221. package/src/decorators/setInterval.ts +37 -26
  222. package/src/decorators/setTimeout.ts +37 -26
  223. package/src/decorators/state.ts +19 -13
  224. package/src/decorators/subscribeSwcAppMessage.ts +106 -0
  225. package/src/decorators/subscribeSwcAppRouteChange.ts +131 -0
  226. package/src/decorators/swcAppRoute.ts +231 -0
  227. package/src/elements/SwcApp.ts +40 -10
  228. package/src/elements/SwcAppMixin.ts +330 -101
  229. package/src/types/index.ts +38 -5
  230. package/src/utils/Utils.ts +50 -18
  231. package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js.map +0 -7
  232. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +0 -7
  233. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js +0 -54
  234. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js.map +0 -7
  235. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +0 -7
  236. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts +0 -23
  237. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts.map +0 -1
  238. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts +0 -31
  239. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts.map +0 -1
  240. package/src/decorators/subscribeSwcAppMessageWhileConnected.ts +0 -91
  241. package/src/decorators/subscribeSwcAppRouteChangeWhileConnected.ts +0 -107
@@ -1,11 +1,48 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { findAllLifecycleMetadata, getSubscribeSwcAppMessageWhileConnectedMetadata, getSubscribeSwcAppRouteChangeWhileConnectedMetadata, ON_CONNECTED_SWC_APP_METADATA_KEY, SUBSCRIBE_SWC_APP_ROUTE_CHANGE_WHILE_CONNECTED_METADATA_KEY, buildSwcParameterArgs } from "../decorators/index.js";
4
+ import { findAllLifecycleMetadata, getSubscribeSwcAppMessageMetadata, getSubscribeSwcAppRouteChangeMetadata, ON_CONNECTED_SWC_APP_METADATA_KEY, SUBSCRIBE_SWC_APP_ROUTE_CHANGE_METADATA_KEY, buildSwcParameterArgs } from "../decorators/index.js";
5
5
  import { SwcAppEngine } from "../SwcAppEngine.js";
6
- import { debounceTimeIntervalLock, FunctionUtils } from "@dooboostore/core";
6
+ import { debounceTimeIntervalLock, FunctionUtils, Subject, Observable } from "@dooboostore/core";
7
7
  import { ValidUtils } from "@dooboostore/core-web";
8
8
  import { SwcUtils } from "../utils/Utils.js";
9
+ const routeStateOf = (instance) => instance.__swc_routeState ?? (instance.__swc_routeState = /* @__PURE__ */ new Map());
10
+ const routeParamValues = (sp, pathDataAll) => {
11
+ const queryAll = Object.fromEntries([...new Set(sp.keys())].map((k) => [k, sp.getAll(k)]));
12
+ const pick = (all, at) => Object.fromEntries(Object.entries(all).map(([k, v]) => [k, at === "first" ? v[0] : v[v.length - 1]]));
13
+ const lastOf = (v) => v && v.length ? v[v.length - 1] : void 0;
14
+ const firstQuery = (k) => sp.get(k);
15
+ const firstPath = (k) => pathDataAll[k]?.[0];
16
+ return {
17
+ swcAppRouteQueryParam: firstQuery,
18
+ swcAppRouteFirstQueryParam: firstQuery,
19
+ swcAppRouteLastQueryParam: (k) => lastOf(sp.getAll(k)) ?? null,
20
+ swcAppRouteQueryParams: (k) => sp.getAll(k),
21
+ swcAppRouteQueryParamObject: pick(queryAll, "first"),
22
+ swcAppRouteFirstQueryParamObject: pick(queryAll, "first"),
23
+ swcAppRouteLastQueryParamObject: pick(queryAll, "last"),
24
+ swcAppRouteQueryParamsObject: queryAll,
25
+ swcAppRouteURLSearchParams: sp,
26
+ swcAppRoutePathVariable: firstPath,
27
+ swcAppRouteFirstPathVariable: firstPath,
28
+ swcAppRouteLastPathVariable: (k) => lastOf(pathDataAll[k]),
29
+ swcAppRoutePathVariables: (k) => pathDataAll[k] ?? [],
30
+ swcAppRoutePathVariableObject: pick(pathDataAll, "first"),
31
+ swcAppRouteFirstPathVariableObject: pick(pathDataAll, "first"),
32
+ swcAppRouteLastPathVariableObject: pick(pathDataAll, "last"),
33
+ swcAppRoutePathVariablesObject: pathDataAll
34
+ };
35
+ };
36
+ const matchRoute = (pathOption, instance, re) => {
37
+ let pattern = typeof pathOption === "function" ? pathOption(instance) : pathOption;
38
+ if (!pattern) return { pathData: {}, pathDataAll: {} };
39
+ const path = re.path || "/";
40
+ for (const p of Array.isArray(pattern) ? pattern : [pattern]) {
41
+ const pathData = SwcUtils.parsePathPattern(p, path);
42
+ if (pathData !== null) return { pathData, pathDataAll: SwcUtils.parsePathPatternAll(p, path) ?? {} };
43
+ }
44
+ return null;
45
+ };
9
46
  const isSSR = (i) => {
10
47
  return i.hasAttribute("swc-use-ssr");
11
48
  };
@@ -16,13 +53,18 @@ const removeSSRAttribute = (i) => {
16
53
  i.removeAttribute("swc-use-ssr");
17
54
  };
18
55
  function SwcAppMixin(Base) {
19
- return class SwcAppMixinClass extends Base {
20
- constructor(...args) {
21
- super(...args);
56
+ class SwcAppMixinClass extends Base {
57
+ constructor() {
58
+ super(...arguments);
22
59
  __publicField(this, "__swc_engine", new SwcAppEngine(this));
60
+ __publicField(this, "_swcId");
23
61
  __publicField(this, "_swc_connected_instance", /* @__PURE__ */ new Set());
24
62
  __publicField(this, "_routerSubscription");
25
63
  __publicField(this, "_lastRouterEvent");
64
+ // replay 옵션으로 발행된 타입별 마지막 메시지 1개 보관
65
+ __publicField(this, "_replayedMessages", /* @__PURE__ */ new Map());
66
+ // 코드 구독(observeMessage)용 live 스트림. 데코레이터 구독과 같은 publishMessage에서 흘러나옴.
67
+ __publicField(this, "_messageSubject", new Subject());
26
68
  __publicField(this, "_routeChangeInvocations", 0);
27
69
  __publicField(this, "_connectedInvocations", 0);
28
70
  __publicField(this, "_childrenRouteChangedInterval");
@@ -33,7 +75,8 @@ function SwcAppMixin(Base) {
33
75
  * 부모가 자식들을 강제로 등록해주는 형태로 처리
34
76
  */
35
77
  __publicField(this, "_connected_safari_and_standby", []);
36
- console.log("[SWC-APP-MIXIN] constructor");
78
+ // connect() 전에 붙은 자식들이 기다리는 곳 — connect() 가 엔진을 띄운 뒤 깨운다
79
+ __publicField(this, "_appReadyWaiters", []);
37
80
  }
38
81
  get simpleApplication() {
39
82
  return this.__swc_engine.simpleApplication;
@@ -44,7 +87,8 @@ function SwcAppMixin(Base) {
44
87
  get router() {
45
88
  return this.__swc_engine?.router;
46
89
  }
47
- async _invokeRouteChangeSubscribers(instance, re) {
90
+ // phase: 'live'(기본, 전체 방송) | 'connected' | 'connectedDone' (replay, 해당 trigger만)
91
+ async _invokeRouteChangeSubscribers(instance, re, phase = "live") {
48
92
  if (instance.isConnected === false) return;
49
93
  this._routeChangeInvocations++;
50
94
  if (this._childrenRouteChangedInterval) {
@@ -61,56 +105,51 @@ function SwcAppMixin(Base) {
61
105
  intervalConfig
62
106
  );
63
107
  try {
64
- const routeChangeSubscribers = getSubscribeSwcAppRouteChangeWhileConnectedMetadata(instance);
108
+ const routeChangeSubscribers = getSubscribeSwcAppRouteChangeMetadata(instance);
65
109
  if (routeChangeSubscribers.length > 0) {
110
+ const state = routeStateOf(instance);
111
+ let stopped = false;
66
112
  for (const metadata of routeChangeSubscribers) {
113
+ if (phase !== "live" && (metadata.options?.trigger ?? "connected") !== phase) continue;
114
+ const on = metadata.options?.on ?? "match";
115
+ if (on === "beforeLeave") continue;
67
116
  const methodName = metadata.propertyKey;
68
- let pathPattern = metadata.options?.path;
69
- const filter = metadata.options?.filter;
70
117
  const extractValue = (v) => {
71
- const keyToUse = metadata.options?.valueKey ?? SUBSCRIBE_SWC_APP_ROUTE_CHANGE_WHILE_CONNECTED_METADATA_KEY;
118
+ const keyToUse = metadata.options?.valueKey ?? SUBSCRIBE_SWC_APP_ROUTE_CHANGE_METADATA_KEY;
72
119
  if (v && typeof v === "object" && keyToUse in v) {
73
120
  return v[keyToUse];
74
121
  }
75
122
  return v;
76
123
  };
77
- if (typeof pathPattern === "function") {
78
- pathPattern = pathPattern(instance);
79
- }
80
- let pathMatched = false;
81
- let pathData = null;
82
- if (!pathPattern) {
83
- pathMatched = true;
84
- pathData = {};
85
- } else if (Array.isArray(pathPattern)) {
86
- for (const pattern of pathPattern) {
87
- const data = SwcUtils.parsePathPattern(pattern, re.path || "/");
88
- if (data !== null) {
89
- pathMatched = true;
90
- pathData = data;
91
- break;
92
- }
93
- }
94
- } else {
95
- pathData = SwcUtils.parsePathPattern(pathPattern, re.path || "/");
96
- pathMatched = pathData !== null;
124
+ const match = matchRoute(metadata.options?.path, instance, re);
125
+ const prev = state.get(methodName);
126
+ const signature = match ? JSON.stringify([re.path ?? "", re.search ?? ""]) : "";
127
+ state.set(methodName, match ? { matched: true, signature, pathData: match.pathData, pathDataAll: match.pathDataAll } : { matched: false, signature: "" });
128
+ const shouldRun = on === "match" ? !!match : on === "enter" ? !!match && !prev?.matched : on === "update" ? !!match && !!prev?.matched && prev.signature !== signature : on === "leave" ? !match && !!prev?.matched : false;
129
+ if (stopped || !shouldRun || !instance[methodName]) continue;
130
+ const pathData = match ? match.pathData : prev?.pathData ?? {};
131
+ const pathDataAll = match ? match.pathDataAll : prev?.pathDataAll ?? {};
132
+ const filter = metadata.options?.filter;
133
+ const instanceHelperHostSet = SwcUtils.getHelperAndHostSet(instance, this.config.window);
134
+ const filterPassed = !filter || await filter(this.router, { helper: instanceHelperHostSet, currentThis: instance });
135
+ if (!filterPassed) continue;
136
+ const before = metadata.options?.before;
137
+ const finaly = metadata.options?.finally;
138
+ const beforeReturn = before ? await before(this.router, { helper: instanceHelperHostSet, currentThis: instance }) : void 0;
139
+ const routeEventValue = { ...re, pathData };
140
+ const args = this._buildRouteArgs(instance, methodName, routeEventValue, pathDataAll, beforeReturn);
141
+ let rawResult, error;
142
+ try {
143
+ rawResult = await instance[methodName](...args);
144
+ } catch (e) {
145
+ error = e;
146
+ } finally {
147
+ if (finaly) await finaly(this.router, { helper: instanceHelperHostSet, currentThis: instance }, { args, result: rawResult, error });
97
148
  }
98
- const hostSet = SwcUtils.getHelperAndHostSet(this.config.window, this);
99
- const filterPassed = !filter || filter(this.router, { helper: hostSet, currentThis: instance });
100
- if (pathMatched && filterPassed && instance[methodName]) {
101
- const routeEventValue = { ...re, pathData };
102
- const instanceHelperHostSet = SwcUtils.getHelperAndHostSet(this.config.window, instance);
103
- const instanceHelperSet = SwcUtils.getHelperSet(this.config.window);
104
- const args = buildSwcParameterArgs(instance, methodName, {
105
- routerEvent: routeEventValue,
106
- hostSet: instanceHelperHostSet,
107
- helperHostSet: instanceHelperHostSet,
108
- helperSet: instanceHelperSet
109
- }, [routeEventValue]);
110
- const result = extractValue(await instance[methodName](...args));
111
- if (result !== void 0 && result !== null) {
112
- break;
113
- }
149
+ if (error) throw error;
150
+ const result = extractValue(rawResult);
151
+ if (result !== void 0 && result !== null) {
152
+ stopped = true;
114
153
  }
115
154
  }
116
155
  }
@@ -124,20 +163,75 @@ function SwcAppMixin(Base) {
124
163
  this._routeChangeInvocations = Math.max(0, this._routeChangeInvocations - 1);
125
164
  }
126
165
  }
166
+ /** 라우트 핸들러 인자: @swcAppRouterEvent / host 계열 / @routeChangeBeforeReturn / 라우트 파라미터(query·path 변수) */
167
+ _buildRouteArgs(instance, methodName, routeEventValue, pathDataAll, beforeReturn) {
168
+ const instanceHelperHostSet = SwcUtils.getHelperAndHostSet(instance, this.config.window);
169
+ const sp = routeEventValue.searchParams ?? new URLSearchParams(routeEventValue.search ?? "");
170
+ return buildSwcParameterArgs(
171
+ instance,
172
+ methodName,
173
+ {
174
+ swcAppRouterEvent: routeEventValue,
175
+ hostSet: instanceHelperHostSet,
176
+ helperHostSet: instanceHelperHostSet,
177
+ helperSet: SwcUtils.getHelperSet(this.config.window),
178
+ routeChangeBeforeReturn: beforeReturn,
179
+ ...routeParamValues(sp, pathDataAll)
180
+ },
181
+ [routeEventValue]
182
+ );
183
+ }
184
+ /**
185
+ * on: 'beforeLeave' 구독을 라우터 가드로 등록. 지금 경로는 맞고 다음 경로는 안 맞을 때 핸들러를 부르고,
186
+ * false 를 리턴하면 이동을 취소한다. 요소가 떨어지면 _disconnected 에서 해제.
187
+ */
188
+ _registerLeaveGuards(instance) {
189
+ if (!this.router?.addLeaveGuard) return;
190
+ instance.__swc_leaveGuardOffs?.forEach((off) => off());
191
+ instance.__swc_leaveGuardOffs = getSubscribeSwcAppRouteChangeMetadata(instance).filter((m) => m.options?.on === "beforeLeave").map(
192
+ (metadata) => this.router.addLeaveGuard(async (to, from) => {
193
+ if (instance.isConnected === false || !instance[metadata.propertyKey]) return true;
194
+ const fromMatch = matchRoute(metadata.options?.path, instance, from);
195
+ if (!fromMatch || matchRoute(metadata.options?.path, instance, to)) return true;
196
+ const filter = metadata.options?.filter;
197
+ const helper = SwcUtils.getHelperAndHostSet(instance, this.config.window);
198
+ if (filter && !await filter(this.router, { helper, currentThis: instance })) return true;
199
+ const beforeReturn = metadata.options?.before ? await metadata.options.before(this.router, { helper, currentThis: instance }) : void 0;
200
+ const routeEventValue = { ...from, pathData: fromMatch.pathData, to };
201
+ const args = this._buildRouteArgs(instance, metadata.propertyKey, routeEventValue, fromMatch.pathDataAll, beforeReturn);
202
+ let result, error;
203
+ try {
204
+ result = await instance[metadata.propertyKey](...args);
205
+ } catch (e) {
206
+ error = e;
207
+ } finally {
208
+ if (metadata.options?.finally) await metadata.options.finally(this.router, { helper, currentThis: instance }, { args, result, error });
209
+ }
210
+ if (error) throw error;
211
+ return result !== false;
212
+ })
213
+ );
214
+ }
127
215
  async _connected(instance, option) {
128
216
  if (instance) {
129
217
  if (!this.simpleApplication && !this.config) {
130
- this._connected_safari_and_standby.push(instance);
131
- return;
218
+ if (instance === this) {
219
+ this._connected_safari_and_standby.push(instance);
220
+ return;
221
+ }
222
+ await new Promise((resolve) => this._appReadyWaiters.push(resolve));
132
223
  }
133
224
  this.config.onConnectedChildBefore?.(instance);
134
225
  if (!option?.noIncrements) {
135
226
  this._connectedInvocations++;
136
227
  }
137
228
  this._swc_connected_instance.add(instance);
229
+ const gen = instance.__swc_connectGen;
230
+ const stale = () => instance.__swc_connectGen !== gen;
138
231
  const connectedSwcAppCallBacks = findAllLifecycleMetadata(instance, ON_CONNECTED_SWC_APP_METADATA_KEY);
139
232
  for (let connectedSwcAppCallBack of connectedSwcAppCallBacks) {
140
233
  await instance?._invokeLifecycleMethod?.(connectedSwcAppCallBack.propertyKey);
234
+ if (stale()) return this;
141
235
  }
142
236
  if (this._childrenConnectedDoneInterval) {
143
237
  this.config.window.clearInterval(this._childrenConnectedDoneInterval);
@@ -155,14 +249,16 @@ function SwcAppMixin(Base) {
155
249
  if (this.simpleApplication) {
156
250
  try {
157
251
  if (this.router && this._lastRouterEvent) {
158
- await this._invokeRouteChangeSubscribers(instance, this._lastRouterEvent);
252
+ await this._invokeRouteChangeSubscribers(instance, this._lastRouterEvent, "connected");
159
253
  }
160
254
  } catch (e) {
161
255
  throw e;
162
256
  }
163
257
  }
258
+ if (stale()) return this;
259
+ if (this.simpleApplication) this._registerLeaveGuards(instance);
260
+ this._replayMessagesTo(instance);
164
261
  const isBrowser = ValidUtils.isBrowser();
165
- console.log("------>", isBrowser, this.config?.ssr);
166
262
  if (!isBrowser && this.config?.ssr) {
167
263
  setSSRAttribute(instance);
168
264
  } else {
@@ -172,8 +268,19 @@ function SwcAppMixin(Base) {
172
268
  this.config.onConnectedChildAfter?.(instance);
173
269
  return this;
174
270
  }
175
- async _connectedDone(instance) {
271
+ async _connectedDone(instance, option) {
176
272
  try {
273
+ if (option?.aborted) return;
274
+ this._replayMessagesTo(instance, "connectedDone");
275
+ if (this.simpleApplication) {
276
+ try {
277
+ if (this.router && this._lastRouterEvent) {
278
+ await this._invokeRouteChangeSubscribers(instance, this._lastRouterEvent, "connectedDone");
279
+ }
280
+ } catch (e) {
281
+ throw e;
282
+ }
283
+ }
177
284
  } finally {
178
285
  this._connectedInvocations = Math.max(0, this._connectedInvocations - 1);
179
286
  }
@@ -181,6 +288,9 @@ function SwcAppMixin(Base) {
181
288
  _disconnected(instance) {
182
289
  if (instance) {
183
290
  this._swc_connected_instance.delete(instance);
291
+ instance.__swc_leaveGuardOffs?.forEach((off) => off());
292
+ instance.__swc_leaveGuardOffs = void 0;
293
+ instance.__swc_routeState = void 0;
184
294
  this.config?.onDisconnectedChildAfter?.(instance);
185
295
  }
186
296
  }
@@ -191,28 +301,24 @@ function SwcAppMixin(Base) {
191
301
  await Promise.allSettled(ps);
192
302
  }
193
303
  async connect(config) {
194
- console.log("[SWC-MIXIN] connect");
195
304
  const swcConfig = {
196
305
  routeType: "element",
197
306
  window: config?.window,
198
307
  ...config
199
308
  };
200
309
  await this.__swc_engine.connect(swcConfig);
310
+ this._appReadyWaiters.splice(0).forEach((resolve) => resolve());
201
311
  this._connected_safari_and_standby.forEach((instance) => {
202
312
  this._connected(instance, { noIncrements: true });
203
313
  });
204
314
  if (!this._routerSubscription && this.router) {
205
- const config2 = this.__swc_engine.config;
206
315
  this._routerSubscription = this.router.observable.subscribe(async (route) => {
207
- console.log("[SWC-MIXIN] Router event received:", route.triggerPoint);
208
316
  if (route.triggerPoint === "end") {
209
317
  await this._handleRouteChange(route);
210
318
  }
211
319
  });
212
- if (config2?.path) {
213
- console.log("[DEBUG] Navigating to initial path:", config2.path);
214
- }
215
320
  }
321
+ await this._invokeHook("onSwcAppConnected");
216
322
  }
217
323
  connectedCallback() {
218
324
  super.connectedCallback?.();
@@ -223,7 +329,7 @@ function SwcAppMixin(Base) {
223
329
  const userConfig = FunctionUtils.executeReturn({
224
330
  script: configStr,
225
331
  context: this,
226
- args: SwcUtils.getHelperAndHostSet(win, this)
332
+ args: SwcUtils.getHelperAndHostSet(this, win)
227
333
  });
228
334
  if (userConfig instanceof Promise) {
229
335
  userConfig.then((resolvedConfig) => {
@@ -241,6 +347,7 @@ function SwcAppMixin(Base) {
241
347
  this._connected(this);
242
348
  this.__swc_engine?.config?.onConnected?.(this);
243
349
  this._connectedDone(this);
350
+ void this._invokeHook("onConnected").catch((e) => console.error("[SWC-MIXIN] onConnected error:", e));
244
351
  }
245
352
  disconnectedCallback() {
246
353
  super.disconnectedCallback?.();
@@ -250,6 +357,7 @@ function SwcAppMixin(Base) {
250
357
  this.__swc_engine.disconnect();
251
358
  this.__swc_engine?.config?.onDisconnected?.(this);
252
359
  this._disconnected(this);
360
+ void this._invokeHook("onDisconnected").catch((e) => console.error("[SWC-MIXIN] onDisconnected error:", e));
253
361
  }
254
362
  async routing(path) {
255
363
  await this.router?.go(path);
@@ -264,42 +372,107 @@ function SwcAppMixin(Base) {
264
372
  this.router?.reload();
265
373
  }
266
374
  publishMessage(message) {
375
+ if (message.type) {
376
+ const buf = [...this._replayedMessages.get(message.type) ?? [], message];
377
+ this._replayedMessages.set(message.type, buf.slice(-Math.max(1, this.config?.messageReplayBufferSize ?? 10)));
378
+ }
267
379
  this._swc_connected_instance.forEach((instance) => {
268
380
  this._invokeMessageSubscribers(instance, message);
269
381
  });
382
+ this._messageSubject.next(message);
383
+ }
384
+ connectedElements() {
385
+ return Array.from(this._swc_connected_instance);
386
+ }
387
+ observeMessage(typeOrOptions, options) {
388
+ const { type, subject } = typeof typeOrOptions === "string" ? { ...options, type: typeOrOptions } : { ...typeOrOptions };
389
+ return new Observable((subscriber) => {
390
+ if (type && (subject === "behavior" || subject === "replay")) {
391
+ const buf = this._replayedMessages.get(type) ?? [];
392
+ (subject === "behavior" ? buf.slice(-1) : buf).forEach((m) => subscriber.next(m));
393
+ }
394
+ const sub = this._messageSubject.subscribe((m) => {
395
+ if (!type || m.type === type) subscriber.next(m);
396
+ });
397
+ return () => sub.unsubscribe();
398
+ });
399
+ }
400
+ // hook 실행 + @inject 파라미터 DI 해결 (host 본체 포함.
401
+ // _invokeLifecycleMethod는 host/hostSet 상황 분기가 달라 호스트 본체에서 주입이 안 됨)
402
+ async _invokeHook(methodName) {
403
+ const fn = this[methodName];
404
+ if (typeof fn !== "function") return;
405
+ const manager = this.simpleApplication?.simstanceManager;
406
+ if (!manager) {
407
+ return fn.call(this);
408
+ }
409
+ return manager.executeBindParameterSimPromise({ target: this, targetKey: methodName });
410
+ }
411
+ // 신규 연결 인스턴스 1곳에만 버퍼 재생. 구독자별 subject 선언 기준:
412
+ // - 'behavior': 마지막 1개 / 'replay': 버퍼 전체 시간순 / 미지정·'subject': live만 (재생 안 함)
413
+ // - trigger 'connectedDone'인 구독은 _connectedDone(render 완료 후)에서 재생. phase로 구분.
414
+ // 이미 연결된 인스턴스는 publishMessage 때 live로 받으므로 여기 오지 않음.
415
+ _replayMessagesTo(instance, phase = "connected") {
416
+ const subs = getSubscribeSwcAppMessageMetadata(instance);
417
+ if (!subs || !Array.isArray(subs)) return;
418
+ const seen = /* @__PURE__ */ new Set();
419
+ subs.forEach((meta) => {
420
+ const type = meta.messageType;
421
+ if (!type || seen.has(type)) return;
422
+ seen.add(type);
423
+ if ((meta.trigger ?? "connected") !== phase) return;
424
+ const buf = this._replayedMessages.get(type) ?? [];
425
+ if (meta.subject === "behavior") {
426
+ const last = buf[buf.length - 1];
427
+ if (last) this._invokeMessageSubscribers(instance, last);
428
+ } else if (meta.subject === "replay") {
429
+ buf.forEach((msg) => this._invokeMessageSubscribers(instance, msg));
430
+ }
431
+ });
270
432
  }
271
433
  _invokeMessageSubscribers(instance, message) {
272
- const messageSubscribers = getSubscribeSwcAppMessageWhileConnectedMetadata(instance);
434
+ const messageSubscribers = getSubscribeSwcAppMessageMetadata(instance);
273
435
  if (messageSubscribers && Array.isArray(messageSubscribers)) {
274
436
  messageSubscribers.forEach((metadata) => {
275
- const methodName = metadata.propertyKey;
276
- const messageType = metadata.messageType;
277
- const filter = metadata.filter;
278
- let typeMatched = false;
279
- if (!messageType) {
280
- typeMatched = true;
281
- } else if (message.type === messageType) {
282
- typeMatched = true;
283
- }
284
- let filterMatched = true;
285
- if (filter && typeMatched) {
286
- filterMatched = filter(message, instance);
287
- }
288
- if (typeMatched && filterMatched && typeof instance[methodName] === "function") {
289
- const instanceHelperHostSet = SwcUtils.getHelperAndHostSet(this.config.window, instance);
290
- const instanceHelperSet = SwcUtils.getHelperSet(this.config.window);
291
- const args = buildSwcParameterArgs(instance, methodName, {
292
- appMessage: message,
293
- hostSet: instanceHelperHostSet,
294
- helperHostSet: instanceHelperHostSet,
295
- helperSet: instanceHelperSet
296
- }, [message]);
297
- instance[methodName](...args);
298
- }
437
+ void this._runMessageSubscriber(instance, message, metadata).catch((e) => console.error("[SWC] subscribeSwcAppMessage error:", e));
299
438
  });
300
439
  }
301
440
  }
302
- };
441
+ async _runMessageSubscriber(instance, message, metadata) {
442
+ const methodName = metadata.propertyKey;
443
+ const messageType = metadata.messageType;
444
+ const { filter, before, finally: finaly } = metadata;
445
+ const typeMatched = !messageType || message.type === messageType;
446
+ if (!typeMatched) return;
447
+ if (filter && !await filter(message, instance)) return;
448
+ if (typeof instance[methodName] !== "function") return;
449
+ const instanceHelperHostSet = SwcUtils.getHelperAndHostSet(instance, this.config.window);
450
+ const instanceHelperSet = SwcUtils.getHelperSet(this.config.window);
451
+ const beforeReturn = before ? await before(message, instance) : void 0;
452
+ const args = buildSwcParameterArgs(
453
+ instance,
454
+ methodName,
455
+ {
456
+ appMessage: message,
457
+ hostSet: instanceHelperHostSet,
458
+ helperHostSet: instanceHelperHostSet,
459
+ helperSet: instanceHelperSet,
460
+ appMessageBeforeReturn: beforeReturn
461
+ },
462
+ [message]
463
+ );
464
+ let result, error;
465
+ try {
466
+ result = await instance[methodName](...args);
467
+ } catch (e) {
468
+ error = e;
469
+ } finally {
470
+ if (finaly) await finaly(message, instance, { args, result, error });
471
+ }
472
+ if (error) throw error;
473
+ }
474
+ }
475
+ return SwcAppMixinClass;
303
476
  }
304
477
  export {
305
478
  SwcAppMixin,