@stackframe/js 2.8.58 → 2.8.60
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/esm/index.js.map +1 -1
- package/dist/esm/integrations/convex/component/convex.config.js.map +1 -1
- package/dist/esm/integrations/convex.js.map +1 -1
- package/dist/esm/lib/auth.js.map +1 -1
- package/dist/esm/lib/cookie.js.map +1 -1
- package/dist/esm/lib/stack-app/api-keys/index.js.map +1 -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 +59 -4
- 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/index.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/index.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/contact-channels/index.js.map +1 -1
- package/dist/esm/lib/stack-app/email-templates/index.js.map +1 -1
- package/dist/esm/lib/stack-app/index.js.map +1 -1
- package/dist/esm/lib/stack-app/internal-api-keys/index.js.map +1 -1
- package/dist/esm/lib/stack-app/permissions/index.js.map +1 -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/utils/url.js.map +1 -1
- package/dist/index.d.mts +36 -1
- package/dist/index.d.ts +36 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/convex/component/convex.config.js.map +1 -1
- package/dist/integrations/convex.js.map +1 -1
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/cookie.js.map +1 -1
- package/dist/lib/stack-app/api-keys/index.js.map +1 -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 +59 -4
- 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/index.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/index.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/contact-channels/index.js.map +1 -1
- package/dist/lib/stack-app/customers/index.js.map +1 -1
- package/dist/lib/stack-app/data-vault/index.js.map +1 -1
- package/dist/lib/stack-app/email/index.js.map +1 -1
- package/dist/lib/stack-app/email-templates/index.js.map +1 -1
- package/dist/lib/stack-app/index.js.map +1 -1
- package/dist/lib/stack-app/internal-api-keys/index.js.map +1 -1
- package/dist/lib/stack-app/notification-categories/index.js.map +1 -1
- package/dist/lib/stack-app/permissions/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.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/utils/url.js.map +1 -1
- package/package.json +13 -13
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nexport * from './lib/stack-app';\n\nexport { getConvexProvidersConfig } from \"./integrations/convex\";\n\n"],"mappings":";AAIA,cAAc;AAEd,SAAS,gCAAgC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nexport * from './lib/stack-app';\n\nexport { getConvexProvidersConfig } from \"./integrations/convex\";\n\n"],"mappings":";AAIA,cAAc;AAEd,SAAS,gCAAgC;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/integrations/convex/component/convex.config.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { defineComponent } from \"convex/server\";\n\nconst component = defineComponent(\"stack_auth\");\n\nexport default component;\n"],"mappings":";AAIA,SAAS,uBAAuB;AAEhC,IAAM,YAAY,gBAAgB,YAAY;AAE9C,IAAO,wBAAQ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/integrations/convex/component/convex.config.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { defineComponent } from \"convex/server\";\n\nconst component = defineComponent(\"stack_auth\");\n\nexport default component;\n"],"mappings":";AAIA,SAAS,uBAAuB;AAEhC,IAAM,YAAY,gBAAgB,YAAY;AAE9C,IAAO,wBAAQ;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/integrations/convex.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { urlString } from \"@stackframe/stack-shared/dist/utils/urls\";\nimport { defaultBaseUrl } from \"../lib/stack-app/apps/implementations/common\";\n\nexport function getConvexProvidersConfig(options: {\n baseUrl?: string,\n projectId: string,\n}) {\n const baseUrl = options.baseUrl || defaultBaseUrl;\n const projectId = options.projectId;\n return [\n {\n type: \"customJwt\",\n issuer: new URL(urlString`/api/v1/projects/${projectId}`, baseUrl),\n jwks: new URL(urlString`/api/v1/projects/${projectId}/.well-known/jwks.json`, baseUrl),\n algorithm: \"ES256\",\n },\n {\n type: \"customJwt\",\n issuer: new URL(urlString`/api/v1/projects-anonymous-users/${projectId}`, baseUrl),\n jwks: new URL(urlString`/api/v1/projects/${projectId}/.well-known/jwks.json?include_anonymous=true`, baseUrl),\n algorithm: \"ES256\",\n },\n ];\n}\n"],"mappings":";AAIA,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAExB,SAAS,yBAAyB,SAGtC;AACD,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,YAAY,QAAQ;AAC1B,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,QAAQ,IAAI,IAAI,6BAA6B,SAAS,IAAI,OAAO;AAAA,MACjE,MAAM,IAAI,IAAI,6BAA6B,SAAS,0BAA0B,OAAO;AAAA,MACrF,WAAW;AAAA,IACb;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,QAAQ,IAAI,IAAI,6CAA6C,SAAS,IAAI,OAAO;AAAA,MACjF,MAAM,IAAI,IAAI,6BAA6B,SAAS,iDAAiD,OAAO;AAAA,MAC5G,WAAW;AAAA,IACb;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/integrations/convex.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { urlString } from \"@stackframe/stack-shared/dist/utils/urls\";\nimport { defaultBaseUrl } from \"../lib/stack-app/apps/implementations/common\";\n\nexport function getConvexProvidersConfig(options: {\n baseUrl?: string,\n projectId: string,\n}) {\n const baseUrl = options.baseUrl || defaultBaseUrl;\n const projectId = options.projectId;\n return [\n {\n type: \"customJwt\",\n issuer: new URL(urlString`/api/v1/projects/${projectId}`, baseUrl),\n jwks: new URL(urlString`/api/v1/projects/${projectId}/.well-known/jwks.json`, baseUrl),\n algorithm: \"ES256\",\n },\n {\n type: \"customJwt\",\n issuer: new URL(urlString`/api/v1/projects-anonymous-users/${projectId}`, baseUrl),\n jwks: new URL(urlString`/api/v1/projects/${projectId}/.well-known/jwks.json?include_anonymous=true`, baseUrl),\n algorithm: \"ES256\",\n },\n ];\n}\n"],"mappings":";AAIA,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAExB,SAAS,yBAAyB,SAGtC;AACD,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,YAAY,QAAQ;AAC1B,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,QAAQ,IAAI,IAAI,6BAA6B,SAAS,IAAI,OAAO;AAAA,MACjE,MAAM,IAAI,IAAI,6BAA6B,SAAS,0BAA0B,OAAO;AAAA,MACrF,WAAW;AAAA,IACb;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,QAAQ,IAAI,IAAI,6CAA6C,SAAS,IAAI,OAAO;AAAA,MACjF,MAAM,IAAI,IAAI,6BAA6B,SAAS,iDAAiD,OAAO;AAAA,MAC5G,WAAW;AAAA,IACb;AAAA,EACF;AACF;","names":[]}
|
package/dist/esm/lib/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/auth.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { KnownError, StackClientInterface } from \"@stackframe/stack-shared\";\nimport { InternalSession } from \"@stackframe/stack-shared/dist/sessions\";\nimport { StackAssertionError, throwErr } from \"@stackframe/stack-shared/dist/utils/errors\";\nimport { neverResolve } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport { deindent } from \"@stackframe/stack-shared/dist/utils/strings\";\nimport { constructRedirectUrl } from \"../utils/url\";\nimport { consumeVerifierAndStateCookie, saveVerifierAndState } from \"./cookie\";\n\nexport async function signInWithOAuth(\n iface: StackClientInterface,\n options: {\n provider: string,\n redirectUrl: string,\n errorRedirectUrl: string,\n providerScope?: string,\n },\n session: InternalSession,\n) {\n const { codeChallenge, state } = await saveVerifierAndState();\n const location = await iface.getOAuthUrl({\n provider: options.provider,\n redirectUrl: constructRedirectUrl(options.redirectUrl, \"redirectUrl\"),\n errorRedirectUrl: constructRedirectUrl(options.errorRedirectUrl, \"errorRedirectUrl\"),\n codeChallenge,\n state,\n type: \"authenticate\",\n providerScope: options.providerScope,\n session,\n });\n window.location.assign(location);\n await neverResolve();\n}\n\nexport async function addNewOAuthProviderOrScope(\n iface: StackClientInterface,\n options: {\n provider: string,\n redirectUrl: string,\n errorRedirectUrl: string,\n providerScope?: string,\n },\n session: InternalSession,\n) {\n const { codeChallenge, state } = await saveVerifierAndState();\n const location = await iface.getOAuthUrl({\n provider: options.provider,\n redirectUrl: constructRedirectUrl(options.redirectUrl, \"redirectUrl\"),\n errorRedirectUrl: constructRedirectUrl(options.errorRedirectUrl, \"errorRedirectUrl\"),\n afterCallbackRedirectUrl: constructRedirectUrl(window.location.href, \"afterCallbackRedirectUrl\"),\n codeChallenge,\n state,\n type: \"link\",\n session,\n providerScope: options.providerScope,\n });\n window.location.assign(location);\n await neverResolve();\n}\n\n/**\n * Checks if the current URL has the query parameters for an OAuth callback, and if so, removes them.\n *\n * Must be synchronous for the logic in callOAuthCallback to work without race conditions.\n */\nfunction consumeOAuthCallbackQueryParams() {\n const requiredParams = [\"code\", \"state\"];\n const originalUrl = new URL(window.location.href);\n for (const param of requiredParams) {\n if (!originalUrl.searchParams.has(param)) {\n console.warn(new Error(`Missing required query parameter on OAuth callback: ${param}. Maybe you opened or reloaded the oauth-callback page from your history?`));\n return null;\n }\n }\n\n const expectedState = originalUrl.searchParams.get(\"state\") ?? throwErr(\"This should never happen; isn't state required above?\");\n const cookieResult = consumeVerifierAndStateCookie(expectedState);\n\n if (!cookieResult) {\n // If the state can't be found in the cookies, then the callback wasn't meant for us.\n // Maybe the website uses another OAuth library?\n console.warn(deindent`\n Stack found an outer OAuth callback state in the query parameters, but not in cookies.\n \n This could have multiple reasons:\n - The cookie expired, because the OAuth flow took too long.\n - The user's browser deleted the cookie, either manually or because of a very strict cookie policy.\n - The cookie was already consumed by this page, and the user already logged in.\n - You are using another OAuth client library with the same callback URL as Stack.\n - The user opened the OAuth callback page from their history.\n\n Either way, it is probably safe to ignore this warning unless you are debugging an OAuth issue.\n `);\n return null;\n }\n\n\n const newUrl = new URL(originalUrl);\n for (const param of requiredParams) {\n newUrl.searchParams.delete(param);\n }\n\n // let's get rid of the authorization code in the history as we\n // don't redirect to `redirectUrl` if there's a validation error\n // (as the redirectUrl might be malicious!).\n //\n // We use history.replaceState instead of location.assign(...) to\n // prevent an unnecessary reload\n window.history.replaceState({}, \"\", newUrl.toString());\n\n return {\n originalUrl,\n codeVerifier: cookieResult.codeVerifier,\n state: expectedState,\n };\n}\n\nexport async function callOAuthCallback(\n iface: StackClientInterface,\n redirectUrl: string,\n) {\n // note: this part of the function (until the return) needs\n // to be synchronous, to prevent race conditions when\n // callOAuthCallback is called multiple times in parallel\n const consumed = consumeOAuthCallbackQueryParams();\n if (!consumed) return Result.ok(undefined);\n\n // the rest can be asynchronous (we now know that we are the\n // intended recipient of the callback, and the only instance\n // of callOAuthCallback that's running)\n try {\n return Result.ok(await iface.callOAuthCallback({\n oauthParams: consumed.originalUrl.searchParams,\n redirectUri: constructRedirectUrl(redirectUrl, \"redirectUri\"),\n codeVerifier: consumed.codeVerifier,\n state: consumed.state,\n }));\n } catch (e) {\n if (KnownError.isKnownError(e)) {\n throw e;\n }\n throw new StackAssertionError(\"Error signing in during OAuth callback. Please try again.\", { cause: e });\n }\n}\n"],"mappings":";AAIA,SAAS,kBAAwC;AAEjD,SAAS,qBAAqB,gBAAgB;AAC9C,SAAS,oBAAoB;AAC7B,SAAS,cAAc;AACvB,SAAS,gBAAgB;AACzB,SAAS,4BAA4B;AACrC,SAAS,+BAA+B,4BAA4B;AAEpE,eAAsB,gBACpB,OACA,SAMA,SACA;AACA,QAAM,EAAE,eAAe,MAAM,IAAI,MAAM,qBAAqB;AAC5D,QAAM,WAAW,MAAM,MAAM,YAAY;AAAA,IACvC,UAAU,QAAQ;AAAA,IAClB,aAAa,qBAAqB,QAAQ,aAAa,aAAa;AAAA,IACpE,kBAAkB,qBAAqB,QAAQ,kBAAkB,kBAAkB;AAAA,IACnF;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,eAAe,QAAQ;AAAA,IACvB;AAAA,EACF,CAAC;AACD,SAAO,SAAS,OAAO,QAAQ;AAC/B,QAAM,aAAa;AACrB;AAEA,eAAsB,2BACpB,OACA,SAMA,SACA;AACA,QAAM,EAAE,eAAe,MAAM,IAAI,MAAM,qBAAqB;AAC5D,QAAM,WAAW,MAAM,MAAM,YAAY;AAAA,IACvC,UAAU,QAAQ;AAAA,IAClB,aAAa,qBAAqB,QAAQ,aAAa,aAAa;AAAA,IACpE,kBAAkB,qBAAqB,QAAQ,kBAAkB,kBAAkB;AAAA,IACnF,0BAA0B,qBAAqB,OAAO,SAAS,MAAM,0BAA0B;AAAA,IAC/F;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,eAAe,QAAQ;AAAA,EACzB,CAAC;AACD,SAAO,SAAS,OAAO,QAAQ;AAC/B,QAAM,aAAa;AACrB;AAOA,SAAS,kCAAkC;AACzC,QAAM,iBAAiB,CAAC,QAAQ,OAAO;AACvC,QAAM,cAAc,IAAI,IAAI,OAAO,SAAS,IAAI;AAChD,aAAW,SAAS,gBAAgB;AAClC,QAAI,CAAC,YAAY,aAAa,IAAI,KAAK,GAAG;AACxC,cAAQ,KAAK,IAAI,MAAM,uDAAuD,KAAK,2EAA2E,CAAC;AAC/J,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAAgB,YAAY,aAAa,IAAI,OAAO,KAAK,SAAS,uDAAuD;AAC/H,QAAM,eAAe,8BAA8B,aAAa;AAEhE,MAAI,CAAC,cAAc;AAGjB,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAWZ;AACD,WAAO;AAAA,EACT;AAGA,QAAM,SAAS,IAAI,IAAI,WAAW;AAClC,aAAW,SAAS,gBAAgB;AAClC,WAAO,aAAa,OAAO,KAAK;AAAA,EAClC;AAQA,SAAO,QAAQ,aAAa,CAAC,GAAG,IAAI,OAAO,SAAS,CAAC;AAErD,SAAO;AAAA,IACL;AAAA,IACA,cAAc,aAAa;AAAA,IAC3B,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,kBACpB,OACA,aACA;AAIA,QAAM,WAAW,gCAAgC;AACjD,MAAI,CAAC,SAAU,QAAO,OAAO,GAAG,MAAS;AAKzC,MAAI;AACF,WAAO,OAAO,GAAG,MAAM,MAAM,kBAAkB;AAAA,MAC7C,aAAa,SAAS,YAAY;AAAA,MAClC,aAAa,qBAAqB,aAAa,aAAa;AAAA,MAC5D,cAAc,SAAS;AAAA,MACvB,OAAO,SAAS;AAAA,IAClB,CAAC,CAAC;AAAA,EACJ,SAAS,GAAG;AACV,QAAI,WAAW,aAAa,CAAC,GAAG;AAC9B,YAAM;AAAA,IACR;AACA,UAAM,IAAI,oBAAoB,6DAA6D,EAAE,OAAO,EAAE,CAAC;AAAA,EACzG;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/auth.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { KnownError, StackClientInterface } from \"@stackframe/stack-shared\";\nimport { InternalSession } from \"@stackframe/stack-shared/dist/sessions\";\nimport { StackAssertionError, throwErr } from \"@stackframe/stack-shared/dist/utils/errors\";\nimport { neverResolve } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport { deindent } from \"@stackframe/stack-shared/dist/utils/strings\";\nimport { constructRedirectUrl } from \"../utils/url\";\nimport { consumeVerifierAndStateCookie, saveVerifierAndState } from \"./cookie\";\n\nexport async function signInWithOAuth(\n iface: StackClientInterface,\n options: {\n provider: string,\n redirectUrl: string,\n errorRedirectUrl: string,\n providerScope?: string,\n },\n session: InternalSession,\n) {\n const { codeChallenge, state } = await saveVerifierAndState();\n const location = await iface.getOAuthUrl({\n provider: options.provider,\n redirectUrl: constructRedirectUrl(options.redirectUrl, \"redirectUrl\"),\n errorRedirectUrl: constructRedirectUrl(options.errorRedirectUrl, \"errorRedirectUrl\"),\n codeChallenge,\n state,\n type: \"authenticate\",\n providerScope: options.providerScope,\n session,\n });\n window.location.assign(location);\n await neverResolve();\n}\n\nexport async function addNewOAuthProviderOrScope(\n iface: StackClientInterface,\n options: {\n provider: string,\n redirectUrl: string,\n errorRedirectUrl: string,\n providerScope?: string,\n },\n session: InternalSession,\n) {\n const { codeChallenge, state } = await saveVerifierAndState();\n const location = await iface.getOAuthUrl({\n provider: options.provider,\n redirectUrl: constructRedirectUrl(options.redirectUrl, \"redirectUrl\"),\n errorRedirectUrl: constructRedirectUrl(options.errorRedirectUrl, \"errorRedirectUrl\"),\n afterCallbackRedirectUrl: constructRedirectUrl(window.location.href, \"afterCallbackRedirectUrl\"),\n codeChallenge,\n state,\n type: \"link\",\n session,\n providerScope: options.providerScope,\n });\n window.location.assign(location);\n await neverResolve();\n}\n\n/**\n * Checks if the current URL has the query parameters for an OAuth callback, and if so, removes them.\n *\n * Must be synchronous for the logic in callOAuthCallback to work without race conditions.\n */\nfunction consumeOAuthCallbackQueryParams() {\n const requiredParams = [\"code\", \"state\"];\n const originalUrl = new URL(window.location.href);\n for (const param of requiredParams) {\n if (!originalUrl.searchParams.has(param)) {\n console.warn(new Error(`Missing required query parameter on OAuth callback: ${param}. Maybe you opened or reloaded the oauth-callback page from your history?`));\n return null;\n }\n }\n\n const expectedState = originalUrl.searchParams.get(\"state\") ?? throwErr(\"This should never happen; isn't state required above?\");\n const cookieResult = consumeVerifierAndStateCookie(expectedState);\n\n if (!cookieResult) {\n // If the state can't be found in the cookies, then the callback wasn't meant for us.\n // Maybe the website uses another OAuth library?\n console.warn(deindent`\n Stack found an outer OAuth callback state in the query parameters, but not in cookies.\n \n This could have multiple reasons:\n - The cookie expired, because the OAuth flow took too long.\n - The user's browser deleted the cookie, either manually or because of a very strict cookie policy.\n - The cookie was already consumed by this page, and the user already logged in.\n - You are using another OAuth client library with the same callback URL as Stack.\n - The user opened the OAuth callback page from their history.\n\n Either way, it is probably safe to ignore this warning unless you are debugging an OAuth issue.\n `);\n return null;\n }\n\n\n const newUrl = new URL(originalUrl);\n for (const param of requiredParams) {\n newUrl.searchParams.delete(param);\n }\n\n // let's get rid of the authorization code in the history as we\n // don't redirect to `redirectUrl` if there's a validation error\n // (as the redirectUrl might be malicious!).\n //\n // We use history.replaceState instead of location.assign(...) to\n // prevent an unnecessary reload\n window.history.replaceState({}, \"\", newUrl.toString());\n\n return {\n originalUrl,\n codeVerifier: cookieResult.codeVerifier,\n state: expectedState,\n };\n}\n\nexport async function callOAuthCallback(\n iface: StackClientInterface,\n redirectUrl: string,\n) {\n // note: this part of the function (until the return) needs\n // to be synchronous, to prevent race conditions when\n // callOAuthCallback is called multiple times in parallel\n const consumed = consumeOAuthCallbackQueryParams();\n if (!consumed) return Result.ok(undefined);\n\n // the rest can be asynchronous (we now know that we are the\n // intended recipient of the callback, and the only instance\n // of callOAuthCallback that's running)\n try {\n return Result.ok(await iface.callOAuthCallback({\n oauthParams: consumed.originalUrl.searchParams,\n redirectUri: constructRedirectUrl(redirectUrl, \"redirectUri\"),\n codeVerifier: consumed.codeVerifier,\n state: consumed.state,\n }));\n } catch (e) {\n if (KnownError.isKnownError(e)) {\n throw e;\n }\n throw new StackAssertionError(\"Error signing in during OAuth callback. Please try again.\", { cause: e });\n }\n}\n"],"mappings":";AAIA,SAAS,kBAAwC;AAEjD,SAAS,qBAAqB,gBAAgB;AAC9C,SAAS,oBAAoB;AAC7B,SAAS,cAAc;AACvB,SAAS,gBAAgB;AACzB,SAAS,4BAA4B;AACrC,SAAS,+BAA+B,4BAA4B;AAEpE,eAAsB,gBACpB,OACA,SAMA,SACA;AACA,QAAM,EAAE,eAAe,MAAM,IAAI,MAAM,qBAAqB;AAC5D,QAAM,WAAW,MAAM,MAAM,YAAY;AAAA,IACvC,UAAU,QAAQ;AAAA,IAClB,aAAa,qBAAqB,QAAQ,aAAa,aAAa;AAAA,IACpE,kBAAkB,qBAAqB,QAAQ,kBAAkB,kBAAkB;AAAA,IACnF;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,eAAe,QAAQ;AAAA,IACvB;AAAA,EACF,CAAC;AACD,SAAO,SAAS,OAAO,QAAQ;AAC/B,QAAM,aAAa;AACrB;AAEA,eAAsB,2BACpB,OACA,SAMA,SACA;AACA,QAAM,EAAE,eAAe,MAAM,IAAI,MAAM,qBAAqB;AAC5D,QAAM,WAAW,MAAM,MAAM,YAAY;AAAA,IACvC,UAAU,QAAQ;AAAA,IAClB,aAAa,qBAAqB,QAAQ,aAAa,aAAa;AAAA,IACpE,kBAAkB,qBAAqB,QAAQ,kBAAkB,kBAAkB;AAAA,IACnF,0BAA0B,qBAAqB,OAAO,SAAS,MAAM,0BAA0B;AAAA,IAC/F;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,eAAe,QAAQ;AAAA,EACzB,CAAC;AACD,SAAO,SAAS,OAAO,QAAQ;AAC/B,QAAM,aAAa;AACrB;AAOA,SAAS,kCAAkC;AACzC,QAAM,iBAAiB,CAAC,QAAQ,OAAO;AACvC,QAAM,cAAc,IAAI,IAAI,OAAO,SAAS,IAAI;AAChD,aAAW,SAAS,gBAAgB;AAClC,QAAI,CAAC,YAAY,aAAa,IAAI,KAAK,GAAG;AACxC,cAAQ,KAAK,IAAI,MAAM,uDAAuD,KAAK,2EAA2E,CAAC;AAC/J,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAAgB,YAAY,aAAa,IAAI,OAAO,KAAK,SAAS,uDAAuD;AAC/H,QAAM,eAAe,8BAA8B,aAAa;AAEhE,MAAI,CAAC,cAAc;AAGjB,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAWZ;AACD,WAAO;AAAA,EACT;AAGA,QAAM,SAAS,IAAI,IAAI,WAAW;AAClC,aAAW,SAAS,gBAAgB;AAClC,WAAO,aAAa,OAAO,KAAK;AAAA,EAClC;AAQA,SAAO,QAAQ,aAAa,CAAC,GAAG,IAAI,OAAO,SAAS,CAAC;AAErD,SAAO;AAAA,IACL;AAAA,IACA,cAAc,aAAa;AAAA,IAC3B,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,kBACpB,OACA,aACA;AAIA,QAAM,WAAW,gCAAgC;AACjD,MAAI,CAAC,SAAU,QAAO,OAAO,GAAG,MAAS;AAKzC,MAAI;AACF,WAAO,OAAO,GAAG,MAAM,MAAM,kBAAkB;AAAA,MAC7C,aAAa,SAAS,YAAY;AAAA,MAClC,aAAa,qBAAqB,aAAa,aAAa;AAAA,MAC5D,cAAc,SAAS;AAAA,MACvB,OAAO,SAAS;AAAA,IAClB,CAAC,CAAC;AAAA,EACJ,SAAS,GAAG;AACV,QAAI,WAAW,aAAa,CAAC,GAAG;AAC9B,YAAM;AAAA,IACR;AACA,UAAM,IAAI,oBAAoB,6DAA6D,EAAE,OAAO,EAAE,CAAC;AAAA,EACzG;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/cookie.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { isBrowserLike } from '@stackframe/stack-shared/dist/utils/env';\nimport { StackAssertionError } from '@stackframe/stack-shared/dist/utils/errors';\nimport Cookies from \"js-cookie\";\nimport { calculatePKCECodeChallenge, generateRandomCodeVerifier, generateRandomState } from \"oauth4webapi\";\n\n\n// INFO: This file is used to manage cookies. It also sets some cookie flags automatically, see this description.\n//\n// It provides asynchronous setCookie, getCookie, deleteCookie, etc. functions that can be used in various environments\n// (browser + Next.js for now). Under the hood, they just get a CookieHelper object and then set the cookies there.\n//\n// The CookieHelper object is a simple object that lets you set, get and delete cookies synchronously. Acquiring one\n// is asynchronous (except for browser environments, where they can be acquired synchronously), but once you have it,\n// you can use it synchronously. This function is useful if you cannot await in the calling code, but otherwise you\n// should prefer to await the functions directly.\n//\n// Some cookie flags are set automatically by the CookieHelper (and hence also the <xyz>Cookie functions).\n// In particular:\n// - SameSite is set to `Lax` by default, which is already true in Chromium-based browsers, so this creates\n// compatibility with other browsers that use either Strict or None (particularly Safari and Firefox, and older\n// versions of Chrome). If Partitioned is automatically set (as described below), then this value is set to `None`\n// instead.\n// - Secure is set depending on whether we could successfully determine that the client is on HTTPS. For this, we use a\n// set of heuristics:\n// - In a browser environment, we check window.location.protocol which is always accurate\n// - In a Next.js server environment:\n// - First we check the `stack-is-https` cookie, which is set in various places on the\n// client with a Secure attribute. If that one is passed on to the server, we know that the client is on HTTPS\n// and we can set the Secure flag on the cookie. TODO: Should we also do this with a second cookie with a\n// __Host- prefix, so a malicious subdomain of the current domain cannot forcibly enable HTTPS mode and\n// therefore prevent new cookies from being set?\n// - Otherwise, we check the X-Forwarded-Proto header. If that one is `https`, we know that the client is\n// (pretending to be) on HTTPS and we can set the Secure flag on the cookie. Note that this header is\n// spoofable by malicious clients (so is the cookie actually), but since setting this value can only *increase*\n// security (and therefore prevent setting of a cookie), and requires a malicious client, this is still safe.\n// - If neither of the above is true, we don't set the Secure flag on the cookie.\n// - Partitioned is set depending on whether it is needed & supported. Unfortunately, the fact that Partitioned\n// cookies require SameSite=None, browsers that don't support it will still set them as normal third-party cookies,\n// which are fundamentally unsafe. Therefore, we need to take extra care that we only ever set Partitioned cookies\n// if we know for sure that the browser supports it.\n// - In a browser environment, we check:\n// - Whether `Secure` is set. If it's not, we don't set Partitioned.\n// - Whether we can set & retrieve cookies without Partitioned being set. If this is the case, we are likely in a\n// top-level context or a browser that partitions cookies by default (eg. Firefox). In this case, we don't need\n// Partitioned and can just proceed as normal.\n// - Whether CHIPS is supported. To prevent the case where CHIPS is not supported but third-party cookies are (in\n// which we would accidentally set SameSite=None without Partitioned as the latter requires the former), we\n// check this by running a simple test with document.cookie.\n// - Whether the browser supports Partitioned cookies. If yes, set Partitioned. Otherwise, don't set Partitioned.\n// Since there's no easy cross-compat way to do this (CookieStore and document.cookie do not return whether a\n// cookie is partitioned on some/all versions of Safari and Firefox), we use a heuristic; we run this test by\n// creating two cookies with the same name: One with Partitioned and one without. If there are two resulting\n// cookies, that means they were put into different jars, implying that the browser supports Partitioned cookies\n// (but doesn't partition cookies by default). If they result in just one cookie, that could mean that the\n// browser doesn't support Partitioned cookies, or that the browser doesn't put partitioned cookies into\n// different jars by default, in which case we still don't know. This heuristic works on Chrome, but may\n// incorrectly conclude that some other browsers don't support Partitioned. But from a security perspective,\n// that is better than accidentally setting SameSite=None without Partitioned. TODO: Find a better heuristic to\n// to determine whether the browser supports Partitioned cookies or not.\n// - In a Next.js server environment, right now we do nothing because of the complexity involved :( TODO: In the\n// future, we could improve this for example by setting hint cookies from the client, but we need to make sure that\n// no malicious actor (eg. on a malicious subdomain) can forcefully enable Partitioned cookies on a browser that\n// does not support it.\n\n\ntype SetCookieOptions = { maxAge: number | \"session\", noOpIfServerComponent?: boolean, domain?: string, secure?: boolean };\ntype DeleteCookieOptions = { noOpIfServerComponent?: boolean, domain?: string };\n\nfunction ensureClient() {\n if (!isBrowserLike()) {\n throw new Error(\"cookieClient functions can only be called in a browser environment, yet window is undefined\");\n }\n}\n\nexport type CookieHelper = {\n get: (name: string) => string | null,\n getAll: () => Record<string, string>,\n set: (name: string, value: string, options: SetCookieOptions) => void,\n setOrDelete: (name: string, value: string | null, options: SetCookieOptions & DeleteCookieOptions) => void,\n delete: (name: string, options: DeleteCookieOptions) => void,\n};\n\nconst placeholderCookieHelperIdentity = { \"placeholder cookie helper identity\": true };\nexport async function createPlaceholderCookieHelper(): Promise<CookieHelper> {\n function throwError(): never {\n throw new StackAssertionError(\"Throwing cookie helper is just a placeholder. This should never be called\");\n }\n return {\n get: throwError,\n getAll: throwError,\n set: throwError,\n setOrDelete: throwError,\n delete: throwError,\n };\n}\n\nexport async function createCookieHelper(): Promise<CookieHelper> {\n if (isBrowserLike()) {\n return createBrowserCookieHelper();\n } else {\n return await createPlaceholderCookieHelper();\n }\n}\n\nexport function createBrowserCookieHelper(): CookieHelper {\n return {\n get: getCookieClient,\n getAll: getAllCookiesClient,\n set: setCookieClient,\n setOrDelete: setOrDeleteCookieClient,\n delete: deleteCookieClient,\n };\n}\n\nfunction handleCookieError(e: unknown, options: DeleteCookieOptions | SetCookieOptions) {\n if (e instanceof Error && e.message.includes(\"Cookies can only be modified in\")) {\n if (options.noOpIfServerComponent) {\n // ignore\n } else {\n throw new StackAssertionError(\"Attempted to set cookie in server component. Pass { noOpIfServerComponent: true } in the options of Stack's cookie functions if this is intentional and you want to ignore this error. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#options\");\n }\n } else {\n throw e;\n }\n}\n\n\nexport function getCookieClient(name: string): string | null {\n const all = getAllCookiesClient();\n return all[name] ?? null;\n}\n\nexport function getAllCookiesClient(): Record<string, string> {\n ensureClient();\n // set a helper cookie, see comment in `NextCookieHelper.set` above\n Cookies.set(\"stack-is-https\", \"true\", { secure: true, expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365) });\n return Cookies.get();\n}\n\nexport async function getCookie(name: string): Promise<string | null> {\n const cookieHelper = await createCookieHelper();\n return cookieHelper.get(name);\n}\n\nexport async function isSecure(): Promise<boolean> {\n if (isBrowserLike()) {\n return determineSecureFromClientContext();\n }\n return false;\n}\n\nfunction determineSecureFromClientContext(): boolean {\n return typeof window !== \"undefined\" && window.location.protocol === \"https:\";\n}\n\n\nlet _shouldSetPartitionedClientCache: boolean | undefined = undefined;\nfunction shouldSetPartitionedClient() {\n return _shouldSetPartitionedClientCache ??= _internalShouldSetPartitionedClient();\n}\nfunction _internalShouldSetPartitionedClient() {\n ensureClient();\n\n if (!(determineSecureFromClientContext())) {\n return false;\n }\n\n // check whether we can set & retrieve normal cookies (either because we're on a top-level/same-origin context or the browser partitions cookies by default)\n const cookie1Name = \"__Host-stack-temporary-chips-test-\" + Math.random().toString(36).substring(2, 15);\n document.cookie = `${cookie1Name}=value1; Secure; path=/`;\n const cookies1 = document.cookie.split(\"; \");\n document.cookie = `${cookie1Name}=delete1; Secure; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;`;\n if (cookies1.some((c) => c.startsWith(cookie1Name + \"=\"))) {\n return false;\n }\n\n\n // check whether Partitioned cookies are supported by the browser\n // TODO: See comment at the top. Feels like we should find a better way to do this\n const cookie2Name = \"__Host-stack-temporary-chips-test-\" + Math.random().toString(36).substring(2, 15);\n\n // just to be safe, delete the cookie first to avoid weird RNG-prediction attacks\n // I don't know what they look like (since this is a host cookie) but better safe than sorry\n // (this function should be 100% bulletproof so we don't accidentally fall back to non-partitioned third party cookies on unsupported browsers)\n document.cookie = `${cookie2Name}=delete1; Secure; SameSite=None; Partitioned; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n document.cookie = `${cookie2Name}=delete2; Secure; SameSite=None; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n\n // set the cookie, once partitioned and once not partitioned\n document.cookie = `${cookie2Name}=set1; Secure; SameSite=None; Partitioned; path=/`;\n document.cookie = `${cookie2Name}=set2; Secure; SameSite=None; path=/`;\n\n // check if there are two cookies\n const cookies2 = document.cookie.split(\"; \");\n const numberOfCookiesWithThisName = cookies2.filter((c) => c.startsWith(cookie2Name + \"=\")).length;\n\n // clean up\n document.cookie = `${cookie2Name}=delete3; Secure; SameSite=None; Partitioned; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n document.cookie = `${cookie2Name}=delete4; Secure; SameSite=None; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n\n return numberOfCookiesWithThisName === 2;\n}\n\nfunction setCookieClientInternal(name: string, value: string, options: SetCookieOptions) {\n const secure = options.secure ?? determineSecureFromClientContext();\n const partitioned = shouldSetPartitionedClient();\n Cookies.set(name, value, {\n expires: options.maxAge === \"session\" ? undefined : new Date(Date.now() + (options.maxAge) * 1000),\n domain: options.domain,\n secure,\n sameSite: \"Lax\",\n ...(partitioned ? {\n partitioned,\n sameSite: \"None\",\n } : {}),\n });\n}\n\nfunction deleteCookieClientInternal(name: string, options: DeleteCookieOptions) {\n for (const partitioned of [true, false]) {\n if (options.domain !== undefined) {\n Cookies.remove(name, { domain: options.domain, secure: determineSecureFromClientContext(), partitioned });\n }\n Cookies.remove(name, { secure: determineSecureFromClientContext(), partitioned });\n }\n}\n\nexport function setOrDeleteCookieClient(name: string, value: string | null, options: SetCookieOptions & DeleteCookieOptions) {\n ensureClient();\n if (value === null) {\n deleteCookieClientInternal(name, options);\n } else {\n setCookieClientInternal(name, value, options);\n }\n}\n\nexport async function setOrDeleteCookie(name: string, value: string | null, options: SetCookieOptions & DeleteCookieOptions) {\n const cookieHelper = await createCookieHelper();\n cookieHelper.setOrDelete(name, value, options);\n}\n\nexport function deleteCookieClient(name: string, options: DeleteCookieOptions) {\n ensureClient();\n deleteCookieClientInternal(name, options);\n}\n\nexport async function deleteCookie(name: string, options: DeleteCookieOptions) {\n const cookieHelper = await createCookieHelper();\n cookieHelper.delete(name, options);\n}\n\nexport function setCookieClient(name: string, value: string, options: SetCookieOptions) {\n ensureClient();\n setCookieClientInternal(name, value, options);\n}\n\nexport async function setCookie(name: string, value: string, options: SetCookieOptions) {\n const cookieHelper = await createCookieHelper();\n cookieHelper.set(name, value, options);\n}\n\nexport async function saveVerifierAndState() {\n const codeVerifier = generateRandomCodeVerifier();\n const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);\n const state = generateRandomState();\n\n await setCookie(\"stack-oauth-outer-\" + state, codeVerifier, { maxAge: 60 * 60 });\n\n return {\n codeChallenge,\n state,\n };\n}\n\nexport function consumeVerifierAndStateCookie(state: string) {\n ensureClient();\n const cookieName = \"stack-oauth-outer-\" + state;\n const codeVerifier = getCookieClient(cookieName);\n if (!codeVerifier) {\n return null;\n }\n deleteCookieClient(cookieName, {});\n return {\n codeVerifier,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/cookie.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { isBrowserLike } from '@stackframe/stack-shared/dist/utils/env';\nimport { StackAssertionError } from '@stackframe/stack-shared/dist/utils/errors';\nimport Cookies from \"js-cookie\";\nimport { calculatePKCECodeChallenge, generateRandomCodeVerifier, generateRandomState } from \"oauth4webapi\";\n\n\n// INFO: This file is used to manage cookies. It also sets some cookie flags automatically, see this description.\n//\n// It provides asynchronous setCookie, getCookie, deleteCookie, etc. functions that can be used in various environments\n// (browser + Next.js for now). Under the hood, they just get a CookieHelper object and then set the cookies there.\n//\n// The CookieHelper object is a simple object that lets you set, get and delete cookies synchronously. Acquiring one\n// is asynchronous (except for browser environments, where they can be acquired synchronously), but once you have it,\n// you can use it synchronously. This function is useful if you cannot await in the calling code, but otherwise you\n// should prefer to await the functions directly.\n//\n// Some cookie flags are set automatically by the CookieHelper (and hence also the <xyz>Cookie functions).\n// In particular:\n// - SameSite is set to `Lax` by default, which is already true in Chromium-based browsers, so this creates\n// compatibility with other browsers that use either Strict or None (particularly Safari and Firefox, and older\n// versions of Chrome). If Partitioned is automatically set (as described below), then this value is set to `None`\n// instead.\n// - Secure is set depending on whether we could successfully determine that the client is on HTTPS. For this, we use a\n// set of heuristics:\n// - In a browser environment, we check window.location.protocol which is always accurate\n// - In a Next.js server environment:\n// - First we check the `stack-is-https` cookie, which is set in various places on the\n// client with a Secure attribute. If that one is passed on to the server, we know that the client is on HTTPS\n// and we can set the Secure flag on the cookie. TODO: Should we also do this with a second cookie with a\n// __Host- prefix, so a malicious subdomain of the current domain cannot forcibly enable HTTPS mode and\n// therefore prevent new cookies from being set?\n// - Otherwise, we check the X-Forwarded-Proto header. If that one is `https`, we know that the client is\n// (pretending to be) on HTTPS and we can set the Secure flag on the cookie. Note that this header is\n// spoofable by malicious clients (so is the cookie actually), but since setting this value can only *increase*\n// security (and therefore prevent setting of a cookie), and requires a malicious client, this is still safe.\n// - If neither of the above is true, we don't set the Secure flag on the cookie.\n// - Partitioned is set depending on whether it is needed & supported. Unfortunately, the fact that Partitioned\n// cookies require SameSite=None, browsers that don't support it will still set them as normal third-party cookies,\n// which are fundamentally unsafe. Therefore, we need to take extra care that we only ever set Partitioned cookies\n// if we know for sure that the browser supports it.\n// - In a browser environment, we check:\n// - Whether `Secure` is set. If it's not, we don't set Partitioned.\n// - Whether we can set & retrieve cookies without Partitioned being set. If this is the case, we are likely in a\n// top-level context or a browser that partitions cookies by default (eg. Firefox). In this case, we don't need\n// Partitioned and can just proceed as normal.\n// - Whether CHIPS is supported. To prevent the case where CHIPS is not supported but third-party cookies are (in\n// which we would accidentally set SameSite=None without Partitioned as the latter requires the former), we\n// check this by running a simple test with document.cookie.\n// - Whether the browser supports Partitioned cookies. If yes, set Partitioned. Otherwise, don't set Partitioned.\n// Since there's no easy cross-compat way to do this (CookieStore and document.cookie do not return whether a\n// cookie is partitioned on some/all versions of Safari and Firefox), we use a heuristic; we run this test by\n// creating two cookies with the same name: One with Partitioned and one without. If there are two resulting\n// cookies, that means they were put into different jars, implying that the browser supports Partitioned cookies\n// (but doesn't partition cookies by default). If they result in just one cookie, that could mean that the\n// browser doesn't support Partitioned cookies, or that the browser doesn't put partitioned cookies into\n// different jars by default, in which case we still don't know. This heuristic works on Chrome, but may\n// incorrectly conclude that some other browsers don't support Partitioned. But from a security perspective,\n// that is better than accidentally setting SameSite=None without Partitioned. TODO: Find a better heuristic to\n// to determine whether the browser supports Partitioned cookies or not.\n// - In a Next.js server environment, right now we do nothing because of the complexity involved :( TODO: In the\n// future, we could improve this for example by setting hint cookies from the client, but we need to make sure that\n// no malicious actor (eg. on a malicious subdomain) can forcefully enable Partitioned cookies on a browser that\n// does not support it.\n\n\ntype SetCookieOptions = { maxAge: number | \"session\", noOpIfServerComponent?: boolean, domain?: string, secure?: boolean };\ntype DeleteCookieOptions = { noOpIfServerComponent?: boolean, domain?: string };\n\nfunction ensureClient() {\n if (!isBrowserLike()) {\n throw new Error(\"cookieClient functions can only be called in a browser environment, yet window is undefined\");\n }\n}\n\nexport type CookieHelper = {\n get: (name: string) => string | null,\n getAll: () => Record<string, string>,\n set: (name: string, value: string, options: SetCookieOptions) => void,\n setOrDelete: (name: string, value: string | null, options: SetCookieOptions & DeleteCookieOptions) => void,\n delete: (name: string, options: DeleteCookieOptions) => void,\n};\n\nconst placeholderCookieHelperIdentity = { \"placeholder cookie helper identity\": true };\nexport async function createPlaceholderCookieHelper(): Promise<CookieHelper> {\n function throwError(): never {\n throw new StackAssertionError(\"Throwing cookie helper is just a placeholder. This should never be called\");\n }\n return {\n get: throwError,\n getAll: throwError,\n set: throwError,\n setOrDelete: throwError,\n delete: throwError,\n };\n}\n\nexport async function createCookieHelper(): Promise<CookieHelper> {\n if (isBrowserLike()) {\n return createBrowserCookieHelper();\n } else {\n return await createPlaceholderCookieHelper();\n }\n}\n\nexport function createBrowserCookieHelper(): CookieHelper {\n return {\n get: getCookieClient,\n getAll: getAllCookiesClient,\n set: setCookieClient,\n setOrDelete: setOrDeleteCookieClient,\n delete: deleteCookieClient,\n };\n}\n\nfunction handleCookieError(e: unknown, options: DeleteCookieOptions | SetCookieOptions) {\n if (e instanceof Error && e.message.includes(\"Cookies can only be modified in\")) {\n if (options.noOpIfServerComponent) {\n // ignore\n } else {\n throw new StackAssertionError(\"Attempted to set cookie in server component. Pass { noOpIfServerComponent: true } in the options of Stack's cookie functions if this is intentional and you want to ignore this error. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#options\");\n }\n } else {\n throw e;\n }\n}\n\n\nexport function getCookieClient(name: string): string | null {\n const all = getAllCookiesClient();\n return all[name] ?? null;\n}\n\nexport function getAllCookiesClient(): Record<string, string> {\n ensureClient();\n // set a helper cookie, see comment in `NextCookieHelper.set` above\n Cookies.set(\"stack-is-https\", \"true\", { secure: true, expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365) });\n return Cookies.get();\n}\n\nexport async function getCookie(name: string): Promise<string | null> {\n const cookieHelper = await createCookieHelper();\n return cookieHelper.get(name);\n}\n\nexport async function isSecure(): Promise<boolean> {\n if (isBrowserLike()) {\n return determineSecureFromClientContext();\n }\n return false;\n}\n\nfunction determineSecureFromClientContext(): boolean {\n return typeof window !== \"undefined\" && window.location.protocol === \"https:\";\n}\n\n\nlet _shouldSetPartitionedClientCache: boolean | undefined = undefined;\nfunction shouldSetPartitionedClient() {\n return _shouldSetPartitionedClientCache ??= _internalShouldSetPartitionedClient();\n}\nfunction _internalShouldSetPartitionedClient() {\n ensureClient();\n\n if (!(determineSecureFromClientContext())) {\n return false;\n }\n\n // check whether we can set & retrieve normal cookies (either because we're on a top-level/same-origin context or the browser partitions cookies by default)\n const cookie1Name = \"__Host-stack-temporary-chips-test-\" + Math.random().toString(36).substring(2, 15);\n document.cookie = `${cookie1Name}=value1; Secure; path=/`;\n const cookies1 = document.cookie.split(\"; \");\n document.cookie = `${cookie1Name}=delete1; Secure; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;`;\n if (cookies1.some((c) => c.startsWith(cookie1Name + \"=\"))) {\n return false;\n }\n\n\n // check whether Partitioned cookies are supported by the browser\n // TODO: See comment at the top. Feels like we should find a better way to do this\n const cookie2Name = \"__Host-stack-temporary-chips-test-\" + Math.random().toString(36).substring(2, 15);\n\n // just to be safe, delete the cookie first to avoid weird RNG-prediction attacks\n // I don't know what they look like (since this is a host cookie) but better safe than sorry\n // (this function should be 100% bulletproof so we don't accidentally fall back to non-partitioned third party cookies on unsupported browsers)\n document.cookie = `${cookie2Name}=delete1; Secure; SameSite=None; Partitioned; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n document.cookie = `${cookie2Name}=delete2; Secure; SameSite=None; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n\n // set the cookie, once partitioned and once not partitioned\n document.cookie = `${cookie2Name}=set1; Secure; SameSite=None; Partitioned; path=/`;\n document.cookie = `${cookie2Name}=set2; Secure; SameSite=None; path=/`;\n\n // check if there are two cookies\n const cookies2 = document.cookie.split(\"; \");\n const numberOfCookiesWithThisName = cookies2.filter((c) => c.startsWith(cookie2Name + \"=\")).length;\n\n // clean up\n document.cookie = `${cookie2Name}=delete3; Secure; SameSite=None; Partitioned; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n document.cookie = `${cookie2Name}=delete4; Secure; SameSite=None; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n\n return numberOfCookiesWithThisName === 2;\n}\n\nfunction setCookieClientInternal(name: string, value: string, options: SetCookieOptions) {\n const secure = options.secure ?? determineSecureFromClientContext();\n const partitioned = shouldSetPartitionedClient();\n Cookies.set(name, value, {\n expires: options.maxAge === \"session\" ? undefined : new Date(Date.now() + (options.maxAge) * 1000),\n domain: options.domain,\n secure,\n sameSite: \"Lax\",\n ...(partitioned ? {\n partitioned,\n sameSite: \"None\",\n } : {}),\n });\n}\n\nfunction deleteCookieClientInternal(name: string, options: DeleteCookieOptions) {\n for (const partitioned of [true, false]) {\n if (options.domain !== undefined) {\n Cookies.remove(name, { domain: options.domain, secure: determineSecureFromClientContext(), partitioned });\n }\n Cookies.remove(name, { secure: determineSecureFromClientContext(), partitioned });\n }\n}\n\nexport function setOrDeleteCookieClient(name: string, value: string | null, options: SetCookieOptions & DeleteCookieOptions) {\n ensureClient();\n if (value === null) {\n deleteCookieClientInternal(name, options);\n } else {\n setCookieClientInternal(name, value, options);\n }\n}\n\nexport async function setOrDeleteCookie(name: string, value: string | null, options: SetCookieOptions & DeleteCookieOptions) {\n const cookieHelper = await createCookieHelper();\n cookieHelper.setOrDelete(name, value, options);\n}\n\nexport function deleteCookieClient(name: string, options: DeleteCookieOptions) {\n ensureClient();\n deleteCookieClientInternal(name, options);\n}\n\nexport async function deleteCookie(name: string, options: DeleteCookieOptions) {\n const cookieHelper = await createCookieHelper();\n cookieHelper.delete(name, options);\n}\n\nexport function setCookieClient(name: string, value: string, options: SetCookieOptions) {\n ensureClient();\n setCookieClientInternal(name, value, options);\n}\n\nexport async function setCookie(name: string, value: string, options: SetCookieOptions) {\n const cookieHelper = await createCookieHelper();\n cookieHelper.set(name, value, options);\n}\n\nexport async function saveVerifierAndState() {\n const codeVerifier = generateRandomCodeVerifier();\n const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);\n const state = generateRandomState();\n\n await setCookie(\"stack-oauth-outer-\" + state, codeVerifier, { maxAge: 60 * 60 });\n\n return {\n codeChallenge,\n state,\n };\n}\n\nexport function consumeVerifierAndStateCookie(state: string) {\n ensureClient();\n const cookieName = \"stack-oauth-outer-\" + state;\n const codeVerifier = getCookieClient(cookieName);\n if (!codeVerifier) {\n return null;\n }\n deleteCookieClient(cookieName, {});\n return {\n codeVerifier,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/stack-app/api-keys/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { TeamApiKeysCrud, UserApiKeysCrud, teamApiKeysCreateInputSchema, userApiKeysCreateInputSchema } from \"@stackframe/stack-shared/dist/interface/crud/project-api-keys\";\nimport { filterUndefined } from \"@stackframe/stack-shared/dist/utils/objects\";\nimport { IfAndOnlyIf, PrettifyType } from \"@stackframe/stack-shared/dist/utils/types\";\nimport type * as yup from \"yup\";\n\nexport type ApiKeyType = \"user\" | \"team\";\n\nexport type ApiKey<Type extends ApiKeyType = ApiKeyType, IsFirstView extends boolean = false> =\n & {\n id: string,\n description: string,\n expiresAt?: Date,\n manuallyRevokedAt?: Date | null,\n createdAt: Date,\n value: IfAndOnlyIf<IsFirstView, true, string, { lastFour: string }>,\n update(options: ApiKeyUpdateOptions<Type>): Promise<void>,\n revoke: () => Promise<void>,\n isValid: () => boolean,\n whyInvalid: () => \"manually-revoked\" | \"expired\" | null,\n }\n & (\n | (\"user\" extends Type ? { type: \"user\", userId: string } : never)\n | (\"team\" extends Type ? { type: \"team\", teamId: string } : never)\n );\n\nexport type UserApiKeyFirstView = PrettifyType<ApiKey<\"user\", true>>;\nexport type UserApiKey = PrettifyType<ApiKey<\"user\", false>>;\n\nexport type TeamApiKeyFirstView = PrettifyType<ApiKey<\"team\", true>>;\nexport type TeamApiKey = PrettifyType<ApiKey<\"team\", false>>;\n\nexport type ApiKeyCreationOptions<Type extends ApiKeyType = ApiKeyType> =\n & {\n description: string,\n expiresAt: Date | null,\n /**\n * Whether the API key should be considered public. A public API key will not be detected by the secret scanner, which\n * automatically revokes API keys when it detects that they may have been exposed to the public.\n */\n isPublic?: boolean,\n };\nexport function apiKeyCreationOptionsToCrud(type: \"user\", userId: string, options: ApiKeyCreationOptions<\"user\">): Promise<yup.InferType<typeof userApiKeysCreateInputSchema>>;\nexport function apiKeyCreationOptionsToCrud(type: \"team\", teamId: string, options: ApiKeyCreationOptions<\"team\">): Promise<yup.InferType<typeof teamApiKeysCreateInputSchema>>;\nexport function apiKeyCreationOptionsToCrud(type: ApiKeyType, userIdOrTeamId: string, options: ApiKeyCreationOptions): Promise<yup.InferType<typeof userApiKeysCreateInputSchema> | yup.InferType<typeof teamApiKeysCreateInputSchema>>;\nexport async function apiKeyCreationOptionsToCrud(type: ApiKeyType, userIdOrTeamId: string, options: ApiKeyCreationOptions): Promise<yup.InferType<typeof userApiKeysCreateInputSchema> | yup.InferType<typeof teamApiKeysCreateInputSchema>> {\n return {\n description: options.description,\n expires_at_millis: options.expiresAt == null ? options.expiresAt : options.expiresAt.getTime(),\n is_public: options.isPublic,\n ...(type === \"user\" ? { user_id: userIdOrTeamId } : { team_id: userIdOrTeamId }),\n };\n}\n\n\nexport type ApiKeyUpdateOptions<Type extends ApiKeyType = ApiKeyType> = {\n description?: string,\n expiresAt?: Date | null,\n revoked?: boolean,\n};\nexport function apiKeyUpdateOptionsToCrud(type: \"user\", options: ApiKeyUpdateOptions<\"user\">): Promise<UserApiKeysCrud[\"Client\"][\"Update\"]>;\nexport function apiKeyUpdateOptionsToCrud(type: \"team\", options: ApiKeyUpdateOptions<\"team\">): Promise<TeamApiKeysCrud[\"Client\"][\"Update\"]>;\nexport function apiKeyUpdateOptionsToCrud(type: ApiKeyType, options: ApiKeyUpdateOptions): Promise<UserApiKeysCrud[\"Client\"][\"Update\"] | TeamApiKeysCrud[\"Client\"][\"Update\"]>;\nexport async function apiKeyUpdateOptionsToCrud(type: ApiKeyType, options: ApiKeyUpdateOptions): Promise<UserApiKeysCrud[\"Client\"][\"Update\"] | TeamApiKeysCrud[\"Client\"][\"Update\"]> {\n return filterUndefined({\n description: options.description,\n expires_at_millis: options.expiresAt == null ? options.expiresAt : options.expiresAt.getTime(),\n revoked: options.revoked,\n });\n}\n"],"mappings":";AAKA,SAAS,uBAAuB;AA2ChC,eAAsB,4BAA4B,MAAkB,gBAAwB,SAAkJ;AAC5O,SAAO;AAAA,IACL,aAAa,QAAQ;AAAA,IACrB,mBAAmB,QAAQ,aAAa,OAAO,QAAQ,YAAY,QAAQ,UAAU,QAAQ;AAAA,IAC7F,WAAW,QAAQ;AAAA,IACnB,GAAI,SAAS,SAAS,EAAE,SAAS,eAAe,IAAI,EAAE,SAAS,eAAe;AAAA,EAChF;AACF;AAWA,eAAsB,0BAA0B,MAAkB,SAAkH;AAClL,SAAO,gBAAgB;AAAA,IACrB,aAAa,QAAQ;AAAA,IACrB,mBAAmB,QAAQ,aAAa,OAAO,QAAQ,YAAY,QAAQ,UAAU,QAAQ;AAAA,IAC7F,SAAS,QAAQ;AAAA,EACnB,CAAC;AACH;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/stack-app/api-keys/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { TeamApiKeysCrud, UserApiKeysCrud, teamApiKeysCreateInputSchema, userApiKeysCreateInputSchema } from \"@stackframe/stack-shared/dist/interface/crud/project-api-keys\";\nimport { filterUndefined } from \"@stackframe/stack-shared/dist/utils/objects\";\nimport { IfAndOnlyIf, PrettifyType } from \"@stackframe/stack-shared/dist/utils/types\";\nimport type * as yup from \"yup\";\n\nexport type ApiKeyType = \"user\" | \"team\";\n\nexport type ApiKey<Type extends ApiKeyType = ApiKeyType, IsFirstView extends boolean = false> =\n & {\n id: string,\n description: string,\n expiresAt?: Date,\n manuallyRevokedAt?: Date | null,\n createdAt: Date,\n value: IfAndOnlyIf<IsFirstView, true, string, { lastFour: string }>,\n update(options: ApiKeyUpdateOptions<Type>): Promise<void>,\n revoke: () => Promise<void>,\n isValid: () => boolean,\n whyInvalid: () => \"manually-revoked\" | \"expired\" | null,\n }\n & (\n | (\"user\" extends Type ? { type: \"user\", userId: string } : never)\n | (\"team\" extends Type ? { type: \"team\", teamId: string } : never)\n );\n\nexport type UserApiKeyFirstView = PrettifyType<ApiKey<\"user\", true>>;\nexport type UserApiKey = PrettifyType<ApiKey<\"user\", false>>;\n\nexport type TeamApiKeyFirstView = PrettifyType<ApiKey<\"team\", true>>;\nexport type TeamApiKey = PrettifyType<ApiKey<\"team\", false>>;\n\nexport type ApiKeyCreationOptions<Type extends ApiKeyType = ApiKeyType> =\n & {\n description: string,\n expiresAt: Date | null,\n /**\n * Whether the API key should be considered public. A public API key will not be detected by the secret scanner, which\n * automatically revokes API keys when it detects that they may have been exposed to the public.\n */\n isPublic?: boolean,\n };\nexport function apiKeyCreationOptionsToCrud(type: \"user\", userId: string, options: ApiKeyCreationOptions<\"user\">): Promise<yup.InferType<typeof userApiKeysCreateInputSchema>>;\nexport function apiKeyCreationOptionsToCrud(type: \"team\", teamId: string, options: ApiKeyCreationOptions<\"team\">): Promise<yup.InferType<typeof teamApiKeysCreateInputSchema>>;\nexport function apiKeyCreationOptionsToCrud(type: ApiKeyType, userIdOrTeamId: string, options: ApiKeyCreationOptions): Promise<yup.InferType<typeof userApiKeysCreateInputSchema> | yup.InferType<typeof teamApiKeysCreateInputSchema>>;\nexport async function apiKeyCreationOptionsToCrud(type: ApiKeyType, userIdOrTeamId: string, options: ApiKeyCreationOptions): Promise<yup.InferType<typeof userApiKeysCreateInputSchema> | yup.InferType<typeof teamApiKeysCreateInputSchema>> {\n return {\n description: options.description,\n expires_at_millis: options.expiresAt == null ? options.expiresAt : options.expiresAt.getTime(),\n is_public: options.isPublic,\n ...(type === \"user\" ? { user_id: userIdOrTeamId } : { team_id: userIdOrTeamId }),\n };\n}\n\n\nexport type ApiKeyUpdateOptions<Type extends ApiKeyType = ApiKeyType> = {\n description?: string,\n expiresAt?: Date | null,\n revoked?: boolean,\n};\nexport function apiKeyUpdateOptionsToCrud(type: \"user\", options: ApiKeyUpdateOptions<\"user\">): Promise<UserApiKeysCrud[\"Client\"][\"Update\"]>;\nexport function apiKeyUpdateOptionsToCrud(type: \"team\", options: ApiKeyUpdateOptions<\"team\">): Promise<TeamApiKeysCrud[\"Client\"][\"Update\"]>;\nexport function apiKeyUpdateOptionsToCrud(type: ApiKeyType, options: ApiKeyUpdateOptions): Promise<UserApiKeysCrud[\"Client\"][\"Update\"] | TeamApiKeysCrud[\"Client\"][\"Update\"]>;\nexport async function apiKeyUpdateOptionsToCrud(type: ApiKeyType, options: ApiKeyUpdateOptions): Promise<UserApiKeysCrud[\"Client\"][\"Update\"] | TeamApiKeysCrud[\"Client\"][\"Update\"]> {\n return filterUndefined({\n description: options.description,\n expires_at_millis: options.expiresAt == null ? options.expiresAt : options.expiresAt.getTime(),\n revoked: options.revoked,\n });\n}\n"],"mappings":";AAKA,SAAS,uBAAuB;AA2ChC,eAAsB,4BAA4B,MAAkB,gBAAwB,SAAkJ;AAC5O,SAAO;AAAA,IACL,aAAa,QAAQ;AAAA,IACrB,mBAAmB,QAAQ,aAAa,OAAO,QAAQ,YAAY,QAAQ,UAAU,QAAQ;AAAA,IAC7F,WAAW,QAAQ;AAAA,IACnB,GAAI,SAAS,SAAS,EAAE,SAAS,eAAe,IAAI,EAAE,SAAS,eAAe;AAAA,EAChF;AACF;AAWA,eAAsB,0BAA0B,MAAkB,SAAkH;AAClL,SAAO,gBAAgB;AAAA,IACrB,aAAa,QAAQ;AAAA,IACrB,mBAAmB,QAAQ,aAAa,OAAO,QAAQ,YAAY,QAAQ,UAAU,QAAQ;AAAA,IAC7F,SAAS,QAAQ;AAAA,EACnB,CAAC;AACH;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/lib/stack-app/apps/implementations/admin-app-impl.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { StackAdminInterface } from \"@stackframe/stack-shared\";\nimport { getProductionModeErrors } from \"@stackframe/stack-shared/dist/helpers/production-mode\";\nimport { InternalApiKeyCreateCrudResponse } from \"@stackframe/stack-shared/dist/interface/admin-interface\";\nimport { EmailTemplateCrud } from \"@stackframe/stack-shared/dist/interface/crud/email-templates\";\nimport { InternalApiKeysCrud } from \"@stackframe/stack-shared/dist/interface/crud/internal-api-keys\";\nimport { ProjectsCrud } from \"@stackframe/stack-shared/dist/interface/crud/projects\";\nimport type { Transaction, TransactionType } from \"@stackframe/stack-shared/dist/interface/crud/transactions\";\nimport { StackAssertionError, throwErr } from \"@stackframe/stack-shared/dist/utils/errors\";\nimport { pick } from \"@stackframe/stack-shared/dist/utils/objects\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport { AdminEmailOutbox, AdminSentEmail } from \"../..\";\nimport { EmailConfig, stackAppInternalsSymbol } from \"../../common\";\nimport { AdminEmailTemplate } from \"../../email-templates\";\nimport { InternalApiKey, InternalApiKeyBase, InternalApiKeyBaseCrudRead, InternalApiKeyCreateOptions, InternalApiKeyFirstView, internalApiKeyCreateOptionsToCrud } from \"../../internal-api-keys\";\nimport { AdminProjectPermission, AdminProjectPermissionDefinition, AdminProjectPermissionDefinitionCreateOptions, AdminProjectPermissionDefinitionUpdateOptions, AdminTeamPermission, AdminTeamPermissionDefinition, AdminTeamPermissionDefinitionCreateOptions, AdminTeamPermissionDefinitionUpdateOptions, adminProjectPermissionDefinitionCreateOptionsToCrud, adminProjectPermissionDefinitionUpdateOptionsToCrud, adminTeamPermissionDefinitionCreateOptionsToCrud, adminTeamPermissionDefinitionUpdateOptionsToCrud } from \"../../permissions\";\nimport { AdminOwnedProject, AdminProject, AdminProjectUpdateOptions, adminProjectUpdateOptionsToCrud } from \"../../projects\";\nimport { StackAdminApp, StackAdminAppConstructorOptions } from \"../interfaces/admin-app\";\nimport { clientVersion, createCache, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getDefaultSecretServerKey, getDefaultSuperSecretAdminKey, resolveConstructorOptions } from \"./common\";\nimport { _StackServerAppImplIncomplete } from \"./server-app-impl\";\n\nimport { CompleteConfig, EnvironmentConfigOverrideOverride } from \"@stackframe/stack-shared/dist/config/schema\";\nimport { ChatContent } from \"@stackframe/stack-shared/dist/interface/admin-interface\";\n\nexport class _StackAdminAppImplIncomplete<HasTokenStore extends boolean, ProjectId extends string> extends _StackServerAppImplIncomplete<HasTokenStore, ProjectId> implements StackAdminApp<HasTokenStore, ProjectId> {\n declare protected _interface: StackAdminInterface;\n\n private readonly _adminProjectCache = createCache(async () => {\n return await this._interface.getProject();\n });\n private readonly _internalApiKeysCache = createCache(async () => {\n const res = await this._interface.listInternalApiKeys();\n return res;\n });\n private readonly _adminEmailThemeCache = createCache(async ([id]: [string]) => {\n return await this._interface.getEmailTheme(id);\n });\n private readonly _adminEmailThemesCache = createCache(async () => {\n return await this._interface.listEmailThemes();\n });\n private readonly _adminEmailTemplatesCache = createCache(async () => {\n return await this._interface.listInternalEmailTemplates();\n });\n private readonly _adminEmailDraftsCache = createCache(async () => {\n return await this._interface.listInternalEmailDrafts();\n });\n private readonly _adminTeamPermissionDefinitionsCache = createCache(async () => {\n return await this._interface.listTeamPermissionDefinitions();\n });\n private readonly _adminProjectPermissionDefinitionsCache = createCache(async () => {\n return await this._interface.listProjectPermissionDefinitions();\n });\n private readonly _svixTokenCache = createCache(async () => {\n return await this._interface.getSvixToken();\n });\n private readonly _metricsCache = createCache(async ([includeAnonymous]: [boolean]) => {\n return await this._interface.getMetrics(includeAnonymous);\n });\n private readonly _emailPreviewCache = createCache(async ([themeId, themeTsxSource, templateId, templateTsxSource]: [string | null | false | undefined, string | undefined, string | undefined, string | undefined]) => {\n return await this._interface.renderEmailPreview({ themeId, themeTsxSource, templateId, templateTsxSource });\n });\n private readonly _configOverridesCache = createCache(async () => {\n return await this._interface.getConfig();\n });\n private readonly _stripeAccountInfoCache = createCache(async () => {\n try {\n return await this._interface.getStripeAccountInfo();\n } catch (error: any) {\n if (error?.status === 404) {\n return null;\n }\n throw error;\n }\n });\n private readonly _transactionsCache = createCache(async ([cursor, limit, type, customerType]: [string | undefined, number | undefined, TransactionType | undefined, 'user' | 'team' | 'custom' | undefined]) => {\n return await this._interface.listTransactions({ cursor, limit, type, customerType });\n });\n\n constructor(options: StackAdminAppConstructorOptions<HasTokenStore, ProjectId>, extraOptions?: { uniqueIdentifier?: string, checkString?: string, interface?: StackAdminInterface }) {\n const resolvedOptions = resolveConstructorOptions(options);\n\n super(resolvedOptions, {\n ...extraOptions,\n interface: extraOptions?.interface ?? new StackAdminInterface({\n getBaseUrl: () => getBaseUrl(resolvedOptions.baseUrl),\n projectId: resolvedOptions.projectId ?? getDefaultProjectId(),\n extraRequestHeaders: resolvedOptions.extraRequestHeaders ?? getDefaultExtraRequestHeaders(),\n clientVersion,\n ...resolvedOptions.projectOwnerSession ? {\n projectOwnerSession: resolvedOptions.projectOwnerSession,\n } : {\n publishableClientKey: resolvedOptions.publishableClientKey ?? getDefaultPublishableClientKey(),\n secretServerKey: resolvedOptions.secretServerKey ?? getDefaultSecretServerKey(),\n superSecretAdminKey: resolvedOptions.superSecretAdminKey ?? getDefaultSuperSecretAdminKey(),\n },\n }),\n });\n }\n\n _adminConfigFromCrud(data: { config_string: string }): CompleteConfig {\n return JSON.parse(data.config_string);\n }\n\n _adminOwnedProjectFromCrud(data: ProjectsCrud['Admin']['Read'], onRefresh: () => Promise<void>): AdminOwnedProject {\n if (this._tokenStoreInit !== null) {\n throw new StackAssertionError(\"Owned apps must always have tokenStore === null — did you not create this project with app._createOwnedApp()?\");\n }\n return {\n ...this._adminProjectFromCrud(data, onRefresh),\n app: this as StackAdminApp<false>,\n };\n }\n\n _adminProjectFromCrud(data: ProjectsCrud['Admin']['Read'], onRefresh: () => Promise<void>): AdminProject {\n if (data.id !== this.projectId) {\n throw new StackAssertionError(`The project ID of the provided project JSON (${data.id}) does not match the project ID of the app (${this.projectId})!`);\n }\n\n const app = this;\n return {\n id: data.id,\n displayName: data.display_name,\n description: data.description,\n createdAt: new Date(data.created_at_millis),\n isProductionMode: data.is_production_mode,\n ownerTeamId: data.owner_team_id,\n logoUrl: data.logo_url,\n logoFullUrl: data.logo_full_url,\n logoDarkModeUrl: data.logo_dark_mode_url,\n logoFullDarkModeUrl: data.logo_full_dark_mode_url,\n config: {\n signUpEnabled: data.config.sign_up_enabled,\n credentialEnabled: data.config.credential_enabled,\n magicLinkEnabled: data.config.magic_link_enabled,\n passkeyEnabled: data.config.passkey_enabled,\n clientTeamCreationEnabled: data.config.client_team_creation_enabled,\n clientUserDeletionEnabled: data.config.client_user_deletion_enabled,\n allowLocalhost: data.config.allow_localhost,\n oauthAccountMergeStrategy: data.config.oauth_account_merge_strategy,\n allowUserApiKeys: data.config.allow_user_api_keys,\n allowTeamApiKeys: data.config.allow_team_api_keys,\n oauthProviders: data.config.oauth_providers.map((p) => ((p.type === 'shared' ? {\n id: p.id,\n type: 'shared',\n } as const : {\n id: p.id,\n type: 'standard',\n clientId: p.client_id ?? throwErr(\"Client ID is missing\"),\n clientSecret: p.client_secret ?? throwErr(\"Client secret is missing\"),\n facebookConfigId: p.facebook_config_id,\n microsoftTenantId: p.microsoft_tenant_id,\n } as const))),\n emailConfig: data.config.email_config.type === 'shared' ? {\n type: 'shared'\n } : {\n type: 'standard',\n host: data.config.email_config.host ?? throwErr(\"Email host is missing\"),\n port: data.config.email_config.port ?? throwErr(\"Email port is missing\"),\n username: data.config.email_config.username ?? throwErr(\"Email username is missing\"),\n password: data.config.email_config.password ?? throwErr(\"Email password is missing\"),\n senderName: data.config.email_config.sender_name ?? throwErr(\"Email sender name is missing\"),\n senderEmail: data.config.email_config.sender_email ?? throwErr(\"Email sender email is missing\"),\n },\n emailTheme: data.config.email_theme,\n domains: data.config.domains.map((d) => ({\n domain: d.domain,\n handlerPath: d.handler_path,\n })),\n createTeamOnSignUp: data.config.create_team_on_sign_up,\n teamCreatorDefaultPermissions: data.config.team_creator_default_permissions,\n teamMemberDefaultPermissions: data.config.team_member_default_permissions,\n userDefaultPermissions: data.config.user_default_permissions,\n },\n async getConfig() {\n return app._adminConfigFromCrud(await app._interface.getConfig());\n },\n async updateConfig(configOverride: EnvironmentConfigOverrideOverride) {\n await app._interface.updateConfig({ configOverride });\n await app._configOverridesCache.refresh([]);\n },\n async update(update: AdminProjectUpdateOptions) {\n const updateOptions = adminProjectUpdateOptionsToCrud(update);\n await app._interface.updateProject(updateOptions);\n await onRefresh();\n },\n async delete() {\n await app._interface.deleteProject();\n },\n async getProductionModeErrors() {\n return getProductionModeErrors(data);\n },\n };\n }\n\n _adminEmailTemplateFromCrud(data: EmailTemplateCrud['Admin']['Read']): AdminEmailTemplate {\n return {\n type: data.type,\n subject: data.subject,\n content: data.content,\n isDefault: data.is_default,\n };\n }\n\n override async getProject(): Promise<AdminProject> {\n return this._adminProjectFromCrud(\n Result.orThrow(await this._adminProjectCache.getOrWait([], \"write-only\")),\n () => this._refreshProject()\n );\n }\n\n\n protected _createInternalApiKeyBaseFromCrud(data: InternalApiKeyBaseCrudRead): InternalApiKeyBase {\n const app = this;\n return {\n id: data.id,\n description: data.description,\n expiresAt: new Date(data.expires_at_millis),\n manuallyRevokedAt: data.manually_revoked_at_millis ? new Date(data.manually_revoked_at_millis) : null,\n createdAt: new Date(data.created_at_millis),\n isValid() {\n return this.whyInvalid() === null;\n },\n whyInvalid() {\n if (this.expiresAt.getTime() < Date.now()) return \"expired\";\n if (this.manuallyRevokedAt) return \"manually-revoked\";\n return null;\n },\n async revoke() {\n const res = await app._interface.revokeInternalApiKeyById(data.id);\n await app._refreshInternalApiKeys();\n return res;\n }\n };\n }\n\n protected _createInternalApiKeyFromCrud(data: InternalApiKeysCrud[\"Admin\"][\"Read\"]): InternalApiKey {\n return {\n ...this._createInternalApiKeyBaseFromCrud(data),\n publishableClientKey: data.publishable_client_key ? { lastFour: data.publishable_client_key.last_four } : null,\n secretServerKey: data.secret_server_key ? { lastFour: data.secret_server_key.last_four } : null,\n superSecretAdminKey: data.super_secret_admin_key ? { lastFour: data.super_secret_admin_key.last_four } : null,\n };\n }\n\n protected _createInternalApiKeyFirstViewFromCrud(data: InternalApiKeyCreateCrudResponse): InternalApiKeyFirstView {\n return {\n ...this._createInternalApiKeyBaseFromCrud(data),\n publishableClientKey: data.publishable_client_key,\n secretServerKey: data.secret_server_key,\n superSecretAdminKey: data.super_secret_admin_key,\n };\n }\n\n async listInternalApiKeys(): Promise<InternalApiKey[]> {\n const crud = Result.orThrow(await this._internalApiKeysCache.getOrWait([], \"write-only\"));\n return crud.map((j) => this._createInternalApiKeyFromCrud(j));\n }\n\n\n async createInternalApiKey(options: InternalApiKeyCreateOptions): Promise<InternalApiKeyFirstView> {\n const crud = await this._interface.createInternalApiKey(internalApiKeyCreateOptionsToCrud(options));\n await this._refreshInternalApiKeys();\n return this._createInternalApiKeyFirstViewFromCrud(crud);\n }\n\n\n async listEmailThemes(): Promise<{ id: string, displayName: string }[]> {\n const crud = Result.orThrow(await this._adminEmailThemesCache.getOrWait([], \"write-only\"));\n return crud.map((theme) => ({\n id: theme.id,\n displayName: theme.display_name,\n }));\n }\n\n async listEmailTemplates(): Promise<{ id: string, displayName: string, themeId?: string, tsxSource: string }[]> {\n const crud = Result.orThrow(await this._adminEmailTemplatesCache.getOrWait([], \"write-only\"));\n return crud.map((template) => ({\n id: template.id,\n displayName: template.display_name,\n themeId: template.theme_id,\n tsxSource: template.tsx_source,\n }));\n }\n\n async listEmailDrafts(): Promise<{ id: string, displayName: string, themeId: string | undefined | false, tsxSource: string, sentAt: Date | null }[]> {\n const crud = Result.orThrow(await this._adminEmailDraftsCache.getOrWait([], \"write-only\"));\n return crud.map((draft) => ({\n id: draft.id,\n displayName: draft.display_name,\n themeId: draft.theme_id,\n tsxSource: draft.tsx_source,\n sentAt: draft.sent_at_millis ? new Date(draft.sent_at_millis) : null,\n }));\n }\n\n\n async createTeamPermissionDefinition(data: AdminTeamPermissionDefinitionCreateOptions): Promise<AdminTeamPermission> {\n const crud = await this._interface.createTeamPermissionDefinition(adminTeamPermissionDefinitionCreateOptionsToCrud(data));\n await this._adminTeamPermissionDefinitionsCache.refresh([]);\n return this._serverTeamPermissionDefinitionFromCrud(crud);\n }\n\n async updateTeamPermissionDefinition(permissionId: string, data: AdminTeamPermissionDefinitionUpdateOptions) {\n await this._interface.updateTeamPermissionDefinition(permissionId, adminTeamPermissionDefinitionUpdateOptionsToCrud(data));\n await this._adminTeamPermissionDefinitionsCache.refresh([]);\n }\n\n async deleteTeamPermissionDefinition(permissionId: string): Promise<void> {\n await this._interface.deleteTeamPermissionDefinition(permissionId);\n await this._adminTeamPermissionDefinitionsCache.refresh([]);\n }\n\n async listTeamPermissionDefinitions(): Promise<AdminTeamPermissionDefinition[]> {\n const crud = Result.orThrow(await this._adminTeamPermissionDefinitionsCache.getOrWait([], \"write-only\"));\n return crud.map((p) => this._serverTeamPermissionDefinitionFromCrud(p));\n }\n\n\n async createProjectPermissionDefinition(data: AdminProjectPermissionDefinitionCreateOptions): Promise<AdminProjectPermission> {\n const crud = await this._interface.createProjectPermissionDefinition(adminProjectPermissionDefinitionCreateOptionsToCrud(data));\n await this._adminProjectPermissionDefinitionsCache.refresh([]);\n return this._serverProjectPermissionDefinitionFromCrud(crud);\n }\n\n async updateProjectPermissionDefinition(permissionId: string, data: AdminProjectPermissionDefinitionUpdateOptions) {\n await this._interface.updateProjectPermissionDefinition(permissionId, adminProjectPermissionDefinitionUpdateOptionsToCrud(data));\n await this._adminProjectPermissionDefinitionsCache.refresh([]);\n }\n\n async deleteProjectPermissionDefinition(permissionId: string): Promise<void> {\n await this._interface.deleteProjectPermissionDefinition(permissionId);\n await this._adminProjectPermissionDefinitionsCache.refresh([]);\n }\n\n async listProjectPermissionDefinitions(): Promise<AdminProjectPermissionDefinition[]> {\n const crud = Result.orThrow(await this._adminProjectPermissionDefinitionsCache.getOrWait([], \"write-only\"));\n return crud.map((p) => this._serverProjectPermissionDefinitionFromCrud(p));\n }\n\n\n protected override async _refreshProject() {\n await Promise.all([\n super._refreshProject(),\n this._adminProjectCache.refresh([]),\n ]);\n }\n\n protected async _refreshInternalApiKeys() {\n await this._internalApiKeysCache.refresh([]);\n }\n\n protected override async _refreshUsers() {\n await Promise.all([\n super._refreshUsers(),\n this._metricsCache.refresh([false]),\n this._metricsCache.refresh([true]),\n ]);\n }\n\n get [stackAppInternalsSymbol]() {\n return {\n ...super[stackAppInternalsSymbol],\n };\n }\n\n async sendTestEmail(options: {\n recipientEmail: string,\n emailConfig: EmailConfig,\n }): Promise<Result<undefined, { errorMessage: string }>> {\n const response = await this._interface.sendTestEmail({\n recipient_email: options.recipientEmail,\n email_config: {\n ...(pick(options.emailConfig, ['host', 'port', 'username', 'password'])),\n sender_email: options.emailConfig.senderEmail,\n sender_name: options.emailConfig.senderName,\n },\n });\n\n if (response.success) {\n return Result.ok(undefined);\n } else {\n return Result.error({ errorMessage: response.error_message ?? throwErr(\"Email test error not specified\") });\n }\n }\n\n async sendTestWebhook(options: { endpointId: string }): Promise<Result<undefined, { errorMessage: string }>> {\n const response = await this._interface.sendTestWebhook({\n endpoint_id: options.endpointId,\n });\n\n if (response.success) {\n return Result.ok(undefined);\n } else {\n return Result.error({ errorMessage: response.error_message ?? throwErr(\"Webhook test error not specified\") });\n }\n }\n\n async listSentEmails(): Promise<AdminSentEmail[]> {\n const response = await this._interface.listSentEmails();\n return response.items.map((email) => ({\n id: email.id,\n to: email.to ?? [],\n subject: email.subject,\n recipient: email.to?.[0] ?? \"\",\n sentAt: new Date(email.sent_at_millis),\n error: email.error,\n }));\n }\n\n async sendSignInInvitationEmail(email: string, callbackUrl: string): Promise<void> {\n await this._interface.sendSignInInvitationEmail(email, callbackUrl);\n }\n\n async createEmailTemplate(displayName: string): Promise<{ id: string }> {\n const result = await this._interface.createEmailTemplate(displayName);\n await this._adminEmailTemplatesCache.refresh([]);\n return result;\n }\n\n async createEmailDraft(options: { displayName: string, themeId?: string | false, tsxSource?: string }): Promise<{ id: string }> {\n const result = await this._interface.createEmailDraft({\n display_name: options.displayName,\n theme_id: options.themeId,\n tsx_source: options.tsxSource,\n });\n await this._adminEmailDraftsCache.refresh([]);\n return result;\n }\n\n async updateEmailDraft(id: string, data: { displayName?: string, themeId?: string | undefined | false, tsxSource?: string }): Promise<void> {\n await this._interface.updateEmailDraft(id, {\n display_name: data.displayName,\n theme_id: data.themeId,\n tsx_source: data.tsxSource,\n });\n await this._adminEmailDraftsCache.refresh([]);\n }\n\n async sendChatMessage(\n threadId: string,\n contextType: \"email-theme\" | \"email-template\" | \"email-draft\",\n messages: Array<{ role: string, content: any }>,\n abortSignal?: AbortSignal,\n ): Promise<{ content: ChatContent }> {\n return await this._interface.sendChatMessage(threadId, contextType, messages, abortSignal);\n }\n\n async saveChatMessage(threadId: string, message: any): Promise<void> {\n await this._interface.saveChatMessage(threadId, message);\n }\n\n async listChatMessages(threadId: string): Promise<{ messages: Array<any> }> {\n return await this._interface.listChatMessages(threadId);\n }\n\n async createEmailTheme(displayName: string): Promise<{ id: string }> {\n const result = await this._interface.createEmailTheme(displayName);\n await this._adminEmailThemesCache.refresh([]);\n return result;\n }\n\n async getEmailPreview(options: { themeId?: string | null | false, themeTsxSource?: string, templateId?: string, templateTsxSource?: string }): Promise<string> {\n return (await this._interface.renderEmailPreview(options)).html;\n }\n async updateEmailTheme(id: string, tsxSource: string): Promise<void> {\n await this._interface.updateEmailTheme(id, tsxSource);\n }\n async updateEmailTemplate(id: string, tsxSource: string, themeId: string | null | false): Promise<{ renderedHtml: string }> {\n const result = await this._interface.updateEmailTemplate(id, tsxSource, themeId);\n await this._adminEmailTemplatesCache.refresh([]);\n return { renderedHtml: result.rendered_html };\n }\n\n async setupPayments(): Promise<{ url: string }> {\n return await this._interface.setupPayments();\n }\n\n async createStripeWidgetAccountSession(): Promise<{ client_secret: string }> {\n return await this._interface.createStripeWidgetAccountSession();\n }\n\n async createItemQuantityChange(options: (\n { userId: string, itemId: string, quantity: number, expiresAt?: string, description?: string } |\n { teamId: string, itemId: string, quantity: number, expiresAt?: string, description?: string } |\n { customCustomerId: string, itemId: string, quantity: number, expiresAt?: string, description?: string }\n )): Promise<void> {\n await this._interface.updateItemQuantity(\n { itemId: options.itemId, ...(\"userId\" in options ? { userId: options.userId } : (\"teamId\" in options ? { teamId: options.teamId } : { customCustomerId: options.customCustomerId })) },\n {\n delta: options.quantity,\n expires_at: options.expiresAt,\n description: options.description,\n allow_negative: true,\n }\n );\n }\n\n async refundTransaction(options: { type: \"subscription\" | \"one-time-purchase\", id: string }): Promise<void> {\n await this._interface.refundTransaction({ type: options.type, id: options.id });\n await this._transactionsCache.invalidateWhere(() => true);\n }\n\n async listTransactions(params: { cursor?: string, limit?: number, type?: TransactionType, customerType?: 'user' | 'team' | 'custom' }): Promise<{ transactions: Transaction[], nextCursor: string | null }> {\n const crud = Result.orThrow(await this._transactionsCache.getOrWait([params.cursor, params.limit, params.type, params.customerType] as const, \"write-only\"));\n return crud;\n }\n\n // Email Outbox methods\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Complex discriminated union conversion from API response\n private _emailOutboxCrudToAdmin(crud: any): AdminEmailOutbox {\n const recipient = crud.to;\n let to: AdminEmailOutbox[\"to\"];\n if (recipient.type === \"user-primary-email\") {\n to = { type: \"user-primary-email\", userId: recipient.user_id };\n } else if (recipient.type === \"user-custom-emails\") {\n to = { type: \"user-custom-emails\", userId: recipient.user_id, emails: recipient.emails };\n } else {\n to = { type: \"custom-emails\", emails: recipient.emails };\n }\n\n // Base fields present on all emails\n const base = {\n id: crud.id as string,\n createdAt: new Date(crud.created_at_millis),\n updatedAt: new Date(crud.updated_at_millis),\n to,\n scheduledAt: new Date(crud.scheduled_at_millis),\n isPaused: false as const,\n hasRendered: false as const,\n hasDelivered: false as const,\n };\n\n // Rendered fields (available after rendering completes successfully)\n const rendered = crud.has_rendered ? {\n ...base,\n startedRenderingAt: new Date(crud.started_rendering_at_millis),\n renderedAt: new Date(crud.rendered_at_millis),\n subject: crud.subject as string,\n html: crud.html as string | null,\n text: crud.text as string | null,\n isTransactional: crud.is_transactional as boolean,\n isHighPriority: crud.is_high_priority as boolean,\n notificationCategoryId: crud.notification_category_id as string | null,\n hasRendered: true as const,\n } : null;\n\n // Started sending fields\n const startedSending = rendered && crud.started_sending_at_millis ? {\n ...rendered,\n startedSendingAt: new Date(crud.started_sending_at_millis),\n } : null;\n\n // Finished delivering fields\n const finishedDelivering = startedSending && crud.has_delivered ? {\n ...startedSending,\n deliveredAt: new Date(crud.delivered_at_millis),\n hasDelivered: true as const,\n } : null;\n\n // Use type assertion at the end because TypeScript has trouble with\n // spread + override patterns on discriminated unions with const literal types\n const result = (() => {\n switch (crud.status) {\n case \"paused\": {\n return {\n ...base,\n status: \"paused\" as const,\n simpleStatus: \"in-progress\" as const,\n isPaused: true as const,\n };\n }\n case \"preparing\": {\n return {\n ...base,\n status: \"preparing\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"rendering\": {\n return {\n ...base,\n status: \"rendering\" as const,\n simpleStatus: \"in-progress\" as const,\n startedRenderingAt: new Date(crud.started_rendering_at_millis),\n };\n }\n case \"render-error\": {\n return {\n ...base,\n status: \"render-error\" as const,\n simpleStatus: \"error\" as const,\n startedRenderingAt: new Date(crud.started_rendering_at_millis),\n renderedAt: new Date(crud.rendered_at_millis),\n renderError: crud.render_error,\n };\n }\n case \"scheduled\": {\n return {\n ...rendered!,\n status: \"scheduled\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"queued\": {\n return {\n ...rendered!,\n status: \"queued\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"sending\": {\n return {\n ...startedSending!,\n status: \"sending\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"server-error\": {\n return {\n ...startedSending!,\n status: \"server-error\" as const,\n simpleStatus: \"error\" as const,\n errorAt: new Date(crud.error_at_millis),\n serverError: crud.server_error,\n };\n }\n case \"skipped\": {\n return {\n ...base,\n status: \"skipped\" as const,\n simpleStatus: \"ok\" as const,\n skippedAt: new Date(crud.skipped_at_millis),\n skippedReason: crud.skipped_reason,\n skippedDetails: crud.skipped_details ?? {},\n hasRendered: crud.has_rendered as boolean,\n // Optional fields\n startedRenderingAt: crud.started_rendering_at_millis ? new Date(crud.started_rendering_at_millis) : undefined,\n renderedAt: crud.rendered_at_millis ? new Date(crud.rendered_at_millis) : undefined,\n subject: crud.subject,\n html: crud.html,\n text: crud.text,\n isTransactional: crud.is_transactional,\n isHighPriority: crud.is_high_priority,\n notificationCategoryId: crud.notification_category_id,\n startedSendingAt: crud.started_sending_at_millis ? new Date(crud.started_sending_at_millis) : undefined,\n };\n }\n case \"bounced\": {\n return {\n ...startedSending!,\n status: \"bounced\" as const,\n simpleStatus: \"error\" as const,\n bouncedAt: new Date(crud.bounced_at_millis),\n };\n }\n case \"delivery-delayed\": {\n return {\n ...startedSending!,\n status: \"delivery-delayed\" as const,\n simpleStatus: \"ok\" as const,\n deliveryDelayedAt: new Date(crud.delivery_delayed_at_millis),\n };\n }\n case \"sent\": {\n return {\n ...finishedDelivering!,\n status: \"sent\" as const,\n simpleStatus: \"ok\" as const,\n canHaveDeliveryInfo: crud.can_have_delivery_info,\n };\n }\n case \"opened\": {\n return {\n ...finishedDelivering!,\n status: \"opened\" as const,\n simpleStatus: \"ok\" as const,\n openedAt: new Date(crud.opened_at_millis),\n canHaveDeliveryInfo: true as const,\n };\n }\n case \"clicked\": {\n return {\n ...finishedDelivering!,\n status: \"clicked\" as const,\n simpleStatus: \"ok\" as const,\n clickedAt: new Date(crud.clicked_at_millis),\n canHaveDeliveryInfo: true as const,\n };\n }\n case \"marked-as-spam\": {\n return {\n ...finishedDelivering!,\n status: \"marked-as-spam\" as const,\n simpleStatus: \"ok\" as const,\n markedAsSpamAt: new Date(crud.marked_as_spam_at_millis),\n canHaveDeliveryInfo: true as const,\n };\n }\n default: {\n throw new StackAssertionError(`Unknown email outbox status: ${crud.status}`, { status: crud.status });\n }\n }\n })();\n // The type system has difficulty with spread + override patterns on discriminated unions,\n // so we use a type assertion here. The switch statement above ensures we return the correct shape.\n return result as AdminEmailOutbox;\n }\n\n async listOutboxEmails(options?: { status?: string, simpleStatus?: string, limit?: number, cursor?: string }): Promise<{ items: AdminEmailOutbox[], nextCursor: string | null }> {\n const response = await this._interface.listOutboxEmails({\n status: options?.status,\n simple_status: options?.simpleStatus,\n limit: options?.limit,\n cursor: options?.cursor,\n });\n return {\n items: response.items.map((item) => this._emailOutboxCrudToAdmin(item)),\n nextCursor: response.pagination?.next_cursor ?? null,\n };\n }\n\n async getOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n const response = await this._interface.getOutboxEmail(id);\n return this._emailOutboxCrudToAdmin(response);\n }\n\n async updateOutboxEmail(id: string, options: { isPaused?: boolean, scheduledAtMillis?: number, cancel?: boolean }): Promise<AdminEmailOutbox> {\n const response = await this._interface.updateOutboxEmail(id, {\n is_paused: options.isPaused,\n scheduled_at_millis: options.scheduledAtMillis,\n cancel: options.cancel,\n });\n return this._emailOutboxCrudToAdmin(response);\n }\n\n async pauseOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n return await this.updateOutboxEmail(id, { isPaused: true });\n }\n\n async unpauseOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n return await this.updateOutboxEmail(id, { isPaused: false });\n }\n\n async cancelOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n return await this.updateOutboxEmail(id, { cancel: true });\n }\n\n\n async getStripeAccountInfo(): Promise<null | { account_id: string, charges_enabled: boolean, details_submitted: boolean, payouts_enabled: boolean }> {\n return await this._interface.getStripeAccountInfo();\n }\n\n\n async previewAffectedUsersByOnboardingChange(\n onboarding: { requireEmailVerification?: boolean },\n limit?: number,\n ): Promise<{\n affectedUsers: Array<{\n id: string,\n displayName: string | null,\n primaryEmail: string | null,\n restrictedReason: { type: \"anonymous\" | \"email_not_verified\" },\n }>,\n totalAffectedCount: number,\n }> {\n const result = await this._interface.previewAffectedUsersByOnboardingChange(\n { require_email_verification: onboarding.requireEmailVerification },\n limit,\n );\n return {\n affectedUsers: result.affected_users.map(u => ({\n id: u.id,\n displayName: u.display_name,\n primaryEmail: u.primary_email,\n restrictedReason: u.restricted_reason as { type: \"anonymous\" | \"email_not_verified\" },\n })),\n totalAffectedCount: result.total_affected_count,\n };\n }\n}\n"],"mappings":";AAIA,SAAS,2BAA2B;AACpC,SAAS,+BAA+B;AAMxC,SAAS,qBAAqB,gBAAgB;AAC9C,SAAS,YAAY;AACrB,SAAS,cAAc;AAEvB,SAAsB,+BAA+B;AAErD,SAA+H,yCAAyC;AACxK,SAA6S,qDAAqD,qDAAqD,kDAAkD,wDAAwD;AACjgB,SAAqE,uCAAuC;AAE5G,SAAS,eAAe,aAAa,YAAY,+BAA+B,qBAAqB,gCAAgC,2BAA2B,+BAA+B,iCAAiC;AAChO,SAAS,qCAAqC;AAKvC,IAAM,+BAAN,cAAoG,8BAA2G;AAAA,EAsDpN,YAAY,SAAoE,cAAqG;AACnL,UAAM,kBAAkB,0BAA0B,OAAO;AAEzD,UAAM,iBAAiB;AAAA,MACrB,GAAG;AAAA,MACH,WAAW,cAAc,aAAa,IAAI,oBAAoB;AAAA,QAC5D,YAAY,MAAM,WAAW,gBAAgB,OAAO;AAAA,QACpD,WAAW,gBAAgB,aAAa,oBAAoB;AAAA,QAC5D,qBAAqB,gBAAgB,uBAAuB,8BAA8B;AAAA,QAC1F;AAAA,QACA,GAAG,gBAAgB,sBAAsB;AAAA,UACvC,qBAAqB,gBAAgB;AAAA,QACvC,IAAI;AAAA,UACF,sBAAsB,gBAAgB,wBAAwB,+BAA+B;AAAA,UAC7F,iBAAiB,gBAAgB,mBAAmB,0BAA0B;AAAA,UAC9E,qBAAqB,gBAAgB,uBAAuB,8BAA8B;AAAA,QAC5F;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AArEH,SAAiB,qBAAqB,YAAY,YAAY;AAC5D,aAAO,MAAM,KAAK,WAAW,WAAW;AAAA,IAC1C,CAAC;AACD,SAAiB,wBAAwB,YAAY,YAAY;AAC/D,YAAM,MAAM,MAAM,KAAK,WAAW,oBAAoB;AACtD,aAAO;AAAA,IACT,CAAC;AACD,SAAiB,wBAAwB,YAAY,OAAO,CAAC,EAAE,MAAgB;AAC7E,aAAO,MAAM,KAAK,WAAW,cAAc,EAAE;AAAA,IAC/C,CAAC;AACD,SAAiB,yBAAyB,YAAY,YAAY;AAChE,aAAO,MAAM,KAAK,WAAW,gBAAgB;AAAA,IAC/C,CAAC;AACD,SAAiB,4BAA4B,YAAY,YAAY;AACnE,aAAO,MAAM,KAAK,WAAW,2BAA2B;AAAA,IAC1D,CAAC;AACD,SAAiB,yBAAyB,YAAY,YAAY;AAChE,aAAO,MAAM,KAAK,WAAW,wBAAwB;AAAA,IACvD,CAAC;AACD,SAAiB,uCAAuC,YAAY,YAAY;AAC9E,aAAO,MAAM,KAAK,WAAW,8BAA8B;AAAA,IAC7D,CAAC;AACD,SAAiB,0CAA0C,YAAY,YAAY;AACjF,aAAO,MAAM,KAAK,WAAW,iCAAiC;AAAA,IAChE,CAAC;AACD,SAAiB,kBAAkB,YAAY,YAAY;AACzD,aAAO,MAAM,KAAK,WAAW,aAAa;AAAA,IAC5C,CAAC;AACD,SAAiB,gBAAgB,YAAY,OAAO,CAAC,gBAAgB,MAAiB;AACpF,aAAO,MAAM,KAAK,WAAW,WAAW,gBAAgB;AAAA,IAC1D,CAAC;AACD,SAAiB,qBAAqB,YAAY,OAAO,CAAC,SAAS,gBAAgB,YAAY,iBAAiB,MAAuG;AACrN,aAAO,MAAM,KAAK,WAAW,mBAAmB,EAAE,SAAS,gBAAgB,YAAY,kBAAkB,CAAC;AAAA,IAC5G,CAAC;AACD,SAAiB,wBAAwB,YAAY,YAAY;AAC/D,aAAO,MAAM,KAAK,WAAW,UAAU;AAAA,IACzC,CAAC;AACD,SAAiB,0BAA0B,YAAY,YAAY;AACjE,UAAI;AACF,eAAO,MAAM,KAAK,WAAW,qBAAqB;AAAA,MACpD,SAAS,OAAY;AACnB,YAAI,OAAO,WAAW,KAAK;AACzB,iBAAO;AAAA,QACT;AACA,cAAM;AAAA,MACR;AAAA,IACF,CAAC;AACD,SAAiB,qBAAqB,YAAY,OAAO,CAAC,QAAQ,OAAO,MAAM,YAAY,MAAqH;AAC9M,aAAO,MAAM,KAAK,WAAW,iBAAiB,EAAE,QAAQ,OAAO,MAAM,aAAa,CAAC;AAAA,IACrF,CAAC;AAAA,EAqBD;AAAA,EAEA,qBAAqB,MAAiD;AACpE,WAAO,KAAK,MAAM,KAAK,aAAa;AAAA,EACtC;AAAA,EAEA,2BAA2B,MAAqC,WAAmD;AACjH,QAAI,KAAK,oBAAoB,MAAM;AACjC,YAAM,IAAI,oBAAoB,oHAA+G;AAAA,IAC/I;AACA,WAAO;AAAA,MACL,GAAG,KAAK,sBAAsB,MAAM,SAAS;AAAA,MAC7C,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,sBAAsB,MAAqC,WAA8C;AACvG,QAAI,KAAK,OAAO,KAAK,WAAW;AAC9B,YAAM,IAAI,oBAAoB,gDAAgD,KAAK,EAAE,+CAA+C,KAAK,SAAS,IAAI;AAAA,IACxJ;AAEA,UAAM,MAAM;AACZ,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,MAC1C,kBAAkB,KAAK;AAAA,MACvB,aAAa,KAAK;AAAA,MAClB,SAAS,KAAK;AAAA,MACd,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK;AAAA,MACtB,qBAAqB,KAAK;AAAA,MAC1B,QAAQ;AAAA,QACN,eAAe,KAAK,OAAO;AAAA,QAC3B,mBAAmB,KAAK,OAAO;AAAA,QAC/B,kBAAkB,KAAK,OAAO;AAAA,QAC9B,gBAAgB,KAAK,OAAO;AAAA,QAC5B,2BAA2B,KAAK,OAAO;AAAA,QACvC,2BAA2B,KAAK,OAAO;AAAA,QACvC,gBAAgB,KAAK,OAAO;AAAA,QAC5B,2BAA2B,KAAK,OAAO;AAAA,QACvC,kBAAkB,KAAK,OAAO;AAAA,QAC9B,kBAAkB,KAAK,OAAO;AAAA,QAC9B,gBAAgB,KAAK,OAAO,gBAAgB,IAAI,CAAC,MAAQ,EAAE,SAAS,WAAW;AAAA,UAC7E,IAAI,EAAE;AAAA,UACN,MAAM;AAAA,QACR,IAAa;AAAA,UACX,IAAI,EAAE;AAAA,UACN,MAAM;AAAA,UACN,UAAU,EAAE,aAAa,SAAS,sBAAsB;AAAA,UACxD,cAAc,EAAE,iBAAiB,SAAS,0BAA0B;AAAA,UACpE,kBAAkB,EAAE;AAAA,UACpB,mBAAmB,EAAE;AAAA,QACvB,CAAY;AAAA,QACZ,aAAa,KAAK,OAAO,aAAa,SAAS,WAAW;AAAA,UACxD,MAAM;AAAA,QACR,IAAI;AAAA,UACF,MAAM;AAAA,UACN,MAAM,KAAK,OAAO,aAAa,QAAQ,SAAS,uBAAuB;AAAA,UACvE,MAAM,KAAK,OAAO,aAAa,QAAQ,SAAS,uBAAuB;AAAA,UACvE,UAAU,KAAK,OAAO,aAAa,YAAY,SAAS,2BAA2B;AAAA,UACnF,UAAU,KAAK,OAAO,aAAa,YAAY,SAAS,2BAA2B;AAAA,UACnF,YAAY,KAAK,OAAO,aAAa,eAAe,SAAS,8BAA8B;AAAA,UAC3F,aAAa,KAAK,OAAO,aAAa,gBAAgB,SAAS,+BAA+B;AAAA,QAChG;AAAA,QACA,YAAY,KAAK,OAAO;AAAA,QACxB,SAAS,KAAK,OAAO,QAAQ,IAAI,CAAC,OAAO;AAAA,UACvC,QAAQ,EAAE;AAAA,UACV,aAAa,EAAE;AAAA,QACjB,EAAE;AAAA,QACF,oBAAoB,KAAK,OAAO;AAAA,QAChC,+BAA+B,KAAK,OAAO;AAAA,QAC3C,8BAA8B,KAAK,OAAO;AAAA,QAC1C,wBAAwB,KAAK,OAAO;AAAA,MACtC;AAAA,MACA,MAAM,YAAY;AAChB,eAAO,IAAI,qBAAqB,MAAM,IAAI,WAAW,UAAU,CAAC;AAAA,MAClE;AAAA,MACA,MAAM,aAAa,gBAAmD;AACpE,cAAM,IAAI,WAAW,aAAa,EAAE,eAAe,CAAC;AACpD,cAAM,IAAI,sBAAsB,QAAQ,CAAC,CAAC;AAAA,MAC5C;AAAA,MACA,MAAM,OAAO,QAAmC;AAC9C,cAAM,gBAAgB,gCAAgC,MAAM;AAC5D,cAAM,IAAI,WAAW,cAAc,aAAa;AAChD,cAAM,UAAU;AAAA,MAClB;AAAA,MACA,MAAM,SAAS;AACb,cAAM,IAAI,WAAW,cAAc;AAAA,MACrC;AAAA,MACA,MAAM,0BAA0B;AAC9B,eAAO,wBAAwB,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,4BAA4B,MAA8D;AACxF,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAe,aAAoC;AACjD,WAAO,KAAK;AAAA,MACV,OAAO,QAAQ,MAAM,KAAK,mBAAmB,UAAU,CAAC,GAAG,YAAY,CAAC;AAAA,MACxE,MAAM,KAAK,gBAAgB;AAAA,IAC7B;AAAA,EACF;AAAA,EAGU,kCAAkC,MAAsD;AAChG,UAAM,MAAM;AACZ,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,aAAa,KAAK;AAAA,MAClB,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,MAC1C,mBAAmB,KAAK,6BAA6B,IAAI,KAAK,KAAK,0BAA0B,IAAI;AAAA,MACjG,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,MAC1C,UAAU;AACR,eAAO,KAAK,WAAW,MAAM;AAAA,MAC/B;AAAA,MACA,aAAa;AACX,YAAI,KAAK,UAAU,QAAQ,IAAI,KAAK,IAAI,EAAG,QAAO;AAClD,YAAI,KAAK,kBAAmB,QAAO;AACnC,eAAO;AAAA,MACT;AAAA,MACA,MAAM,SAAS;AACb,cAAM,MAAM,MAAM,IAAI,WAAW,yBAAyB,KAAK,EAAE;AACjE,cAAM,IAAI,wBAAwB;AAClC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EAEU,8BAA8B,MAA4D;AAClG,WAAO;AAAA,MACL,GAAG,KAAK,kCAAkC,IAAI;AAAA,MAC9C,sBAAsB,KAAK,yBAAyB,EAAE,UAAU,KAAK,uBAAuB,UAAU,IAAI;AAAA,MAC1G,iBAAiB,KAAK,oBAAoB,EAAE,UAAU,KAAK,kBAAkB,UAAU,IAAI;AAAA,MAC3F,qBAAqB,KAAK,yBAAyB,EAAE,UAAU,KAAK,uBAAuB,UAAU,IAAI;AAAA,IAC3G;AAAA,EACF;AAAA,EAEU,uCAAuC,MAAiE;AAChH,WAAO;AAAA,MACL,GAAG,KAAK,kCAAkC,IAAI;AAAA,MAC9C,sBAAsB,KAAK;AAAA,MAC3B,iBAAiB,KAAK;AAAA,MACtB,qBAAqB,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,MAAM,sBAAiD;AACrD,UAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,sBAAsB,UAAU,CAAC,GAAG,YAAY,CAAC;AACxF,WAAO,KAAK,IAAI,CAAC,MAAM,KAAK,8BAA8B,CAAC,CAAC;AAAA,EAC9D;AAAA,EAGA,MAAM,qBAAqB,SAAwE;AACjG,UAAM,OAAO,MAAM,KAAK,WAAW,qBAAqB,kCAAkC,OAAO,CAAC;AAClG,UAAM,KAAK,wBAAwB;AACnC,WAAO,KAAK,uCAAuC,IAAI;AAAA,EACzD;AAAA,EAGA,MAAM,kBAAkE;AACtE,UAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,uBAAuB,UAAU,CAAC,GAAG,YAAY,CAAC;AACzF,WAAO,KAAK,IAAI,CAAC,WAAW;AAAA,MAC1B,IAAI,MAAM;AAAA,MACV,aAAa,MAAM;AAAA,IACrB,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,qBAA0G;AAC9G,UAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,0BAA0B,UAAU,CAAC,GAAG,YAAY,CAAC;AAC5F,WAAO,KAAK,IAAI,CAAC,cAAc;AAAA,MAC7B,IAAI,SAAS;AAAA,MACb,aAAa,SAAS;AAAA,MACtB,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,IACtB,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,kBAA+I;AACnJ,UAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,uBAAuB,UAAU,CAAC,GAAG,YAAY,CAAC;AACzF,WAAO,KAAK,IAAI,CAAC,WAAW;AAAA,MAC1B,IAAI,MAAM;AAAA,MACV,aAAa,MAAM;AAAA,MACnB,SAAS,MAAM;AAAA,MACf,WAAW,MAAM;AAAA,MACjB,QAAQ,MAAM,iBAAiB,IAAI,KAAK,MAAM,cAAc,IAAI;AAAA,IAClE,EAAE;AAAA,EACJ;AAAA,EAGA,MAAM,+BAA+B,MAAgF;AACnH,UAAM,OAAO,MAAM,KAAK,WAAW,+BAA+B,iDAAiD,IAAI,CAAC;AACxH,UAAM,KAAK,qCAAqC,QAAQ,CAAC,CAAC;AAC1D,WAAO,KAAK,wCAAwC,IAAI;AAAA,EAC1D;AAAA,EAEA,MAAM,+BAA+B,cAAsB,MAAkD;AAC3G,UAAM,KAAK,WAAW,+BAA+B,cAAc,iDAAiD,IAAI,CAAC;AACzH,UAAM,KAAK,qCAAqC,QAAQ,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEA,MAAM,+BAA+B,cAAqC;AACxE,UAAM,KAAK,WAAW,+BAA+B,YAAY;AACjE,UAAM,KAAK,qCAAqC,QAAQ,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEA,MAAM,gCAA0E;AAC9E,UAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,qCAAqC,UAAU,CAAC,GAAG,YAAY,CAAC;AACvG,WAAO,KAAK,IAAI,CAAC,MAAM,KAAK,wCAAwC,CAAC,CAAC;AAAA,EACxE;AAAA,EAGA,MAAM,kCAAkC,MAAsF;AAC5H,UAAM,OAAO,MAAM,KAAK,WAAW,kCAAkC,oDAAoD,IAAI,CAAC;AAC9H,UAAM,KAAK,wCAAwC,QAAQ,CAAC,CAAC;AAC7D,WAAO,KAAK,2CAA2C,IAAI;AAAA,EAC7D;AAAA,EAEA,MAAM,kCAAkC,cAAsB,MAAqD;AACjH,UAAM,KAAK,WAAW,kCAAkC,cAAc,oDAAoD,IAAI,CAAC;AAC/H,UAAM,KAAK,wCAAwC,QAAQ,CAAC,CAAC;AAAA,EAC/D;AAAA,EAEA,MAAM,kCAAkC,cAAqC;AAC3E,UAAM,KAAK,WAAW,kCAAkC,YAAY;AACpE,UAAM,KAAK,wCAAwC,QAAQ,CAAC,CAAC;AAAA,EAC/D;AAAA,EAEA,MAAM,mCAAgF;AACpF,UAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,wCAAwC,UAAU,CAAC,GAAG,YAAY,CAAC;AAC1G,WAAO,KAAK,IAAI,CAAC,MAAM,KAAK,2CAA2C,CAAC,CAAC;AAAA,EAC3E;AAAA,EAGA,MAAyB,kBAAkB;AACzC,UAAM,QAAQ,IAAI;AAAA,MAChB,MAAM,gBAAgB;AAAA,MACtB,KAAK,mBAAmB,QAAQ,CAAC,CAAC;AAAA,IACpC,CAAC;AAAA,EACH;AAAA,EAEA,MAAgB,0BAA0B;AACxC,UAAM,KAAK,sBAAsB,QAAQ,CAAC,CAAC;AAAA,EAC7C;AAAA,EAEA,MAAyB,gBAAgB;AACvC,UAAM,QAAQ,IAAI;AAAA,MAChB,MAAM,cAAc;AAAA,MACpB,KAAK,cAAc,QAAQ,CAAC,KAAK,CAAC;AAAA,MAClC,KAAK,cAAc,QAAQ,CAAC,IAAI,CAAC;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEA,KAAK,uBAAuB,IAAI;AAC9B,WAAO;AAAA,MACL,GAAG,MAAM,uBAAuB;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,SAGqC;AACvD,UAAM,WAAW,MAAM,KAAK,WAAW,cAAc;AAAA,MACnD,iBAAiB,QAAQ;AAAA,MACzB,cAAc;AAAA,QACZ,GAAI,KAAK,QAAQ,aAAa,CAAC,QAAQ,QAAQ,YAAY,UAAU,CAAC;AAAA,QACtE,cAAc,QAAQ,YAAY;AAAA,QAClC,aAAa,QAAQ,YAAY;AAAA,MACnC;AAAA,IACF,CAAC;AAED,QAAI,SAAS,SAAS;AACpB,aAAO,OAAO,GAAG,MAAS;AAAA,IAC5B,OAAO;AACL,aAAO,OAAO,MAAM,EAAE,cAAc,SAAS,iBAAiB,SAAS,gCAAgC,EAAE,CAAC;AAAA,IAC5G;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,SAAuF;AAC3G,UAAM,WAAW,MAAM,KAAK,WAAW,gBAAgB;AAAA,MACrD,aAAa,QAAQ;AAAA,IACvB,CAAC;AAED,QAAI,SAAS,SAAS;AACpB,aAAO,OAAO,GAAG,MAAS;AAAA,IAC5B,OAAO;AACL,aAAO,OAAO,MAAM,EAAE,cAAc,SAAS,iBAAiB,SAAS,kCAAkC,EAAE,CAAC;AAAA,IAC9G;AAAA,EACF;AAAA,EAEA,MAAM,iBAA4C;AAChD,UAAM,WAAW,MAAM,KAAK,WAAW,eAAe;AACtD,WAAO,SAAS,MAAM,IAAI,CAAC,WAAW;AAAA,MACpC,IAAI,MAAM;AAAA,MACV,IAAI,MAAM,MAAM,CAAC;AAAA,MACjB,SAAS,MAAM;AAAA,MACf,WAAW,MAAM,KAAK,CAAC,KAAK;AAAA,MAC5B,QAAQ,IAAI,KAAK,MAAM,cAAc;AAAA,MACrC,OAAO,MAAM;AAAA,IACf,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,0BAA0B,OAAe,aAAoC;AACjF,UAAM,KAAK,WAAW,0BAA0B,OAAO,WAAW;AAAA,EACpE;AAAA,EAEA,MAAM,oBAAoB,aAA8C;AACtE,UAAM,SAAS,MAAM,KAAK,WAAW,oBAAoB,WAAW;AACpE,UAAM,KAAK,0BAA0B,QAAQ,CAAC,CAAC;AAC/C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBAAiB,SAAyG;AAC9H,UAAM,SAAS,MAAM,KAAK,WAAW,iBAAiB;AAAA,MACpD,cAAc,QAAQ;AAAA,MACtB,UAAU,QAAQ;AAAA,MAClB,YAAY,QAAQ;AAAA,IACtB,CAAC;AACD,UAAM,KAAK,uBAAuB,QAAQ,CAAC,CAAC;AAC5C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBAAiB,IAAY,MAAyG;AAC1I,UAAM,KAAK,WAAW,iBAAiB,IAAI;AAAA,MACzC,cAAc,KAAK;AAAA,MACnB,UAAU,KAAK;AAAA,MACf,YAAY,KAAK;AAAA,IACnB,CAAC;AACD,UAAM,KAAK,uBAAuB,QAAQ,CAAC,CAAC;AAAA,EAC9C;AAAA,EAEA,MAAM,gBACJ,UACA,aACA,UACA,aACmC;AACnC,WAAO,MAAM,KAAK,WAAW,gBAAgB,UAAU,aAAa,UAAU,WAAW;AAAA,EAC3F;AAAA,EAEA,MAAM,gBAAgB,UAAkB,SAA6B;AACnE,UAAM,KAAK,WAAW,gBAAgB,UAAU,OAAO;AAAA,EACzD;AAAA,EAEA,MAAM,iBAAiB,UAAqD;AAC1E,WAAO,MAAM,KAAK,WAAW,iBAAiB,QAAQ;AAAA,EACxD;AAAA,EAEA,MAAM,iBAAiB,aAA8C;AACnE,UAAM,SAAS,MAAM,KAAK,WAAW,iBAAiB,WAAW;AACjE,UAAM,KAAK,uBAAuB,QAAQ,CAAC,CAAC;AAC5C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBAAgB,SAAyI;AAC7J,YAAQ,MAAM,KAAK,WAAW,mBAAmB,OAAO,GAAG;AAAA,EAC7D;AAAA,EACA,MAAM,iBAAiB,IAAY,WAAkC;AACnE,UAAM,KAAK,WAAW,iBAAiB,IAAI,SAAS;AAAA,EACtD;AAAA,EACA,MAAM,oBAAoB,IAAY,WAAmB,SAAmE;AAC1H,UAAM,SAAS,MAAM,KAAK,WAAW,oBAAoB,IAAI,WAAW,OAAO;AAC/E,UAAM,KAAK,0BAA0B,QAAQ,CAAC,CAAC;AAC/C,WAAO,EAAE,cAAc,OAAO,cAAc;AAAA,EAC9C;AAAA,EAEA,MAAM,gBAA0C;AAC9C,WAAO,MAAM,KAAK,WAAW,cAAc;AAAA,EAC7C;AAAA,EAEA,MAAM,mCAAuE;AAC3E,WAAO,MAAM,KAAK,WAAW,iCAAiC;AAAA,EAChE;AAAA,EAEA,MAAM,yBAAyB,SAIb;AAChB,UAAM,KAAK,WAAW;AAAA,MACpB,EAAE,QAAQ,QAAQ,QAAQ,GAAI,YAAY,UAAU,EAAE,QAAQ,QAAQ,OAAO,IAAK,YAAY,UAAU,EAAE,QAAQ,QAAQ,OAAO,IAAI,EAAE,kBAAkB,QAAQ,iBAAiB,EAAI;AAAA,MACtL;AAAA,QACE,OAAO,QAAQ;AAAA,QACf,YAAY,QAAQ;AAAA,QACpB,aAAa,QAAQ;AAAA,QACrB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,SAAoF;AAC1G,UAAM,KAAK,WAAW,kBAAkB,EAAE,MAAM,QAAQ,MAAM,IAAI,QAAQ,GAAG,CAAC;AAC9E,UAAM,KAAK,mBAAmB,gBAAgB,MAAM,IAAI;AAAA,EAC1D;AAAA,EAEA,MAAM,iBAAiB,QAAqL;AAC1M,UAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,mBAAmB,UAAU,CAAC,OAAO,QAAQ,OAAO,OAAO,OAAO,MAAM,OAAO,YAAY,GAAY,YAAY,CAAC;AAC3J,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKQ,wBAAwB,MAA6B;AAC3D,UAAM,YAAY,KAAK;AACvB,QAAI;AACJ,QAAI,UAAU,SAAS,sBAAsB;AAC3C,WAAK,EAAE,MAAM,sBAAsB,QAAQ,UAAU,QAAQ;AAAA,IAC/D,WAAW,UAAU,SAAS,sBAAsB;AAClD,WAAK,EAAE,MAAM,sBAAsB,QAAQ,UAAU,SAAS,QAAQ,UAAU,OAAO;AAAA,IACzF,OAAO;AACL,WAAK,EAAE,MAAM,iBAAiB,QAAQ,UAAU,OAAO;AAAA,IACzD;AAGA,UAAM,OAAO;AAAA,MACX,IAAI,KAAK;AAAA,MACT,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,MAC1C,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,MAC1C;AAAA,MACA,aAAa,IAAI,KAAK,KAAK,mBAAmB;AAAA,MAC9C,UAAU;AAAA,MACV,aAAa;AAAA,MACb,cAAc;AAAA,IAChB;AAGA,UAAM,WAAW,KAAK,eAAe;AAAA,MACnC,GAAG;AAAA,MACH,oBAAoB,IAAI,KAAK,KAAK,2BAA2B;AAAA,MAC7D,YAAY,IAAI,KAAK,KAAK,kBAAkB;AAAA,MAC5C,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,iBAAiB,KAAK;AAAA,MACtB,gBAAgB,KAAK;AAAA,MACrB,wBAAwB,KAAK;AAAA,MAC7B,aAAa;AAAA,IACf,IAAI;AAGJ,UAAM,iBAAiB,YAAY,KAAK,4BAA4B;AAAA,MAClE,GAAG;AAAA,MACH,kBAAkB,IAAI,KAAK,KAAK,yBAAyB;AAAA,IAC3D,IAAI;AAGJ,UAAM,qBAAqB,kBAAkB,KAAK,gBAAgB;AAAA,MAChE,GAAG;AAAA,MACH,aAAa,IAAI,KAAK,KAAK,mBAAmB;AAAA,MAC9C,cAAc;AAAA,IAChB,IAAI;AAIJ,UAAM,UAAU,MAAM;AACpB,cAAQ,KAAK,QAAQ;AAAA,QACnB,KAAK,UAAU;AACb,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,QACA,KAAK,aAAa;AAChB,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,QACA,KAAK,aAAa;AAChB,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,oBAAoB,IAAI,KAAK,KAAK,2BAA2B;AAAA,UAC/D;AAAA,QACF;AAAA,QACA,KAAK,gBAAgB;AACnB,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,oBAAoB,IAAI,KAAK,KAAK,2BAA2B;AAAA,YAC7D,YAAY,IAAI,KAAK,KAAK,kBAAkB;AAAA,YAC5C,aAAa,KAAK;AAAA,UACpB;AAAA,QACF;AAAA,QACA,KAAK,aAAa;AAChB,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AACb,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,QACA,KAAK,WAAW;AACd,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,QACA,KAAK,gBAAgB;AACnB,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,SAAS,IAAI,KAAK,KAAK,eAAe;AAAA,YACtC,aAAa,KAAK;AAAA,UACpB;AAAA,QACF;AAAA,QACA,KAAK,WAAW;AACd,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,YAC1C,eAAe,KAAK;AAAA,YACpB,gBAAgB,KAAK,mBAAmB,CAAC;AAAA,YACzC,aAAa,KAAK;AAAA;AAAA,YAElB,oBAAoB,KAAK,8BAA8B,IAAI,KAAK,KAAK,2BAA2B,IAAI;AAAA,YACpG,YAAY,KAAK,qBAAqB,IAAI,KAAK,KAAK,kBAAkB,IAAI;AAAA,YAC1E,SAAS,KAAK;AAAA,YACd,MAAM,KAAK;AAAA,YACX,MAAM,KAAK;AAAA,YACX,iBAAiB,KAAK;AAAA,YACtB,gBAAgB,KAAK;AAAA,YACrB,wBAAwB,KAAK;AAAA,YAC7B,kBAAkB,KAAK,4BAA4B,IAAI,KAAK,KAAK,yBAAyB,IAAI;AAAA,UAChG;AAAA,QACF;AAAA,QACA,KAAK,WAAW;AACd,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,UAC5C;AAAA,QACF;AAAA,QACA,KAAK,oBAAoB;AACvB,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,mBAAmB,IAAI,KAAK,KAAK,0BAA0B;AAAA,UAC7D;AAAA,QACF;AAAA,QACA,KAAK,QAAQ;AACX,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,qBAAqB,KAAK;AAAA,UAC5B;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AACb,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,UAAU,IAAI,KAAK,KAAK,gBAAgB;AAAA,YACxC,qBAAqB;AAAA,UACvB;AAAA,QACF;AAAA,QACA,KAAK,WAAW;AACd,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,WAAW,IAAI,KAAK,KAAK,iBAAiB;AAAA,YAC1C,qBAAqB;AAAA,UACvB;AAAA,QACF;AAAA,QACA,KAAK,kBAAkB;AACrB,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,gBAAgB,IAAI,KAAK,KAAK,wBAAwB;AAAA,YACtD,qBAAqB;AAAA,UACvB;AAAA,QACF;AAAA,QACA,SAAS;AACP,gBAAM,IAAI,oBAAoB,gCAAgC,KAAK,MAAM,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,QACtG;AAAA,MACF;AAAA,IACF,GAAG;AAGH,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBAAiB,SAA0J;AAC/K,UAAM,WAAW,MAAM,KAAK,WAAW,iBAAiB;AAAA,MACtD,QAAQ,SAAS;AAAA,MACjB,eAAe,SAAS;AAAA,MACxB,OAAO,SAAS;AAAA,MAChB,QAAQ,SAAS;AAAA,IACnB,CAAC;AACD,WAAO;AAAA,MACL,OAAO,SAAS,MAAM,IAAI,CAAC,SAAS,KAAK,wBAAwB,IAAI,CAAC;AAAA,MACtE,YAAY,SAAS,YAAY,eAAe;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,IAAuC;AAC1D,UAAM,WAAW,MAAM,KAAK,WAAW,eAAe,EAAE;AACxD,WAAO,KAAK,wBAAwB,QAAQ;AAAA,EAC9C;AAAA,EAEA,MAAM,kBAAkB,IAAY,SAA0G;AAC5I,UAAM,WAAW,MAAM,KAAK,WAAW,kBAAkB,IAAI;AAAA,MAC3D,WAAW,QAAQ;AAAA,MACnB,qBAAqB,QAAQ;AAAA,MAC7B,QAAQ,QAAQ;AAAA,IAClB,CAAC;AACD,WAAO,KAAK,wBAAwB,QAAQ;AAAA,EAC9C;AAAA,EAEA,MAAM,iBAAiB,IAAuC;AAC5D,WAAO,MAAM,KAAK,kBAAkB,IAAI,EAAE,UAAU,KAAK,CAAC;AAAA,EAC5D;AAAA,EAEA,MAAM,mBAAmB,IAAuC;AAC9D,WAAO,MAAM,KAAK,kBAAkB,IAAI,EAAE,UAAU,MAAM,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,kBAAkB,IAAuC;AAC7D,WAAO,MAAM,KAAK,kBAAkB,IAAI,EAAE,QAAQ,KAAK,CAAC;AAAA,EAC1D;AAAA,EAGA,MAAM,uBAA+I;AACnJ,WAAO,MAAM,KAAK,WAAW,qBAAqB;AAAA,EACpD;AAAA,EAGA,MAAM,uCACJ,YACA,OASC;AACD,UAAM,SAAS,MAAM,KAAK,WAAW;AAAA,MACnC,EAAE,4BAA4B,WAAW,yBAAyB;AAAA,MAClE;AAAA,IACF;AACA,WAAO;AAAA,MACL,eAAe,OAAO,eAAe,IAAI,QAAM;AAAA,QAC7C,IAAI,EAAE;AAAA,QACN,aAAa,EAAE;AAAA,QACf,cAAc,EAAE;AAAA,QAChB,kBAAkB,EAAE;AAAA,MACtB,EAAE;AAAA,MACF,oBAAoB,OAAO;AAAA,IAC7B;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/lib/stack-app/apps/implementations/admin-app-impl.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { StackAdminInterface } from \"@stackframe/stack-shared\";\nimport { getProductionModeErrors } from \"@stackframe/stack-shared/dist/helpers/production-mode\";\nimport { InternalApiKeyCreateCrudResponse } from \"@stackframe/stack-shared/dist/interface/admin-interface\";\nimport { EmailTemplateCrud } from \"@stackframe/stack-shared/dist/interface/crud/email-templates\";\nimport { InternalApiKeysCrud } from \"@stackframe/stack-shared/dist/interface/crud/internal-api-keys\";\nimport { ProjectsCrud } from \"@stackframe/stack-shared/dist/interface/crud/projects\";\nimport type { Transaction, TransactionType } from \"@stackframe/stack-shared/dist/interface/crud/transactions\";\nimport { StackAssertionError, throwErr } from \"@stackframe/stack-shared/dist/utils/errors\";\nimport { pick } from \"@stackframe/stack-shared/dist/utils/objects\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport { AdminEmailOutbox, AdminSentEmail } from \"../..\";\nimport { EmailConfig, stackAppInternalsSymbol } from \"../../common\";\nimport { AdminEmailTemplate } from \"../../email-templates\";\nimport { InternalApiKey, InternalApiKeyBase, InternalApiKeyBaseCrudRead, InternalApiKeyCreateOptions, InternalApiKeyFirstView, internalApiKeyCreateOptionsToCrud } from \"../../internal-api-keys\";\nimport { AdminProjectPermission, AdminProjectPermissionDefinition, AdminProjectPermissionDefinitionCreateOptions, AdminProjectPermissionDefinitionUpdateOptions, AdminTeamPermission, AdminTeamPermissionDefinition, AdminTeamPermissionDefinitionCreateOptions, AdminTeamPermissionDefinitionUpdateOptions, adminProjectPermissionDefinitionCreateOptionsToCrud, adminProjectPermissionDefinitionUpdateOptionsToCrud, adminTeamPermissionDefinitionCreateOptionsToCrud, adminTeamPermissionDefinitionUpdateOptionsToCrud } from \"../../permissions\";\nimport { AdminOwnedProject, AdminProject, AdminProjectUpdateOptions, adminProjectUpdateOptionsToCrud } from \"../../projects\";\nimport { StackAdminApp, StackAdminAppConstructorOptions } from \"../interfaces/admin-app\";\nimport { clientVersion, createCache, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getDefaultSecretServerKey, getDefaultSuperSecretAdminKey, resolveConstructorOptions } from \"./common\";\nimport { _StackServerAppImplIncomplete } from \"./server-app-impl\";\n\nimport { CompleteConfig, EnvironmentConfigOverrideOverride } from \"@stackframe/stack-shared/dist/config/schema\";\nimport { ChatContent } from \"@stackframe/stack-shared/dist/interface/admin-interface\";\n\nexport class _StackAdminAppImplIncomplete<HasTokenStore extends boolean, ProjectId extends string> extends _StackServerAppImplIncomplete<HasTokenStore, ProjectId> implements StackAdminApp<HasTokenStore, ProjectId> {\n declare protected _interface: StackAdminInterface;\n\n private readonly _adminProjectCache = createCache(async () => {\n return await this._interface.getProject();\n });\n private readonly _internalApiKeysCache = createCache(async () => {\n const res = await this._interface.listInternalApiKeys();\n return res;\n });\n private readonly _adminEmailThemeCache = createCache(async ([id]: [string]) => {\n return await this._interface.getEmailTheme(id);\n });\n private readonly _adminEmailThemesCache = createCache(async () => {\n return await this._interface.listEmailThemes();\n });\n private readonly _adminEmailTemplatesCache = createCache(async () => {\n return await this._interface.listInternalEmailTemplates();\n });\n private readonly _adminEmailDraftsCache = createCache(async () => {\n return await this._interface.listInternalEmailDrafts();\n });\n private readonly _adminTeamPermissionDefinitionsCache = createCache(async () => {\n return await this._interface.listTeamPermissionDefinitions();\n });\n private readonly _adminProjectPermissionDefinitionsCache = createCache(async () => {\n return await this._interface.listProjectPermissionDefinitions();\n });\n private readonly _svixTokenCache = createCache(async () => {\n return await this._interface.getSvixToken();\n });\n private readonly _metricsCache = createCache(async ([includeAnonymous]: [boolean]) => {\n return await this._interface.getMetrics(includeAnonymous);\n });\n private readonly _emailPreviewCache = createCache(async ([themeId, themeTsxSource, templateId, templateTsxSource]: [string | null | false | undefined, string | undefined, string | undefined, string | undefined]) => {\n return await this._interface.renderEmailPreview({ themeId, themeTsxSource, templateId, templateTsxSource });\n });\n private readonly _configOverridesCache = createCache(async () => {\n return await this._interface.getConfig();\n });\n private readonly _stripeAccountInfoCache = createCache(async () => {\n try {\n return await this._interface.getStripeAccountInfo();\n } catch (error: any) {\n if (error?.status === 404) {\n return null;\n }\n throw error;\n }\n });\n private readonly _transactionsCache = createCache(async ([cursor, limit, type, customerType]: [string | undefined, number | undefined, TransactionType | undefined, 'user' | 'team' | 'custom' | undefined]) => {\n return await this._interface.listTransactions({ cursor, limit, type, customerType });\n });\n\n constructor(options: StackAdminAppConstructorOptions<HasTokenStore, ProjectId>, extraOptions?: { uniqueIdentifier?: string, checkString?: string, interface?: StackAdminInterface }) {\n const resolvedOptions = resolveConstructorOptions(options);\n\n super(resolvedOptions, {\n ...extraOptions,\n interface: extraOptions?.interface ?? new StackAdminInterface({\n getBaseUrl: () => getBaseUrl(resolvedOptions.baseUrl),\n projectId: resolvedOptions.projectId ?? getDefaultProjectId(),\n extraRequestHeaders: resolvedOptions.extraRequestHeaders ?? getDefaultExtraRequestHeaders(),\n clientVersion,\n ...resolvedOptions.projectOwnerSession ? {\n projectOwnerSession: resolvedOptions.projectOwnerSession,\n } : {\n publishableClientKey: resolvedOptions.publishableClientKey ?? getDefaultPublishableClientKey(),\n secretServerKey: resolvedOptions.secretServerKey ?? getDefaultSecretServerKey(),\n superSecretAdminKey: resolvedOptions.superSecretAdminKey ?? getDefaultSuperSecretAdminKey(),\n },\n }),\n });\n }\n\n _adminConfigFromCrud(data: { config_string: string }): CompleteConfig {\n return JSON.parse(data.config_string);\n }\n\n _adminOwnedProjectFromCrud(data: ProjectsCrud['Admin']['Read'], onRefresh: () => Promise<void>): AdminOwnedProject {\n if (this._tokenStoreInit !== null) {\n throw new StackAssertionError(\"Owned apps must always have tokenStore === null — did you not create this project with app._createOwnedApp()?\");\n }\n return {\n ...this._adminProjectFromCrud(data, onRefresh),\n app: this as StackAdminApp<false>,\n };\n }\n\n _adminProjectFromCrud(data: ProjectsCrud['Admin']['Read'], onRefresh: () => Promise<void>): AdminProject {\n if (data.id !== this.projectId) {\n throw new StackAssertionError(`The project ID of the provided project JSON (${data.id}) does not match the project ID of the app (${this.projectId})!`);\n }\n\n const app = this;\n return {\n id: data.id,\n displayName: data.display_name,\n description: data.description,\n createdAt: new Date(data.created_at_millis),\n isProductionMode: data.is_production_mode,\n ownerTeamId: data.owner_team_id,\n logoUrl: data.logo_url,\n logoFullUrl: data.logo_full_url,\n logoDarkModeUrl: data.logo_dark_mode_url,\n logoFullDarkModeUrl: data.logo_full_dark_mode_url,\n config: {\n signUpEnabled: data.config.sign_up_enabled,\n credentialEnabled: data.config.credential_enabled,\n magicLinkEnabled: data.config.magic_link_enabled,\n passkeyEnabled: data.config.passkey_enabled,\n clientTeamCreationEnabled: data.config.client_team_creation_enabled,\n clientUserDeletionEnabled: data.config.client_user_deletion_enabled,\n allowLocalhost: data.config.allow_localhost,\n oauthAccountMergeStrategy: data.config.oauth_account_merge_strategy,\n allowUserApiKeys: data.config.allow_user_api_keys,\n allowTeamApiKeys: data.config.allow_team_api_keys,\n oauthProviders: data.config.oauth_providers.map((p) => ((p.type === 'shared' ? {\n id: p.id,\n type: 'shared',\n } as const : {\n id: p.id,\n type: 'standard',\n clientId: p.client_id ?? throwErr(\"Client ID is missing\"),\n clientSecret: p.client_secret ?? throwErr(\"Client secret is missing\"),\n facebookConfigId: p.facebook_config_id,\n microsoftTenantId: p.microsoft_tenant_id,\n } as const))),\n emailConfig: data.config.email_config.type === 'shared' ? {\n type: 'shared'\n } : {\n type: 'standard',\n host: data.config.email_config.host ?? throwErr(\"Email host is missing\"),\n port: data.config.email_config.port ?? throwErr(\"Email port is missing\"),\n username: data.config.email_config.username ?? throwErr(\"Email username is missing\"),\n password: data.config.email_config.password ?? throwErr(\"Email password is missing\"),\n senderName: data.config.email_config.sender_name ?? throwErr(\"Email sender name is missing\"),\n senderEmail: data.config.email_config.sender_email ?? throwErr(\"Email sender email is missing\"),\n },\n emailTheme: data.config.email_theme,\n domains: data.config.domains.map((d) => ({\n domain: d.domain,\n handlerPath: d.handler_path,\n })),\n createTeamOnSignUp: data.config.create_team_on_sign_up,\n teamCreatorDefaultPermissions: data.config.team_creator_default_permissions,\n teamMemberDefaultPermissions: data.config.team_member_default_permissions,\n userDefaultPermissions: data.config.user_default_permissions,\n },\n async getConfig() {\n return app._adminConfigFromCrud(await app._interface.getConfig());\n },\n async updateConfig(configOverride: EnvironmentConfigOverrideOverride) {\n await app._interface.updateConfig({ configOverride });\n await app._configOverridesCache.refresh([]);\n },\n async update(update: AdminProjectUpdateOptions) {\n const updateOptions = adminProjectUpdateOptionsToCrud(update);\n await app._interface.updateProject(updateOptions);\n await onRefresh();\n },\n async delete() {\n await app._interface.deleteProject();\n },\n async getProductionModeErrors() {\n return getProductionModeErrors(data);\n },\n };\n }\n\n _adminEmailTemplateFromCrud(data: EmailTemplateCrud['Admin']['Read']): AdminEmailTemplate {\n return {\n type: data.type,\n subject: data.subject,\n content: data.content,\n isDefault: data.is_default,\n };\n }\n\n override async getProject(): Promise<AdminProject> {\n return this._adminProjectFromCrud(\n Result.orThrow(await this._adminProjectCache.getOrWait([], \"write-only\")),\n () => this._refreshProject()\n );\n }\n\n\n protected _createInternalApiKeyBaseFromCrud(data: InternalApiKeyBaseCrudRead): InternalApiKeyBase {\n const app = this;\n return {\n id: data.id,\n description: data.description,\n expiresAt: new Date(data.expires_at_millis),\n manuallyRevokedAt: data.manually_revoked_at_millis ? new Date(data.manually_revoked_at_millis) : null,\n createdAt: new Date(data.created_at_millis),\n isValid() {\n return this.whyInvalid() === null;\n },\n whyInvalid() {\n if (this.expiresAt.getTime() < Date.now()) return \"expired\";\n if (this.manuallyRevokedAt) return \"manually-revoked\";\n return null;\n },\n async revoke() {\n const res = await app._interface.revokeInternalApiKeyById(data.id);\n await app._refreshInternalApiKeys();\n return res;\n }\n };\n }\n\n protected _createInternalApiKeyFromCrud(data: InternalApiKeysCrud[\"Admin\"][\"Read\"]): InternalApiKey {\n return {\n ...this._createInternalApiKeyBaseFromCrud(data),\n publishableClientKey: data.publishable_client_key ? { lastFour: data.publishable_client_key.last_four } : null,\n secretServerKey: data.secret_server_key ? { lastFour: data.secret_server_key.last_four } : null,\n superSecretAdminKey: data.super_secret_admin_key ? { lastFour: data.super_secret_admin_key.last_four } : null,\n };\n }\n\n protected _createInternalApiKeyFirstViewFromCrud(data: InternalApiKeyCreateCrudResponse): InternalApiKeyFirstView {\n return {\n ...this._createInternalApiKeyBaseFromCrud(data),\n publishableClientKey: data.publishable_client_key,\n secretServerKey: data.secret_server_key,\n superSecretAdminKey: data.super_secret_admin_key,\n };\n }\n\n async listInternalApiKeys(): Promise<InternalApiKey[]> {\n const crud = Result.orThrow(await this._internalApiKeysCache.getOrWait([], \"write-only\"));\n return crud.map((j) => this._createInternalApiKeyFromCrud(j));\n }\n\n\n async createInternalApiKey(options: InternalApiKeyCreateOptions): Promise<InternalApiKeyFirstView> {\n const crud = await this._interface.createInternalApiKey(internalApiKeyCreateOptionsToCrud(options));\n await this._refreshInternalApiKeys();\n return this._createInternalApiKeyFirstViewFromCrud(crud);\n }\n\n\n async listEmailThemes(): Promise<{ id: string, displayName: string }[]> {\n const crud = Result.orThrow(await this._adminEmailThemesCache.getOrWait([], \"write-only\"));\n return crud.map((theme) => ({\n id: theme.id,\n displayName: theme.display_name,\n }));\n }\n\n async listEmailTemplates(): Promise<{ id: string, displayName: string, themeId?: string, tsxSource: string }[]> {\n const crud = Result.orThrow(await this._adminEmailTemplatesCache.getOrWait([], \"write-only\"));\n return crud.map((template) => ({\n id: template.id,\n displayName: template.display_name,\n themeId: template.theme_id,\n tsxSource: template.tsx_source,\n }));\n }\n\n async listEmailDrafts(): Promise<{ id: string, displayName: string, themeId: string | undefined | false, tsxSource: string, sentAt: Date | null }[]> {\n const crud = Result.orThrow(await this._adminEmailDraftsCache.getOrWait([], \"write-only\"));\n return crud.map((draft) => ({\n id: draft.id,\n displayName: draft.display_name,\n themeId: draft.theme_id,\n tsxSource: draft.tsx_source,\n sentAt: draft.sent_at_millis ? new Date(draft.sent_at_millis) : null,\n }));\n }\n\n\n async createTeamPermissionDefinition(data: AdminTeamPermissionDefinitionCreateOptions): Promise<AdminTeamPermission> {\n const crud = await this._interface.createTeamPermissionDefinition(adminTeamPermissionDefinitionCreateOptionsToCrud(data));\n await this._adminTeamPermissionDefinitionsCache.refresh([]);\n return this._serverTeamPermissionDefinitionFromCrud(crud);\n }\n\n async updateTeamPermissionDefinition(permissionId: string, data: AdminTeamPermissionDefinitionUpdateOptions) {\n await this._interface.updateTeamPermissionDefinition(permissionId, adminTeamPermissionDefinitionUpdateOptionsToCrud(data));\n await this._adminTeamPermissionDefinitionsCache.refresh([]);\n }\n\n async deleteTeamPermissionDefinition(permissionId: string): Promise<void> {\n await this._interface.deleteTeamPermissionDefinition(permissionId);\n await this._adminTeamPermissionDefinitionsCache.refresh([]);\n }\n\n async listTeamPermissionDefinitions(): Promise<AdminTeamPermissionDefinition[]> {\n const crud = Result.orThrow(await this._adminTeamPermissionDefinitionsCache.getOrWait([], \"write-only\"));\n return crud.map((p) => this._serverTeamPermissionDefinitionFromCrud(p));\n }\n\n\n async createProjectPermissionDefinition(data: AdminProjectPermissionDefinitionCreateOptions): Promise<AdminProjectPermission> {\n const crud = await this._interface.createProjectPermissionDefinition(adminProjectPermissionDefinitionCreateOptionsToCrud(data));\n await this._adminProjectPermissionDefinitionsCache.refresh([]);\n return this._serverProjectPermissionDefinitionFromCrud(crud);\n }\n\n async updateProjectPermissionDefinition(permissionId: string, data: AdminProjectPermissionDefinitionUpdateOptions) {\n await this._interface.updateProjectPermissionDefinition(permissionId, adminProjectPermissionDefinitionUpdateOptionsToCrud(data));\n await this._adminProjectPermissionDefinitionsCache.refresh([]);\n }\n\n async deleteProjectPermissionDefinition(permissionId: string): Promise<void> {\n await this._interface.deleteProjectPermissionDefinition(permissionId);\n await this._adminProjectPermissionDefinitionsCache.refresh([]);\n }\n\n async listProjectPermissionDefinitions(): Promise<AdminProjectPermissionDefinition[]> {\n const crud = Result.orThrow(await this._adminProjectPermissionDefinitionsCache.getOrWait([], \"write-only\"));\n return crud.map((p) => this._serverProjectPermissionDefinitionFromCrud(p));\n }\n\n\n protected override async _refreshProject() {\n await Promise.all([\n super._refreshProject(),\n this._adminProjectCache.refresh([]),\n ]);\n }\n\n protected async _refreshInternalApiKeys() {\n await this._internalApiKeysCache.refresh([]);\n }\n\n protected override async _refreshUsers() {\n await Promise.all([\n super._refreshUsers(),\n this._metricsCache.refresh([false]),\n this._metricsCache.refresh([true]),\n ]);\n }\n\n get [stackAppInternalsSymbol]() {\n return {\n ...super[stackAppInternalsSymbol],\n };\n }\n\n async sendTestEmail(options: {\n recipientEmail: string,\n emailConfig: EmailConfig,\n }): Promise<Result<undefined, { errorMessage: string }>> {\n const response = await this._interface.sendTestEmail({\n recipient_email: options.recipientEmail,\n email_config: {\n ...(pick(options.emailConfig, ['host', 'port', 'username', 'password'])),\n sender_email: options.emailConfig.senderEmail,\n sender_name: options.emailConfig.senderName,\n },\n });\n\n if (response.success) {\n return Result.ok(undefined);\n } else {\n return Result.error({ errorMessage: response.error_message ?? throwErr(\"Email test error not specified\") });\n }\n }\n\n async sendTestWebhook(options: { endpointId: string }): Promise<Result<undefined, { errorMessage: string }>> {\n const response = await this._interface.sendTestWebhook({\n endpoint_id: options.endpointId,\n });\n\n if (response.success) {\n return Result.ok(undefined);\n } else {\n return Result.error({ errorMessage: response.error_message ?? throwErr(\"Webhook test error not specified\") });\n }\n }\n\n async listSentEmails(): Promise<AdminSentEmail[]> {\n const response = await this._interface.listSentEmails();\n return response.items.map((email) => ({\n id: email.id,\n to: email.to ?? [],\n subject: email.subject,\n recipient: email.to?.[0] ?? \"\",\n sentAt: new Date(email.sent_at_millis),\n error: email.error,\n }));\n }\n\n async sendSignInInvitationEmail(email: string, callbackUrl: string): Promise<void> {\n await this._interface.sendSignInInvitationEmail(email, callbackUrl);\n }\n\n async createEmailTemplate(displayName: string): Promise<{ id: string }> {\n const result = await this._interface.createEmailTemplate(displayName);\n await this._adminEmailTemplatesCache.refresh([]);\n return result;\n }\n\n async createEmailDraft(options: { displayName: string, themeId?: string | false, tsxSource?: string }): Promise<{ id: string }> {\n const result = await this._interface.createEmailDraft({\n display_name: options.displayName,\n theme_id: options.themeId,\n tsx_source: options.tsxSource,\n });\n await this._adminEmailDraftsCache.refresh([]);\n return result;\n }\n\n async updateEmailDraft(id: string, data: { displayName?: string, themeId?: string | undefined | false, tsxSource?: string }): Promise<void> {\n await this._interface.updateEmailDraft(id, {\n display_name: data.displayName,\n theme_id: data.themeId,\n tsx_source: data.tsxSource,\n });\n await this._adminEmailDraftsCache.refresh([]);\n }\n\n async sendChatMessage(\n threadId: string,\n contextType: \"email-theme\" | \"email-template\" | \"email-draft\",\n messages: Array<{ role: string, content: any }>,\n abortSignal?: AbortSignal,\n ): Promise<{ content: ChatContent }> {\n return await this._interface.sendChatMessage(threadId, contextType, messages, abortSignal);\n }\n\n async saveChatMessage(threadId: string, message: any): Promise<void> {\n await this._interface.saveChatMessage(threadId, message);\n }\n\n async listChatMessages(threadId: string): Promise<{ messages: Array<any> }> {\n return await this._interface.listChatMessages(threadId);\n }\n\n async createEmailTheme(displayName: string): Promise<{ id: string }> {\n const result = await this._interface.createEmailTheme(displayName);\n await this._adminEmailThemesCache.refresh([]);\n return result;\n }\n\n async getEmailPreview(options: { themeId?: string | null | false, themeTsxSource?: string, templateId?: string, templateTsxSource?: string }): Promise<string> {\n return (await this._interface.renderEmailPreview(options)).html;\n }\n async updateEmailTheme(id: string, tsxSource: string): Promise<void> {\n await this._interface.updateEmailTheme(id, tsxSource);\n }\n async updateEmailTemplate(id: string, tsxSource: string, themeId: string | null | false): Promise<{ renderedHtml: string }> {\n const result = await this._interface.updateEmailTemplate(id, tsxSource, themeId);\n await this._adminEmailTemplatesCache.refresh([]);\n return { renderedHtml: result.rendered_html };\n }\n\n async setupPayments(): Promise<{ url: string }> {\n return await this._interface.setupPayments();\n }\n\n async createStripeWidgetAccountSession(): Promise<{ client_secret: string }> {\n return await this._interface.createStripeWidgetAccountSession();\n }\n\n async createItemQuantityChange(options: (\n { userId: string, itemId: string, quantity: number, expiresAt?: string, description?: string } |\n { teamId: string, itemId: string, quantity: number, expiresAt?: string, description?: string } |\n { customCustomerId: string, itemId: string, quantity: number, expiresAt?: string, description?: string }\n )): Promise<void> {\n await this._interface.updateItemQuantity(\n { itemId: options.itemId, ...(\"userId\" in options ? { userId: options.userId } : (\"teamId\" in options ? { teamId: options.teamId } : { customCustomerId: options.customCustomerId })) },\n {\n delta: options.quantity,\n expires_at: options.expiresAt,\n description: options.description,\n allow_negative: true,\n }\n );\n }\n\n async refundTransaction(options: { type: \"subscription\" | \"one-time-purchase\", id: string }): Promise<void> {\n await this._interface.refundTransaction({ type: options.type, id: options.id });\n await this._transactionsCache.invalidateWhere(() => true);\n }\n\n async listTransactions(params: { cursor?: string, limit?: number, type?: TransactionType, customerType?: 'user' | 'team' | 'custom' }): Promise<{ transactions: Transaction[], nextCursor: string | null }> {\n const crud = Result.orThrow(await this._transactionsCache.getOrWait([params.cursor, params.limit, params.type, params.customerType] as const, \"write-only\"));\n return crud;\n }\n\n // Email Outbox methods\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Complex discriminated union conversion from API response\n private _emailOutboxCrudToAdmin(crud: any): AdminEmailOutbox {\n const recipient = crud.to;\n let to: AdminEmailOutbox[\"to\"];\n if (recipient.type === \"user-primary-email\") {\n to = { type: \"user-primary-email\", userId: recipient.user_id };\n } else if (recipient.type === \"user-custom-emails\") {\n to = { type: \"user-custom-emails\", userId: recipient.user_id, emails: recipient.emails };\n } else {\n to = { type: \"custom-emails\", emails: recipient.emails };\n }\n\n // Base fields present on all emails\n const base = {\n id: crud.id as string,\n createdAt: new Date(crud.created_at_millis),\n updatedAt: new Date(crud.updated_at_millis),\n to,\n scheduledAt: new Date(crud.scheduled_at_millis),\n isPaused: false as const,\n hasRendered: false as const,\n hasDelivered: false as const,\n };\n\n // Rendered fields (available after rendering completes successfully)\n const rendered = crud.has_rendered ? {\n ...base,\n startedRenderingAt: new Date(crud.started_rendering_at_millis),\n renderedAt: new Date(crud.rendered_at_millis),\n subject: crud.subject as string,\n html: crud.html as string | null,\n text: crud.text as string | null,\n isTransactional: crud.is_transactional as boolean,\n isHighPriority: crud.is_high_priority as boolean,\n notificationCategoryId: crud.notification_category_id as string | null,\n hasRendered: true as const,\n } : null;\n\n // Started sending fields\n const startedSending = rendered && crud.started_sending_at_millis ? {\n ...rendered,\n startedSendingAt: new Date(crud.started_sending_at_millis),\n } : null;\n\n // Finished delivering fields\n const finishedDelivering = startedSending && crud.has_delivered ? {\n ...startedSending,\n deliveredAt: new Date(crud.delivered_at_millis),\n hasDelivered: true as const,\n } : null;\n\n // Use type assertion at the end because TypeScript has trouble with\n // spread + override patterns on discriminated unions with const literal types\n const result = (() => {\n switch (crud.status) {\n case \"paused\": {\n return {\n ...base,\n status: \"paused\" as const,\n simpleStatus: \"in-progress\" as const,\n isPaused: true as const,\n };\n }\n case \"preparing\": {\n return {\n ...base,\n status: \"preparing\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"rendering\": {\n return {\n ...base,\n status: \"rendering\" as const,\n simpleStatus: \"in-progress\" as const,\n startedRenderingAt: new Date(crud.started_rendering_at_millis),\n };\n }\n case \"render-error\": {\n return {\n ...base,\n status: \"render-error\" as const,\n simpleStatus: \"error\" as const,\n startedRenderingAt: new Date(crud.started_rendering_at_millis),\n renderedAt: new Date(crud.rendered_at_millis),\n renderError: crud.render_error,\n };\n }\n case \"scheduled\": {\n return {\n ...rendered!,\n status: \"scheduled\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"queued\": {\n return {\n ...rendered!,\n status: \"queued\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"sending\": {\n return {\n ...startedSending!,\n status: \"sending\" as const,\n simpleStatus: \"in-progress\" as const,\n };\n }\n case \"server-error\": {\n return {\n ...startedSending!,\n status: \"server-error\" as const,\n simpleStatus: \"error\" as const,\n errorAt: new Date(crud.error_at_millis),\n serverError: crud.server_error,\n };\n }\n case \"skipped\": {\n return {\n ...base,\n status: \"skipped\" as const,\n simpleStatus: \"ok\" as const,\n skippedAt: new Date(crud.skipped_at_millis),\n skippedReason: crud.skipped_reason,\n skippedDetails: crud.skipped_details ?? {},\n hasRendered: crud.has_rendered as boolean,\n // Optional fields\n startedRenderingAt: crud.started_rendering_at_millis ? new Date(crud.started_rendering_at_millis) : undefined,\n renderedAt: crud.rendered_at_millis ? new Date(crud.rendered_at_millis) : undefined,\n subject: crud.subject,\n html: crud.html,\n text: crud.text,\n isTransactional: crud.is_transactional,\n isHighPriority: crud.is_high_priority,\n notificationCategoryId: crud.notification_category_id,\n startedSendingAt: crud.started_sending_at_millis ? new Date(crud.started_sending_at_millis) : undefined,\n };\n }\n case \"bounced\": {\n return {\n ...startedSending!,\n status: \"bounced\" as const,\n simpleStatus: \"error\" as const,\n bouncedAt: new Date(crud.bounced_at_millis),\n };\n }\n case \"delivery-delayed\": {\n return {\n ...startedSending!,\n status: \"delivery-delayed\" as const,\n simpleStatus: \"ok\" as const,\n deliveryDelayedAt: new Date(crud.delivery_delayed_at_millis),\n };\n }\n case \"sent\": {\n return {\n ...finishedDelivering!,\n status: \"sent\" as const,\n simpleStatus: \"ok\" as const,\n canHaveDeliveryInfo: crud.can_have_delivery_info,\n };\n }\n case \"opened\": {\n return {\n ...finishedDelivering!,\n status: \"opened\" as const,\n simpleStatus: \"ok\" as const,\n openedAt: new Date(crud.opened_at_millis),\n canHaveDeliveryInfo: true as const,\n };\n }\n case \"clicked\": {\n return {\n ...finishedDelivering!,\n status: \"clicked\" as const,\n simpleStatus: \"ok\" as const,\n clickedAt: new Date(crud.clicked_at_millis),\n canHaveDeliveryInfo: true as const,\n };\n }\n case \"marked-as-spam\": {\n return {\n ...finishedDelivering!,\n status: \"marked-as-spam\" as const,\n simpleStatus: \"ok\" as const,\n markedAsSpamAt: new Date(crud.marked_as_spam_at_millis),\n canHaveDeliveryInfo: true as const,\n };\n }\n default: {\n throw new StackAssertionError(`Unknown email outbox status: ${crud.status}`, { status: crud.status });\n }\n }\n })();\n // The type system has difficulty with spread + override patterns on discriminated unions,\n // so we use a type assertion here. The switch statement above ensures we return the correct shape.\n return result as AdminEmailOutbox;\n }\n\n async listOutboxEmails(options?: { status?: string, simpleStatus?: string, limit?: number, cursor?: string }): Promise<{ items: AdminEmailOutbox[], nextCursor: string | null }> {\n const response = await this._interface.listOutboxEmails({\n status: options?.status,\n simple_status: options?.simpleStatus,\n limit: options?.limit,\n cursor: options?.cursor,\n });\n return {\n items: response.items.map((item) => this._emailOutboxCrudToAdmin(item)),\n nextCursor: response.pagination?.next_cursor ?? null,\n };\n }\n\n async getOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n const response = await this._interface.getOutboxEmail(id);\n return this._emailOutboxCrudToAdmin(response);\n }\n\n async updateOutboxEmail(id: string, options: { isPaused?: boolean, scheduledAtMillis?: number, cancel?: boolean }): Promise<AdminEmailOutbox> {\n const response = await this._interface.updateOutboxEmail(id, {\n is_paused: options.isPaused,\n scheduled_at_millis: options.scheduledAtMillis,\n cancel: options.cancel,\n });\n return this._emailOutboxCrudToAdmin(response);\n }\n\n async pauseOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n return await this.updateOutboxEmail(id, { isPaused: true });\n }\n\n async unpauseOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n return await this.updateOutboxEmail(id, { isPaused: false });\n }\n\n async cancelOutboxEmail(id: string): Promise<AdminEmailOutbox> {\n return await this.updateOutboxEmail(id, { cancel: true });\n }\n\n\n async getStripeAccountInfo(): Promise<null | { account_id: string, charges_enabled: boolean, details_submitted: boolean, payouts_enabled: boolean }> {\n return await this._interface.getStripeAccountInfo();\n }\n\n\n async previewAffectedUsersByOnboardingChange(\n onboarding: { requireEmailVerification?: boolean },\n limit?: number,\n ): Promise<{\n affectedUsers: Array<{\n id: string,\n displayName: string | null,\n primaryEmail: string | null,\n restrictedReason: { type: \"anonymous\" | \"email_not_verified\" },\n }>,\n totalAffectedCount: number,\n }> {\n const result = await this._interface.previewAffectedUsersByOnboardingChange(\n { require_email_verification: onboarding.requireEmailVerification },\n limit,\n );\n return {\n affectedUsers: result.affected_users.map(u => ({\n id: u.id,\n displayName: u.display_name,\n primaryEmail: u.primary_email,\n restrictedReason: u.restricted_reason as { type: \"anonymous\" | \"email_not_verified\" },\n })),\n totalAffectedCount: result.total_affected_count,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -170,6 +170,11 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
170
170
|
}, session);
|
|
171
171
|
}
|
|
172
172
|
);
|
|
173
|
+
this._customerBillingCache = createCacheBySession(
|
|
174
|
+
async (session, [customerType, customerId]) => {
|
|
175
|
+
return await this._interface.getCustomerBilling(customerType, customerId, session);
|
|
176
|
+
}
|
|
177
|
+
);
|
|
173
178
|
this._convexPartialUserCache = createCache(
|
|
174
179
|
async ([ctx]) => await this._getPartialUserFromConvex(ctx)
|
|
175
180
|
);
|
|
@@ -397,7 +402,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
397
402
|
if (!isBrowserLike()) {
|
|
398
403
|
throw new StackAssertionError("Cannot get browser cookies on the server!");
|
|
399
404
|
}
|
|
400
|
-
return cookie.
|
|
405
|
+
return cookie.parseCookie(document.cookie || "");
|
|
401
406
|
}
|
|
402
407
|
_getRefreshTokenCookieNamePatterns() {
|
|
403
408
|
return {
|
|
@@ -595,7 +600,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
595
600
|
});
|
|
596
601
|
}
|
|
597
602
|
const cookieHeader = tokenStoreInit.headers.get("cookie");
|
|
598
|
-
const parsed = cookie.
|
|
603
|
+
const parsed = cookie.parseCookie(cookieHeader || "");
|
|
599
604
|
const res = new Store(this._getTokensFromCookies(parsed));
|
|
600
605
|
this._requestTokenStores.set(tokenStoreInit, res);
|
|
601
606
|
return res;
|
|
@@ -887,10 +892,27 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
887
892
|
displayName: item.product.display_name,
|
|
888
893
|
customerType: item.product.customer_type,
|
|
889
894
|
isServerOnly: item.product.server_only,
|
|
890
|
-
stackable: item.product.stackable
|
|
895
|
+
stackable: item.product.stackable,
|
|
896
|
+
type: item.type,
|
|
897
|
+
subscription: item.subscription ? {
|
|
898
|
+
currentPeriodEnd: item.subscription.current_period_end ? new Date(item.subscription.current_period_end) : null,
|
|
899
|
+
cancelAtPeriodEnd: item.subscription.cancel_at_period_end,
|
|
900
|
+
isCancelable: item.subscription.is_cancelable
|
|
901
|
+
} : null,
|
|
902
|
+
switchOptions: item.switch_options?.map((option) => ({
|
|
903
|
+
productId: option.product_id,
|
|
904
|
+
displayName: option.product.display_name,
|
|
905
|
+
prices: option.product.prices
|
|
906
|
+
}))
|
|
891
907
|
}));
|
|
892
908
|
return Object.assign(products, { nextCursor: response.pagination.next_cursor ?? null });
|
|
893
909
|
}
|
|
910
|
+
_customerBillingFromResponse(response) {
|
|
911
|
+
return {
|
|
912
|
+
hasCustomer: response.has_customer,
|
|
913
|
+
defaultPaymentMethod: response.default_payment_method
|
|
914
|
+
};
|
|
915
|
+
}
|
|
894
916
|
_createAuth(session) {
|
|
895
917
|
const app = this;
|
|
896
918
|
return {
|
|
@@ -1157,8 +1179,25 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1157
1179
|
}
|
|
1158
1180
|
_createCustomer(userIdOrTeamId, type, session) {
|
|
1159
1181
|
const app = this;
|
|
1182
|
+
const effectiveSession = session ?? app._interface.createSession({ refreshToken: null });
|
|
1160
1183
|
const customerOptions = type === "user" ? { userId: userIdOrTeamId } : { teamId: userIdOrTeamId };
|
|
1161
1184
|
return {
|
|
1185
|
+
async getBilling() {
|
|
1186
|
+
const response = Result.orThrow(await app._customerBillingCache.getOrWait([effectiveSession, type, userIdOrTeamId], "write-only"));
|
|
1187
|
+
return app._customerBillingFromResponse(response);
|
|
1188
|
+
},
|
|
1189
|
+
async createPaymentMethodSetupIntent() {
|
|
1190
|
+
const body = await app._interface.createCustomerPaymentMethodSetupIntent(type, userIdOrTeamId, effectiveSession);
|
|
1191
|
+
return {
|
|
1192
|
+
clientSecret: body.client_secret,
|
|
1193
|
+
stripeAccountId: body.stripe_account_id
|
|
1194
|
+
};
|
|
1195
|
+
},
|
|
1196
|
+
async setDefaultPaymentMethodFromSetupIntent(setupIntentId) {
|
|
1197
|
+
const body = await app._interface.setDefaultCustomerPaymentMethodFromSetupIntent(type, userIdOrTeamId, setupIntentId, effectiveSession);
|
|
1198
|
+
await app._customerBillingCache.refresh([effectiveSession, type, userIdOrTeamId]);
|
|
1199
|
+
return body.default_payment_method;
|
|
1200
|
+
},
|
|
1162
1201
|
async getItem(itemId) {
|
|
1163
1202
|
return await app.getItem({ itemId, ...customerOptions });
|
|
1164
1203
|
},
|
|
@@ -1166,7 +1205,23 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1166
1205
|
return await app.listProducts({ ...options, ...customerOptions });
|
|
1167
1206
|
},
|
|
1168
1207
|
async createCheckoutUrl(options) {
|
|
1169
|
-
return await app._interface.createCheckoutUrl(type, userIdOrTeamId, options.productId,
|
|
1208
|
+
return await app._interface.createCheckoutUrl(type, userIdOrTeamId, options.productId, effectiveSession, options.returnUrl);
|
|
1209
|
+
},
|
|
1210
|
+
async switchSubscription(options) {
|
|
1211
|
+
await app._interface.switchSubscription({
|
|
1212
|
+
customer_type: type,
|
|
1213
|
+
customer_id: userIdOrTeamId,
|
|
1214
|
+
from_product_id: options.fromProductId,
|
|
1215
|
+
to_product_id: options.toProductId,
|
|
1216
|
+
price_id: options.priceId,
|
|
1217
|
+
quantity: options.quantity
|
|
1218
|
+
}, effectiveSession);
|
|
1219
|
+
await app._customerBillingCache.refresh([effectiveSession, type, userIdOrTeamId]);
|
|
1220
|
+
if (type === "user") {
|
|
1221
|
+
await app._userProductsCache.invalidateWhere(([cachedSession, userId]) => cachedSession === effectiveSession && userId === userIdOrTeamId);
|
|
1222
|
+
} else {
|
|
1223
|
+
await app._teamProductsCache.invalidateWhere(([cachedSession, teamId]) => cachedSession === effectiveSession && teamId === userIdOrTeamId);
|
|
1224
|
+
}
|
|
1170
1225
|
}
|
|
1171
1226
|
};
|
|
1172
1227
|
}
|