anentrypoint-design 0.0.192 → 0.0.193
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/dist/247420.js +10 -10
- package/package.json +1 -1
- package/src/components/freddie.js +42 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.193",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
|
@@ -464,17 +464,52 @@ export const config = makePage((ctx) => {
|
|
|
464
464
|
// ---- env -------------------------------------------------------------------
|
|
465
465
|
|
|
466
466
|
export const env = makePage((ctx) => {
|
|
467
|
-
|
|
467
|
+
Object.assign(ctx.state, { auth: null, vars: null, draft: {}, busy: '', note: null });
|
|
468
|
+
async function load() {
|
|
469
|
+
try {
|
|
470
|
+
const [auth, vars] = await Promise.all([api('/api/auth').catch(() => null), api('/api/env').catch(() => null)]);
|
|
471
|
+
ctx.set({ loading: false, auth, vars, error: null });
|
|
472
|
+
} catch (e) { ctx.set({ loading: false, error: e }); }
|
|
473
|
+
}
|
|
474
|
+
// Set a provider key through the dashboard (POST /api/auth). The key is sent
|
|
475
|
+
// once and never echoed back — GET /api/auth returns only a masked fingerprint.
|
|
476
|
+
async function setKey(provider) {
|
|
477
|
+
const key = (ctx.state.draft[provider] || '').trim();
|
|
478
|
+
if (!key) { ctx.set({ note: { kind: 'warn', msg: 'key required for ' + provider } }); return; }
|
|
479
|
+
ctx.set({ busy: provider, note: null });
|
|
480
|
+
try { await api('/api/auth', { method: 'POST', body: { provider, key } }); ctx.state.draft[provider] = ''; await load(); ctx.set({ note: { kind: 'success', msg: 'stored ' + provider } }); }
|
|
481
|
+
catch (e) { ctx.set({ note: { kind: 'error', msg: String(e.message || e) } }); }
|
|
482
|
+
ctx.set({ busy: '' });
|
|
483
|
+
}
|
|
484
|
+
async function removeKey(provider) {
|
|
485
|
+
ctx.set({ busy: provider, note: null });
|
|
486
|
+
try { await api('/api/auth/' + encodeURIComponent(provider), { method: 'DELETE' }); await load(); ctx.set({ note: { kind: 'success', msg: 'removed ' + provider } }); }
|
|
487
|
+
catch (e) { ctx.set({ note: { kind: 'error', msg: String(e.message || e) } }); }
|
|
488
|
+
ctx.set({ busy: '' });
|
|
489
|
+
}
|
|
468
490
|
load();
|
|
469
491
|
return () => {
|
|
470
492
|
const s = ctx.state;
|
|
471
|
-
if (s.loading) return loadingState('loading
|
|
472
|
-
if (s.error) return errorState(s.error, load);
|
|
473
|
-
const
|
|
474
|
-
const
|
|
493
|
+
if (s.loading) return loadingState('loading keys…');
|
|
494
|
+
if (s.error && !s.auth) return errorState(s.error, load);
|
|
495
|
+
const auth = Array.isArray(s.auth) ? s.auth : [];
|
|
496
|
+
const vars = Array.isArray(s.vars) ? s.vars : [];
|
|
497
|
+
// Non-provider env vars (platform tokens etc) stay a read-only presence table.
|
|
498
|
+
const providerEnvs = new Set(auth.map(a => a.env));
|
|
499
|
+
const otherRows = vars.filter(v => !providerEnvs.has(v.key)).map(v => [v.key, v.set ? Chip({ tone: 'ok', children: v.source || 'set' }) : Chip({ tone: 'neutral', children: 'unset' })]);
|
|
475
500
|
return [
|
|
476
|
-
PageHeader({ eyebrow: 'freddie', title: '
|
|
477
|
-
|
|
501
|
+
PageHeader({ eyebrow: 'freddie', title: 'keys', lede: 'provider api keys · stored locally, never displayed' }),
|
|
502
|
+
noteAlert(s.note),
|
|
503
|
+
section('provider keys',
|
|
504
|
+
auth.length ? auth.map((a, i) => Row({
|
|
505
|
+
key: i, title: a.provider, sub: a.env + (a.set ? ' · ' + a.source + (a.fingerprint ? ' · ' + a.fingerprint : '') : ''),
|
|
506
|
+
trailing: h('span', { class: 'fd-row-actions' },
|
|
507
|
+
a.set ? Chip({ tone: 'ok', children: 'set' }) : Chip({ tone: 'neutral', children: 'unset' }),
|
|
508
|
+
TextField({ type: 'password', value: s.draft[a.provider] || '', onInput: (v) => { s.draft[a.provider] = v; }, placeholder: 'paste key', 'aria-label': 'key for ' + a.provider }),
|
|
509
|
+
Btn({ primary: true, disabled: s.busy === a.provider, children: s.busy === a.provider ? '…' : 'save', onClick: () => setKey(a.provider) }),
|
|
510
|
+
(a.set && a.source === 'stored') ? Btn({ danger: true, disabled: s.busy === a.provider, children: 'remove', onClick: () => removeKey(a.provider) }) : null),
|
|
511
|
+
})) : emptyState('no providers')),
|
|
512
|
+
otherRows.length ? section('other environment', Table({ headers: ['key', 'status'], rows: otherRows })) : null,
|
|
478
513
|
];
|
|
479
514
|
};
|
|
480
515
|
});
|