@wcstack/storage 1.15.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +54 -3
- package/README.md +56 -3
- package/dist/index.d.ts +8 -2
- package/dist/index.esm.js +67 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -177,6 +177,57 @@ HTML、JS、または `@wcstack/state` バインディングからストレー
|
|
|
177
177
|
| `trigger` | `boolean` | 単方向の保存トリガー |
|
|
178
178
|
| `manual` | `boolean` | 自動読み込み・自動保存を無効化 |
|
|
179
179
|
|
|
180
|
+
## `:state()` による CSS スタイリング
|
|
181
|
+
|
|
182
|
+
`<wcs-storage>` は 2 つの boolean 出力ステートを
|
|
183
|
+
[`ElementInternals` の `CustomStateSet`](https://developer.mozilla.org/ja/docs/Web/API/CustomStateSet)
|
|
184
|
+
に反映します。そのため `data-wcs` バインディングやクラスの手動トグルなしに、CSS の
|
|
185
|
+
`:state()` 疑似クラスで直接スタイリングできます。
|
|
186
|
+
|
|
187
|
+
| ステート | on になる条件 |
|
|
188
|
+
|----------|----------------|
|
|
189
|
+
| `loading` | `wcs-storage:loading-changed` が `true` で発火(`false` でクリア) |
|
|
190
|
+
| `error` | `wcs-storage:error` が非 `null` の detail で発火(`null` でクリア) |
|
|
191
|
+
|
|
192
|
+
```css
|
|
193
|
+
wcs-storage:state(loading) ~ .spinner { display: block; }
|
|
194
|
+
wcs-storage:state(loading) ~ .spinner { display: none; } /* デフォルト */
|
|
195
|
+
|
|
196
|
+
form:has(wcs-storage:state(error)) .banner { display: block; }
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
属性やクラスと異なり `:state()` は要素の外部から書き込めないため、この出力ステートが
|
|
200
|
+
入力と混同される心配がありません。
|
|
201
|
+
|
|
202
|
+
**対応ブラウザ**(新構文 `:state(x)`): Chrome/Edge 125+、Safari 17.4+、Firefox 126+。
|
|
203
|
+
非対応の環境ではステートが一切 set されないだけです — `:state()` セレクタがマッチしなく
|
|
204
|
+
なりますが、`<wcs-storage>` 自体は通常どおり動作し続けます(graceful degradation・never-throw)。
|
|
205
|
+
|
|
206
|
+
**SSR:** `:state()` は HTML にシリアライズできないため、サーバーレンダリングされた
|
|
207
|
+
マークアップの初期ペイントにはこれらのステートは乗りません(`@wcstack/server` は無改変)。
|
|
208
|
+
ハイドレーション前の見た目を制御したい場合は、代わりに `wcs-storage:not(:defined)` と組み合わせてください。
|
|
209
|
+
|
|
210
|
+
### デバッグ
|
|
211
|
+
|
|
212
|
+
カスタムステートは DevTools の Elements パネルには表示されず、`attachInternals()`
|
|
213
|
+
は同一要素に 2 回呼べないため、コンソールから直接覗く手段がありません。そのための
|
|
214
|
+
デバッグ専用の補助を 2 つ用意しています:
|
|
215
|
+
|
|
216
|
+
- `el.debugStates` — 現在 on になっているステート名の**スナップショット**配列
|
|
217
|
+
(例: `["loading"]`)。`wc-bindable` の一部ではなく(バインド対象ではない)、
|
|
218
|
+
形状も契約として保証されません — デバッグ用途にのみ使ってください。
|
|
219
|
+
- `debug-states` 属性(opt-in・既定 OFF)は、ステート変化を要素の
|
|
220
|
+
`data-wcs-state-loading` / `data-wcs-state-error` 属性にミラーします。
|
|
221
|
+
Elements パネルを開いておけば、トグルのたびにハイライトされます:
|
|
222
|
+
|
|
223
|
+
```html
|
|
224
|
+
<wcs-storage key="prefs" debug-states></wcs-storage>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**CSS は `data-wcs-state-*` ではなく `:state()` に書いてください。** ミラーされた
|
|
228
|
+
属性は、DevTools を開いた状態でステート変化を可視化するためだけのものであり、
|
|
229
|
+
スタイリング用の正式なフックではありません。
|
|
230
|
+
|
|
180
231
|
## アーキテクチャ
|
|
181
232
|
|
|
182
233
|
`@wcstack/storage` は CSBC アーキテクチャに従います。
|
|
@@ -340,7 +391,7 @@ type StorageType = "local" | "session";
|
|
|
340
391
|
|
|
341
392
|
// ストレージ操作エラー
|
|
342
393
|
interface WcsStorageError {
|
|
343
|
-
operation: "load" | "save" | "remove";
|
|
394
|
+
operation: "load" | "save" | "remove" | "type";
|
|
344
395
|
message: string;
|
|
345
396
|
}
|
|
346
397
|
|
|
@@ -499,7 +550,7 @@ bootstrapStorage({
|
|
|
499
550
|
|
|
500
551
|
- `value`、`loading`、`error` は **出力ステート**
|
|
501
552
|
- `key`、`type`、`trigger` は **入力 / コマンドサーフェス**
|
|
502
|
-
- `trigger` は意図的に単方向: `true`
|
|
553
|
+
- `trigger` は意図的に単方向: `true` を書き込むと保存、リセットで完了を通知。`save()` は never-throw(`key` 未設定などの失敗は throw せず `error` プロパティに流す)で、`trigger` は成否にかかわらず `false` へ復帰し完了イベントも発火するため、`true` で固着しない。
|
|
503
554
|
- `value` セッターは `manual` でない場合に自動保存を行う
|
|
504
555
|
- **`value` セッター vs `save()` / `trigger`**: `value` への代入(非 manual)は *代入された引数* を保存する(ライトスルー)。一方 `save()` と `trigger` は *現在の `value`*(直前の `load()` や他タブからの `storage` イベントで更新されうる)を保存する。このため `trigger`/`save()` は他タブ由来の値を書き戻す可能性がある。
|
|
505
556
|
- **`manual` モードでの `value`**: `manual` では `value` セッターは値を**ステージング**する(ストレージへは書き込まない)。`el.value = x` で読み取り値は更新される(`el.value === x`)が、ストレージには触れず、実際の書き込みは `save()` / `trigger` でのみ行われる。これにより `value: …` + `trigger: …` のバインディング対が機能する — バインドされた値がステージングされ、トリガー時にコミットされる。
|
|
@@ -507,7 +558,7 @@ bootstrapStorage({
|
|
|
507
558
|
- **`save` コマンドのアリティ**: ヘッドレスな Core は `save(value)`、Shell は `save()`(現在値を保存)。どちらも同じ `commands` 名 `save` に現れるが、プロトコルの `commands` メタデータは記述的でアリティを持たないため、これは契約上の差異でありプロトコル違反ではない。
|
|
508
559
|
- **不正な `type`**: `"session"` 以外の `type` 属性はすべて `"local"` として扱う。不正値(例: `type="foo"`)は例外を投げず暗黙に `local` へフォールバックする。
|
|
509
560
|
- **実行時の `type` 変更**: 接続後に `type` 属性を変更すると以降の操作で使うストレージ領域は切り替わるが、新しい領域から**自動で再ロードはしない**(非 manual で自動再ロードするのは `key` 変更時のみ)。新領域の値が必要なら明示的に `load()` を呼ぶこと。
|
|
510
|
-
- **`error` の形状**: ストレージ失敗時、`error`
|
|
561
|
+
- **`error` の形状**: ストレージ失敗時、`error` には失敗した呼び出し(`load` / `save` / `remove`、あるいはヘッドレスで不正な `type` を代入した場合の `type`)を示す `WcsStorageError`(`{ operation, message }`)が設定される。操作は **never-throw**: key 未設定での操作呼び出しは throw せず `error` に `{ operation, message: "key is required." }` として流れる(`wcs-storage:error` も発火)。したがって実際には `error` は常に `WcsStorageError` か `null` のいずれかになる。より広い `WcsStorageError | Error | null` 型は前方互換性と兄弟パッケージとの一貫性のために維持している。
|
|
511
562
|
- JSON 自動シリアライズにより、オブジェクト / 配列 / プリミティブを透過的に扱える
|
|
512
563
|
- `null` / `undefined` の保存はストレージからのキー削除として扱われる
|
|
513
564
|
- `storage` イベントによるクロスタブ同期は localStorage でのみ動作。Shell は接続時(および再 attach 時)に監視を現在の `key` / `type` へ結びつけるため、自動ロードが走らない `manual` モードでもクロスタブ同期が機能する。接続後に `key` 属性を変更した場合も常に Core の key を再同期するため、`manual` モードや key を空にした場合でもクロスタブ同期は新しい key を追従する。クロスタブ更新が成功すると残存していた `error` もクリアされる(`load()` / `save()` / `remove()` が成功時に冒頭で error を null にするのと同様)。これにより、過去の失敗で残った error と新鮮な value が共存しない。
|
package/README.md
CHANGED
|
@@ -176,6 +176,59 @@ Controls storage operations from HTML, JS, or `@wcstack/state` bindings:
|
|
|
176
176
|
| `trigger` | `boolean` | One-way save trigger |
|
|
177
177
|
| `manual` | `boolean` | Disables auto-load and auto-save |
|
|
178
178
|
|
|
179
|
+
## CSS styling with `:state()`
|
|
180
|
+
|
|
181
|
+
`<wcs-storage>` reflects two boolean output states onto its
|
|
182
|
+
[`ElementInternals` `CustomStateSet`](https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet),
|
|
183
|
+
so you can style it directly from CSS with the `:state()` pseudo-class — no
|
|
184
|
+
`data-wcs` binding or extra class toggling required.
|
|
185
|
+
|
|
186
|
+
| State | On when |
|
|
187
|
+
|-------|---------|
|
|
188
|
+
| `loading` | `wcs-storage:loading-changed` fires with `true` (cleared on `false`) |
|
|
189
|
+
| `error` | `wcs-storage:error` fires with a non-`null` detail (cleared on `null`) |
|
|
190
|
+
|
|
191
|
+
```css
|
|
192
|
+
wcs-storage:state(loading) ~ .spinner { display: block; }
|
|
193
|
+
wcs-storage:state(loading) ~ .spinner { display: none; } /* default */
|
|
194
|
+
|
|
195
|
+
form:has(wcs-storage:state(error)) .banner { display: block; }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Unlike attributes or classes, `:state()` cannot be written from outside the
|
|
199
|
+
element, so there is no risk of confusing this output state with an input.
|
|
200
|
+
|
|
201
|
+
**Browser support** (`:state(x)` syntax): Chrome/Edge 125+, Safari 17.4+,
|
|
202
|
+
Firefox 126+. In older browsers the states are simply never set — `:state()`
|
|
203
|
+
selectors never match, but `<wcs-storage>` itself keeps working normally
|
|
204
|
+
(graceful degradation, never-throw).
|
|
205
|
+
|
|
206
|
+
**SSR**: `:state()` cannot be serialized into HTML, so server-rendered markup
|
|
207
|
+
never carries these states on first paint (`@wcstack/server` is unaffected).
|
|
208
|
+
If you need to style the pre-hydration gap, pair your rule with
|
|
209
|
+
`wcs-storage:not(:defined)` instead.
|
|
210
|
+
|
|
211
|
+
### Debugging
|
|
212
|
+
|
|
213
|
+
Custom states are invisible in DevTools' Elements panel and `attachInternals()`
|
|
214
|
+
cannot be called twice, so there is no console way to inspect them directly.
|
|
215
|
+
Two debug-only aids are provided for that:
|
|
216
|
+
|
|
217
|
+
- `el.debugStates` — a **snapshot** array of the currently-on state names
|
|
218
|
+
(e.g. `["loading"]`). It is not part of `wc-bindable` (not a bind target)
|
|
219
|
+
and its shape is not a guaranteed contract — use it for debugging only.
|
|
220
|
+
- The `debug-states` attribute (opt-in, default off) mirrors state changes
|
|
221
|
+
onto `data-wcs-state-loading` / `data-wcs-state-error` attributes on the
|
|
222
|
+
element, so the Elements panel highlights them as they toggle:
|
|
223
|
+
|
|
224
|
+
```html
|
|
225
|
+
<wcs-storage key="prefs" debug-states></wcs-storage>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Write your CSS against `:state()`, not `data-wcs-state-*`.** The mirrored
|
|
229
|
+
attributes exist purely to make state changes visible while debugging with
|
|
230
|
+
DevTools open; they are not a supported styling hook.
|
|
231
|
+
|
|
179
232
|
## Architecture
|
|
180
233
|
|
|
181
234
|
`@wcstack/storage` follows the CSBC architecture.
|
|
@@ -337,7 +390,7 @@ type StorageType = "local" | "session";
|
|
|
337
390
|
|
|
338
391
|
// Storage operation error
|
|
339
392
|
interface WcsStorageError {
|
|
340
|
-
operation: "load" | "save" | "remove";
|
|
393
|
+
operation: "load" | "save" | "remove" | "type";
|
|
341
394
|
message: string;
|
|
342
395
|
}
|
|
343
396
|
|
|
@@ -496,7 +549,7 @@ bootstrapStorage({
|
|
|
496
549
|
|
|
497
550
|
- `value`, `loading`, `error` are **output state**
|
|
498
551
|
- `key`, `type`, `trigger` are **input / command surface**
|
|
499
|
-
- `trigger` is intentionally one-way: writing `true` saves, reset signals completion.
|
|
552
|
+
- `trigger` is intentionally one-way: writing `true` saves, reset signals completion. `save()` is never-throw (a failure such as an unset `key` is routed to the `error` property, not thrown); `trigger` is reset to `false` and the completion event fires regardless, so it never gets stuck in the `true` state.
|
|
500
553
|
- The `value` setter auto-saves when not in `manual` mode
|
|
501
554
|
- **`value` setter vs `save()` / `trigger`**: assigning `value` (non-manual) persists the *assigned* argument (write-through). `save()` and `trigger`, by contrast, persist the *current* `value` — which a prior `load()` or a cross-tab `storage` event may have updated. This means `trigger`/`save()` can write back a value that arrived from another tab.
|
|
502
555
|
- **`value` in `manual` mode**: the `value` setter **stages** the value (no storage write) instead of persisting it. `el.value = x` updates the readable value (`el.value === x`) but does **not** touch storage; the actual write happens only via `save()` / `trigger`. This is what makes the `value: …` + `trigger: …` binding pair work — the bound value is staged, then committed on trigger.
|
|
@@ -504,7 +557,7 @@ bootstrapStorage({
|
|
|
504
557
|
- **`save` command arity**: the headless Core takes `save(value)`, while the Shell exposes `save()` (persists the current value). Both appear under the same `commands` name `save`; the protocol's `commands` metadata is descriptive and arity-less, so this is contractual, not a protocol violation.
|
|
505
558
|
- **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.
|
|
506
559
|
- **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.
|
|
507
|
-
- **`error` shape**: on a storage failure, `error` is set to a `WcsStorageError` (`{ operation, message }`) identifying which
|
|
560
|
+
- **`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.
|
|
508
561
|
- JSON auto-serialization handles objects, arrays, and primitives transparently
|
|
509
562
|
- Saving `null` / `undefined` removes the key from storage
|
|
510
563
|
- 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
|
@@ -38,10 +38,12 @@ interface IWritableConfig {
|
|
|
38
38
|
|
|
39
39
|
type StorageType = "local" | "session";
|
|
40
40
|
/**
|
|
41
|
-
* Error returned when a storage operation fails.
|
|
41
|
+
* Error returned when a storage operation fails. `operation` names the failing
|
|
42
|
+
* call: `load` / `save` / `remove`, or `type` for an invalid `type` assignment
|
|
43
|
+
* (a value other than `"local"` / `"session"`).
|
|
42
44
|
*/
|
|
43
45
|
interface WcsStorageError {
|
|
44
|
-
operation: "load" | "save" | "remove";
|
|
46
|
+
operation: "load" | "save" | "remove" | "type";
|
|
45
47
|
message: string;
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
@@ -107,7 +109,11 @@ declare class Storage extends HTMLElement {
|
|
|
107
109
|
private _core;
|
|
108
110
|
private _trigger;
|
|
109
111
|
private _connectedCallbackPromise;
|
|
112
|
+
private _internals;
|
|
110
113
|
constructor();
|
|
114
|
+
get debugStates(): string[];
|
|
115
|
+
private _initInternals;
|
|
116
|
+
private _wireStates;
|
|
111
117
|
private _syncCore;
|
|
112
118
|
get key(): string;
|
|
113
119
|
set key(value: string);
|
package/dist/index.esm.js
CHANGED
|
@@ -161,7 +161,7 @@ class StorageCore extends EventTarget {
|
|
|
161
161
|
// never-throw: an invalid type is routed to the error property and the
|
|
162
162
|
// current type is kept (the safe default), rather than throwing out of the
|
|
163
163
|
// setter / setAttribute / connectedCallback.
|
|
164
|
-
this._setError({ message: `Invalid storage type: "${value}". Must be "local" or "session".` });
|
|
164
|
+
this._setError({ operation: "type", message: `Invalid storage type: "${value}". Must be "local" or "session".` });
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
167
|
this._type = value;
|
|
@@ -177,6 +177,13 @@ class StorageCore extends EventTarget {
|
|
|
177
177
|
}));
|
|
178
178
|
}
|
|
179
179
|
_setError(error) {
|
|
180
|
+
// Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,
|
|
181
|
+
// so suppressing redundant null→null dispatches (every load/save/remove start
|
|
182
|
+
// clears a usually-already-null error) avoids a spurious error event per
|
|
183
|
+
// successful operation. Reference identity is sufficient: each failure builds
|
|
184
|
+
// a fresh object, and the clear path always passes null.
|
|
185
|
+
if (this._error === error)
|
|
186
|
+
return;
|
|
180
187
|
this._error = error;
|
|
181
188
|
this._target.dispatchEvent(new CustomEvent(STORAGE_EVENTS.error, {
|
|
182
189
|
detail: error,
|
|
@@ -389,9 +396,63 @@ class Storage extends HTMLElement {
|
|
|
389
396
|
// `await el.connectedCallbackPromise`). connectedCallback intentionally does
|
|
390
397
|
// not reassign it — there is nothing async to wait for, unlike <wcs-fetch>.
|
|
391
398
|
_connectedCallbackPromise = Promise.resolve();
|
|
399
|
+
_internals = null;
|
|
392
400
|
constructor() {
|
|
393
401
|
super();
|
|
394
402
|
this._core = new StorageCore(this);
|
|
403
|
+
this._internals = this._initInternals();
|
|
404
|
+
this._wireStates({
|
|
405
|
+
[STORAGE_EVENTS.loadingChanged]: (d) => ({ loading: d === true }),
|
|
406
|
+
[STORAGE_EVENTS.error]: (d) => ({ error: d != null }),
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
// CSS state reflection (:state()) — debug-only snapshot getter. NOT part of
|
|
410
|
+
// wc-bindable (not a bind target); see README "CSS styling with :state()".
|
|
411
|
+
// MUST NOT return the live CustomStateSet (that would let callers write
|
|
412
|
+
// states from outside, defeating the point of :state() being read-only).
|
|
413
|
+
get debugStates() {
|
|
414
|
+
return this._internals ? [...this._internals.states] : [];
|
|
415
|
+
}
|
|
416
|
+
_initInternals() {
|
|
417
|
+
// never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent
|
|
418
|
+
// in happy-dom / older environments, and pre-125 Chromium rejects
|
|
419
|
+
// non-dashed state names from states.add() (probed and discarded here).
|
|
420
|
+
// Either case silently disables reflection — the component still works,
|
|
421
|
+
// it just doesn't expose :state() selectors.
|
|
422
|
+
try {
|
|
423
|
+
if (typeof this.attachInternals !== "function")
|
|
424
|
+
return null;
|
|
425
|
+
const internals = this.attachInternals();
|
|
426
|
+
internals.states.add("wcs-probe");
|
|
427
|
+
internals.states.delete("wcs-probe");
|
|
428
|
+
return internals;
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
_wireStates(map) {
|
|
435
|
+
if (this._internals === null)
|
|
436
|
+
return;
|
|
437
|
+
const states = this._internals.states;
|
|
438
|
+
for (const [event, toStates] of Object.entries(map)) {
|
|
439
|
+
this.addEventListener(event, (e) => {
|
|
440
|
+
const debug = this.hasAttribute("debug-states");
|
|
441
|
+
for (const [name, on] of Object.entries(toStates(e.detail))) {
|
|
442
|
+
try {
|
|
443
|
+
if (on) {
|
|
444
|
+
states.add(name);
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
states.delete(name);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch { /* never-throw */ }
|
|
451
|
+
if (debug)
|
|
452
|
+
this.toggleAttribute(`data-wcs-state-${name}`, on);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
}
|
|
395
456
|
}
|
|
396
457
|
// Push the Shell's current attribute-derived key / type down into the Core.
|
|
397
458
|
// Every operation (load / save / remove / value setter) and every lifecycle
|
|
@@ -468,9 +529,11 @@ class Storage extends HTMLElement {
|
|
|
468
529
|
const v = !!value;
|
|
469
530
|
if (v) {
|
|
470
531
|
this._trigger = true;
|
|
471
|
-
// save()
|
|
472
|
-
//
|
|
473
|
-
//
|
|
532
|
+
// save() is never-throw (a failure — e.g. key unset — is routed to the
|
|
533
|
+
// `error` property, not thrown), but the try/finally is kept defensively
|
|
534
|
+
// to guarantee the trigger resets to false and the completion event fires
|
|
535
|
+
// even in the unexpected event of a throw, so the trigger never gets stuck
|
|
536
|
+
// in the `true` state.
|
|
474
537
|
try {
|
|
475
538
|
this.save();
|
|
476
539
|
}
|
package/dist/index.esm.js.map
CHANGED
|
@@ -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({ 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 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\n constructor() {\n super();\n this._core = new StorageCore(this);\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() may raise (e.g. key unset). Guarantee the trigger resets to\n // false and the completion event fires even on failure, so the trigger\n // never gets stuck 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
|
+
{"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":"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"}
|
package/dist/index.esm.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const
|
|
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};
|
|
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({ 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 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\n constructor() {\n super();\n this._core = new StorageCore(this);\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() may raise (e.g. key unset). Guarantee the trigger resets to\n // false and the completion event fires even on failure, so the trigger\n // never gets stuck 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","message","_getStorage","sessionStorage","localStorage","_setLoading","dispatchEvent","CustomEvent","bubbles","_toStorageError","operation","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","_syncCore","setAttribute","manual","connectedCallbackPromise","hasAttribute","removeAttribute","trigger","attributeChangedCallback","_oldValue","isConnected","connectedCallback","style","display","disconnectedCallback","bootstrapStorage","userConfig","partialConfig","entries","setConfig","define"],"mappings":"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"}
|
|
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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/storage",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
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",
|