@dooboostore/simple-web-component 1.0.25 → 1.0.27
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.
- package/README.md +284 -68
- package/dist/cjs/decorators/attribute.js +32 -43
- package/dist/cjs/decorators/attribute.js.map +3 -3
- package/dist/cjs/decorators/elementDefine.js +33 -19
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/index.js +1 -0
- package/dist/cjs/decorators/index.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +5 -5
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/query.js +4 -4
- package/dist/cjs/decorators/query.js.map +2 -2
- package/dist/cjs/decorators/queryAll.js +4 -4
- package/dist/cjs/decorators/queryAll.js.map +2 -2
- package/dist/cjs/decorators/subscribeSwcAppRouteChange.js +59 -0
- package/dist/cjs/decorators/subscribeSwcAppRouteChange.js.map +7 -0
- package/dist/cjs/elements/SwcAppEngine.js +18 -63
- package/dist/cjs/elements/SwcAppEngine.js.map +3 -3
- package/dist/cjs/elements/SwcAppMixin.js +103 -24
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/elements/register.js +0 -1
- package/dist/cjs/elements/register.js.map +2 -2
- package/dist/cjs/utils/Utils.js +18 -0
- package/dist/cjs/utils/Utils.js.map +3 -3
- package/dist/esm/decorators/attribute.js +32 -43
- package/dist/esm/decorators/attribute.js.map +3 -3
- package/dist/esm/decorators/elementDefine.js +34 -20
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/index.js +1 -0
- package/dist/esm/decorators/index.js.map +2 -2
- package/dist/esm/decorators/lifecycles.js +5 -5
- package/dist/esm/decorators/lifecycles.js.map +2 -2
- package/dist/esm/decorators/query.js +4 -4
- package/dist/esm/decorators/query.js.map +2 -2
- package/dist/esm/decorators/queryAll.js +4 -4
- package/dist/esm/decorators/queryAll.js.map +2 -2
- package/dist/esm/decorators/subscribeSwcAppRouteChange.js +40 -0
- package/dist/esm/decorators/subscribeSwcAppRouteChange.js.map +7 -0
- package/dist/esm/elements/SwcAppEngine.js +18 -63
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +103 -24
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/elements/register.js +0 -1
- package/dist/esm/elements/register.js.map +2 -2
- package/dist/esm/utils/Utils.js +18 -0
- package/dist/esm/utils/Utils.js.map +3 -3
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +135 -2470
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/attribute.d.ts +0 -1
- package/dist/types/decorators/attribute.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/index.d.ts +1 -0
- package/dist/types/decorators/index.d.ts.map +1 -1
- package/dist/types/decorators/lifecycles.d.ts +2 -2
- package/dist/types/decorators/lifecycles.d.ts.map +1 -1
- package/dist/types/decorators/query.d.ts +1 -1
- package/dist/types/decorators/query.d.ts.map +1 -1
- package/dist/types/decorators/queryAll.d.ts +1 -1
- package/dist/types/decorators/queryAll.d.ts.map +1 -1
- package/dist/types/decorators/subscribeSwcAppRouteChange.d.ts +18 -0
- package/dist/types/decorators/subscribeSwcAppRouteChange.d.ts.map +1 -0
- package/dist/types/elements/SwcAppEngine.d.ts +3 -5
- package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts +9 -0
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/types/elements/register.d.ts +1 -1
- package/dist/types/elements/register.d.ts.map +1 -1
- package/dist/types/utils/Utils.d.ts +3 -0
- package/dist/types/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +135 -2470
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +3 -3
- package/src/decorators/attribute.ts +62 -53
- package/src/decorators/elementDefine.ts +79 -30
- package/src/decorators/index.ts +1 -0
- package/src/decorators/lifecycles.ts +2 -2
- package/src/decorators/query.ts +5 -5
- package/src/decorators/queryAll.ts +8 -7
- package/src/decorators/subscribeSwcAppRouteChange.ts +71 -0
- package/src/elements/SwcAppEngine.ts +25 -81
- package/src/elements/SwcAppMixin.ts +143 -28
- package/src/elements/register.ts +0 -2
- package/src/utils/Utils.ts +33 -0
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import { SwcAppEngine, SwcAttributeConfigType } from './SwcAppEngine';
|
|
2
|
-
import {SwcAppInterface} from
|
|
1
|
+
import { SwcAppEngine, SwcAttributeConfigType, SwcConfigType } from './SwcAppEngine';
|
|
2
|
+
import { SwcAppInterface } from '../types';
|
|
3
|
+
import { SwcUtils } from '../utils/Utils';
|
|
4
|
+
import { FunctionUtils, Subscription } from '@dooboostore/core';
|
|
5
|
+
import { RouterEventType } from '@dooboostore/core-web';
|
|
6
|
+
import { getSubscribeSwcAppRouteChangeMetadata } from '../decorators/subscribeSwcAppRouteChange';
|
|
3
7
|
|
|
4
8
|
export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Base: T) {
|
|
5
|
-
return class extends Base implements SwcAppInterface{
|
|
9
|
+
return class extends Base implements SwcAppInterface {
|
|
6
10
|
__swc_engine = new SwcAppEngine(this as any);
|
|
11
|
+
_swc_connected_instance = new Set<any>();
|
|
12
|
+
_routerSubscription?: Subscription;
|
|
13
|
+
_lastRouterEvent?: RouterEventType;
|
|
7
14
|
|
|
8
15
|
get simpleApplication() {
|
|
9
16
|
return this.__swc_engine.simpleApplication;
|
|
@@ -12,51 +19,159 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
12
19
|
return this.__swc_engine.router;
|
|
13
20
|
}
|
|
14
21
|
|
|
22
|
+
_invokeRouteChangeSubscribers(instance: any, re: RouterEventType) {
|
|
23
|
+
const routeChangeSubscribers = getSubscribeSwcAppRouteChangeMetadata(instance);
|
|
24
|
+
if (routeChangeSubscribers && Array.isArray(routeChangeSubscribers)) {
|
|
25
|
+
routeChangeSubscribers.forEach((metadata: any) => {
|
|
26
|
+
const methodName = metadata.propertyKey || metadata;
|
|
27
|
+
const pathPattern = metadata.pathPattern;
|
|
28
|
+
const filter = metadata.filter;
|
|
29
|
+
|
|
30
|
+
// Path pattern matching (support both string and array)
|
|
31
|
+
let pathMatched = false;
|
|
32
|
+
let pathData: any = null;
|
|
33
|
+
|
|
34
|
+
if (!pathPattern) {
|
|
35
|
+
// pathPattern이 없으면 모든 경로 매칭 (와일드카드)
|
|
36
|
+
pathMatched = true;
|
|
37
|
+
pathData = {};
|
|
38
|
+
} else if (Array.isArray(pathPattern)) {
|
|
39
|
+
// 배열: 하나라도 매칭되면 OK
|
|
40
|
+
for (const pattern of pathPattern) {
|
|
41
|
+
const data = SwcUtils.parsePathPattern(pattern, re.path || '/');
|
|
42
|
+
if (data !== null) {
|
|
43
|
+
pathMatched = true;
|
|
44
|
+
pathData = data;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
// 문자열
|
|
50
|
+
pathData = SwcUtils.parsePathPattern(pathPattern, re.path || '/');
|
|
51
|
+
pathMatched = pathData !== null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Filter validation
|
|
55
|
+
const filterPassed = !filter || filter(this.router!);
|
|
56
|
+
|
|
57
|
+
// Invoke method if conditions pass
|
|
58
|
+
if (pathMatched && filterPassed) {
|
|
59
|
+
instance[methodName]?.(re, pathData || {});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
_connected(instance: any) {
|
|
66
|
+
// console.log('------------------>', instance);
|
|
67
|
+
if (instance) {
|
|
68
|
+
this._swc_connected_instance.add(instance);
|
|
69
|
+
|
|
70
|
+
// Notify current route subscribers immediately after connection
|
|
71
|
+
if (this.router && this._lastRouterEvent) {
|
|
72
|
+
this._invokeRouteChangeSubscribers(instance, this._lastRouterEvent);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_disconnected(instance: any) {
|
|
78
|
+
if (instance) {
|
|
79
|
+
this._swc_connected_instance.delete(instance);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_handleRouteChange(route: RouterEventType) {
|
|
84
|
+
if (route.triggerPoint === 'end') {
|
|
85
|
+
// Iterate through all connected component instances
|
|
86
|
+
this._swc_connected_instance.forEach((instance: any) => {
|
|
87
|
+
this._invokeRouteChangeSubscribers(instance, route);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Save last router event
|
|
92
|
+
this._lastRouterEvent = route;
|
|
93
|
+
}
|
|
94
|
+
|
|
15
95
|
async connect(config?: SwcAttributeConfigType) {
|
|
96
|
+
const swcConfig = {
|
|
97
|
+
routeType: 'element',
|
|
98
|
+
window: config.window,
|
|
99
|
+
...config
|
|
100
|
+
} as SwcConfigType;
|
|
101
|
+
|
|
16
102
|
const mode = config?.connectMode || 'direct';
|
|
17
103
|
|
|
18
|
-
if (mode
|
|
19
|
-
await this.__swc_engine.connect(
|
|
104
|
+
if (mode === 'direct') {
|
|
105
|
+
await this.__swc_engine.connect(swcConfig);
|
|
20
106
|
this.setAttribute('swc-connect-mode', 'direct');
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const parent = this.parentNode;
|
|
25
|
-
if (!parent) {
|
|
26
|
-
await this.__swc_engine.connect(config);
|
|
107
|
+
} else if (mode === 'swap' && !this.parentNode) {
|
|
108
|
+
await this.__swc_engine.connect(swcConfig);
|
|
27
109
|
this.setAttribute('swc-connect-mode', 'direct');
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
110
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
111
|
+
const clonedApp = this.cloneNode(true) as any;
|
|
112
|
+
clonedApp.style.display = 'none';
|
|
113
|
+
this.parentNode.insertBefore(clonedApp, this.nextSibling);
|
|
34
114
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
115
|
+
try {
|
|
116
|
+
await clonedApp.connect({ ...(config || {}), connectMode: 'direct' });
|
|
117
|
+
if (this.parentNode) {
|
|
118
|
+
this.parentNode.removeChild(this);
|
|
119
|
+
}
|
|
120
|
+
clonedApp.setAttribute('swc-connect-mode', 'swap');
|
|
121
|
+
clonedApp.style.display = '';
|
|
122
|
+
} catch (e) {
|
|
123
|
+
if (clonedApp.parentNode) {
|
|
124
|
+
clonedApp.parentNode.removeChild(clonedApp);
|
|
125
|
+
}
|
|
126
|
+
throw e;
|
|
45
127
|
}
|
|
46
|
-
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// console.log('vvvvvvv222222', this.router);
|
|
131
|
+
// Subscribe to router changes after connect
|
|
132
|
+
if (!this._routerSubscription && this.router) {
|
|
133
|
+
this._routerSubscription = this.router.observable.subscribe((route: RouterEventType) => {
|
|
134
|
+
// console.log('Route changed:', route);
|
|
135
|
+
this._handleRouteChange(route);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Navigate to initial path if specified
|
|
139
|
+
// const config = this.__swc_engine.config;
|
|
140
|
+
// if (config?.path) {
|
|
141
|
+
// this.router.go(config.path);
|
|
142
|
+
// }
|
|
47
143
|
}
|
|
48
144
|
}
|
|
49
145
|
|
|
50
146
|
connectedCallback() {
|
|
51
147
|
// @ts-ignore
|
|
52
148
|
if (super.connectedCallback) super.connectedCallback();
|
|
53
|
-
|
|
149
|
+
|
|
150
|
+
const configStr = this.getAttribute('swc-get-application-config');
|
|
151
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
152
|
+
if (configStr && win) {
|
|
153
|
+
try {
|
|
154
|
+
// console.log('vvvvvvvvvvvvvvvv->>>>', SwcUtils.findNearestSwcHost(this.host), SwcUtils.getHostSet(this.host))
|
|
155
|
+
const userConfig = FunctionUtils.executeReturn({
|
|
156
|
+
script: configStr,
|
|
157
|
+
context: this,
|
|
158
|
+
args: SwcUtils.getHelperAndHostSet(win, SwcUtils.findNearestSwcHost(this))
|
|
159
|
+
});
|
|
160
|
+
this.connect(userConfig);
|
|
161
|
+
} catch (e) {
|
|
162
|
+
console.error('[SWC-APP-ENGINE] Script execution failed:', e);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
54
166
|
this.__swc_engine?.config?.onConnected?.(this);
|
|
55
167
|
}
|
|
56
168
|
|
|
57
169
|
disconnectedCallback() {
|
|
58
170
|
// @ts-ignore
|
|
59
171
|
if (super.disconnectedCallback) super.disconnectedCallback();
|
|
172
|
+
this._routerSubscription?.unsubscribe();
|
|
173
|
+
this._routerSubscription = undefined;
|
|
174
|
+
this._lastRouterEvent = undefined;
|
|
60
175
|
this.__swc_engine.disconnect();
|
|
61
176
|
this.__swc_engine?.config?.onDisconnected?.(this);
|
|
62
177
|
}
|
package/src/elements/register.ts
CHANGED
package/src/utils/Utils.ts
CHANGED
|
@@ -282,4 +282,37 @@ export namespace SwcUtils {
|
|
|
282
282
|
...loopContext
|
|
283
283
|
} as any;
|
|
284
284
|
};
|
|
285
|
+
|
|
286
|
+
export const parsePathPattern = (pattern: string | undefined, currentPath: string): { [key: string]: string } | null => {
|
|
287
|
+
// pattern이 null/undefined면 와일드카드 (모든 경로 매칭)
|
|
288
|
+
if (pattern === null || pattern === undefined) return {};
|
|
289
|
+
|
|
290
|
+
// 공백만 있는 패턴도 와일드카드
|
|
291
|
+
const trimmedPattern = pattern.trim();
|
|
292
|
+
if (trimmedPattern === '' && pattern !== '') return {}; // 공백 문자만 있는 경우
|
|
293
|
+
|
|
294
|
+
// 패턴을 정규식으로 변환
|
|
295
|
+
// 지원 형식:
|
|
296
|
+
// {id} → ([^/]+) 기본 (/ 제외한 모든 문자)
|
|
297
|
+
// {tail:.*} → (.*) 정규표현식 직접 지정
|
|
298
|
+
// {slug:[a-z0-9-]+} → ([a-z0-9-]+)
|
|
299
|
+
const paramNames: string[] = [];
|
|
300
|
+
const regexPattern = trimmedPattern.replace(/{(\w+)(?::(.+?))?}/g, (match, paramName, customRegex) => {
|
|
301
|
+
paramNames.push(paramName);
|
|
302
|
+
// customRegex가 있으면 사용, 없으면 기본값 ([^/]+)
|
|
303
|
+
return `(${customRegex || '[^/]+'})`;
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
307
|
+
const match = currentPath.match(regex);
|
|
308
|
+
|
|
309
|
+
if (!match) return null;
|
|
310
|
+
|
|
311
|
+
const result: { [key: string]: string } = {};
|
|
312
|
+
paramNames.forEach((name, index) => {
|
|
313
|
+
result[name] = match[index + 1];
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
return result;
|
|
317
|
+
};
|
|
285
318
|
}
|