@wcstack/credential 1.16.0 → 1.18.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 +51 -0
- package/README.md +54 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.esm.js +55 -0
- 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
|
@@ -73,6 +73,57 @@ npm install @wcstack/credential
|
|
|
73
73
|
|
|
74
74
|
**無し。**
|
|
75
75
|
|
|
76
|
+
## `:state()` による CSS スタイリング
|
|
77
|
+
|
|
78
|
+
`<wcs-credential>` は 3 つの boolean 出力ステートを
|
|
79
|
+
[`ElementInternals` の `CustomStateSet`](https://developer.mozilla.org/ja/docs/Web/API/CustomStateSet)
|
|
80
|
+
に反映します。そのため `data-wcs` バインディングやクラスの手動トグルなしに、CSS の
|
|
81
|
+
`:state()` 疑似クラスで直接スタイリングできます。
|
|
82
|
+
|
|
83
|
+
| ステート | on になる条件 |
|
|
84
|
+
|----------|----------------|
|
|
85
|
+
| `loading` | `wcs-credential:loading-changed` が `true` で発火(`false` でクリア) |
|
|
86
|
+
| `cancelled` | `wcs-credential:cancelled-changed` が `true` で発火(`false` でクリア) |
|
|
87
|
+
| `error` | `wcs-credential:error` が非 `null` の detail で発火(`null` でクリア) |
|
|
88
|
+
|
|
89
|
+
```css
|
|
90
|
+
wcs-credential:state(loading) ~ .spinner { display: block; }
|
|
91
|
+
wcs-credential:state(cancelled) ~ .hint { display: block; }
|
|
92
|
+
form:has(wcs-credential:state(error)) .banner { display: block; }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
属性やクラスと異なり `:state()` は要素の外部から書き込めないため、この出力ステートが
|
|
96
|
+
入力と混同される心配がありません。
|
|
97
|
+
|
|
98
|
+
**対応ブラウザ**(新構文 `:state(x)`): Chrome/Edge 125+、Safari 17.4+、Firefox 126+。
|
|
99
|
+
非対応の環境ではステートが一切 set されないだけです — `:state()` セレクタがマッチしなく
|
|
100
|
+
なりますが、`<wcs-credential>` 自体は通常どおり動作し続けます(graceful degradation・never-throw)。
|
|
101
|
+
|
|
102
|
+
**SSR:** `:state()` は HTML にシリアライズできないため、サーバーレンダリングされた
|
|
103
|
+
マークアップの初期ペイントにはこれらのステートは乗りません(`@wcstack/server` は無改変)。
|
|
104
|
+
ハイドレーション前の見た目を制御したい場合は、代わりに `wcs-credential:not(:defined)` と組み合わせてください。
|
|
105
|
+
|
|
106
|
+
### デバッグ
|
|
107
|
+
|
|
108
|
+
カスタムステートは DevTools の Elements パネルには表示されず、`attachInternals()`
|
|
109
|
+
は同一要素に 2 回呼べないため、コンソールから直接覗く手段がありません。そのための
|
|
110
|
+
デバッグ専用の補助を 2 つ用意しています:
|
|
111
|
+
|
|
112
|
+
- `el.debugStates` — 現在 on になっているステート名の**スナップショット**配列
|
|
113
|
+
(例: `["loading"]`)。`wc-bindable` の一部ではなく(バインド対象ではない)、
|
|
114
|
+
形状も契約として保証されません — デバッグ用途にのみ使ってください。
|
|
115
|
+
- `debug-states` 属性(opt-in・既定 OFF)は、ステート変化を要素の
|
|
116
|
+
`data-wcs-state-loading` / `data-wcs-state-cancelled` / `data-wcs-state-error`
|
|
117
|
+
属性にミラーします。Elements パネルを開いておけば、トグルのたびにハイライトされます:
|
|
118
|
+
|
|
119
|
+
```html
|
|
120
|
+
<wcs-credential debug-states></wcs-credential>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**CSS は `data-wcs-state-*` ではなく `:state()` に書いてください。** ミラーされた
|
|
124
|
+
属性は、DevTools を開いた状態でステート変化を可視化するためだけのものであり、
|
|
125
|
+
スタイリング用の正式なフックではありません。
|
|
126
|
+
|
|
76
127
|
## 注意・制限
|
|
77
128
|
|
|
78
129
|
- **WebAuthn(`publicKey`)はv1スコープ外です** — 将来の`<wcs-webauthn>`ノードで対応予定。
|
package/README.md
CHANGED
|
@@ -74,6 +74,60 @@ npm install @wcstack/credential
|
|
|
74
74
|
|
|
75
75
|
**None.**
|
|
76
76
|
|
|
77
|
+
## CSS styling with `:state()`
|
|
78
|
+
|
|
79
|
+
`<wcs-credential>` reflects three boolean output states onto its
|
|
80
|
+
[`ElementInternals` `CustomStateSet`](https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet),
|
|
81
|
+
so you can style it directly from CSS with the `:state()` pseudo-class — no
|
|
82
|
+
`data-wcs` binding or extra class toggling required.
|
|
83
|
+
|
|
84
|
+
| State | On when |
|
|
85
|
+
|-------|---------|
|
|
86
|
+
| `loading` | `wcs-credential:loading-changed` fires with `true` (cleared on `false`) |
|
|
87
|
+
| `cancelled` | `wcs-credential:cancelled-changed` fires with `true` (cleared on `false`) |
|
|
88
|
+
| `error` | `wcs-credential:error` fires with a non-`null` detail (cleared on `null`) |
|
|
89
|
+
|
|
90
|
+
```css
|
|
91
|
+
wcs-credential:state(loading) ~ .spinner { display: block; }
|
|
92
|
+
wcs-credential:state(cancelled) ~ .hint { display: block; }
|
|
93
|
+
form:has(wcs-credential:state(error)) .banner { display: block; }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Unlike attributes or classes, `:state()` cannot be written from outside the
|
|
97
|
+
element, so there is no risk of confusing this output state with an input.
|
|
98
|
+
|
|
99
|
+
**Browser support** (`:state(x)` syntax): Chrome/Edge 125+, Safari 17.4+,
|
|
100
|
+
Firefox 126+. In older browsers the states are simply never set — `:state()`
|
|
101
|
+
selectors never match, but `<wcs-credential>` itself keeps working normally
|
|
102
|
+
(graceful degradation, never-throw).
|
|
103
|
+
|
|
104
|
+
**SSR**: `:state()` cannot be serialized into HTML, so server-rendered markup
|
|
105
|
+
never carries these states on first paint (`@wcstack/server` is unaffected).
|
|
106
|
+
If you need to style the pre-hydration gap, pair your rule with
|
|
107
|
+
`wcs-credential:not(:defined)` instead.
|
|
108
|
+
|
|
109
|
+
### Debugging
|
|
110
|
+
|
|
111
|
+
Custom states are invisible in DevTools' Elements panel and `attachInternals()`
|
|
112
|
+
cannot be called twice, so there is no console way to inspect them directly.
|
|
113
|
+
Two debug-only aids are provided for that:
|
|
114
|
+
|
|
115
|
+
- `el.debugStates` — a **snapshot** array of the currently-on state names
|
|
116
|
+
(e.g. `["loading"]`). It is not part of `wc-bindable` (not a bind target)
|
|
117
|
+
and its shape is not a guaranteed contract — use it for debugging only.
|
|
118
|
+
- The `debug-states` attribute (opt-in, default off) mirrors state changes
|
|
119
|
+
onto `data-wcs-state-loading` / `data-wcs-state-cancelled` /
|
|
120
|
+
`data-wcs-state-error` attributes on the element, so the Elements panel
|
|
121
|
+
highlights them as they toggle:
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<wcs-credential debug-states></wcs-credential>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Write your CSS against `:state()`, not `data-wcs-state-*`.** The mirrored
|
|
128
|
+
attributes exist purely to make state changes visible while debugging with
|
|
129
|
+
DevTools open; they are not a supported styling hook.
|
|
130
|
+
|
|
77
131
|
## Notes & limitations
|
|
78
132
|
|
|
79
133
|
- **WebAuthn (`publicKey`) is out of scope for v1** — a future `<wcs-webauthn>` node would cover it.
|
package/dist/index.d.ts
CHANGED
|
@@ -158,7 +158,11 @@ declare class WcsCredential extends HTMLElement {
|
|
|
158
158
|
static wcBindable: IWcBindable;
|
|
159
159
|
private _core;
|
|
160
160
|
private _connectedCallbackPromise;
|
|
161
|
+
private _internals;
|
|
161
162
|
constructor();
|
|
163
|
+
get debugStates(): string[];
|
|
164
|
+
private _initInternals;
|
|
165
|
+
private _wireStates;
|
|
162
166
|
get value(): Credential | null;
|
|
163
167
|
get loading(): boolean;
|
|
164
168
|
get error(): any;
|
package/dist/index.esm.js
CHANGED
|
@@ -302,9 +302,64 @@ class WcsCredential extends HTMLElement {
|
|
|
302
302
|
};
|
|
303
303
|
_core;
|
|
304
304
|
_connectedCallbackPromise = Promise.resolve();
|
|
305
|
+
_internals = null;
|
|
305
306
|
constructor() {
|
|
306
307
|
super();
|
|
307
308
|
this._core = new CredentialCore(this);
|
|
309
|
+
this._internals = this._initInternals();
|
|
310
|
+
this._wireStates({
|
|
311
|
+
"wcs-credential:loading-changed": (d) => ({ loading: d === true }),
|
|
312
|
+
"wcs-credential:cancelled-changed": (d) => ({ cancelled: d === true }),
|
|
313
|
+
"wcs-credential:error": (d) => ({ error: d != null }),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
// CSS state reflection (:state()) — debug-only snapshot getter. NOT part of
|
|
317
|
+
// wc-bindable (not a bind target); see README "CSS styling with :state()".
|
|
318
|
+
// MUST NOT return the live CustomStateSet (that would let callers write
|
|
319
|
+
// states from outside, defeating the point of :state() being read-only).
|
|
320
|
+
get debugStates() {
|
|
321
|
+
return this._internals ? [...this._internals.states] : [];
|
|
322
|
+
}
|
|
323
|
+
_initInternals() {
|
|
324
|
+
// never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent
|
|
325
|
+
// in happy-dom / older environments, and pre-125 Chromium rejects
|
|
326
|
+
// non-dashed state names from states.add() (probed and discarded here).
|
|
327
|
+
// Either case silently disables reflection — the component still works,
|
|
328
|
+
// it just doesn't expose :state() selectors.
|
|
329
|
+
try {
|
|
330
|
+
if (typeof this.attachInternals !== "function")
|
|
331
|
+
return null;
|
|
332
|
+
const internals = this.attachInternals();
|
|
333
|
+
internals.states.add("wcs-probe");
|
|
334
|
+
internals.states.delete("wcs-probe");
|
|
335
|
+
return internals;
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
_wireStates(map) {
|
|
342
|
+
if (this._internals === null)
|
|
343
|
+
return;
|
|
344
|
+
const states = this._internals.states;
|
|
345
|
+
for (const [event, toStates] of Object.entries(map)) {
|
|
346
|
+
this.addEventListener(event, (e) => {
|
|
347
|
+
const debug = this.hasAttribute("debug-states");
|
|
348
|
+
for (const [name, on] of Object.entries(toStates(e.detail))) {
|
|
349
|
+
try {
|
|
350
|
+
if (on) {
|
|
351
|
+
states.add(name);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
states.delete(name);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
catch { /* never-throw */ }
|
|
358
|
+
if (debug)
|
|
359
|
+
this.toggleAttribute(`data-wcs-state-${name}`, on);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
}
|
|
308
363
|
}
|
|
309
364
|
// --- Core delegated getters ---
|
|
310
365
|
get value() {
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/CredentialCore.ts","../src/components/Credential.ts","../src/registerComponents.ts","../src/bootstrapCredential.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n credential: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n credential: \"wcs-credential\",\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\n// Note: this is the live, mutable internal config. It is not part of the public\n// package exports (see exports.ts) — only `getConfig()` (a frozen snapshot) is\n// surfaced. `setConfig()` is applied internally via `bootstrapCredential()` and\n// is not re-exported from the package root, though a deep path import\n// (`.../src/config.js`) can still reach and mutate it. Accepted as-is for\n// cross-package consistency: every @wcstack package follows this same shape.\n// Use `getConfig()` for a frozen, safe read.\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 (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\n\n/**\n * Headless Credential Management primitive. A thin, framework-agnostic\n * wrapper around `navigator.credentials.get()`/`.store()` exposed through the\n * wc-bindable protocol.\n *\n * Reuses batch3's \"thin command\" archetype established by `@wcstack/share`\n * (docs/credential-tag-design.md): single `_gen` generation guard,\n * same-value-guarded private setters, never-throw try/catch, no\n * `AbortController`/`abort()` command.\n *\n * **v1 scope excludes WebAuthn (`publicKey`)** — see docs/credential-tag-design.md\n * §0. `get()` validates and strips a `publicKey` option rather than silently\n * forwarding it, surfacing the attempt as a scope-violation `error` instead of\n * accidentally supporting WebAuthn through a side door.\n *\n * **`get()`/`store()` share one `_gen`** — an accepted v1 simplification\n * (docs/multi-promise-io-node-design.md): these two operations are used\n * sequentially in real auth flows (store after a successful login, get before\n * attempting one), not naturally concurrently on the same instance. If both\n * ARE invoked concurrently on the same `<wcs-credential>`, the later call's\n * generation bump silently drops the earlier call's completion write. If this\n * limitation actually bites, use two separate `<wcs-credential>` instances\n * (one for get, one for store) rather than reworking the Core.\n */\nexport class CredentialCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-credential:complete\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-credential:loading-changed\" },\n { name: \"error\", event: \"wcs-credential:error\" },\n { name: \"cancelled\", event: \"wcs-credential:cancelled-changed\" },\n ],\n commands: [\n { name: \"get\", async: true },\n { name: \"store\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _value: Credential | null = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _cancelled: boolean = false;\n // Generation guard (§3.4): shared by get() and store() (see class docs on\n // the accepted concurrency limitation this implies).\n private _gen = 0;\n // SSR (§3.8): no asynchronous probe to await, so 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 get value(): Credential | null {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n get cancelled(): boolean {\n return this._cancelled;\n }\n\n // Lifecycle (§3.5). Command-driven with no subscription to establish, so\n // observe() is an idempotent no-op that resolves once ready; dispose() only\n // invalidates any in-flight get()/store() (there is nothing to unsubscribe).\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n }\n\n private _setLoading(loading: boolean): void {\n if (this._loading === loading) return;\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n // Deliberately NO same-value guard (unlike error/loading/cancelled below).\n // `value` is a success-completion signal, not idempotent state: it is written\n // only on a successful get()/store(), and wcs-credential:complete is the *sole*\n // success notification. store() echoes the caller's credential argument, so two\n // consecutive successful store() calls with the same object reference are two\n // distinct completions and must each re-fire wcs-credential:complete so an\n // `$on`/eventToken consumer (and a `value:` binding) sees every success. This\n // matches clipboard `_setRead` / broadcast `_setMessage`, which carve\n // result/event values out of the §3.3 guard for the same reason.\n private _setValue(value: Credential | null): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:complete\", {\n detail: { value },\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setCancelled(cancelled: boolean): void {\n if (this._cancelled === cancelled) return;\n this._cancelled = cancelled;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:cancelled-changed\", {\n detail: cancelled,\n bubbles: true,\n }));\n }\n\n private _api(): typeof navigator.credentials | undefined {\n const nav = (globalThis as any).navigator;\n return nav?.credentials;\n }\n\n // Normalizes a rejection reason to a consistent { name, message } shape,\n // mirroring WorkerCore._normalizeError (packages/worker/src/core/WorkerCore.ts).\n private _normalizeError(e: unknown): { name: string; message: string } {\n if (e instanceof Error) {\n return { name: e.name, message: e.message };\n }\n return { name: \"Error\", message: String(e) };\n }\n\n // Classifies a get()/store() rejection as a user cancellation vs a real\n // failure (docs/credential-tag-design.md §2/§5). For the Credential\n // Management API the browser rejects with `NotAllowedError` when the user\n // dismisses/declines the native account-chooser UI — this is a routine \"the\n // user did not pick\" outcome, not a platform failure, so it maps to\n // `cancelled` and is kept out of `error`. Note this is `NotAllowedError`,\n // NOT `AbortError`: unlike Web Share/Contact Picker (whose APIs reject with\n // `AbortError` on dismissal), credentials.get()/store() signal user refusal\n // via `NotAllowedError`. Every other name (SecurityError, NetworkError, a\n // programmatic signal abort, etc.) flows to `error`.\n private _isCancellation(e: unknown): boolean {\n return (e as { name?: unknown } | null)?.name === \"NotAllowedError\";\n }\n\n /**\n * `get(options)` — v1 scope excludes `publicKey` (WebAuthn). If present, it\n * is stripped and the call surfaces a scope-violation `error` instead of\n * forwarding it to the platform API (which would accidentally support\n * WebAuthn through a side door). `navigator.credentials.get()` does not\n * require a user gesture (unlike Web Share/Fullscreen), so this can be\n * invoked automatically on page load for a \"silent sign-in\" flow.\n */\n async get(options: CredentialGetOptions & { publicKey?: unknown } = {}): Promise<Credential | null> {\n if (\"publicKey\" in options) {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) is out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new get so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n const credential = await api.get(options as CredentialRequestOptions);\n\n if (gen !== this._gen) return null; // stale (dispose() ran while awaiting)\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n\n /**\n * `store(credential)` — shares the same single `_gen` as `get()` (see class\n * docs). `navigator.credentials.store()` resolves `Promise<void>` (per\n * `lib.dom.d.ts`) — there is no payload to read off the API, so `value` is\n * synthesized as an echo of the caller's `credential`, mirroring\n * `ShareCore.share()`'s same accommodation for `navigator.share()`.\n *\n * A `PublicKeyCredential` (`type === \"public-key\"`, WebAuthn) is rejected as a\n * scope violation before touching the platform API — the same v1 boundary\n * `get()` enforces on the `publicKey` option (docs/credential-tag-design.md\n * §3.2), so this node never becomes a WebAuthn store backdoor.\n */\n async store(credential: StorableCredential): Promise<Credential | null> {\n if ((credential as { type?: unknown } | null)?.type === \"public-key\") {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) credentials are out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new store so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n await api.store(credential);\n\n if (gen !== this._gen) return null;\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\nimport { CredentialCore } from \"../core/CredentialCore.js\";\n\n/**\n * `<wcs-credential>` — declarative Credential Management API primitive\n * (password/federated only — see docs/credential-tag-design.md §0 for the\n * WebAuthn scope exclusion).\n *\n * A thin command-only Shell (mirrors `<wcs-share>`): no attributes at all.\n * `get(options)`/`store(credential)`'s arguments are per-call.\n */\nexport class WcsCredential extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n\n static wcBindable: IWcBindable = {\n ...CredentialCore.wcBindable,\n inputs: [],\n // Inherit commands from Core (single source of truth).\n commands: CredentialCore.wcBindable.commands,\n };\n\n private _core: CredentialCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new CredentialCore(this);\n }\n\n // --- Core delegated getters ---\n\n get value(): Credential | null {\n return this._core.value;\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 cancelled(): boolean {\n return this._core.cancelled;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Commands ---\n\n get(options?: CredentialGetOptions): Promise<Credential | null> {\n return this._core.get(options);\n }\n\n store(credential: StorableCredential): Promise<Credential | null> {\n return this._core.store(credential);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { WcsCredential } from \"./components/Credential.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.credential)) {\n customElements.define(config.tagNames.credential, WcsCredential);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapCredential(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/core/CredentialCore.ts","../src/components/Credential.ts","../src/registerComponents.ts","../src/bootstrapCredential.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n credential: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n credential: \"wcs-credential\",\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\n// Note: this is the live, mutable internal config. It is not part of the public\n// package exports (see exports.ts) — only `getConfig()` (a frozen snapshot) is\n// surfaced. `setConfig()` is applied internally via `bootstrapCredential()` and\n// is not re-exported from the package root, though a deep path import\n// (`.../src/config.js`) can still reach and mutate it. Accepted as-is for\n// cross-package consistency: every @wcstack package follows this same shape.\n// Use `getConfig()` for a frozen, safe read.\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 (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\n\n/**\n * Headless Credential Management primitive. A thin, framework-agnostic\n * wrapper around `navigator.credentials.get()`/`.store()` exposed through the\n * wc-bindable protocol.\n *\n * Reuses batch3's \"thin command\" archetype established by `@wcstack/share`\n * (docs/credential-tag-design.md): single `_gen` generation guard,\n * same-value-guarded private setters, never-throw try/catch, no\n * `AbortController`/`abort()` command.\n *\n * **v1 scope excludes WebAuthn (`publicKey`)** — see docs/credential-tag-design.md\n * §0. `get()` validates and strips a `publicKey` option rather than silently\n * forwarding it, surfacing the attempt as a scope-violation `error` instead of\n * accidentally supporting WebAuthn through a side door.\n *\n * **`get()`/`store()` share one `_gen`** — an accepted v1 simplification\n * (docs/multi-promise-io-node-design.md): these two operations are used\n * sequentially in real auth flows (store after a successful login, get before\n * attempting one), not naturally concurrently on the same instance. If both\n * ARE invoked concurrently on the same `<wcs-credential>`, the later call's\n * generation bump silently drops the earlier call's completion write. If this\n * limitation actually bites, use two separate `<wcs-credential>` instances\n * (one for get, one for store) rather than reworking the Core.\n */\nexport class CredentialCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-credential:complete\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-credential:loading-changed\" },\n { name: \"error\", event: \"wcs-credential:error\" },\n { name: \"cancelled\", event: \"wcs-credential:cancelled-changed\" },\n ],\n commands: [\n { name: \"get\", async: true },\n { name: \"store\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _value: Credential | null = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _cancelled: boolean = false;\n // Generation guard (§3.4): shared by get() and store() (see class docs on\n // the accepted concurrency limitation this implies).\n private _gen = 0;\n // SSR (§3.8): no asynchronous probe to await, so 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 get value(): Credential | null {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n get cancelled(): boolean {\n return this._cancelled;\n }\n\n // Lifecycle (§3.5). Command-driven with no subscription to establish, so\n // observe() is an idempotent no-op that resolves once ready; dispose() only\n // invalidates any in-flight get()/store() (there is nothing to unsubscribe).\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n }\n\n private _setLoading(loading: boolean): void {\n if (this._loading === loading) return;\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n // Deliberately NO same-value guard (unlike error/loading/cancelled below).\n // `value` is a success-completion signal, not idempotent state: it is written\n // only on a successful get()/store(), and wcs-credential:complete is the *sole*\n // success notification. store() echoes the caller's credential argument, so two\n // consecutive successful store() calls with the same object reference are two\n // distinct completions and must each re-fire wcs-credential:complete so an\n // `$on`/eventToken consumer (and a `value:` binding) sees every success. This\n // matches clipboard `_setRead` / broadcast `_setMessage`, which carve\n // result/event values out of the §3.3 guard for the same reason.\n private _setValue(value: Credential | null): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:complete\", {\n detail: { value },\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setCancelled(cancelled: boolean): void {\n if (this._cancelled === cancelled) return;\n this._cancelled = cancelled;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:cancelled-changed\", {\n detail: cancelled,\n bubbles: true,\n }));\n }\n\n private _api(): typeof navigator.credentials | undefined {\n const nav = (globalThis as any).navigator;\n return nav?.credentials;\n }\n\n // Normalizes a rejection reason to a consistent { name, message } shape,\n // mirroring WorkerCore._normalizeError (packages/worker/src/core/WorkerCore.ts).\n private _normalizeError(e: unknown): { name: string; message: string } {\n if (e instanceof Error) {\n return { name: e.name, message: e.message };\n }\n return { name: \"Error\", message: String(e) };\n }\n\n // Classifies a get()/store() rejection as a user cancellation vs a real\n // failure (docs/credential-tag-design.md §2/§5). For the Credential\n // Management API the browser rejects with `NotAllowedError` when the user\n // dismisses/declines the native account-chooser UI — this is a routine \"the\n // user did not pick\" outcome, not a platform failure, so it maps to\n // `cancelled` and is kept out of `error`. Note this is `NotAllowedError`,\n // NOT `AbortError`: unlike Web Share/Contact Picker (whose APIs reject with\n // `AbortError` on dismissal), credentials.get()/store() signal user refusal\n // via `NotAllowedError`. Every other name (SecurityError, NetworkError, a\n // programmatic signal abort, etc.) flows to `error`.\n private _isCancellation(e: unknown): boolean {\n return (e as { name?: unknown } | null)?.name === \"NotAllowedError\";\n }\n\n /**\n * `get(options)` — v1 scope excludes `publicKey` (WebAuthn). If present, it\n * is stripped and the call surfaces a scope-violation `error` instead of\n * forwarding it to the platform API (which would accidentally support\n * WebAuthn through a side door). `navigator.credentials.get()` does not\n * require a user gesture (unlike Web Share/Fullscreen), so this can be\n * invoked automatically on page load for a \"silent sign-in\" flow.\n */\n async get(options: CredentialGetOptions & { publicKey?: unknown } = {}): Promise<Credential | null> {\n if (\"publicKey\" in options) {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) is out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new get so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n const credential = await api.get(options as CredentialRequestOptions);\n\n if (gen !== this._gen) return null; // stale (dispose() ran while awaiting)\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n\n /**\n * `store(credential)` — shares the same single `_gen` as `get()` (see class\n * docs). `navigator.credentials.store()` resolves `Promise<void>` (per\n * `lib.dom.d.ts`) — there is no payload to read off the API, so `value` is\n * synthesized as an echo of the caller's `credential`, mirroring\n * `ShareCore.share()`'s same accommodation for `navigator.share()`.\n *\n * A `PublicKeyCredential` (`type === \"public-key\"`, WebAuthn) is rejected as a\n * scope violation before touching the platform API — the same v1 boundary\n * `get()` enforces on the `publicKey` option (docs/credential-tag-design.md\n * §3.2), so this node never becomes a WebAuthn store backdoor.\n */\n async store(credential: StorableCredential): Promise<Credential | null> {\n if ((credential as { type?: unknown } | null)?.type === \"public-key\") {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) credentials are out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new store so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n await api.store(credential);\n\n if (gen !== this._gen) return null;\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\nimport { CredentialCore } from \"../core/CredentialCore.js\";\n\n/**\n * `<wcs-credential>` — declarative Credential Management API primitive\n * (password/federated only — see docs/credential-tag-design.md §0 for the\n * WebAuthn scope exclusion).\n *\n * A thin command-only Shell (mirrors `<wcs-share>`): no attributes at all.\n * `get(options)`/`store(credential)`'s arguments are per-call.\n */\nexport class WcsCredential extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n\n static wcBindable: IWcBindable = {\n ...CredentialCore.wcBindable,\n inputs: [],\n // Inherit commands from Core (single source of truth).\n commands: CredentialCore.wcBindable.commands,\n };\n\n private _core: CredentialCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new CredentialCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-credential:loading-changed\": (d) => ({ loading: d === true }),\n \"wcs-credential:cancelled-changed\": (d) => ({ cancelled: d === true }),\n \"wcs-credential: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 // --- Core delegated getters ---\n\n get value(): Credential | null {\n return this._core.value;\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 cancelled(): boolean {\n return this._core.cancelled;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Commands ---\n\n get(options?: CredentialGetOptions): Promise<Credential | null> {\n return this._core.get(options);\n }\n\n store(credential: StorableCredential): Promise<Credential | null> {\n return this._core.store(credential);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { WcsCredential } from \"./components/Credential.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.credential)) {\n customElements.define(config.tagNames.credential, WcsCredential);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapCredential(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 e={tagNames:{credential:"wcs-credential"}};function t(e){if(null===e||"object"!=typeof e)return e;Object.freeze(e);for(const
|
|
1
|
+
const e={tagNames:{credential:"wcs-credential"}};function t(e){if(null===e||"object"!=typeof e)return e;Object.freeze(e);for(const n of Object.keys(e))t(e[n]);return e}function n(e){if(null===e||"object"!=typeof e)return e;const t={};for(const s of Object.keys(e))t[s]=n(e[s]);return t}let s=null;const r=e;function a(){return s||(s=t(n(e))),s}class i extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-credential:complete",getter:e=>e.detail.value},{name:"loading",event:"wcs-credential:loading-changed"},{name:"error",event:"wcs-credential:error"},{name:"cancelled",event:"wcs-credential:cancelled-changed"}],commands:[{name:"get",async:!0},{name:"store",async:!0}]};_target;_value=null;_loading=!1;_error=null;_cancelled=!1;_gen=0;_ready=Promise.resolve();constructor(e){super(),this._target=e??this}get ready(){return this._ready}get value(){return this._value}get loading(){return this._loading}get error(){return this._error}get cancelled(){return this._cancelled}observe(){return this._ready}dispose(){this._gen++}_setLoading(e){this._loading!==e&&(this._loading=e,this._target.dispatchEvent(new CustomEvent("wcs-credential:loading-changed",{detail:e,bubbles:!0})))}_setValue(e){this._value=e,this._target.dispatchEvent(new CustomEvent("wcs-credential:complete",{detail:{value:e},bubbles:!0}))}_setError(e){this._error!==e&&(this._error=e,this._target.dispatchEvent(new CustomEvent("wcs-credential:error",{detail:e,bubbles:!0})))}_setCancelled(e){this._cancelled!==e&&(this._cancelled=e,this._target.dispatchEvent(new CustomEvent("wcs-credential:cancelled-changed",{detail:e,bubbles:!0})))}_api(){const e=globalThis.navigator;return e?.credentials}_normalizeError(e){return e instanceof Error?{name:e.name,message:e.message}:{name:"Error",message:String(e)}}_isCancellation(e){return"NotAllowedError"===e?.name}async get(e={}){if("publicKey"in e)return this._setError({name:"NotSupportedError",message:"WebAuthn (publicKey) is out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead."}),null;const t=this._api();if(!t)return this._setError({message:"Credential Management API is not supported in this browser."}),null;const n=++this._gen;this._setLoading(!0),this._setError(null),this._setCancelled(!1);try{const s=await t.get(e);return n!==this._gen?null:(this._setValue(s),this._setLoading(!1),s)}catch(e){return n!==this._gen||(this._isCancellation(e)?this._setCancelled(!0):this._setError(this._normalizeError(e)),this._setLoading(!1)),null}}async store(e){if("public-key"===e?.type)return this._setError({name:"NotSupportedError",message:"WebAuthn (publicKey) credentials are out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead."}),null;const t=this._api();if(!t)return this._setError({message:"Credential Management API is not supported in this browser."}),null;const n=++this._gen;this._setLoading(!0),this._setError(null),this._setCancelled(!1);try{return await t.store(e),n!==this._gen?null:(this._setValue(e),this._setLoading(!1),e)}catch(e){return n!==this._gen||(this._isCancellation(e)?this._setCancelled(!0):this._setError(this._normalizeError(e)),this._setLoading(!1)),null}}}class l extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...i.wcBindable,inputs:[],commands:i.wcBindable.commands};_core;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new i(this),this._internals=this._initInternals(),this._wireStates({"wcs-credential:loading-changed":e=>({loading:!0===e}),"wcs-credential:cancelled-changed":e=>({cancelled:!0===e}),"wcs-credential:error":e=>({error:null!=e})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const e=this.attachInternals();return e.states.add("wcs-probe"),e.states.delete("wcs-probe"),e}catch{return null}}_wireStates(e){if(null===this._internals)return;const t=this._internals.states;for(const[n,s]of Object.entries(e))this.addEventListener(n,e=>{const n=this.hasAttribute("debug-states");for(const[r,a]of Object.entries(s(e.detail))){try{a?t.add(r):t.delete(r)}catch{}n&&this.toggleAttribute(`data-wcs-state-${r}`,a)}})}get value(){return this._core.value}get loading(){return this._core.loading}get error(){return this._core.error}get cancelled(){return this._core.cancelled}get connectedCallbackPromise(){return this._connectedCallbackPromise}get(e){return this._core.get(e)}store(e){return this._core.store(e)}connectedCallback(){this.style.display="none",this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}function c(t){var n;t&&((n=t).tagNames&&Object.assign(e.tagNames,n.tagNames),s=null),customElements.get(r.tagNames.credential)||customElements.define(r.tagNames.credential,l)}export{i as CredentialCore,l as WcsCredential,c as bootstrapCredential,a 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/core/CredentialCore.ts","../src/components/Credential.ts","../src/bootstrapCredential.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n credential: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n credential: \"wcs-credential\",\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\n// Note: this is the live, mutable internal config. It is not part of the public\n// package exports (see exports.ts) — only `getConfig()` (a frozen snapshot) is\n// surfaced. `setConfig()` is applied internally via `bootstrapCredential()` and\n// is not re-exported from the package root, though a deep path import\n// (`.../src/config.js`) can still reach and mutate it. Accepted as-is for\n// cross-package consistency: every @wcstack package follows this same shape.\n// Use `getConfig()` for a frozen, safe read.\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 (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\n\n/**\n * Headless Credential Management primitive. A thin, framework-agnostic\n * wrapper around `navigator.credentials.get()`/`.store()` exposed through the\n * wc-bindable protocol.\n *\n * Reuses batch3's \"thin command\" archetype established by `@wcstack/share`\n * (docs/credential-tag-design.md): single `_gen` generation guard,\n * same-value-guarded private setters, never-throw try/catch, no\n * `AbortController`/`abort()` command.\n *\n * **v1 scope excludes WebAuthn (`publicKey`)** — see docs/credential-tag-design.md\n * §0. `get()` validates and strips a `publicKey` option rather than silently\n * forwarding it, surfacing the attempt as a scope-violation `error` instead of\n * accidentally supporting WebAuthn through a side door.\n *\n * **`get()`/`store()` share one `_gen`** — an accepted v1 simplification\n * (docs/multi-promise-io-node-design.md): these two operations are used\n * sequentially in real auth flows (store after a successful login, get before\n * attempting one), not naturally concurrently on the same instance. If both\n * ARE invoked concurrently on the same `<wcs-credential>`, the later call's\n * generation bump silently drops the earlier call's completion write. If this\n * limitation actually bites, use two separate `<wcs-credential>` instances\n * (one for get, one for store) rather than reworking the Core.\n */\nexport class CredentialCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-credential:complete\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-credential:loading-changed\" },\n { name: \"error\", event: \"wcs-credential:error\" },\n { name: \"cancelled\", event: \"wcs-credential:cancelled-changed\" },\n ],\n commands: [\n { name: \"get\", async: true },\n { name: \"store\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _value: Credential | null = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _cancelled: boolean = false;\n // Generation guard (§3.4): shared by get() and store() (see class docs on\n // the accepted concurrency limitation this implies).\n private _gen = 0;\n // SSR (§3.8): no asynchronous probe to await, so 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 get value(): Credential | null {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n get cancelled(): boolean {\n return this._cancelled;\n }\n\n // Lifecycle (§3.5). Command-driven with no subscription to establish, so\n // observe() is an idempotent no-op that resolves once ready; dispose() only\n // invalidates any in-flight get()/store() (there is nothing to unsubscribe).\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n }\n\n private _setLoading(loading: boolean): void {\n if (this._loading === loading) return;\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n // Deliberately NO same-value guard (unlike error/loading/cancelled below).\n // `value` is a success-completion signal, not idempotent state: it is written\n // only on a successful get()/store(), and wcs-credential:complete is the *sole*\n // success notification. store() echoes the caller's credential argument, so two\n // consecutive successful store() calls with the same object reference are two\n // distinct completions and must each re-fire wcs-credential:complete so an\n // `$on`/eventToken consumer (and a `value:` binding) sees every success. This\n // matches clipboard `_setRead` / broadcast `_setMessage`, which carve\n // result/event values out of the §3.3 guard for the same reason.\n private _setValue(value: Credential | null): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:complete\", {\n detail: { value },\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setCancelled(cancelled: boolean): void {\n if (this._cancelled === cancelled) return;\n this._cancelled = cancelled;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:cancelled-changed\", {\n detail: cancelled,\n bubbles: true,\n }));\n }\n\n private _api(): typeof navigator.credentials | undefined {\n const nav = (globalThis as any).navigator;\n return nav?.credentials;\n }\n\n // Normalizes a rejection reason to a consistent { name, message } shape,\n // mirroring WorkerCore._normalizeError (packages/worker/src/core/WorkerCore.ts).\n private _normalizeError(e: unknown): { name: string; message: string } {\n if (e instanceof Error) {\n return { name: e.name, message: e.message };\n }\n return { name: \"Error\", message: String(e) };\n }\n\n // Classifies a get()/store() rejection as a user cancellation vs a real\n // failure (docs/credential-tag-design.md §2/§5). For the Credential\n // Management API the browser rejects with `NotAllowedError` when the user\n // dismisses/declines the native account-chooser UI — this is a routine \"the\n // user did not pick\" outcome, not a platform failure, so it maps to\n // `cancelled` and is kept out of `error`. Note this is `NotAllowedError`,\n // NOT `AbortError`: unlike Web Share/Contact Picker (whose APIs reject with\n // `AbortError` on dismissal), credentials.get()/store() signal user refusal\n // via `NotAllowedError`. Every other name (SecurityError, NetworkError, a\n // programmatic signal abort, etc.) flows to `error`.\n private _isCancellation(e: unknown): boolean {\n return (e as { name?: unknown } | null)?.name === \"NotAllowedError\";\n }\n\n /**\n * `get(options)` — v1 scope excludes `publicKey` (WebAuthn). If present, it\n * is stripped and the call surfaces a scope-violation `error` instead of\n * forwarding it to the platform API (which would accidentally support\n * WebAuthn through a side door). `navigator.credentials.get()` does not\n * require a user gesture (unlike Web Share/Fullscreen), so this can be\n * invoked automatically on page load for a \"silent sign-in\" flow.\n */\n async get(options: CredentialGetOptions & { publicKey?: unknown } = {}): Promise<Credential | null> {\n if (\"publicKey\" in options) {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) is out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new get so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n const credential = await api.get(options as CredentialRequestOptions);\n\n if (gen !== this._gen) return null; // stale (dispose() ran while awaiting)\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n\n /**\n * `store(credential)` — shares the same single `_gen` as `get()` (see class\n * docs). `navigator.credentials.store()` resolves `Promise<void>` (per\n * `lib.dom.d.ts`) — there is no payload to read off the API, so `value` is\n * synthesized as an echo of the caller's `credential`, mirroring\n * `ShareCore.share()`'s same accommodation for `navigator.share()`.\n *\n * A `PublicKeyCredential` (`type === \"public-key\"`, WebAuthn) is rejected as a\n * scope violation before touching the platform API — the same v1 boundary\n * `get()` enforces on the `publicKey` option (docs/credential-tag-design.md\n * §3.2), so this node never becomes a WebAuthn store backdoor.\n */\n async store(credential: StorableCredential): Promise<Credential | null> {\n if ((credential as { type?: unknown } | null)?.type === \"public-key\") {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) credentials are out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new store so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n await api.store(credential);\n\n if (gen !== this._gen) return null;\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\nimport { CredentialCore } from \"../core/CredentialCore.js\";\n\n/**\n * `<wcs-credential>` — declarative Credential Management API primitive\n * (password/federated only — see docs/credential-tag-design.md §0 for the\n * WebAuthn scope exclusion).\n *\n * A thin command-only Shell (mirrors `<wcs-share>`): no attributes at all.\n * `get(options)`/`store(credential)`'s arguments are per-call.\n */\nexport class WcsCredential extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n\n static wcBindable: IWcBindable = {\n ...CredentialCore.wcBindable,\n inputs: [],\n // Inherit commands from Core (single source of truth).\n commands: CredentialCore.wcBindable.commands,\n };\n\n private _core: CredentialCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new CredentialCore(this);\n }\n\n // --- Core delegated getters ---\n\n get value(): Credential | null {\n return this._core.value;\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 cancelled(): boolean {\n return this._core.cancelled;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Commands ---\n\n get(options?: CredentialGetOptions): Promise<Credential | null> {\n return this._core.get(options);\n }\n\n store(credential: StorableCredential): Promise<Credential | null> {\n return this._core.store(credential);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapCredential(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsCredential } from \"./components/Credential.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.credential)) {\n customElements.define(config.tagNames.credential, WcsCredential);\n }\n}\n"],"names":["_config","tagNames","credential","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","CredentialCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","value","commands","async","_target","_value","_loading","_error","_cancelled","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","loading","error","cancelled","observe","dispose","_setLoading","dispatchEvent","CustomEvent","bubbles","_setValue","_setError","_setCancelled","_api","nav","globalThis","navigator","credentials","_normalizeError","Error","message","String","_isCancellation","get","options","api","gen","store","type","WcsCredential","HTMLElement","wcBindable","inputs","_core","_connectedCallbackPromise","connectedCallbackPromise","connectedCallback","style","display","disconnectedCallback","bootstrapCredential","userConfig","partialConfig","assign","customElements","define"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/CredentialCore.ts","../src/components/Credential.ts","../src/bootstrapCredential.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n credential: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n credential: \"wcs-credential\",\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\n// Note: this is the live, mutable internal config. It is not part of the public\n// package exports (see exports.ts) — only `getConfig()` (a frozen snapshot) is\n// surfaced. `setConfig()` is applied internally via `bootstrapCredential()` and\n// is not re-exported from the package root, though a deep path import\n// (`.../src/config.js`) can still reach and mutate it. Accepted as-is for\n// cross-package consistency: every @wcstack package follows this same shape.\n// Use `getConfig()` for a frozen, safe read.\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 (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\n\n/**\n * Headless Credential Management primitive. A thin, framework-agnostic\n * wrapper around `navigator.credentials.get()`/`.store()` exposed through the\n * wc-bindable protocol.\n *\n * Reuses batch3's \"thin command\" archetype established by `@wcstack/share`\n * (docs/credential-tag-design.md): single `_gen` generation guard,\n * same-value-guarded private setters, never-throw try/catch, no\n * `AbortController`/`abort()` command.\n *\n * **v1 scope excludes WebAuthn (`publicKey`)** — see docs/credential-tag-design.md\n * §0. `get()` validates and strips a `publicKey` option rather than silently\n * forwarding it, surfacing the attempt as a scope-violation `error` instead of\n * accidentally supporting WebAuthn through a side door.\n *\n * **`get()`/`store()` share one `_gen`** — an accepted v1 simplification\n * (docs/multi-promise-io-node-design.md): these two operations are used\n * sequentially in real auth flows (store after a successful login, get before\n * attempting one), not naturally concurrently on the same instance. If both\n * ARE invoked concurrently on the same `<wcs-credential>`, the later call's\n * generation bump silently drops the earlier call's completion write. If this\n * limitation actually bites, use two separate `<wcs-credential>` instances\n * (one for get, one for store) rather than reworking the Core.\n */\nexport class CredentialCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-credential:complete\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-credential:loading-changed\" },\n { name: \"error\", event: \"wcs-credential:error\" },\n { name: \"cancelled\", event: \"wcs-credential:cancelled-changed\" },\n ],\n commands: [\n { name: \"get\", async: true },\n { name: \"store\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _value: Credential | null = null;\n private _loading: boolean = false;\n private _error: any = null;\n private _cancelled: boolean = false;\n // Generation guard (§3.4): shared by get() and store() (see class docs on\n // the accepted concurrency limitation this implies).\n private _gen = 0;\n // SSR (§3.8): no asynchronous probe to await, so 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 get value(): Credential | null {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get error(): any {\n return this._error;\n }\n\n get cancelled(): boolean {\n return this._cancelled;\n }\n\n // Lifecycle (§3.5). Command-driven with no subscription to establish, so\n // observe() is an idempotent no-op that resolves once ready; dispose() only\n // invalidates any in-flight get()/store() (there is nothing to unsubscribe).\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n }\n\n private _setLoading(loading: boolean): void {\n if (this._loading === loading) return;\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n // Deliberately NO same-value guard (unlike error/loading/cancelled below).\n // `value` is a success-completion signal, not idempotent state: it is written\n // only on a successful get()/store(), and wcs-credential:complete is the *sole*\n // success notification. store() echoes the caller's credential argument, so two\n // consecutive successful store() calls with the same object reference are two\n // distinct completions and must each re-fire wcs-credential:complete so an\n // `$on`/eventToken consumer (and a `value:` binding) sees every success. This\n // matches clipboard `_setRead` / broadcast `_setMessage`, which carve\n // result/event values out of the §3.3 guard for the same reason.\n private _setValue(value: Credential | null): void {\n this._value = value;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:complete\", {\n detail: { value },\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setCancelled(cancelled: boolean): void {\n if (this._cancelled === cancelled) return;\n this._cancelled = cancelled;\n this._target.dispatchEvent(new CustomEvent(\"wcs-credential:cancelled-changed\", {\n detail: cancelled,\n bubbles: true,\n }));\n }\n\n private _api(): typeof navigator.credentials | undefined {\n const nav = (globalThis as any).navigator;\n return nav?.credentials;\n }\n\n // Normalizes a rejection reason to a consistent { name, message } shape,\n // mirroring WorkerCore._normalizeError (packages/worker/src/core/WorkerCore.ts).\n private _normalizeError(e: unknown): { name: string; message: string } {\n if (e instanceof Error) {\n return { name: e.name, message: e.message };\n }\n return { name: \"Error\", message: String(e) };\n }\n\n // Classifies a get()/store() rejection as a user cancellation vs a real\n // failure (docs/credential-tag-design.md §2/§5). For the Credential\n // Management API the browser rejects with `NotAllowedError` when the user\n // dismisses/declines the native account-chooser UI — this is a routine \"the\n // user did not pick\" outcome, not a platform failure, so it maps to\n // `cancelled` and is kept out of `error`. Note this is `NotAllowedError`,\n // NOT `AbortError`: unlike Web Share/Contact Picker (whose APIs reject with\n // `AbortError` on dismissal), credentials.get()/store() signal user refusal\n // via `NotAllowedError`. Every other name (SecurityError, NetworkError, a\n // programmatic signal abort, etc.) flows to `error`.\n private _isCancellation(e: unknown): boolean {\n return (e as { name?: unknown } | null)?.name === \"NotAllowedError\";\n }\n\n /**\n * `get(options)` — v1 scope excludes `publicKey` (WebAuthn). If present, it\n * is stripped and the call surfaces a scope-violation `error` instead of\n * forwarding it to the platform API (which would accidentally support\n * WebAuthn through a side door). `navigator.credentials.get()` does not\n * require a user gesture (unlike Web Share/Fullscreen), so this can be\n * invoked automatically on page load for a \"silent sign-in\" flow.\n */\n async get(options: CredentialGetOptions & { publicKey?: unknown } = {}): Promise<Credential | null> {\n if (\"publicKey\" in options) {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) is out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new get so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n const credential = await api.get(options as CredentialRequestOptions);\n\n if (gen !== this._gen) return null; // stale (dispose() ran while awaiting)\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n\n /**\n * `store(credential)` — shares the same single `_gen` as `get()` (see class\n * docs). `navigator.credentials.store()` resolves `Promise<void>` (per\n * `lib.dom.d.ts`) — there is no payload to read off the API, so `value` is\n * synthesized as an echo of the caller's `credential`, mirroring\n * `ShareCore.share()`'s same accommodation for `navigator.share()`.\n *\n * A `PublicKeyCredential` (`type === \"public-key\"`, WebAuthn) is rejected as a\n * scope violation before touching the platform API — the same v1 boundary\n * `get()` enforces on the `publicKey` option (docs/credential-tag-design.md\n * §3.2), so this node never becomes a WebAuthn store backdoor.\n */\n async store(credential: StorableCredential): Promise<Credential | null> {\n if ((credential as { type?: unknown } | null)?.type === \"public-key\") {\n this._setError({ name: \"NotSupportedError\", message: \"WebAuthn (publicKey) credentials are out of scope for @wcstack/credential v1. Use a dedicated WebAuthn node instead.\" });\n return null;\n }\n\n const api = this._api();\n if (!api) {\n this._setError({ message: \"Credential Management API is not supported in this browser.\" });\n return null;\n }\n\n const gen = ++this._gen;\n\n this._setLoading(true);\n // Reset the previous outcome before starting a new store so a stale\n // cancelled/error does not linger into this call's result.\n this._setError(null);\n this._setCancelled(false);\n\n try {\n await api.store(credential);\n\n if (gen !== this._gen) return null;\n\n this._setValue(credential);\n this._setLoading(false);\n return credential;\n } catch (e: any) {\n if (gen !== this._gen) return null;\n if (this._isCancellation(e)) {\n this._setCancelled(true);\n } else {\n this._setError(this._normalizeError(e));\n }\n this._setLoading(false);\n return null;\n }\n }\n}\n","import { CredentialGetOptions, IWcBindable, StorableCredential } from \"../types.js\";\nimport { CredentialCore } from \"../core/CredentialCore.js\";\n\n/**\n * `<wcs-credential>` — declarative Credential Management API primitive\n * (password/federated only — see docs/credential-tag-design.md §0 for the\n * WebAuthn scope exclusion).\n *\n * A thin command-only Shell (mirrors `<wcs-share>`): no attributes at all.\n * `get(options)`/`store(credential)`'s arguments are per-call.\n */\nexport class WcsCredential extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n\n static wcBindable: IWcBindable = {\n ...CredentialCore.wcBindable,\n inputs: [],\n // Inherit commands from Core (single source of truth).\n commands: CredentialCore.wcBindable.commands,\n };\n\n private _core: CredentialCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new CredentialCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-credential:loading-changed\": (d) => ({ loading: d === true }),\n \"wcs-credential:cancelled-changed\": (d) => ({ cancelled: d === true }),\n \"wcs-credential: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 // --- Core delegated getters ---\n\n get value(): Credential | null {\n return this._core.value;\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 cancelled(): boolean {\n return this._core.cancelled;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Commands ---\n\n get(options?: CredentialGetOptions): Promise<Credential | null> {\n return this._core.get(options);\n }\n\n store(credential: StorableCredential): Promise<Credential | null> {\n return this._core.store(credential);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapCredential(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsCredential } from \"./components/Credential.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.credential)) {\n customElements.define(config.tagNames.credential, WcsCredential);\n }\n}\n"],"names":["_config","tagNames","credential","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","CredentialCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","value","commands","async","_target","_value","_loading","_error","_cancelled","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","loading","error","cancelled","observe","dispose","_setLoading","dispatchEvent","CustomEvent","bubbles","_setValue","_setError","_setCancelled","_api","nav","globalThis","navigator","credentials","_normalizeError","Error","message","String","_isCancellation","get","options","api","gen","store","type","WcsCredential","HTMLElement","wcBindable","inputs","_core","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","addEventListener","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","connectedCallback","style","display","disconnectedCallback","bootstrapCredential","userConfig","partialConfig","assign","customElements","define"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/credential",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"description": "Declarative Credential Management component for Web Components. Framework-agnostic navigator.credentials get/store wrapper (password/federated only) via wc-bindable-protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|