@wcstack/storage 1.20.0 → 1.21.1

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 CHANGED
@@ -8,7 +8,7 @@ It is an **I/O node** that connects browser storage (localStorage / sessionStora
8
8
  When combined with `@wcstack/state`, `<wcs-storage>` can be bound directly through a path contract:
9
9
 
10
10
  - **Input / Command Surface**: `key`, `type`, `trigger`
11
- - **Output State Surface**: `value`, `loading`, `error`
11
+ - **Output State Surface**: `value`, `loading`, `error`, `errorInfo`
12
12
 
13
13
  This means you can express browser storage persistence declaratively in HTML, without writing `localStorage.getItem()`, `JSON.parse()`, or serialization glue code in the UI layer.
14
14
 
@@ -215,6 +215,7 @@ Represents the current storage value and is the CSBC main surface:
215
215
  | `value` | `any` | Value stored in storage |
216
216
  | `loading` | `boolean` | `true` during read/write |
217
217
  | `error` | `WcsStorageError \| Error \| null` | Storage operation error |
218
+ | `errorInfo` | `WcsIoErrorInfo \| null` | Serializable failure taxonomy (stable `code` / `phase` / `recoverable`), derived from `error`. Additive — the `error` shape is unchanged. |
218
219
 
219
220
  ### Input / Command Surface
220
221
 
@@ -357,6 +358,7 @@ unbind();
357
358
  | `value` | `any` | Storage value (auto-saves on set) |
358
359
  | `loading` | `boolean` | `true` during read/write |
359
360
  | `error` | `WcsStorageError \| Error \| null` | Error info |
361
+ | `errorInfo` | `WcsIoErrorInfo \| null` | Failure taxonomy (`code` / `phase` / `recoverable`), derived from `error` |
360
362
  | `trigger` | `boolean` | Set `true` to execute save |
361
363
  | `manual` | `boolean` | Manual mode |
362
364
 
@@ -391,6 +393,7 @@ static wcBindable = {
391
393
  getter: (e) => e.detail },
392
394
  { name: "loading", event: "wcs-storage:loading-changed" },
393
395
  { name: "error", event: "wcs-storage:error" },
396
+ { name: "errorInfo", event: "wcs-storage:error-info-changed" },
394
397
  ],
