@augmenting-integrations/auth 4.2.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/client/AppUserProvider.cjs +73 -0
  2. package/dist/client/AppUserProvider.cjs.map +1 -0
  3. package/dist/client/AppUserProvider.d.ts +49 -0
  4. package/dist/client/AppUserProvider.d.ts.map +1 -0
  5. package/dist/client/AppUserProvider.js +36 -0
  6. package/dist/client/AppUserProvider.js.map +1 -0
  7. package/dist/client/ImpersonationBanner.cjs +103 -0
  8. package/dist/client/ImpersonationBanner.cjs.map +1 -0
  9. package/dist/client/ImpersonationBanner.d.ts +9 -0
  10. package/dist/client/ImpersonationBanner.d.ts.map +1 -0
  11. package/dist/client/ImpersonationBanner.js +69 -0
  12. package/dist/client/ImpersonationBanner.js.map +1 -0
  13. package/dist/client/SignOutButton.cjs +59 -0
  14. package/dist/client/SignOutButton.cjs.map +1 -0
  15. package/dist/client/SignOutButton.d.ts +10 -0
  16. package/dist/client/SignOutButton.d.ts.map +1 -0
  17. package/dist/client/SignOutButton.js +35 -0
  18. package/dist/client/SignOutButton.js.map +1 -0
  19. package/dist/client/UserMenu.cjs +54 -0
  20. package/dist/client/UserMenu.cjs.map +1 -0
  21. package/dist/client/UserMenu.d.ts +6 -0
  22. package/dist/client/UserMenu.d.ts.map +1 -0
  23. package/dist/client/UserMenu.js +30 -0
  24. package/dist/client/UserMenu.js.map +1 -0
  25. package/dist/client/use-impersonation.cjs +77 -0
  26. package/dist/client/use-impersonation.cjs.map +1 -0
  27. package/dist/client/use-impersonation.d.ts +39 -0
  28. package/dist/client/use-impersonation.d.ts.map +1 -0
  29. package/dist/client/use-impersonation.js +43 -0
  30. package/dist/client/use-impersonation.js.map +1 -0
  31. package/dist/client.cjs +47 -0
  32. package/dist/client.cjs.map +1 -0
  33. package/dist/client.d.ts +6 -0
  34. package/dist/client.d.ts.map +1 -0
  35. package/dist/client.js +23 -0
  36. package/dist/client.js.map +1 -0
  37. package/dist/{index.d.ts → server/createAuth.d.ts} +1 -1
  38. package/dist/server/createAuth.d.ts.map +1 -0
  39. package/dist/server/impersonation.d.ts +23 -0
  40. package/dist/server/impersonation.d.ts.map +1 -0
  41. package/dist/server/jit.d.ts +97 -0
  42. package/dist/server/jit.d.ts.map +1 -0
  43. package/dist/{index.cjs → server.cjs} +155 -7
  44. package/dist/server.cjs.map +1 -0
  45. package/dist/server.d.ts +4 -0
  46. package/dist/server.d.ts.map +1 -0
  47. package/dist/{index.js → server.js} +144 -3
  48. package/dist/server.js.map +1 -0
  49. package/package.json +22 -11
  50. package/dist/index.cjs.map +0 -1
  51. package/dist/index.d.ts.map +0 -1
  52. package/dist/index.js.map +0 -1
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var use_impersonation_exports = {};
31
+ __export(use_impersonation_exports, {
32
+ useImpersonation: () => useImpersonation
33
+ });
34
+ module.exports = __toCommonJS(use_impersonation_exports);
35
+ var React = __toESM(require("react"));
36
+ function useImpersonation() {
37
+ const [state, setState] = React.useState({
38
+ status: "loading",
39
+ data: null,
40
+ error: null
41
+ });
42
+ const refresh = React.useCallback(async () => {
43
+ try {
44
+ const res = await fetch("/api/auth/me", {
45
+ credentials: "same-origin",
46
+ cache: "no-store"
47
+ });
48
+ if (res.status === 401) {
49
+ setState({ status: "anonymous", data: null, error: null });
50
+ return;
51
+ }
52
+ if (!res.ok) {
53
+ const txt = await res.text().catch(() => "");
54
+ setState({
55
+ status: "error",
56
+ data: null,
57
+ error: txt || `HTTP ${res.status}`
58
+ });
59
+ return;
60
+ }
61
+ const data = await res.json();
62
+ setState({ status: "ready", data, error: null });
63
+ } catch (err) {
64
+ const message = err instanceof Error ? err.message : String(err);
65
+ setState({ status: "error", data: null, error: message });
66
+ }
67
+ }, []);
68
+ React.useEffect(() => {
69
+ void refresh();
70
+ }, [refresh]);
71
+ return { ...state, refresh };
72
+ }
73
+ // Annotate the CommonJS export names for ESM import in node:
74
+ 0 && (module.exports = {
75
+ useImpersonation
76
+ });
77
+ //# sourceMappingURL=use-impersonation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/use-impersonation.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n// =============================================================================\n// useImpersonation -- surfaces the *effective* user via /api/auth/me.\n//\n// Used by ImpersonationBanner + admin surfaces to know whether the current\n// session is impersonated. Hits the spoke's /api/auth/me which returns\n// `{user, impersonatedBy}`.\n//\n// Deliberately doesn't lean on TanStack Query so this can be imported from\n// any client component without forcing a QueryClient provider. Refetch is\n// manual via `refresh()`, which the impersonate API mutators call after a\n// successful start / stop.\n// =============================================================================\n\nexport type EffectiveUser = {\n id: string;\n email: string;\n name: string;\n role: string;\n is_active: boolean;\n credit_balance: number;\n};\n\nexport type ImpersonatedBy = {\n id: string;\n name: string;\n email: string;\n};\n\nexport type MeResponse = {\n user: EffectiveUser;\n impersonatedBy: ImpersonatedBy | null;\n};\n\ntype State =\n | { status: \"loading\"; data: null; error: null }\n | { status: \"anonymous\"; data: null; error: null }\n | { status: \"ready\"; data: MeResponse; error: null }\n | { status: \"error\"; data: null; error: string };\n\nexport function useImpersonation(): State & { refresh: () => Promise<void> } {\n const [state, setState] = React.useState<State>({\n status: \"loading\",\n data: null,\n error: null,\n });\n\n const refresh = React.useCallback(async () => {\n try {\n const res = await fetch(\"/api/auth/me\", {\n credentials: \"same-origin\",\n cache: \"no-store\",\n });\n if (res.status === 401) {\n setState({ status: \"anonymous\", data: null, error: null });\n return;\n }\n if (!res.ok) {\n const txt = await res.text().catch(() => \"\");\n setState({\n status: \"error\",\n data: null,\n error: txt || `HTTP ${res.status}`,\n });\n return;\n }\n const data = (await res.json()) as MeResponse;\n setState({ status: \"ready\", data, error: null });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n setState({ status: \"error\", data: null, error: message });\n }\n }, []);\n\n React.useEffect(() => {\n void refresh();\n }, [refresh]);\n\n return { ...state, refresh };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,YAAuB;AAyChB,SAAS,mBAA6D;AAC3E,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAgB;AAAA,IAC9C,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,MAAM,YAAY,YAAY;AAC5C,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,gBAAgB;AAAA,QACtC,aAAa;AAAA,QACb,OAAO;AAAA,MACT,CAAC;AACD,UAAI,IAAI,WAAW,KAAK;AACtB,iBAAS,EAAE,QAAQ,aAAa,MAAM,MAAM,OAAO,KAAK,CAAC;AACzD;AAAA,MACF;AACA,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,MAAM,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC3C,iBAAS;AAAA,UACP,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO,OAAO,QAAQ,IAAI,MAAM;AAAA,QAClC,CAAC;AACD;AAAA,MACF;AACA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,eAAS,EAAE,QAAQ,SAAS,MAAM,OAAO,KAAK,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,eAAS,EAAE,QAAQ,SAAS,MAAM,MAAM,OAAO,QAAQ,CAAC;AAAA,IAC1D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,MAAM;AACpB,SAAK,QAAQ;AAAA,EACf,GAAG,CAAC,OAAO,CAAC;AAEZ,SAAO,EAAE,GAAG,OAAO,QAAQ;AAC7B;","names":[]}
@@ -0,0 +1,39 @@
1
+ export type EffectiveUser = {
2
+ id: string;
3
+ email: string;
4
+ name: string;
5
+ role: string;
6
+ is_active: boolean;
7
+ credit_balance: number;
8
+ };
9
+ export type ImpersonatedBy = {
10
+ id: string;
11
+ name: string;
12
+ email: string;
13
+ };
14
+ export type MeResponse = {
15
+ user: EffectiveUser;
16
+ impersonatedBy: ImpersonatedBy | null;
17
+ };
18
+ type State = {
19
+ status: "loading";
20
+ data: null;
21
+ error: null;
22
+ } | {
23
+ status: "anonymous";
24
+ data: null;
25
+ error: null;
26
+ } | {
27
+ status: "ready";
28
+ data: MeResponse;
29
+ error: null;
30
+ } | {
31
+ status: "error";
32
+ data: null;
33
+ error: string;
34
+ };
35
+ export declare function useImpersonation(): State & {
36
+ refresh: () => Promise<void>;
37
+ };
38
+ export {};
39
+ //# sourceMappingURL=use-impersonation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-impersonation.d.ts","sourceRoot":"","sources":["../../src/client/use-impersonation.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC,CAAC;AAEF,KAAK,KAAK,GACN;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAC9C;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,wBAAgB,gBAAgB,IAAI,KAAK,GAAG;IAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAuC3E"}
@@ -0,0 +1,43 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ function useImpersonation() {
4
+ const [state, setState] = React.useState({
5
+ status: "loading",
6
+ data: null,
7
+ error: null
8
+ });
9
+ const refresh = React.useCallback(async () => {
10
+ try {
11
+ const res = await fetch("/api/auth/me", {
12
+ credentials: "same-origin",
13
+ cache: "no-store"
14
+ });
15
+ if (res.status === 401) {
16
+ setState({ status: "anonymous", data: null, error: null });
17
+ return;
18
+ }
19
+ if (!res.ok) {
20
+ const txt = await res.text().catch(() => "");
21
+ setState({
22
+ status: "error",
23
+ data: null,
24
+ error: txt || `HTTP ${res.status}`
25
+ });
26
+ return;
27
+ }
28
+ const data = await res.json();
29
+ setState({ status: "ready", data, error: null });
30
+ } catch (err) {
31
+ const message = err instanceof Error ? err.message : String(err);
32
+ setState({ status: "error", data: null, error: message });
33
+ }
34
+ }, []);
35
+ React.useEffect(() => {
36
+ void refresh();
37
+ }, [refresh]);
38
+ return { ...state, refresh };
39
+ }
40
+ export {
41
+ useImpersonation
42
+ };
43
+ //# sourceMappingURL=use-impersonation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/use-impersonation.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n// =============================================================================\n// useImpersonation -- surfaces the *effective* user via /api/auth/me.\n//\n// Used by ImpersonationBanner + admin surfaces to know whether the current\n// session is impersonated. Hits the spoke's /api/auth/me which returns\n// `{user, impersonatedBy}`.\n//\n// Deliberately doesn't lean on TanStack Query so this can be imported from\n// any client component without forcing a QueryClient provider. Refetch is\n// manual via `refresh()`, which the impersonate API mutators call after a\n// successful start / stop.\n// =============================================================================\n\nexport type EffectiveUser = {\n id: string;\n email: string;\n name: string;\n role: string;\n is_active: boolean;\n credit_balance: number;\n};\n\nexport type ImpersonatedBy = {\n id: string;\n name: string;\n email: string;\n};\n\nexport type MeResponse = {\n user: EffectiveUser;\n impersonatedBy: ImpersonatedBy | null;\n};\n\ntype State =\n | { status: \"loading\"; data: null; error: null }\n | { status: \"anonymous\"; data: null; error: null }\n | { status: \"ready\"; data: MeResponse; error: null }\n | { status: \"error\"; data: null; error: string };\n\nexport function useImpersonation(): State & { refresh: () => Promise<void> } {\n const [state, setState] = React.useState<State>({\n status: \"loading\",\n data: null,\n error: null,\n });\n\n const refresh = React.useCallback(async () => {\n try {\n const res = await fetch(\"/api/auth/me\", {\n credentials: \"same-origin\",\n cache: \"no-store\",\n });\n if (res.status === 401) {\n setState({ status: \"anonymous\", data: null, error: null });\n return;\n }\n if (!res.ok) {\n const txt = await res.text().catch(() => \"\");\n setState({\n status: \"error\",\n data: null,\n error: txt || `HTTP ${res.status}`,\n });\n return;\n }\n const data = (await res.json()) as MeResponse;\n setState({ status: \"ready\", data, error: null });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n setState({ status: \"error\", data: null, error: message });\n }\n }, []);\n\n React.useEffect(() => {\n void refresh();\n }, [refresh]);\n\n return { ...state, refresh };\n}\n"],"mappings":";AAEA,YAAY,WAAW;AAyChB,SAAS,mBAA6D;AAC3E,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAgB;AAAA,IAC9C,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,MAAM,YAAY,YAAY;AAC5C,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,gBAAgB;AAAA,QACtC,aAAa;AAAA,QACb,OAAO;AAAA,MACT,CAAC;AACD,UAAI,IAAI,WAAW,KAAK;AACtB,iBAAS,EAAE,QAAQ,aAAa,MAAM,MAAM,OAAO,KAAK,CAAC;AACzD;AAAA,MACF;AACA,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,MAAM,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC3C,iBAAS;AAAA,UACP,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO,OAAO,QAAQ,IAAI,MAAM;AAAA,QAClC,CAAC;AACD;AAAA,MACF;AACA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,eAAS,EAAE,QAAQ,SAAS,MAAM,OAAO,KAAK,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,eAAS,EAAE,QAAQ,SAAS,MAAM,MAAM,OAAO,QAAQ,CAAC;AAAA,IAC1D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,MAAM;AACpB,SAAK,QAAQ;AAAA,EACf,GAAG,CAAC,OAAO,CAAC;AAEZ,SAAO,EAAE,GAAG,OAAO,QAAQ;AAC7B;","names":[]}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var client_exports = {};
20
+ __export(client_exports, {
21
+ AppUserProvider: () => import_AppUserProvider.AppUserProvider,
22
+ ImpersonationBanner: () => import_ImpersonationBanner.ImpersonationBanner,
23
+ SignOutButton: () => import_SignOutButton.SignOutButton,
24
+ UserMenu: () => import_UserMenu.UserMenu,
25
+ useAppUser: () => import_AppUserProvider.useAppUser,
26
+ useDbAppUser: () => import_AppUserProvider.useDbAppUser,
27
+ useImpersonation: () => import_use_impersonation.useImpersonation,
28
+ useRole: () => import_AppUserProvider.useRole
29
+ });
30
+ module.exports = __toCommonJS(client_exports);
31
+ var import_AppUserProvider = require("./client/AppUserProvider.js");
32
+ var import_UserMenu = require("./client/UserMenu.js");
33
+ var import_SignOutButton = require("./client/SignOutButton.js");
34
+ var import_ImpersonationBanner = require("./client/ImpersonationBanner.js");
35
+ var import_use_impersonation = require("./client/use-impersonation.js");
36
+ // Annotate the CommonJS export names for ESM import in node:
37
+ 0 && (module.exports = {
38
+ AppUserProvider,
39
+ ImpersonationBanner,
40
+ SignOutButton,
41
+ UserMenu,
42
+ useAppUser,
43
+ useDbAppUser,
44
+ useImpersonation,
45
+ useRole
46
+ });
47
+ //# sourceMappingURL=client.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["export {\n AppUserProvider,\n useAppUser,\n useDbAppUser,\n useRole,\n type AppUserState,\n type DbAppUser,\n type SessionAppUser,\n} from \"./client/AppUserProvider.js\";\nexport { UserMenu } from \"./client/UserMenu.js\";\nexport { SignOutButton } from \"./client/SignOutButton.js\";\nexport { ImpersonationBanner } from \"./client/ImpersonationBanner.js\";\nexport {\n useImpersonation,\n type EffectiveUser,\n type ImpersonatedBy,\n type MeResponse,\n} from \"./client/use-impersonation.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAQO;AACP,sBAAyB;AACzB,2BAA8B;AAC9B,iCAAoC;AACpC,+BAKO;","names":[]}
@@ -0,0 +1,6 @@
1
+ export { AppUserProvider, useAppUser, useDbAppUser, useRole, type AppUserState, type DbAppUser, type SessionAppUser, } from "./client/AppUserProvider.js";
2
+ export { UserMenu } from "./client/UserMenu.js";
3
+ export { SignOutButton } from "./client/SignOutButton.js";
4
+ export { ImpersonationBanner } from "./client/ImpersonationBanner.js";
5
+ export { useImpersonation, type EffectiveUser, type ImpersonatedBy, type MeResponse, } from "./client/use-impersonation.js";
6
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EACV,YAAY,EACZ,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,cAAc,GACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,+BAA+B,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,23 @@
1
+ import {
2
+ AppUserProvider,
3
+ useAppUser,
4
+ useDbAppUser,
5
+ useRole
6
+ } from "./client/AppUserProvider.js";
7
+ import { UserMenu } from "./client/UserMenu.js";
8
+ import { SignOutButton } from "./client/SignOutButton.js";
9
+ import { ImpersonationBanner } from "./client/ImpersonationBanner.js";
10
+ import {
11
+ useImpersonation
12
+ } from "./client/use-impersonation.js";
13
+ export {
14
+ AppUserProvider,
15
+ ImpersonationBanner,
16
+ SignOutButton,
17
+ UserMenu,
18
+ useAppUser,
19
+ useDbAppUser,
20
+ useImpersonation,
21
+ useRole
22
+ };
23
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["export {\n AppUserProvider,\n useAppUser,\n useDbAppUser,\n useRole,\n type AppUserState,\n type DbAppUser,\n type SessionAppUser,\n} from \"./client/AppUserProvider.js\";\nexport { UserMenu } from \"./client/UserMenu.js\";\nexport { SignOutButton } from \"./client/SignOutButton.js\";\nexport { ImpersonationBanner } from \"./client/ImpersonationBanner.js\";\nexport {\n useImpersonation,\n type EffectiveUser,\n type ImpersonatedBy,\n type MeResponse,\n} from \"./client/use-impersonation.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,OAIK;","names":[]}
@@ -70,4 +70,4 @@ export declare function hasGroup(session: Session | null | undefined, name: stri
70
70
  export declare function requireGroup(session: Session | null | undefined, ...names: string[]): void;
71
71
  export declare function createAuth(opts: CreateAuthOptions): import("next-auth").NextAuthResult;
72
72
  export type { NextAuthConfig } from "next-auth";
73
- //# sourceMappingURL=index.d.ts.map
73
+ //# sourceMappingURL=createAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAuth.d.ts","sourceRoot":"","sources":["../../src/server/createAuth.ts"],"names":[],"mappings":"AAkBA,OAAiB,EACf,KAAK,cAAc,EAEnB,KAAK,OAAO,EACb,MAAM,WAAW,CAAC;AAInB,OAAO,QAAQ,WAAW,CAAC;IACzB,UAAU,OAAO;QACf,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM,EAAE,CAAC;YACjB,IAAI,EAAE,MAAM,CAAC;SACd,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;KAC5B;IACD,UAAU,IAAI;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB;CACF;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2DAA2D;IAC3D,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAIF,qBAAa,SAAU,SAAQ,KAAK;IACf,IAAI,EAAE,iBAAiB,GAAG,WAAW;gBAArC,IAAI,EAAE,iBAAiB,GAAG,WAAW;CAIzD;AAID,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAE3E;AAED,+CAA+C;AAC/C,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAInF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EACnC,GAAG,KAAK,EAAE,MAAM,EAAE,GACjB,IAAI,CAKN;AAyFD,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,sCAgJjD;AAED,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,23 @@
1
+ import "server-only";
2
+ export declare const IMPERSONATE_COOKIE_NAME = "__impersonate";
3
+ export declare const IMPERSONATE_TTL_SECONDS = 3600;
4
+ export type ImpersonationClaims = {
5
+ /** Admin user id who started the impersonation (stringified BigInt). */
6
+ impersonatedBy: string;
7
+ /** Target user id being impersonated (stringified BigInt). */
8
+ sub: string;
9
+ /** Issued-at (seconds since epoch). */
10
+ iat: number;
11
+ /** Expiry (seconds since epoch). */
12
+ exp: number;
13
+ };
14
+ export declare function mintImpersonationToken(args: {
15
+ adminId: bigint | string;
16
+ targetId: bigint | string;
17
+ now?: Date;
18
+ }): Promise<{
19
+ token: string;
20
+ expiresAt: Date;
21
+ }>;
22
+ export declare function verifyImpersonationToken(token: string): Promise<ImpersonationClaims | null>;
23
+ //# sourceMappingURL=impersonation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impersonation.d.ts","sourceRoot":"","sources":["../../src/server/impersonation.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AAqBrB,eAAO,MAAM,uBAAuB,kBAAkB,CAAC;AACvD,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAG5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAkBF,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC,CAgB9C;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA0BrC"}
@@ -0,0 +1,97 @@
1
+ import "server-only";
2
+ import type { Session } from "next-auth";
3
+ /**
4
+ * Minimum contract every spoke User row must satisfy. Spokes can widen this
5
+ * with additional fields (credit_balance, must_change_password, etc.) and the
6
+ * factory will preserve them through the returned `Promise<TUser>`.
7
+ */
8
+ export type BaseAppUser = {
9
+ id: bigint | string | number;
10
+ email: string;
11
+ name: string;
12
+ role: string;
13
+ parent_id: bigint | string | number | null;
14
+ };
15
+ /**
16
+ * Loose typing for the Prisma delegates the factory touches. Each spoke has
17
+ * its own generated client whose actual types are concrete; we use loose
18
+ * shapes here so the factory works with any spoke's schema.
19
+ */
20
+ export type PrismaLikeUserDelegate<TUser> = {
21
+ findUnique: (args: {
22
+ where: {
23
+ id?: unknown;
24
+ email?: string;
25
+ };
26
+ }) => Promise<TUser | null>;
27
+ create: (args: {
28
+ data: unknown;
29
+ }) => Promise<TUser>;
30
+ };
31
+ export type PrismaLikeInvitationDelegate = {
32
+ findFirst: (args: {
33
+ where: {
34
+ email: string;
35
+ accepted_at: null;
36
+ expires_at: {
37
+ gt: Date;
38
+ };
39
+ };
40
+ orderBy?: unknown;
41
+ }) => Promise<{
42
+ id: bigint | string | number;
43
+ intended_role: string;
44
+ parent_id: bigint | string | number | null;
45
+ } | null>;
46
+ update: (args: {
47
+ where: {
48
+ id: unknown;
49
+ };
50
+ data: {
51
+ accepted_at: Date;
52
+ accepted_by_user_id: unknown;
53
+ };
54
+ }) => Promise<unknown>;
55
+ };
56
+ export type PrismaLikeClient<TUser> = {
57
+ user: PrismaLikeUserDelegate<TUser>;
58
+ invitation: PrismaLikeInvitationDelegate;
59
+ $transaction: <T>(fn: (tx: {
60
+ user: PrismaLikeUserDelegate<TUser>;
61
+ invitation: PrismaLikeInvitationDelegate;
62
+ }) => Promise<T>) => Promise<T>;
63
+ };
64
+ export type CreateGetOrCreateAppUserOptions<TUser extends BaseAppUser> = {
65
+ /** Returns the spoke's PrismaClient (lazily). */
66
+ db: () => Promise<PrismaLikeClient<TUser>>;
67
+ /** Fallback role when no admin email + no Cognito groups. */
68
+ defaultRole: string;
69
+ /** Starting credit balance per role. */
70
+ computeCreditBalance: (role: string) => number;
71
+ /** Emails auto-promoted to "admin" role on first sign-in (case-insensitive). */
72
+ adminEmails?: string[];
73
+ /**
74
+ * Hash value written to User.password on creation. Schema-inherited
75
+ * not-null constraint; never used to authenticate (Cognito does that).
76
+ * Default: a recognizable placeholder string.
77
+ */
78
+ placeholderPasswordHash?: string;
79
+ /**
80
+ * Extra column values written on creation. Use this for spoke-specific
81
+ * defaults (e.g. is_active: true, must_change_password: false).
82
+ */
83
+ extraCreateFields?: Record<string, unknown>;
84
+ };
85
+ export type AppUserWithImpersonation<TUser extends BaseAppUser> = TUser & {
86
+ /** Stringified admin id when this session is impersonated; absent otherwise. */
87
+ impersonatedBy?: string;
88
+ };
89
+ /**
90
+ * Build a `getOrCreateAppUser(session)` function configured for this spoke.
91
+ *
92
+ * Returned function is idempotent: subsequent calls with the same email
93
+ * return the existing row. First-time emails are created inside a transaction
94
+ * that also auto-accepts a matching Invitation row if present.
95
+ */
96
+ export declare function createGetOrCreateAppUser<TUser extends BaseAppUser>(opts: CreateGetOrCreateAppUserOptions<TUser>): (session: Session) => Promise<AppUserWithImpersonation<TUser>>;
97
+ //# sourceMappingURL=jit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jit.d.ts","sourceRoot":"","sources":["../../src/server/jit.ts"],"names":[],"mappings":"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"}
@@ -27,16 +27,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
30
+ // src/server.ts
31
+ var server_exports = {};
32
+ __export(server_exports, {
33
33
  AuthError: () => AuthError,
34
+ IMPERSONATE_COOKIE_NAME: () => IMPERSONATE_COOKIE_NAME,
35
+ IMPERSONATE_TTL_SECONDS: () => IMPERSONATE_TTL_SECONDS,
34
36
  createAuth: () => createAuth,
37
+ createGetOrCreateAppUser: () => createGetOrCreateAppUser,
35
38
  getUserGroups: () => getUserGroups,
36
39
  hasGroup: () => hasGroup,
37
- requireGroup: () => requireGroup
40
+ mintImpersonationToken: () => mintImpersonationToken,
41
+ requireGroup: () => requireGroup,
42
+ verifyImpersonationToken: () => verifyImpersonationToken
38
43
  });
39
- module.exports = __toCommonJS(index_exports);
44
+ module.exports = __toCommonJS(server_exports);
45
+
46
+ // src/server/createAuth.ts
40
47
  var import_next_auth = __toESM(require("next-auth"));
41
48
  var import_credentials = __toESM(require("next-auth/providers/credentials"));
42
49
  var import_cognito = __toESM(require("next-auth/providers/cognito"));
@@ -233,12 +240,153 @@ function createAuth(opts) {
233
240
  };
234
241
  return (0, import_next_auth.default)(config);
235
242
  }
