@dooboostore/simple-web-component 1.0.54 → 1.0.55
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 +308 -56
- package/dist/cjs/decorators/addEventListener.js +37 -14
- package/dist/cjs/decorators/addEventListener.js.map +2 -2
- package/dist/cjs/decorators/applyAttribute.js +6 -3
- package/dist/cjs/decorators/applyAttribute.js.map +2 -2
- package/dist/cjs/decorators/applyClass.js +18 -2
- package/dist/cjs/decorators/applyClass.js.map +2 -2
- package/dist/cjs/decorators/applyNode.js +10 -3
- package/dist/cjs/decorators/applyNode.js.map +2 -2
- package/dist/cjs/decorators/changedAttribute.js +2 -5
- package/dist/cjs/decorators/changedAttribute.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +13 -2
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/eventMedia.js +2 -5
- package/dist/cjs/decorators/eventMedia.js.map +2 -2
- package/dist/cjs/decorators/fetch.js +216 -82
- package/dist/cjs/decorators/fetch.js.map +3 -3
- package/dist/cjs/decorators/index.js +1 -0
- package/dist/cjs/decorators/index.js.map +2 -2
- package/dist/cjs/decorators/intersectionObserver.js +3 -6
- package/dist/cjs/decorators/intersectionObserver.js.map +2 -2
- package/dist/cjs/decorators/mutationObserver.js +3 -6
- package/dist/cjs/decorators/mutationObserver.js.map +2 -2
- package/dist/cjs/decorators/parameter.js +197 -33
- package/dist/cjs/decorators/parameter.js.map +3 -3
- package/dist/cjs/decorators/persistState.js +474 -0
- package/dist/cjs/decorators/persistState.js.map +7 -0
- package/dist/cjs/decorators/resizeObserver.js +3 -6
- package/dist/cjs/decorators/resizeObserver.js.map +2 -2
- package/dist/cjs/decorators/setInterval.js +2 -5
- package/dist/cjs/decorators/setInterval.js.map +2 -2
- package/dist/cjs/decorators/setTimeout.js +2 -5
- package/dist/cjs/decorators/setTimeout.js.map +2 -2
- package/dist/cjs/decorators/subscribeSwcAppMessage.js.map +1 -1
- package/dist/cjs/elements/SwcAppMixin.js +50 -2
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/decorators/addEventListener.js +38 -15
- package/dist/esm/decorators/addEventListener.js.map +2 -2
- package/dist/esm/decorators/applyAttribute.js +6 -3
- package/dist/esm/decorators/applyAttribute.js.map +2 -2
- package/dist/esm/decorators/applyClass.js +18 -2
- package/dist/esm/decorators/applyClass.js.map +2 -2
- package/dist/esm/decorators/applyNode.js +10 -3
- package/dist/esm/decorators/applyNode.js.map +2 -2
- package/dist/esm/decorators/changedAttribute.js +3 -6
- package/dist/esm/decorators/changedAttribute.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +15 -4
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/eventMedia.js +3 -6
- package/dist/esm/decorators/eventMedia.js.map +2 -2
- package/dist/esm/decorators/fetch.js +216 -82
- package/dist/esm/decorators/fetch.js.map +3 -3
- package/dist/esm/decorators/index.js +1 -0
- package/dist/esm/decorators/index.js.map +2 -2
- package/dist/esm/decorators/intersectionObserver.js +4 -7
- package/dist/esm/decorators/intersectionObserver.js.map +2 -2
- package/dist/esm/decorators/mutationObserver.js +4 -7
- package/dist/esm/decorators/mutationObserver.js.map +2 -2
- package/dist/esm/decorators/parameter.js +197 -33
- package/dist/esm/decorators/parameter.js.map +3 -3
- package/dist/esm/decorators/persistState.js +455 -0
- package/dist/esm/decorators/persistState.js.map +7 -0
- package/dist/esm/decorators/resizeObserver.js +4 -7
- package/dist/esm/decorators/resizeObserver.js.map +2 -2
- package/dist/esm/decorators/setInterval.js +3 -6
- package/dist/esm/decorators/setInterval.js.map +2 -2
- package/dist/esm/decorators/setTimeout.js +3 -6
- package/dist/esm/decorators/setTimeout.js.map +2 -2
- package/dist/esm/decorators/subscribeSwcAppMessage.js.map +1 -1
- package/dist/esm/elements/SwcAppMixin.js +51 -3
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +3226 -2391
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/addEventListener.d.ts +15 -0
- package/dist/types/decorators/addEventListener.d.ts.map +1 -1
- package/dist/types/decorators/applyAttribute.d.ts +1 -0
- package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
- package/dist/types/decorators/applyClass.d.ts.map +1 -1
- package/dist/types/decorators/applyNode.d.ts +4 -2
- package/dist/types/decorators/applyNode.d.ts.map +1 -1
- package/dist/types/decorators/changedAttribute.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/eventMedia.d.ts.map +1 -1
- package/dist/types/decorators/fetch.d.ts +52 -31
- package/dist/types/decorators/fetch.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/intersectionObserver.d.ts.map +1 -1
- package/dist/types/decorators/mutationObserver.d.ts.map +1 -1
- package/dist/types/decorators/parameter.d.ts +169 -31
- package/dist/types/decorators/parameter.d.ts.map +1 -1
- package/dist/types/decorators/persistState.d.ts +66 -0
- package/dist/types/decorators/persistState.d.ts.map +1 -0
- package/dist/types/decorators/resizeObserver.d.ts.map +1 -1
- package/dist/types/decorators/setInterval.d.ts.map +1 -1
- package/dist/types/decorators/setTimeout.d.ts.map +1 -1
- package/dist/types/decorators/subscribeSwcAppMessage.d.ts +1 -1
- package/dist/types/decorators/subscribeSwcAppMessage.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts +12 -0
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +3226 -2391
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +3 -3
- package/src/decorators/addEventListener.ts +23 -15
- package/src/decorators/applyAttribute.ts +8 -3
- package/src/decorators/applyClass.ts +22 -2
- package/src/decorators/applyNode.ts +18 -6
- package/src/decorators/changedAttribute.ts +3 -4
- package/src/decorators/elementDefine.ts +19 -7
- package/src/decorators/eventMedia.ts +3 -6
- package/src/decorators/fetch.ts +270 -140
- package/src/decorators/index.ts +1 -0
- package/src/decorators/intersectionObserver.ts +4 -5
- package/src/decorators/mutationObserver.ts +4 -5
- package/src/decorators/parameter.ts +326 -42
- package/src/decorators/persistState.ts +408 -0
- package/src/decorators/resizeObserver.ts +4 -5
- package/src/decorators/setInterval.ts +3 -4
- package/src/decorators/setTimeout.ts +3 -4
- package/src/decorators/subscribeSwcAppMessage.ts +1 -1
- package/src/elements/SwcAppMixin.ts +64 -5
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { ReflectUtils } from '@dooboostore/core';
|
|
2
|
+
import { SwcUtils } from '../utils/Utils';
|
|
3
|
+
import { QuerySelector, QueryOptions, QueryBaseOptions, resolveQueryElements, pickElements } from './query';
|
|
4
|
+
import { AttributeOptions, AttributeSelector, getAttributeValue } from './applyAttribute';
|
|
5
|
+
import { PersistOptions, persistRead, persistReadAsync } from './persistState';
|
|
6
|
+
import type { HelperHostSet, SwcAppMessageSubject } from '../types';
|
|
2
7
|
|
|
3
8
|
/**
|
|
4
|
-
* @eventObject/@matchedElement/@hostSet/@helperHostSet/@helperSet/@swcAppRouterEvent/@
|
|
9
|
+
* @eventObject/@matchedElement/@hostSet/@helperHostSet/@helperSet/@swcAppRouterEvent/@swcAppMessage/@eventBeforeReturn —
|
|
5
10
|
* @event/lifecycle/subscribeSwcAppRouteChange/subscribeSwcAppMessage
|
|
6
11
|
* 계열 핸들러의 파라미터를 순서 무관하게 선언할 수 있게 해주는 파라미터 데코레이터.
|
|
7
12
|
* @dooboostore/simple-boot의 @Inject와 동일한 인덱스 기반 메타데이터 패턴을 따른다:
|
|
8
13
|
* 데코레이터가 실행되는 순서가 아니라 실제 parameterIndex로 슬롯을 매칭하므로,
|
|
9
14
|
* 사용자가 파라미터 선언 순서를 자유롭게 바꿔도 된다.
|
|
10
15
|
*/
|
|
11
|
-
export type SwcParamKind = 'eventObject' | 'matchedElement' | 'hostSet' | 'helperHostSet' | 'helperSet' | 'swcAppRouterEvent' | '
|
|
16
|
+
export type SwcParamKind = 'eventObject' | 'matchedElement' | 'hostSet' | 'helperHostSet' | 'helperSet' | 'swcAppRouterEvent' | 'swcAppRouter' | 'swcAppSimpleApplication' | 'swcAppHost' | 'swcAppMessage' | 'eventBeforeReturn' | 'swcAppMessageBeforeReturn' | 'routeChangeBeforeReturn' | 'eventMediaBeforeReturn' | 'mutationObserverBeforeReturn' | 'intersectionObserverBeforeReturn' | 'resizeObserverBeforeReturn' | 'changedAttributeBeforeReturn' | 'setTimeoutBeforeReturn' | 'setIntervalBeforeReturn' | 'fetchPromise'
|
|
17
|
+
| 'querySelectorParam' | 'querySelectorAllParam' | 'attributeParam' | 'localStorageParam' | 'sessionStorageParam' | 'cookieParam' | 'indexedDbParam' | 'fetchParam'
|
|
12
18
|
| SwcRouteParamKind;
|
|
13
19
|
|
|
14
|
-
/** 라우트
|
|
20
|
+
/** 라우트 값 (kind 이름 = 데코레이터 이름). 파라미터면 subscribeSwcAppRouteChange 핸들러 인자로, 필드면 SwcApp 이 라우트 변경 때 채운다 */
|
|
15
21
|
export type SwcRouteParamKind =
|
|
16
22
|
| 'swcAppRouteQueryParam' | 'swcAppRouteFirstQueryParam' | 'swcAppRouteLastQueryParam' | 'swcAppRouteQueryParams'
|
|
17
23
|
| 'swcAppRouteQueryParamObject' | 'swcAppRouteFirstQueryParamObject' | 'swcAppRouteLastQueryParamObject' | 'swcAppRouteQueryParamsObject'
|
|
@@ -21,10 +27,10 @@ export type SwcRouteParamKind =
|
|
|
21
27
|
|
|
22
28
|
const SWC_PARAMETER_METADATA_KEY = Symbol.for('simple-web-component:parameter');
|
|
23
29
|
|
|
24
|
-
/** key: @swcAppRouteQueryParam('q') 처럼 키를 받는 파라미터 데코레이터의 키 */
|
|
25
|
-
type SaveParamConfig = { index: number; kind: SwcParamKind; key?:
|
|
30
|
+
/** key: @swcAppRouteQueryParam('q') 처럼 키를 받는 파라미터 데코레이터의 키 (querySelectorParam/attributeParam은 객체를 담는다) */
|
|
31
|
+
type SaveParamConfig = { index: number; kind: SwcParamKind; key?: any };
|
|
26
32
|
|
|
27
|
-
const registerParam = (kind: SwcParamKind, target: Object, propertyKey: string | symbol | undefined, parameterIndex: number, key?:
|
|
33
|
+
const registerParam = (kind: SwcParamKind, target: Object, propertyKey: string | symbol | undefined, parameterIndex: number, key?: any) => {
|
|
28
34
|
if (!propertyKey) return;
|
|
29
35
|
const constructor = target.constructor;
|
|
30
36
|
const saves = (ReflectUtils.getOwnMetadata(SWC_PARAMETER_METADATA_KEY, constructor, propertyKey) ?? []) as SaveParamConfig[];
|
|
@@ -62,9 +68,73 @@ export function swcAppRouterEvent(target: Object, propertyKey: string | symbol,
|
|
|
62
68
|
registerParam('swcAppRouterEvent', target, propertyKey, parameterIndex);
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
/**
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Router 인스턴스($appHost.router)를 주입한다 — @Inject(DI) 없이도 router.go()/pathData 등에 바로 접근.
|
|
73
|
+
* SwcApp 트리 밖(standalone, $appHost 없음)이면 undefined.
|
|
74
|
+
*/
|
|
75
|
+
export function swcAppRouter(target: Object, propertyKey: string | symbol, parameterIndex: number): void {
|
|
76
|
+
registerParam('swcAppRouter', target, propertyKey, parameterIndex);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* SimpleApplication(DI 컨테이너) 인스턴스($appHost.simpleApplication)를 주입한다 —
|
|
81
|
+
* simstanceManager 등 컨테이너 자체를 직접 다뤄야 할 때. 보통은 @inject로 충분하니 그거부터 고려할 것.
|
|
82
|
+
* SwcApp 트리 밖이거나 DI 컨테이너 없이 쓰는 standalone이면 undefined.
|
|
83
|
+
*/
|
|
84
|
+
export function swcAppSimpleApplication(target: Object, propertyKey: string | symbol, parameterIndex: number): void {
|
|
85
|
+
registerParam('swcAppSimpleApplication', target, propertyKey, parameterIndex);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* SwcApp 호스트 엘리먼트 자신($appHost)을 주입한다 — @hostSet으로도 hs.$appHost로 바로 꺼내지지만,
|
|
90
|
+
* HostSet 전체 말고 호스트 하나만 필요할 때 짧게 쓰는 용도. SwcApp 트리 밖이면 undefined.
|
|
91
|
+
*/
|
|
92
|
+
export function swcAppHost(target: Object, propertyKey: string | symbol, parameterIndex: number): void {
|
|
93
|
+
registerParam('swcAppHost', target, propertyKey, parameterIndex);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ─── @swcAppMessage: 파라미터(@subscribeSwcAppMessage 핸들러의 메시지) · 필드(발행될 때마다 최신 메시지) ───
|
|
97
|
+
|
|
98
|
+
/** 필드용 옵션 — @subscribeSwcAppMessage 와 같은 규칙. subject 는 messageType 이 있을 때만 의미가 있다 */
|
|
99
|
+
export type SwcAppMessageFieldOptions = { messageType?: string; subject?: SwcAppMessageSubject };
|
|
100
|
+
export type SwcAppMessageFieldConfig = { propertyKey: string | symbol; messageType?: string; subject?: SwcAppMessageSubject };
|
|
101
|
+
/** 파라미터·필드 겸용 데코레이터. 세 번째 인자가 숫자면 파라미터, 아니면 필드 */
|
|
102
|
+
export type SwcAppMessageDecorator = (target: Object, propertyKey: string | symbol | undefined, parameterIndex?: number) => void;
|
|
103
|
+
|
|
104
|
+
const SWC_MESSAGE_FIELD_METADATA_KEY = Symbol.for('simple-web-component:message-field');
|
|
105
|
+
|
|
106
|
+
const applySwcAppMessage = (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number | undefined, options?: SwcAppMessageFieldOptions) => {
|
|
107
|
+
if (typeof parameterIndex === 'number') return registerParam('swcAppMessage', target, propertyKey, parameterIndex);
|
|
108
|
+
if (propertyKey === undefined) return;
|
|
109
|
+
const constructor = target.constructor;
|
|
110
|
+
const list = (ReflectUtils.getOwnMetadata(SWC_MESSAGE_FIELD_METADATA_KEY, constructor) ?? []) as SwcAppMessageFieldConfig[];
|
|
111
|
+
list.push({ propertyKey, ...(options?.messageType ? { messageType: options.messageType } : {}), ...(options?.subject ? { subject: options.subject } : {}) });
|
|
112
|
+
ReflectUtils.defineMetadata(SWC_MESSAGE_FIELD_METADATA_KEY, list, constructor);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/** 상속 체인 전체의 메시지 필드 설정 */
|
|
116
|
+
export const getSwcAppMessageFieldMetadata = (target: any): SwcAppMessageFieldConfig[] => {
|
|
117
|
+
const constructor = target instanceof Function ? target : target?.constructor;
|
|
118
|
+
if (!constructor) return [];
|
|
119
|
+
return (ReflectUtils.findAllMetadata<SwcAppMessageFieldConfig[]>(SWC_MESSAGE_FIELD_METADATA_KEY, constructor) || []).flat();
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 파라미터: @subscribeSwcAppMessage 핸들러의 SwcAppMessage 를 주입한다 — onMsg(@swcAppMessage m) { ... }
|
|
124
|
+
* 필드: SwcApp 이 메시지를 발행할 때마다 그 필드에 최신 SwcAppMessage 를 넣는다 (같은 요소의 구독 핸들러보다 먼저).
|
|
125
|
+
* @swcAppMessage last?: SwcAppMessage 전 타입 (live만)
|
|
126
|
+
* @swcAppMessage('login') login?: SwcAppMessage login (live만 — subject 기본값)
|
|
127
|
+
* @swcAppMessage('login', { subject: 'behavior' }) login? 늦게 붙어도 마지막 1개로 채움
|
|
128
|
+
* @swcAppMessage({ messageType: 'login', subject: 'replay' }) ... 버퍼를 시간순으로 넣음 (마지막 값이 남음)
|
|
129
|
+
*/
|
|
130
|
+
export function swcAppMessage(target: Object, propertyKey: string | symbol | undefined, parameterIndex?: number): void;
|
|
131
|
+
export function swcAppMessage(messageType: string, options?: Omit<SwcAppMessageFieldOptions, 'messageType'>): SwcAppMessageDecorator;
|
|
132
|
+
export function swcAppMessage(options: SwcAppMessageFieldOptions): SwcAppMessageDecorator;
|
|
133
|
+
export function swcAppMessage(a: any, b?: any, c?: any): any {
|
|
134
|
+
// 데코레이터로 바로 불렸으면 (target, propertyKey, …) — propertyKey 는 문자열/심볼
|
|
135
|
+
if (typeof b === 'string' || typeof b === 'symbol') return applySwcAppMessage(a, b, c);
|
|
136
|
+
const options: SwcAppMessageFieldOptions = typeof a === 'string' ? { ...(b ?? {}), messageType: a } : { ...(a ?? {}) };
|
|
137
|
+
return ((target, propertyKey, parameterIndex) => applySwcAppMessage(target, propertyKey, parameterIndex, options)) as SwcAppMessageDecorator;
|
|
68
138
|
}
|
|
69
139
|
|
|
70
140
|
/**
|
|
@@ -79,10 +149,11 @@ export function eventBeforeReturn(target: Object, propertyKey: string | symbol,
|
|
|
79
149
|
/**
|
|
80
150
|
* @subscribeSwcAppMessage 의 before 훅이 이번 호출에 리턴한 값을 주입한다.
|
|
81
151
|
* (before에서 async로 준비한 데이터를 핸들러가 받는 용도. 없으면 undefined)
|
|
82
|
-
* 예: onMsg(@
|
|
152
|
+
* 예: onMsg(@swcAppMessage m, @swcAppMessageBeforeReturn prepared) { ... }
|
|
153
|
+
* 핸들러 호출마다 생기는 값이라 파라미터 전용이다 (필드에는 붙이지 않는다).
|
|
83
154
|
*/
|
|
84
|
-
export function
|
|
85
|
-
registerParam('
|
|
155
|
+
export function swcAppMessageBeforeReturn(target: Object, propertyKey: string | symbol, parameterIndex: number): void {
|
|
156
|
+
registerParam('swcAppMessageBeforeReturn', target, propertyKey, parameterIndex);
|
|
86
157
|
}
|
|
87
158
|
|
|
88
159
|
/**
|
|
@@ -133,11 +204,114 @@ export function setIntervalBeforeReturn(target: Object, propertyKey: string | sy
|
|
|
133
204
|
}
|
|
134
205
|
|
|
135
206
|
/**
|
|
136
|
-
* @fetch(
|
|
137
|
-
*
|
|
207
|
+
* @fetch(before 모드)가 시작한 요청의 Promise 를 주입한다. 메서드는 요청을 기다리지 않고 바로 불리고,
|
|
208
|
+
* 기다릴지·어떻게 처리할지(then/catch/finally)는 메서드가 정한다. 실패는 reject, 프레임워크가 끊으면 끝나지 않는다.
|
|
209
|
+
* 예: load(@fetchPromise p: Promise<Post>) { return p.then(post => post.title); }
|
|
138
210
|
*/
|
|
139
|
-
export function
|
|
140
|
-
registerParam('
|
|
211
|
+
export function fetchPromise(target: Object, propertyKey: string | symbol, parameterIndex: number): void {
|
|
212
|
+
registerParam('fetchPromise', target, propertyKey, parameterIndex);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 셀렉터로 찾은 DOM 요소 하나를 주입한다 — 필드용 @query 데코레이터(query.ts)와 같은 탐색 엔진 재사용.
|
|
217
|
+
* options.root로 'light'/'shadow'/'auto'(기본)/'all' 탐색 범위를 그대로 지정할 수 있다(@query와 동일).
|
|
218
|
+
* onConnectedAfter/addEventListener/setInterval 등 "자동 트리거" 메서드에서만 채워진다
|
|
219
|
+
* (buildCommonKindValues를 거치는 호출부 한정 — 임의로 직접 호출하는 메서드에는 못 꽂는다).
|
|
220
|
+
* URL의 query parameter와 헷갈리지 않도록 "query"가 아니라 "querySelector"로 이름 붙였다.
|
|
221
|
+
* 예: onReady(@querySelectorParam('#name') input: HTMLInputElement) { ... }
|
|
222
|
+
*/
|
|
223
|
+
export function querySelectorParam(selector: QuerySelector, options?: QueryOptions): ParameterDecorator {
|
|
224
|
+
return (target, propertyKey, parameterIndex) => registerParam('querySelectorParam', target, propertyKey, parameterIndex, { selector, options });
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** @querySelectorParam의 복수형 — 매칭된 모든 요소를 배열로 주입한다(= @queryAll, pick 고정 'all'). */
|
|
228
|
+
export function querySelectorAllParam(selector: QuerySelector, options?: Omit<QueryOptions, 'pick'>): ParameterDecorator {
|
|
229
|
+
return (target, propertyKey, parameterIndex) => registerParam('querySelectorAllParam', target, propertyKey, parameterIndex, { selector, options });
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ─── root별 편의 alias — query.ts의 queryShadow/queryLight/queryAllRoots/queryAllShadow/queryAllLight/queryAllAll과 1:1 대응 ───
|
|
233
|
+
|
|
234
|
+
/** shadow DOM에서 요소 하나를 찾아 주입한다 (= @querySelectorParam(selector, {root:'shadow'})). */
|
|
235
|
+
export function querySelectorShadowParam(selector: QuerySelector, options?: QueryBaseOptions): ParameterDecorator {
|
|
236
|
+
return querySelectorParam(selector, { ...(options ?? {}), root: 'shadow' });
|
|
237
|
+
}
|
|
238
|
+
/** light DOM에서 요소 하나를 찾아 주입한다. */
|
|
239
|
+
export function querySelectorLightParam(selector: QuerySelector, options?: QueryBaseOptions): ParameterDecorator {
|
|
240
|
+
return querySelectorParam(selector, { ...(options ?? {}), root: 'light' });
|
|
241
|
+
}
|
|
242
|
+
/** shadow+light 모두에서 찾아 하나만 주입한다 (pick 기본 'first') — "All"은 탐색 범위가 전부라는 뜻. */
|
|
243
|
+
export function querySelectorAllRootsParam(selector: QuerySelector, options?: QueryBaseOptions): ParameterDecorator {
|
|
244
|
+
return querySelectorParam(selector, { ...(options ?? {}), root: 'all' });
|
|
245
|
+
}
|
|
246
|
+
/** shadow DOM에서 매칭된 모든 요소를 배열로 주입한다. */
|
|
247
|
+
export function querySelectorAllShadowParam(selector: QuerySelector, options?: Omit<QueryBaseOptions, 'pick'>): ParameterDecorator {
|
|
248
|
+
return querySelectorAllParam(selector, { ...(options ?? {}), root: 'shadow' });
|
|
249
|
+
}
|
|
250
|
+
/** light DOM에서 매칭된 모든 요소를 배열로 주입한다. */
|
|
251
|
+
export function querySelectorAllLightParam(selector: QuerySelector, options?: Omit<QueryBaseOptions, 'pick'>): ParameterDecorator {
|
|
252
|
+
return querySelectorAllParam(selector, { ...(options ?? {}), root: 'light' });
|
|
253
|
+
}
|
|
254
|
+
/** shadow+light 모두에서 매칭된 모든 요소를 배열로 주입한다. */
|
|
255
|
+
export function querySelectorAllAllParam(selector: QuerySelector, options?: Omit<QueryBaseOptions, 'pick'>): ParameterDecorator {
|
|
256
|
+
return querySelectorAllParam(selector, { ...(options ?? {}), root: 'all' });
|
|
257
|
+
}
|
|
258
|
+
// skipped: queryIn처럼 root+pick을 동적으로 조합하는 팩토리형 alias — 필요해지면 그때 추가.
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* attribute 값을 주입한다 — 필드용 @attribute 데코레이터(applyAttribute.ts)와 같은 엔진 재사용.
|
|
262
|
+
* - attributeParam('data-x', options?) — 이 엘리먼트 자신의 attribute.
|
|
263
|
+
* - attributeParam(selector, 'data-x', options?) — selector(+options.root)로 찾은 다른 요소의 attribute.
|
|
264
|
+
* 필드용 @attribute(selector?, attrName, options?)와 동일한 2-form 시그니처.
|
|
265
|
+
*/
|
|
266
|
+
export function attributeParam(attributeName: string, options?: AttributeOptions): ParameterDecorator;
|
|
267
|
+
export function attributeParam(selector: AttributeSelector, attributeName: string, options?: AttributeOptions): ParameterDecorator;
|
|
268
|
+
export function attributeParam(selectorOrName: AttributeSelector | string, attrNameOrOptions?: string | AttributeOptions, maybeOptions?: AttributeOptions): ParameterDecorator {
|
|
269
|
+
const withSelector = typeof attrNameOrOptions === 'string';
|
|
270
|
+
const attributeName = withSelector ? attrNameOrOptions as string : selectorOrName as string;
|
|
271
|
+
const options = (withSelector ? maybeOptions : attrNameOrOptions as AttributeOptions | undefined) ?? {};
|
|
272
|
+
const resolved: AttributeOptions & { selector?: AttributeSelector } = withSelector ? { ...options, selector: selectorOrName as AttributeSelector } : options;
|
|
273
|
+
return (target, propertyKey, parameterIndex) => registerParam('attributeParam', target, propertyKey, parameterIndex, { attributeName, options: resolved });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const keyedStorageParam = (kind: SwcParamKind) => (key: string, options?: Omit<PersistOptions, 'storage'>): ParameterDecorator =>
|
|
277
|
+
(target, propertyKey, parameterIndex) => registerParam(kind, target, propertyKey, parameterIndex, { key, options });
|
|
278
|
+
|
|
279
|
+
/** localStorage에 저장된 값을 주입한다 (persistState.ts의 persistRead 재사용). */
|
|
280
|
+
export const localStorageParam = keyedStorageParam('localStorageParam');
|
|
281
|
+
/** sessionStorage에 저장된 값을 주입한다. */
|
|
282
|
+
export const sessionStorageParam = keyedStorageParam('sessionStorageParam');
|
|
283
|
+
/** 쿠키에 저장된 값을 주입한다. */
|
|
284
|
+
export const cookieParam = keyedStorageParam('cookieParam');
|
|
285
|
+
/**
|
|
286
|
+
* IndexedDB에 저장된 값을 주입한다 — 단, 비동기 백엔드라 (동기 호출 계약상) resolve된 값이 아니라
|
|
287
|
+
* **Promise 자체**가 꽂힌다. 메서드 쪽에서 타입을 Promise로 받고 await 하면 된다.
|
|
288
|
+
* 예: async onReady(@indexedDbParam('wow') wow: Promise<string>) { const v = await wow; ... }
|
|
289
|
+
*/
|
|
290
|
+
export const indexedDbParam = keyedStorageParam('indexedDbParam');
|
|
291
|
+
|
|
292
|
+
/** url/init 자리에 고정값 대신 (currentThis, helper) => ... 콜백을 줄 수 있다 — query.ts 함수 셀렉터·fetch.ts FetchUrlFactory와 동일한 패턴. */
|
|
293
|
+
export type FetchParamUrlFactory = (currentThis: any, helper: HelperHostSet) => RequestInfo | URL;
|
|
294
|
+
export type FetchParamInitFactory = (currentThis: any, helper: HelperHostSet) => RequestInit | undefined;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* 간단 버전 fetch — 네이티브 fetch(url, init) 그대로, 성공하면 Content-Type 보고 JSON/텍스트로 파싱한 뒤
|
|
298
|
+
* **그 Promise를 주입**한다 (indexedDbParam과 동일한 계약 — 비동기라 resolve된 값이 아니라 Promise 자체).
|
|
299
|
+
* abort/abortPrevious 같은 건 없다 — 그런 게 필요하면 @fetch/@fetchManual + @fetchPromise를 쓴다
|
|
300
|
+
* (disconnect 시 자동 abort까지 되는 더 안전한 버전). 이건 딱 "그냥 fetch 결과를 파라미터로 받고 싶다"는 경우용.
|
|
301
|
+
*
|
|
302
|
+
* url/init은 고정값뿐 아니라 (currentThis, helper) => ... 콜백도 받는다 — 인스턴스 필드를 참조해서
|
|
303
|
+
* URL이나 body를 동적으로 만들어야 할 때 쓴다.
|
|
304
|
+
* 예: async onReady(@fetchParam('/api/products/1') p: Promise<Product>) { const data = await p; }
|
|
305
|
+
* 예: async onSave(@fetchParam(
|
|
306
|
+
* (self) => `/api/products/${self.productId}`,
|
|
307
|
+
* (self) => ({ method: 'POST', body: JSON.stringify({ qty: self.qty }) })
|
|
308
|
+
* ) p: Promise<any>) { const result = await p; }
|
|
309
|
+
*/
|
|
310
|
+
export function fetchParam(
|
|
311
|
+
input: RequestInfo | URL | FetchParamUrlFactory,
|
|
312
|
+
init?: RequestInit | FetchParamInitFactory
|
|
313
|
+
): ParameterDecorator {
|
|
314
|
+
return (target, propertyKey, parameterIndex) => registerParam('fetchParam', target, propertyKey, parameterIndex, { input, init });
|
|
141
315
|
}
|
|
142
316
|
|
|
143
317
|
export const getParameterMetadata = (target: any, propertyKey: string | symbol): SaveParamConfig[] => {
|
|
@@ -148,6 +322,8 @@ export const getParameterMetadata = (target: any, propertyKey: string | symbol):
|
|
|
148
322
|
/**
|
|
149
323
|
* 위 파라미터 데코레이터 메타데이터가 하나라도 있으면 kind별 값을 index 순서에 맞게
|
|
150
324
|
* 배열로 조립하고, 하나도 없으면 기존 위치 인자(legacyArgs)를 그대로 반환한다 — 완전 하위호환.
|
|
325
|
+
* 데코레이터가 안 붙은 인덱스는 legacyArgs의 같은 자리 값으로 채운다 — 그래야
|
|
326
|
+
* onId(nv, old, @querySelectorParam('#x') el) 처럼 기존 위치 인자와 섞어 써도 nv/old가 undefined로 날아가지 않는다.
|
|
151
327
|
*/
|
|
152
328
|
export const buildSwcParameterArgs = (
|
|
153
329
|
target: any,
|
|
@@ -157,8 +333,8 @@ export const buildSwcParameterArgs = (
|
|
|
157
333
|
): any[] => {
|
|
158
334
|
const saves = getParameterMetadata(target, propertyKey);
|
|
159
335
|
if (saves.length === 0) return legacyArgs;
|
|
160
|
-
const maxIndex = Math.max(...saves.map(s => s.index));
|
|
161
|
-
const args: any[] =
|
|
336
|
+
const maxIndex = Math.max(Math.max(...saves.map(s => s.index)), legacyArgs.length - 1);
|
|
337
|
+
const args: any[] = legacyArgs.slice(0, maxIndex + 1);
|
|
162
338
|
for (const s of saves) {
|
|
163
339
|
const value = kindValues[s.kind];
|
|
164
340
|
// 키를 받는 kind 는 kindValues 에 (key) => 값 resolver 가 들어 있다
|
|
@@ -167,46 +343,154 @@ export const buildSwcParameterArgs = (
|
|
|
167
343
|
return args;
|
|
168
344
|
};
|
|
169
345
|
|
|
170
|
-
|
|
346
|
+
/** @fetchParam 전용 — 네이티브 fetch, 실패하면 상태코드를 담아 던지고, 성공하면 Content-Type 보고 json/text로 파싱. */
|
|
347
|
+
const simpleFetchJsonOrText = async (win: Window, input: RequestInfo | URL, init?: RequestInit): Promise<any> => {
|
|
348
|
+
const fetchFn: typeof fetch = typeof (win as any)?.fetch === 'function' ? (win as any).fetch.bind(win) : fetch;
|
|
349
|
+
const res = await fetchFn(input, init);
|
|
350
|
+
if (!res.ok) throw new Error(`[SWC] @fetchParam failed: ${res.status} ${String(input)}`);
|
|
351
|
+
const text = await res.text();
|
|
352
|
+
if (!text) return undefined;
|
|
353
|
+
return (res.headers.get('Content-Type') ?? '').includes('json') ? JSON.parse(text) : text;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* @querySelectorParam/@querySelectorAllParam/@attributeParam/@local·session·cookie·indexedDb·fetchParam 리졸버만 —
|
|
358
|
+
* hostSet 3종과 분리해서, 이미 자기만의 hostSet/helperHostSet 계산 방식을 가진 호출부
|
|
359
|
+
* (예: elementDefine._invokeLifecycleMethod)에서도 기존 계산은 그대로 둔 채 이 kind들만 얹을 수 있게 한다.
|
|
360
|
+
* indexedDB/fetch는 비동기라 (동기 호출 계약상) resolve된 값이 아니라 Promise 자체를 반환한다 —
|
|
361
|
+
* 둘 다 async 함수라 호출 즉시 Promise를 반환하므로 await 없이도 동기 리졸버 계약을 지킨다.
|
|
362
|
+
*/
|
|
363
|
+
export const buildDomStorageKindValues = (inst: any, win: Window): Partial<Record<SwcParamKind, any>> => ({
|
|
364
|
+
querySelectorParam: (cfg: { selector: QuerySelector; options?: QueryOptions }) =>
|
|
365
|
+
pickElements(resolveQueryElements(inst, cfg.selector, cfg.options ?? {}, win), cfg.options?.pick ?? 'first'),
|
|
366
|
+
querySelectorAllParam: (cfg: { selector: QuerySelector; options?: Omit<QueryOptions, 'pick'> }) =>
|
|
367
|
+
pickElements(resolveQueryElements(inst, cfg.selector, cfg.options ?? {}, win), 'all'),
|
|
368
|
+
attributeParam: (cfg: { attributeName: string; options?: AttributeOptions & { selector?: AttributeSelector } }) =>
|
|
369
|
+
getAttributeValue(inst, cfg.attributeName, cfg.options),
|
|
370
|
+
localStorageParam: (cfg: { key: string; options?: Omit<PersistOptions, 'storage'> }) =>
|
|
371
|
+
persistRead(inst, cfg.key, { ...(cfg.options as any), storage: 'local' }),
|
|
372
|
+
sessionStorageParam: (cfg: { key: string; options?: Omit<PersistOptions, 'storage'> }) =>
|
|
373
|
+
persistRead(inst, cfg.key, { ...(cfg.options as any), storage: 'session' }),
|
|
374
|
+
cookieParam: (cfg: { key: string; options?: Omit<PersistOptions, 'storage'> }) =>
|
|
375
|
+
persistRead(inst, cfg.key, { ...(cfg.options as any), storage: 'cookie' }),
|
|
376
|
+
indexedDbParam: (cfg: { key: string; options?: Omit<PersistOptions, 'storage'> }): Promise<any> =>
|
|
377
|
+
persistReadAsync(inst, cfg.key, { ...(cfg.options as any), storage: 'indexeddb' }),
|
|
378
|
+
fetchParam: (cfg: { input: RequestInfo | URL | FetchParamUrlFactory; init?: RequestInit | FetchParamInitFactory }): Promise<any> => {
|
|
379
|
+
const helper = SwcUtils.getHelperAndHostSet(inst, win);
|
|
380
|
+
const resolvedInput = typeof cfg.input === 'function' ? (cfg.input as FetchParamUrlFactory)(inst, helper) : cfg.input;
|
|
381
|
+
const resolvedInit = typeof cfg.init === 'function' ? (cfg.init as FetchParamInitFactory)(inst, helper) : cfg.init;
|
|
382
|
+
return simpleFetchJsonOrText(win, resolvedInput, resolvedInit);
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* 트리거 데코레이터(onConnectedAfter/addEventListener/setInterval/setTimeout/옵저버 계열/...)가
|
|
388
|
+
* 공통으로 필요로 하는 kindValues 베이스 — hostSet/helperSet/helperHostSet 3종 + buildDomStorageKindValues를
|
|
389
|
+
* 한 번에 만든다. 각 호출부는 자기만의 kind(eventObject, setTimeoutBeforeReturn 등)만 추가로 섞어 쓰면 된다.
|
|
390
|
+
*/
|
|
391
|
+
export const buildCommonKindValues = (inst: any, win: Window): Partial<Record<SwcParamKind, any>> => {
|
|
392
|
+
const hostSet = SwcUtils.getHostSet(inst);
|
|
393
|
+
const helperSet = SwcUtils.getHelperSet(win);
|
|
394
|
+
const helperHostSet = { ...helperSet, ...hostSet, $this: inst };
|
|
395
|
+
return {
|
|
396
|
+
hostSet, helperSet, helperHostSet,
|
|
397
|
+
swcAppRouter: hostSet.$appHost?.router,
|
|
398
|
+
swcAppSimpleApplication: hostSet.$appHost?.simpleApplication,
|
|
399
|
+
swcAppHost: hostSet.$appHost,
|
|
400
|
+
...buildDomStorageKindValues(inst, win)
|
|
401
|
+
};
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// ─── 라우트 파라미터 (@subscribeSwcAppRouteChange 핸들러 파라미터 · 필드) ───
|
|
171
405
|
// 규칙: 접두어 없음 = First, First/Last = 같은 키가 여러 번일 때 첫/마지막 값, 복수형 = 모든 값 배열.
|
|
406
|
+
// 같은 데코레이터를 파라미터에도, 필드에도 붙인다. 파라미터면 핸들러 인자로, 필드면 SwcApp 이 라우트가 바뀔 때마다
|
|
407
|
+
// (그리고 요소가 붙을 때 마지막 라우트로) 그 필드에 값을 넣는다 — SwcAppMixin._applyRouteFields.
|
|
408
|
+
|
|
409
|
+
/** 파라미터·필드 겸용 데코레이터. 세 번째 인자가 숫자면 파라미터, 아니면(필드) undefined */
|
|
410
|
+
export type SwcRouteParamDecorator = (target: Object, propertyKey: string | symbol | undefined, parameterIndex?: number) => void;
|
|
411
|
+
/** path 변수 필드용 — 어떤 패턴에서 값을 뽑을지. @subscribeSwcAppRouteChange 의 path 와 같은 형태 */
|
|
412
|
+
export type SwcRouteFieldOptions = { path?: string | string[] | ((currentThis: any) => string | string[]) };
|
|
413
|
+
/** 맨 데코레이터로도(@swcAppRoutePathVariableObject), 옵션을 받는 팩토리로도(@swcAppRoutePathVariableObject({ path })) 쓴다 */
|
|
414
|
+
export type SwcRouteParamDecoratorOrFactory = SwcRouteParamDecorator & ((options?: SwcRouteFieldOptions) => SwcRouteParamDecorator);
|
|
415
|
+
|
|
416
|
+
export type SwcRouteFieldConfig = { propertyKey: string | symbol; kind: SwcRouteParamKind; key?: string; path?: SwcRouteFieldOptions['path'] };
|
|
417
|
+
const SWC_ROUTE_FIELD_METADATA_KEY = Symbol.for('simple-web-component:route-field');
|
|
418
|
+
|
|
419
|
+
const isPathKind = (kind: SwcRouteParamKind) => kind.includes('PathVariable');
|
|
420
|
+
|
|
421
|
+
const registerRouteField = (kind: SwcRouteParamKind, target: Object, propertyKey: string | symbol, key?: string, options?: SwcRouteFieldOptions) => {
|
|
422
|
+
if (isPathKind(kind) && !options?.path) {
|
|
423
|
+
// 필드에는 @subscribeSwcAppRouteChange 처럼 매칭할 패턴이 없다 → 늘 비게 된다. 실수일 가능성이 커서 알린다.
|
|
424
|
+
console.warn(`[SWC] @${kind} on field "${String(propertyKey)}" needs { path } (e.g. { path: '/user/{id}' }) — it will stay empty without it.`);
|
|
425
|
+
}
|
|
426
|
+
const constructor = target.constructor;
|
|
427
|
+
const list = (ReflectUtils.getOwnMetadata(SWC_ROUTE_FIELD_METADATA_KEY, constructor) ?? []) as SwcRouteFieldConfig[];
|
|
428
|
+
list.push({ propertyKey, kind, ...(key !== undefined ? { key } : {}), ...(options?.path ? { path: options.path } : {}) });
|
|
429
|
+
ReflectUtils.defineMetadata(SWC_ROUTE_FIELD_METADATA_KEY, list, constructor);
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
/** 상속 체인 전체의 라우트 필드 설정 (부모 → 자식). 같은 필드를 자식이 다시 선언하면 자식 것이 뒤에 와서 이긴다 */
|
|
433
|
+
export const getSwcRouteFieldMetadata = (target: any): SwcRouteFieldConfig[] => {
|
|
434
|
+
const constructor = target instanceof Function ? target : target?.constructor;
|
|
435
|
+
if (!constructor) return [];
|
|
436
|
+
return (ReflectUtils.findAllMetadata<SwcRouteFieldConfig[]>(SWC_ROUTE_FIELD_METADATA_KEY, constructor) || []).flat();
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
const applyRouteParam = (kind: SwcRouteParamKind, target: Object, propertyKey: string | symbol | undefined, parameterIndex: number | undefined, key?: string, options?: SwcRouteFieldOptions) => {
|
|
440
|
+
if (typeof parameterIndex === 'number') return registerParam(kind, target, propertyKey, parameterIndex, key);
|
|
441
|
+
if (propertyKey !== undefined) registerRouteField(kind, target, propertyKey, key, options);
|
|
442
|
+
};
|
|
172
443
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
444
|
+
/** 키를 받는 query 계열: @swcAppRouteQueryParam('tag') */
|
|
445
|
+
const keyedQueryParam = (kind: SwcRouteParamKind) => (key: string): SwcRouteParamDecorator =>
|
|
446
|
+
(target, propertyKey, parameterIndex) => applyRouteParam(kind, target, propertyKey, parameterIndex, key);
|
|
447
|
+
/** 키를 받는 path 변수 계열: @swcAppRoutePathVariable('id') · 필드면 @swcAppRoutePathVariable('id', { path: '/user/{id}' }) */
|
|
448
|
+
const keyedPathParam = (kind: SwcRouteParamKind) => (key: string, options?: SwcRouteFieldOptions): SwcRouteParamDecorator =>
|
|
449
|
+
(target, propertyKey, parameterIndex) => applyRouteParam(kind, target, propertyKey, parameterIndex, key, options);
|
|
450
|
+
/** 키 없는 query 계열 — 맨 데코레이터: @swcAppRouteQueryParamObject */
|
|
451
|
+
const queryParam = (kind: SwcRouteParamKind): SwcRouteParamDecorator =>
|
|
452
|
+
(target, propertyKey, parameterIndex) => applyRouteParam(kind, target, propertyKey, parameterIndex);
|
|
453
|
+
/** 키 없는 path 변수 계열 — 맨 데코레이터(파라미터) 또는 팩토리(필드: { path }) 둘 다 */
|
|
454
|
+
const pathParam = (kind: SwcRouteParamKind): SwcRouteParamDecoratorOrFactory =>
|
|
455
|
+
function (this: unknown, ...args: any[]) {
|
|
456
|
+
// 데코레이터 호출은 (target, propertyKey, …) 로 인자가 2개 이상, 팩토리 호출은 (options?) 하나 이하
|
|
457
|
+
if (args.length >= 2) return applyRouteParam(kind, args[0], args[1], args[2]);
|
|
458
|
+
const options = args[0] as SwcRouteFieldOptions | undefined;
|
|
459
|
+
return ((target, propertyKey, parameterIndex) => applyRouteParam(kind, target, propertyKey, parameterIndex, undefined, options)) as SwcRouteParamDecorator;
|
|
460
|
+
} as SwcRouteParamDecoratorOrFactory;
|
|
177
461
|
|
|
178
462
|
/** ?tag=a&tag=b → @swcAppRouteQueryParam('tag') = 'a' (없으면 null) */
|
|
179
|
-
export const swcAppRouteQueryParam =
|
|
463
|
+
export const swcAppRouteQueryParam = keyedQueryParam('swcAppRouteQueryParam');
|
|
180
464
|
/** = swcAppRouteQueryParam */
|
|
181
|
-
export const swcAppRouteFirstQueryParam =
|
|
465
|
+
export const swcAppRouteFirstQueryParam = keyedQueryParam('swcAppRouteFirstQueryParam');
|
|
182
466
|
/** ?tag=a&tag=b → 'b' */
|
|
183
|
-
export const swcAppRouteLastQueryParam =
|
|
467
|
+
export const swcAppRouteLastQueryParam = keyedQueryParam('swcAppRouteLastQueryParam');
|
|
184
468
|
/** ?tag=a&tag=b → ['a', 'b'] */
|
|
185
|
-
export const swcAppRouteQueryParams =
|
|
469
|
+
export const swcAppRouteQueryParams = keyedQueryParam('swcAppRouteQueryParams');
|
|
186
470
|
/** ?tag=a&tag=b → { tag: 'a' } */
|
|
187
|
-
export const swcAppRouteQueryParamObject =
|
|
471
|
+
export const swcAppRouteQueryParamObject = queryParam('swcAppRouteQueryParamObject');
|
|
188
472
|
/** = swcAppRouteQueryParamObject */
|
|
189
|
-
export const swcAppRouteFirstQueryParamObject =
|
|
473
|
+
export const swcAppRouteFirstQueryParamObject = queryParam('swcAppRouteFirstQueryParamObject');
|
|
190
474
|
/** ?tag=a&tag=b → { tag: 'b' } */
|
|
191
|
-
export const swcAppRouteLastQueryParamObject =
|
|
475
|
+
export const swcAppRouteLastQueryParamObject = queryParam('swcAppRouteLastQueryParamObject');
|
|
192
476
|
/** ?tag=a&tag=b → { tag: ['a', 'b'] } */
|
|
193
|
-
export const swcAppRouteQueryParamsObject =
|
|
477
|
+
export const swcAppRouteQueryParamsObject = queryParam('swcAppRouteQueryParamsObject');
|
|
194
478
|
/** URLSearchParams 그대로 */
|
|
195
|
-
export const swcAppRouteURLSearchParams =
|
|
479
|
+
export const swcAppRouteURLSearchParams = queryParam('swcAppRouteURLSearchParams');
|
|
196
480
|
|
|
197
|
-
/** '/a/{id}/b/{id}' ← '/a/1/b/2' → @swcAppRoutePathVariable('id') = '1' */
|
|
198
|
-
export const swcAppRoutePathVariable =
|
|
481
|
+
/** '/a/{id}/b/{id}' ← '/a/1/b/2' → @swcAppRoutePathVariable('id') = '1' · 필드: @swcAppRoutePathVariable('id', { path: '/a/{id}/b/{id}' }) */
|
|
482
|
+
export const swcAppRoutePathVariable = keyedPathParam('swcAppRoutePathVariable');
|
|
199
483
|
/** = swcAppRoutePathVariable */
|
|
200
|
-
export const swcAppRouteFirstPathVariable =
|
|
484
|
+
export const swcAppRouteFirstPathVariable = keyedPathParam('swcAppRouteFirstPathVariable');
|
|
201
485
|
/** → '2' */
|
|
202
|
-
export const swcAppRouteLastPathVariable =
|
|
486
|
+
export const swcAppRouteLastPathVariable = keyedPathParam('swcAppRouteLastPathVariable');
|
|
203
487
|
/** → ['1', '2'] */
|
|
204
|
-
export const swcAppRoutePathVariables =
|
|
205
|
-
/** → { id: '1' } */
|
|
206
|
-
export const swcAppRoutePathVariableObject =
|
|
488
|
+
export const swcAppRoutePathVariables = keyedPathParam('swcAppRoutePathVariables');
|
|
489
|
+
/** → { id: '1' } · 필드: @swcAppRoutePathVariableObject({ path: '/a/{id}/b/{id}' }) */
|
|
490
|
+
export const swcAppRoutePathVariableObject = pathParam('swcAppRoutePathVariableObject');
|
|
207
491
|
/** = swcAppRoutePathVariableObject */
|
|
208
|
-
export const swcAppRouteFirstPathVariableObject =
|
|
492
|
+
export const swcAppRouteFirstPathVariableObject = pathParam('swcAppRouteFirstPathVariableObject');
|
|
209
493
|
/** → { id: '2' } */
|
|
210
|
-
export const swcAppRouteLastPathVariableObject =
|
|
494
|
+
export const swcAppRouteLastPathVariableObject = pathParam('swcAppRouteLastPathVariableObject');
|
|
211
495
|
/** → { id: ['1', '2'] } */
|
|
212
|
-
export const swcAppRoutePathVariablesObject =
|
|
496
|
+
export const swcAppRoutePathVariablesObject = pathParam('swcAppRoutePathVariablesObject');
|