@segmentstream-cloud/app 0.16.3 → 0.16.4
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/oauth-completion.js +58 -9
- package/package.json +1 -1
package/dist/oauth-completion.js
CHANGED
|
@@ -8,6 +8,52 @@ function escape(value) {
|
|
|
8
8
|
"'": "'",
|
|
9
9
|
})[character]);
|
|
10
10
|
}
|
|
11
|
+
// The shadcn/ui tokens and Card, Input and Button styles of the workspace app template, inlined so
|
|
12
|
+
// the page needs no external stylesheet under its strict CSP.
|
|
13
|
+
const STYLE = `
|
|
14
|
+
:root{color-scheme:light;--radius:0.625rem;--background:oklch(1 0 0);--foreground:oklch(0.145 0 0);
|
|
15
|
+
--card:oklch(1 0 0);--primary:oklch(0.205 0 0);--primary-foreground:oklch(0.985 0 0);
|
|
16
|
+
--muted:oklch(0.97 0 0);--muted-foreground:oklch(0.556 0 0);--accent:oklch(0.97 0 0);
|
|
17
|
+
--border:oklch(0.922 0 0);--input:oklch(0.922 0 0);--ring:oklch(0.708 0 0);--field:transparent;
|
|
18
|
+
--outline:var(--background);--outline-hover:var(--accent);--logo:none}
|
|
19
|
+
@media (prefers-color-scheme:dark){:root{color-scheme:dark;--background:oklch(0.145 0 0);
|
|
20
|
+
--foreground:oklch(0.985 0 0);--card:oklch(0.205 0 0);--primary:oklch(0.922 0 0);
|
|
21
|
+
--primary-foreground:oklch(0.205 0 0);--muted:oklch(0.269 0 0);--muted-foreground:oklch(0.708 0 0);
|
|
22
|
+
--accent:oklch(0.269 0 0);--border:oklch(1 0 0 / 10%);--input:oklch(1 0 0 / 15%);
|
|
23
|
+
--ring:oklch(0.556 0 0);--field:oklch(1 0 0 / 4.5%);--outline:oklch(1 0 0 / 4.5%);
|
|
24
|
+
--outline-hover:oklch(1 0 0 / 7.5%);--logo:invert(1)}}
|
|
25
|
+
*{box-sizing:border-box}
|
|
26
|
+
body{margin:0;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
|
|
27
|
+
color:var(--foreground);background:color-mix(in oklab,var(--muted) 40%,var(--background));
|
|
28
|
+
-webkit-font-smoothing:antialiased}
|
|
29
|
+
main{min-height:100svh;max-width:calc(28rem + 3rem);margin:0 auto;padding:1.5rem;display:flex;
|
|
30
|
+
flex-direction:column;align-items:center;justify-content:center;gap:1.5rem}
|
|
31
|
+
main>img{filter:var(--logo);height:auto;max-width:100%}
|
|
32
|
+
.card{width:100%;display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem;
|
|
33
|
+
background:var(--card);border:1px solid var(--border);border-radius:calc(var(--radius) + 4px);
|
|
34
|
+
box-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1),0 1px 2px -1px rgb(0 0 0 / 0.1)}
|
|
35
|
+
header,.content{display:grid;gap:0.5rem}
|
|
36
|
+
h1{margin:0;font-size:1.25rem;line-height:1.75rem;font-weight:600;letter-spacing:-0.025em}
|
|
37
|
+
p{margin:0}.muted{color:var(--muted-foreground);font-size:0.875rem;line-height:1.25rem}
|
|
38
|
+
.status:empty{display:none}.secured{font-size:0.75rem;line-height:1rem;text-align:center}
|
|
39
|
+
.field{display:flex;gap:0.5rem}
|
|
40
|
+
input{flex:1;min-width:0;height:2.25rem;padding:0 0.75rem;border:1px solid var(--input);
|
|
41
|
+
border-radius:calc(var(--radius) - 2px);background:var(--field);color:inherit;
|
|
42
|
+
font:0.875rem/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;letter-spacing:0.025em;
|
|
43
|
+
box-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);outline:none}
|
|
44
|
+
.button{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;height:2.25rem;
|
|
45
|
+
padding:0 1rem;border:1px solid transparent;border-radius:calc(var(--radius) - 2px);
|
|
46
|
+
background:var(--primary);color:var(--primary-foreground);font-family:inherit;font-size:0.875rem;
|
|
47
|
+
font-weight:500;line-height:1.25rem;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;
|
|
48
|
+
transition:background-color .15s,box-shadow .15s}
|
|
49
|
+
.button:hover{background:color-mix(in oklab,var(--primary) 90%,transparent)}
|
|
50
|
+
.outline{background:var(--outline);color:var(--foreground);border-color:var(--input);
|
|
51
|
+
box-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05)}.outline:hover{background:var(--outline-hover)}
|
|
52
|
+
input:focus-visible,.button:focus-visible{border-color:var(--ring);
|
|
53
|
+
box-shadow:0 0 0 3px color-mix(in oklab,var(--ring) 50%,transparent)}
|
|
54
|
+
footer{display:flex;justify-content:flex-end}
|
|
55
|
+
@media (max-width:30rem){.field{flex-direction:column}input{flex:none}.button{width:100%}}
|
|
56
|
+
`;
|
|
11
57
|
/** Keep a copyable PKCE-bound code visible while trying the client's loopback callback. */
|
|
12
58
|
export function oauthCompletion(options) {
|
|
13
59
|
// Web Crypto keeps this module bundleable for client components (no node: imports).
|
|
@@ -16,12 +62,14 @@ export function oauthCompletion(options) {
|
|
|
16
62
|
const code = redirect === undefined ? null : new URL(redirect).searchParams.get("code");
|
|
17
63
|
const title = options.approved === false ? "Request denied" : "Authorization complete";
|
|
18
64
|
const manual = code === null
|
|
19
|
-
? "
|
|
20
|
-
:
|
|
21
|
-
<p>Return to your terminal. If it is still waiting, copy and paste this code:</p>
|
|
65
|
+
? `<header><h1>${title}</h1><p class="muted">You can return to your terminal.</p></header>`
|
|
66
|
+
: `<header><h1>${title}</h1>
|
|
67
|
+
<p class="muted">Return to your terminal. If it is still waiting, copy and paste this code:</p></header>
|
|
68
|
+
<div class="content"><div class="field">
|
|
22
69
|
<input id="code" aria-label="Authorization code" readonly value="${escape(code)}">
|
|
23
|
-
<button id="copy" type="button">Copy code</button
|
|
24
|
-
<p
|
|
70
|
+
<button id="copy" class="button" type="button">Copy code</button></div>
|
|
71
|
+
<p id="status" class="muted status" role="status"></p></div>
|
|
72
|
+
<footer><a class="button outline" href="${escape(redirect)}">Continue to the client</a></footer>`;
|
|
25
73
|
const script = code === null
|
|
26
74
|
? ""
|
|
27
75
|
: `
|
|
@@ -36,10 +84,11 @@ export function oauthCompletion(options) {
|
|
|
36
84
|
frame.src = ${JSON.stringify(redirect).replace(/</g, "\\u003c")}; document.body.appendChild(frame);`;
|
|
37
85
|
return new Response(`<!doctype html><html lang="en"><meta charset="utf-8">
|
|
38
86
|
<meta name="viewport" content="width=device-width, initial-scale=1"><title>${title}</title>
|
|
39
|
-
<style nonce="${nonce}">
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
<
|
|
87
|
+
<style nonce="${nonce}">${STYLE}</style>
|
|
88
|
+
<main><img src="${escape(SEGMENTSTREAM_LOGO_URI)}" alt="SegmentStream" width="210" height="45">
|
|
89
|
+
<section class="card">${manual}</section>
|
|
90
|
+
<p class="muted secured">Secured by SegmentStream</p></main>
|
|
91
|
+
<script nonce="${nonce}">${script}</script></html>`, {
|
|
43
92
|
headers: {
|
|
44
93
|
"content-type": "text/html; charset=utf-8",
|
|
45
94
|
"cache-control": "no-store",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@segmentstream-cloud/app",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.4",
|
|
4
4
|
"description": "Sign-in, users, permissions, the ontology client and warehouse data access for SegmentStream workspace apps built with Next.js.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "SegmentStream",
|