243
+
244
+ // src/server/jit.ts
245
+ var import_server_only2 = require("server-only");
246
+ var import_headers = require("next/headers");
247
+
248
+ // src/server/impersonation.ts
249
+ var import_server_only = require("server-only");
250
+ var import_jwt = require("next-auth/jwt");
251
+ var import_server = require("@augmenting-integrations/aws/server");
252
+ var IMPERSONATE_COOKIE_NAME = "__impersonate";
253
+ var IMPERSONATE_TTL_SECONDS = 3600;
254
+ var IMPERSONATE_JWT_SALT = "impersonate.v1";
255
+ var cachedSecret = null;
256
+ async function getAuthSecret() {
257
+ if (cachedSecret) return cachedSecret;
258
+ const arn = process.env.AUTH_SECRET_ARN;
259
+ const fromSm = arn ? await (0, import_server.getSecret)(arn) : null;
260
+ const secret = fromSm ?? process.env.AUTH_SECRET;
261
+ if (!secret) {
262
+ throw new Error(
263
+ "AUTH_SECRET (or AUTH_SECRET_ARN) must be set to mint/verify impersonation tokens"
264
+ );
265
+ }
266
+ cachedSecret = secret;
267
+ return secret;
268
+ }
269
+ async function mintImpersonationToken(args) {
270
+ const secret = await getAuthSecret();
271
+ const nowSec = Math.floor((args.now?.getTime() ?? Date.now()) / 1e3);
272
+ const exp = nowSec + IMPERSONATE_TTL_SECONDS;
273
+ const token = await (0, import_jwt.encode)({
274
+ secret,
275
+ salt: IMPERSONATE_JWT_SALT,
276
+ maxAge: IMPERSONATE_TTL_SECONDS,
277
+ token: {
278
+ impersonatedBy: String(args.adminId),
279
+ sub: String(args.targetId),
280
+ iat: nowSec,
281
+ exp
282
+ }
283
+ });
284
+ return { token, expiresAt: new Date(exp * 1e3) };
285
+ }
286
+ async function verifyImpersonationToken(token) {
287
+ try {
288
+ const secret = await getAuthSecret();
289
+ const decoded = await (0, import_jwt.decode)({
290
+ token,
291
+ secret,
292
+ salt: IMPERSONATE_JWT_SALT
293
+ });
294
+ if (!decoded) return null;
295
+ const impersonatedBy = decoded["impersonatedBy"];
296
+ const sub = decoded["sub"];
297
+ const iat = decoded["iat"];
298
+ const exp = decoded["exp"];
299
+ if (typeof impersonatedBy !== "string" || typeof sub !== "string" || typeof iat !== "number" || typeof exp !== "number") {
300
+ return null;
301
+ }
302
+ if (exp * 1e3 < Date.now()) return null;
303
+ return { impersonatedBy, sub, iat, exp };
304
+ } catch {
305
+ return null;
306
+ }
307
+ }
308
+
309
+ // src/server/jit.ts
310
+ var DEFAULT_PLACEHOLDER_HASH = "$2y$12$.cognito-managed.never.used-for-login.placeholder";
311
+ function createGetOrCreateAppUser(opts) {
312
+ const adminEmailsLower = (opts.adminEmails ?? []).map((s) => s.toLowerCase());
313
+ const placeholder = opts.placeholderPasswordHash ?? DEFAULT_PLACEHOLDER_HASH;
314
+ return async function getOrCreateAppUser(session) {
315
+ const email = session.user?.email;
316
+ if (!email) {
317
+ throw new Error("getOrCreateAppUser called with a session that has no user.email");
318
+ }
319
+ const db = await opts.db();
320
+ try {
321
+ const cookieStore = await (0, import_headers.cookies)();
322
+ const cookie = cookieStore.get(IMPERSONATE_COOKIE_NAME);
323
+ if (cookie?.value) {
324
+ const claims = await verifyImpersonationToken(cookie.value);
325
+ if (claims) {
326
+ const [admin, target] = await Promise.all([
327
+ db.user.findUnique({ where: { id: claims.impersonatedBy } }),
328
+ db.user.findUnique({ where: { id: claims.sub } })
329
+ ]);
330
+ if (admin && admin.role === "admin" && target) {
331
+ return Object.assign(target, {
332
+ impersonatedBy: claims.impersonatedBy
333
+ });
334
+ }
335
+ }
336
+ }
337
+ } catch {
338
+ }
339
+ const existing = await db.user.findUnique({ where: { email } });
340
+ if (existing) return existing;
341
+ const groups = session.user.groups ?? [];
342
+ const fallbackRole = adminEmailsLower.includes(email.toLowerCase()) ? "admin" : groups[0] ?? opts.defaultRole;
343
+ const name = session.user.name ?? email.split("@")[0];
344
+ return db.$transaction(async (tx) => {
345
+ const pendingInvite = await tx.invitation.findFirst({
346
+ where: {
347
+ email,
348
+ accepted_at: null,
349
+ expires_at: { gt: /* @__PURE__ */ new Date() }
350
+ },
351
+ orderBy: { created_at: "desc" }
352
+ });
353
+ const role = pendingInvite ? pendingInvite.intended_role : fallbackRole;
354
+ const parent_id = pendingInvite ? pendingInvite.parent_id : null;
355
+ const created = await tx.user.create({
356
+ data: {
357
+ email,
358
+ name,
359
+ role,
360
+ parent_id,
361
+ password: placeholder,
362
+ credit_balance: opts.computeCreditBalance(role),
363
+ ...opts.extraCreateFields ?? {}
364
+ }
365
+ });
366
+ if (pendingInvite) {
367
+ await tx.invitation.update({
368
+ where: { id: pendingInvite.id },
369
+ data: {
370
+ accepted_at: /* @__PURE__ */ new Date(),
371
+ accepted_by_user_id: created.id
372
+ }
373
+ });
374
+ }
375
+ return created;
376
+ });
377
+ };
378
+ }
236
379
  // Annotate the CommonJS export names for ESM import in node:
237
380
  0 && (module.exports = {
238
381
  AuthError,
382
+ IMPERSONATE_COOKIE_NAME,
383
+ IMPERSONATE_TTL_SECONDS,
239
384
  createAuth,
385
+ createGetOrCreateAppUser,
240
386
  getUserGroups,
241
387
  hasGroup,
242
- requireGroup
388
+ mintImpersonationToken,
389
+ requireGroup,
390
+ verifyImpersonationToken
243
391
  });
244
- //# sourceMappingURL=index.cjs.map
392
+ //# sourceMappingURL=server.cjs.map