@eminuckan/spine 0.2.0

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 (99) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/LICENSE +21 -0
  3. package/README.md +425 -0
  4. package/dist/api-client/index.d.ts +3 -0
  5. package/dist/api-client/index.js +4 -0
  6. package/dist/api-client/server.d.ts +4 -0
  7. package/dist/api-client/server.js +5 -0
  8. package/dist/api-client-Ftxqm3Ep.js +212 -0
  9. package/dist/api-client-Ftxqm3Ep.js.map +1 -0
  10. package/dist/auth/index.d.ts +2 -0
  11. package/dist/auth/index.js +0 -0
  12. package/dist/auth/server.d.ts +3 -0
  13. package/dist/auth/server.js +6 -0
  14. package/dist/auth.server-C979TR6W.js +724 -0
  15. package/dist/auth.server-C979TR6W.js.map +1 -0
  16. package/dist/auth.server-DU-x2LPA.js +5 -0
  17. package/dist/identity/index.d.ts +4 -0
  18. package/dist/identity/index.js +3 -0
  19. package/dist/identity/server.d.ts +4 -0
  20. package/dist/identity/server.js +4 -0
  21. package/dist/identity-CFa1txoj.js +235 -0
  22. package/dist/identity-CFa1txoj.js.map +1 -0
  23. package/dist/index-BIJOC8Fb.d.ts +272 -0
  24. package/dist/index-BIJOC8Fb.d.ts.map +1 -0
  25. package/dist/index-Bt9XE6gj.d.ts +104 -0
  26. package/dist/index-Bt9XE6gj.d.ts.map +1 -0
  27. package/dist/index-C2hGpzGr.d.ts +74 -0
  28. package/dist/index-C2hGpzGr.d.ts.map +1 -0
  29. package/dist/index-CfQsb3l_.d.ts +170 -0
  30. package/dist/index-CfQsb3l_.d.ts.map +1 -0
  31. package/dist/index-D6RK_5vm.d.ts +199 -0
  32. package/dist/index-D6RK_5vm.d.ts.map +1 -0
  33. package/dist/index-DrttYPAj.d.ts +30 -0
  34. package/dist/index-DrttYPAj.d.ts.map +1 -0
  35. package/dist/index-geY2ynnN.d.ts +141 -0
  36. package/dist/index-geY2ynnN.d.ts.map +1 -0
  37. package/dist/index-kr8Wk7v5.d.ts +1 -0
  38. package/dist/index.d.ts +12 -0
  39. package/dist/index.js +10 -0
  40. package/dist/logging/index.d.ts +3 -0
  41. package/dist/logging/index.js +3 -0
  42. package/dist/logging-_h2mi3L9.js +118 -0
  43. package/dist/logging-_h2mi3L9.js.map +1 -0
  44. package/dist/permissions/index.d.ts +2 -0
  45. package/dist/permissions/index.js +3 -0
  46. package/dist/permissions-D5ScGGnd.js +281 -0
  47. package/dist/permissions-D5ScGGnd.js.map +1 -0
  48. package/dist/query-client/index.d.ts +2 -0
  49. package/dist/query-client/index.js +3 -0
  50. package/dist/query-client-DRPQIKHX.js +174 -0
  51. package/dist/query-client-DRPQIKHX.js.map +1 -0
  52. package/dist/react-router/index.d.ts +12 -0
  53. package/dist/react-router/index.js +10 -0
  54. package/dist/react-router/server.d.ts +18 -0
  55. package/dist/react-router/server.js +17 -0
  56. package/dist/redis-session-storage.server-DhufyPjd.js +250 -0
  57. package/dist/redis-session-storage.server-DhufyPjd.js.map +1 -0
  58. package/dist/server-BoeUiXSh.d.ts +40 -0
  59. package/dist/server-BoeUiXSh.d.ts.map +1 -0
  60. package/dist/server-C-DiVP9e.js +185 -0
  61. package/dist/server-C-DiVP9e.js.map +1 -0
  62. package/dist/server-CLbksnvg.d.ts +144 -0
  63. package/dist/server-CLbksnvg.d.ts.map +1 -0
  64. package/dist/server-CNp6gjFE.js +78 -0
  65. package/dist/server-CNp6gjFE.js.map +1 -0
  66. package/dist/server-CXGaRaiS.d.ts +256 -0
  67. package/dist/server-CXGaRaiS.d.ts.map +1 -0
  68. package/dist/server-CiSbg-9C.js +352 -0
  69. package/dist/server-CiSbg-9C.js.map +1 -0
  70. package/dist/server-DLgH3FRR.js +312 -0
  71. package/dist/server-DLgH3FRR.js.map +1 -0
  72. package/dist/server-DazqdM63.d.ts +93 -0
  73. package/dist/server-DazqdM63.d.ts.map +1 -0
  74. package/dist/server-iWm3oeCM.js +145 -0
  75. package/dist/server-iWm3oeCM.js.map +1 -0
  76. package/dist/server-zEKMDpP7.d.ts +80 -0
  77. package/dist/server-zEKMDpP7.d.ts.map +1 -0
  78. package/dist/server.d.ts +18 -0
  79. package/dist/server.js +17 -0
  80. package/dist/signalr/index.d.ts +4 -0
  81. package/dist/signalr/index.js +3 -0
  82. package/dist/signalr-BJGcXc0m.js +274 -0
  83. package/dist/signalr-BJGcXc0m.js.map +1 -0
  84. package/dist/src-D7mh9MKA.js +0 -0
  85. package/dist/tenant/index.d.ts +3 -0
  86. package/dist/tenant/index.js +3 -0
  87. package/dist/tenant/server.d.ts +3 -0
  88. package/dist/tenant/server.js +5 -0
  89. package/dist/tenant-C6KPaSCX.js +256 -0
  90. package/dist/tenant-C6KPaSCX.js.map +1 -0
  91. package/dist/types-BTjFzIhv.d.ts +31 -0
  92. package/dist/types-BTjFzIhv.d.ts.map +1 -0
  93. package/dist/types-DoIfDhl6.d.ts +55 -0
  94. package/dist/types-DoIfDhl6.d.ts.map +1 -0
  95. package/dist/types-DufLRY7A.d.ts +164 -0
  96. package/dist/types-DufLRY7A.d.ts.map +1 -0
  97. package/dist/types-uDrDMkCq.d.ts +93 -0
  98. package/dist/types-uDrDMkCq.d.ts.map +1 -0
  99. package/package.json +147 -0