395
398
  inputs: [
396
399
  { name: "key" },
@@ -611,6 +614,7 @@ bootstrapStorage({
611
614
  - **Invalid `type`**: any `type` attribute other than `"session"` is treated as `"local"`. An invalid value (e.g. `type="foo"`) silently falls back to `local` rather than throwing.
612
615
  - **Runtime `type` change**: changing the `type` attribute after connection updates the Core's storage area for subsequent operations but does **not** re-load from the new area (only `key` changes auto-reload in non-manual mode). Re-load explicitly with `load()` if you need the value from the newly selected area.
613
616
  - **`error` shape**: on a storage failure, `error` is set to a `WcsStorageError` (`{ operation, message }`) identifying which call failed (`load` / `save` / `remove`, or `type` for an invalid headless `type` assignment). Operations are **never-throw**: calling one with no key does **not** throw — it is surfaced on `error` as `{ operation, message: "key is required." }` (and dispatched as `wcs-storage:error`). In practice `error` is therefore always either a `WcsStorageError` or `null`; the wider `WcsStorageError | Error | null` type is kept for forward compatibility and consistency with sibling packages.
617
+ - **`errorInfo` taxonomy**: an **additive** bindable output (`wcs-storage:error-info-changed`) that classifies the same failure into a serializable `WcsIoErrorInfo` with a stable `code` / `phase` / `recoverable`, without changing the `error` shape. Validation failures (invalid `type` / missing `key`) are `invalid-argument` (phase `start`, not recoverable). A caught storage exception is phase `execute` and classified by its `Error.name`: `QuotaExceededError` → `quota-exceeded` (recoverable — succeeds once space is freed), `SecurityError` → `not-allowed` (storage access denied, not recoverable), anything else → `storage-error`. `errorInfo` transitions exactly when `error` does (cleared to `null` on any successful operation); the shared `WcsIoErrorInfo` type and the `WCS_STORAGE_ERROR_CODE` constants are exported.
614
618
  - JSON auto-serialization handles objects, arrays, and primitives transparently
615
619
  - Saving `null` / `undefined` removes the key from storage
616
620
  - Cross-tab sync via `storage` event works only with localStorage. The Shell binds the watcher to its current `key` / `type` on connect (and re-binds on re-attach), so cross-tab sync works even in `manual` mode where no auto-load runs. Changing the `key` attribute after connection always re-syncs the Core key, so cross-tab sync follows the new key even in `manual` mode or when the key is cleared. A successful cross-tab update also clears any stale `error` (just like `load()` / `save()` / `remove()` do at the start of a successful operation), so a fresh value never coexists with a leftover error from an earlier failure.
package/dist/index.d.ts CHANGED
@@ -13,12 +13,24 @@ interface IWcBindableCommand {
13
13
  }
14
14
  interface IWcBindable {
15
15
  readonly protocol: "wc-bindable";
16
- readonly version: 1;
16
+ /** Integer protocol version. All versions >= 1 are core-compatible. */
17
+ readonly version: number;
17
18
  readonly properties: readonly IWcBindableProperty[];
18
19
  readonly inputs?: readonly IWcBindableInput[];
19
20
  readonly commands?: readonly IWcBindableCommand[];
20
21
  }
21
22
 
23
+ /** operation error の phase(taxonomy)。 */
24
+ type WcsIoErrorPhase = "probe" | "start" | "execute" | "decode" | "commit" | "dispose";
25
+ /** serializable な error info(non-cloneable な cause とは分離。DevTools / remote へは info のみ)。 */
26
+ interface WcsIoErrorInfo {
27
+ readonly code: string;
28
+ readonly phase: WcsIoErrorPhase;
29
+ readonly recoverable: boolean;
30
+ readonly capabilityId?: string;
31
+ readonly message: string;
32
+ }
33
+
22
34
  interface ITagNames {
23
35
  readonly storage: string;
24
36
  }
@@ -54,6 +66,8 @@ interface WcsStorageCoreValues<T = unknown> {
54
66
  value: T;
55
67
  loading: boolean;
56
68
  error: WcsStorageError | Error | null;
69
+ /** Additive failure taxonomy derived from `error` (stable code / phase / recoverable). */
70
+ errorInfo: WcsIoErrorInfo | null;
57
71
  }
58
72
  /**
59
73
  * Value types for the Shell (`<wcs-storage>`) — extends Core with `trigger`.
@@ -73,6 +87,7 @@ declare class StorageCore extends EventTarget {
73
87
  private _value;
74
88
  private _loading;
75
89
  private _error;
90
+ private _errorInfo;
76
91
  private _key;
77
92
  private _type;
78
93
  private _storageListener;
@@ -86,6 +101,13 @@ declare class StorageCore extends EventTarget {
86
101
  set value(v: any);
87
102
  get loading(): boolean;
88
103
  get error(): any;
104
+ /**
105
+ * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /
106
+ * `recoverable`), or null. Additive wc-bindable property (event
107
+ * `wcs-storage:error-info-changed`), derived from `error`; the existing `error`
108
+ * property/event are unchanged.
109
+ */
110
+ get errorInfo(): WcsIoErrorInfo | null;
89
111
  get key(): string;
90
112
  set key(value: string);
91
113
  get type(): StorageType;
@@ -93,7 +115,9 @@ declare class StorageCore extends EventTarget {
93
115
  private _getStorage;
94
116
  private _setLoading;
95
117
  private _setError;
118
+ private _commitErrorInfo;
96
119
  private _toStorageError;
120
+ private _errName;
97
121
  private _setValue;
98
122
  load(): any;
99
123
  save(value: any): void;
@@ -123,6 +147,7 @@ declare class Storage extends HTMLElement {
123
147
  set value(v: any);
124
148
  get loading(): boolean;
125
149
  get error(): any;
150
+ get errorInfo(): WcsIoErrorInfo | null;
126
151
  get connectedCallbackPromise(): Promise<void>;
127
152
  get manual(): boolean;
128
153
  set manual(value: boolean);
@@ -136,5 +161,26 @@ declare class Storage extends HTMLElement {
136
161
  disconnectedCallback(): void;
137
162
  }
138
163
 
139
- export { StorageCore, Storage as WcsStorage, bootstrapStorage, getConfig };
140
- export type { IWritableConfig, IWritableTagNames, StorageType, WcsStorageCoreValues, WcsStorageError, WcsStorageValues };
164
+ /**
165
+ * storageCapabilities.ts
166
+ *
167
+ * Storage node 固有の error code(taxonomy)と derivation。汎用の error info 型は
168
+ * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から
169
+ * import する。storage の load / save / remove は同期で互いに競合しないため lane は
170
+ * 持たず、error taxonomy(errorInfo)のみを採用する。
171
+ */
172
+
173
+ /** 安定した storage error code(taxonomy)。値は公開キーとして固定。 */
174
+ declare const WCS_STORAGE_ERROR_CODE: {
175
+ /** `key` 未設定 / 不正な `type` などの入力不備。retry では回復しない。 */
176
+ readonly InvalidArgument: "invalid-argument";
177
+ /** `QuotaExceededError` — 容量超過。空きを作れば回復しうる(環境要因)。 */
178
+ readonly QuotaExceeded: "quota-exceeded";
179
+ /** `SecurityError` — storage アクセス拒否(cookie 無効 / third-party context 等)。retry では回復しない。 */
180
+ readonly NotAllowed: "not-allowed";
181
+ /** その他の caught 例外。 */
182
+ readonly StorageError: "storage-error";
183
+ };
184
+
185
+ export { StorageCore, WCS_STORAGE_ERROR_CODE, Storage as WcsStorage, bootstrapStorage, getConfig };
186
+ export type { IWritableConfig, IWritableTagNames, StorageType, WcsIoErrorInfo, WcsIoErrorPhase, WcsStorageCoreValues, WcsStorageError, WcsStorageValues };
package/dist/index.esm.js CHANGED
@@ -63,9 +63,56 @@ const STORAGE_EVENTS = {
63
63
  valueChanged: "wcs-storage:value-changed",
64
64
  loadingChanged: "wcs-storage:loading-changed",
65
65
  error: "wcs-storage:error",
66
+ errorInfoChanged: "wcs-storage:error-info-changed",
66
67
  triggerChanged: "wcs-storage:trigger-changed",
67
68
  };
68
69
 
70
+ /**
71
+ * storageCapabilities.ts
72
+ *
73
+ * Storage node 固有の error code(taxonomy)と derivation。汎用の error info 型は
74
+ * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から
75
+ * import する。storage の load / save / remove は同期で互いに競合しないため lane は
76
+ * 持たず、error taxonomy(errorInfo)のみを採用する。
77
+ */
78
+ /** 安定した storage error code(taxonomy)。値は公開キーとして固定。 */
79
+ const WCS_STORAGE_ERROR_CODE = {
80
+ /** `key` 未設定 / 不正な `type` などの入力不備。retry では回復しない。 */
81
+ InvalidArgument: "invalid-argument",
82
+ /** `QuotaExceededError` — 容量超過。空きを作れば回復しうる(環境要因)。 */
83
+ QuotaExceeded: "quota-exceeded",
84
+ /** `SecurityError` — storage アクセス拒否(cookie 無効 / third-party context 等)。retry では回復しない。 */
85
+ NotAllowed: "not-allowed",
86
+ /** その他の caught 例外。 */
87
+ StorageError: "storage-error",
88
+ };
89
+ /**
90
+ * storage の失敗を serializable な error taxonomy に写す。
91
+ *
92
+ * `name` は caught 例外の `Error.name`(load / save / remove の catch から渡る)。
93
+ * 未指定(undefined)は inline 構築の validation error(不正 `type` / `key` 未設定)を意味し、
94
+ * これは開始前の入力不備なので phase="start" / `invalid-argument` / recoverable=false。
95
+ * caught 例外は実行中の失敗なので phase="execute"。`QuotaExceededError` は環境要因で
96
+ * 空きを作れば回復しうる(recoverable=true)、`SecurityError` は retry で回復しない。
97
+ */
98
+ function deriveStorageErrorInfo(error, name) {
99
+ if (name === undefined) {
100
+ return {
101
+ code: WCS_STORAGE_ERROR_CODE.InvalidArgument,
102
+ phase: "start",
103
+ recoverable: false,
104
+ message: error.message,
105
+ };
106
+ }
107
+ if (name === "QuotaExceededError") {
108
+ return { code: WCS_STORAGE_ERROR_CODE.QuotaExceeded, phase: "execute", recoverable: true, message: error.message };
109
+ }
110
+ if (name === "SecurityError") {
111
+ return { code: WCS_STORAGE_ERROR_CODE.NotAllowed, phase: "execute", recoverable: false, message: error.message };
112
+ }
113
+ return { code: WCS_STORAGE_ERROR_CODE.StorageError, phase: "execute", recoverable: true, message: error.message };
114
+ }
115
+
69
116
  class StorageCore extends EventTarget {
70
117
  static wcBindable = {
71
118
  protocol: "wc-bindable",
@@ -74,6 +121,11 @@ class StorageCore extends EventTarget {
74
121
  { name: "value", event: STORAGE_EVENTS.valueChanged, getter: (e) => e.detail },
75
122
  { name: "loading", event: STORAGE_EVENTS.loadingChanged },
76
123
  { name: "error", event: STORAGE_EVENTS.error },
124
+ // Serializable failure taxonomy (stable code / phase / recoverable), or null.
125
+ // Additive bindable output derived from `error` (invalid-argument / quota-exceeded
126
+ // / not-allowed / storage-error); the existing `error` property/event are unchanged.
127
+ // Fires wcs-storage:error-info-changed. No lane — load/save/remove don't compete.
128
+ { name: "errorInfo", event: STORAGE_EVENTS.errorInfoChanged },
77
129
  ],
78
130
  inputs: [
79
131
  { name: "key" },
@@ -90,6 +142,7 @@ class StorageCore extends EventTarget {
90
142
  _value = null;
91
143
  _loading = false;
92
144
  _error = null;
145
+ _errorInfo = null;
93
146
  _key = "";
94
147
  _type = "local";
95
148
  _storageListener = null;
@@ -143,6 +196,15 @@ class StorageCore extends EventTarget {
143
196
  get error() {
144
197
  return this._error;
145
198
  }
199
+ /**
200
+ * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /
201
+ * `recoverable`), or null. Additive wc-bindable property (event
202
+ * `wcs-storage:error-info-changed`), derived from `error`; the existing `error`
203
+ * property/event are unchanged.
204
+ */
205
+ get errorInfo() {
206
+ return this._errorInfo;
207
+ }
146
208
  get key() {
147
209
  return this._key;
148
210
  }
@@ -176,7 +238,11 @@ class StorageCore extends EventTarget {
176
238
  bubbles: true,
177
239
  }));
178
240
  }
179
- _setError(error) {
241
+ // `name` is the caught exception's `Error.name` (passed only from the
242
+ // load/save/remove catch blocks); it stays out of the public `error` shape and
243
+ // is used solely to classify errorInfo (quota vs security vs generic). Inline
244
+ // validation errors (invalid type / missing key) pass no name → invalid-argument.
245
+ _setError(error, name) {
180
246
  // Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,
181
247
  // so suppressing redundant null→null dispatches (every load/save/remove start
182
248
  // clears a usually-already-null error) avoids a spurious error event per
@@ -185,11 +251,25 @@ class StorageCore extends EventTarget {
185
251
  if (this._error === error)
186
252
  return;
187
253
  this._error = error;
254
+ // Keep the additive `errorInfo` taxonomy in sync with `error`: derive from the
255
+ // error (or null on clear). Fires before the `error` event so an observer
256
+ // binding both sees the classification first, mirroring the io-node family.
257
+ this._commitErrorInfo(error === null ? null : deriveStorageErrorInfo(error, name));
188
258
  this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.error, {
189
259
  detail: error,
190
260
  bubbles: true,
191
261
  }));
192
262
  }
263
+ // Called only from _setError (which already same-value-guards on the error
264
+ // reference), so errorInfo transitions exactly when error does — no separate
265
+ // guard needed here.
266
+ _commitErrorInfo(info) {
267
+ this._errorInfo = info;
268
+ this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.errorInfoChanged, {
269
+ detail: info,
270
+ bubbles: true,
271
+ }));
272
+ }
193
273
  // Wrap a caught storage exception into the documented WcsStorageError shape,
194
274
  // tagging it with the failing operation so consumers know which call failed.
195
275
  _toStorageError(operation, e) {
@@ -198,6 +278,14 @@ class StorageCore extends EventTarget {
198
278
  message: e instanceof Error ? e.message : String(e),
199
279
  };
200
280
  }
281
+ // The caught exception's `Error.name` for errorInfo classification (quota vs
282
+ // security vs generic), or "" for a non-Error throw (→ storage-error). Returning
283
+ // a string (never undefined) keeps a caught exception in the execute phase; only
284
+ // inline validation errors, which pass no name to _setError, become start-phase
285
+ // invalid-argument. Single chokepoint so the ternary is covered in one place.
286
+ _errName(e) {
287
+ return e instanceof Error ? e.name : "";
288
+ }
201
289
  _setValue(value) {
202
290
  this._value = value;
203
291
  this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.valueChanged, {
@@ -232,7 +320,7 @@ class StorageCore extends EventTarget {
232
320
  return this._value;
233
321
  }
234
322
  catch (e) {
235
- this._setError(this._toStorageError("load", e));
323
+ this._setError(this._toStorageError("load", e), this._errName(e));
236
324
  this._setLoading(false);
237
325
  return null;
238
326
  }
@@ -267,7 +355,7 @@ class StorageCore extends EventTarget {
267
355
  this._setLoading(false);
268
356
  }
269
357
  catch (e) {
270
- this._setError(this._toStorageError("save", e));
358
+ this._setError(this._toStorageError("save", e), this._errName(e));
271
359
  this._setLoading(false);
272
360
  }
273
361
  }
@@ -287,7 +375,7 @@ class StorageCore extends EventTarget {
287
375
  this._setLoading(false);
288
376
  }
289
377
  catch (e) {
290
- this._setError(this._toStorageError("remove", e));
378
+ this._setError(this._toStorageError("remove", e), this._errName(e));
291
379
  this._setLoading(false);
292
380
  }
293
381
  }
@@ -508,6 +596,9 @@ class Storage extends HTMLElement {
508
596
  get error() {
509
597
  return this._core.error;
510
598
  }
599
+ get errorInfo() {
600
+ return this._core.errorInfo;
601
+ }
511
602
  get connectedCallbackPromise() {
512
603
  return this._connectedCallbackPromise;
513
604
  }
@@ -620,5 +711,5 @@ function bootstrapStorage(userConfig) {
620
711
  registerComponents();
621
712
  }
622
713
 
623
- export { StorageCore, Storage as WcsStorage, bootstrapStorage, getConfig };
714
+ export { StorageCore, WCS_STORAGE_ERROR_CODE, Storage as WcsStorage, bootstrapStorage, getConfig };
624
715
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/events.ts","../src/core/StorageCore.ts","../src/autoTrigger.ts","../src/components/Storage.ts","../src/registerComponents.ts","../src/bootstrapStorage.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n storage: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-storagetarget\",\n tagNames: {\n storage: \"wcs-storage\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n // Validate each tagNames entry individually instead of a blanket\n // Object.assign: a non-string (e.g. { storage: undefined }) would otherwise\n // poison the config and make customElements.define(undefined, …) throw at\n // registration time. Mirrors the typeof guards on autoTrigger / triggerAttribute.\n for (const [key, value] of Object.entries(partialConfig.tagNames)) {\n if (typeof value === \"string\") {\n (_config.tagNames as Record<string, string>)[key] = value;\n }\n }\n }\n frozenConfig = null;\n}\n","// Single source of truth for the custom event names dispatched by StorageCore /\n// Storage. These names appear in two places that must stay in lock-step:\n// 1. the `wcBindable.properties[].event` declarations (consumed by bind())\n// 2. the `dispatchEvent(new CustomEvent(...))` calls that emit them\n// Hard-coding the same string literal in both places risks a silent typo that\n// makes bind() listen for an event no one ever fires. Referencing these\n// constants from both sites keeps them in sync.\nexport const STORAGE_EVENTS = {\n valueChanged: \"wcs-storage:value-changed\",\n loadingChanged: \"wcs-storage:loading-changed\",\n error: \"wcs-storage:error\",\n triggerChanged: \"wcs-storage:trigger-changed\",\n} as const;\n","import { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType, WcsStorageError } from \"../types.js\";\n\nexport class StorageCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: STORAGE_EVENTS.valueChanged, getter: (e: Event) => (e as CustomEvent).detail },\n { name: \"loading\", event: STORAGE_EVENTS.loadingChanged },\n { name: \"error\", event: STORAGE_EVENTS.error },\n ],\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n ],\n // load / save / remove are synchronous, so none carry the `async` hint.\n commands: [\n { name: \"load\" },\n { name: \"save\" },\n { name: \"remove\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _key: string = \"\";\n private _type: StorageType = \"local\";\n private _storageListener: ((e: StorageEvent) => void) | null = null;\n // Generation guard: bumped on dispose(). The cross-tab `storage` listener\n // captures the generation active when startSync() ran; a callback that fires\n // after dispose() (or a teardown→re-setup) has a stale gen and MUST NOT write\n // state to a torn-down element. A boolean flag is insufficient (dispose→observe\n // would let a stale listener slip through).\n private _gen = 0;\n // SSR: storage access is synchronous, so there is no asynchronous probe to\n // await — readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). Storage sync is command-driven (the Shell calls startSync()\n // from connectedCallback), so observe() is an idempotent no-op that resolves\n // once ready; dispose() tears down the cross-tab listener and invalidates any\n // in-flight listener callback.\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stopSync();\n }\n\n get value(): any {\n return this._value;\n }\n\n // Set the current value *without* persisting it. Persistence happens only via\n // save() / remove() / a cross-tab storage event. This setter exists so the\n // Shell (manual mode) can stage a value handed in via a `value` binding and\n // then commit it later with save()/trigger. It mirrors the value to observers\n // through the same `value-changed` event load()/save() use (CSBC: a Core value\n // change is observable), but it deliberately does not touch storage.\n //\n // Same-value writes are skipped to break a potential feedback loop:\n // value-changed → state binding → value setter → value-changed → …\n set value(v: any) {\n if (Object.is(v, this._value)) return;\n this._setValue(v);\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n get key(): string {\n return this._key;\n }\n\n set key(value: string) {\n // Defensive normalization for direct Core use (the Shell already passes a\n // string via `getAttribute(\"key\") || \"\"`). Coercing to String keeps a\n // non-string assignment from poisoning the cross-tab `e.key !== _key`\n // comparison; empty keys are still rejected at operation time.\n this._key = String(value);\n }\n\n get type(): StorageType {\n return this._type;\n }\n\n set type(value: StorageType) {\n if (value !== \"local\" && value !== \"session\") {\n // never-throw: an invalid type is routed to the error property and the\n // current type is kept (the safe default), rather than throwing out of the\n // setter / setAttribute / connectedCallback.\n this._setError({ operation: \"type\", message: `Invalid storage type: \"${value}\". Must be \"local\" or \"session\".` });\n return;\n }\n this._type = value;\n }\n\n private _getStorage(): globalThis.Storage {\n return this._type === \"session\" ? sessionStorage : localStorage;\n }\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.loadingChanged, {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n // Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,\n // so suppressing redundant null→null dispatches (every load/save/remove start\n // clears a usually-already-null error) avoids a spurious error event per\n // successful operation. Reference identity is sufficient: each failure builds\n // a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.error, {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Wrap a caught storage exception into the documented WcsStorageError shape,\n // tagging it with the failing operation so consumers know which call failed.\n private _toStorageError(operation: WcsStorageError[\"operation\"], e: unknown): WcsStorageError {\n return {\n operation,\n message: e instanceof Error ? e.message : String(e),\n };\n }\n\n private _setValue(value: any): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.valueChanged, {\n detail: value,\n bubbles: true,\n }));\n }\n\n load(): any {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property and a\n // sanitized null is returned, rather than throwing.\n this._setError({ operation: \"load\", message: \"key is required.\" });\n return null;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n const raw = storage.getItem(this._key);\n\n if (raw === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(raw));\n } catch {\n this._setValue(raw);\n }\n }\n\n this._setLoading(false);\n return this._value;\n } catch (e: any) {\n this._setError(this._toStorageError(\"load\", e));\n this._setLoading(false);\n return null;\n }\n }\n\n save(value: any): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (save returns void).\n this._setError({ operation: \"save\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n\n if (value === null || value === undefined) {\n storage.removeItem(this._key);\n // Normalize the removed value to null (matching remove() and load() of a\n // missing key) so saving `undefined` does not leave the getter returning\n // `undefined`. README's serialization table documents null/undefined as\n // \"null\" on read-back.\n this._setValue(null);\n } else if (typeof value === \"string\") {\n storage.setItem(this._key, value);\n this._setValue(value);\n } else {\n storage.setItem(this._key, JSON.stringify(value));\n this._setValue(value);\n }\n\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"save\", e));\n this._setLoading(false);\n }\n }\n\n remove(): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (remove returns void).\n this._setError({ operation: \"remove\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n storage.removeItem(this._key);\n this._setValue(null);\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"remove\", e));\n this._setLoading(false);\n }\n }\n\n startSync(): void {\n if (this._storageListener) return;\n\n // Capture the generation active when sync starts. A `storage` event that\n // fires after dispose() (which bumps _gen and removes the listener) carries a\n // stale gen and must not write state to a torn-down element. stopSync()\n // already detaches the listener, but the gen guard also covers a queued event\n // delivered between dispose()'s bump and the actual removeEventListener.\n const gen = ++this._gen;\n\n this._storageListener = (e: StorageEvent) => {\n if (gen !== this._gen) return;\n if (e.key !== this._key) return;\n if (this._type === \"session\") return;\n\n // A fresh value arriving from another tab supersedes any stale error from\n // a prior failed load/save/remove. Clearing it here keeps the sync path\n // consistent with load()/save()/remove(), which all reset error to null at\n // the start of a successful operation — otherwise an \"error present + fresh\n // value\" inconsistency could persist after a cross-tab update.\n this._setError(null);\n\n if (e.newValue === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(e.newValue));\n } catch {\n this._setValue(e.newValue);\n }\n }\n };\n\n globalThis.addEventListener(\"storage\", this._storageListener);\n }\n\n stopSync(): void {\n if (!this._storageListener) return;\n globalThis.removeEventListener(\"storage\", this._storageListener);\n this._storageListener = null;\n }\n}\n","import { config } from \"./config.js\";\nimport type { Storage } from \"./components/Storage.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const storageId = triggerElement.getAttribute(config.triggerAttribute);\n if (!storageId) return;\n\n // Resolve the registered constructor at call time instead of importing Storage\n // as a value. The value import created a components/Storage.ts ⇄ autoTrigger.ts\n // cycle (Storage.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-storage> class matches — without the import cycle.\n const StorageCtor = customElements.get(config.tagNames.storage);\n const storageElement = document.getElementById(storageId);\n if (!StorageCtor || !(storageElement instanceof StorageCtor)) return;\n\n event.preventDefault();\n (storageElement as Storage).save();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType } from \"../types.js\";\nimport { StorageCore } from \"../core/StorageCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class Storage extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...StorageCore.wcBindable,\n properties: [\n ...StorageCore.wcBindable.properties,\n { name: \"trigger\", event: STORAGE_EVENTS.triggerChanged },\n ],\n // Shell-level input surface. The Core declares only the portable `key` / `type`;\n // the Shell adds the DOM-driven settable surface. No `attribute` hints are given:\n // the `key` / `type` / `manual` setters already reflect to their attributes, so a\n // binding system that mirrors inputs[].attribute would set the attribute twice\n // (`value` / `trigger` are not attribute-backed). `commands` (load / save / remove)\n // are inherited unchanged from the Core via the spread above.\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n { name: \"value\" },\n { name: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n static get observedAttributes(): string[] { return [\"key\", \"type\"]; }\n\n private _core: StorageCore;\n private _trigger: boolean = false;\n // Storage load()/save() are synchronous, so connection work never defers.\n // This stays an already-resolved Promise for the whole lifecycle; it exists\n // only to satisfy the `hasConnectedCallbackPromise` protocol (consumers may\n // `await el.connectedCallbackPromise`). connectedCallback intentionally does\n // not reassign it — there is nothing async to wait for, unlike <wcs-fetch>.\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new StorageCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n [STORAGE_EVENTS.loadingChanged]: (d) => ({ loading: d === true }),\n [STORAGE_EVENTS.error]: (d) => ({ error: d != null }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // Push the Shell's current attribute-derived key / type down into the Core.\n // Every operation (load / save / remove / value setter) and every lifecycle\n // hook that may run a Core operation or cross-tab sync must do this first, so\n // the Core never acts on a stale key / type. Centralizing it here avoids the\n // previous pattern of repeating `_core.key = …; _core.type = …;` at each call\n // site, which risked a future call site forgetting one of the two.\n private _syncCore(): void {\n this._core.key = this.key;\n this._core.type = this.type;\n }\n\n get key(): string {\n return this.getAttribute(\"key\") || \"\";\n }\n\n set key(value: string) {\n this.setAttribute(\"key\", value);\n }\n\n get type(): StorageType {\n // Normalize at the Shell boundary: any attribute value other than the\n // exact \"session\" falls back to \"local\". This keeps an invalid attribute\n // (e.g. type=\"foo\") from reaching the Core's validating setter and throwing\n // out of setAttribute / connectedCallback.\n return this.getAttribute(\"type\") === \"session\" ? \"session\" : \"local\";\n }\n\n set type(value: StorageType) {\n this.setAttribute(\"type\", value);\n }\n\n get value(): any {\n return this._core.value;\n }\n\n set value(v: any) {\n // Non-manual mode: assigning `value` auto-saves the *assigned* argument `v`\n // (write-through). Note this differs from save()/trigger, which persist the\n // *current* `_core.value` (which load() or a cross-tab `storage` event may\n // have updated). See README \"Design Notes\" for the rationale.\n //\n // Manual mode: assigning `value` does NOT persist — it only stages the value\n // into the Core (no storage write). This keeps the getter/setter consistent\n // (`el.value = x; el.value === x`) and lets a later save()/trigger commit the\n // staged value, so a `value: …` + `trigger: …` binding pair works as\n // documented. The actual write still happens only via save()/trigger.\n if (!this.manual) {\n this._syncCore();\n this._core.save(v);\n } else {\n this._core.value = v;\n }\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n const v = !!value;\n if (v) {\n this._trigger = true;\n // save() is never-throw (a failure — e.g. key unset — is routed to the\n // `error` property, not thrown), but the try/finally is kept defensively\n // to guarantee the trigger resets to false and the completion event fires\n // even in the unexpected event of a throw, so the trigger never gets stuck\n // in the `true` state.\n try {\n this.save();\n } finally {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(STORAGE_EVENTS.triggerChanged, {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n load(): any {\n this._syncCore();\n return this._core.load();\n }\n\n // The `save` command differs in arity between the two CSBC surfaces:\n // - Core: save(value) — caller supplies the value to persist\n // - Shell: save() — persists the current `_core.value` (no argument)\n // Both are exposed under the same `commands` entry name \"save\". The protocol\n // `commands` list is descriptive metadata only and carries no arity, so this\n // is not a protocol violation; the difference is contractual and documented\n // in the README (\"Design Notes\").\n save(): void {\n this._syncCore();\n this._core.save(this._core.value);\n }\n\n remove(): void {\n this._syncCore();\n this._core.remove();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected) return;\n if (name === \"key\") {\n // Always keep the Core's key in sync with the attribute, regardless of\n // mode or whether the new value is empty. The cross-tab `storage` listener\n // compares `e.key !== _core.key`, so a stale Core key would make sync watch\n // the wrong (old/empty) key after a runtime key change. load() (which also\n // syncs the Core) only runs for non-manual mode with a non-empty key.\n this._syncCore();\n if (newValue && !this.manual) {\n this.load();\n }\n }\n if (name === \"type\") {\n // Route through the normalizing getter so an invalid attribute value\n // (e.g. type=\"foo\") falls back to \"local\" instead of throwing.\n this._syncCore();\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.key) {\n this.load();\n }\n // Always bind the cross-tab watcher to the Shell's current key/type before\n // starting sync. In paths where load()/save() never run (e.g. manual mode,\n // or key set via JS without a load), _core.key/_core.type would otherwise\n // keep a stale/empty value and the storage listener's `e.key !== _key`\n // check would compare against the wrong key. This also covers detach →\n // re-attach: stale Core key from a previous session is overwritten here.\n this._syncCore();\n this._core.startSync();\n }\n\n disconnectedCallback(): void {\n this._core.stopSync();\n }\n}\n","import { Storage } from \"./components/Storage.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.storage)) {\n customElements.define(config.tagNames.storage, Storage);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapStorage(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"AAUA,MAAM,OAAO,GAAoB;AAC/B,IAAA,WAAW,EAAE,IAAI;AACjB,IAAA,gBAAgB,EAAE,oBAAoB;AACtC,IAAA,QAAQ,EAAE;AACR,QAAA,OAAO,EAAE,aAAa;AACvB,KAAA;CACF;AAED,SAAS,UAAU,CAAI,GAAM,EAAA;AAC3B,IAAA,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,QAAA,OAAO,GAAG;AACvD,IAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;IAClB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AAClC,QAAA,UAAU,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC;IACnD;AACA,IAAA,OAAO,GAAG;AACZ;AAEA,SAAS,SAAS,CAAI,GAAM,EAAA;AAC1B,IAAA,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,QAAA,OAAO,GAAG;IACvD,MAAM,KAAK,GAA4B,EAAE;IACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAClC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC;IAC/D;AACA,IAAA,OAAO,KAAU;AACnB;AAEA,IAAI,YAAY,GAAmB,IAAI;AAEhC,MAAM,MAAM,GAAY,OAAkB;SAEjC,SAAS,GAAA;IACvB,IAAI,CAAC,YAAY,EAAE;QACjB,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/C;AACA,IAAA,OAAO,YAAY;AACrB;AAEM,SAAU,SAAS,CAAC,aAA8B,EAAA;AACtD,IAAA,IAAI,OAAO,aAAa,CAAC,WAAW,KAAK,SAAS,EAAE;AAClD,QAAA,OAAO,CAAC,WAAW,GAAG,aAAa,CAAC,WAAW;IACjD;AACA,IAAA,IAAI,OAAO,aAAa,CAAC,gBAAgB,KAAK,QAAQ,EAAE;AACtD,QAAA,OAAO,CAAC,gBAAgB,GAAG,aAAa,CAAC,gBAAgB;IAC3D;AACA,IAAA,IAAI,aAAa,CAAC,QAAQ,EAAE;;;;;AAK1B,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE;AACjE,YAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC5B,gBAAA,OAAO,CAAC,QAAmC,CAAC,GAAG,CAAC,GAAG,KAAK;YAC3D;QACF;IACF;IACA,YAAY,GAAG,IAAI;AACrB;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,cAAc,GAAG;AAC5B,IAAA,YAAY,EAAE,2BAA2B;AACzC,IAAA,cAAc,EAAE,6BAA6B;AAC7C,IAAA,KAAK,EAAE,mBAAmB;AAC1B,IAAA,cAAc,EAAE,6BAA6B;CACrC;;ACTJ,MAAO,WAAY,SAAQ,WAAW,CAAA;IAC1C,OAAO,UAAU,GAAgB;AAC/B,QAAA,QAAQ,EAAE,aAAa;AACvB,QAAA,OAAO,EAAE,CAAC;AACV,QAAA,UAAU,EAAE;YACV,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,CAAQ,KAAM,CAAiB,CAAC,MAAM,EAAE;YACtG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,cAAc,EAAE;YACzD,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,KAAK,EAAE;AAC/C,SAAA;AACD,QAAA,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,KAAK,EAAE;YACf,EAAE,IAAI,EAAE,MAAM,EAAE;AACjB,SAAA;;AAED,QAAA,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,MAAM,EAAE;YAChB,EAAE,IAAI,EAAE,MAAM,EAAE;YAChB,EAAE,IAAI,EAAE,QAAQ,EAAE;AACnB,SAAA;KACF;AAEO,IAAA,OAAO;IACP,MAAM,GAAQ,IAAI;IAClB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAQ,IAAI;IAClB,IAAI,GAAW,EAAE;IACjB,KAAK,GAAgB,OAAO;IAC5B,gBAAgB,GAAuC,IAAI;;;;;;IAM3D,IAAI,GAAG,CAAC;;;AAGR,IAAA,MAAM,GAAkB,OAAO,CAAC,OAAO,EAAE;AAEjD,IAAA,WAAA,CAAY,MAAoB,EAAA;AAC9B,QAAA,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,IAAI;IAC/B;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;;;;;IAMA,OAAO,GAAA;QACL,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,OAAO,GAAA;QACL,IAAI,CAAC,IAAI,EAAE;QACX,IAAI,CAAC,QAAQ,EAAE;IACjB;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;;;;;;;;;;IAWA,IAAI,KAAK,CAAC,CAAM,EAAA;QACd,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;YAAE;AAC/B,QAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACnB;AAEA,IAAA,IAAI,OAAO,GAAA;QACT,OAAO,IAAI,CAAC,QAAQ;IACtB;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;AAEA,IAAA,IAAI,GAAG,GAAA;QACL,OAAO,IAAI,CAAC,IAAI;IAClB;IAEA,IAAI,GAAG,CAAC,KAAa,EAAA;;;;;AAKnB,QAAA,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B;AAEA,IAAA,IAAI,IAAI,GAAA;QACN,OAAO,IAAI,CAAC,KAAK;IACnB;IAEA,IAAI,IAAI,CAAC,KAAkB,EAAA;QACzB,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS,EAAE;;;;AAI5C,YAAA,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA,uBAAA,EAA0B,KAAK,CAAA,gCAAA,CAAkC,EAAE,CAAC;YACjH;QACF;AACA,QAAA,IAAI,CAAC,KAAK,GAAG,KAAK;IACpB;IAEQ,WAAW,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,GAAG,cAAc,GAAG,YAAY;IACjE;AAEQ,IAAA,WAAW,CAAC,OAAgB,EAAA;AAClC,QAAA,IAAI,CAAC,QAAQ,GAAG,OAAO;QACvB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE;AACxE,YAAA,MAAM,EAAE,OAAO;AACf,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;AAEQ,IAAA,SAAS,CAAC,KAAU,EAAA;;;;;;AAM1B,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK;YAAE;AAC3B,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;QACnB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,KAAK,EAAE;AAC/D,YAAA,MAAM,EAAE,KAAK;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;;;IAIQ,eAAe,CAAC,SAAuC,EAAE,CAAU,EAAA;QACzE,OAAO;YACL,SAAS;AACT,YAAA,OAAO,EAAE,CAAC,YAAY,KAAK,GAAG,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC;SACpD;IACH;AAEQ,IAAA,SAAS,CAAC,KAAU,EAAA;AAC1B,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;QACnB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,YAAY,EAAE;AACtE,YAAA,MAAM,EAAE,KAAK;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;IAEA,IAAI,GAAA;AACF,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;;;AAGd,YAAA,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAClE,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAEpB,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE;YAClC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;AAEtC,YAAA,IAAI,GAAG,KAAK,IAAI,EAAE;AAChB,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACtB;iBAAO;AACL,gBAAA,IAAI;oBACF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACjC;AAAE,gBAAA,MAAM;AACN,oBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;gBACrB;YACF;AAEA,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;YACvB,OAAO,IAAI,CAAC,MAAM;QACpB;QAAE,OAAO,CAAM,EAAE;AACf,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC/C,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AACvB,YAAA,OAAO,IAAI;QACb;IACF;AAEA,IAAA,IAAI,CAAC,KAAU,EAAA;AACb,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;;;AAGd,YAAA,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;YAClE;QACF;AAEA,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAEpB,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE;YAElC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE;AACzC,gBAAA,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;AAK7B,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACtB;AAAO,iBAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBACpC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;AACjC,gBAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YACvB;iBAAO;AACL,gBAAA,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACjD,gBAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YACvB;AAEA,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QACzB;QAAE,OAAO,CAAM,EAAE;AACf,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC/C,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QACzB;IACF;IAEA,MAAM,GAAA;AACJ,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;;;AAGd,YAAA,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;YACpE;QACF;AAEA,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAEpB,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE;AAClC,YAAA,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7B,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACpB,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QACzB;QAAE,OAAO,CAAM,EAAE;AACf,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;AACjD,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QACzB;IACF;IAEA,SAAS,GAAA;QACP,IAAI,IAAI,CAAC,gBAAgB;YAAE;;;;;;AAO3B,QAAA,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,IAAI;AAEvB,QAAA,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAe,KAAI;AAC1C,YAAA,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI;gBAAE;AACvB,YAAA,IAAI,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI;gBAAE;AACzB,YAAA,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE;;;;;;AAO9B,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAEpB,YAAA,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,EAAE;AACvB,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACtB;iBAAO;AACL,gBAAA,IAAI;AACF,oBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBACxC;AAAE,gBAAA,MAAM;AACN,oBAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAC5B;YACF;AACF,QAAA,CAAC;QAED,UAAU,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC;IAC/D;IAEA,QAAQ,GAAA;QACN,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE;QAC5B,UAAU,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC;AAChE,QAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI;IAC9B;;;AChSF,IAAI,UAAU,GAAG,KAAK;AAEtB,SAAS,WAAW,CAAC,KAAY,EAAA;AAC/B,IAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;AAC3B,IAAA,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC;QAAE;AAElC,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAU,CAAA,CAAA,EAAI,MAAM,CAAC,gBAAgB,CAAA,CAAA,CAAG,CAAC;AAC9E,IAAA,IAAI,CAAC,cAAc;QAAE;IAErB,MAAM,SAAS,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC,gBAAgB,CAAC;AACtE,IAAA,IAAI,CAAC,SAAS;QAAE;;;;;;AAOhB,IAAA,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;IAC/D,MAAM,cAAc,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC;IACzD,IAAI,CAAC,WAAW,IAAI,EAAE,cAAc,YAAY,WAAW,CAAC;QAAE;IAE9D,KAAK,CAAC,cAAc,EAAE;IACrB,cAA0B,CAAC,IAAI,EAAE;AACpC;SAEgB,mBAAmB,GAAA;AACjC,IAAA,IAAI,UAAU;QAAE;IAChB,UAAU,GAAG,IAAI;AACjB,IAAA,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC;AACjD;;AC1BM,MAAO,OAAQ,SAAQ,WAAW,CAAA;AACtC,IAAA,OAAO,2BAA2B,GAAG,IAAI;IACzC,OAAO,UAAU,GAAgB;QAC/B,GAAG,WAAW,CAAC,UAAU;AACzB,QAAA,UAAU,EAAE;AACV,YAAA,GAAG,WAAW,CAAC,UAAU,CAAC,UAAU;YACpC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,cAAc,EAAE;AAC1D,SAAA;;;;;;;AAOD,QAAA,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,KAAK,EAAE;YACf,EAAE,IAAI,EAAE,MAAM,EAAE;YAChB,EAAE,IAAI,EAAE,OAAO,EAAE;YACjB,EAAE,IAAI,EAAE,QAAQ,EAAE;YAClB,EAAE,IAAI,EAAE,SAAS,EAAE;AACpB,SAAA;KACF;IACD,WAAW,kBAAkB,GAAA,EAAe,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D,IAAA,KAAK;IACL,QAAQ,GAAY,KAAK;;;;;;AAMzB,IAAA,yBAAyB,GAAkB,OAAO,CAAC,OAAO,EAAE;IAC5D,UAAU,GAA4B,IAAI;AAElD,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QACP,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC;AAClC,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE;QACvC,IAAI,CAAC,WAAW,CAAC;AACf,YAAA,CAAC,cAAc,CAAC,cAAc,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;AACjE,YAAA,CAAC,cAAc,CAAC,KAAK,GAAY,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;AAC/D,SAAA,CAAC;IACJ;;;;;AAMA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE;IAC3D;IAEQ,cAAc,GAAA;;;;;;AAMpB,QAAA,IAAI;AACF,YAAA,IAAI,OAAO,IAAI,CAAC,eAAe,KAAK,UAAU;AAAE,gBAAA,OAAO,IAAI;AAC3D,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE;AACxC,YAAA,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;AACjC,YAAA,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;AACpC,YAAA,OAAO,SAAS;QAClB;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;IACF;AAEQ,IAAA,WAAW,CAAC,GAA6D,EAAA;AAC/E,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE;AAC9B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM;AACrC,QAAA,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACnD,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAI;gBACjC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC;AAC/C,gBAAA,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAE,CAAiB,CAAC,MAAM,CAAC,CAAC,EAAE;AAC5E,oBAAA,IAAI;wBACF,IAAI,EAAE,EAAE;AAAE,4BAAA,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;wBAAE;6BAAO;AAAE,4BAAA,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;wBAAE;oBAC5D;AAAE,oBAAA,MAAM,oBAAoB;AAC5B,oBAAA,IAAI,KAAK;wBAAE,IAAI,CAAC,eAAe,CAAC,CAAA,eAAA,EAAkB,IAAI,CAAA,CAAE,EAAE,EAAE,CAAC;gBAC/D;AACF,YAAA,CAAC,CAAC;QACJ;IACF;;;;;;;IAQQ,SAAS,GAAA;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG;QACzB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI;IAC7B;AAEA,IAAA,IAAI,GAAG,GAAA;QACL,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE;IACvC;IAEA,IAAI,GAAG,CAAC,KAAa,EAAA;AACnB,QAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC;IACjC;AAEA,IAAA,IAAI,IAAI,GAAA;;;;;AAKN,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,SAAS,GAAG,SAAS,GAAG,OAAO;IACtE;IAEA,IAAI,IAAI,CAAC,KAAkB,EAAA;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAClC;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;IACzB;IAEA,IAAI,KAAK,CAAC,CAAM,EAAA;;;;;;;;;;;AAWd,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAChB,IAAI,CAAC,SAAS,EAAE;AAChB,YAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACpB;aAAO;AACL,YAAA,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC;QACtB;IACF;AAEA,IAAA,IAAI,OAAO,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO;IAC3B;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;IACzB;AAEA,IAAA,IAAI,wBAAwB,GAAA;QAC1B,OAAO,IAAI,CAAC,yBAAyB;IACvC;AAEA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;IACpC;IAEA,IAAI,MAAM,CAAC,KAAc,EAAA;QACvB,IAAI,KAAK,EAAE;AACT,YAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC;QACjC;aAAO;AACL,YAAA,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAChC;IACF;AAEA,IAAA,IAAI,OAAO,GAAA;QACT,OAAO,IAAI,CAAC,QAAQ;IACtB;IAEA,IAAI,OAAO,CAAC,KAAc,EAAA;AACxB,QAAA,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK;QACjB,IAAI,CAAC,EAAE;AACL,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;;;;;;AAMpB,YAAA,IAAI;gBACF,IAAI,CAAC,IAAI,EAAE;YACb;oBAAU;AACR,gBAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;gBACrB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE;AAChE,oBAAA,MAAM,EAAE,KAAK;AACb,oBAAA,OAAO,EAAE,IAAI;AACd,iBAAA,CAAC,CAAC;YACL;QACF;IACF;IAEA,IAAI,GAAA;QACF,IAAI,CAAC,SAAS,EAAE;AAChB,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;IAC1B;;;;;;;;IASA,IAAI,GAAA;QACF,IAAI,CAAC,SAAS,EAAE;QAChB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IACnC;IAEA,MAAM,GAAA;QACJ,IAAI,CAAC,SAAS,EAAE;AAChB,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;IACrB;AAEA,IAAA,wBAAwB,CAAC,IAAY,EAAE,SAAwB,EAAE,QAAuB,EAAA;QACtF,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE;AACvB,QAAA,IAAI,IAAI,KAAK,KAAK,EAAE;;;;;;YAMlB,IAAI,CAAC,SAAS,EAAE;AAChB,YAAA,IAAI,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;gBAC5B,IAAI,CAAC,IAAI,EAAE;YACb;QACF;AACA,QAAA,IAAI,IAAI,KAAK,MAAM,EAAE;;;YAGnB,IAAI,CAAC,SAAS,EAAE;QAClB;IACF;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AAC3B,QAAA,IAAI,MAAM,CAAC,WAAW,EAAE;AACtB,YAAA,mBAAmB,EAAE;QACvB;QACA,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,IAAI,EAAE;QACb;;;;;;;QAOA,IAAI,CAAC,SAAS,EAAE;AAChB,QAAA,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;IACxB;IAEA,oBAAoB,GAAA;AAClB,QAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;IACvB;;;SC7Pc,kBAAkB,GAAA;AAChC,IAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QAChD,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IACzD;AACF;;ACHM,SAAU,gBAAgB,CAAC,UAA4B,EAAA;IAC3D,IAAI,UAAU,EAAE;QACd,SAAS,CAAC,UAAU,CAAC;IACvB;AACA,IAAA,kBAAkB,EAAE;AACtB;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/events.ts","../src/core/storageCapabilities.ts","../src/core/StorageCore.ts","../src/autoTrigger.ts","../src/components/Storage.ts","../src/registerComponents.ts","../src/bootstrapStorage.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n storage: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-storagetarget\",\n tagNames: {\n storage: \"wcs-storage\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n // Validate each tagNames entry individually instead of a blanket\n // Object.assign: a non-string (e.g. { storage: undefined }) would otherwise\n // poison the config and make customElements.define(undefined, …) throw at\n // registration time. Mirrors the typeof guards on autoTrigger / triggerAttribute.\n for (const [key, value] of Object.entries(partialConfig.tagNames)) {\n if (typeof value === \"string\") {\n (_config.tagNames as Record<string, string>)[key] = value;\n }\n }\n }\n frozenConfig = null;\n}\n","// Single source of truth for the custom event names dispatched by StorageCore /\n// Storage. These names appear in two places that must stay in lock-step:\n// 1. the `wcBindable.properties[].event` declarations (consumed by bind())\n// 2. the `dispatchEvent(new CustomEvent(...))` calls that emit them\n// Hard-coding the same string literal in both places risks a silent typo that\n// makes bind() listen for an event no one ever fires. Referencing these\n// constants from both sites keeps them in sync.\nexport const STORAGE_EVENTS = {\n valueChanged: \"wcs-storage:value-changed\",\n loadingChanged: \"wcs-storage:loading-changed\",\n error: \"wcs-storage:error\",\n errorInfoChanged: \"wcs-storage:error-info-changed\",\n triggerChanged: \"wcs-storage:trigger-changed\",\n} as const;\n","/**\n * storageCapabilities.ts\n *\n * Storage node 固有の error code(taxonomy)と derivation。汎用の error info 型は\n * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から\n * import する。storage の load / save / remove は同期で互いに競合しないため lane は\n * 持たず、error taxonomy(errorInfo)のみを採用する。\n */\n\nimport type { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport type { WcsStorageError } from \"../types.js\";\n\n/** 安定した storage error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_STORAGE_ERROR_CODE = {\n /** `key` 未設定 / 不正な `type` などの入力不備。retry では回復しない。 */\n InvalidArgument: \"invalid-argument\",\n /** `QuotaExceededError` — 容量超過。空きを作れば回復しうる(環境要因)。 */\n QuotaExceeded: \"quota-exceeded\",\n /** `SecurityError` — storage アクセス拒否(cookie 無効 / third-party context 等)。retry では回復しない。 */\n NotAllowed: \"not-allowed\",\n /** その他の caught 例外。 */\n StorageError: \"storage-error\",\n} as const;\n\n/**\n * storage の失敗を serializable な error taxonomy に写す。\n *\n * `name` は caught 例外の `Error.name`(load / save / remove の catch から渡る)。\n * 未指定(undefined)は inline 構築の validation error(不正 `type` / `key` 未設定)を意味し、\n * これは開始前の入力不備なので phase=\"start\" / `invalid-argument` / recoverable=false。\n * caught 例外は実行中の失敗なので phase=\"execute\"。`QuotaExceededError` は環境要因で\n * 空きを作れば回復しうる(recoverable=true)、`SecurityError` は retry で回復しない。\n */\nexport function deriveStorageErrorInfo(error: WcsStorageError, name?: string): WcsIoErrorInfo {\n if (name === undefined) {\n return {\n code: WCS_STORAGE_ERROR_CODE.InvalidArgument,\n phase: \"start\",\n recoverable: false,\n message: error.message,\n };\n }\n if (name === \"QuotaExceededError\") {\n return { code: WCS_STORAGE_ERROR_CODE.QuotaExceeded, phase: \"execute\", recoverable: true, message: error.message };\n }\n if (name === \"SecurityError\") {\n return { code: WCS_STORAGE_ERROR_CODE.NotAllowed, phase: \"execute\", recoverable: false, message: error.message };\n }\n return { code: WCS_STORAGE_ERROR_CODE.StorageError, phase: \"execute\", recoverable: true, message: error.message };\n}\n","import { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType, WcsStorageError } from \"../types.js\";\nimport { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport { deriveStorageErrorInfo } from \"./storageCapabilities.js\";\n\nexport class StorageCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: STORAGE_EVENTS.valueChanged, getter: (e: Event) => (e as CustomEvent).detail },\n { name: \"loading\", event: STORAGE_EVENTS.loadingChanged },\n { name: \"error\", event: STORAGE_EVENTS.error },\n // Serializable failure taxonomy (stable code / phase / recoverable), or null.\n // Additive bindable output derived from `error` (invalid-argument / quota-exceeded\n // / not-allowed / storage-error); the existing `error` property/event are unchanged.\n // Fires wcs-storage:error-info-changed. No lane — load/save/remove don't compete.\n { name: \"errorInfo\", event: STORAGE_EVENTS.errorInfoChanged },\n ],\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n ],\n // load / save / remove are synchronous, so none carry the `async` hint.\n commands: [\n { name: \"load\" },\n { name: \"save\" },\n { name: \"remove\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _errorInfo: WcsIoErrorInfo | null = null;\n private _key: string = \"\";\n private _type: StorageType = \"local\";\n private _storageListener: ((e: StorageEvent) => void) | null = null;\n // Generation guard: bumped on dispose(). The cross-tab `storage` listener\n // captures the generation active when startSync() ran; a callback that fires\n // after dispose() (or a teardown→re-setup) has a stale gen and MUST NOT write\n // state to a torn-down element. A boolean flag is insufficient (dispose→observe\n // would let a stale listener slip through).\n private _gen = 0;\n // SSR: storage access is synchronous, so there is no asynchronous probe to\n // await — readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). Storage sync is command-driven (the Shell calls startSync()\n // from connectedCallback), so observe() is an idempotent no-op that resolves\n // once ready; dispose() tears down the cross-tab listener and invalidates any\n // in-flight listener callback.\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stopSync();\n }\n\n get value(): any {\n return this._value;\n }\n\n // Set the current value *without* persisting it. Persistence happens only via\n // save() / remove() / a cross-tab storage event. This setter exists so the\n // Shell (manual mode) can stage a value handed in via a `value` binding and\n // then commit it later with save()/trigger. It mirrors the value to observers\n // through the same `value-changed` event load()/save() use (CSBC: a Core value\n // change is observable), but it deliberately does not touch storage.\n //\n // Same-value writes are skipped to break a potential feedback loop:\n // value-changed → state binding → value setter → value-changed → …\n set value(v: any) {\n if (Object.is(v, this._value)) return;\n this._setValue(v);\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n /**\n * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /\n * `recoverable`), or null. Additive wc-bindable property (event\n * `wcs-storage:error-info-changed`), derived from `error`; the existing `error`\n * property/event are unchanged.\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n get key(): string {\n return this._key;\n }\n\n set key(value: string) {\n // Defensive normalization for direct Core use (the Shell already passes a\n // string via `getAttribute(\"key\") || \"\"`). Coercing to String keeps a\n // non-string assignment from poisoning the cross-tab `e.key !== _key`\n // comparison; empty keys are still rejected at operation time.\n this._key = String(value);\n }\n\n get type(): StorageType {\n return this._type;\n }\n\n set type(value: StorageType) {\n if (value !== \"local\" && value !== \"session\") {\n // never-throw: an invalid type is routed to the error property and the\n // current type is kept (the safe default), rather than throwing out of the\n // setter / setAttribute / connectedCallback.\n this._setError({ operation: \"type\", message: `Invalid storage type: \"${value}\". Must be \"local\" or \"session\".` });\n return;\n }\n this._type = value;\n }\n\n private _getStorage(): globalThis.Storage {\n return this._type === \"session\" ? sessionStorage : localStorage;\n }\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.loadingChanged, {\n detail: loading,\n bubbles: true,\n }));\n }\n\n // `name` is the caught exception's `Error.name` (passed only from the\n // load/save/remove catch blocks); it stays out of the public `error` shape and\n // is used solely to classify errorInfo (quota vs security vs generic). Inline\n // validation errors (invalid type / missing key) pass no name → invalid-argument.\n private _setError(error: any, name?: string): void {\n // Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,\n // so suppressing redundant null→null dispatches (every load/save/remove start\n // clears a usually-already-null error) avoids a spurious error event per\n // successful operation. Reference identity is sufficient: each failure builds\n // a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n // Keep the additive `errorInfo` taxonomy in sync with `error`: derive from the\n // error (or null on clear). Fires before the `error` event so an observer\n // binding both sees the classification first, mirroring the io-node family.\n this._commitErrorInfo(error === null ? null : deriveStorageErrorInfo(error, name));\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.error, {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Called only from _setError (which already same-value-guards on the error\n // reference), so errorInfo transitions exactly when error does — no separate\n // guard needed here.\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.errorInfoChanged, {\n detail: info,\n bubbles: true,\n }));\n }\n\n // Wrap a caught storage exception into the documented WcsStorageError shape,\n // tagging it with the failing operation so consumers know which call failed.\n private _toStorageError(operation: WcsStorageError[\"operation\"], e: unknown): WcsStorageError {\n return {\n operation,\n message: e instanceof Error ? e.message : String(e),\n };\n }\n\n // The caught exception's `Error.name` for errorInfo classification (quota vs\n // security vs generic), or \"\" for a non-Error throw (→ storage-error). Returning\n // a string (never undefined) keeps a caught exception in the execute phase; only\n // inline validation errors, which pass no name to _setError, become start-phase\n // invalid-argument. Single chokepoint so the ternary is covered in one place.\n private _errName(e: unknown): string {\n return e instanceof Error ? e.name : \"\";\n }\n\n private _setValue(value: any): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.valueChanged, {\n detail: value,\n bubbles: true,\n }));\n }\n\n load(): any {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property and a\n // sanitized null is returned, rather than throwing.\n this._setError({ operation: \"load\", message: \"key is required.\" });\n return null;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n const raw = storage.getItem(this._key);\n\n if (raw === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(raw));\n } catch {\n this._setValue(raw);\n }\n }\n\n this._setLoading(false);\n return this._value;\n } catch (e: any) {\n this._setError(this._toStorageError(\"load\", e), this._errName(e));\n this._setLoading(false);\n return null;\n }\n }\n\n save(value: any): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (save returns void).\n this._setError({ operation: \"save\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n\n if (value === null || value === undefined) {\n storage.removeItem(this._key);\n // Normalize the removed value to null (matching remove() and load() of a\n // missing key) so saving `undefined` does not leave the getter returning\n // `undefined`. README's serialization table documents null/undefined as\n // \"null\" on read-back.\n this._setValue(null);\n } else if (typeof value === \"string\") {\n storage.setItem(this._key, value);\n this._setValue(value);\n } else {\n storage.setItem(this._key, JSON.stringify(value));\n this._setValue(value);\n }\n\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"save\", e), this._errName(e));\n this._setLoading(false);\n }\n }\n\n remove(): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (remove returns void).\n this._setError({ operation: \"remove\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n storage.removeItem(this._key);\n this._setValue(null);\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"remove\", e), this._errName(e));\n this._setLoading(false);\n }\n }\n\n startSync(): void {\n if (this._storageListener) return;\n\n // Capture the generation active when sync starts. A `storage` event that\n // fires after dispose() (which bumps _gen and removes the listener) carries a\n // stale gen and must not write state to a torn-down element. stopSync()\n // already detaches the listener, but the gen guard also covers a queued event\n // delivered between dispose()'s bump and the actual removeEventListener.\n const gen = ++this._gen;\n\n this._storageListener = (e: StorageEvent) => {\n if (gen !== this._gen) return;\n if (e.key !== this._key) return;\n if (this._type === \"session\") return;\n\n // A fresh value arriving from another tab supersedes any stale error from\n // a prior failed load/save/remove. Clearing it here keeps the sync path\n // consistent with load()/save()/remove(), which all reset error to null at\n // the start of a successful operation — otherwise an \"error present + fresh\n // value\" inconsistency could persist after a cross-tab update.\n this._setError(null);\n\n if (e.newValue === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(e.newValue));\n } catch {\n this._setValue(e.newValue);\n }\n }\n };\n\n globalThis.addEventListener(\"storage\", this._storageListener);\n }\n\n stopSync(): void {\n if (!this._storageListener) return;\n globalThis.removeEventListener(\"storage\", this._storageListener);\n this._storageListener = null;\n }\n}\n","import { config } from \"./config.js\";\nimport type { Storage } from \"./components/Storage.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const storageId = triggerElement.getAttribute(config.triggerAttribute);\n if (!storageId) return;\n\n // Resolve the registered constructor at call time instead of importing Storage\n // as a value. The value import created a components/Storage.ts ⇄ autoTrigger.ts\n // cycle (Storage.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-storage> class matches — without the import cycle.\n const StorageCtor = customElements.get(config.tagNames.storage);\n const storageElement = document.getElementById(storageId);\n if (!StorageCtor || !(storageElement instanceof StorageCtor)) return;\n\n event.preventDefault();\n (storageElement as Storage).save();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType } from \"../types.js\";\nimport { StorageCore } from \"../core/StorageCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class Storage extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...StorageCore.wcBindable,\n properties: [\n ...StorageCore.wcBindable.properties,\n { name: \"trigger\", event: STORAGE_EVENTS.triggerChanged },\n ],\n // Shell-level input surface. The Core declares only the portable `key` / `type`;\n // the Shell adds the DOM-driven settable surface. No `attribute` hints are given:\n // the `key` / `type` / `manual` setters already reflect to their attributes, so a\n // binding system that mirrors inputs[].attribute would set the attribute twice\n // (`value` / `trigger` are not attribute-backed). `commands` (load / save / remove)\n // are inherited unchanged from the Core via the spread above.\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n { name: \"value\" },\n { name: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n static get observedAttributes(): string[] { return [\"key\", \"type\"]; }\n\n private _core: StorageCore;\n private _trigger: boolean = false;\n // Storage load()/save() are synchronous, so connection work never defers.\n // This stays an already-resolved Promise for the whole lifecycle; it exists\n // only to satisfy the `hasConnectedCallbackPromise` protocol (consumers may\n // `await el.connectedCallbackPromise`). connectedCallback intentionally does\n // not reassign it — there is nothing async to wait for, unlike <wcs-fetch>.\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new StorageCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n [STORAGE_EVENTS.loadingChanged]: (d) => ({ loading: d === true }),\n [STORAGE_EVENTS.error]: (d) => ({ error: d != null }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // Push the Shell's current attribute-derived key / type down into the Core.\n // Every operation (load / save / remove / value setter) and every lifecycle\n // hook that may run a Core operation or cross-tab sync must do this first, so\n // the Core never acts on a stale key / type. Centralizing it here avoids the\n // previous pattern of repeating `_core.key = …; _core.type = …;` at each call\n // site, which risked a future call site forgetting one of the two.\n private _syncCore(): void {\n this._core.key = this.key;\n this._core.type = this.type;\n }\n\n get key(): string {\n return this.getAttribute(\"key\") || \"\";\n }\n\n set key(value: string) {\n this.setAttribute(\"key\", value);\n }\n\n get type(): StorageType {\n // Normalize at the Shell boundary: any attribute value other than the\n // exact \"session\" falls back to \"local\". This keeps an invalid attribute\n // (e.g. type=\"foo\") from reaching the Core's validating setter and throwing\n // out of setAttribute / connectedCallback.\n return this.getAttribute(\"type\") === \"session\" ? \"session\" : \"local\";\n }\n\n set type(value: StorageType) {\n this.setAttribute(\"type\", value);\n }\n\n get value(): any {\n return this._core.value;\n }\n\n set value(v: any) {\n // Non-manual mode: assigning `value` auto-saves the *assigned* argument `v`\n // (write-through). Note this differs from save()/trigger, which persist the\n // *current* `_core.value` (which load() or a cross-tab `storage` event may\n // have updated). See README \"Design Notes\" for the rationale.\n //\n // Manual mode: assigning `value` does NOT persist — it only stages the value\n // into the Core (no storage write). This keeps the getter/setter consistent\n // (`el.value = x; el.value === x`) and lets a later save()/trigger commit the\n // staged value, so a `value: …` + `trigger: …` binding pair works as\n // documented. The actual write still happens only via save()/trigger.\n if (!this.manual) {\n this._syncCore();\n this._core.save(v);\n } else {\n this._core.value = v;\n }\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n const v = !!value;\n if (v) {\n this._trigger = true;\n // save() is never-throw (a failure — e.g. key unset — is routed to the\n // `error` property, not thrown), but the try/finally is kept defensively\n // to guarantee the trigger resets to false and the completion event fires\n // even in the unexpected event of a throw, so the trigger never gets stuck\n // in the `true` state.\n try {\n this.save();\n } finally {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(STORAGE_EVENTS.triggerChanged, {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n load(): any {\n this._syncCore();\n return this._core.load();\n }\n\n // The `save` command differs in arity between the two CSBC surfaces:\n // - Core: save(value) — caller supplies the value to persist\n // - Shell: save() — persists the current `_core.value` (no argument)\n // Both are exposed under the same `commands` entry name \"save\". The protocol\n // `commands` list is descriptive metadata only and carries no arity, so this\n // is not a protocol violation; the difference is contractual and documented\n // in the README (\"Design Notes\").\n save(): void {\n this._syncCore();\n this._core.save(this._core.value);\n }\n\n remove(): void {\n this._syncCore();\n this._core.remove();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected) return;\n if (name === \"key\") {\n // Always keep the Core's key in sync with the attribute, regardless of\n // mode or whether the new value is empty. The cross-tab `storage` listener\n // compares `e.key !== _core.key`, so a stale Core key would make sync watch\n // the wrong (old/empty) key after a runtime key change. load() (which also\n // syncs the Core) only runs for non-manual mode with a non-empty key.\n this._syncCore();\n if (newValue && !this.manual) {\n this.load();\n }\n }\n if (name === \"type\") {\n // Route through the normalizing getter so an invalid attribute value\n // (e.g. type=\"foo\") falls back to \"local\" instead of throwing.\n this._syncCore();\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.key) {\n this.load();\n }\n // Always bind the cross-tab watcher to the Shell's current key/type before\n // starting sync. In paths where load()/save() never run (e.g. manual mode,\n // or key set via JS without a load), _core.key/_core.type would otherwise\n // keep a stale/empty value and the storage listener's `e.key !== _key`\n // check would compare against the wrong key. This also covers detach →\n // re-attach: stale Core key from a previous session is overwritten here.\n this._syncCore();\n this._core.startSync();\n }\n\n disconnectedCallback(): void {\n this._core.stopSync();\n }\n}\n","import { Storage } from \"./components/Storage.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.storage)) {\n customElements.define(config.tagNames.storage, Storage);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapStorage(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const t={autoTrigger:!0,triggerAttribute:"data-storagetarget",tagNames:{storage:"wcs-storage"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const r of Object.keys(t))e[r]=s(t[r]);return e}let r=null;const i=t;function n(){return r||(r=e(s(t))),r}const a="wcs-storage:value-changed",o="wcs-storage:loading-changed",l="wcs-storage:error",g="wcs-storage:trigger-changed";class h extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:a,getter:t=>t.detail},{name:"loading",event:o},{name:"error",event:l}],inputs:[{name:"key"},{name:"type"}],commands:[{name:"load"},{name:"save"},{name:"remove"}]};_target;_value=null;_loading=!1;_error=null;_key="";_type="local";_storageListener=null;_gen=0;_ready=Promise.resolve();constructor(t){super(),this._target=t??this}get ready(){return this._ready}observe(){return this._ready}dispose(){this._gen++,this.stopSync()}get value(){return this._value}set value(t){Object.is(t,this._value)||this._setValue(t)}get loading(){return this._loading}get error(){return this._error}get key(){return this._key}set key(t){this._key=String(t)}get type(){return this._type}set type(t){"local"===t||"session"===t?this._type=t:this._setError({operation:"type",message:`Invalid storage type: "${t}". Must be "local" or "session".`})}_getStorage(){return"session"===this._type?sessionStorage:localStorage}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent(o,{detail:t,bubbles:!0}))}_setError(t){this._error!==t&&(this._error=t,this._target.dispatchEvent(new CustomEvent(l,{detail:t,bubbles:!0})))}_toStorageError(t,e){return{operation:t,message:e instanceof Error?e.message:String(e)}}_setValue(t){this._value=t,this._target.dispatchEvent(new CustomEvent(a,{detail:t,bubbles:!0}))}load(){if(!this._key)return this._setError({operation:"load",message:"key is required."}),null;this._setLoading(!0),this._setError(null);try{const t=this._getStorage().getItem(this._key);if(null===t)this._setValue(null);else try{this._setValue(JSON.parse(t))}catch{this._setValue(t)}return this._setLoading(!1),this._value}catch(t){return this._setError(this._toStorageError("load",t)),this._setLoading(!1),null}}save(t){if(this._key){this._setLoading(!0),this._setError(null);try{const e=this._getStorage();null==t?(e.removeItem(this._key),this._setValue(null)):"string"==typeof t?(e.setItem(this._key,t),this._setValue(t)):(e.setItem(this._key,JSON.stringify(t)),this._setValue(t)),this._setLoading(!1)}catch(t){this._setError(this._toStorageError("save",t)),this._setLoading(!1)}}else this._setError({operation:"save",message:"key is required."})}remove(){if(this._key){this._setLoading(!0),this._setError(null);try{this._getStorage().removeItem(this._key),this._setValue(null),this._setLoading(!1)}catch(t){this._setError(this._toStorageError("remove",t)),this._setLoading(!1)}}else this._setError({operation:"remove",message:"key is required."})}startSync(){if(this._storageListener)return;const t=++this._gen;this._storageListener=e=>{if(t===this._gen&&e.key===this._key&&"session"!==this._type)if(this._setError(null),null===e.newValue)this._setValue(null);else try{this._setValue(JSON.parse(e.newValue))}catch{this._setValue(e.newValue)}},globalThis.addEventListener("storage",this._storageListener)}stopSync(){this._storageListener&&(globalThis.removeEventListener("storage",this._storageListener),this._storageListener=null)}}let u=!1;function c(t){const e=t.target;if(!(e instanceof Element))return;const s=e.closest(`[${i.triggerAttribute}]`);if(!s)return;const r=s.getAttribute(i.triggerAttribute);if(!r)return;const n=customElements.get(i.tagNames.storage),a=document.getElementById(r);n&&a instanceof n&&(t.preventDefault(),a.save())}class _ extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...h.wcBindable,properties:[...h.wcBindable.properties,{name:"trigger",event:g}],inputs:[{name:"key"},{name:"type"},{name:"value"},{name:"manual"},{name:"trigger"}]};static get observedAttributes(){return["key","type"]}_core;_trigger=!1;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new h(this),this._internals=this._initInternals(),this._wireStates({[o]:t=>({loading:!0===t}),[l]:t=>({error:null!=t})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const t=this.attachInternals();return t.states.add("wcs-probe"),t.states.delete("wcs-probe"),t}catch{return null}}_wireStates(t){if(null===this._internals)return;const e=this._internals.states;for(const[s,r]of Object.entries(t))this.addEventListener(s,t=>{const s=this.hasAttribute("debug-states");for(const[i,n]of Object.entries(r(t.detail))){try{n?e.add(i):e.delete(i)}catch{}s&&this.toggleAttribute(`data-wcs-state-${i}`,n)}})}_syncCore(){this._core.key=this.key,this._core.type=this.type}get key(){return this.getAttribute("key")||""}set key(t){this.setAttribute("key",t)}get type(){return"session"===this.getAttribute("type")?"session":"local"}set type(t){this.setAttribute("type",t)}get value(){return this._core.value}set value(t){this.manual?this._core.value=t:(this._syncCore(),this._core.save(t))}get loading(){return this._core.loading}get error(){return this._core.error}get connectedCallbackPromise(){return this._connectedCallbackPromise}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get trigger(){return this._trigger}set trigger(t){if(!!t){this._trigger=!0;try{this.save()}finally{this._trigger=!1,this.dispatchEvent(new CustomEvent(g,{detail:!1,bubbles:!0}))}}}load(){return this._syncCore(),this._core.load()}save(){this._syncCore(),this._core.save(this._core.value)}remove(){this._syncCore(),this._core.remove()}attributeChangedCallback(t,e,s){this.isConnected&&("key"===t&&(this._syncCore(),s&&!this.manual&&this.load()),"type"===t&&this._syncCore())}connectedCallback(){this.style.display="none",i.autoTrigger&&(u||(u=!0,document.addEventListener("click",c))),!this.manual&&this.key&&this.load(),this._syncCore(),this._core.startSync()}disconnectedCallback(){this._core.stopSync()}}function d(e){e&&function(e){if("boolean"==typeof e.autoTrigger&&(t.autoTrigger=e.autoTrigger),"string"==typeof e.triggerAttribute&&(t.triggerAttribute=e.triggerAttribute),e.tagNames)for(const[s,r]of Object.entries(e.tagNames))"string"==typeof r&&(t.tagNames[s]=r);r=null}(e),customElements.get(i.tagNames.storage)||customElements.define(i.tagNames.storage,_)}export{h as StorageCore,_ as WcsStorage,d as bootstrapStorage,n as getConfig};
1
+ const e={autoTrigger:!0,triggerAttribute:"data-storagetarget",tagNames:{storage:"wcs-storage"}};function t(e){if(null===e||"object"!=typeof e)return e;Object.freeze(e);for(const r of Object.keys(e))t(e[r]);return e}function r(e){if(null===e||"object"!=typeof e)return e;const t={};for(const s of Object.keys(e))t[s]=r(e[s]);return t}let s=null;const i=e;function n(){return s||(s=t(r(e))),s}const a="wcs-storage:value-changed",o="wcs-storage:loading-changed",l="wcs-storage:error",g="wcs-storage:error-info-changed",u="wcs-storage:trigger-changed",c={InvalidArgument:"invalid-argument",QuotaExceeded:"quota-exceeded",NotAllowed:"not-allowed",StorageError:"storage-error"};class h extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:a,getter:e=>e.detail},{name:"loading",event:o},{name:"error",event:l},{name:"errorInfo",event:g}],inputs:[{name:"key"},{name:"type"}],commands:[{name:"load"},{name:"save"},{name:"remove"}]};_target;_value=null;_loading=!1;_error=null;_errorInfo=null;_key="";_type="local";_storageListener=null;_gen=0;_ready=Promise.resolve();constructor(e){super(),this._target=e??this}get ready(){return this._ready}observe(){return this._ready}dispose(){this._gen++,this.stopSync()}get value(){return this._value}set value(e){Object.is(e,this._value)||this._setValue(e)}get loading(){return this._loading}get error(){return this._error}get errorInfo(){return this._errorInfo}get key(){return this._key}set key(e){this._key=String(e)}get type(){return this._type}set type(e){"local"===e||"session"===e?this._type=e:this._setError({operation:"type",message:`Invalid storage type: "${e}". Must be "local" or "session".`})}_getStorage(){return"session"===this._type?sessionStorage:localStorage}_setLoading(e){this._loading=e,this._target.dispatchEvent(new CustomEvent(o,{detail:e,bubbles:!0}))}_setError(e,t){this._error!==e&&(this._error=e,this._commitErrorInfo(null===e?null:function(e,t){return void 0===t?{code:c.InvalidArgument,phase:"start",recoverable:!1,message:e.message}:"QuotaExceededError"===t?{code:c.QuotaExceeded,phase:"execute",recoverable:!0,message:e.message}:"SecurityError"===t?{code:c.NotAllowed,phase:"execute",recoverable:!1,message:e.message}:{code:c.StorageError,phase:"execute",recoverable:!0,message:e.message}}(e,t)),this._target.dispatchEvent(new CustomEvent(l,{detail:e,bubbles:!0})))}_commitErrorInfo(e){this._errorInfo=e,this._target.dispatchEvent(new CustomEvent(g,{detail:e,bubbles:!0}))}_toStorageError(e,t){return{operation:e,message:t instanceof Error?t.message:String(t)}}_errName(e){return e instanceof Error?e.name:""}_setValue(e){this._value=e,this._target.dispatchEvent(new CustomEvent(a,{detail:e,bubbles:!0}))}load(){if(!this._key)return this._setError({operation:"load",message:"key is required."}),null;this._setLoading(!0),this._setError(null);try{const e=this._getStorage().getItem(this._key);if(null===e)this._setValue(null);else try{this._setValue(JSON.parse(e))}catch{this._setValue(e)}return this._setLoading(!1),this._value}catch(e){return this._setError(this._toStorageError("load",e),this._errName(e)),this._setLoading(!1),null}}save(e){if(this._key){this._setLoading(!0),this._setError(null);try{const t=this._getStorage();null==e?(t.removeItem(this._key),this._setValue(null)):"string"==typeof e?(t.setItem(this._key,e),this._setValue(e)):(t.setItem(this._key,JSON.stringify(e)),this._setValue(e)),this._setLoading(!1)}catch(e){this._setError(this._toStorageError("save",e),this._errName(e)),this._setLoading(!1)}}else this._setError({operation:"save",message:"key is required."})}remove(){if(this._key){this._setLoading(!0),this._setError(null);try{this._getStorage().removeItem(this._key),this._setValue(null),this._setLoading(!1)}catch(e){this._setError(this._toStorageError("remove",e),this._errName(e)),this._setLoading(!1)}}else this._setError({operation:"remove",message:"key is required."})}startSync(){if(this._storageListener)return;const e=++this._gen;this._storageListener=t=>{if(e===this._gen&&t.key===this._key&&"session"!==this._type)if(this._setError(null),null===t.newValue)this._setValue(null);else try{this._setValue(JSON.parse(t.newValue))}catch{this._setValue(t.newValue)}},globalThis.addEventListener("storage",this._storageListener)}stopSync(){this._storageListener&&(globalThis.removeEventListener("storage",this._storageListener),this._storageListener=null)}}let _=!1;function d(e){const t=e.target;if(!(t instanceof Element))return;const r=t.closest(`[${i.triggerAttribute}]`);if(!r)return;const s=r.getAttribute(i.triggerAttribute);if(!s)return;const n=customElements.get(i.tagNames.storage),a=document.getElementById(s);n&&a instanceof n&&(e.preventDefault(),a.save())}class m extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...h.wcBindable,properties:[...h.wcBindable.properties,{name:"trigger",event:u}],inputs:[{name:"key"},{name:"type"},{name:"value"},{name:"manual"},{name:"trigger"}]};static get observedAttributes(){return["key","type"]}_core;_trigger=!1;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new h(this),this._internals=this._initInternals(),this._wireStates({[o]:e=>({loading:!0===e}),[l]:e=>({error:null!=e})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const e=this.attachInternals();return e.states.add("wcs-probe"),e.states.delete("wcs-probe"),e}catch{return null}}_wireStates(e){if(null===this._internals)return;const t=this._internals.states;for(const[r,s]of Object.entries(e))this.addEventListener(r,e=>{const r=this.hasAttribute("debug-states");for(const[i,n]of Object.entries(s(e.detail))){try{n?t.add(i):t.delete(i)}catch{}r&&this.toggleAttribute(`data-wcs-state-${i}`,n)}})}_syncCore(){this._core.key=this.key,this._core.type=this.type}get key(){return this.getAttribute("key")||""}set key(e){this.setAttribute("key",e)}get type(){return"session"===this.getAttribute("type")?"session":"local"}set type(e){this.setAttribute("type",e)}get value(){return this._core.value}set value(e){this.manual?this._core.value=e:(this._syncCore(),this._core.save(e))}get loading(){return this._core.loading}get error(){return this._core.error}get errorInfo(){return this._core.errorInfo}get connectedCallbackPromise(){return this._connectedCallbackPromise}get manual(){return this.hasAttribute("manual")}set manual(e){e?this.setAttribute("manual",""):this.removeAttribute("manual")}get trigger(){return this._trigger}set trigger(e){if(!!e){this._trigger=!0;try{this.save()}finally{this._trigger=!1,this.dispatchEvent(new CustomEvent(u,{detail:!1,bubbles:!0}))}}}load(){return this._syncCore(),this._core.load()}save(){this._syncCore(),this._core.save(this._core.value)}remove(){this._syncCore(),this._core.remove()}attributeChangedCallback(e,t,r){this.isConnected&&("key"===e&&(this._syncCore(),r&&!this.manual&&this.load()),"type"===e&&this._syncCore())}connectedCallback(){this.style.display="none",i.autoTrigger&&(_||(_=!0,document.addEventListener("click",d))),!this.manual&&this.key&&this.load(),this._syncCore(),this._core.startSync()}disconnectedCallback(){this._core.stopSync()}}function y(t){t&&function(t){if("boolean"==typeof t.autoTrigger&&(e.autoTrigger=t.autoTrigger),"string"==typeof t.triggerAttribute&&(e.triggerAttribute=t.triggerAttribute),t.tagNames)for(const[r,s]of Object.entries(t.tagNames))"string"==typeof s&&(e.tagNames[r]=s);s=null}(t),customElements.get(i.tagNames.storage)||customElements.define(i.tagNames.storage,m)}export{h as StorageCore,c as WCS_STORAGE_ERROR_CODE,m as WcsStorage,y as bootstrapStorage,n as getConfig};
2
2
  //# sourceMappingURL=index.esm.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/events.ts","../src/core/StorageCore.ts","../src/autoTrigger.ts","../src/components/Storage.ts","../src/bootstrapStorage.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n storage: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-storagetarget\",\n tagNames: {\n storage: \"wcs-storage\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n // Validate each tagNames entry individually instead of a blanket\n // Object.assign: a non-string (e.g. { storage: undefined }) would otherwise\n // poison the config and make customElements.define(undefined, …) throw at\n // registration time. Mirrors the typeof guards on autoTrigger / triggerAttribute.\n for (const [key, value] of Object.entries(partialConfig.tagNames)) {\n if (typeof value === \"string\") {\n (_config.tagNames as Record<string, string>)[key] = value;\n }\n }\n }\n frozenConfig = null;\n}\n","// Single source of truth for the custom event names dispatched by StorageCore /\n// Storage. These names appear in two places that must stay in lock-step:\n// 1. the `wcBindable.properties[].event` declarations (consumed by bind())\n// 2. the `dispatchEvent(new CustomEvent(...))` calls that emit them\n// Hard-coding the same string literal in both places risks a silent typo that\n// makes bind() listen for an event no one ever fires. Referencing these\n// constants from both sites keeps them in sync.\nexport const STORAGE_EVENTS = {\n valueChanged: \"wcs-storage:value-changed\",\n loadingChanged: \"wcs-storage:loading-changed\",\n error: \"wcs-storage:error\",\n triggerChanged: \"wcs-storage:trigger-changed\",\n} as const;\n","import { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType, WcsStorageError } from \"../types.js\";\n\nexport class StorageCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: STORAGE_EVENTS.valueChanged, getter: (e: Event) => (e as CustomEvent).detail },\n { name: \"loading\", event: STORAGE_EVENTS.loadingChanged },\n { name: \"error\", event: STORAGE_EVENTS.error },\n ],\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n ],\n // load / save / remove are synchronous, so none carry the `async` hint.\n commands: [\n { name: \"load\" },\n { name: \"save\" },\n { name: \"remove\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _key: string = \"\";\n private _type: StorageType = \"local\";\n private _storageListener: ((e: StorageEvent) => void) | null = null;\n // Generation guard: bumped on dispose(). The cross-tab `storage` listener\n // captures the generation active when startSync() ran; a callback that fires\n // after dispose() (or a teardown→re-setup) has a stale gen and MUST NOT write\n // state to a torn-down element. A boolean flag is insufficient (dispose→observe\n // would let a stale listener slip through).\n private _gen = 0;\n // SSR: storage access is synchronous, so there is no asynchronous probe to\n // await — readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). Storage sync is command-driven (the Shell calls startSync()\n // from connectedCallback), so observe() is an idempotent no-op that resolves\n // once ready; dispose() tears down the cross-tab listener and invalidates any\n // in-flight listener callback.\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stopSync();\n }\n\n get value(): any {\n return this._value;\n }\n\n // Set the current value *without* persisting it. Persistence happens only via\n // save() / remove() / a cross-tab storage event. This setter exists so the\n // Shell (manual mode) can stage a value handed in via a `value` binding and\n // then commit it later with save()/trigger. It mirrors the value to observers\n // through the same `value-changed` event load()/save() use (CSBC: a Core value\n // change is observable), but it deliberately does not touch storage.\n //\n // Same-value writes are skipped to break a potential feedback loop:\n // value-changed → state binding → value setter → value-changed → …\n set value(v: any) {\n if (Object.is(v, this._value)) return;\n this._setValue(v);\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n get key(): string {\n return this._key;\n }\n\n set key(value: string) {\n // Defensive normalization for direct Core use (the Shell already passes a\n // string via `getAttribute(\"key\") || \"\"`). Coercing to String keeps a\n // non-string assignment from poisoning the cross-tab `e.key !== _key`\n // comparison; empty keys are still rejected at operation time.\n this._key = String(value);\n }\n\n get type(): StorageType {\n return this._type;\n }\n\n set type(value: StorageType) {\n if (value !== \"local\" && value !== \"session\") {\n // never-throw: an invalid type is routed to the error property and the\n // current type is kept (the safe default), rather than throwing out of the\n // setter / setAttribute / connectedCallback.\n this._setError({ operation: \"type\", message: `Invalid storage type: \"${value}\". Must be \"local\" or \"session\".` });\n return;\n }\n this._type = value;\n }\n\n private _getStorage(): globalThis.Storage {\n return this._type === \"session\" ? sessionStorage : localStorage;\n }\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.loadingChanged, {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n // Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,\n // so suppressing redundant null→null dispatches (every load/save/remove start\n // clears a usually-already-null error) avoids a spurious error event per\n // successful operation. Reference identity is sufficient: each failure builds\n // a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.error, {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Wrap a caught storage exception into the documented WcsStorageError shape,\n // tagging it with the failing operation so consumers know which call failed.\n private _toStorageError(operation: WcsStorageError[\"operation\"], e: unknown): WcsStorageError {\n return {\n operation,\n message: e instanceof Error ? e.message : String(e),\n };\n }\n\n private _setValue(value: any): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.valueChanged, {\n detail: value,\n bubbles: true,\n }));\n }\n\n load(): any {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property and a\n // sanitized null is returned, rather than throwing.\n this._setError({ operation: \"load\", message: \"key is required.\" });\n return null;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n const raw = storage.getItem(this._key);\n\n if (raw === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(raw));\n } catch {\n this._setValue(raw);\n }\n }\n\n this._setLoading(false);\n return this._value;\n } catch (e: any) {\n this._setError(this._toStorageError(\"load\", e));\n this._setLoading(false);\n return null;\n }\n }\n\n save(value: any): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (save returns void).\n this._setError({ operation: \"save\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n\n if (value === null || value === undefined) {\n storage.removeItem(this._key);\n // Normalize the removed value to null (matching remove() and load() of a\n // missing key) so saving `undefined` does not leave the getter returning\n // `undefined`. README's serialization table documents null/undefined as\n // \"null\" on read-back.\n this._setValue(null);\n } else if (typeof value === \"string\") {\n storage.setItem(this._key, value);\n this._setValue(value);\n } else {\n storage.setItem(this._key, JSON.stringify(value));\n this._setValue(value);\n }\n\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"save\", e));\n this._setLoading(false);\n }\n }\n\n remove(): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (remove returns void).\n this._setError({ operation: \"remove\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n storage.removeItem(this._key);\n this._setValue(null);\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"remove\", e));\n this._setLoading(false);\n }\n }\n\n startSync(): void {\n if (this._storageListener) return;\n\n // Capture the generation active when sync starts. A `storage` event that\n // fires after dispose() (which bumps _gen and removes the listener) carries a\n // stale gen and must not write state to a torn-down element. stopSync()\n // already detaches the listener, but the gen guard also covers a queued event\n // delivered between dispose()'s bump and the actual removeEventListener.\n const gen = ++this._gen;\n\n this._storageListener = (e: StorageEvent) => {\n if (gen !== this._gen) return;\n if (e.key !== this._key) return;\n if (this._type === \"session\") return;\n\n // A fresh value arriving from another tab supersedes any stale error from\n // a prior failed load/save/remove. Clearing it here keeps the sync path\n // consistent with load()/save()/remove(), which all reset error to null at\n // the start of a successful operation — otherwise an \"error present + fresh\n // value\" inconsistency could persist after a cross-tab update.\n this._setError(null);\n\n if (e.newValue === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(e.newValue));\n } catch {\n this._setValue(e.newValue);\n }\n }\n };\n\n globalThis.addEventListener(\"storage\", this._storageListener);\n }\n\n stopSync(): void {\n if (!this._storageListener) return;\n globalThis.removeEventListener(\"storage\", this._storageListener);\n this._storageListener = null;\n }\n}\n","import { config } from \"./config.js\";\nimport type { Storage } from \"./components/Storage.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const storageId = triggerElement.getAttribute(config.triggerAttribute);\n if (!storageId) return;\n\n // Resolve the registered constructor at call time instead of importing Storage\n // as a value. The value import created a components/Storage.ts ⇄ autoTrigger.ts\n // cycle (Storage.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-storage> class matches — without the import cycle.\n const StorageCtor = customElements.get(config.tagNames.storage);\n const storageElement = document.getElementById(storageId);\n if (!StorageCtor || !(storageElement instanceof StorageCtor)) return;\n\n event.preventDefault();\n (storageElement as Storage).save();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType } from \"../types.js\";\nimport { StorageCore } from \"../core/StorageCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class Storage extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...StorageCore.wcBindable,\n properties: [\n ...StorageCore.wcBindable.properties,\n { name: \"trigger\", event: STORAGE_EVENTS.triggerChanged },\n ],\n // Shell-level input surface. The Core declares only the portable `key` / `type`;\n // the Shell adds the DOM-driven settable surface. No `attribute` hints are given:\n // the `key` / `type` / `manual` setters already reflect to their attributes, so a\n // binding system that mirrors inputs[].attribute would set the attribute twice\n // (`value` / `trigger` are not attribute-backed). `commands` (load / save / remove)\n // are inherited unchanged from the Core via the spread above.\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n { name: \"value\" },\n { name: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n static get observedAttributes(): string[] { return [\"key\", \"type\"]; }\n\n private _core: StorageCore;\n private _trigger: boolean = false;\n // Storage load()/save() are synchronous, so connection work never defers.\n // This stays an already-resolved Promise for the whole lifecycle; it exists\n // only to satisfy the `hasConnectedCallbackPromise` protocol (consumers may\n // `await el.connectedCallbackPromise`). connectedCallback intentionally does\n // not reassign it — there is nothing async to wait for, unlike <wcs-fetch>.\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new StorageCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n [STORAGE_EVENTS.loadingChanged]: (d) => ({ loading: d === true }),\n [STORAGE_EVENTS.error]: (d) => ({ error: d != null }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // Push the Shell's current attribute-derived key / type down into the Core.\n // Every operation (load / save / remove / value setter) and every lifecycle\n // hook that may run a Core operation or cross-tab sync must do this first, so\n // the Core never acts on a stale key / type. Centralizing it here avoids the\n // previous pattern of repeating `_core.key = …; _core.type = …;` at each call\n // site, which risked a future call site forgetting one of the two.\n private _syncCore(): void {\n this._core.key = this.key;\n this._core.type = this.type;\n }\n\n get key(): string {\n return this.getAttribute(\"key\") || \"\";\n }\n\n set key(value: string) {\n this.setAttribute(\"key\", value);\n }\n\n get type(): StorageType {\n // Normalize at the Shell boundary: any attribute value other than the\n // exact \"session\" falls back to \"local\". This keeps an invalid attribute\n // (e.g. type=\"foo\") from reaching the Core's validating setter and throwing\n // out of setAttribute / connectedCallback.\n return this.getAttribute(\"type\") === \"session\" ? \"session\" : \"local\";\n }\n\n set type(value: StorageType) {\n this.setAttribute(\"type\", value);\n }\n\n get value(): any {\n return this._core.value;\n }\n\n set value(v: any) {\n // Non-manual mode: assigning `value` auto-saves the *assigned* argument `v`\n // (write-through). Note this differs from save()/trigger, which persist the\n // *current* `_core.value` (which load() or a cross-tab `storage` event may\n // have updated). See README \"Design Notes\" for the rationale.\n //\n // Manual mode: assigning `value` does NOT persist — it only stages the value\n // into the Core (no storage write). This keeps the getter/setter consistent\n // (`el.value = x; el.value === x`) and lets a later save()/trigger commit the\n // staged value, so a `value: …` + `trigger: …` binding pair works as\n // documented. The actual write still happens only via save()/trigger.\n if (!this.manual) {\n this._syncCore();\n this._core.save(v);\n } else {\n this._core.value = v;\n }\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n const v = !!value;\n if (v) {\n this._trigger = true;\n // save() is never-throw (a failure — e.g. key unset — is routed to the\n // `error` property, not thrown), but the try/finally is kept defensively\n // to guarantee the trigger resets to false and the completion event fires\n // even in the unexpected event of a throw, so the trigger never gets stuck\n // in the `true` state.\n try {\n this.save();\n } finally {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(STORAGE_EVENTS.triggerChanged, {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n load(): any {\n this._syncCore();\n return this._core.load();\n }\n\n // The `save` command differs in arity between the two CSBC surfaces:\n // - Core: save(value) — caller supplies the value to persist\n // - Shell: save() — persists the current `_core.value` (no argument)\n // Both are exposed under the same `commands` entry name \"save\". The protocol\n // `commands` list is descriptive metadata only and carries no arity, so this\n // is not a protocol violation; the difference is contractual and documented\n // in the README (\"Design Notes\").\n save(): void {\n this._syncCore();\n this._core.save(this._core.value);\n }\n\n remove(): void {\n this._syncCore();\n this._core.remove();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected) return;\n if (name === \"key\") {\n // Always keep the Core's key in sync with the attribute, regardless of\n // mode or whether the new value is empty. The cross-tab `storage` listener\n // compares `e.key !== _core.key`, so a stale Core key would make sync watch\n // the wrong (old/empty) key after a runtime key change. load() (which also\n // syncs the Core) only runs for non-manual mode with a non-empty key.\n this._syncCore();\n if (newValue && !this.manual) {\n this.load();\n }\n }\n if (name === \"type\") {\n // Route through the normalizing getter so an invalid attribute value\n // (e.g. type=\"foo\") falls back to \"local\" instead of throwing.\n this._syncCore();\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.key) {\n this.load();\n }\n // Always bind the cross-tab watcher to the Shell's current key/type before\n // starting sync. In paths where load()/save() never run (e.g. manual mode,\n // or key set via JS without a load), _core.key/_core.type would otherwise\n // keep a stale/empty value and the storage listener's `e.key !== _key`\n // check would compare against the wrong key. This also covers detach →\n // re-attach: stale Core key from a previous session is overwritten here.\n this._syncCore();\n this._core.startSync();\n }\n\n disconnectedCallback(): void {\n this._core.stopSync();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapStorage(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { Storage } from \"./components/Storage.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.storage)) {\n customElements.define(config.tagNames.storage, Storage);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","storage","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","STORAGE_EVENTS","StorageCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","inputs","commands","_target","_value","_loading","_error","_key","_type","_storageListener","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","observe","dispose","stopSync","value","v","is","_setValue","loading","error","String","type","_setError","operation","message","_getStorage","sessionStorage","localStorage","_setLoading","dispatchEvent","CustomEvent","bubbles","_toStorageError","Error","load","raw","getItem","JSON","parse","save","removeItem","setItem","stringify","remove","startSync","gen","newValue","globalThis","addEventListener","removeEventListener","registered","handleClick","Element","triggerElement","closest","storageId","getAttribute","StorageCtor","customElements","get","storageElement","document","getElementById","preventDefault","Storage","HTMLElement","wcBindable","observedAttributes","_core","_trigger","_connectedCallbackPromise","_internals","_initInternals","_wireStates","STORAGE_EVENTS_loadingChanged","d","STORAGE_EVENTS_error","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","debug","hasAttribute","on","toggleAttribute","_syncCore","setAttribute","manual","connectedCallbackPromise","removeAttribute","trigger","attributeChangedCallback","_oldValue","isConnected","connectedCallback","style","display","disconnectedCallback","bootstrapStorage","userConfig","partialConfig","setConfig","define"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/events.ts","../src/core/storageCapabilities.ts","../src/core/StorageCore.ts","../src/autoTrigger.ts","../src/components/Storage.ts","../src/bootstrapStorage.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n storage: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-storagetarget\",\n tagNames: {\n storage: \"wcs-storage\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n // Validate each tagNames entry individually instead of a blanket\n // Object.assign: a non-string (e.g. { storage: undefined }) would otherwise\n // poison the config and make customElements.define(undefined, …) throw at\n // registration time. Mirrors the typeof guards on autoTrigger / triggerAttribute.\n for (const [key, value] of Object.entries(partialConfig.tagNames)) {\n if (typeof value === \"string\") {\n (_config.tagNames as Record<string, string>)[key] = value;\n }\n }\n }\n frozenConfig = null;\n}\n","// Single source of truth for the custom event names dispatched by StorageCore /\n// Storage. These names appear in two places that must stay in lock-step:\n// 1. the `wcBindable.properties[].event` declarations (consumed by bind())\n// 2. the `dispatchEvent(new CustomEvent(...))` calls that emit them\n// Hard-coding the same string literal in both places risks a silent typo that\n// makes bind() listen for an event no one ever fires. Referencing these\n// constants from both sites keeps them in sync.\nexport const STORAGE_EVENTS = {\n valueChanged: \"wcs-storage:value-changed\",\n loadingChanged: \"wcs-storage:loading-changed\",\n error: \"wcs-storage:error\",\n errorInfoChanged: \"wcs-storage:error-info-changed\",\n triggerChanged: \"wcs-storage:trigger-changed\",\n} as const;\n","/**\n * storageCapabilities.ts\n *\n * Storage node 固有の error code(taxonomy)と derivation。汎用の error info 型は\n * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から\n * import する。storage の load / save / remove は同期で互いに競合しないため lane は\n * 持たず、error taxonomy(errorInfo)のみを採用する。\n */\n\nimport type { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport type { WcsStorageError } from \"../types.js\";\n\n/** 安定した storage error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_STORAGE_ERROR_CODE = {\n /** `key` 未設定 / 不正な `type` などの入力不備。retry では回復しない。 */\n InvalidArgument: \"invalid-argument\",\n /** `QuotaExceededError` — 容量超過。空きを作れば回復しうる(環境要因)。 */\n QuotaExceeded: \"quota-exceeded\",\n /** `SecurityError` — storage アクセス拒否(cookie 無効 / third-party context 等)。retry では回復しない。 */\n NotAllowed: \"not-allowed\",\n /** その他の caught 例外。 */\n StorageError: \"storage-error\",\n} as const;\n\n/**\n * storage の失敗を serializable な error taxonomy に写す。\n *\n * `name` は caught 例外の `Error.name`(load / save / remove の catch から渡る)。\n * 未指定(undefined)は inline 構築の validation error(不正 `type` / `key` 未設定)を意味し、\n * これは開始前の入力不備なので phase=\"start\" / `invalid-argument` / recoverable=false。\n * caught 例外は実行中の失敗なので phase=\"execute\"。`QuotaExceededError` は環境要因で\n * 空きを作れば回復しうる(recoverable=true)、`SecurityError` は retry で回復しない。\n */\nexport function deriveStorageErrorInfo(error: WcsStorageError, name?: string): WcsIoErrorInfo {\n if (name === undefined) {\n return {\n code: WCS_STORAGE_ERROR_CODE.InvalidArgument,\n phase: \"start\",\n recoverable: false,\n message: error.message,\n };\n }\n if (name === \"QuotaExceededError\") {\n return { code: WCS_STORAGE_ERROR_CODE.QuotaExceeded, phase: \"execute\", recoverable: true, message: error.message };\n }\n if (name === \"SecurityError\") {\n return { code: WCS_STORAGE_ERROR_CODE.NotAllowed, phase: \"execute\", recoverable: false, message: error.message };\n }\n return { code: WCS_STORAGE_ERROR_CODE.StorageError, phase: \"execute\", recoverable: true, message: error.message };\n}\n","import { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType, WcsStorageError } from \"../types.js\";\nimport { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport { deriveStorageErrorInfo } from \"./storageCapabilities.js\";\n\nexport class StorageCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: STORAGE_EVENTS.valueChanged, getter: (e: Event) => (e as CustomEvent).detail },\n { name: \"loading\", event: STORAGE_EVENTS.loadingChanged },\n { name: \"error\", event: STORAGE_EVENTS.error },\n // Serializable failure taxonomy (stable code / phase / recoverable), or null.\n // Additive bindable output derived from `error` (invalid-argument / quota-exceeded\n // / not-allowed / storage-error); the existing `error` property/event are unchanged.\n // Fires wcs-storage:error-info-changed. No lane — load/save/remove don't compete.\n { name: \"errorInfo\", event: STORAGE_EVENTS.errorInfoChanged },\n ],\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n ],\n // load / save / remove are synchronous, so none carry the `async` hint.\n commands: [\n { name: \"load\" },\n { name: \"save\" },\n { name: \"remove\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _errorInfo: WcsIoErrorInfo | null = null;\n private _key: string = \"\";\n private _type: StorageType = \"local\";\n private _storageListener: ((e: StorageEvent) => void) | null = null;\n // Generation guard: bumped on dispose(). The cross-tab `storage` listener\n // captures the generation active when startSync() ran; a callback that fires\n // after dispose() (or a teardown→re-setup) has a stale gen and MUST NOT write\n // state to a torn-down element. A boolean flag is insufficient (dispose→observe\n // would let a stale listener slip through).\n private _gen = 0;\n // SSR: storage access is synchronous, so there is no asynchronous probe to\n // await — readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). Storage sync is command-driven (the Shell calls startSync()\n // from connectedCallback), so observe() is an idempotent no-op that resolves\n // once ready; dispose() tears down the cross-tab listener and invalidates any\n // in-flight listener callback.\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stopSync();\n }\n\n get value(): any {\n return this._value;\n }\n\n // Set the current value *without* persisting it. Persistence happens only via\n // save() / remove() / a cross-tab storage event. This setter exists so the\n // Shell (manual mode) can stage a value handed in via a `value` binding and\n // then commit it later with save()/trigger. It mirrors the value to observers\n // through the same `value-changed` event load()/save() use (CSBC: a Core value\n // change is observable), but it deliberately does not touch storage.\n //\n // Same-value writes are skipped to break a potential feedback loop:\n // value-changed → state binding → value setter → value-changed → …\n set value(v: any) {\n if (Object.is(v, this._value)) return;\n this._setValue(v);\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n /**\n * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /\n * `recoverable`), or null. Additive wc-bindable property (event\n * `wcs-storage:error-info-changed`), derived from `error`; the existing `error`\n * property/event are unchanged.\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n get key(): string {\n return this._key;\n }\n\n set key(value: string) {\n // Defensive normalization for direct Core use (the Shell already passes a\n // string via `getAttribute(\"key\") || \"\"`). Coercing to String keeps a\n // non-string assignment from poisoning the cross-tab `e.key !== _key`\n // comparison; empty keys are still rejected at operation time.\n this._key = String(value);\n }\n\n get type(): StorageType {\n return this._type;\n }\n\n set type(value: StorageType) {\n if (value !== \"local\" && value !== \"session\") {\n // never-throw: an invalid type is routed to the error property and the\n // current type is kept (the safe default), rather than throwing out of the\n // setter / setAttribute / connectedCallback.\n this._setError({ operation: \"type\", message: `Invalid storage type: \"${value}\". Must be \"local\" or \"session\".` });\n return;\n }\n this._type = value;\n }\n\n private _getStorage(): globalThis.Storage {\n return this._type === \"session\" ? sessionStorage : localStorage;\n }\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.loadingChanged, {\n detail: loading,\n bubbles: true,\n }));\n }\n\n // `name` is the caught exception's `Error.name` (passed only from the\n // load/save/remove catch blocks); it stays out of the public `error` shape and\n // is used solely to classify errorInfo (quota vs security vs generic). Inline\n // validation errors (invalid type / missing key) pass no name → invalid-argument.\n private _setError(error: any, name?: string): void {\n // Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,\n // so suppressing redundant null→null dispatches (every load/save/remove start\n // clears a usually-already-null error) avoids a spurious error event per\n // successful operation. Reference identity is sufficient: each failure builds\n // a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n // Keep the additive `errorInfo` taxonomy in sync with `error`: derive from the\n // error (or null on clear). Fires before the `error` event so an observer\n // binding both sees the classification first, mirroring the io-node family.\n this._commitErrorInfo(error === null ? null : deriveStorageErrorInfo(error, name));\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.error, {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Called only from _setError (which already same-value-guards on the error\n // reference), so errorInfo transitions exactly when error does — no separate\n // guard needed here.\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.errorInfoChanged, {\n detail: info,\n bubbles: true,\n }));\n }\n\n // Wrap a caught storage exception into the documented WcsStorageError shape,\n // tagging it with the failing operation so consumers know which call failed.\n private _toStorageError(operation: WcsStorageError[\"operation\"], e: unknown): WcsStorageError {\n return {\n operation,\n message: e instanceof Error ? e.message : String(e),\n };\n }\n\n // The caught exception's `Error.name` for errorInfo classification (quota vs\n // security vs generic), or \"\" for a non-Error throw (→ storage-error). Returning\n // a string (never undefined) keeps a caught exception in the execute phase; only\n // inline validation errors, which pass no name to _setError, become start-phase\n // invalid-argument. Single chokepoint so the ternary is covered in one place.\n private _errName(e: unknown): string {\n return e instanceof Error ? e.name : \"\";\n }\n\n private _setValue(value: any): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.valueChanged, {\n detail: value,\n bubbles: true,\n }));\n }\n\n load(): any {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property and a\n // sanitized null is returned, rather than throwing.\n this._setError({ operation: \"load\", message: \"key is required.\" });\n return null;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n const raw = storage.getItem(this._key);\n\n if (raw === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(raw));\n } catch {\n this._setValue(raw);\n }\n }\n\n this._setLoading(false);\n return this._value;\n } catch (e: any) {\n this._setError(this._toStorageError(\"load\", e), this._errName(e));\n this._setLoading(false);\n return null;\n }\n }\n\n save(value: any): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (save returns void).\n this._setError({ operation: \"save\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n\n if (value === null || value === undefined) {\n storage.removeItem(this._key);\n // Normalize the removed value to null (matching remove() and load() of a\n // missing key) so saving `undefined` does not leave the getter returning\n // `undefined`. README's serialization table documents null/undefined as\n // \"null\" on read-back.\n this._setValue(null);\n } else if (typeof value === \"string\") {\n storage.setItem(this._key, value);\n this._setValue(value);\n } else {\n storage.setItem(this._key, JSON.stringify(value));\n this._setValue(value);\n }\n\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"save\", e), this._errName(e));\n this._setLoading(false);\n }\n }\n\n remove(): void {\n if (!this._key) {\n // never-throw: a missing key is routed to the error property instead of\n // throwing. No return value to sanitize (remove returns void).\n this._setError({ operation: \"remove\", message: \"key is required.\" });\n return;\n }\n\n this._setLoading(true);\n this._setError(null);\n\n try {\n const storage = this._getStorage();\n storage.removeItem(this._key);\n this._setValue(null);\n this._setLoading(false);\n } catch (e: any) {\n this._setError(this._toStorageError(\"remove\", e), this._errName(e));\n this._setLoading(false);\n }\n }\n\n startSync(): void {\n if (this._storageListener) return;\n\n // Capture the generation active when sync starts. A `storage` event that\n // fires after dispose() (which bumps _gen and removes the listener) carries a\n // stale gen and must not write state to a torn-down element. stopSync()\n // already detaches the listener, but the gen guard also covers a queued event\n // delivered between dispose()'s bump and the actual removeEventListener.\n const gen = ++this._gen;\n\n this._storageListener = (e: StorageEvent) => {\n if (gen !== this._gen) return;\n if (e.key !== this._key) return;\n if (this._type === \"session\") return;\n\n // A fresh value arriving from another tab supersedes any stale error from\n // a prior failed load/save/remove. Clearing it here keeps the sync path\n // consistent with load()/save()/remove(), which all reset error to null at\n // the start of a successful operation — otherwise an \"error present + fresh\n // value\" inconsistency could persist after a cross-tab update.\n this._setError(null);\n\n if (e.newValue === null) {\n this._setValue(null);\n } else {\n try {\n this._setValue(JSON.parse(e.newValue));\n } catch {\n this._setValue(e.newValue);\n }\n }\n };\n\n globalThis.addEventListener(\"storage\", this._storageListener);\n }\n\n stopSync(): void {\n if (!this._storageListener) return;\n globalThis.removeEventListener(\"storage\", this._storageListener);\n this._storageListener = null;\n }\n}\n","import { config } from \"./config.js\";\nimport type { Storage } from \"./components/Storage.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const storageId = triggerElement.getAttribute(config.triggerAttribute);\n if (!storageId) return;\n\n // Resolve the registered constructor at call time instead of importing Storage\n // as a value. The value import created a components/Storage.ts ⇄ autoTrigger.ts\n // cycle (Storage.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-storage> class matches — without the import cycle.\n const StorageCtor = customElements.get(config.tagNames.storage);\n const storageElement = document.getElementById(storageId);\n if (!StorageCtor || !(storageElement instanceof StorageCtor)) return;\n\n event.preventDefault();\n (storageElement as Storage).save();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { STORAGE_EVENTS } from \"../events.js\";\nimport { IWcBindable, StorageType } from \"../types.js\";\nimport { StorageCore } from \"../core/StorageCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class Storage extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...StorageCore.wcBindable,\n properties: [\n ...StorageCore.wcBindable.properties,\n { name: \"trigger\", event: STORAGE_EVENTS.triggerChanged },\n ],\n // Shell-level input surface. The Core declares only the portable `key` / `type`;\n // the Shell adds the DOM-driven settable surface. No `attribute` hints are given:\n // the `key` / `type` / `manual` setters already reflect to their attributes, so a\n // binding system that mirrors inputs[].attribute would set the attribute twice\n // (`value` / `trigger` are not attribute-backed). `commands` (load / save / remove)\n // are inherited unchanged from the Core via the spread above.\n inputs: [\n { name: \"key\" },\n { name: \"type\" },\n { name: \"value\" },\n { name: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n static get observedAttributes(): string[] { return [\"key\", \"type\"]; }\n\n private _core: StorageCore;\n private _trigger: boolean = false;\n // Storage load()/save() are synchronous, so connection work never defers.\n // This stays an already-resolved Promise for the whole lifecycle; it exists\n // only to satisfy the `hasConnectedCallbackPromise` protocol (consumers may\n // `await el.connectedCallbackPromise`). connectedCallback intentionally does\n // not reassign it — there is nothing async to wait for, unlike <wcs-fetch>.\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new StorageCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n [STORAGE_EVENTS.loadingChanged]: (d) => ({ loading: d === true }),\n [STORAGE_EVENTS.error]: (d) => ({ error: d != null }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // Push the Shell's current attribute-derived key / type down into the Core.\n // Every operation (load / save / remove / value setter) and every lifecycle\n // hook that may run a Core operation or cross-tab sync must do this first, so\n // the Core never acts on a stale key / type. Centralizing it here avoids the\n // previous pattern of repeating `_core.key = …; _core.type = …;` at each call\n // site, which risked a future call site forgetting one of the two.\n private _syncCore(): void {\n this._core.key = this.key;\n this._core.type = this.type;\n }\n\n get key(): string {\n return this.getAttribute(\"key\") || \"\";\n }\n\n set key(value: string) {\n this.setAttribute(\"key\", value);\n }\n\n get type(): StorageType {\n // Normalize at the Shell boundary: any attribute value other than the\n // exact \"session\" falls back to \"local\". This keeps an invalid attribute\n // (e.g. type=\"foo\") from reaching the Core's validating setter and throwing\n // out of setAttribute / connectedCallback.\n return this.getAttribute(\"type\") === \"session\" ? \"session\" : \"local\";\n }\n\n set type(value: StorageType) {\n this.setAttribute(\"type\", value);\n }\n\n get value(): any {\n return this._core.value;\n }\n\n set value(v: any) {\n // Non-manual mode: assigning `value` auto-saves the *assigned* argument `v`\n // (write-through). Note this differs from save()/trigger, which persist the\n // *current* `_core.value` (which load() or a cross-tab `storage` event may\n // have updated). See README \"Design Notes\" for the rationale.\n //\n // Manual mode: assigning `value` does NOT persist — it only stages the value\n // into the Core (no storage write). This keeps the getter/setter consistent\n // (`el.value = x; el.value === x`) and lets a later save()/trigger commit the\n // staged value, so a `value: …` + `trigger: …` binding pair works as\n // documented. The actual write still happens only via save()/trigger.\n if (!this.manual) {\n this._syncCore();\n this._core.save(v);\n } else {\n this._core.value = v;\n }\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n const v = !!value;\n if (v) {\n this._trigger = true;\n // save() is never-throw (a failure — e.g. key unset — is routed to the\n // `error` property, not thrown), but the try/finally is kept defensively\n // to guarantee the trigger resets to false and the completion event fires\n // even in the unexpected event of a throw, so the trigger never gets stuck\n // in the `true` state.\n try {\n this.save();\n } finally {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(STORAGE_EVENTS.triggerChanged, {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n load(): any {\n this._syncCore();\n return this._core.load();\n }\n\n // The `save` command differs in arity between the two CSBC surfaces:\n // - Core: save(value) — caller supplies the value to persist\n // - Shell: save() — persists the current `_core.value` (no argument)\n // Both are exposed under the same `commands` entry name \"save\". The protocol\n // `commands` list is descriptive metadata only and carries no arity, so this\n // is not a protocol violation; the difference is contractual and documented\n // in the README (\"Design Notes\").\n save(): void {\n this._syncCore();\n this._core.save(this._core.value);\n }\n\n remove(): void {\n this._syncCore();\n this._core.remove();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected) return;\n if (name === \"key\") {\n // Always keep the Core's key in sync with the attribute, regardless of\n // mode or whether the new value is empty. The cross-tab `storage` listener\n // compares `e.key !== _core.key`, so a stale Core key would make sync watch\n // the wrong (old/empty) key after a runtime key change. load() (which also\n // syncs the Core) only runs for non-manual mode with a non-empty key.\n this._syncCore();\n if (newValue && !this.manual) {\n this.load();\n }\n }\n if (name === \"type\") {\n // Route through the normalizing getter so an invalid attribute value\n // (e.g. type=\"foo\") falls back to \"local\" instead of throwing.\n this._syncCore();\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.key) {\n this.load();\n }\n // Always bind the cross-tab watcher to the Shell's current key/type before\n // starting sync. In paths where load()/save() never run (e.g. manual mode,\n // or key set via JS without a load), _core.key/_core.type would otherwise\n // keep a stale/empty value and the storage listener's `e.key !== _key`\n // check would compare against the wrong key. This also covers detach →\n // re-attach: stale Core key from a previous session is overwritten here.\n this._syncCore();\n this._core.startSync();\n }\n\n disconnectedCallback(): void {\n this._core.stopSync();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapStorage(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { Storage } from \"./components/Storage.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.storage)) {\n customElements.define(config.tagNames.storage, Storage);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","storage","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","STORAGE_EVENTS","WCS_STORAGE_ERROR_CODE","InvalidArgument","QuotaExceeded","NotAllowed","StorageError","StorageCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","inputs","commands","_target","_value","_loading","_error","_errorInfo","_key","_type","_storageListener","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","observe","dispose","stopSync","value","v","is","_setValue","loading","error","errorInfo","String","type","_setError","operation","message","_getStorage","sessionStorage","localStorage","_setLoading","dispatchEvent","CustomEvent","bubbles","_commitErrorInfo","undefined","code","phase","recoverable","deriveStorageErrorInfo","info","_toStorageError","Error","_errName","load","raw","getItem","JSON","parse","save","removeItem","setItem","stringify","remove","startSync","gen","newValue","globalThis","addEventListener","removeEventListener","registered","handleClick","Element","triggerElement","closest","storageId","getAttribute","StorageCtor","customElements","get","storageElement","document","getElementById","preventDefault","Storage","HTMLElement","wcBindable","observedAttributes","_core","_trigger","_connectedCallbackPromise","_internals","_initInternals","_wireStates","STORAGE_EVENTS_loadingChanged","d","STORAGE_EVENTS_error","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","debug","hasAttribute","on","toggleAttribute","_syncCore","setAttribute","manual","connectedCallbackPromise","removeAttribute","trigger","attributeChangedCallback","_oldValue","isConnected","connectedCallback","style","display","disconnectedCallback","bootstrapStorage","userConfig","partialConfig","setConfig","define"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/storage",
3
- "version": "1.20.0",
3
+ "version": "1.21.1",
4
4
  "description": "Declarative persistent storage component for Web Components. Framework-agnostic localStorage/sessionStorage via wc-bindable-protocol.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",