@wcstack/fetch 1.4.0

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.
@@ -0,0 +1,93 @@
1
+ interface IWritableTagNames {
2
+ fetch?: string;
3
+ fetchHeader?: string;
4
+ fetchBody?: string;
5
+ }
6
+ interface IWritableConfig {
7
+ autoTrigger?: boolean;
8
+ triggerAttribute?: string;
9
+ tagNames?: IWritableTagNames;
10
+ }
11
+ interface IWcBindableProperty {
12
+ readonly name: string;
13
+ readonly event: string;
14
+ readonly getter?: (event: Event) => any;
15
+ }
16
+ interface IWcBindable {
17
+ readonly protocol: "wc-bindable";
18
+ readonly version: number;
19
+ readonly properties: IWcBindableProperty[];
20
+ }
21
+ /**
22
+ * HTTP error returned when the server responds with a non-ok status (>= 400).
23
+ */
24
+ interface WcsFetchHttpError {
25
+ status: number;
26
+ statusText: string;
27
+ body: string;
28
+ }
29
+ /**
30
+ * Value types for FetchCore (headless) — the 4 async state properties.
31
+ * Use with `bind()` from `@wc-bindable/core` for compile-time type checking.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * interface User { id: number; name: string; }
36
+ * const core = new FetchCore();
37
+ * bind(core, (name: keyof WcsFetchCoreValues<User>, value) => { ... });
38
+ * ```
39
+ */
40
+ interface WcsFetchCoreValues<T = unknown> {
41
+ value: T;
42
+ loading: boolean;
43
+ error: WcsFetchHttpError | Error | null;
44
+ status: number;
45
+ }
46
+ /**
47
+ * Value types for the Shell (`<wcs-fetch>`) — extends Core with `trigger`.
48
+ * Use with framework adapters for compile-time type checking.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * // React
53
+ * interface User { id: number; name: string; }
54
+ * const [ref, values] = useWcBindable<HTMLElement, WcsFetchValues<User>>();
55
+ * values.value // User
56
+ * values.loading // boolean
57
+ * ```
58
+ */
59
+ interface WcsFetchValues<T = unknown> extends WcsFetchCoreValues<T> {
60
+ trigger: boolean;
61
+ }
62
+
63
+ declare function bootstrapFetch(userConfig?: IWritableConfig): void;
64
+
65
+ interface FetchRequestOptions {
66
+ method?: string;
67
+ headers?: Record<string, string>;
68
+ body?: BodyInit | null;
69
+ contentType?: string | null;
70
+ forceText?: boolean;
71
+ }
72
+ declare class FetchCore extends EventTarget {
73
+ static wcBindable: IWcBindable;
74
+ private _target;
75
+ private _value;
76
+ private _loading;
77
+ private _error;
78
+ private _status;
79
+ private _abortController;
80
+ constructor(target?: EventTarget);
81
+ get value(): any;
82
+ get loading(): boolean;
83
+ get error(): any;
84
+ get status(): number;
85
+ private _setLoading;
86
+ private _setError;
87
+ private _setResponse;
88
+ abort(): void;
89
+ fetch(url: string, options?: FetchRequestOptions): Promise<any>;
90
+ }
91
+
92
+ export { FetchCore, bootstrapFetch };
93
+ export type { FetchRequestOptions, IWritableConfig, IWritableTagNames, WcsFetchCoreValues, WcsFetchHttpError, WcsFetchValues };
@@ -0,0 +1,380 @@
1
+ const _config = {
2
+ autoTrigger: true,
3
+ triggerAttribute: "data-fetchtarget",
4
+ tagNames: {
5
+ fetch: "wcs-fetch",
6
+ fetchHeader: "wcs-fetch-header",
7
+ fetchBody: "wcs-fetch-body",
8
+ },
9
+ };
10
+ const config = _config;
11
+ function setConfig(partialConfig) {
12
+ if (typeof partialConfig.autoTrigger === "boolean") {
13
+ _config.autoTrigger = partialConfig.autoTrigger;
14
+ }
15
+ if (typeof partialConfig.triggerAttribute === "string") {
16
+ _config.triggerAttribute = partialConfig.triggerAttribute;
17
+ }
18
+ if (partialConfig.tagNames) {
19
+ Object.assign(_config.tagNames, partialConfig.tagNames);
20
+ }
21
+ }
22
+
23
+ function raiseError(message) {
24
+ throw new Error(`[@wcstack/fetch] ${message}`);
25
+ }
26
+
27
+ class FetchCore extends EventTarget {
28
+ static wcBindable = {
29
+ protocol: "wc-bindable",
30
+ version: 1,
31
+ properties: [
32
+ { name: "value", event: "wcs-fetch:response", getter: (e) => e.detail.value },
33
+ { name: "loading", event: "wcs-fetch:loading-changed" },
34
+ { name: "error", event: "wcs-fetch:error" },
35
+ { name: "status", event: "wcs-fetch:response", getter: (e) => e.detail.status },
36
+ ],
37
+ };
38
+ _target;
39
+ _value = null;
40
+ _loading = false;
41
+ _error = null;
42
+ _status = 0;
43
+ _abortController = null;
44
+ constructor(target) {
45
+ super();
46
+ this._target = target ?? this;
47
+ }
48
+ get value() {
49
+ return this._value;
50
+ }
51
+ get loading() {
52
+ return this._loading;
53
+ }
54
+ get error() {
55
+ return this._error;
56
+ }
57
+ get status() {
58
+ return this._status;
59
+ }
60
+ _setLoading(loading) {
61
+ this._loading = loading;
62
+ this._target.dispatchEvent(new CustomEvent("wcs-fetch:loading-changed", {
63
+ detail: loading,
64
+ bubbles: true,
65
+ }));
66
+ }
67
+ _setError(error) {
68
+ this._error = error;
69
+ this._target.dispatchEvent(new CustomEvent("wcs-fetch:error", {
70
+ detail: error,
71
+ bubbles: true,
72
+ }));
73
+ }
74
+ _setResponse(value, status) {
75
+ this._value = value;
76
+ this._status = status;
77
+ this._target.dispatchEvent(new CustomEvent("wcs-fetch:response", {
78
+ detail: { value, status },
79
+ bubbles: true,
80
+ }));
81
+ }
82
+ abort() {
83
+ if (this._abortController) {
84
+ this._abortController.abort();
85
+ this._abortController = null;
86
+ }
87
+ }
88
+ async fetch(url, options = {}) {
89
+ if (!url) {
90
+ raiseError("url attribute is required.");
91
+ }
92
+ // 進行中のリクエストをキャンセル
93
+ this.abort();
94
+ this._abortController = new AbortController();
95
+ const { signal } = this._abortController;
96
+ this._setLoading(true);
97
+ this._error = null;
98
+ const { method = "GET", headers = {}, body = null, contentType = null, forceText = false, } = options;
99
+ try {
100
+ if (contentType && !headers["Content-Type"]) {
101
+ headers["Content-Type"] = contentType;
102
+ }
103
+ const requestInit = {
104
+ method,
105
+ headers,
106
+ signal,
107
+ };
108
+ if (method !== "GET" && method !== "HEAD" && body !== null) {
109
+ requestInit.body = body;
110
+ }
111
+ const response = await globalThis.fetch(url, requestInit);
112
+ this._status = response.status;
113
+ if (!response.ok) {
114
+ const errorBody = await response.text().catch(() => "");
115
+ const error = { status: response.status, statusText: response.statusText, body: errorBody };
116
+ this._setError(error);
117
+ this._setLoading(false);
118
+ return null;
119
+ }
120
+ if (forceText) {
121
+ const text = await response.text();
122
+ this._setResponse(text, response.status);
123
+ }
124
+ else {
125
+ const responseContentType = response.headers.get("Content-Type") || "";
126
+ if (responseContentType.includes("application/json")) {
127
+ const data = await response.json();
128
+ this._setResponse(data, response.status);
129
+ }
130
+ else {
131
+ const text = await response.text();
132
+ this._setResponse(text, response.status);
133
+ }
134
+ }
135
+ this._setLoading(false);
136
+ return this._value;
137
+ }
138
+ catch (e) {
139
+ if (e.name === "AbortError") {
140
+ this._setLoading(false);
141
+ return null;
142
+ }
143
+ this._setError(e);
144
+ this._setLoading(false);
145
+ return null;
146
+ }
147
+ finally {
148
+ this._abortController = null;
149
+ }
150
+ }
151
+ }
152
+
153
+ class Fetch extends HTMLElement {
154
+ static wcBindable = {
155
+ ...FetchCore.wcBindable,
156
+ properties: [
157
+ ...FetchCore.wcBindable.properties,
158
+ { name: "trigger", event: "wcs-fetch:trigger-changed" },
159
+ ],
160
+ };
161
+ static get observedAttributes() { return ["url"]; }
162
+ _core;
163
+ _body = null;
164
+ _trigger = false;
165
+ constructor() {
166
+ super();
167
+ this._core = new FetchCore(this);
168
+ }
169
+ get url() {
170
+ return this.getAttribute("url") || "";
171
+ }
172
+ set url(value) {
173
+ this.setAttribute("url", value);
174
+ }
175
+ get method() {
176
+ return (this.getAttribute("method") || "GET").toUpperCase();
177
+ }
178
+ set method(value) {
179
+ this.setAttribute("method", value);
180
+ }
181
+ get target() {
182
+ return this.getAttribute("target");
183
+ }
184
+ set target(value) {
185
+ if (value === null) {
186
+ this.removeAttribute("target");
187
+ }
188
+ else {
189
+ this.setAttribute("target", value);
190
+ }
191
+ }
192
+ get value() {
193
+ return this._core.value;
194
+ }
195
+ get loading() {
196
+ return this._core.loading;
197
+ }
198
+ get error() {
199
+ return this._core.error;
200
+ }
201
+ get status() {
202
+ return this._core.status;
203
+ }
204
+ get manual() {
205
+ return this.hasAttribute("manual");
206
+ }
207
+ set manual(value) {
208
+ if (value) {
209
+ this.setAttribute("manual", "");
210
+ }
211
+ else {
212
+ this.removeAttribute("manual");
213
+ }
214
+ }
215
+ get body() {
216
+ return this._body;
217
+ }
218
+ set body(value) {
219
+ this._body = value;
220
+ }
221
+ get trigger() {
222
+ return this._trigger;
223
+ }
224
+ set trigger(value) {
225
+ const v = !!value;
226
+ if (v) {
227
+ this._trigger = true;
228
+ this.fetch().finally(() => {
229
+ this._trigger = false;
230
+ this.dispatchEvent(new CustomEvent("wcs-fetch:trigger-changed", {
231
+ detail: false,
232
+ bubbles: true,
233
+ }));
234
+ });
235
+ }
236
+ }
237
+ _collectHeaders() {
238
+ const headers = {};
239
+ const headerElements = this.querySelectorAll(config.tagNames.fetchHeader);
240
+ for (const el of headerElements) {
241
+ const name = el.headerName;
242
+ const value = el.headerValue;
243
+ if (name) {
244
+ headers[name] = value;
245
+ }
246
+ }
247
+ return headers;
248
+ }
249
+ _collectBody() {
250
+ // JS API経由のbodyが優先
251
+ if (this._body !== null) {
252
+ return {
253
+ body: typeof this._body === "string" ? this._body : JSON.stringify(this._body),
254
+ contentType: typeof this._body === "string" ? null : "application/json",
255
+ };
256
+ }
257
+ // サブタグからbodyを取得
258
+ const bodyElement = this.querySelector(config.tagNames.fetchBody);
259
+ if (bodyElement) {
260
+ return {
261
+ body: bodyElement.bodyContent || null,
262
+ contentType: bodyElement.contentType,
263
+ };
264
+ }
265
+ return { body: null, contentType: null };
266
+ }
267
+ abort() {
268
+ this._core.abort();
269
+ }
270
+ async fetch() {
271
+ const headers = this._collectHeaders();
272
+ const { body, contentType } = this._collectBody();
273
+ const result = await this._core.fetch(this.url, {
274
+ method: this.method,
275
+ headers,
276
+ body,
277
+ contentType,
278
+ forceText: !!this.target,
279
+ });
280
+ // HTML置換モード
281
+ if (this.target && result !== null) {
282
+ const targetElement = document.getElementById(this.target);
283
+ if (targetElement) {
284
+ targetElement.innerHTML = result;
285
+ }
286
+ }
287
+ // bodyをリセット(一回限りの使用)
288
+ this._body = null;
289
+ return result;
290
+ }
291
+ attributeChangedCallback(name, _oldValue, newValue) {
292
+ if (name === "url" && this.isConnected && !this.manual && newValue) {
293
+ this.fetch();
294
+ }
295
+ }
296
+ connectedCallback() {
297
+ this.style.display = "none";
298
+ if (!this.manual && this.url) {
299
+ this.fetch();
300
+ }
301
+ }
302
+ disconnectedCallback() {
303
+ this.abort();
304
+ }
305
+ }
306
+
307
+ class FetchHeader extends HTMLElement {
308
+ connectedCallback() {
309
+ this.style.display = "none";
310
+ }
311
+ get headerName() {
312
+ return this.getAttribute("name") || "";
313
+ }
314
+ get headerValue() {
315
+ return this.getAttribute("value") || "";
316
+ }
317
+ }
318
+
319
+ class FetchBody extends HTMLElement {
320
+ constructor() {
321
+ super();
322
+ // スロットなしのShadow DOMでlight DOM(bodyテキスト)の描画を抑制
323
+ this.attachShadow({ mode: "open" });
324
+ }
325
+ get contentType() {
326
+ return this.getAttribute("type") || "application/json";
327
+ }
328
+ get bodyContent() {
329
+ return this.textContent?.trim() || "";
330
+ }
331
+ }
332
+
333
+ function registerComponents() {
334
+ if (!customElements.get(config.tagNames.fetch)) {
335
+ customElements.define(config.tagNames.fetch, Fetch);
336
+ }
337
+ if (!customElements.get(config.tagNames.fetchHeader)) {
338
+ customElements.define(config.tagNames.fetchHeader, FetchHeader);
339
+ }
340
+ if (!customElements.get(config.tagNames.fetchBody)) {
341
+ customElements.define(config.tagNames.fetchBody, FetchBody);
342
+ }
343
+ }
344
+
345
+ let registered = false;
346
+ function handleClick(event) {
347
+ const target = event.target;
348
+ if (!(target instanceof Element))
349
+ return;
350
+ const triggerElement = target.closest(`[${config.triggerAttribute}]`);
351
+ if (!triggerElement)
352
+ return;
353
+ const fetchId = triggerElement.getAttribute(config.triggerAttribute);
354
+ if (!fetchId)
355
+ return;
356
+ const fetchElement = document.getElementById(fetchId);
357
+ if (!fetchElement || !(fetchElement instanceof Fetch))
358
+ return;
359
+ event.preventDefault();
360
+ fetchElement.fetch();
361
+ }
362
+ function registerAutoTrigger() {
363
+ if (registered)
364
+ return;
365
+ registered = true;
366
+ document.addEventListener("click", handleClick);
367
+ }
368
+
369
+ function bootstrapFetch(userConfig) {
370
+ if (userConfig) {
371
+ setConfig(userConfig);
372
+ }
373
+ registerComponents();
374
+ if (config.autoTrigger) {
375
+ registerAutoTrigger();
376
+ }
377
+ }
378
+
379
+ export { FetchCore, bootstrapFetch };
380
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/raiseError.ts","../src/core/FetchCore.ts","../src/components/Fetch.ts","../src/components/FetchHeader.ts","../src/components/FetchBody.ts","../src/registerComponents.ts","../src/autoTrigger.ts","../src/bootstrapFetch.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\r\n\r\ninterface IInternalConfig extends IConfig {\r\n autoTrigger: boolean;\r\n triggerAttribute: string;\r\n tagNames: {\r\n fetch: string;\r\n fetchHeader: string;\r\n fetchBody: string;\r\n };\r\n}\r\n\r\nconst _config: IInternalConfig = {\r\n autoTrigger: true,\r\n triggerAttribute: \"data-fetchtarget\",\r\n tagNames: {\r\n fetch: \"wcs-fetch\",\r\n fetchHeader: \"wcs-fetch-header\",\r\n fetchBody: \"wcs-fetch-body\",\r\n },\r\n};\r\n\r\nfunction deepFreeze<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n Object.freeze(obj);\r\n for (const key of Object.keys(obj)) {\r\n deepFreeze((obj as Record<string, unknown>)[key]);\r\n }\r\n return obj;\r\n}\r\n\r\nfunction deepClone<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n const clone: Record<string, unknown> = {};\r\n for (const key of Object.keys(obj)) {\r\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\r\n }\r\n return clone as T;\r\n}\r\n\r\nlet frozenConfig: IConfig | null = null;\r\n\r\nexport const config: IConfig = _config as IConfig;\r\n\r\nexport function getConfig(): IConfig {\r\n if (!frozenConfig) {\r\n frozenConfig = deepFreeze(deepClone(_config));\r\n }\r\n return frozenConfig;\r\n}\r\n\r\nexport function setConfig(partialConfig: IWritableConfig): void {\r\n if (typeof partialConfig.autoTrigger === \"boolean\") {\r\n _config.autoTrigger = partialConfig.autoTrigger;\r\n }\r\n if (typeof partialConfig.triggerAttribute === \"string\") {\r\n _config.triggerAttribute = partialConfig.triggerAttribute;\r\n }\r\n if (partialConfig.tagNames) {\r\n Object.assign(_config.tagNames, partialConfig.tagNames);\r\n }\r\n frozenConfig = null;\r\n}\r\n","export function raiseError(message: string): never {\r\n throw new Error(`[@wcstack/fetch] ${message}`);\r\n}\r\n","import { raiseError } from \"../raiseError.js\";\r\nimport { IWcBindable } from \"../types.js\";\r\n\r\nexport interface FetchRequestOptions {\r\n method?: string;\r\n headers?: Record<string, string>;\r\n body?: BodyInit | null;\r\n contentType?: string | null;\r\n forceText?: boolean;\r\n}\r\n\r\nexport class FetchCore extends EventTarget {\r\n static wcBindable: IWcBindable = {\r\n protocol: \"wc-bindable\",\r\n version: 1,\r\n properties: [\r\n { name: \"value\", event: \"wcs-fetch:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\r\n { name: \"loading\", event: \"wcs-fetch:loading-changed\" },\r\n { name: \"error\", event: \"wcs-fetch:error\" },\r\n { name: \"status\", event: \"wcs-fetch:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\r\n ],\r\n };\r\n\r\n private _target: EventTarget;\r\n private _value: any = null;\r\n private _loading: boolean = false;\r\n private _error: any = null;\r\n private _status: number = 0;\r\n private _abortController: AbortController | null = null;\r\n\r\n constructor(target?: EventTarget) {\r\n super();\r\n this._target = target ?? this;\r\n }\r\n\r\n get value(): any {\r\n return this._value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._loading;\r\n }\r\n\r\n get error(): any {\r\n return this._error;\r\n }\r\n\r\n get status(): number {\r\n return this._status;\r\n }\r\n\r\n private _setLoading(loading: boolean): void {\r\n this._loading = loading;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-fetch:loading-changed\", {\r\n detail: loading,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setError(error: any): void {\r\n this._error = error;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-fetch:error\", {\r\n detail: error,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setResponse(value: any, status: number): void {\r\n this._value = value;\r\n this._status = status;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-fetch:response\", {\r\n detail: { value, status },\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n abort(): void {\r\n if (this._abortController) {\r\n this._abortController.abort();\r\n this._abortController = null;\r\n }\r\n }\r\n\r\n async fetch(url: string, options: FetchRequestOptions = {}): Promise<any> {\r\n if (!url) {\r\n raiseError(\"url attribute is required.\");\r\n }\r\n\r\n // 進行中のリクエストをキャンセル\r\n this.abort();\r\n\r\n this._abortController = new AbortController();\r\n const { signal } = this._abortController;\r\n\r\n this._setLoading(true);\r\n this._error = null;\r\n\r\n const {\r\n method = \"GET\",\r\n headers = {},\r\n body = null,\r\n contentType = null,\r\n forceText = false,\r\n } = options;\r\n\r\n try {\r\n if (contentType && !headers[\"Content-Type\"]) {\r\n headers[\"Content-Type\"] = contentType;\r\n }\r\n\r\n const requestInit: RequestInit = {\r\n method,\r\n headers,\r\n signal,\r\n };\r\n\r\n if (method !== \"GET\" && method !== \"HEAD\" && body !== null) {\r\n requestInit.body = body;\r\n }\r\n\r\n const response = await globalThis.fetch(url, requestInit);\r\n this._status = response.status;\r\n\r\n if (!response.ok) {\r\n const errorBody = await response.text().catch(() => \"\");\r\n const error = { status: response.status, statusText: response.statusText, body: errorBody };\r\n this._setError(error);\r\n this._setLoading(false);\r\n return null;\r\n }\r\n\r\n if (forceText) {\r\n const text = await response.text();\r\n this._setResponse(text, response.status);\r\n } else {\r\n const responseContentType = response.headers.get(\"Content-Type\") || \"\";\r\n if (responseContentType.includes(\"application/json\")) {\r\n const data = await response.json();\r\n this._setResponse(data, response.status);\r\n } else {\r\n const text = await response.text();\r\n this._setResponse(text, response.status);\r\n }\r\n }\r\n\r\n this._setLoading(false);\r\n return this._value;\r\n } catch (e: any) {\r\n if (e.name === \"AbortError\") {\r\n this._setLoading(false);\r\n return null;\r\n }\r\n this._setError(e);\r\n this._setLoading(false);\r\n return null;\r\n } finally {\r\n this._abortController = null;\r\n }\r\n }\r\n}\r\n","import { config } from \"../config.js\";\r\nimport { IWcBindable } from \"../types.js\";\r\nimport { FetchCore } from \"../core/FetchCore.js\";\r\nimport { FetchHeader } from \"./FetchHeader.js\";\r\nimport { FetchBody } from \"./FetchBody.js\";\r\n\r\nexport class Fetch extends HTMLElement {\r\n static wcBindable: IWcBindable = {\r\n ...FetchCore.wcBindable,\r\n properties: [\r\n ...FetchCore.wcBindable.properties,\r\n { name: \"trigger\", event: \"wcs-fetch:trigger-changed\" },\r\n ],\r\n };\r\n static get observedAttributes(): string[] { return [\"url\"]; }\r\n\r\n private _core: FetchCore;\r\n private _body: any = null;\r\n private _trigger: boolean = false;\r\n\r\n constructor() {\r\n super();\r\n this._core = new FetchCore(this);\r\n }\r\n\r\n get url(): string {\r\n return this.getAttribute(\"url\") || \"\";\r\n }\r\n\r\n set url(value: string) {\r\n this.setAttribute(\"url\", value);\r\n }\r\n\r\n get method(): string {\r\n return (this.getAttribute(\"method\") || \"GET\").toUpperCase();\r\n }\r\n\r\n set method(value: string) {\r\n this.setAttribute(\"method\", value);\r\n }\r\n\r\n get target(): string | null {\r\n return this.getAttribute(\"target\");\r\n }\r\n\r\n set target(value: string | null) {\r\n if (value === null) {\r\n this.removeAttribute(\"target\");\r\n } else {\r\n this.setAttribute(\"target\", value);\r\n }\r\n }\r\n\r\n get value(): any {\r\n return this._core.value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._core.loading;\r\n }\r\n\r\n get error(): any {\r\n return this._core.error;\r\n }\r\n\r\n get status(): number {\r\n return this._core.status;\r\n }\r\n\r\n get manual(): boolean {\r\n return this.hasAttribute(\"manual\");\r\n }\r\n\r\n set manual(value: boolean) {\r\n if (value) {\r\n this.setAttribute(\"manual\", \"\");\r\n } else {\r\n this.removeAttribute(\"manual\");\r\n }\r\n }\r\n\r\n get body(): any {\r\n return this._body;\r\n }\r\n\r\n set body(value: any) {\r\n this._body = value;\r\n }\r\n\r\n get trigger(): boolean {\r\n return this._trigger;\r\n }\r\n\r\n set trigger(value: boolean) {\r\n const v = !!value;\r\n if (v) {\r\n this._trigger = true;\r\n this.fetch().finally(() => {\r\n this._trigger = false;\r\n this.dispatchEvent(new CustomEvent(\"wcs-fetch:trigger-changed\", {\r\n detail: false,\r\n bubbles: true,\r\n }));\r\n });\r\n }\r\n }\r\n\r\n private _collectHeaders(): Record<string, string> {\r\n const headers: Record<string, string> = {};\r\n const headerElements = this.querySelectorAll<FetchHeader>(config.tagNames.fetchHeader);\r\n for (const el of headerElements) {\r\n const name = el.headerName;\r\n const value = el.headerValue;\r\n if (name) {\r\n headers[name] = value;\r\n }\r\n }\r\n return headers;\r\n }\r\n\r\n private _collectBody(): { body: BodyInit | null; contentType: string | null } {\r\n // JS API経由のbodyが優先\r\n if (this._body !== null) {\r\n return {\r\n body: typeof this._body === \"string\" ? this._body : JSON.stringify(this._body),\r\n contentType: typeof this._body === \"string\" ? null : \"application/json\",\r\n };\r\n }\r\n\r\n // サブタグからbodyを取得\r\n const bodyElement = this.querySelector<FetchBody>(config.tagNames.fetchBody);\r\n if (bodyElement) {\r\n return {\r\n body: bodyElement.bodyContent || null,\r\n contentType: bodyElement.contentType,\r\n };\r\n }\r\n\r\n return { body: null, contentType: null };\r\n }\r\n\r\n abort(): void {\r\n this._core.abort();\r\n }\r\n\r\n async fetch(): Promise<any> {\r\n const headers = this._collectHeaders();\r\n const { body, contentType } = this._collectBody();\r\n\r\n const result = await this._core.fetch(this.url, {\r\n method: this.method,\r\n headers,\r\n body,\r\n contentType,\r\n forceText: !!this.target,\r\n });\r\n\r\n // HTML置換モード\r\n if (this.target && result !== null) {\r\n const targetElement = document.getElementById(this.target);\r\n if (targetElement) {\r\n targetElement.innerHTML = result;\r\n }\r\n }\r\n\r\n // bodyをリセット(一回限りの使用)\r\n this._body = null;\r\n\r\n return result;\r\n }\r\n\r\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\r\n if (name === \"url\" && this.isConnected && !this.manual && newValue) {\r\n this.fetch();\r\n }\r\n }\r\n\r\n connectedCallback(): void {\r\n this.style.display = \"none\";\r\n if (!this.manual && this.url) {\r\n this.fetch();\r\n }\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this.abort();\r\n }\r\n}\r\n","export class FetchHeader extends HTMLElement {\r\n connectedCallback(): void {\r\n this.style.display = \"none\";\r\n }\r\n\r\n get headerName(): string {\r\n return this.getAttribute(\"name\") || \"\";\r\n }\r\n\r\n get headerValue(): string {\r\n return this.getAttribute(\"value\") || \"\";\r\n }\r\n}\r\n","export class FetchBody extends HTMLElement {\r\n constructor() {\r\n super();\r\n // スロットなしのShadow DOMでlight DOM(bodyテキスト)の描画を抑制\r\n this.attachShadow({ mode: \"open\" });\r\n }\r\n\r\n get contentType(): string {\r\n return this.getAttribute(\"type\") || \"application/json\";\r\n }\r\n\r\n get bodyContent(): string {\r\n return this.textContent?.trim() || \"\";\r\n }\r\n}\r\n","import { Fetch } from \"./components/Fetch.js\";\r\nimport { FetchHeader } from \"./components/FetchHeader.js\";\r\nimport { FetchBody } from \"./components/FetchBody.js\";\r\nimport { config } from \"./config.js\";\r\n\r\nexport function registerComponents(): void {\r\n if (!customElements.get(config.tagNames.fetch)) {\r\n customElements.define(config.tagNames.fetch, Fetch);\r\n }\r\n if (!customElements.get(config.tagNames.fetchHeader)) {\r\n customElements.define(config.tagNames.fetchHeader, FetchHeader);\r\n }\r\n if (!customElements.get(config.tagNames.fetchBody)) {\r\n customElements.define(config.tagNames.fetchBody, FetchBody);\r\n }\r\n}\r\n","import { config } from \"./config.js\";\r\nimport { Fetch } from \"./components/Fetch.js\";\r\n\r\nlet registered = false;\r\n\r\nfunction handleClick(event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof Element)) return;\r\n\r\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\r\n if (!triggerElement) return;\r\n\r\n const fetchId = triggerElement.getAttribute(config.triggerAttribute);\r\n if (!fetchId) return;\r\n\r\n const fetchElement = document.getElementById(fetchId) as Fetch | null;\r\n if (!fetchElement || !(fetchElement instanceof Fetch)) return;\r\n\r\n event.preventDefault();\r\n fetchElement.fetch();\r\n}\r\n\r\nexport function registerAutoTrigger(): void {\r\n if (registered) return;\r\n registered = true;\r\n document.addEventListener(\"click\", handleClick);\r\n}\r\n\r\nexport function unregisterAutoTrigger(): void {\r\n if (!registered) return;\r\n registered = false;\r\n document.removeEventListener(\"click\", handleClick);\r\n}\r\n","import { setConfig } from \"./config.js\";\r\nimport { config } from \"./config.js\";\r\nimport { registerComponents } from \"./registerComponents.js\";\r\nimport { registerAutoTrigger } from \"./autoTrigger.js\";\r\nimport { IWritableConfig } from \"./types.js\";\r\n\r\nexport function bootstrapFetch(userConfig?: IWritableConfig): void {\r\n if (userConfig) {\r\n setConfig(userConfig);\r\n }\r\n registerComponents();\r\n if (config.autoTrigger) {\r\n registerAutoTrigger();\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const t={autoTrigger:!0,triggerAttribute:"data-fetchtarget",tagNames:{fetch:"wcs-fetch",fetchHeader:"wcs-fetch-header",fetchBody:"wcs-fetch-body"}},e=t;class s extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-fetch:response",getter:t=>t.detail.value},{name:"loading",event:"wcs-fetch:loading-changed"},{name:"error",event:"wcs-fetch:error"},{name:"status",event:"wcs-fetch:response",getter:t=>t.detail.status}]};_target;_value=null;_loading=!1;_error=null;_status=0;_abortController=null;constructor(t){super(),this._target=t??this}get value(){return this._value}get loading(){return this._loading}get error(){return this._error}get status(){return this._status}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent("wcs-fetch:loading-changed",{detail:t,bubbles:!0}))}_setError(t){this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-fetch:error",{detail:t,bubbles:!0}))}_setResponse(t,e){this._value=t,this._status=e,this._target.dispatchEvent(new CustomEvent("wcs-fetch:response",{detail:{value:t,status:e},bubbles:!0}))}abort(){this._abortController&&(this._abortController.abort(),this._abortController=null)}async fetch(t,e={}){t||function(t){throw new Error(`[@wcstack/fetch] ${t}`)}("url attribute is required."),this.abort(),this._abortController=new AbortController;const{signal:s}=this._abortController;this._setLoading(!0),this._error=null;const{method:r="GET",headers:n={},body:a=null,contentType:o=null,forceText:i=!1}=e;try{o&&!n["Content-Type"]&&(n["Content-Type"]=o);const e={method:r,headers:n,signal:s};"GET"!==r&&"HEAD"!==r&&null!==a&&(e.body=a);const l=await globalThis.fetch(t,e);if(this._status=l.status,!l.ok){const t=await l.text().catch(()=>""),e={status:l.status,statusText:l.statusText,body:t};return this._setError(e),this._setLoading(!1),null}if(i){const t=await l.text();this._setResponse(t,l.status)}else{if((l.headers.get("Content-Type")||"").includes("application/json")){const t=await l.json();this._setResponse(t,l.status)}else{const t=await l.text();this._setResponse(t,l.status)}}return this._setLoading(!1),this._value}catch(t){return"AbortError"===t.name?(this._setLoading(!1),null):(this._setError(t),this._setLoading(!1),null)}finally{this._abortController=null}}}class r extends HTMLElement{static wcBindable={...s.wcBindable,properties:[...s.wcBindable.properties,{name:"trigger",event:"wcs-fetch:trigger-changed"}]};static get observedAttributes(){return["url"]}_core;_body=null;_trigger=!1;constructor(){super(),this._core=new s(this)}get url(){return this.getAttribute("url")||""}set url(t){this.setAttribute("url",t)}get method(){return(this.getAttribute("method")||"GET").toUpperCase()}set method(t){this.setAttribute("method",t)}get target(){return this.getAttribute("target")}set target(t){null===t?this.removeAttribute("target"):this.setAttribute("target",t)}get value(){return this._core.value}get loading(){return this._core.loading}get error(){return this._core.error}get status(){return this._core.status}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get body(){return this._body}set body(t){this._body=t}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.fetch().finally(()=>{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-fetch:trigger-changed",{detail:!1,bubbles:!0}))}))}_collectHeaders(){const t={},s=this.querySelectorAll(e.tagNames.fetchHeader);for(const e of s){const s=e.headerName,r=e.headerValue;s&&(t[s]=r)}return t}_collectBody(){if(null!==this._body)return{body:"string"==typeof this._body?this._body:JSON.stringify(this._body),contentType:"string"==typeof this._body?null:"application/json"};const t=this.querySelector(e.tagNames.fetchBody);return t?{body:t.bodyContent||null,contentType:t.contentType}:{body:null,contentType:null}}abort(){this._core.abort()}async fetch(){const t=this._collectHeaders(),{body:e,contentType:s}=this._collectBody(),r=await this._core.fetch(this.url,{method:this.method,headers:t,body:e,contentType:s,forceText:!!this.target});if(this.target&&null!==r){const t=document.getElementById(this.target);t&&(t.innerHTML=r)}return this._body=null,r}attributeChangedCallback(t,e,s){"url"===t&&this.isConnected&&!this.manual&&s&&this.fetch()}connectedCallback(){this.style.display="none",!this.manual&&this.url&&this.fetch()}disconnectedCallback(){this.abort()}}class n extends HTMLElement{connectedCallback(){this.style.display="none"}get headerName(){return this.getAttribute("name")||""}get headerValue(){return this.getAttribute("value")||""}}class a extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}get contentType(){return this.getAttribute("type")||"application/json"}get bodyContent(){return this.textContent?.trim()||""}}let o=!1;function i(t){const s=t.target;if(!(s instanceof Element))return;const n=s.closest(`[${e.triggerAttribute}]`);if(!n)return;const a=n.getAttribute(e.triggerAttribute);if(!a)return;const o=document.getElementById(a);o&&o instanceof r&&(t.preventDefault(),o.fetch())}function l(s){var l;s&&("boolean"==typeof(l=s).autoTrigger&&(t.autoTrigger=l.autoTrigger),"string"==typeof l.triggerAttribute&&(t.triggerAttribute=l.triggerAttribute),l.tagNames&&Object.assign(t.tagNames,l.tagNames)),customElements.get(e.tagNames.fetch)||customElements.define(e.tagNames.fetch,r),customElements.get(e.tagNames.fetchHeader)||customElements.define(e.tagNames.fetchHeader,n),customElements.get(e.tagNames.fetchBody)||customElements.define(e.tagNames.fetchBody,a),e.autoTrigger&&(o||(o=!0,document.addEventListener("click",i)))}export{s as FetchCore,l as bootstrapFetch};
2
+ //# sourceMappingURL=index.esm.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/FetchCore.ts","../src/raiseError.ts","../src/components/Fetch.ts","../src/components/FetchHeader.ts","../src/components/FetchBody.ts","../src/autoTrigger.ts","../src/bootstrapFetch.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\r\n\r\ninterface IInternalConfig extends IConfig {\r\n autoTrigger: boolean;\r\n triggerAttribute: string;\r\n tagNames: {\r\n fetch: string;\r\n fetchHeader: string;\r\n fetchBody: string;\r\n };\r\n}\r\n\r\nconst _config: IInternalConfig = {\r\n autoTrigger: true,\r\n triggerAttribute: \"data-fetchtarget\",\r\n tagNames: {\r\n fetch: \"wcs-fetch\",\r\n fetchHeader: \"wcs-fetch-header\",\r\n fetchBody: \"wcs-fetch-body\",\r\n },\r\n};\r\n\r\nfunction deepFreeze<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n Object.freeze(obj);\r\n for (const key of Object.keys(obj)) {\r\n deepFreeze((obj as Record<string, unknown>)[key]);\r\n }\r\n return obj;\r\n}\r\n\r\nfunction deepClone<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n const clone: Record<string, unknown> = {};\r\n for (const key of Object.keys(obj)) {\r\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\r\n }\r\n return clone as T;\r\n}\r\n\r\nlet frozenConfig: IConfig | null = null;\r\n\r\nexport const config: IConfig = _config as IConfig;\r\n\r\nexport function getConfig(): IConfig {\r\n if (!frozenConfig) {\r\n frozenConfig = deepFreeze(deepClone(_config));\r\n }\r\n return frozenConfig;\r\n}\r\n\r\nexport function setConfig(partialConfig: IWritableConfig): void {\r\n if (typeof partialConfig.autoTrigger === \"boolean\") {\r\n _config.autoTrigger = partialConfig.autoTrigger;\r\n }\r\n if (typeof partialConfig.triggerAttribute === \"string\") {\r\n _config.triggerAttribute = partialConfig.triggerAttribute;\r\n }\r\n if (partialConfig.tagNames) {\r\n Object.assign(_config.tagNames, partialConfig.tagNames);\r\n }\r\n frozenConfig = null;\r\n}\r\n","import { raiseError } from \"../raiseError.js\";\r\nimport { IWcBindable } from \"../types.js\";\r\n\r\nexport interface FetchRequestOptions {\r\n method?: string;\r\n headers?: Record<string, string>;\r\n body?: BodyInit | null;\r\n contentType?: string | null;\r\n forceText?: boolean;\r\n}\r\n\r\nexport class FetchCore extends EventTarget {\r\n static wcBindable: IWcBindable = {\r\n protocol: \"wc-bindable\",\r\n version: 1,\r\n properties: [\r\n { name: \"value\", event: \"wcs-fetch:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\r\n { name: \"loading\", event: \"wcs-fetch:loading-changed\" },\r\n { name: \"error\", event: \"wcs-fetch:error\" },\r\n { name: \"status\", event: \"wcs-fetch:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\r\n ],\r\n };\r\n\r\n private _target: EventTarget;\r\n private _value: any = null;\r\n private _loading: boolean = false;\r\n private _error: any = null;\r\n private _status: number = 0;\r\n private _abortController: AbortController | null = null;\r\n\r\n constructor(target?: EventTarget) {\r\n super();\r\n this._target = target ?? this;\r\n }\r\n\r\n get value(): any {\r\n return this._value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._loading;\r\n }\r\n\r\n get error(): any {\r\n return this._error;\r\n }\r\n\r\n get status(): number {\r\n return this._status;\r\n }\r\n\r\n private _setLoading(loading: boolean): void {\r\n this._loading = loading;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-fetch:loading-changed\", {\r\n detail: loading,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setError(error: any): void {\r\n this._error = error;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-fetch:error\", {\r\n detail: error,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setResponse(value: any, status: number): void {\r\n this._value = value;\r\n this._status = status;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-fetch:response\", {\r\n detail: { value, status },\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n abort(): void {\r\n if (this._abortController) {\r\n this._abortController.abort();\r\n this._abortController = null;\r\n }\r\n }\r\n\r\n async fetch(url: string, options: FetchRequestOptions = {}): Promise<any> {\r\n if (!url) {\r\n raiseError(\"url attribute is required.\");\r\n }\r\n\r\n // 進行中のリクエストをキャンセル\r\n this.abort();\r\n\r\n this._abortController = new AbortController();\r\n const { signal } = this._abortController;\r\n\r\n this._setLoading(true);\r\n this._error = null;\r\n\r\n const {\r\n method = \"GET\",\r\n headers = {},\r\n body = null,\r\n contentType = null,\r\n forceText = false,\r\n } = options;\r\n\r\n try {\r\n if (contentType && !headers[\"Content-Type\"]) {\r\n headers[\"Content-Type\"] = contentType;\r\n }\r\n\r\n const requestInit: RequestInit = {\r\n method,\r\n headers,\r\n signal,\r\n };\r\n\r\n if (method !== \"GET\" && method !== \"HEAD\" && body !== null) {\r\n requestInit.body = body;\r\n }\r\n\r\n const response = await globalThis.fetch(url, requestInit);\r\n this._status = response.status;\r\n\r\n if (!response.ok) {\r\n const errorBody = await response.text().catch(() => \"\");\r\n const error = { status: response.status, statusText: response.statusText, body: errorBody };\r\n this._setError(error);\r\n this._setLoading(false);\r\n return null;\r\n }\r\n\r\n if (forceText) {\r\n const text = await response.text();\r\n this._setResponse(text, response.status);\r\n } else {\r\n const responseContentType = response.headers.get(\"Content-Type\") || \"\";\r\n if (responseContentType.includes(\"application/json\")) {\r\n const data = await response.json();\r\n this._setResponse(data, response.status);\r\n } else {\r\n const text = await response.text();\r\n this._setResponse(text, response.status);\r\n }\r\n }\r\n\r\n this._setLoading(false);\r\n return this._value;\r\n } catch (e: any) {\r\n if (e.name === \"AbortError\") {\r\n this._setLoading(false);\r\n return null;\r\n }\r\n this._setError(e);\r\n this._setLoading(false);\r\n return null;\r\n } finally {\r\n this._abortController = null;\r\n }\r\n }\r\n}\r\n","export function raiseError(message: string): never {\r\n throw new Error(`[@wcstack/fetch] ${message}`);\r\n}\r\n","import { config } from \"../config.js\";\r\nimport { IWcBindable } from \"../types.js\";\r\nimport { FetchCore } from \"../core/FetchCore.js\";\r\nimport { FetchHeader } from \"./FetchHeader.js\";\r\nimport { FetchBody } from \"./FetchBody.js\";\r\n\r\nexport class Fetch extends HTMLElement {\r\n static wcBindable: IWcBindable = {\r\n ...FetchCore.wcBindable,\r\n properties: [\r\n ...FetchCore.wcBindable.properties,\r\n { name: \"trigger\", event: \"wcs-fetch:trigger-changed\" },\r\n ],\r\n };\r\n static get observedAttributes(): string[] { return [\"url\"]; }\r\n\r\n private _core: FetchCore;\r\n private _body: any = null;\r\n private _trigger: boolean = false;\r\n\r\n constructor() {\r\n super();\r\n this._core = new FetchCore(this);\r\n }\r\n\r\n get url(): string {\r\n return this.getAttribute(\"url\") || \"\";\r\n }\r\n\r\n set url(value: string) {\r\n this.setAttribute(\"url\", value);\r\n }\r\n\r\n get method(): string {\r\n return (this.getAttribute(\"method\") || \"GET\").toUpperCase();\r\n }\r\n\r\n set method(value: string) {\r\n this.setAttribute(\"method\", value);\r\n }\r\n\r\n get target(): string | null {\r\n return this.getAttribute(\"target\");\r\n }\r\n\r\n set target(value: string | null) {\r\n if (value === null) {\r\n this.removeAttribute(\"target\");\r\n } else {\r\n this.setAttribute(\"target\", value);\r\n }\r\n }\r\n\r\n get value(): any {\r\n return this._core.value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._core.loading;\r\n }\r\n\r\n get error(): any {\r\n return this._core.error;\r\n }\r\n\r\n get status(): number {\r\n return this._core.status;\r\n }\r\n\r\n get manual(): boolean {\r\n return this.hasAttribute(\"manual\");\r\n }\r\n\r\n set manual(value: boolean) {\r\n if (value) {\r\n this.setAttribute(\"manual\", \"\");\r\n } else {\r\n this.removeAttribute(\"manual\");\r\n }\r\n }\r\n\r\n get body(): any {\r\n return this._body;\r\n }\r\n\r\n set body(value: any) {\r\n this._body = value;\r\n }\r\n\r\n get trigger(): boolean {\r\n return this._trigger;\r\n }\r\n\r\n set trigger(value: boolean) {\r\n const v = !!value;\r\n if (v) {\r\n this._trigger = true;\r\n this.fetch().finally(() => {\r\n this._trigger = false;\r\n this.dispatchEvent(new CustomEvent(\"wcs-fetch:trigger-changed\", {\r\n detail: false,\r\n bubbles: true,\r\n }));\r\n });\r\n }\r\n }\r\n\r\n private _collectHeaders(): Record<string, string> {\r\n const headers: Record<string, string> = {};\r\n const headerElements = this.querySelectorAll<FetchHeader>(config.tagNames.fetchHeader);\r\n for (const el of headerElements) {\r\n const name = el.headerName;\r\n const value = el.headerValue;\r\n if (name) {\r\n headers[name] = value;\r\n }\r\n }\r\n return headers;\r\n }\r\n\r\n private _collectBody(): { body: BodyInit | null; contentType: string | null } {\r\n // JS API経由のbodyが優先\r\n if (this._body !== null) {\r\n return {\r\n body: typeof this._body === \"string\" ? this._body : JSON.stringify(this._body),\r\n contentType: typeof this._body === \"string\" ? null : \"application/json\",\r\n };\r\n }\r\n\r\n // サブタグからbodyを取得\r\n const bodyElement = this.querySelector<FetchBody>(config.tagNames.fetchBody);\r\n if (bodyElement) {\r\n return {\r\n body: bodyElement.bodyContent || null,\r\n contentType: bodyElement.contentType,\r\n };\r\n }\r\n\r\n return { body: null, contentType: null };\r\n }\r\n\r\n abort(): void {\r\n this._core.abort();\r\n }\r\n\r\n async fetch(): Promise<any> {\r\n const headers = this._collectHeaders();\r\n const { body, contentType } = this._collectBody();\r\n\r\n const result = await this._core.fetch(this.url, {\r\n method: this.method,\r\n headers,\r\n body,\r\n contentType,\r\n forceText: !!this.target,\r\n });\r\n\r\n // HTML置換モード\r\n if (this.target && result !== null) {\r\n const targetElement = document.getElementById(this.target);\r\n if (targetElement) {\r\n targetElement.innerHTML = result;\r\n }\r\n }\r\n\r\n // bodyをリセット(一回限りの使用)\r\n this._body = null;\r\n\r\n return result;\r\n }\r\n\r\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\r\n if (name === \"url\" && this.isConnected && !this.manual && newValue) {\r\n this.fetch();\r\n }\r\n }\r\n\r\n connectedCallback(): void {\r\n this.style.display = \"none\";\r\n if (!this.manual && this.url) {\r\n this.fetch();\r\n }\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this.abort();\r\n }\r\n}\r\n","export class FetchHeader extends HTMLElement {\r\n connectedCallback(): void {\r\n this.style.display = \"none\";\r\n }\r\n\r\n get headerName(): string {\r\n return this.getAttribute(\"name\") || \"\";\r\n }\r\n\r\n get headerValue(): string {\r\n return this.getAttribute(\"value\") || \"\";\r\n }\r\n}\r\n","export class FetchBody extends HTMLElement {\r\n constructor() {\r\n super();\r\n // スロットなしのShadow DOMでlight DOM(bodyテキスト)の描画を抑制\r\n this.attachShadow({ mode: \"open\" });\r\n }\r\n\r\n get contentType(): string {\r\n return this.getAttribute(\"type\") || \"application/json\";\r\n }\r\n\r\n get bodyContent(): string {\r\n return this.textContent?.trim() || \"\";\r\n }\r\n}\r\n","import { config } from \"./config.js\";\r\nimport { Fetch } from \"./components/Fetch.js\";\r\n\r\nlet registered = false;\r\n\r\nfunction handleClick(event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof Element)) return;\r\n\r\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\r\n if (!triggerElement) return;\r\n\r\n const fetchId = triggerElement.getAttribute(config.triggerAttribute);\r\n if (!fetchId) return;\r\n\r\n const fetchElement = document.getElementById(fetchId) as Fetch | null;\r\n if (!fetchElement || !(fetchElement instanceof Fetch)) return;\r\n\r\n event.preventDefault();\r\n fetchElement.fetch();\r\n}\r\n\r\nexport function registerAutoTrigger(): void {\r\n if (registered) return;\r\n registered = true;\r\n document.addEventListener(\"click\", handleClick);\r\n}\r\n\r\nexport function unregisterAutoTrigger(): void {\r\n if (!registered) return;\r\n registered = false;\r\n document.removeEventListener(\"click\", handleClick);\r\n}\r\n","import { setConfig } from \"./config.js\";\r\nimport { config } from \"./config.js\";\r\nimport { registerComponents } from \"./registerComponents.js\";\r\nimport { registerAutoTrigger } from \"./autoTrigger.js\";\r\nimport { IWritableConfig } from \"./types.js\";\r\n\r\nexport function bootstrapFetch(userConfig?: IWritableConfig): void {\r\n if (userConfig) {\r\n setConfig(userConfig);\r\n }\r\n registerComponents();\r\n if (config.autoTrigger) {\r\n registerAutoTrigger();\r\n }\r\n}\r\n","import { Fetch } from \"./components/Fetch.js\";\r\nimport { FetchHeader } from \"./components/FetchHeader.js\";\r\nimport { FetchBody } from \"./components/FetchBody.js\";\r\nimport { config } from \"./config.js\";\r\n\r\nexport function registerComponents(): void {\r\n if (!customElements.get(config.tagNames.fetch)) {\r\n customElements.define(config.tagNames.fetch, Fetch);\r\n }\r\n if (!customElements.get(config.tagNames.fetchHeader)) {\r\n customElements.define(config.tagNames.fetchHeader, FetchHeader);\r\n }\r\n if (!customElements.get(config.tagNames.fetchBody)) {\r\n customElements.define(config.tagNames.fetchBody, FetchBody);\r\n }\r\n}\r\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","fetch","fetchHeader","fetchBody","config","FetchCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","value","status","_target","_value","_loading","_error","_status","_abortController","constructor","target","super","this","loading","error","_setLoading","dispatchEvent","CustomEvent","bubbles","_setError","_setResponse","abort","url","options","message","Error","raiseError","AbortController","signal","method","headers","body","contentType","forceText","requestInit","response","globalThis","ok","errorBody","text","catch","statusText","get","includes","data","json","Fetch","HTMLElement","wcBindable","observedAttributes","_core","_body","_trigger","getAttribute","setAttribute","toUpperCase","removeAttribute","manual","hasAttribute","trigger","finally","_collectHeaders","headerElements","querySelectorAll","el","headerName","headerValue","_collectBody","JSON","stringify","bodyElement","querySelector","bodyContent","result","targetElement","document","getElementById","innerHTML","attributeChangedCallback","_oldValue","newValue","isConnected","connectedCallback","style","display","disconnectedCallback","FetchHeader","FetchBody","attachShadow","mode","textContent","trim","registered","handleClick","Element","triggerElement","closest","fetchId","fetchElement","preventDefault","bootstrapFetch","userConfig","partialConfig","Object","assign","customElements","define","addEventListener"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@wcstack/fetch",
3
+ "version": "1.4.0",
4
+ "description": "Declarative fetch component for Web Components. Framework-agnostic async data fetching via wc-bindable-protocol.",
5
+ "type": "module",
6
+ "main": "./dist/index.esm.js",
7
+ "module": "./dist/index.esm.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.esm.js"
13
+ },
14
+ "./auto": "./dist/auto.min.js"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "clean": "rimraf dist .tsc-out",
21
+ "build": "rimraf dist .tsc-out && tsc && rollup -c",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "test:coverage": "vitest run --coverage",
25
+ "lint": "eslint src",
26
+ "version:patch": "npm version patch",
27
+ "version:minor": "npm version minor",
28
+ "version:major": "npm version major",
29
+ "prepublishOnly": "npm run build && npm run test:coverage"
30
+ },
31
+ "keywords": [
32
+ "web-components",
33
+ "fetch",
34
+ "custom-elements",
35
+ "wc-bindable",
36
+ "declarative",
37
+ "htmx",
38
+ "async",
39
+ "zero-dependencies",
40
+ "framework-agnostic"
41
+ ],
42
+ "author": "mogera551",
43
+ "homepage": "https://wcstack.github.io",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/wcstack/wcstack.git",
47
+ "directory": "packages/fetch"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/wcstack/wcstack/issues"
51
+ },
52
+ "license": "MIT",
53
+ "devDependencies": {
54
+ "@eslint/js": "^9.39.1",
55
+ "@rollup/plugin-terser": "^0.4.4",
56
+ "@rollup/plugin-typescript": "^11.1.6",
57
+ "@vitest/coverage-v8": "^4.0.15",
58
+ "@vitest/ui": "^4.0.15",
59
+ "eslint": "^9.39.1",
60
+ "globals": "^16.5.0",
61
+ "happy-dom": "^20.0.11",
62
+ "rimraf": "^6.0.1",
63
+ "rollup": "^4.22.4",
64
+ "rollup-plugin-dts": "^6.1.1",
65
+ "rollup-plugin-copy": "^3.5.0",
66
+ "tslib": "^2.8.1",
67
+ "typescript": "^5.9.3",
68
+ "typescript-eslint": "^8.49.0",
69
+ "vitest": "^4.0.15"
70
+ }
71
+ }