@tempoxyz/id 0.0.0-pr-748.sha-9ca4b35 → 0.0.0-pr-670.sha-e9b244c
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/{Connections-XQEOD6XM.js → Connections-4J63W3O3.js} +3 -3
- package/dist/Server-GHH2TOPL.js +335 -0
- package/dist/{Sheet-PXWIG5RT.js → Sheet-D644QHD6.js} +2 -1
- package/dist/{chunk-AUGJ5ANC.js → chunk-2BJJYAAI.js} +1596 -4147
- package/dist/{chunk-YW5DUQT3.js → chunk-HWONYWNC.js} +2 -0
- package/dist/chunk-MLMRZMAK.js +908 -0
- package/dist/chunk-OR4H7ZKK.js +933 -0
- package/dist/{chunk-HGF2MYA7.js → chunk-QL7UYVGP.js} +76 -12
- package/dist/chunk-RXFSIUSG.js +1055 -0
- package/dist/commands/login.js +6 -4
- package/dist/commands/logout.js +6 -4
- package/dist/commands/whoami.js +6 -4
- package/dist/{dialog-4H576QJI.js → dialog-CPAB7R2I.js} +42 -14
- package/package.json +2 -2
- package/dist/Server-AR57IJGR.js +0 -22
- package/dist/chunk-ACADGOSV.js +0 -200
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
name,
|
|
5
5
|
parseName,
|
|
6
6
|
pending
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-QL7UYVGP.js";
|
|
8
|
+
import "./chunk-HWONYWNC.js";
|
|
9
|
+
import "./chunk-2BJJYAAI.js";
|
|
10
10
|
import "./chunk-MLKGABMK.js";
|
|
11
11
|
export {
|
|
12
12
|
attach,
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import {
|
|
2
|
+
basePath,
|
|
3
|
+
from
|
|
4
|
+
} from "./chunk-HWONYWNC.js";
|
|
5
|
+
import {
|
|
6
|
+
PendingNotFoundError,
|
|
7
|
+
RequestError
|
|
8
|
+
} from "./chunk-2BJJYAAI.js";
|
|
9
|
+
import "./chunk-MLKGABMK.js";
|
|
10
|
+
|
|
11
|
+
// ../../accounts/src/internal/BackendCookie.ts
|
|
12
|
+
var names = {
|
|
13
|
+
/** Present while a sign-in that the dialog started is in progress, for 10 minutes. */
|
|
14
|
+
dialog: "__Host-tempo-id.dialog",
|
|
15
|
+
/** The session ID of a sign-in in progress, for 10 minutes. */
|
|
16
|
+
pending: "__Host-tempo-id.pending",
|
|
17
|
+
/** The app's path to return to after the sign-in, for 10 minutes. */
|
|
18
|
+
return: "__Host-tempo-id.return",
|
|
19
|
+
/** The session ID. */
|
|
20
|
+
session: "__Host-tempo-id.sid"
|
|
21
|
+
};
|
|
22
|
+
function get(request, options) {
|
|
23
|
+
const header = request.headers.get("cookie");
|
|
24
|
+
if (!header) return void 0;
|
|
25
|
+
for (const part of header.split(";")) {
|
|
26
|
+
const index = part.indexOf("=");
|
|
27
|
+
if (index < 0) continue;
|
|
28
|
+
if (part.slice(0, index).trim() !== options.name) continue;
|
|
29
|
+
const value = part.slice(index + 1).trim();
|
|
30
|
+
return value || void 0;
|
|
31
|
+
}
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
function serialize(options) {
|
|
35
|
+
const { maxAge, name, value } = options;
|
|
36
|
+
const attributes = ["Path=/", "HttpOnly", "Secure", "SameSite=Lax"];
|
|
37
|
+
if (value === void 0) attributes.push("Max-Age=0");
|
|
38
|
+
else if (maxAge !== void 0) attributes.push(`Max-Age=${maxAge}`);
|
|
39
|
+
return [`${name}=${value ?? ""}`, ...attributes].join("; ");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ../../accounts/src/internal/handlers/Backend.ts
|
|
43
|
+
var pendingMaxAge = 10 * 60;
|
|
44
|
+
var relayScript = `(() => {
|
|
45
|
+
const url = new URL(location.href)
|
|
46
|
+
const state = url.searchParams.getAll('state').at(-1)
|
|
47
|
+
if (state) {
|
|
48
|
+
const channel = new BroadcastChannel('tempo-id:dialog:' + state)
|
|
49
|
+
channel.postMessage({ url: url.href })
|
|
50
|
+
channel.close()
|
|
51
|
+
}
|
|
52
|
+
window.close()
|
|
53
|
+
})()`;
|
|
54
|
+
function create(options) {
|
|
55
|
+
const { backend } = options;
|
|
56
|
+
const base = (options.basePath ?? "").replace(/\/+$/, "");
|
|
57
|
+
function redirectUri(request) {
|
|
58
|
+
return options.redirectUri ?? `${new URL(request.url).origin}${base}/callback`;
|
|
59
|
+
}
|
|
60
|
+
async function login(request) {
|
|
61
|
+
const url = new URL(request.url);
|
|
62
|
+
const { id, url: location } = await backend.start({
|
|
63
|
+
redirectUri: redirectUri(request)
|
|
64
|
+
});
|
|
65
|
+
const headers = new Headers({ location });
|
|
66
|
+
headers.append(
|
|
67
|
+
"set-cookie",
|
|
68
|
+
serialize({
|
|
69
|
+
maxAge: pendingMaxAge,
|
|
70
|
+
name: names.pending,
|
|
71
|
+
value: id
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
headers.append(
|
|
75
|
+
"set-cookie",
|
|
76
|
+
serialize({
|
|
77
|
+
maxAge: pendingMaxAge,
|
|
78
|
+
name: names.return,
|
|
79
|
+
value: encodeURIComponent(
|
|
80
|
+
returnTo(url.searchParams.get("returnTo"), { origin: url.origin })
|
|
81
|
+
)
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
headers.append(
|
|
85
|
+
"set-cookie",
|
|
86
|
+
serialize({ name: names.dialog })
|
|
87
|
+
);
|
|
88
|
+
return new Response(null, { headers, status: 302 });
|
|
89
|
+
}
|
|
90
|
+
async function dialogLogin(request) {
|
|
91
|
+
const refusal = foreign(request);
|
|
92
|
+
if (refusal) return refusal;
|
|
93
|
+
const { id, url } = await backend.start({
|
|
94
|
+
display: "popup",
|
|
95
|
+
par: false,
|
|
96
|
+
redirectUri: redirectUri(request)
|
|
97
|
+
});
|
|
98
|
+
const headers = new Headers({ "cache-control": "no-store" });
|
|
99
|
+
headers.append(
|
|
100
|
+
"set-cookie",
|
|
101
|
+
serialize({
|
|
102
|
+
maxAge: pendingMaxAge,
|
|
103
|
+
name: names.pending,
|
|
104
|
+
value: id
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
headers.append(
|
|
108
|
+
"set-cookie",
|
|
109
|
+
serialize({
|
|
110
|
+
maxAge: pendingMaxAge,
|
|
111
|
+
name: names.dialog,
|
|
112
|
+
value: "1"
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
return Response.json({ url }, { headers });
|
|
116
|
+
}
|
|
117
|
+
async function callback(request) {
|
|
118
|
+
if (get(request, { name: names.dialog }))
|
|
119
|
+
return relay();
|
|
120
|
+
const url = new URL(request.url);
|
|
121
|
+
const path = returnTo(
|
|
122
|
+
decode(get(request, { name: names.return })),
|
|
123
|
+
{ origin: url.origin }
|
|
124
|
+
);
|
|
125
|
+
const headers = cleared();
|
|
126
|
+
const result = await complete(request, { url: request.url });
|
|
127
|
+
if ("error" in result) {
|
|
128
|
+
headers.set(
|
|
129
|
+
"location",
|
|
130
|
+
withError(path, { error: result.error, origin: url.origin })
|
|
131
|
+
);
|
|
132
|
+
return new Response(null, { headers, status: 302 });
|
|
133
|
+
}
|
|
134
|
+
headers.set("location", path);
|
|
135
|
+
headers.append(
|
|
136
|
+
"set-cookie",
|
|
137
|
+
serialize({
|
|
138
|
+
name: names.session,
|
|
139
|
+
value: result.id
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
return new Response(null, { headers, status: 302 });
|
|
143
|
+
}
|
|
144
|
+
async function dialogCallback(request) {
|
|
145
|
+
const refusal = foreign(request);
|
|
146
|
+
if (refusal) return refusal;
|
|
147
|
+
const body = await request.json().catch(() => void 0);
|
|
148
|
+
const url = typeof body?.url === "string" ? URL.parse(body.url) : null;
|
|
149
|
+
if (!url)
|
|
150
|
+
return Response.json(
|
|
151
|
+
{
|
|
152
|
+
error: "invalid_request",
|
|
153
|
+
error_description: "Invalid body: `url` is not a URL. Send the callback URL of the sign-in as `url`."
|
|
154
|
+
},
|
|
155
|
+
{ status: 400 }
|
|
156
|
+
);
|
|
157
|
+
const headers = cleared();
|
|
158
|
+
const result = await complete(request, { url: url.href });
|
|
159
|
+
if ("error" in result)
|
|
160
|
+
return Response.json({ error: result.error }, { headers, status: 400 });
|
|
161
|
+
headers.append(
|
|
162
|
+
"set-cookie",
|
|
163
|
+
serialize({
|
|
164
|
+
name: names.session,
|
|
165
|
+
value: result.id
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
return Response.json({ session: pageSession(result.session) }, { headers });
|
|
169
|
+
}
|
|
170
|
+
async function complete(request, options2) {
|
|
171
|
+
const id = get(request, { name: names.pending });
|
|
172
|
+
if (!id) return { error: "invalid_request" };
|
|
173
|
+
const session2 = await (async () => {
|
|
174
|
+
try {
|
|
175
|
+
return await backend.complete({ id, url: options2.url });
|
|
176
|
+
} catch (error) {
|
|
177
|
+
if (error instanceof PendingNotFoundError) return "invalid_request";
|
|
178
|
+
if (error instanceof RequestError) return error.code;
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
})();
|
|
182
|
+
if (typeof session2 === "string") return { error: session2 };
|
|
183
|
+
const previous = get(request, {
|
|
184
|
+
name: names.session
|
|
185
|
+
});
|
|
186
|
+
if (previous && previous !== id)
|
|
187
|
+
await backend.end({ id: previous }).catch(() => void 0);
|
|
188
|
+
return { id, session: session2 };
|
|
189
|
+
}
|
|
190
|
+
async function logout(request) {
|
|
191
|
+
const refusal = foreign(request);
|
|
192
|
+
if (refusal) return refusal;
|
|
193
|
+
const id = get(request, { name: names.session });
|
|
194
|
+
const headers = new Headers({
|
|
195
|
+
"set-cookie": serialize({
|
|
196
|
+
name: names.session
|
|
197
|
+
})
|
|
198
|
+
});
|
|
199
|
+
const ended = id ? await backend.end({ id }).then(
|
|
200
|
+
() => true,
|
|
201
|
+
() => false
|
|
202
|
+
) : true;
|
|
203
|
+
if (!ended)
|
|
204
|
+
return Response.json(
|
|
205
|
+
{ error: "temporarily_unavailable" },
|
|
206
|
+
{ headers, status: 503 }
|
|
207
|
+
);
|
|
208
|
+
return new Response(null, { headers, status: 204 });
|
|
209
|
+
}
|
|
210
|
+
async function session(request) {
|
|
211
|
+
const id = get(request, { name: names.session });
|
|
212
|
+
const current = id ? await backend.get({ id }) : void 0;
|
|
213
|
+
const headers = new Headers({ "cache-control": "no-store" });
|
|
214
|
+
if (id && !current)
|
|
215
|
+
headers.set(
|
|
216
|
+
"set-cookie",
|
|
217
|
+
serialize({ name: names.session })
|
|
218
|
+
);
|
|
219
|
+
return Response.json(
|
|
220
|
+
{ session: current ? pageSession(current) : null },
|
|
221
|
+
{ headers }
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
const routes = {
|
|
225
|
+
[`${base}/callback`]: { GET: callback, POST: dialogCallback },
|
|
226
|
+
[`${base}/login`]: { GET: login, POST: dialogLogin },
|
|
227
|
+
[`${base}/logout`]: { POST: logout },
|
|
228
|
+
[`${base}/session`]: { GET: session }
|
|
229
|
+
};
|
|
230
|
+
return from({
|
|
231
|
+
async fetch(request) {
|
|
232
|
+
const route = routes[new URL(request.url).pathname];
|
|
233
|
+
if (!route) return Response.json({ error: "not_found" }, { status: 404 });
|
|
234
|
+
const fn = route[request.method];
|
|
235
|
+
if (!fn)
|
|
236
|
+
return Response.json(
|
|
237
|
+
{ error: "method_not_allowed" },
|
|
238
|
+
{ headers: { allow: Object.keys(route).join(", ") }, status: 405 }
|
|
239
|
+
);
|
|
240
|
+
return fn(request);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function cleared() {
|
|
245
|
+
const headers = new Headers({ "cache-control": "no-store" });
|
|
246
|
+
for (const name of [
|
|
247
|
+
names.dialog,
|
|
248
|
+
names.pending,
|
|
249
|
+
names.return
|
|
250
|
+
])
|
|
251
|
+
headers.append("set-cookie", serialize({ name }));
|
|
252
|
+
return headers;
|
|
253
|
+
}
|
|
254
|
+
function decode(value) {
|
|
255
|
+
if (value === void 0) return void 0;
|
|
256
|
+
try {
|
|
257
|
+
return decodeURIComponent(value);
|
|
258
|
+
} catch {
|
|
259
|
+
return void 0;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function foreign(request) {
|
|
263
|
+
if (request.headers.get("origin") === new URL(request.url).origin)
|
|
264
|
+
return void 0;
|
|
265
|
+
return Response.json(
|
|
266
|
+
{
|
|
267
|
+
error: "forbidden",
|
|
268
|
+
error_description: "Invalid origin: only a request from the app\u2019s own origin can call this route. Send the request from the app\u2019s page."
|
|
269
|
+
},
|
|
270
|
+
{ status: 403 }
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
function pageSession(session) {
|
|
274
|
+
return { account: session.key?.account ?? null, user: session.user };
|
|
275
|
+
}
|
|
276
|
+
function relay() {
|
|
277
|
+
const nonce = crypto.randomUUID();
|
|
278
|
+
return new Response(
|
|
279
|
+
`<!doctype html><meta charset="utf-8"><title>Sign-in</title><p>Return to the app\u2019s window to continue.</p><script nonce="${nonce}">${relayScript}</script>`,
|
|
280
|
+
{
|
|
281
|
+
headers: {
|
|
282
|
+
"cache-control": "no-store",
|
|
283
|
+
"content-security-policy": `default-src 'none'; script-src 'nonce-${nonce}'`,
|
|
284
|
+
"content-type": "text/html; charset=utf-8",
|
|
285
|
+
"referrer-policy": "no-referrer"
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
function returnTo(value, options) {
|
|
291
|
+
if (!value?.startsWith("/")) return "/";
|
|
292
|
+
const url = (() => {
|
|
293
|
+
try {
|
|
294
|
+
return new URL(value, options.origin);
|
|
295
|
+
} catch {
|
|
296
|
+
return void 0;
|
|
297
|
+
}
|
|
298
|
+
})();
|
|
299
|
+
if (url?.origin !== options.origin) return "/";
|
|
300
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
301
|
+
}
|
|
302
|
+
function withError(path, options) {
|
|
303
|
+
const url = new URL(path, options.origin);
|
|
304
|
+
url.searchParams.set("error", options.error);
|
|
305
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ../../accounts/src/internal/handlers/Server.ts
|
|
309
|
+
function create2(options) {
|
|
310
|
+
const { accessKeys, relay: relay2 } = options;
|
|
311
|
+
const base = (options.basePath ?? basePath).replace(/\/+$/, "");
|
|
312
|
+
const backend = options.backend ? create({
|
|
313
|
+
backend: options.backend,
|
|
314
|
+
basePath: base,
|
|
315
|
+
redirectUri: options.redirectUri
|
|
316
|
+
}) : void 0;
|
|
317
|
+
const backendPaths = new Set(
|
|
318
|
+
["/callback", "/login", "/logout", "/session"].map(
|
|
319
|
+
(path) => `${base}${path}`
|
|
320
|
+
)
|
|
321
|
+
);
|
|
322
|
+
return from({
|
|
323
|
+
async fetch(request) {
|
|
324
|
+
const { pathname } = new URL(request.url);
|
|
325
|
+
if (accessKeys && pathname === `${base}/access-keys`)
|
|
326
|
+
return (await accessKeys()).fetch(request);
|
|
327
|
+
if (backend && backendPaths.has(pathname)) return backend.fetch(request);
|
|
328
|
+
if (relay2 && pathname === `${base}/relay`) return relay2().fetch(request);
|
|
329
|
+
return Response.json({ error: "not_found" }, { status: 404 });
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
export {
|
|
334
|
+
create2 as create
|
|
335
|
+
};
|