@8ux-co/eelzap 0.10.0 → 0.10.2
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/CHANGELOG.md +79 -1
- package/README.md +68 -8
- package/dist/{chunk-2IUU53QA.js → chunk-4ET7VBJA.js} +230 -7
- package/dist/chunk-4ET7VBJA.js.map +1 -0
- package/dist/{chunk-QN53G5P7.js → chunk-6XHCA4U4.js} +25 -9
- package/dist/chunk-6XHCA4U4.js.map +1 -0
- package/dist/{chunk-VW4EH7NY.js → chunk-T6S3S5RH.js} +149 -81
- package/dist/chunk-T6S3S5RH.js.map +1 -0
- package/dist/index.cjs +94 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +119 -12
- package/dist/index.d.ts +119 -12
- package/dist/index.js +94 -1
- package/dist/index.js.map +1 -1
- package/dist/next.d.ts +6 -0
- package/dist/next.js.map +1 -1
- package/dist/preview.d.ts +55 -7
- package/dist/preview.js +98 -39
- package/dist/preview.js.map +1 -1
- package/dist/react.js +3 -3
- package/dist/react.js.map +1 -1
- package/dist/{signin-2QOSWZFK.js → signin-XOGBCGBL.js} +16 -117
- package/dist/signin-XOGBCGBL.js.map +1 -0
- package/dist/suggest-KLS6B7AM.js +2583 -0
- package/dist/suggest-KLS6B7AM.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2IUU53QA.js.map +0 -1
- package/dist/chunk-QN53G5P7.js.map +0 -1
- package/dist/chunk-VW4EH7NY.js.map +0 -1
- package/dist/signin-2QOSWZFK.js.map +0 -1
- package/dist/suggest-5RHURHED.js +0 -1256
- package/dist/suggest-5RHURHED.js.map +0 -1
|
@@ -1,121 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SIGNIN_MESSAGES,
|
|
3
3
|
TOKENS,
|
|
4
|
+
authorizeUrl,
|
|
5
|
+
challengeFor,
|
|
6
|
+
checkCallback,
|
|
7
|
+
createState,
|
|
8
|
+
createVerifier,
|
|
4
9
|
el,
|
|
10
|
+
exchangeCode,
|
|
5
11
|
icon,
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
kbd,
|
|
13
|
+
mountHost,
|
|
14
|
+
returnPathOf,
|
|
15
|
+
savePending,
|
|
16
|
+
takePending
|
|
17
|
+
} from "./chunk-4ET7VBJA.js";
|
|
8
18
|
import {
|
|
9
|
-
PENDING_STORAGE_KEY,
|
|
10
19
|
SIGNIN_CHANNEL,
|
|
11
|
-
SITE_CLIENT_SCOPE,
|
|
12
|
-
STATE_PREFIX,
|
|
13
|
-
__publicField,
|
|
14
20
|
writeToken
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
|
|
17
|
-
// src/preview/site/oauth.ts
|
|
18
|
-
function base64url(bytes) {
|
|
19
|
-
let binary = "";
|
|
20
|
-
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
21
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
22
|
-
}
|
|
23
|
-
function randomToken(win, size) {
|
|
24
|
-
return base64url(win.crypto.getRandomValues(new Uint8Array(size)));
|
|
25
|
-
}
|
|
26
|
-
function createVerifier(win) {
|
|
27
|
-
return randomToken(win, 32);
|
|
28
|
-
}
|
|
29
|
-
async function challengeFor(win, verifier) {
|
|
30
|
-
const digest = await win.crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
|
|
31
|
-
return base64url(new Uint8Array(digest));
|
|
32
|
-
}
|
|
33
|
-
function isReturnPath(value) {
|
|
34
|
-
return /^\/(?![/\\])/.test(value) && !/[\\\s]/.test(value) && value.length <= 2048;
|
|
35
|
-
}
|
|
36
|
-
function createState(win, returnPath) {
|
|
37
|
-
const nonce = randomToken(win, 16);
|
|
38
|
-
if (returnPath === void 0 || !isReturnPath(returnPath)) return `${STATE_PREFIX}${nonce}`;
|
|
39
|
-
return `${STATE_PREFIX}${nonce}.${base64url(new TextEncoder().encode(returnPath))}`;
|
|
40
|
-
}
|
|
41
|
-
function returnPathOf(state) {
|
|
42
|
-
const encoded = state.slice(STATE_PREFIX.length).split(".")[1];
|
|
43
|
-
if (!encoded) return null;
|
|
44
|
-
try {
|
|
45
|
-
const binary = atob(encoded.replace(/-/g, "+").replace(/_/g, "/"));
|
|
46
|
-
const path = new TextDecoder().decode(Uint8Array.from(binary, (c) => c.charCodeAt(0)));
|
|
47
|
-
return isReturnPath(path) ? path : null;
|
|
48
|
-
} catch {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function authorizeUrl(ctx, state, challenge) {
|
|
53
|
-
const url = new URL("/oauth/authorize", ctx.authOrigin);
|
|
54
|
-
url.search = new URLSearchParams({
|
|
55
|
-
response_type: "code",
|
|
56
|
-
client_id: ctx.clientId,
|
|
57
|
-
redirect_uri: ctx.redirectUri,
|
|
58
|
-
code_challenge: challenge,
|
|
59
|
-
code_challenge_method: "S256",
|
|
60
|
-
state,
|
|
61
|
-
scope: SITE_CLIENT_SCOPE
|
|
62
|
-
}).toString();
|
|
63
|
-
return url.toString();
|
|
64
|
-
}
|
|
65
|
-
function checkCallback(callback, pending, authOrigin) {
|
|
66
|
-
if (!pending || !callback || callback.state !== pending.state) return "state";
|
|
67
|
-
if (callback.iss !== authOrigin) return "iss";
|
|
68
|
-
if (typeof callback.code !== "string" || !callback.code || callback.code.length > 512) {
|
|
69
|
-
return "code";
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
var ExchangeError = class extends Error {
|
|
74
|
-
constructor(status) {
|
|
75
|
-
super(`token exchange failed (${status})`);
|
|
76
|
-
__publicField(this, "status", status);
|
|
77
|
-
this.name = "ExchangeError";
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
async function exchangeCode(ctx, code, verifier, now = Date.now()) {
|
|
81
|
-
const response = await ctx.win.fetch(`${ctx.authOrigin}/api/oauth/token`, {
|
|
82
|
-
method: "POST",
|
|
83
|
-
credentials: "omit",
|
|
84
|
-
body: new URLSearchParams({
|
|
85
|
-
grant_type: "authorization_code",
|
|
86
|
-
code,
|
|
87
|
-
client_id: ctx.clientId,
|
|
88
|
-
redirect_uri: ctx.redirectUri,
|
|
89
|
-
code_verifier: verifier
|
|
90
|
-
})
|
|
91
|
-
});
|
|
92
|
-
if (!response.ok) throw new ExchangeError(response.status);
|
|
93
|
-
const body = await response.json().catch(() => null);
|
|
94
|
-
const token = body?.access_token;
|
|
95
|
-
const expiresIn = body?.expires_in;
|
|
96
|
-
if (typeof token !== "string" || !/^eel_at_[A-Za-z0-9_-]{8,200}$/.test(token) || typeof expiresIn !== "number" || !(expiresIn > 0)) {
|
|
97
|
-
throw new ExchangeError(502);
|
|
98
|
-
}
|
|
99
|
-
return { token, exp: now + Math.min(expiresIn, 3600) * 1e3, site: ctx.siteId };
|
|
100
|
-
}
|
|
101
|
-
function savePending(win, pending) {
|
|
102
|
-
try {
|
|
103
|
-
win.sessionStorage.setItem(PENDING_STORAGE_KEY, JSON.stringify(pending));
|
|
104
|
-
} catch {
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
function takePending(win) {
|
|
108
|
-
try {
|
|
109
|
-
const raw = win.sessionStorage.getItem(PENDING_STORAGE_KEY);
|
|
110
|
-
win.sessionStorage.removeItem(PENDING_STORAGE_KEY);
|
|
111
|
-
const value = raw ? JSON.parse(raw) : null;
|
|
112
|
-
if (value && typeof value.state === "string" && typeof value.verifier === "string" && (value.mode === "popup" || value.mode === "redirect")) {
|
|
113
|
-
return { state: value.state, verifier: value.verifier, mode: value.mode };
|
|
114
|
-
}
|
|
115
|
-
} catch {
|
|
116
|
-
}
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
21
|
+
} from "./chunk-6XHCA4U4.js";
|
|
119
22
|
|
|
120
23
|
// src/preview/site/signin.ts
|
|
121
24
|
var POPUP_NAME = "eelzap-signin";
|
|
@@ -155,12 +58,9 @@ function start(ctx, options = {}) {
|
|
|
155
58
|
function hint() {
|
|
156
59
|
const key = ctx.shortcut;
|
|
157
60
|
if (!key) return "";
|
|
158
|
-
const kbd = (text) => el(doc, "kbd", { text });
|
|
159
61
|
return el(doc, "span", { class: "hint", attrs: { role: "tooltip" } }, [
|
|
160
62
|
`${m.hintBefore} `,
|
|
161
|
-
kbd("Shift"),
|
|
162
|
-
" ",
|
|
163
|
-
kbd(key.toUpperCase()),
|
|
63
|
+
kbd(doc, "Shift", key.toUpperCase()),
|
|
164
64
|
` ${m.hintAfter}`
|
|
165
65
|
]);
|
|
166
66
|
}
|
|
@@ -272,6 +172,7 @@ function start(ctx, options = {}) {
|
|
|
272
172
|
}
|
|
273
173
|
} else {
|
|
274
174
|
render();
|
|
175
|
+
if (options.signIn) void signIn();
|
|
275
176
|
}
|
|
276
177
|
return {
|
|
277
178
|
destroy() {
|
|
@@ -288,8 +189,6 @@ var CSS = `
|
|
|
288
189
|
box-shadow: 0 10px 15px -3px rgba(15,23,42,.10), 0 4px 6px -4px rgba(15,23,42,.08); }
|
|
289
190
|
.hint { pointer-events: none; position: fixed; left: 50%; transform: translateX(-50%); bottom: 76px; display: flex; align-items: center; gap: 4px;
|
|
290
191
|
padding: 6px 10px; border-radius: 9px; background: ${TOKENS.dark}; color: #FFFFFF; font-size: 12px; white-space: nowrap; }
|
|
291
|
-
kbd { font: 600 11px Poppins, ui-sans-serif, system-ui, sans-serif; padding: 1px 5px; border-radius: 5px;
|
|
292
|
-
background: rgba(255,255,255,.16); color: #FFFFFF; }
|
|
293
192
|
.launcher[aria-expanded="true"] { box-shadow: 0 10px 15px -3px rgba(15,23,42,.10), 0 0 0 3px ${TOKENS.focus}; }
|
|
294
193
|
.panel { left: calc(50% - 160px); bottom: 78px; width: 320px; padding: 16px; }
|
|
295
194
|
.head { display: flex; align-items: center; justify-content: space-between; }
|
|
@@ -302,4 +201,4 @@ kbd { font: 600 11px Poppins, ui-sans-serif, system-ui, sans-serif; padding: 1px
|
|
|
302
201
|
export {
|
|
303
202
|
start
|
|
304
203
|
};
|
|
305
|
-
//# sourceMappingURL=signin-
|
|
204
|
+
//# sourceMappingURL=signin-XOGBCGBL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preview/site/signin.ts"],"sourcesContent":["import {\n SIGNIN_CHANNEL,\n type CallbackParams,\n type ChunkHandle,\n type SiteContext,\n type StartOptions,\n} from './config'\nimport { SIGNIN_MESSAGES } from './messages'\nimport {\n authorizeUrl,\n challengeFor,\n checkCallback,\n createState,\n createVerifier,\n exchangeCode,\n returnPathOf,\n savePending,\n takePending,\n type PendingSignIn,\n} from './oauth'\nimport { writeToken } from './token'\nimport { el, icon, kbd, mountHost, TOKENS as T } from './ui'\n\n/**\n * The `signin` chunk (zap-cms-v2 §3.4 steps 2 to 5, ADR 041; boards\n * SitioLanzador, SitioEntrar and SitioRenovacion): loaded only after the\n * opt-in trigger.\n *\n * The launcher «Editar o comentar», with the Shift Z hint above it, opens a\n * panel with «Entrar con Eel». All three sit at the bottom centre, the zone\n * the toolbar takes after sign-in (SitioBarra): sites keep the corners for\n * their own floating buttons (a WhatsApp button, a chat bubble). Signing in opens a popup on Nest's consent\n * screen (or, when the person consented to this site before and is signed in\n * to Eel, a popup Nest answers at once and closes, ADR 041 amendment\n * 2026-10-05); the popup lands back on\n * `{origin}/`, where the core hands the code over `BroadcastChannel('eel-zap')`\n * and closes it. This tab, which alone holds the PKCE verifier and the state,\n * checks both and the issuer, exchanges the code and opens `suggest`.\n *\n * A blocked popup turns into a full-page redirect: the verifier and state wait\n * in `sessionStorage` (`PENDING_STORAGE_KEY`), the state carries the return\n * path, and the callback page finishes here (`options.callback`) and goes back.\n */\n\nconst POPUP_NAME = 'eelzap-signin'\nconst POPUP_FEATURES = 'popup,width=480,height=720'\n\ntype Phase = 'closed' | 'open' | 'waiting' | 'error'\n\nexport function start(ctx: SiteContext, options: StartOptions = {}): ChunkHandle {\n const { win, doc } = ctx\n const m = SIGNIN_MESSAGES[ctx.locale]\n const host = mountHost(doc, CSS)\n const layer = el(doc, 'div', { class: 'layer' })\n host.root.append(layer)\n\n const renewing = options.reason === 'expired'\n let phase: Phase = renewing ? 'open' : 'closed'\n let notice: string | null = options.reason === 'expired' ? m.expired : null\n let pending: PendingSignIn | null = null\n let destroyed = false\n\n let channel: BroadcastChannel | null = null\n try {\n channel = new BroadcastChannel(SIGNIN_CHANNEL)\n channel.onmessage = (event: MessageEvent) => onCallback(event.data)\n } catch {\n // No BroadcastChannel: the popup cannot hand back; the redirect path still works.\n }\n\n function render(): void {\n if (destroyed) return\n const expanded = phase !== 'closed'\n const launcher = el(\n doc,\n 'button',\n {\n class: 'launcher',\n attrs: { type: 'button', 'aria-expanded': String(expanded) },\n on: { click: () => setPhase(expanded ? 'closed' : 'open') },\n },\n [icon(doc, 'zap', 18), m.launcher],\n )\n layer.replaceChildren(launcher, expanded ? panel() : hint())\n }\n\n /** «Pulsa Shift Z para editar o comentar», above the closed launcher (SitioLanzador). */\n function hint(): HTMLElement | string {\n const key = ctx.shortcut\n if (!key) return ''\n return el(doc, 'span', { class: 'hint', attrs: { role: 'tooltip' } }, [\n `${m.hintBefore} `,\n kbd(doc, 'Shift', key.toUpperCase()),\n ` ${m.hintAfter}`,\n ])\n }\n\n function panel(): HTMLElement {\n const waiting = phase === 'waiting'\n return el(\n doc,\n 'div',\n {\n class: 'card panel sheet',\n attrs: { role: 'dialog', 'aria-labelledby': 'eelzap-signin-title' },\n },\n [\n el(doc, 'div', { class: 'head' }, [\n el(doc, 'h2', { attrs: { id: 'eelzap-signin-title' } }, [icon(doc, 'zap', 20), m.title]),\n el(\n doc,\n 'button',\n {\n class: 'iconbtn',\n attrs: { type: 'button', 'aria-label': m.close, title: m.close },\n on: { click: () => ctx.close() },\n },\n [icon(doc, 'x')],\n ),\n ]),\n el(doc, 'p', { class: 'muted body', text: waiting ? m.waitingHelp : m.body }),\n notice ? el(doc, 'p', { class: 'notice', attrs: { role: 'status' }, text: notice }) : null,\n el(\n doc,\n 'button',\n {\n class: 'btn-dark',\n attrs: { type: 'button', 'data-action': 'sign-in' },\n on: { click: () => void signIn() },\n },\n [icon(doc, 'eel', 18), waiting ? m.retry : m.signIn],\n ),\n waiting\n ? el(doc, 'p', { class: 'muted waiting', attrs: { role: 'status' }, text: m.waiting })\n : null,\n el(doc, 'p', { class: 'muted note' }, [\n icon(doc, 'lock', 13),\n el(doc, 'span', { text: m.note }),\n ]),\n ],\n )\n }\n\n function setPhase(next: Phase, message: string | null = null): void {\n phase = next\n notice = message\n render()\n }\n\n async function signIn(): Promise<void> {\n // A stale full-page attempt in this tab is abandoned.\n takePending(win)\n // The popup opens INSIDE the click, before any await, or the browser blocks it.\n const popup = win.open('', POPUP_NAME, POPUP_FEATURES)\n const verifier = createVerifier(win)\n try {\n const challenge = await challengeFor(win, verifier)\n if (popup) {\n const state = createState(win)\n pending = { state, verifier, mode: 'popup' }\n setPhase('waiting')\n popup.location.href = authorizeUrl(ctx, state, challenge)\n return\n }\n // Popup blocked: the whole tab goes to Nest and comes back to this path.\n const { pathname, search, hash } = win.location\n const state = createState(win, `${pathname}${search}${hash}`)\n savePending(win, { state, verifier, mode: 'redirect' })\n win.location.assign(authorizeUrl(ctx, state, challenge))\n } catch {\n popup?.close()\n setPhase('error', m.failed)\n }\n }\n\n function onCallback(data: unknown): void {\n if (!pending || !data || (data as { type?: unknown }).type !== 'eelzap:callback') return\n const callback = data as Partial<CallbackParams>\n const problem = checkCallback(callback, pending, ctx.authOrigin)\n // Another sign-in's callback (another tab of this site): not ours to judge.\n if (problem === 'state') return\n const used = pending\n pending = null\n if (problem) {\n setPhase('error', m.failed)\n return\n }\n void complete(callback.code!, used.verifier, null)\n }\n\n async function complete(code: string, verifier: string, returnPath: string | null) {\n try {\n const token = await exchangeCode(ctx, code, verifier)\n writeToken(win, token)\n if (destroyed) return\n if (returnPath && returnPath !== `${win.location.pathname}${win.location.search}`) {\n win.location.replace(returnPath)\n return\n }\n await ctx.open('suggest', renewing ? { reason: 'renewed' } : undefined)\n } catch {\n setPhase('error', m.failed)\n }\n }\n\n if (options.callback) {\n const stored = takePending(win)\n const problem =\n stored?.mode === 'redirect'\n ? checkCallback(options.callback, stored, ctx.authOrigin)\n : 'state'\n if (problem) {\n setPhase('error', m.failed)\n } else {\n render()\n void complete(options.callback.code, stored!.verifier, returnPathOf(options.callback.state))\n }\n } else {\n render()\n // «Volver a entrar»: one click already made, so the sign-in starts now.\n if (options.signIn) void signIn()\n }\n\n return {\n destroy() {\n destroyed = true\n pending = null\n channel?.close()\n host.destroy()\n },\n }\n}\n\nconst CSS = `\n.launcher { pointer-events: auto; position: fixed; left: 50%; transform: translateX(-50%); bottom: 24px; height: 42px; gap: 8px;\n padding: 0 16px 0 12px; border: 1px solid ${T.border}; border-radius: 999px; background: ${T.bg}; color: ${T.fg};\n box-shadow: 0 10px 15px -3px rgba(15,23,42,.10), 0 4px 6px -4px rgba(15,23,42,.08); }\n.hint { pointer-events: none; position: fixed; left: 50%; transform: translateX(-50%); bottom: 76px; display: flex; align-items: center; gap: 4px;\n padding: 6px 10px; border-radius: 9px; background: ${T.dark}; color: #FFFFFF; font-size: 12px; white-space: nowrap; }\n.launcher[aria-expanded=\"true\"] { box-shadow: 0 10px 15px -3px rgba(15,23,42,.10), 0 0 0 3px ${T.focus}; }\n.panel { left: calc(50% - 160px); bottom: 78px; width: 320px; padding: 16px; }\n.head { display: flex; align-items: center; justify-content: space-between; }\n.body { margin: 8px 0 14px; }\n.notice { margin: 0 0 12px; padding: 8px 10px; border-radius: 9px; background: ${T.goldTint}; color: ${T.goldText}; font-size: 12px; }\n.waiting { margin-top: 8px; font-size: 12px; text-align: center; }\n.note { margin-top: 10px; display: flex; align-items: flex-start; gap: 6px; font-size: 12px; }\n.note .icon { margin-top: 2px; }\n`\n"],"mappings":"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","names":["state"]}
|