@stackframe/stack 2.7.25 → 2.7.27
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 +20 -0
- package/dist/components/elements/maybe-full-page.js +1 -0
- package/dist/components/elements/maybe-full-page.js.map +1 -1
- package/dist/components/link.js.map +1 -1
- package/dist/components-page/account-settings.js +127 -0
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/cli-auth-confirm.js +123 -0
- package/dist/components-page/cli-auth-confirm.js.map +1 -0
- package/dist/components-page/stack-handler.js +11 -0
- package/dist/components-page/stack-handler.js.map +1 -1
- package/dist/esm/components/elements/maybe-full-page.js +1 -0
- package/dist/esm/components/elements/maybe-full-page.js.map +1 -1
- package/dist/esm/components/link.js.map +1 -1
- package/dist/esm/components-page/account-settings.js +128 -1
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/cli-auth-confirm.js +99 -0
- package/dist/esm/components-page/cli-auth-confirm.js.map +1 -0
- package/dist/esm/components-page/stack-handler.js +11 -0
- package/dist/esm/components-page/stack-handler.js.map +1 -1
- package/dist/esm/generated/global-css.js +1 -1
- package/dist/esm/generated/global-css.js.map +1 -1
- package/dist/esm/lib/cookie.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +13 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +19 -0
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +9 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
- package/dist/esm/lib/stack-app/common.js.map +1 -1
- package/dist/esm/lib/stack-app/email/index.js +1 -0
- package/dist/esm/lib/stack-app/email/index.js.map +1 -0
- package/dist/esm/lib/stack-app/index.js.map +1 -1
- package/dist/esm/lib/stack-app/projects/index.js +2 -1
- package/dist/esm/lib/stack-app/projects/index.js.map +1 -1
- package/dist/esm/lib/stack-app/teams/index.js.map +1 -1
- package/dist/esm/lib/stack-app/users/index.js.map +1 -1
- package/dist/esm/lib/translations.js.map +1 -1
- package/dist/generated/global-css.js +1 -1
- package/dist/generated/global-css.js.map +1 -1
- package/dist/index.d.mts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/lib/cookie.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +13 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js +19 -0
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/common.js +1 -1
- package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js +9 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
- package/dist/lib/stack-app/common.js.map +1 -1
- package/dist/lib/stack-app/connected-accounts/index.js.map +1 -1
- package/dist/lib/stack-app/email/index.js +19 -0
- package/dist/lib/stack-app/email/index.js.map +1 -0
- package/dist/lib/stack-app/index.js.map +1 -1
- package/dist/lib/stack-app/project-configs/index.js.map +1 -1
- package/dist/lib/stack-app/projects/index.js +2 -1
- package/dist/lib/stack-app/projects/index.js.map +1 -1
- package/dist/lib/stack-app/teams/index.js.map +1 -1
- package/dist/lib/stack-app/users/index.js.map +1 -1
- package/dist/lib/translations.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
"use client";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/components-page/cli-auth-confirm.tsx
|
|
23
|
+
var cli_auth_confirm_exports = {};
|
|
24
|
+
__export(cli_auth_confirm_exports, {
|
|
25
|
+
CliAuthConfirmation: () => CliAuthConfirmation
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(cli_auth_confirm_exports);
|
|
28
|
+
var import_stack_ui = require("@stackframe/stack-ui");
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
var import__ = require("..");
|
|
31
|
+
var import_message_card = require("../components/message-cards/message-card");
|
|
32
|
+
var import_translations = require("../lib/translations");
|
|
33
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
34
|
+
function CliAuthConfirmation({ fullPage = true }) {
|
|
35
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
36
|
+
const app = (0, import__.useStackApp)();
|
|
37
|
+
const [authorizing, setAuthorizing] = (0, import_react.useState)(false);
|
|
38
|
+
const [success, setSuccess] = (0, import_react.useState)(false);
|
|
39
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
40
|
+
const user = app.useUser({ or: "redirect" });
|
|
41
|
+
const handleAuthorize = async () => {
|
|
42
|
+
if (authorizing) return;
|
|
43
|
+
setAuthorizing(true);
|
|
44
|
+
try {
|
|
45
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
46
|
+
const loginCode = urlParams.get("login_code");
|
|
47
|
+
if (!loginCode) {
|
|
48
|
+
throw new Error("Missing login code in URL parameters");
|
|
49
|
+
}
|
|
50
|
+
const refreshToken = (await user.currentSession.getTokens()).refreshToken;
|
|
51
|
+
if (!refreshToken) {
|
|
52
|
+
throw new Error("You must be logged in to authorize CLI access");
|
|
53
|
+
}
|
|
54
|
+
const result = await app[import__.stackAppInternalsSymbol].sendRequest("/auth/cli/complete", {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: {
|
|
57
|
+
"Content-Type": "application/json"
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
login_code: loginCode,
|
|
61
|
+
refresh_token: (await user.currentSession.getTokens()).refreshToken
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
if (!result.ok) {
|
|
65
|
+
throw new Error(`Authorization failed: ${result.status} ${await result.text()}`);
|
|
66
|
+
}
|
|
67
|
+
setSuccess(true);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
setError(err);
|
|
70
|
+
} finally {
|
|
71
|
+
setAuthorizing(false);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
if (success) {
|
|
75
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
76
|
+
import_message_card.MessageCard,
|
|
77
|
+
{
|
|
78
|
+
title: t("CLI Authorization Successful"),
|
|
79
|
+
fullPage,
|
|
80
|
+
primaryButtonText: t("Close"),
|
|
81
|
+
primaryAction: () => window.close(),
|
|
82
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("The CLI application has been authorized successfully. You can now close this window and return to the command line.") })
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (error) {
|
|
87
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
88
|
+
import_message_card.MessageCard,
|
|
89
|
+
{
|
|
90
|
+
title: t("Authorization Failed"),
|
|
91
|
+
fullPage,
|
|
92
|
+
primaryButtonText: t("Try Again"),
|
|
93
|
+
primaryAction: () => setError(null),
|
|
94
|
+
secondaryButtonText: t("Cancel"),
|
|
95
|
+
secondaryAction: () => window.close(),
|
|
96
|
+
children: [
|
|
97
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { className: "text-red-600", children: t("Failed to authorize the CLI application:") }),
|
|
98
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { className: "text-red-600", children: error.message })
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
104
|
+
import_message_card.MessageCard,
|
|
105
|
+
{
|
|
106
|
+
title: t("Authorize CLI Application"),
|
|
107
|
+
fullPage,
|
|
108
|
+
primaryButtonText: authorizing ? t("Authorizing...") : t("Authorize"),
|
|
109
|
+
primaryAction: handleAuthorize,
|
|
110
|
+
secondaryButtonText: t("Cancel"),
|
|
111
|
+
secondaryAction: () => window.close(),
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("A command line application is requesting access to your account. Click the button below to authorize it.") }),
|
|
114
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("WARNING: Make sure you trust the command line application, as it will gain access to your account. If you did not initiate this request, you can close this page and ignore it. We will never send you this link via email or any other means.") })
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
120
|
+
0 && (module.exports = {
|
|
121
|
+
CliAuthConfirmation
|
|
122
|
+
});
|
|
123
|
+
//# sourceMappingURL=cli-auth-confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components-page/cli-auth-confirm.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useState } from \"react\";\nimport { stackAppInternalsSymbol, useStackApp } from \"..\";\nimport { MessageCard } from \"../components/message-cards/message-card\";\nimport { useTranslation } from \"../lib/translations\";\n\nexport function CliAuthConfirmation({ fullPage = true }: { fullPage?: boolean }) {\n const { t } = useTranslation();\n const app = useStackApp();\n const [authorizing, setAuthorizing] = useState(false);\n const [success, setSuccess] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const user = app.useUser({ or: \"redirect\" });\n\n const handleAuthorize = async () => {\n if (authorizing) return;\n\n setAuthorizing(true);\n try {\n // Get login code from URL query parameters\n const urlParams = new URLSearchParams(window.location.search);\n const loginCode = urlParams.get(\"login_code\");\n\n if (!loginCode) {\n throw new Error(\"Missing login code in URL parameters\");\n }\n const refreshToken = (await user.currentSession.getTokens()).refreshToken;\n if (!refreshToken) {\n throw new Error(\"You must be logged in to authorize CLI access\");\n }\n\n // Use the internal API to send the CLI login request\n const result = await (app as any)[stackAppInternalsSymbol].sendRequest(\"/auth/cli/complete\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify({\n login_code: loginCode,\n refresh_token: (await user.currentSession.getTokens()).refreshToken\n })\n });\n\n if (!result.ok) {\n throw new Error(`Authorization failed: ${result.status} ${await result.text()}`);\n }\n\n setSuccess(true);\n } catch (err) {\n setError(err as Error);\n } finally {\n setAuthorizing(false);\n }\n };\n\n if (success) {\n return (\n <MessageCard\n title={t(\"CLI Authorization Successful\")}\n fullPage={fullPage}\n primaryButtonText={t(\"Close\")}\n primaryAction={() => window.close()}\n >\n <Typography>\n {t(\"The CLI application has been authorized successfully. You can now close this window and return to the command line.\")}\n </Typography>\n </MessageCard>\n );\n }\n\n if (error) {\n return (\n <MessageCard\n title={t(\"Authorization Failed\")}\n fullPage={fullPage}\n primaryButtonText={t(\"Try Again\")}\n primaryAction={() => setError(null)}\n secondaryButtonText={t(\"Cancel\")}\n secondaryAction={() => window.close()}\n >\n <Typography className=\"text-red-600\">\n {t(\"Failed to authorize the CLI application:\")}\n </Typography>\n <Typography className=\"text-red-600\">\n {error.message}\n </Typography>\n </MessageCard>\n );\n }\n\n return (\n <MessageCard\n title={t(\"Authorize CLI Application\")}\n fullPage={fullPage}\n primaryButtonText={authorizing ? t(\"Authorizing...\") : t(\"Authorize\")}\n primaryAction={handleAuthorize}\n secondaryButtonText={t(\"Cancel\")}\n secondaryAction={() => window.close()}\n >\n <Typography>\n {t(\"A command line application is requesting access to your account. Click the button below to authorize it.\")}\n </Typography>\n <Typography variant=\"destructive\">\n {t(\"WARNING: Make sure you trust the command line application, as it will gain access to your account. If you did not initiate this request, you can close this page and ignore it. We will never send you this link via email or any other means.\")}\n </Typography>\n </MessageCard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAA2B;AAC3B,mBAAyB;AACzB,eAAqD;AACrD,0BAA4B;AAC5B,0BAA+B;AA4DvB;AA1DD,SAAS,oBAAoB,EAAE,WAAW,KAAK,GAA2B;AAC/E,QAAM,EAAE,EAAE,QAAI,oCAAe;AAC7B,QAAM,UAAM,sBAAY;AACxB,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAS,KAAK;AACpD,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAuB,IAAI;AAErD,QAAM,OAAO,IAAI,QAAQ,EAAE,IAAI,WAAW,CAAC;AAE3C,QAAM,kBAAkB,YAAY;AAClC,QAAI,YAAa;AAEjB,mBAAe,IAAI;AACnB,QAAI;AAEF,YAAM,YAAY,IAAI,gBAAgB,OAAO,SAAS,MAAM;AAC5D,YAAM,YAAY,UAAU,IAAI,YAAY;AAE5C,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,sCAAsC;AAAA,MACxD;AACA,YAAM,gBAAgB,MAAM,KAAK,eAAe,UAAU,GAAG;AAC7D,UAAI,CAAC,cAAc;AACjB,cAAM,IAAI,MAAM,+CAA+C;AAAA,MACjE;AAGA,YAAM,SAAS,MAAO,IAAY,gCAAuB,EAAE,YAAY,sBAAsB;AAAA,QAC3F,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,YAAY;AAAA,UACZ,gBAAgB,MAAM,KAAK,eAAe,UAAU,GAAG;AAAA,QACzD,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,OAAO,IAAI;AACd,cAAM,IAAI,MAAM,yBAAyB,OAAO,MAAM,IAAI,MAAM,OAAO,KAAK,CAAC,EAAE;AAAA,MACjF;AAEA,iBAAW,IAAI;AAAA,IACjB,SAAS,KAAK;AACZ,eAAS,GAAY;AAAA,IACvB,UAAE;AACA,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,SAAS;AACX,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,8BAA8B;AAAA,QACvC;AAAA,QACA,mBAAmB,EAAE,OAAO;AAAA,QAC5B,eAAe,MAAM,OAAO,MAAM;AAAA,QAElC,sDAAC,8BACE,YAAE,qHAAqH,GAC1H;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,MAAI,OAAO;AACT,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,sBAAsB;AAAA,QAC/B;AAAA,QACA,mBAAmB,EAAE,WAAW;AAAA,QAChC,eAAe,MAAM,SAAS,IAAI;AAAA,QAClC,qBAAqB,EAAE,QAAQ;AAAA,QAC/B,iBAAiB,MAAM,OAAO,MAAM;AAAA,QAEpC;AAAA,sDAAC,8BAAW,WAAU,gBACnB,YAAE,0CAA0C,GAC/C;AAAA,UACA,4CAAC,8BAAW,WAAU,gBACnB,gBAAM,SACT;AAAA;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,EAAE,2BAA2B;AAAA,MACpC;AAAA,MACA,mBAAmB,cAAc,EAAE,gBAAgB,IAAI,EAAE,WAAW;AAAA,MACpE,eAAe;AAAA,MACf,qBAAqB,EAAE,QAAQ;AAAA,MAC/B,iBAAiB,MAAM,OAAO,MAAM;AAAA,MAEpC;AAAA,oDAAC,8BACE,YAAE,0GAA0G,GAC/G;AAAA,QACA,4CAAC,8BAAW,SAAQ,eACjB,YAAE,gPAAgP,GACrP;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -31,6 +31,7 @@ var import__ = require("..");
|
|
|
31
31
|
var import_iframe_preventer = require("../components/iframe-preventer");
|
|
32
32
|
var import_message_card = require("../components/message-cards/message-card");
|
|
33
33
|
var import_account_settings = require("./account-settings");
|
|
34
|
+
var import_cli_auth_confirm = require("./cli-auth-confirm");
|
|
34
35
|
var import_email_verification = require("./email-verification");
|
|
35
36
|
var import_error_page = require("./error-page");
|
|
36
37
|
var import_forgot_password = require("./forgot-password");
|
|
@@ -52,6 +53,7 @@ var availablePaths = {
|
|
|
52
53
|
magicLinkCallback: "magic-link-callback",
|
|
53
54
|
teamInvitation: "team-invitation",
|
|
54
55
|
accountSettings: "account-settings",
|
|
56
|
+
cliAuthConfirm: "cli-auth-confirm",
|
|
55
57
|
error: "error"
|
|
56
58
|
};
|
|
57
59
|
var pathAliases = {
|
|
@@ -178,6 +180,15 @@ function renderComponent(props) {
|
|
|
178
180
|
}
|
|
179
181
|
);
|
|
180
182
|
}
|
|
183
|
+
case availablePaths.cliAuthConfirm: {
|
|
184
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
185
|
+
import_cli_auth_confirm.CliAuthConfirmation,
|
|
186
|
+
{
|
|
187
|
+
fullPage,
|
|
188
|
+
...filterUndefinedINU(componentProps?.CliAuthConfirmation)
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
181
192
|
default: {
|
|
182
193
|
if (Object.values(availablePaths).includes(path)) {
|
|
183
194
|
throw new import_errors.StackAssertionError(`Path alias ${path} not included in switch statement, but in availablePaths?`, { availablePaths });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components-page/stack-handler.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { StackAssertionError } from \"@stackframe/stack-shared/dist/utils/errors\";\nimport { FilterUndefined, filterUndefined, pick } from \"@stackframe/stack-shared/dist/utils/objects\";\nimport { getRelativePart } from \"@stackframe/stack-shared/dist/utils/urls\";\nimport { RedirectType, notFound, redirect } from 'next/navigation';\nimport { useMemo } from 'react';\nimport { SignIn, SignUp, StackServerApp } from \"..\";\nimport { IframePreventer } from \"../components/iframe-preventer\";\nimport { MessageCard } from \"../components/message-cards/message-card\";\nimport { HandlerUrls, StackClientApp } from \"../lib/stack-app\";\nimport { AccountSettings } from \"./account-settings\";\nimport { EmailVerification } from \"./email-verification\";\nimport { ErrorPage } from \"./error-page\";\nimport { ForgotPassword } from \"./forgot-password\";\nimport { MagicLinkCallback } from \"./magic-link-callback\";\nimport { OAuthCallback } from \"./oauth-callback\";\nimport { PasswordReset } from \"./password-reset\";\nimport { SignOut } from \"./sign-out\";\nimport { TeamInvitation } from \"./team-invitation\";\n\ntype Components = {\n SignIn: typeof SignIn,\n SignUp: typeof SignUp,\n EmailVerification: typeof EmailVerification,\n PasswordReset: typeof PasswordReset,\n ForgotPassword: typeof ForgotPassword,\n SignOut: typeof SignOut,\n OAuthCallback: typeof OAuthCallback,\n MagicLinkCallback: typeof MagicLinkCallback,\n TeamInvitation: typeof TeamInvitation,\n ErrorPage: typeof ErrorPage,\n AccountSettings: typeof AccountSettings,\n};\n\ntype RouteProps = {\n params: Promise<{ stack?: string[] }> | { stack?: string[] },\n searchParams: Promise<Record<string, string>> | Record<string, string>,\n};\n\nconst next15DeprecationWarning = \"DEPRECATION WARNING: Next.js 15 disallows spreading the props argument of <StackHandler /> like `{...props}`, so you must now explicitly pass them in the `routeProps` argument: `routeProps={props}`. You can fix this by updating the code in the file `app/handler/[...stack]/route.tsx`.\";\n\nconst availablePaths = {\n signIn: 'sign-in',\n signUp: 'sign-up',\n emailVerification: 'email-verification',\n passwordReset: 'password-reset',\n forgotPassword: 'forgot-password',\n signOut: 'sign-out',\n oauthCallback: 'oauth-callback',\n magicLinkCallback: 'magic-link-callback',\n teamInvitation: 'team-invitation',\n accountSettings: 'account-settings',\n error: 'error',\n} as const;\n\nconst pathAliases = {\n // also includes the uppercase and non-dashed versions\n ...Object.fromEntries(Object.entries(availablePaths).map(([key, value]) => [value, value])),\n \"log-in\": availablePaths.signIn,\n \"register\": availablePaths.signUp,\n} as const;\n\ntype BaseHandlerProps = {\n fullPage: boolean,\n componentProps?: {\n [K in keyof Components]?: Parameters<Components[K]>[0];\n },\n};\n\nfunction renderComponent(props: {\n path: string,\n searchParams: Record<string, string>,\n fullPage: boolean,\n componentProps?: BaseHandlerProps['componentProps'],\n redirectIfNotHandler?: (name: keyof HandlerUrls) => void,\n onNotFound: () => any,\n app: StackClientApp<any> | StackServerApp<any>,\n}) {\n const { path, searchParams, fullPage, componentProps, redirectIfNotHandler, onNotFound, app } = props;\n\n switch (path) {\n case availablePaths.signIn: {\n redirectIfNotHandler?.('signIn');\n return <SignIn\n fullPage={fullPage}\n automaticRedirect\n {...filterUndefinedINU(componentProps?.SignIn)}\n />;\n }\n case availablePaths.signUp: {\n redirectIfNotHandler?.('signUp');\n return <SignUp\n fullPage={fullPage}\n automaticRedirect\n {...filterUndefinedINU(componentProps?.SignUp)}\n />;\n }\n case availablePaths.emailVerification: {\n redirectIfNotHandler?.('emailVerification');\n return <EmailVerification\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.EmailVerification)}\n />;\n }\n case availablePaths.passwordReset: {\n redirectIfNotHandler?.('passwordReset');\n return <PasswordReset\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.PasswordReset)}\n />;\n }\n case availablePaths.forgotPassword: {\n redirectIfNotHandler?.('forgotPassword');\n return <ForgotPassword\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.ForgotPassword)}\n />;\n }\n case availablePaths.signOut: {\n redirectIfNotHandler?.('signOut');\n return <SignOut\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.SignOut)}\n />;\n }\n case availablePaths.oauthCallback: {\n redirectIfNotHandler?.('oauthCallback');\n return <OAuthCallback\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.OAuthCallback)}\n />;\n }\n case availablePaths.magicLinkCallback: {\n redirectIfNotHandler?.('magicLinkCallback');\n return <MagicLinkCallback\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.MagicLinkCallback)}\n />;\n }\n case availablePaths.teamInvitation: {\n redirectIfNotHandler?.('teamInvitation');\n return <TeamInvitation\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.TeamInvitation)}\n />;\n }\n case availablePaths.accountSettings: {\n return <AccountSettings\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.AccountSettings)}\n />;\n }\n case availablePaths.error: {\n return <ErrorPage\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.ErrorPage)}\n />;\n }\n default: {\n if (Object.values(availablePaths).includes(path as any)) {\n throw new StackAssertionError(`Path alias ${path} not included in switch statement, but in availablePaths?`, { availablePaths });\n }\n for (const [key, value] of Object.entries(pathAliases)) {\n if (path === key.toLowerCase().replaceAll('-', '')) {\n const redirectUrl = `${app.urls.handler}/${value}?${new URLSearchParams(searchParams).toString()}`;\n return { redirect: redirectUrl };\n }\n }\n return onNotFound();\n }\n }\n}\n\nasync function NextStackHandler<HasTokenStore extends boolean>(props: BaseHandlerProps & {\n app: StackServerApp<HasTokenStore>,\n} & (\n | Partial<RouteProps>\n | {\n routeProps: RouteProps | unknown,\n }\n)): Promise<any> {\n if (!(\"routeProps\" in props)) {\n console.warn(next15DeprecationWarning);\n }\n\n const routeProps = \"routeProps\" in props ? props.routeProps as RouteProps : pick(props, [\"params\", \"searchParams\"] as any);\n const params = await routeProps.params;\n const searchParams = await routeProps.searchParams;\n\n if (!params?.stack) {\n return (\n <MessageCard title=\"Invalid Stack Handler Setup\" fullPage={props.fullPage}>\n <p>Can't use {\"<StackHandler />\"} at this location. Make sure that the file is in a folder called [...stack] and you are passing the routeProps prop.</p>\n </MessageCard>\n );\n }\n\n const path = params.stack.join('/');\n\n const redirectIfNotHandler = (name: keyof HandlerUrls) => {\n const url = props.app.urls[name];\n const handlerUrl = props.app.urls.handler;\n\n if (url !== handlerUrl && url.startsWith(handlerUrl + \"/\")) {\n return;\n }\n\n const urlObj = new URL(url, \"http://example.com\");\n if (searchParams) {\n for (const [key, value] of Object.entries(searchParams)) {\n urlObj.searchParams.set(key, value);\n }\n }\n\n redirect(getRelativePart(urlObj), RedirectType.replace);\n };\n\n const result = renderComponent({\n path,\n searchParams: searchParams ?? {},\n fullPage: props.fullPage,\n componentProps: props.componentProps,\n redirectIfNotHandler,\n onNotFound: () => notFound(),\n app: props.app,\n });\n\n if (result && 'redirect' in result) {\n redirect(result.redirect, RedirectType.replace);\n }\n\n return <>\n {process.env.NODE_ENV === \"development\" && !(\"routeProps\" in props) && (\n <span style={{ color: \"red\" }}>\n {next15DeprecationWarning}. This warning will not be shown in production.\n </span>\n )}\n <IframePreventer>\n {result}\n </IframePreventer>\n </>;\n}\n\n\nexport default NextStackHandler;\n\nfunction filterUndefinedINU<T extends {}>(value: T | undefined): FilterUndefined<T> | undefined {\n return value === undefined ? value : filterUndefined(value);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components-page/stack-handler.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { StackAssertionError } from \"@stackframe/stack-shared/dist/utils/errors\";\nimport { FilterUndefined, filterUndefined, pick } from \"@stackframe/stack-shared/dist/utils/objects\";\nimport { getRelativePart } from \"@stackframe/stack-shared/dist/utils/urls\";\nimport { RedirectType, notFound, redirect } from 'next/navigation'; // THIS_LINE_PLATFORM next\nimport { useMemo } from 'react';\nimport { SignIn, SignUp, StackServerApp } from \"..\";\nimport { IframePreventer } from \"../components/iframe-preventer\";\nimport { MessageCard } from \"../components/message-cards/message-card\";\nimport { HandlerUrls, StackClientApp } from \"../lib/stack-app\";\nimport { AccountSettings } from \"./account-settings\";\nimport { CliAuthConfirmation } from \"./cli-auth-confirm\";\nimport { EmailVerification } from \"./email-verification\";\nimport { ErrorPage } from \"./error-page\";\nimport { ForgotPassword } from \"./forgot-password\";\nimport { MagicLinkCallback } from \"./magic-link-callback\";\nimport { OAuthCallback } from \"./oauth-callback\";\nimport { PasswordReset } from \"./password-reset\";\nimport { SignOut } from \"./sign-out\";\nimport { TeamInvitation } from \"./team-invitation\";\n\ntype Components = {\n SignIn: typeof SignIn,\n SignUp: typeof SignUp,\n EmailVerification: typeof EmailVerification,\n PasswordReset: typeof PasswordReset,\n ForgotPassword: typeof ForgotPassword,\n SignOut: typeof SignOut,\n OAuthCallback: typeof OAuthCallback,\n MagicLinkCallback: typeof MagicLinkCallback,\n TeamInvitation: typeof TeamInvitation,\n ErrorPage: typeof ErrorPage,\n AccountSettings: typeof AccountSettings,\n CliAuthConfirmation: typeof CliAuthConfirmation,\n};\n\ntype RouteProps = {\n params: Promise<{ stack?: string[] }> | { stack?: string[] },\n searchParams: Promise<Record<string, string>> | Record<string, string>,\n};\n\nconst next15DeprecationWarning = \"DEPRECATION WARNING: Next.js 15 disallows spreading the props argument of <StackHandler /> like `{...props}`, so you must now explicitly pass them in the `routeProps` argument: `routeProps={props}`. You can fix this by updating the code in the file `app/handler/[...stack]/route.tsx`.\";\n\nconst availablePaths = {\n signIn: 'sign-in',\n signUp: 'sign-up',\n emailVerification: 'email-verification',\n passwordReset: 'password-reset',\n forgotPassword: 'forgot-password',\n signOut: 'sign-out',\n oauthCallback: 'oauth-callback',\n magicLinkCallback: 'magic-link-callback',\n teamInvitation: 'team-invitation',\n accountSettings: 'account-settings',\n cliAuthConfirm: 'cli-auth-confirm',\n error: 'error',\n} as const;\n\nconst pathAliases = {\n // also includes the uppercase and non-dashed versions\n ...Object.fromEntries(Object.entries(availablePaths).map(([key, value]) => [value, value])),\n \"log-in\": availablePaths.signIn,\n \"register\": availablePaths.signUp,\n} as const;\n\ntype BaseHandlerProps = {\n fullPage: boolean,\n componentProps?: {\n [K in keyof Components]?: Parameters<Components[K]>[0];\n },\n};\n\nfunction renderComponent(props: {\n path: string,\n searchParams: Record<string, string>,\n fullPage: boolean,\n componentProps?: BaseHandlerProps['componentProps'],\n redirectIfNotHandler?: (name: keyof HandlerUrls) => void,\n onNotFound: () => any,\n app: StackClientApp<any> | StackServerApp<any>,\n}) {\n const { path, searchParams, fullPage, componentProps, redirectIfNotHandler, onNotFound, app } = props;\n\n switch (path) {\n case availablePaths.signIn: {\n redirectIfNotHandler?.('signIn');\n return <SignIn\n fullPage={fullPage}\n automaticRedirect\n {...filterUndefinedINU(componentProps?.SignIn)}\n />;\n }\n case availablePaths.signUp: {\n redirectIfNotHandler?.('signUp');\n return <SignUp\n fullPage={fullPage}\n automaticRedirect\n {...filterUndefinedINU(componentProps?.SignUp)}\n />;\n }\n case availablePaths.emailVerification: {\n redirectIfNotHandler?.('emailVerification');\n return <EmailVerification\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.EmailVerification)}\n />;\n }\n case availablePaths.passwordReset: {\n redirectIfNotHandler?.('passwordReset');\n return <PasswordReset\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.PasswordReset)}\n />;\n }\n case availablePaths.forgotPassword: {\n redirectIfNotHandler?.('forgotPassword');\n return <ForgotPassword\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.ForgotPassword)}\n />;\n }\n case availablePaths.signOut: {\n redirectIfNotHandler?.('signOut');\n return <SignOut\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.SignOut)}\n />;\n }\n case availablePaths.oauthCallback: {\n redirectIfNotHandler?.('oauthCallback');\n return <OAuthCallback\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.OAuthCallback)}\n />;\n }\n case availablePaths.magicLinkCallback: {\n redirectIfNotHandler?.('magicLinkCallback');\n return <MagicLinkCallback\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.MagicLinkCallback)}\n />;\n }\n case availablePaths.teamInvitation: {\n redirectIfNotHandler?.('teamInvitation');\n return <TeamInvitation\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.TeamInvitation)}\n />;\n }\n case availablePaths.accountSettings: {\n return <AccountSettings\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.AccountSettings)}\n />;\n }\n case availablePaths.error: {\n return <ErrorPage\n searchParams={searchParams}\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.ErrorPage)}\n />;\n }\n case availablePaths.cliAuthConfirm: {\n return <CliAuthConfirmation\n fullPage={fullPage}\n {...filterUndefinedINU(componentProps?.CliAuthConfirmation)}\n />;\n }\n default: {\n if (Object.values(availablePaths).includes(path as any)) {\n throw new StackAssertionError(`Path alias ${path} not included in switch statement, but in availablePaths?`, { availablePaths });\n }\n for (const [key, value] of Object.entries(pathAliases)) {\n if (path === key.toLowerCase().replaceAll('-', '')) {\n const redirectUrl = `${app.urls.handler}/${value}?${new URLSearchParams(searchParams).toString()}`;\n return { redirect: redirectUrl };\n }\n }\n return onNotFound();\n }\n }\n}\n\nasync function NextStackHandler<HasTokenStore extends boolean>(props: BaseHandlerProps & {\n app: StackServerApp<HasTokenStore>,\n} & (\n | Partial<RouteProps>\n | {\n routeProps: RouteProps | unknown,\n }\n)): Promise<any> {\n if (!(\"routeProps\" in props)) {\n console.warn(next15DeprecationWarning);\n }\n\n const routeProps = \"routeProps\" in props ? props.routeProps as RouteProps : pick(props, [\"params\", \"searchParams\"] as any);\n const params = await routeProps.params;\n const searchParams = await routeProps.searchParams;\n\n if (!params?.stack) {\n return (\n <MessageCard title=\"Invalid Stack Handler Setup\" fullPage={props.fullPage}>\n <p>Can't use {\"<StackHandler />\"} at this location. Make sure that the file is in a folder called [...stack] and you are passing the routeProps prop.</p>\n </MessageCard>\n );\n }\n\n const path = params.stack.join('/');\n\n const redirectIfNotHandler = (name: keyof HandlerUrls) => {\n const url = props.app.urls[name];\n const handlerUrl = props.app.urls.handler;\n\n if (url !== handlerUrl && url.startsWith(handlerUrl + \"/\")) {\n return;\n }\n\n const urlObj = new URL(url, \"http://example.com\");\n if (searchParams) {\n for (const [key, value] of Object.entries(searchParams)) {\n urlObj.searchParams.set(key, value);\n }\n }\n\n redirect(getRelativePart(urlObj), RedirectType.replace);\n };\n\n const result = renderComponent({\n path,\n searchParams: searchParams ?? {},\n fullPage: props.fullPage,\n componentProps: props.componentProps,\n redirectIfNotHandler,\n onNotFound: () => notFound(),\n app: props.app,\n });\n\n if (result && 'redirect' in result) {\n redirect(result.redirect, RedirectType.replace);\n }\n\n return <>\n {process.env.NODE_ENV === \"development\" && !(\"routeProps\" in props) && (\n <span style={{ color: \"red\" }}>\n {next15DeprecationWarning}. This warning will not be shown in production.\n </span>\n )}\n <IframePreventer>\n {result}\n </IframePreventer>\n </>;\n}\n\n\nexport default NextStackHandler;\n\n// filter undefined values in object. if object itself is undefined, return undefined\nfunction filterUndefinedINU<T extends {}>(value: T | undefined): FilterUndefined<T> | undefined {\n return value === undefined ? value : filterUndefined(value);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/elements/maybe-full-page.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport React, { useId } from \"react\";\nimport { SsrScript } from \"./ssr-layout-effect\";\n\nexport function MaybeFullPage({\n children,\n fullPage,\n}: {\n children: React.ReactNode,\n fullPage: boolean,\n size?: number,\n containerClassName?: string,\n}) {\n const uniqueId = useId();\n const id = `stack-full-page-container-${uniqueId}`;\n\n const scriptString = `(([id]) => {\n const el = document.getElementById(id);\n if (!el) {\n // component is not full page\n return;\n }\n const offset = el.getBoundingClientRect().top + document.documentElement.scrollTop;\n el.style.minHeight = \\`calc(100vh - \\${offset}px)\\`;\n })(${JSON.stringify([id])})`;\n\n if (fullPage) {\n return (\n <>\n <div\n suppressHydrationWarning\n id={id}\n style={{\n minHeight: '100vh',\n alignSelf: 'stretch',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n className=\"stack-scope\"\n >\n {children}\n </div>\n <SsrScript script={scriptString} />\n </>\n );\n } else {\n return <>\n {children}\n </>;\n }\n\n}\n"],"mappings":";;;AAOA,SAAgB,aAAa;AAC7B,SAAS,iBAAiB;AA0BpB,mBACE,KADF;AAxBC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAKG;AACD,QAAM,WAAW,MAAM;AACvB,QAAM,KAAK,6BAA6B,QAAQ;AAEhD,QAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAQhB,KAAK,UAAU,CAAC,EAAE,CAAC,CAAC;AAEzB,MAAI,UAAU;AACZ,WACE,iCACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,0BAAwB;AAAA,UACxB;AAAA,UACA,OAAO;AAAA,YACL,WAAW;AAAA,YACX,WAAW;AAAA,YACX,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,YAAY;AAAA,UACd;AAAA,UACA,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MACA,oBAAC,aAAU,QAAQ,cAAc;AAAA,OACnC;AAAA,EAEJ,OAAO;AACL,WAAO,gCACJ,UACH;AAAA,EACF;AAEF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/elements/maybe-full-page.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport React, { useId } from \"react\";\nimport { SsrScript } from \"./ssr-layout-effect\";\n\nexport function MaybeFullPage({\n children,\n fullPage,\n}: {\n children: React.ReactNode,\n fullPage: boolean,\n size?: number,\n containerClassName?: string,\n}) {\n const uniqueId = useId();\n const id = `stack-full-page-container-${uniqueId}`;\n\n const scriptString = `(([id]) => {\n const el = document.getElementById(id);\n if (!el) {\n // component is not full page\n return;\n }\n const offset = el.getBoundingClientRect().top + document.documentElement.scrollTop;\n el.style.minHeight = \\`calc(100vh - \\${offset}px)\\`;\n })(${JSON.stringify([id])})`;\n\n if (fullPage) {\n return (\n <>\n <div\n suppressHydrationWarning\n id={id}\n style={{\n minHeight: '100vh',\n alignSelf: 'stretch',\n flexGrow: 1,\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n className=\"stack-scope\"\n >\n {children}\n </div>\n <SsrScript script={scriptString} />\n </>\n );\n } else {\n return <>\n {children}\n </>;\n }\n\n}\n"],"mappings":";;;AAOA,SAAgB,aAAa;AAC7B,SAAS,iBAAiB;AA0BpB,mBACE,KADF;AAxBC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAKG;AACD,QAAM,WAAW,MAAM;AACvB,QAAM,KAAK,6BAA6B,QAAQ;AAEhD,QAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAQhB,KAAK,UAAU,CAAC,EAAE,CAAC,CAAC;AAEzB,MAAI,UAAU;AACZ,WACE,iCACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,0BAAwB;AAAA,UACxB;AAAA,UACA,OAAO;AAAA,YACL,WAAW;AAAA,YACX,WAAW;AAAA,YACX,UAAU;AAAA,YACV,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,YAAY;AAAA,UACd;AAAA,UACA,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MACA,oBAAC,aAAU,QAAQ,cAAc;AAAA,OACnC;AAAA,EAEJ,OAAO;AACL,WAAO,gCACJ,UACH;AAAA,EACF;AAEF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/link.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { cn } from \"@stackframe/stack-ui\";\nimport NextLink from 'next/link'
|
|
1
|
+
{"version":3,"sources":["../../../src/components/link.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { cn } from \"@stackframe/stack-ui\";\nimport NextLink from 'next/link'; // THIS_LINE_PLATFORM next\n\ntype LinkProps = {\n href: string,\n children: React.ReactNode,\n className?: string,\n target?: string,\n onClick?: React.MouseEventHandler<HTMLAnchorElement>,\n prefetch?: boolean,\n};\n\nfunction Link(props: LinkProps) {\n return <NextLink\n href={props.href}\n target={props.target}\n className={props.className}\n prefetch={props.prefetch}\n onClick={props.onClick}\n >\n {props.children}\n </NextLink>;\n}\n\nfunction StyledLink(props: LinkProps) {\n return (\n <Link {...props} className={cn(\"underline font-medium\", props.className)}>\n {props.children}\n </Link>\n );\n}\n\nexport { Link, StyledLink };\n"],"mappings":";;;AAOA,SAAS,UAAU;AACnB,OAAO,cAAc;AAYZ;AADT,SAAS,KAAK,OAAkB;AAC9B,SAAO;AAAA,IAAC;AAAA;AAAA,MACN,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd,WAAW,MAAM;AAAA,MACjB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,MAEd,gBAAM;AAAA;AAAA,EACT;AACF;AAEA,SAAS,WAAW,OAAkB;AACpC,SACE,oBAAC,QAAM,GAAG,OAAO,WAAW,GAAG,yBAAyB,MAAM,SAAS,GACpE,gBAAM,UACT;AAEJ;","names":[]}
|
|
@@ -8,7 +8,8 @@ import { getPasswordError } from "@stackframe/stack-shared/dist/helpers/password
|
|
|
8
8
|
import { useAsyncCallback } from "@stackframe/stack-shared/dist/hooks/use-async-callback";
|
|
9
9
|
import { passwordSchema as schemaFieldsPasswordSchema, strictEmailSchema, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields";
|
|
10
10
|
import { generateRandomValues } from "@stackframe/stack-shared/dist/utils/crypto";
|
|
11
|
-
import {
|
|
11
|
+
import { fromNow } from "@stackframe/stack-shared/dist/utils/dates";
|
|
12
|
+
import { captureError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
|
|
12
13
|
import { runAsynchronously, runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/promises";
|
|
13
14
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActionCell, Badge, Button, Input, Label, PasswordInput, Separator, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from "@stackframe/stack-ui";
|
|
14
15
|
import { Edit, Trash, icons } from "lucide-react";
|
|
@@ -54,6 +55,13 @@ function AccountSettings(props) {
|
|
|
54
55
|
icon: /* @__PURE__ */ jsx(Icon, { name: "ShieldCheck" }),
|
|
55
56
|
content: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(EmailsAndAuthPageSkeleton, {}), children: /* @__PURE__ */ jsx(EmailsAndAuthPage, {}) })
|
|
56
57
|
},
|
|
58
|
+
{
|
|
59
|
+
title: t("Active Sessions"),
|
|
60
|
+
type: "item",
|
|
61
|
+
id: "sessions",
|
|
62
|
+
icon: /* @__PURE__ */ jsx(Icon, { name: "Monitor" }),
|
|
63
|
+
content: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(ActiveSessionsPageSkeleton, {}), children: /* @__PURE__ */ jsx(ActiveSessionsPage, {}) })
|
|
64
|
+
},
|
|
57
65
|
{
|
|
58
66
|
title: t("Settings"),
|
|
59
67
|
type: "item",
|
|
@@ -310,6 +318,118 @@ function EmailsAndAuthPage() {
|
|
|
310
318
|
/* @__PURE__ */ jsx(MfaSection, {})
|
|
311
319
|
] });
|
|
312
320
|
}
|
|
321
|
+
function ActiveSessionsPage() {
|
|
322
|
+
const { t } = useTranslation();
|
|
323
|
+
const user = useUser({ or: "throw" });
|
|
324
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
325
|
+
const [isRevokingAll, setIsRevokingAll] = useState(false);
|
|
326
|
+
const [sessions, setSessions] = useState([]);
|
|
327
|
+
const [showConfirmRevokeAll, setShowConfirmRevokeAll] = useState(false);
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
runAsynchronously(async () => {
|
|
330
|
+
setIsLoading(true);
|
|
331
|
+
const sessionsData = await user.getActiveSessions();
|
|
332
|
+
const enhancedSessions = sessionsData;
|
|
333
|
+
setSessions(enhancedSessions);
|
|
334
|
+
setIsLoading(false);
|
|
335
|
+
});
|
|
336
|
+
}, [user]);
|
|
337
|
+
const handleRevokeSession = async (sessionId) => {
|
|
338
|
+
try {
|
|
339
|
+
await user.revokeSession(sessionId);
|
|
340
|
+
setSessions(sessions.filter((session) => session.id !== sessionId));
|
|
341
|
+
} catch (error) {
|
|
342
|
+
captureError("Failed to revoke session", { sessionId, error });
|
|
343
|
+
throw error;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
const handleRevokeAllSessions = async () => {
|
|
347
|
+
setIsRevokingAll(true);
|
|
348
|
+
try {
|
|
349
|
+
const deletionPromises = sessions.filter((session) => !session.isCurrentSession).map((session) => user.revokeSession(session.id));
|
|
350
|
+
await Promise.all(deletionPromises);
|
|
351
|
+
setSessions((prevSessions) => prevSessions.filter((session) => session.isCurrentSession));
|
|
352
|
+
} catch (error) {
|
|
353
|
+
captureError("Failed to revoke all sessions", { error, sessionIds: sessions.map((session) => session.id) });
|
|
354
|
+
throw error;
|
|
355
|
+
} finally {
|
|
356
|
+
setIsRevokingAll(false);
|
|
357
|
+
setShowConfirmRevokeAll(false);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
return /* @__PURE__ */ jsx(PageLayout, { children: /* @__PURE__ */ jsxs("div", { children: [
|
|
361
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-2", children: [
|
|
362
|
+
/* @__PURE__ */ jsx(Typography, { className: "font-medium", children: t("Active Sessions") }),
|
|
363
|
+
sessions.filter((s) => !s.isCurrentSession).length > 0 && !isLoading && (showConfirmRevokeAll ? /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
364
|
+
/* @__PURE__ */ jsx(
|
|
365
|
+
Button,
|
|
366
|
+
{
|
|
367
|
+
variant: "destructive",
|
|
368
|
+
size: "sm",
|
|
369
|
+
loading: isRevokingAll,
|
|
370
|
+
onClick: handleRevokeAllSessions,
|
|
371
|
+
children: t("Confirm")
|
|
372
|
+
}
|
|
373
|
+
),
|
|
374
|
+
/* @__PURE__ */ jsx(
|
|
375
|
+
Button,
|
|
376
|
+
{
|
|
377
|
+
variant: "secondary",
|
|
378
|
+
size: "sm",
|
|
379
|
+
disabled: isRevokingAll,
|
|
380
|
+
onClick: () => setShowConfirmRevokeAll(false),
|
|
381
|
+
children: t("Cancel")
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
] }) : /* @__PURE__ */ jsx(
|
|
385
|
+
Button,
|
|
386
|
+
{
|
|
387
|
+
variant: "outline",
|
|
388
|
+
size: "sm",
|
|
389
|
+
onClick: () => setShowConfirmRevokeAll(true),
|
|
390
|
+
children: t("Revoke All Other Sessions")
|
|
391
|
+
}
|
|
392
|
+
))
|
|
393
|
+
] }),
|
|
394
|
+
/* @__PURE__ */ jsx(Typography, { variant: "secondary", type: "footnote", className: "mb-4", children: t("These are devices where you're currently logged in. You can revoke access to end a session.") }),
|
|
395
|
+
isLoading ? /* @__PURE__ */ jsx(Skeleton, { className: "h-[300px] w-full rounded-md" }) : /* @__PURE__ */ jsx("div", { className: "border rounded-md", children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
396
|
+
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
397
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[200px]", children: t("Session") }),
|
|
398
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[150px]", children: t("IP Address") }),
|
|
399
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[150px]", children: t("Location") }),
|
|
400
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[150px]", children: t("Last used") }),
|
|
401
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[80px]" })
|
|
402
|
+
] }) }),
|
|
403
|
+
/* @__PURE__ */ jsx(TableBody, { children: sessions.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 5, className: "text-center py-6", children: /* @__PURE__ */ jsx(Typography, { variant: "secondary", children: t("No active sessions found") }) }) }) : sessions.map((session) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
404
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
405
|
+
/* @__PURE__ */ jsx(Typography, { children: session.isCurrentSession ? t("Current Session") : t("Other Session") }),
|
|
406
|
+
session.isImpersonation && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "w-fit mt-1", children: t("Impersonation") }),
|
|
407
|
+
/* @__PURE__ */ jsx(Typography, { variant: "secondary", type: "footnote", children: t("Signed in {time}", { time: new Date(session.createdAt).toLocaleDateString() }) })
|
|
408
|
+
] }) }),
|
|
409
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { children: session.geoInfo?.ip || t("-") }) }),
|
|
410
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { children: session.geoInfo?.cityName || t("Unknown") }) }),
|
|
411
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
412
|
+
/* @__PURE__ */ jsx(Typography, { children: session.lastUsedAt ? fromNow(new Date(session.lastUsedAt)) : t("Never") }),
|
|
413
|
+
/* @__PURE__ */ jsx(Typography, { variant: "secondary", type: "footnote", title: session.lastUsedAt ? new Date(session.lastUsedAt).toLocaleString() : "", children: session.lastUsedAt ? new Date(session.lastUsedAt).toLocaleDateString() : "" })
|
|
414
|
+
] }) }),
|
|
415
|
+
/* @__PURE__ */ jsx(TableCell, { align: "right", children: /* @__PURE__ */ jsx(
|
|
416
|
+
ActionCell,
|
|
417
|
+
{
|
|
418
|
+
items: [
|
|
419
|
+
{
|
|
420
|
+
item: t("Revoke"),
|
|
421
|
+
onClick: () => handleRevokeSession(session.id),
|
|
422
|
+
danger: true,
|
|
423
|
+
disabled: session.isCurrentSession,
|
|
424
|
+
disabledTooltip: session.isCurrentSession ? t("You cannot revoke your current session") : void 0
|
|
425
|
+
}
|
|
426
|
+
]
|
|
427
|
+
}
|
|
428
|
+
) })
|
|
429
|
+
] }, session.id)) })
|
|
430
|
+
] }) })
|
|
431
|
+
] }) });
|
|
432
|
+
}
|
|
313
433
|
function EmailsAndAuthPageSkeleton() {
|
|
314
434
|
return /* @__PURE__ */ jsxs(PageLayout, { children: [
|
|
315
435
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-full mt-1" }),
|
|
@@ -318,6 +438,13 @@ function EmailsAndAuthPageSkeleton() {
|
|
|
318
438
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-full mt-1" })
|
|
319
439
|
] });
|
|
320
440
|
}
|
|
441
|
+
function ActiveSessionsPageSkeleton() {
|
|
442
|
+
return /* @__PURE__ */ jsxs(PageLayout, { children: [
|
|
443
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-48 mb-2" }),
|
|
444
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full mb-4" }),
|
|
445
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[200px] w-full mt-1 rounded-md" })
|
|
446
|
+
] });
|
|
447
|
+
}
|
|
321
448
|
function PasskeySection() {
|
|
322
449
|
const { t } = useTranslation();
|
|
323
450
|
const user = useUser({ or: "throw" });
|