@dooboostore/simple-web-component 1.0.50 → 1.0.52

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