@8ux-co/eelzap 0.0.0-stage → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +207 -0
- package/LICENSE +21 -0
- package/README.md +1121 -2
- package/dist/chunk-6XHCA4U4.js +80 -0
- package/dist/chunk-6XHCA4U4.js.map +1 -0
- package/dist/chunk-7CXQK2PR.js +1230 -0
- package/dist/chunk-7CXQK2PR.js.map +1 -0
- package/dist/chunk-7ZPXZZUT.js +452 -0
- package/dist/chunk-7ZPXZZUT.js.map +1 -0
- package/dist/fields.cjs +132 -0
- package/dist/fields.cjs.map +1 -0
- package/dist/fields.d.cts +116 -0
- package/dist/fields.d.ts +116 -0
- package/dist/fields.js +105 -0
- package/dist/fields.js.map +1 -0
- package/dist/index.cjs +2148 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2516 -0
- package/dist/index.d.ts +2516 -0
- package/dist/index.js +2091 -0
- package/dist/index.js.map +1 -0
- package/dist/next.d.ts +287 -0
- package/dist/next.js +214 -0
- package/dist/next.js.map +1 -0
- package/dist/preview.d.ts +980 -0
- package/dist/preview.js +941 -0
- package/dist/preview.js.map +1 -0
- package/dist/react.d.ts +181 -0
- package/dist/react.js +225 -0
- package/dist/react.js.map +1 -0
- package/dist/signin-QT7YANBN.js +208 -0
- package/dist/signin-QT7YANBN.js.map +1 -0
- package/dist/suggest-JZ63L3WP.js +2191 -0
- package/dist/suggest-JZ63L3WP.js.map +1 -0
- package/package.json +109 -4
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
5
|
+
// src/preview/site/config.ts
|
|
6
|
+
var NEST_PRODUCTION_ORIGIN = "https://auth.eel.software";
|
|
7
|
+
var SITE_CLIENT_SCOPE = "zap:suggest:write";
|
|
8
|
+
var SIGNIN_CHANNEL = "eel-zap";
|
|
9
|
+
var STATE_PREFIX = "zap1.";
|
|
10
|
+
var TOKEN_STORAGE_KEY = "eelzap:site-token";
|
|
11
|
+
var PENDING_STORAGE_KEY = "eelzap:signin";
|
|
12
|
+
function siteClientId(zapOrigin, siteId) {
|
|
13
|
+
return `${zapOrigin}/oauth/clients/${siteId.toLowerCase()}.json`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/preview/site/token.ts
|
|
17
|
+
var EXPIRY_MARGIN_MS = 3e4;
|
|
18
|
+
var REFRESH_LIFETIME_MS = 8 * 60 * 60 * 1e3;
|
|
19
|
+
function store(win) {
|
|
20
|
+
try {
|
|
21
|
+
return win.sessionStorage;
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function parse(raw, siteId) {
|
|
27
|
+
if (!raw) return null;
|
|
28
|
+
const value = JSON.parse(raw);
|
|
29
|
+
if (typeof value.token !== "string" || !value.token.startsWith("eel_at_") || typeof value.exp !== "number" || value.site !== siteId) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const refresh = typeof value.refresh === "string" && value.refresh.startsWith("eel_rt_") && typeof value.rexp === "number" ? { refresh: value.refresh, rexp: value.rexp } : {};
|
|
33
|
+
return { token: value.token, exp: value.exp, site: value.site, ...refresh };
|
|
34
|
+
}
|
|
35
|
+
function accessLive(value, now = Date.now()) {
|
|
36
|
+
return value.exp - EXPIRY_MARGIN_MS > now;
|
|
37
|
+
}
|
|
38
|
+
function refreshLive(value, now = Date.now()) {
|
|
39
|
+
return !!value.refresh && typeof value.rexp === "number" && value.rexp > now;
|
|
40
|
+
}
|
|
41
|
+
function readSession(win, siteId, now = Date.now()) {
|
|
42
|
+
const storage = store(win);
|
|
43
|
+
try {
|
|
44
|
+
const value = parse(storage?.getItem(TOKEN_STORAGE_KEY), siteId);
|
|
45
|
+
if (value && (accessLive(value, now) || refreshLive(value, now))) return value;
|
|
46
|
+
storage?.removeItem(TOKEN_STORAGE_KEY);
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function writeToken(win, value) {
|
|
52
|
+
try {
|
|
53
|
+
store(win)?.setItem(TOKEN_STORAGE_KEY, JSON.stringify(value));
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function clearToken(win) {
|
|
58
|
+
try {
|
|
59
|
+
store(win)?.removeItem(TOKEN_STORAGE_KEY);
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export {
|
|
65
|
+
__publicField,
|
|
66
|
+
NEST_PRODUCTION_ORIGIN,
|
|
67
|
+
SITE_CLIENT_SCOPE,
|
|
68
|
+
SIGNIN_CHANNEL,
|
|
69
|
+
STATE_PREFIX,
|
|
70
|
+
PENDING_STORAGE_KEY,
|
|
71
|
+
siteClientId,
|
|
72
|
+
EXPIRY_MARGIN_MS,
|
|
73
|
+
REFRESH_LIFETIME_MS,
|
|
74
|
+
accessLive,
|
|
75
|
+
refreshLive,
|
|
76
|
+
readSession,
|
|
77
|
+
writeToken,
|
|
78
|
+
clearToken
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=chunk-6XHCA4U4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preview/site/config.ts","../src/preview/site/token.ts"],"sourcesContent":["/**\n * «Editar» and «Comentar» on the customer's site (zap-cms-v2 §3.4, ADR 041):\n * the constants and the context the core hands its two lazy chunks.\n *\n * Three pieces, so an ordinary visitor downloads nothing beyond the core:\n *\n * - the core (`boot.ts`, in the `./preview` budget): the opt-in trigger\n * (`?zap` in the URL, or Shift Z), the OAuth callback relay on `{origin}/`,\n * and the loader;\n * - `signin` (loaded only on the trigger): the launcher, «Entrar con Eel», PKCE,\n * the popup or full-page redirect and the code exchange at Nest;\n * - `suggest` (loaded only after sign-in; the name is the file's, kept): the\n * toolbar, Navegar, Editar and Comentar, the composer, the numbered pins\n * and the calls to Zap.\n *\n * No directive, no imports: pure values both chunks and the core share.\n */\n\n/** Nest, the suite's OAuth issuer (ADR 024). Compiled in; `authOrigin` is the dev opt-in. */\nexport const NEST_PRODUCTION_ORIGIN = 'https://auth.eel.software'\n\n/**\n * The scope a site client asks for, by name (ADR 041 §2). `zap:preview:read`\n * is not asked for until a «Ver borradores» feature needs it (Manager,\n * 2026-10-05); Nest would drop it anyway.\n */\nexport const SITE_CLIENT_SCOPE = 'zap:suggest:write'\n\n/** The popup hands the code to the opener tab over this channel (same origin). */\nexport const SIGNIN_CHANNEL = 'eel-zap'\n\n/** Every `state` this client mints starts with it, so a site's own `?code=` is never ours. */\nexport const STATE_PREFIX = 'zap1.'\n\n/** sessionStorage only (ADR 041 §7): the token, and a pending full-page sign-in. */\nexport const TOKEN_STORAGE_KEY = 'eelzap:site-token'\nexport const PENDING_STORAGE_KEY = 'eelzap:signin'\n\nexport type ChunkName = 'signin' | 'suggest'\n\n/** What a callback page carries back from Nest (`{origin}/?code&state&iss`). */\nexport interface CallbackParams {\n code: string\n state: string\n iss: string\n}\n\nexport interface StartOptions {\n /**\n * signin: open the panel at once, and why (`expired` after a 401 or the\n * hour). suggest: `renewed` after a sign-in that followed an expiry, which\n * says «Sesión renovada» (board SitioRenovacion).\n */\n reason?: 'expired' | 'trigger' | 'renewed'\n /** signin: finish a full-page sign-in that landed on this page. */\n callback?: CallbackParams\n /**\n * signin: start signing in at once, as if «Entrar con Eel» was pressed.\n * Passed by «Volver a entrar» (the bar's expired state), inside its click, so\n * the popup is still allowed.\n */\n signIn?: boolean\n}\n\nexport interface ChunkHandle {\n destroy(): void\n}\n\nexport interface ChunkModule {\n start(ctx: SiteContext, options?: StartOptions): ChunkHandle\n}\n\n/** Everything a chunk needs, decided once by the core. */\nexport interface SiteContext {\n win: Window\n doc: Document\n /** The Zap site's id (`data-site-id`); names its OAuth client. */\n siteId: string\n /** Where Zap's API and the client's CIMD document live. */\n zapOrigin: string\n /** Nest, the issuer: `/oauth/authorize`, `/api/oauth/token`, and the `iss` to expect. */\n authOrigin: string\n /** `{zapOrigin}/oauth/clients/{siteId}.json` (ADR 041 §1). */\n clientId: string\n /** `{page origin}/`, exactly as the CIMD document lists it. */\n redirectUri: string\n locale: 'es' | 'en'\n /** The letter pressed with Shift to open the tools, for the launcher's hint; false when off. */\n shortcut: string | false\n /**\n * The site's draft-mode route (`/api/zap-preview` by default), as the page\n * announced it: «Editar» enters draft mode through it on an untagged page\n * (`draft-session.ts`). Null or absent when the site has none.\n */\n draftRoute?: string | null\n /** Replace whatever chunk is showing with `name`. */\n open(name: ChunkName, options?: StartOptions): Promise<void>\n /** Close the showing chunk; the trigger works again. */\n close(): void\n}\n\n/** The client id of one site, the same string `@eel/api-keys` `zapSiteClientId` builds. */\nexport function siteClientId(zapOrigin: string, siteId: string): string {\n return `${zapOrigin}/oauth/clients/${siteId.toLowerCase()}.json`\n}\n","import { TOKEN_STORAGE_KEY } from './config'\n\n/**\n * The site client's tokens (ADR 041 §7): in memory and in `sessionStorage`,\n * never in `localStorage` or a cookie. The access token lives one hour. Since\n * ADR 041's amendment of 2026-10-06 it comes with a short refresh token (eight\n * hours, rotating, redeemable only inside the person's remembered consent and\n * from this origin), which `session.ts` spends to renew the hour without a\n * sign-in; when that fails the person signs in again.\n *\n * Stored with the expiries and the site it was issued for: a token for another\n * site, a malformed entry, or one whose access AND refresh are both spent reads\n * as nothing and is removed.\n */\n\nexport interface SiteToken {\n /** The `eel_at_` access token. */\n token: string\n /** Epoch ms when it stops working. */\n exp: number\n /** The site it was issued for. */\n site: string\n /** The `eel_rt_` refresh token, when Nest issued one. */\n refresh?: string\n /** Epoch ms after which the refresh token is not worth trying. */\n rexp?: number\n}\n\n/** How long before the real expiry we stop using a token, so a call never races it. */\nexport const EXPIRY_MARGIN_MS = 30_000\n\n/** A refresh token lives eight hours at Nest (ADR 041 amendment 2026-10-06). */\nexport const REFRESH_LIFETIME_MS = 8 * 60 * 60 * 1000\n\nfunction store(win: Window): Storage | null {\n try {\n return win.sessionStorage\n } catch {\n return null\n }\n}\n\nfunction parse(raw: string | null | undefined, siteId: string): SiteToken | null {\n if (!raw) return null\n const value = JSON.parse(raw) as Partial<SiteToken>\n if (\n typeof value.token !== 'string' ||\n !value.token.startsWith('eel_at_') ||\n typeof value.exp !== 'number' ||\n value.site !== siteId\n ) {\n return null\n }\n const refresh =\n typeof value.refresh === 'string' &&\n value.refresh.startsWith('eel_rt_') &&\n typeof value.rexp === 'number'\n ? { refresh: value.refresh, rexp: value.rexp }\n : {}\n return { token: value.token, exp: value.exp, site: value.site, ...refresh }\n}\n\n/** True while the access token is still worth sending. */\nexport function accessLive(value: SiteToken, now = Date.now()): boolean {\n return value.exp - EXPIRY_MARGIN_MS > now\n}\n\n/** True while the refresh token is still worth trying. */\nexport function refreshLive(value: SiteToken, now = Date.now()): boolean {\n return !!value.refresh && typeof value.rexp === 'number' && value.rexp > now\n}\n\n/**\n * The stored session while it can still act: a live access token, or a\n * refresh token that may renew it (`session.ts` does). Anything else is\n * removed and reads as null.\n */\nexport function readSession(win: Window, siteId: string, now = Date.now()): SiteToken | null {\n const storage = store(win)\n try {\n const value = parse(storage?.getItem(TOKEN_STORAGE_KEY), siteId)\n if (value && (accessLive(value, now) || refreshLive(value, now))) return value\n storage?.removeItem(TOKEN_STORAGE_KEY)\n } catch {\n // Unreadable entry or blocked storage: no token.\n }\n return null\n}\n\n/** The stored session only while its ACCESS token is live (no renewal needed). */\nexport function readToken(win: Window, siteId: string, now = Date.now()): SiteToken | null {\n const value = readSession(win, siteId, now)\n return value && accessLive(value, now) ? value : null\n}\n\nexport function writeToken(win: Window, value: SiteToken): void {\n try {\n store(win)?.setItem(TOKEN_STORAGE_KEY, JSON.stringify(value))\n } catch {\n // Blocked storage: the token lives in memory for this page only.\n }\n}\n\nexport function clearToken(win: Window): void {\n try {\n store(win)?.removeItem(TOKEN_STORAGE_KEY)\n } catch {\n // Nothing to clear.\n }\n}\n"],"mappings":";;;;;AAmBO,IAAM,yBAAyB;AAO/B,IAAM,oBAAoB;AAG1B,IAAM,iBAAiB;AAGvB,IAAM,eAAe;AAGrB,IAAM,oBAAoB;AAC1B,IAAM,sBAAsB;AAkE5B,SAAS,aAAa,WAAmB,QAAwB;AACtE,SAAO,GAAG,SAAS,kBAAkB,OAAO,YAAY,CAAC;AAC3D;;;AC3EO,IAAM,mBAAmB;AAGzB,IAAM,sBAAsB,IAAI,KAAK,KAAK;AAEjD,SAAS,MAAM,KAA6B;AAC1C,MAAI;AACF,WAAO,IAAI;AAAA,EACb,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,MAAM,KAAgC,QAAkC;AAC/E,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MACE,OAAO,MAAM,UAAU,YACvB,CAAC,MAAM,MAAM,WAAW,SAAS,KACjC,OAAO,MAAM,QAAQ,YACrB,MAAM,SAAS,QACf;AACA,WAAO;AAAA,EACT;AACA,QAAM,UACJ,OAAO,MAAM,YAAY,YACzB,MAAM,QAAQ,WAAW,SAAS,KAClC,OAAO,MAAM,SAAS,WAClB,EAAE,SAAS,MAAM,SAAS,MAAM,MAAM,KAAK,IAC3C,CAAC;AACP,SAAO,EAAE,OAAO,MAAM,OAAO,KAAK,MAAM,KAAK,MAAM,MAAM,MAAM,GAAG,QAAQ;AAC5E;AAGO,SAAS,WAAW,OAAkB,MAAM,KAAK,IAAI,GAAY;AACtE,SAAO,MAAM,MAAM,mBAAmB;AACxC;AAGO,SAAS,YAAY,OAAkB,MAAM,KAAK,IAAI,GAAY;AACvE,SAAO,CAAC,CAAC,MAAM,WAAW,OAAO,MAAM,SAAS,YAAY,MAAM,OAAO;AAC3E;AAOO,SAAS,YAAY,KAAa,QAAgB,MAAM,KAAK,IAAI,GAAqB;AAC3F,QAAM,UAAU,MAAM,GAAG;AACzB,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,QAAQ,iBAAiB,GAAG,MAAM;AAC/D,QAAI,UAAU,WAAW,OAAO,GAAG,KAAK,YAAY,OAAO,GAAG,GAAI,QAAO;AACzE,aAAS,WAAW,iBAAiB;AAAA,EACvC,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAQO,SAAS,WAAW,KAAa,OAAwB;AAC9D,MAAI;AACF,UAAM,GAAG,GAAG,QAAQ,mBAAmB,KAAK,UAAU,KAAK,CAAC;AAAA,EAC9D,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,WAAW,KAAmB;AAC5C,MAAI;AACF,UAAM,GAAG,GAAG,WAAW,iBAAiB;AAAA,EAC1C,QAAQ;AAAA,EAER;AACF;","names":[]}
|