@@ -0,0 +1,144 @@
1
+ import { APIConfig, APILogger, CreateAPIConfigOptions, GetAccessTokenFn, GetCurrentTenantFn, RetryConfig, TokenRefreshFn } from "./index-D6RK_5vm.js";
2
+ import { AxiosInstance } from "axios";
3
+
4
+ //#region src/api-client/api-config.server.d.ts
5
+ /**
6
+ * API Config Factory Options
7
+ */
8
+
9
+ /**
10
+ * API Config Factory Options
11
+ */
12
+ interface APIConfigFactoryOptions {
13
+ /**
14
+ * Base URL for API requests
15
+ */
16
+ baseURL?: string;
17
+ /**
18
+ * Default headers applied to all requests
19
+ */
20
+ defaultHeaders?: Record<string, string>;
21
+ /**
22
+ * User agent string
23
+ */
24
+ userAgent?: string;
25
+ /**
26
+ * Default timeout in milliseconds
27
+ */
28
+ timeout?: number;
29
+ }
30
+ /**
31
+ * Create API Config Factory
32
+ *
33
+ * Creates a factory function that generates API configurations
34
+ * with the provided auth and tenant resolvers.
35
+ */
36
+ declare function createAPIConfigFactory(getAccessToken: GetAccessTokenFn, getCurrentTenant: GetCurrentTenantFn, logger?: APILogger, factoryOptions?: APIConfigFactoryOptions): {
37
+ createAPIConfig: (request: Request, options?: CreateAPIConfigOptions) => Promise<APIConfig>;
38
+ getAPIBaseURL: () => string;
39
+ };
40
+ type APIConfigFactory = ReturnType<typeof createAPIConfigFactory>; //#endregion
41
+ //#region src/api-client/axios-setup.server.d.ts
42
+
43
+ //# sourceMappingURL=api-config.server.d.ts.map
44
+ /**
45
+ * Axios Setup Options
46
+ */
47
+ interface AxiosSetupOptions {
48
+ /**
49
+ * Logger instance for logging
50
+ */
51
+ logger?: APILogger;
52
+ /**
53
+ * Token refresh function
54
+ */
55
+ attemptTokenRefresh?: TokenRefreshFn;
56
+ /**
57
+ * Retry configuration
58
+ */
59
+ retryConfig?: RetryConfig;
60
+ /**
61
+ * Whether to add request ID header
62
+ */
63
+ addRequestId?: boolean;
64
+ }
65
+ /**
66
+ * Setup Axios interceptors for auto-generated clients
67
+ *
68
+ * Features:
69
+ * - Automatic token refresh on 401
70
+ * - Retry logic with exponential backoff
71
+ * - ProblemDetails error parsing
72
+ * - Timeout management
73
+ * - Comprehensive logging
74
+ *
75
+ * @param axiosInstance - The Axios instance from auto-generated client
76
+ * @param request - The incoming request object (for token refresh)
77
+ * @param options - Configuration options
78
+ *
79
+ * @example
80
+ * ` ypescript
81
+ * const config = await createAPIConfig(request);
82
+ * const api = new IdentityApi(config);
83
+ * setupAxiosInterceptors(api.axios, request, { logger, attemptTokenRefresh });
84
+ *
85
+ * // Now all API calls have automatic retry, token refresh, error handling
86
+ * const users = await api.getUsers(tenantId);
87
+ * `
88
+ */
89
+ declare function setupAxiosInterceptors(axiosInstance: AxiosInstance, request: Request, options?: AxiosSetupOptions): void;
90
+ /**
91
+ * Create Enhanced Client Options
92
+ */
93
+ interface CreateEnhancedClientOptions extends AxiosSetupOptions {
94
+ /**
95
+ * Whether tenant is required
96
+ */
97
+ requireTenant?: boolean;
98
+ /**
99
+ * Whether to include auth
100
+ */
101
+ includeAuth?: boolean;
102
+ /**
103
+ * Explicit tenant ID override
104
+ */
105
+ tenantId?: string;
106
+ /**
107
+ * Custom headers
108
+ */
109
+ customHeaders?: Record<string, string>;
110
+ }
111
+ /**
112
+ * Helper to create and setup an API client in one call
113
+ *
114
+ * @param request - The incoming request object
115
+ * @param ClientClass - The auto-generated API client class
116
+ * @param createAPIConfig - Function to create API configuration
117
+ * @param ConfigurationClass - The Configuration class from generated API
118
+ * @param options - Configuration options
119
+ * @returns Configured API client instance with interceptors
120
+ *
121
+ * @example
122
+ * ` ypescript
123
+ * import { IdentityApi, Configuration } from './generated-api';
124
+ *
125
+ * const { client: api, tenantId } = await createEnhancedClient(
126
+ * request,
127
+ * IdentityApi,
128
+ * createAPIConfig,
129
+ * Configuration,
130
+ * { logger, attemptTokenRefresh }
131
+ * );
132
+ * const users = await api.getUsers(tenantId);
133
+ * `
134
+ */
135
+ declare function createEnhancedClient<T>(request: Request, ClientClass: new (configuration?: any, basePath?: string, axios?: AxiosInstance) => T, createAPIConfig: (request: Request, options?: any) => Promise<any>, ConfigurationClass: new (params?: any) => any, options?: CreateEnhancedClientOptions): Promise<{
136
+ client: T;
137
+ tenantId: string;
138
+ }>;
139
+
140
+ //#endregion
141
+ //# sourceMappingURL=axios-setup.server.d.ts.map
142
+
143
+ export { APIConfigFactory, APIConfigFactoryOptions, AxiosSetupOptions, CreateEnhancedClientOptions, createAPIConfigFactory as createAPIConfigFactory$1, createEnhancedClient as createEnhancedClient$1, setupAxiosInterceptors as setupAxiosInterceptors$1 };
144
+ //# sourceMappingURL=server-CLbksnvg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-CLbksnvg.d.ts","names":[],"sources":["../src/api-client/api-config.server.ts","../src/api-client/axios-setup.server.ts"],"sourcesContent":null,"mappings":";;;;;;;;AA2BA;;;UAAiB,uBAAA;;;;EAyBD,OAAA,CAAA,EAAA,MAAA;EAAsB;;;EAEA,cAC3B,CAAA,EApBQ,MAoBR,CAAA,MAAA,EAAA,MAAA,CAAA;EAAS;;;EAiEe,SACtB,CAAA,EAAA,MAAA;EAAS;AAAV;AA0EZ;EAA4B,OAAA,CAAA,EAAA,MAAA;;;AAAa;;;;;iBA/IzB,sBAAA,iBACE,oCACE,6BACT,4BACO;6BA+DL,mBACA,2BACR,QAAQ;EClDI,aAAA,EAAA,GAAA,GAAiB,MAAA;CAAA;AAIvB,KDwHC,gBAAA,GAAmB,UCxHpB,CAAA,ODwHsC,sBCxHtC,CAAA,CAAA;;;;;;;AD4CE,UChDI,iBAAA,CDgDJ;EAAO;;;EAER,MAAA,CAAA,EC9CD,SD8CC;EA0EA;;;EAA2D,mBAAxC,CAAA,ECpHP,cDoHO;EAAU;;;gBChHzB;;;;EAZC,YAAA,CAAA,EAAA,OAAiB;;;;;AAYP;;;;;;;;;;;;;;;;;;;;;iBA+BX,sBAAA,gBACC,wBACN,mBACA;;;;AAHK,UA8KC,2BAAA,SAAoC,iBA9Kf,CAAA;EAAA;;;EAEpB,aACP,CAAA,EAAA,OAAA;EAAsB;;;;EA2KhB;;;EAgBO,QAhB6B,CAAA,EAAA,MAAA;EAAiB;;;kBAgBpD;;;;;;;;;;;;;;;;;;;;;;AA2BlB;;;;AAEsF,iBAFhE,oBAEgE,CAAA,CAAA,CAAA,CAAA,OAAA,EAD3E,OAC2E,EAAA,WAAA,EAAA,KAAA,aAAA,CAAA,EAAA,GAAA,EAAA,QAAA,CAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAlB,aAAkB,EAAA,GAAA,CAAA,EAAA,eAAA,EAAA,CAAA,OAAA,EACzD,OADyD,EAAA,OAAA,CAAA,EAAA,GAAA,EAAA,GAC9B,OAD8B,CAAA,GAAA,CAAA,EAAA,kBAAA,EAAA,KAAA,MAAA,CAAA,EAAA,GAAA,EAAA,GAAA,GAAA,EAAA,OAAA,CAAA,EAG3E,2BAH2E,CAAA,EAInF,OAJmF,CAAA;EAAC,MAC1D,EAGR,CAHQ;EAAO,QAAoB,EAAA,MAAA;CAAO,CAAA"}
@@ -0,0 +1,78 @@
1
+ import { PermissionChecker } from "./permissions-D5ScGGnd.js";
2
+
3
+ //#region src/permissions/route-protection.server.ts
4
+ const DEFAULT_UNAUTHORIZED_RESPONSE = () => new Response("Unauthorized", {
5
+ status: 401,
6
+ statusText: "You must be logged in to access this resource"
7
+ });
8
+ const DEFAULT_FORBIDDEN_RESPONSE = (details) => {
9
+ const message = process.env.NODE_ENV === "development" ? `Missing permissions: ${details.missingPermissions?.join(", ")}` : "You don't have permission to access this resource";
10
+ return new Response(message, {
11
+ status: 403,
12
+ statusText: "Forbidden"
13
+ });
14
+ };
15
+ let permissionRouteProtectionConfig = {};
16
+ function getPermissionRouteProtectionConfig() {
17
+ if (!permissionRouteProtectionConfig.getSession) throw new Error("Permission route protection session getter not configured. Call configurePermissionRouteProtection first.");
18
+ if (!permissionRouteProtectionConfig.resolveContext) throw new Error("Permission route protection context resolver not configured. Call configurePermissionRouteProtection first.");
19
+ return {
20
+ getSession: permissionRouteProtectionConfig.getSession,
21
+ resolveContext: permissionRouteProtectionConfig.resolveContext,
22
+ createUnauthorizedResponse: permissionRouteProtectionConfig.createUnauthorizedResponse || DEFAULT_UNAUTHORIZED_RESPONSE,
23
+ createForbiddenResponse: permissionRouteProtectionConfig.createForbiddenResponse || DEFAULT_FORBIDDEN_RESPONSE
24
+ };
25
+ }
26
+ function configurePermissionRouteProtection(config) {
27
+ permissionRouteProtectionConfig = {
28
+ ...permissionRouteProtectionConfig,
29
+ ...config
30
+ };
31
+ }
32
+ function resetPermissionRouteProtection() {
33
+ permissionRouteProtectionConfig = {};
34
+ }
35
+ async function getPermissionRouteState(request) {
36
+ const config = getPermissionRouteProtectionConfig();
37
+ const session = await config.getSession(request);
38
+ const context = await config.resolveContext(request, session);
39
+ return {
40
+ config,
41
+ session,
42
+ context
43
+ };
44
+ }
45
+ async function requirePermission(request, permission, options = {}) {
46
+ const { config, session, context } = await getPermissionRouteState(request);
47
+ if (!session.user || !session.accessToken) throw config.createUnauthorizedResponse(request, session);
48
+ const checker = new PermissionChecker(context.permissions || []);
49
+ const permissionsToCheck = Array.isArray(permission) ? permission : [permission];
50
+ const result = checker.hasPermissions(permissionsToCheck, options);
51
+ if (!result.hasPermission) throw config.createForbiddenResponse({
52
+ request,
53
+ permission,
54
+ permissionsToCheck,
55
+ missingPermissions: result.missingPermissions,
56
+ options,
57
+ session,
58
+ context
59
+ });
60
+ }
61
+ async function checkPermission(request, permission, options = {}) {
62
+ try {
63
+ await requirePermission(request, permission, options);
64
+ return true;
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+ function withPermission(permission, loader, options) {
70
+ return async (args) => {
71
+ await requirePermission(args.request, permission, options);
72
+ return loader(args);
73
+ };
74
+ }
75
+
76
+ //#endregion
77
+ export { checkPermission, configurePermissionRouteProtection, requirePermission, resetPermissionRouteProtection, withPermission };
78
+ //# sourceMappingURL=server-CNp6gjFE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-CNp6gjFE.js","names":["details: ForbiddenPermissionDetails","permissionRouteProtectionConfig: PermissionRouteProtectionConfig","config: PermissionRouteProtectionConfig","request: Request","permission: PermissionCode | PermissionCode[]","options: PermissionCheckOptions","loader: (args: any) => Promise<TLoaderData>","options?: PermissionCheckOptions","args: any"],"sources":["../src/permissions/route-protection.server.ts"],"sourcesContent":["import { PermissionChecker } from './permission-service';\nimport type { PermissionCheckOptions, PermissionCode } from './types';\n\nexport interface PermissionRouteSession {\n user?: {\n sub?: string;\n email?: string | null;\n } | null;\n accessToken?: string | null;\n}\n\nexport interface PermissionRouteContext {\n permissions: PermissionCode[];\n currentTenant?: string | null;\n}\n\nexport interface ForbiddenPermissionDetails {\n request: Request;\n permission: PermissionCode | PermissionCode[];\n permissionsToCheck: PermissionCode[];\n missingPermissions?: PermissionCode[];\n options: PermissionCheckOptions;\n session: PermissionRouteSession;\n context: PermissionRouteContext;\n}\n\nexport interface PermissionRouteProtectionConfig {\n getSession?: (request: Request) => Promise<PermissionRouteSession>;\n resolveContext?: (\n request: Request,\n session: PermissionRouteSession\n ) => Promise<PermissionRouteContext>;\n createUnauthorizedResponse?: (\n request: Request,\n session: PermissionRouteSession\n ) => Response;\n createForbiddenResponse?: (details: ForbiddenPermissionDetails) => Response;\n}\n\nconst DEFAULT_UNAUTHORIZED_RESPONSE = () =>\n new Response('Unauthorized', {\n status: 401,\n statusText: 'You must be logged in to access this resource',\n });\n\nconst DEFAULT_FORBIDDEN_RESPONSE = (details: ForbiddenPermissionDetails) => {\n const message =\n process.env.NODE_ENV === 'development'\n ? `Missing permissions: ${details.missingPermissions?.join(', ')}`\n : \"You don't have permission to access this resource\";\n\n return new Response(message, {\n status: 403,\n statusText: 'Forbidden',\n });\n};\n\nlet permissionRouteProtectionConfig: PermissionRouteProtectionConfig = {};\n\nfunction getPermissionRouteProtectionConfig(): Required<PermissionRouteProtectionConfig> {\n if (!permissionRouteProtectionConfig.getSession) {\n throw new Error(\n 'Permission route protection session getter not configured. Call configurePermissionRouteProtection first.'\n );\n }\n\n if (!permissionRouteProtectionConfig.resolveContext) {\n throw new Error(\n 'Permission route protection context resolver not configured. Call configurePermissionRouteProtection first.'\n );\n }\n\n return {\n getSession: permissionRouteProtectionConfig.getSession,\n resolveContext: permissionRouteProtectionConfig.resolveContext,\n createUnauthorizedResponse:\n permissionRouteProtectionConfig.createUnauthorizedResponse || DEFAULT_UNAUTHORIZED_RESPONSE,\n createForbiddenResponse:\n permissionRouteProtectionConfig.createForbiddenResponse || DEFAULT_FORBIDDEN_RESPONSE,\n };\n}\n\nexport function configurePermissionRouteProtection(\n config: PermissionRouteProtectionConfig\n): void {\n permissionRouteProtectionConfig = {\n ...permissionRouteProtectionConfig,\n ...config,\n };\n}\n\nexport function resetPermissionRouteProtection(): void {\n permissionRouteProtectionConfig = {};\n}\n\nasync function getPermissionRouteState(request: Request): Promise<{\n config: Required<PermissionRouteProtectionConfig>;\n session: PermissionRouteSession;\n context: PermissionRouteContext;\n}> {\n const config = getPermissionRouteProtectionConfig();\n const session = await config.getSession(request);\n const context = await config.resolveContext(request, session);\n\n return {\n config,\n session,\n context,\n };\n}\n\nexport async function requirePermission(\n request: Request,\n permission: PermissionCode | PermissionCode[],\n options: PermissionCheckOptions = {}\n): Promise<void> {\n const { config, session, context } = await getPermissionRouteState(request);\n\n if (!session.user || !session.accessToken) {\n throw config.createUnauthorizedResponse(request, session);\n }\n\n const checker = new PermissionChecker(context.permissions || []);\n const permissionsToCheck = Array.isArray(permission) ? permission : [permission];\n const result = checker.hasPermissions(permissionsToCheck, options);\n\n if (!result.hasPermission) {\n throw config.createForbiddenResponse({\n request,\n permission,\n permissionsToCheck,\n missingPermissions: result.missingPermissions,\n options,\n session,\n context,\n });\n }\n}\n\nexport async function checkPermission(\n request: Request,\n permission: PermissionCode | PermissionCode[],\n options: PermissionCheckOptions = {}\n): Promise<boolean> {\n try {\n await requirePermission(request, permission, options);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function withPermission<TLoaderData>(\n permission: PermissionCode | PermissionCode[],\n loader: (args: any) => Promise<TLoaderData>,\n options?: PermissionCheckOptions\n) {\n return async (args: any): Promise<TLoaderData> => {\n await requirePermission(args.request, permission, options);\n return loader(args);\n };\n}\n"],"mappings":";;;AAuCA,MAAM,gCAAgC,MACpC,IAAI,SAAS,gBAAgB;CAC3B,QAAQ;CACR,YAAY;AACb;AAEH,MAAM,6BAA6B,CAACA,YAAwC;CAC1E,MAAM,UACJ,QAAQ,IAAI,aAAa,iBACpB,uBAAuB,QAAQ,oBAAoB,KAAK,KAAK,CAAC,IAC/D;AAEN,QAAO,IAAI,SAAS,SAAS;EAC3B,QAAQ;EACR,YAAY;CACb;AACF;AAED,IAAIC,kCAAmE,CAAE;AAEzE,SAAS,qCAAgF;AACvF,MAAK,gCAAgC,WACnC,OAAM,IAAI,MACR;AAIJ,MAAK,gCAAgC,eACnC,OAAM,IAAI,MACR;AAIJ,QAAO;EACL,YAAY,gCAAgC;EAC5C,gBAAgB,gCAAgC;EAChD,4BACE,gCAAgC,8BAA8B;EAChE,yBACE,gCAAgC,2BAA2B;CAC9D;AACF;AAED,SAAgB,mCACdC,QACM;AACN,mCAAkC;EAChC,GAAG;EACH,GAAG;CACJ;AACF;AAED,SAAgB,iCAAuC;AACrD,mCAAkC,CAAE;AACrC;AAED,eAAe,wBAAwBC,SAIpC;CACD,MAAM,SAAS,oCAAoC;CACnD,MAAM,UAAU,MAAM,OAAO,WAAW,QAAQ;CAChD,MAAM,UAAU,MAAM,OAAO,eAAe,SAAS,QAAQ;AAE7D,QAAO;EACL;EACA;EACA;CACD;AACF;AAED,eAAsB,kBACpBA,SACAC,YACAC,UAAkC,CAAE,GACrB;CACf,MAAM,EAAE,QAAQ,SAAS,SAAS,GAAG,MAAM,wBAAwB,QAAQ;AAE3E,MAAK,QAAQ,SAAS,QAAQ,YAC5B,OAAM,OAAO,2BAA2B,SAAS,QAAQ;CAG3D,MAAM,UAAU,IAAI,kBAAkB,QAAQ,eAAe,CAAE;CAC/D,MAAM,qBAAqB,MAAM,QAAQ,WAAW,GAAG,aAAa,CAAC,UAAW;CAChF,MAAM,SAAS,QAAQ,eAAe,oBAAoB,QAAQ;AAElE,MAAK,OAAO,cACV,OAAM,OAAO,wBAAwB;EACnC;EACA;EACA;EACA,oBAAoB,OAAO;EAC3B;EACA;EACA;CACD,EAAC;AAEL;AAED,eAAsB,gBACpBF,SACAC,YACAC,UAAkC,CAAE,GAClB;AAClB,KAAI;AACF,QAAM,kBAAkB,SAAS,YAAY,QAAQ;AACrD,SAAO;CACR,QAAO;AACN,SAAO;CACR;AACF;AAED,SAAgB,eACdD,YACAE,QACAC,SACA;AACA,QAAO,OAAOC,SAAoC;AAChD,QAAM,kBAAkB,KAAK,SAAS,YAAY,QAAQ;AAC1D,SAAO,OAAO,KAAK;CACpB;AACF"}
@@ -0,0 +1,256 @@
1
+ import { AuthClaimMapping, AuthError, LoginOptions, OAuthState, ProtectionLevel, SessionData, TokenRefreshResult$1 as TokenRefreshResult, UserInfo } from "./types-DufLRY7A.js";
2
+
3
+ //#region src/auth/redis-session-storage.server.d.ts
4
+
5
+ declare const AUTH_ERROR_COOKIE_PREFIX: string;
6
+ declare function createAuthSession(request: Request, sessionData: Partial<SessionData>): Promise<Headers>;
7
+ declare function getAuthSession(request: Request): Promise<SessionData>;
8
+ declare function updateAuthSession(request: Request, updates: Partial<SessionData>): Promise<Headers>;
9
+ declare function destroyAuthSession(request: Request): Promise<Headers>;
10
+ declare function requireAuthSession(request: Request): Promise<SessionData>;
11
+ declare function isSessionValid(request: Request): Promise<boolean>;
12
+ declare function createOAuthState(state: OAuthState): Promise<string>;
13
+ declare function getOAuthState(stateId: string): Promise<OAuthState | null>;
14
+ declare function deleteOAuthState(stateId: string): Promise<void>;
15
+ declare function cleanupExpiredOAuthStates(): Promise<number>;
16
+ declare function closeRedisConnection(): Promise<void>;
17
+
18
+ //#endregion
19
+ //#region src/auth/auth.server.d.ts
20
+ //# sourceMappingURL=redis-session-storage.server.d.ts.map
21
+ /**
22
+ * Configure claim mapping so different providers/backends can project their
23
+ * own claim names onto the shared auth/session primitives.
24
+ */
25
+ declare function configureAuthClaimMapping(mapping: AuthClaimMapping): void;
26
+ /**
27
+ * Reset claim mapping to the built-in defaults.
28
+ */
29
+ declare function resetAuthClaimMapping(): void;
30
+ /**
31
+ * Extract user info from ID token claims
32
+ */
33
+ declare function extractUserInfo(claims: Record<string, unknown>): {
34
+ tenants: string[];
35
+ currentTenant?: string;
36
+ isOnboarded: boolean;
37
+ tenantRoles: Record<string, string[]>;
38
+ permissions: string[];
39
+ };
40
+ /**
41
+ * Check if there's an auth error in cookies
42
+ *
43
+ * This should be called by apps (especially those without landing pages like Dashboard)
44
+ * BEFORE starting OAuth flow to prevent redirect loops.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * // In dashboard's index route loader
49
+ * const authError = getAuthError(request);
50
+ * if (authError) {
51
+ * return { authError }; // Show error to user
52
+ * }
53
+ * // No error, proceed with session check
54
+ * const user = await getUser(request);
55
+ * if (!user) {
56
+ * return login(request);
57
+ * }
58
+ * ```
59
+ */
60
+ declare function getAuthError(request: Request): AuthError | null;
61
+ /**
62
+ * Clear auth error cookies
63
+ *
64
+ * Call this after displaying the error to the user
65
+ */
66
+ declare function clearAuthErrorHeaders(): Headers;
67
+ /**
68
+ * Check if request has auth error (quick check without parsing)
69
+ */
70
+ declare function hasAuthError(request: Request): boolean;
71
+ /**
72
+ * Initiate OAuth login flow
73
+ *
74
+ * @param request - The incoming request
75
+ * @param returnUrlOrOptions - Either a return URL string or LoginOptions object
76
+ */
77
+ declare function login(request: Request, returnUrlOrOptions?: string | LoginOptions): Promise<Response>;
78
+ /**
79
+ * Handle OAuth callback
80
+ *
81
+ * Handles OAuth authorization response including success and error cases.
82
+ *
83
+ * Error Handling:
84
+ * - `access_denied`: User doesn't have access to this application
85
+ * - For apps with landing page: Redirect home with error cookie
86
+ * - For apps without landing page: Redirect home with error cookie (must handle specially)
87
+ * - `login_required`: No active identity session
88
+ * - Redirect to home to start fresh login
89
+ */
90
+ declare function handleCallback(request: Request): Promise<Response>;
91
+ /**
92
+ * Logout user
93
+ *
94
+ * Backend uses id_token_hint to identify which tokens to revoke.
95
+ *
96
+ * **Scenario 1: Full SSO Logout (Manual Sign Out)**
97
+ * - Query param: sso_logout=true
98
+ * - Result: Full logout + identity cookie cleared
99
+ * - User must re-authenticate everywhere
100
+ *
101
+ * **Scenario 2: Standard Logout (Automatic/Token Expired)**
102
+ * - No sso_logout param
103
+ * - Result: Tokens revoked based on id_token_hint
104
+ * - Backend determines which tokens to revoke
105
+ *
106
+ * Configuration:
107
+ * - `OIDC_SSO_LOGOUT` env var ('true' | 'false') - default behavior
108
+ * - Query param `sso_logout=true` - override for full logout
109
+ */
110
+ declare function logout(request: Request): Promise<Response>;
111
+ /**
112
+ * Get current user from session
113
+ */
114
+ declare function getUser(request: Request): Promise<UserInfo | null>;
115
+ /**
116
+ * Require authenticated user (throws redirect to login if not authenticated)
117
+ */
118
+ declare function requireAuth(request: Request): Promise<UserInfo>;
119
+ /**
120
+ * Get access token from session
121
+ */
122
+ declare function getAccessToken(request: Request): Promise<string | null>;
123
+ /**
124
+ * Refresh tokens
125
+ */
126
+ declare function refreshTokens(request: Request, refreshToken?: string): Promise<TokenRefreshResult>;
127
+ /**
128
+ * Clear auth server cache (useful for testing)
129
+ */
130
+ declare function clearAuthServerCache(): void;
131
+
132
+ //#endregion
133
+ //#region src/auth/route-protection.server.d.ts
134
+ //# sourceMappingURL=auth.server.d.ts.map
135
+ /**
136
+ * Check if token needs refresh
137
+ */
138
+ declare function shouldRefreshToken(request: Request): Promise<boolean>;
139
+ /**
140
+ * Identity context check configuration
141
+ */
142
+ interface DefaultRouteIdentityContext {
143
+ hasAnyMembership: boolean;
144
+ hasSubscription: boolean;
145
+ isOnboarded: boolean;
146
+ }
147
+ interface IdentityContextChecker<TIdentityContext = DefaultRouteIdentityContext> {
148
+ getIdentityContext: (request: Request, userId: string, forceRefresh?: boolean) => Promise<DefaultRouteIdentityContext & TIdentityContext>;
149
+ }
150
+ /**
151
+ * Tenant checker configuration
152
+ */
153
+ interface TenantChecker {
154
+ getCurrentTenant: (request: Request) => Promise<string | null>;
155
+ initializeTenant: (request: Request) => Promise<{
156
+ headers: Headers;
157
+ tenantId: string;
158
+ } | null>;
159
+ }
160
+ /**
161
+ * Subscription checker configuration
162
+ */
163
+ interface SubscriptionChecker {
164
+ checkTenantSubscriptionStatus: (request: Request, tenantId: string) => Promise<boolean>;
165
+ }
166
+ interface RouteProtectionRedirect {
167
+ location: string;
168
+ headers?: HeadersInit;
169
+ status?: number;
170
+ }
171
+ interface AutomaticLogoutRequestContext {
172
+ request: Request;
173
+ reason: 'expired-no-refresh-token' | 'refresh-failed';
174
+ }
175
+ interface LoginReturnUrlContext {
176
+ request: Request;
177
+ currentPath: string;
178
+ protection: ProtectionLevel;
179
+ }
180
+ interface RouteProtectionResolverContext<TIdentityContext = DefaultRouteIdentityContext> {
181
+ request: Request;
182
+ user: UserInfo;
183
+ currentPath: string;
184
+ protection: ProtectionLevel;
185
+ getIdentityContext: (forceRefresh?: boolean) => Promise<TIdentityContext | null>;
186
+ getCurrentTenant: () => Promise<string | null>;
187
+ initializeTenant: () => Promise<{
188
+ headers: Headers;
189
+ tenantId: string;
190
+ } | null>;
191
+ }
192
+ interface RouteProtectionErrorHandlerContext<TIdentityContext = DefaultRouteIdentityContext> extends RouteProtectionResolverContext<TIdentityContext> {
193
+ error: unknown;
194
+ }
195
+ /**
196
+ * Route protection configuration
197
+ */
198
+ interface RouteProtectionConfig<TIdentityContext = DefaultRouteIdentityContext> {
199
+ identityChecker?: IdentityContextChecker<TIdentityContext>;
200
+ tenantChecker?: TenantChecker;
201
+ subscriptionChecker?: SubscriptionChecker;
202
+ resolveRoute?: (context: RouteProtectionResolverContext<TIdentityContext>) => Promise<RouteProtectionRedirect | null | void> | RouteProtectionRedirect | null | void;
203
+ handleRouteError?: (context: RouteProtectionErrorHandlerContext<TIdentityContext>) => Promise<RouteProtectionRedirect | null | void> | RouteProtectionRedirect | null | void;
204
+ getLoginReturnUrl?: (context: LoginReturnUrlContext) => string;
205
+ createAutomaticLogoutRequest?: (context: AutomaticLogoutRequestContext) => Promise<Request> | Request;
206
+ }
207
+ /**
208
+ * Configure route protection with identity/tenant/subscription checkers
209
+ */
210
+ declare function configureRouteProtection<TIdentityContext = DefaultRouteIdentityContext>(config: RouteProtectionConfig<TIdentityContext>): void;
211
+ /**
212
+ * Reset route protection to its built-in defaults.
213
+ */
214
+ declare function resetRouteProtectionConfig(): void;
215
+ /**
216
+ * Main route protection function
217
+ */
218
+ declare function protectRoute<T>(request: Request, protection: ProtectionLevel, loaderFn: (user?: UserInfo) => Promise<T> | T): Promise<T>;
219
+ /**
220
+ * Public route (optional auth)
221
+ */
222
+ declare const publicRoute: <T>(request: Request, loaderFn: (user?: UserInfo) => Promise<T> | T) => Promise<T>;
223
+ /**
224
+ * Auth-protected route
225
+ */
226
+ declare const authRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
227
+ /**
228
+ * Onboarding route
229
+ */
230
+ declare const onboardingRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
231
+ /**
232
+ * Subscription route
233
+ */
234
+ declare const subscriptionRoute: <T>(request: Request, loaderFn: (user: UserInfo) => Promise<T> | T) => Promise<T>;
235
+
236
+ //#endregion
237
+ //#region src/auth/token-refresh.server.d.ts
238
+ //# sourceMappingURL=route-protection.server.d.ts.map
239
+ /**
240
+ * Attempt to refresh the access token
241
+ */
242
+ declare function attemptTokenRefresh(request: Request): Promise<TokenRefreshResult>;
243
+ /**
244
+ * Check if a response indicates token expiration
245
+ */
246
+ declare function isTokenExpiredResponse(response: Response): boolean;
247
+ /**
248
+ * Check if token refresh should be attempted
249
+ */
250
+ declare function shouldAttemptTokenRefresh(response: Response, hasAuth: boolean): boolean;
251
+
252
+ //#endregion
253
+ //# sourceMappingURL=token-refresh.server.d.ts.map
254
+
255
+ export { AUTH_ERROR_COOKIE_PREFIX, AutomaticLogoutRequestContext, DefaultRouteIdentityContext, IdentityContextChecker, LoginReturnUrlContext, RouteProtectionConfig, RouteProtectionErrorHandlerContext, RouteProtectionRedirect, RouteProtectionResolverContext, SubscriptionChecker, TenantChecker, attemptTokenRefresh as attemptTokenRefresh$1, authRoute as authRoute$1, cleanupExpiredOAuthStates, clearAuthErrorHeaders, clearAuthServerCache, closeRedisConnection, configureAuthClaimMapping, configureRouteProtection as configureRouteProtection$1, createAuthSession, createOAuthState, deleteOAuthState, destroyAuthSession, extractUserInfo, getAccessToken, getAuthError, getAuthSession, getOAuthState, getUser, handleCallback, hasAuthError, isSessionValid, isTokenExpiredResponse as isTokenExpiredResponse$1, login, logout, onboardingRoute as onboardingRoute$1, protectRoute as protectRoute$1, publicRoute as publicRoute$1, refreshTokens, requireAuth, requireAuthSession, resetAuthClaimMapping, resetRouteProtectionConfig as resetRouteProtectionConfig$1, shouldAttemptTokenRefresh as shouldAttemptTokenRefresh$1, shouldRefreshToken as shouldRefreshToken$1, subscriptionRoute as subscriptionRoute$1, updateAuthSession };
256
+ //# sourceMappingURL=server-CXGaRaiS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-CXGaRaiS.d.ts","names":[],"sources":["../src/auth/redis-session-storage.server.ts","../src/auth/auth.server.ts","../src/auth/route-protection.server.ts","../src/auth/token-refresh.server.ts"],"sourcesContent":null,"mappings":"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"}