@cloudauth/core 0.1.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 (134) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapter.d.ts +20 -0
  3. package/dist/adapter.d.ts.map +1 -0
  4. package/dist/adapter.js +2 -0
  5. package/dist/adapter.js.map +1 -0
  6. package/dist/additional-fields.d.ts +31 -0
  7. package/dist/additional-fields.d.ts.map +1 -0
  8. package/dist/additional-fields.js +2 -0
  9. package/dist/additional-fields.js.map +1 -0
  10. package/dist/auth.d.ts +26 -0
  11. package/dist/auth.d.ts.map +1 -0
  12. package/dist/auth.js +280 -0
  13. package/dist/auth.js.map +1 -0
  14. package/dist/config.d.ts +55 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +2 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/cookies.d.ts +29 -0
  19. package/dist/cookies.d.ts.map +1 -0
  20. package/dist/cookies.js +98 -0
  21. package/dist/cookies.js.map +1 -0
  22. package/dist/crypto.d.ts +23 -0
  23. package/dist/crypto.d.ts.map +1 -0
  24. package/dist/crypto.js +57 -0
  25. package/dist/crypto.js.map +1 -0
  26. package/dist/csrf.d.ts +6 -0
  27. package/dist/csrf.d.ts.map +1 -0
  28. package/dist/csrf.js +24 -0
  29. package/dist/csrf.js.map +1 -0
  30. package/dist/encryption.d.ts +10 -0
  31. package/dist/encryption.d.ts.map +1 -0
  32. package/dist/encryption.js +61 -0
  33. package/dist/encryption.js.map +1 -0
  34. package/dist/errors.d.ts +29 -0
  35. package/dist/errors.d.ts.map +1 -0
  36. package/dist/errors.js +57 -0
  37. package/dist/errors.js.map +1 -0
  38. package/dist/hooks.d.ts +45 -0
  39. package/dist/hooks.d.ts.map +1 -0
  40. package/dist/hooks.js +2 -0
  41. package/dist/hooks.js.map +1 -0
  42. package/dist/http.d.ts +23 -0
  43. package/dist/http.d.ts.map +1 -0
  44. package/dist/http.js +126 -0
  45. package/dist/http.js.map +1 -0
  46. package/dist/index.d.ts +23 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +53 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/provider.d.ts +19 -0
  51. package/dist/provider.d.ts.map +1 -0
  52. package/dist/provider.js +2 -0
  53. package/dist/provider.js.map +1 -0
  54. package/dist/rate-limiter.d.ts +33 -0
  55. package/dist/rate-limiter.d.ts.map +1 -0
  56. package/dist/rate-limiter.js +45 -0
  57. package/dist/rate-limiter.js.map +1 -0
  58. package/dist/test/adapter-conformance.d.ts +13 -0
  59. package/dist/test/adapter-conformance.d.ts.map +1 -0
  60. package/dist/test/adapter-conformance.js +212 -0
  61. package/dist/test/adapter-conformance.js.map +1 -0
  62. package/dist/test/cookies.test.d.ts +2 -0
  63. package/dist/test/cookies.test.d.ts.map +1 -0
  64. package/dist/test/cookies.test.js +83 -0
  65. package/dist/test/cookies.test.js.map +1 -0
  66. package/dist/test/crypto.test.d.ts +2 -0
  67. package/dist/test/crypto.test.d.ts.map +1 -0
  68. package/dist/test/crypto.test.js +84 -0
  69. package/dist/test/crypto.test.js.map +1 -0
  70. package/dist/test/encryption.test.d.ts +2 -0
  71. package/dist/test/encryption.test.d.ts.map +1 -0
  72. package/dist/test/encryption.test.js +34 -0
  73. package/dist/test/encryption.test.js.map +1 -0
  74. package/dist/test/factories.d.ts +11 -0
  75. package/dist/test/factories.d.ts.map +1 -0
  76. package/dist/test/factories.js +110 -0
  77. package/dist/test/factories.js.map +1 -0
  78. package/dist/test/index.d.ts +6 -0
  79. package/dist/test/index.d.ts.map +1 -0
  80. package/dist/test/index.js +4 -0
  81. package/dist/test/index.js.map +1 -0
  82. package/dist/test/mock-provider.d.ts +34 -0
  83. package/dist/test/mock-provider.d.ts.map +1 -0
  84. package/dist/test/mock-provider.js +99 -0
  85. package/dist/test/mock-provider.js.map +1 -0
  86. package/dist/test/rate-limiter.test.d.ts +2 -0
  87. package/dist/test/rate-limiter.test.d.ts.map +1 -0
  88. package/dist/test/rate-limiter.test.js +38 -0
  89. package/dist/test/rate-limiter.test.js.map +1 -0
  90. package/dist/test/url.test.d 2.ts +2 -0
  91. package/dist/test/url.test.d.ts +2 -0
  92. package/dist/test/url.test.d.ts 2.map +1 -0
  93. package/dist/test/url.test.d.ts.map +1 -0
  94. package/dist/test/url.test.js +40 -0
  95. package/dist/test/url.test.js 2.map +1 -0
  96. package/dist/test/url.test.js.map +1 -0
  97. package/dist/types.d.ts +109 -0
  98. package/dist/types.d.ts.map +1 -0
  99. package/dist/types.js +2 -0
  100. package/dist/types.js.map +1 -0
  101. package/dist/url.d.ts +11 -0
  102. package/dist/url.d.ts.map +1 -0
  103. package/dist/url.js +35 -0
  104. package/dist/url.js.map +1 -0
  105. package/package.json +27 -0
  106. package/src/adapter.ts +39 -0
  107. package/src/additional-fields.ts +53 -0
  108. package/src/auth.ts +355 -0
  109. package/src/config.ts +62 -0
  110. package/src/cookies.ts +123 -0
  111. package/src/crypto.ts +62 -0
  112. package/src/csrf.ts +27 -0
  113. package/src/encryption.ts +88 -0
  114. package/src/errors.ts +65 -0
  115. package/src/hooks.ts +54 -0
  116. package/src/http.ts +192 -0
  117. package/src/index.ts +161 -0
  118. package/src/provider.ts +21 -0
  119. package/src/rate-limiter.ts +64 -0
  120. package/src/test/adapter-conformance.ts +267 -0
  121. package/src/test/cookies.test.ts +99 -0
  122. package/src/test/crypto.test.ts +103 -0
  123. package/src/test/encryption.test.ts +40 -0
  124. package/src/test/factories.ts +139 -0
  125. package/src/test/index.ts +17 -0
  126. package/src/test/mock-provider.ts +130 -0
  127. package/src/test/rate-limiter.test.ts +49 -0
  128. package/src/test/url.test.ts +48 -0
  129. package/src/types.ts +122 -0
  130. package/src/url.ts +35 -0
  131. package/tsconfig 2.tsbuildinfo +1 -0
  132. package/tsconfig.json +11 -0
  133. package/tsconfig.tsbuildinfo +1 -0
  134. package/vitest.config.ts +14 -0
@@ -0,0 +1,110 @@
1
+ let nextId = 1;
2
+ let idCounter = 1;
3
+ function nextStr(prefix) {
4
+ const n = idCounter++;
5
+ return `${prefix}_${String(n)}`;
6
+ }
7
+ export function resetIds() {
8
+ nextId = 1;
9
+ idCounter = 1;
10
+ }
11
+ export function createUser(overrides) {
12
+ return {
13
+ email: `user_${String(nextId)}@example.com`,
14
+ emailVerified: true,
15
+ name: `Test User ${String(nextId)}`,
16
+ image: null,
17
+ ...overrides,
18
+ };
19
+ }
20
+ export function createAccount(userId, overrides) {
21
+ return {
22
+ userId,
23
+ provider: 'google',
24
+ providerAccountId: `google_${String(nextId)}`,
25
+ accessToken: null,
26
+ refreshToken: null,
27
+ idToken: null,
28
+ scope: null,
29
+ tokenType: null,
30
+ expiresAt: null,
31
+ ...overrides,
32
+ };
33
+ }
34
+ export function createSession(userId, tokenHash, overrides) {
35
+ return {
36
+ userId,
37
+ tokenHash,
38
+ expiresAt: new Date(Date.now() + 86_400_000),
39
+ ipAddress: null,
40
+ userAgent: null,
41
+ ...overrides,
42
+ };
43
+ }
44
+ export function createOAuthState(overrides) {
45
+ return {
46
+ stateHash: nextStr('state_hash'),
47
+ codeVerifier: nextStr('code_verifier'),
48
+ provider: 'google',
49
+ callbackUrl: null,
50
+ errorUrl: null,
51
+ expiresAt: new Date(Date.now() + 600_000),
52
+ ...overrides,
53
+ };
54
+ }
55
+ export function buildUser(overrides) {
56
+ return {
57
+ id: nextStr('user'),
58
+ email: nextStr('email') + '@example.com',
59
+ emailVerified: true,
60
+ name: nextStr('Test User'),
61
+ image: null,
62
+ createdAt: new Date(),
63
+ updatedAt: new Date(),
64
+ ...overrides,
65
+ };
66
+ }
67
+ export function buildAccount(userId, overrides) {
68
+ return {
69
+ id: nextStr('account'),
70
+ userId,
71
+ provider: 'google',
72
+ providerAccountId: nextStr('google'),
73
+ accessToken: null,
74
+ refreshToken: null,
75
+ idToken: null,
76
+ scope: null,
77
+ tokenType: null,
78
+ expiresAt: null,
79
+ createdAt: new Date(),
80
+ updatedAt: new Date(),
81
+ ...overrides,
82
+ };
83
+ }
84
+ export function buildSession(userId, overrides) {
85
+ return {
86
+ id: nextStr('session'),
87
+ userId,
88
+ tokenHash: nextStr('token_hash'),
89
+ expiresAt: new Date(Date.now() + 86_400_000),
90
+ ipAddress: null,
91
+ userAgent: null,
92
+ createdAt: new Date(),
93
+ updatedAt: new Date(),
94
+ ...overrides,
95
+ };
96
+ }
97
+ export function buildOAuthState(overrides) {
98
+ return {
99
+ id: nextStr('state'),
100
+ stateHash: nextStr('state_hash'),
101
+ codeVerifier: nextStr('code_verifier'),
102
+ provider: 'google',
103
+ callbackUrl: null,
104
+ errorUrl: null,
105
+ expiresAt: new Date(Date.now() + 600_000),
106
+ createdAt: new Date(),
107
+ ...overrides,
108
+ };
109
+ }
110
+ //# sourceMappingURL=factories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factories.js","sourceRoot":"","sources":["../../src/test/factories.ts"],"names":[],"mappings":"AAWA,IAAI,MAAM,GAAG,CAAC,CAAA;AACd,IAAI,SAAS,GAAG,CAAC,CAAA;AAEjB,SAAS,OAAO,CAAC,MAAc;IAC7B,MAAM,CAAC,GAAG,SAAS,EAAE,CAAA;IACrB,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;AACjC,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,MAAM,GAAG,CAAC,CAAA;IACV,SAAS,GAAG,CAAC,CAAA;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAoC;IAC7D,OAAO;QACL,KAAK,EAAE,QAAQ,MAAM,CAAC,MAAM,CAAC,cAAc;QAC3C,aAAa,EAAE,IAAI;QACnB,IAAI,EAAE,aAAa,MAAM,CAAC,MAAM,CAAC,EAAE;QACnC,KAAK,EAAE,IAAI;QACX,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,SAAuC;IAEvC,OAAO;QACL,MAAM;QACN,QAAQ,EAAE,QAAQ;QAClB,iBAAiB,EAAE,UAAU,MAAM,CAAC,MAAM,CAAC,EAAE;QAC7C,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,SAAiB,EACjB,SAAuC;IAEvC,OAAO;QACL,MAAM;QACN,SAAS;QACT,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;QAC5C,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,SAA0C;IAE1C,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC;QAChC,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC;QACtC,QAAQ,EAAE,QAAQ;QAClB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;QACzC,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,SAAyB;IACjD,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,cAAc;QACxC,aAAa,EAAE,IAAI;QACnB,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC;QAC1B,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,SAA4B;IACvE,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC;QACtB,MAAM;QACN,QAAQ,EAAE,QAAQ;QAClB,iBAAiB,EAAE,OAAO,CAAC,QAAQ,CAAC;QACpC,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,SAA4B;IACvE,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC;QACtB,MAAM;QACN,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC;QAChC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;QAC5C,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAA+B;IAC7D,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC;QAChC,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC;QACtC,QAAQ,EAAE,QAAQ;QAClB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;QACzC,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,GAAG,SAAS;KACb,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { createUser, createAccount, createSession, createOAuthState, buildUser, buildAccount, buildSession, buildOAuthState, resetIds, } from './factories.js';
2
+ export type { MockProviderConfig } from './mock-provider.js';
3
+ export { createMockProvider, createMockTokenSet } from './mock-provider.js';
4
+ export type { AdapterConformanceOptions } from './adapter-conformance.js';
5
+ export { runAdapterConformanceTests } from './adapter-conformance.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,GACT,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE3E,YAAY,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,4 @@
1
+ export { createUser, createAccount, createSession, createOAuthState, buildUser, buildAccount, buildSession, buildOAuthState, resetIds, } from './factories.js';
2
+ export { createMockProvider, createMockTokenSet } from './mock-provider.js';
3
+ export { runAdapterConformanceTests } from './adapter-conformance.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,GACT,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAG3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,34 @@
1
+ import type { TokenSet } from '../types.js';
2
+ export interface MockProviderConfig {
3
+ tokenEndpoint: string;
4
+ userinfoEndpoint: string;
5
+ defaultProfile?: Record<string, unknown>;
6
+ tokenResponse?: Record<string, unknown>;
7
+ tokenError?: {
8
+ status: number;
9
+ body: string;
10
+ };
11
+ userinfoError?: {
12
+ status: number;
13
+ body: string;
14
+ };
15
+ tokenDelay?: number;
16
+ userinfoDelay?: number;
17
+ tokenNetworkError?: boolean;
18
+ userinfoNetworkError?: boolean;
19
+ }
20
+ /**
21
+ * Creates a mock OAuth provider server for testing.
22
+ * Intercepts fetch calls to simulate provider HTTP endpoints.
23
+ */
24
+ export declare function createMockProvider(config: MockProviderConfig): {
25
+ intercept: () => void;
26
+ restore: () => void;
27
+ getRequests: () => {
28
+ url: string;
29
+ method: string;
30
+ body?: string;
31
+ }[];
32
+ };
33
+ export declare function createMockTokenSet(overrides?: Partial<TokenSet>): TokenSet;
34
+ //# sourceMappingURL=mock-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-provider.d.ts","sourceRoot":"","sources":["../../src/test/mock-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,aAAa,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG;IAC9D,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,WAAW,EAAE,MAAM;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CACpE,CA0FA;AAED,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAU1E"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Creates a mock OAuth provider server for testing.
3
+ * Intercepts fetch calls to simulate provider HTTP endpoints.
4
+ */
5
+ export function createMockProvider(config) {
6
+ const requests = [];
7
+ const originalFetch = globalThis.fetch;
8
+ const mockFetch = async (input, init) => {
9
+ const url = typeof input === 'string'
10
+ ? input
11
+ : input instanceof URL
12
+ ? input.href
13
+ : 'url' in input
14
+ ? input.url
15
+ : String(input);
16
+ const method = init?.method ?? 'GET';
17
+ requests.push({ url, method, body: init?.body });
18
+ // Handle token endpoint requests
19
+ if (url === config.tokenEndpoint) {
20
+ if (config.tokenNetworkError) {
21
+ throw new TypeError('Network error simulating token endpoint failure');
22
+ }
23
+ if (config.tokenError) {
24
+ await delay(config.tokenDelay ?? 0);
25
+ return new Response(config.tokenError.body, {
26
+ status: config.tokenError.status,
27
+ headers: { 'Content-Type': 'application/json' },
28
+ });
29
+ }
30
+ await delay(config.tokenDelay ?? 0);
31
+ const tokenData = config.tokenResponse ?? {
32
+ access_token: 'mock_access_token',
33
+ refresh_token: 'mock_refresh_token',
34
+ id_token: 'mock_id_token',
35
+ token_type: 'Bearer',
36
+ expires_in: 3600,
37
+ scope: 'openid email profile',
38
+ };
39
+ return new Response(JSON.stringify(tokenData), {
40
+ status: 200,
41
+ headers: { 'Content-Type': 'application/json' },
42
+ });
43
+ }
44
+ // Handle userinfo endpoint requests
45
+ if (url === config.userinfoEndpoint) {
46
+ if (config.userinfoNetworkError) {
47
+ throw new TypeError('Network error simulating userinfo endpoint failure');
48
+ }
49
+ if (config.userinfoError) {
50
+ await delay(config.userinfoDelay ?? 0);
51
+ return new Response(config.userinfoError.body, {
52
+ status: config.userinfoError.status,
53
+ headers: { 'Content-Type': 'application/json' },
54
+ });
55
+ }
56
+ await delay(config.userinfoDelay ?? 0);
57
+ const profileData = config.defaultProfile ?? {
58
+ sub: 'mock_provider_account_id',
59
+ email: 'mock@example.com',
60
+ email_verified: true,
61
+ name: 'Mock User',
62
+ picture: 'https://example.com/avatar.png',
63
+ provider: 'mock',
64
+ };
65
+ return new Response(JSON.stringify(profileData), {
66
+ status: 200,
67
+ headers: { 'Content-Type': 'application/json' },
68
+ });
69
+ }
70
+ // Pass through for other requests
71
+ return originalFetch(input, init);
72
+ };
73
+ return {
74
+ intercept() {
75
+ globalThis.fetch = mockFetch;
76
+ },
77
+ restore() {
78
+ globalThis.fetch = originalFetch;
79
+ },
80
+ getRequests() {
81
+ return [...requests];
82
+ },
83
+ };
84
+ }
85
+ export function createMockTokenSet(overrides) {
86
+ return {
87
+ accessToken: 'mock_access_token',
88
+ refreshToken: 'mock_refresh_token',
89
+ idToken: 'mock_id_token',
90
+ scope: 'openid email profile',
91
+ tokenType: 'Bearer',
92
+ expiresAt: 3600,
93
+ ...overrides,
94
+ };
95
+ }
96
+ function delay(ms) {
97
+ return new Promise((resolve) => setTimeout(resolve, ms));
98
+ }
99
+ //# sourceMappingURL=mock-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-provider.js","sourceRoot":"","sources":["../../src/test/mock-provider.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAK3D,MAAM,QAAQ,GAAqD,EAAE,CAAA;IACrE,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAA;IAEtC,MAAM,SAAS,GAAG,KAAK,EAAE,KAAwB,EAAE,IAAkB,EAAqB,EAAE;QAC1F,MAAM,GAAG,GACP,OAAO,KAAK,KAAK,QAAQ;YACvB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,KAAK,YAAY,GAAG;gBACpB,CAAC,CAAC,KAAK,CAAC,IAAI;gBACZ,CAAC,CAAC,KAAK,IAAI,KAAK;oBACd,CAAC,CAAC,KAAK,CAAC,GAAG;oBACX,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACvB,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,KAAK,CAAA;QAEpC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAA0B,EAAE,CAAC,CAAA;QAEtE,iCAAiC;QACjC,IAAI,GAAG,KAAK,MAAM,CAAC,aAAa,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAC7B,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAA;YACxE,CAAC;YAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACtB,MAAM,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,CAAA;gBACnC,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE;oBAC1C,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM;oBAChC,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;iBAChD,CAAC,CAAA;YACJ,CAAC;YAED,MAAM,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,CAAA;YACnC,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,IAAI;gBACxC,YAAY,EAAE,mBAAmB;gBACjC,aAAa,EAAE,oBAAoB;gBACnC,QAAQ,EAAE,eAAe;gBACzB,UAAU,EAAE,QAAQ;gBACpB,UAAU,EAAE,IAAI;gBAChB,KAAK,EAAE,sBAAsB;aAC9B,CAAA;YACD,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE;gBAC7C,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aAChD,CAAC,CAAA;QACJ,CAAC;QAED,oCAAoC;QACpC,IAAI,GAAG,KAAK,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;gBAChC,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAA;YAC3E,CAAC;YAED,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBACzB,MAAM,KAAK,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC,CAAA;gBACtC,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE;oBAC7C,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,MAAM;oBACnC,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;iBAChD,CAAC,CAAA;YACJ,CAAC;YAED,MAAM,KAAK,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC,CAAA;YACtC,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,IAAI;gBAC3C,GAAG,EAAE,0BAA0B;gBAC/B,KAAK,EAAE,kBAAkB;gBACzB,cAAc,EAAE,IAAI;gBACpB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,gCAAgC;gBACzC,QAAQ,EAAE,MAAM;aACjB,CAAA;YACD,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;gBAC/C,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aAChD,CAAC,CAAA;QACJ,CAAC;QAED,kCAAkC;QAClC,OAAO,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACnC,CAAC,CAAA;IAED,OAAO;QACL,SAAS;YACP,UAAU,CAAC,KAAK,GAAG,SAAS,CAAA;QAC9B,CAAC;QACD,OAAO;YACL,UAAU,CAAC,KAAK,GAAG,aAAa,CAAA;QAClC,CAAC;QACD,WAAW;YACT,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAA;QACtB,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAA6B;IAC9D,OAAO;QACL,WAAW,EAAE,mBAAmB;QAChC,YAAY,EAAE,oBAAoB;QAClC,OAAO,EAAE,eAAe;QACxB,KAAK,EAAE,sBAAsB;QAC7B,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,IAAI;QACf,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC1D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rate-limiter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.test.d.ts","sourceRoot":"","sources":["../../src/test/rate-limiter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { inMemoryRateLimiter } from '../rate-limiter.js';
3
+ describe('inMemoryRateLimiter', () => {
4
+ it('should allow requests within the limit', async () => {
5
+ const limiter = inMemoryRateLimiter();
6
+ const result = await limiter.check('test-key', 5, 60_000);
7
+ expect(result.allowed).toBe(true);
8
+ expect(result.remaining).toBe(4);
9
+ });
10
+ it('should block requests exceeding the limit', async () => {
11
+ const limiter = inMemoryRateLimiter();
12
+ for (let i = 0; i < 3; i++) {
13
+ await limiter.check('block-key', 3, 60_000);
14
+ }
15
+ const result = await limiter.check('block-key', 3, 60_000);
16
+ expect(result.allowed).toBe(false);
17
+ expect(result.remaining).toBe(0);
18
+ });
19
+ it('should track different keys independently', async () => {
20
+ const limiter = inMemoryRateLimiter();
21
+ await limiter.check('key-a', 1, 60_000);
22
+ const a2 = await limiter.check('key-a', 1, 60_000);
23
+ expect(a2.allowed).toBe(false);
24
+ const b1 = await limiter.check('key-b', 1, 60_000);
25
+ expect(b1.allowed).toBe(true);
26
+ });
27
+ it('should reset after the window expires', async () => {
28
+ const limiter = inMemoryRateLimiter();
29
+ await limiter.check('window-key', 1, 50);
30
+ const result = await limiter.check('window-key', 1, 50);
31
+ expect(result.allowed).toBe(false);
32
+ // Wait for window to expire
33
+ await new Promise((resolve) => setTimeout(resolve, 60));
34
+ const after = await limiter.check('window-key', 1, 50);
35
+ expect(after.allowed).toBe(true);
36
+ }, 10_000);
37
+ });
38
+ //# sourceMappingURL=rate-limiter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.test.js","sourceRoot":"","sources":["../../src/test/rate-limiter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAExD,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAA;QACrC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;QACzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAA;QAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;QAC7C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;QAC1D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAClC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAA;QAErC,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;QACvC,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;QAClD,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAE9B,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;QAClD,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAA;QAErC,MAAM,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;QAExC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;QACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAElC,4BAA4B;QAC5B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;QAEvD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;QACtD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClC,CAAC,EAAE,MAAM,CAAC,CAAA;AACZ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=url.test.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=url.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.test.d.ts","sourceRoot":"","sources":["../../src/test/url.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.test.d.ts","sourceRoot":"","sources":["../../src/test/url.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { isTrustedOrigin, buildCallbackURL } from '../url.js';
3
+ describe('isTrustedOrigin', () => {
4
+ const trustedOrigins = ['https://app.example.com', 'https://admin.example.com'];
5
+ it('should accept URLs matching trusted origins', () => {
6
+ expect(isTrustedOrigin('https://app.example.com/dashboard', trustedOrigins)).toBe(true);
7
+ expect(isTrustedOrigin('https://app.example.com/auth/callback', trustedOrigins)).toBe(true);
8
+ expect(isTrustedOrigin('https://admin.example.com/users', trustedOrigins)).toBe(true);
9
+ });
10
+ it('should reject URLs from untrusted origins', () => {
11
+ expect(isTrustedOrigin('https://evil.com/steal', trustedOrigins)).toBe(false);
12
+ expect(isTrustedOrigin('http://app.example.com', trustedOrigins)).toBe(false);
13
+ });
14
+ it('should reject malformed URLs', () => {
15
+ expect(isTrustedOrigin('not-a-url', trustedOrigins)).toBe(false);
16
+ expect(isTrustedOrigin('', trustedOrigins)).toBe(false);
17
+ });
18
+ it('should return false for empty trusted origins', () => {
19
+ expect(isTrustedOrigin('https://app.example.com', [])).toBe(false);
20
+ });
21
+ });
22
+ describe('buildCallbackURL', () => {
23
+ it('should build a simple callback URL', () => {
24
+ const result = buildCallbackURL('https://app.example.com', '/auth/callback');
25
+ expect(result).toBe('https://app.example.com/auth/callback');
26
+ });
27
+ it('should handle base URL with trailing slash', () => {
28
+ const result = buildCallbackURL('https://app.example.com/', '/auth/callback');
29
+ expect(result).toBe('https://app.example.com/auth/callback');
30
+ });
31
+ it('should handle path without leading slash', () => {
32
+ const result = buildCallbackURL('https://app.example.com', 'auth/callback');
33
+ expect(result).toBe('https://app.example.com/auth/callback');
34
+ });
35
+ it('should preserve query parameters', () => {
36
+ const result = buildCallbackURL('https://app.example.com', '/callback?provider=google');
37
+ expect(result).toBe('https://app.example.com/callback?provider=google');
38
+ });
39
+ });
40
+ //# sourceMappingURL=url.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.test.js","sourceRoot":"","sources":["../../src/test/url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE7D,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,MAAM,cAAc,GAAG,CAAC,yBAAyB,EAAE,2BAA2B,CAAC,CAAA;IAE/E,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,eAAe,CAAC,mCAAmC,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACvF,MAAM,CAAC,eAAe,CAAC,uCAAuC,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3F,MAAM,CAAC,eAAe,CAAC,iCAAiC,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,eAAe,CAAC,wBAAwB,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7E,MAAM,CAAC,eAAe,CAAC,wBAAwB,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChE,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,eAAe,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,gBAAgB,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAAA;QAC5E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,gBAAgB,CAAC,0BAA0B,EAAE,gBAAgB,CAAC,CAAA;QAC7E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,gBAAgB,CAAC,yBAAyB,EAAE,eAAe,CAAC,CAAA;QAC3E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,MAAM,GAAG,gBAAgB,CAAC,yBAAyB,EAAE,2BAA2B,CAAC,CAAA;QACvF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.test.js","sourceRoot":"","sources":["../../src/test/url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE7D,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,MAAM,cAAc,GAAG,CAAC,yBAAyB,EAAE,2BAA2B,CAAC,CAAA;IAE/E,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,eAAe,CAAC,mCAAmC,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACvF,MAAM,CAAC,eAAe,CAAC,uCAAuC,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3F,MAAM,CAAC,eAAe,CAAC,iCAAiC,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,eAAe,CAAC,wBAAwB,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7E,MAAM,CAAC,eAAe,CAAC,wBAAwB,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChE,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,eAAe,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,gBAAgB,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAAA;QAC5E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,gBAAgB,CAAC,0BAA0B,EAAE,gBAAgB,CAAC,CAAA;QAC7E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,gBAAgB,CAAC,yBAAyB,EAAE,eAAe,CAAC,CAAA;QAC3E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,MAAM,GAAG,gBAAgB,CAAC,yBAAyB,EAAE,2BAA2B,CAAC,CAAA;QACvF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,109 @@
1
+ export interface User {
2
+ id: string;
3
+ email: string | null;
4
+ emailVerified: boolean;
5
+ name: string | null;
6
+ image: string | null;
7
+ createdAt: Date;
8
+ updatedAt: Date;
9
+ }
10
+ export interface Account {
11
+ id: string;
12
+ userId: string;
13
+ provider: string;
14
+ providerAccountId: string;
15
+ accessToken: string | null;
16
+ refreshToken: string | null;
17
+ idToken: string | null;
18
+ scope: string | null;
19
+ tokenType: string | null;
20
+ expiresAt: Date | null;
21
+ createdAt: Date;
22
+ updatedAt: Date;
23
+ }
24
+ export interface Session {
25
+ id: string;
26
+ userId: string;
27
+ tokenHash: string;
28
+ expiresAt: Date;
29
+ ipAddress: string | null;
30
+ userAgent: string | null;
31
+ createdAt: Date;
32
+ updatedAt: Date;
33
+ }
34
+ export interface SessionWithUser {
35
+ session: Session;
36
+ user: User;
37
+ }
38
+ export interface OAuthState {
39
+ id: string;
40
+ stateHash: string;
41
+ codeVerifier: string;
42
+ provider: string;
43
+ callbackUrl: string | null;
44
+ errorUrl: string | null;
45
+ expiresAt: Date;
46
+ createdAt: Date;
47
+ }
48
+ export interface ProviderProfile {
49
+ provider: string;
50
+ providerAccountId: string;
51
+ email?: string;
52
+ emailVerified?: boolean;
53
+ name?: string;
54
+ image?: string;
55
+ raw?: unknown;
56
+ }
57
+ export interface TokenSet {
58
+ accessToken: string;
59
+ refreshToken?: string;
60
+ idToken?: string;
61
+ scope?: string;
62
+ tokenType?: string;
63
+ expiresAt?: number;
64
+ }
65
+ export interface CreateUserInput {
66
+ email: string | null;
67
+ emailVerified: boolean;
68
+ name: string | null;
69
+ image: string | null;
70
+ }
71
+ export interface UpdateUserInput {
72
+ email?: string | null;
73
+ emailVerified?: boolean;
74
+ name?: string | null;
75
+ image?: string | null;
76
+ }
77
+ export interface CreateAccountInput {
78
+ userId: string;
79
+ provider: string;
80
+ providerAccountId: string;
81
+ accessToken?: string | null;
82
+ refreshToken?: string | null;
83
+ idToken?: string | null;
84
+ scope?: string | null;
85
+ tokenType?: string | null;
86
+ expiresAt?: Date | null;
87
+ }
88
+ export interface CreateSessionInput {
89
+ userId: string;
90
+ tokenHash: string;
91
+ expiresAt: Date;
92
+ ipAddress?: string | null;
93
+ userAgent?: string | null;
94
+ }
95
+ export interface UpdateSessionInput {
96
+ tokenHash?: string;
97
+ expiresAt?: Date;
98
+ ipAddress?: string | null;
99
+ userAgent?: string | null;
100
+ }
101
+ export interface CreateOAuthStateInput {
102
+ stateHash: string;
103
+ codeVerifier: string;
104
+ provider: string;
105
+ callbackUrl?: string | null;
106
+ errorUrl?: string | null;
107
+ expiresAt: Date;
108
+ }
109
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/url.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Check if a URL's origin is in the list of trusted origins.
3
+ * Returns false if the URL is malformed or trustedOrigins is empty.
4
+ */
5
+ export declare function isTrustedOrigin(url: string, trustedOrigins: string[]): boolean;
6
+ /**
7
+ * Build a callback URL from a base URL and path.
8
+ * Ensures no double slashes and trailing slashes are cleaned.
9
+ */
10
+ export declare function buildCallbackURL(baseURL: string, path: string): string;
11
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAoB9E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAItE"}
package/dist/url.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Check if a URL's origin is in the list of trusted origins.
3
+ * Returns false if the URL is malformed or trustedOrigins is empty.
4
+ */
5
+ export function isTrustedOrigin(url, trustedOrigins) {
6
+ let parsed;
7
+ try {
8
+ parsed = new URL(url);
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ if (trustedOrigins.length === 0) {
14
+ return false;
15
+ }
16
+ return trustedOrigins.some((origin) => {
17
+ try {
18
+ const trusted = new URL(origin);
19
+ return parsed.origin === trusted.origin;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ });
25
+ }
26
+ /**
27
+ * Build a callback URL from a base URL and path.
28
+ * Ensures no double slashes and trailing slashes are cleaned.
29
+ */
30
+ export function buildCallbackURL(baseURL, path) {
31
+ const base = baseURL.replace(/\/+$/, '');
32
+ const cleanPath = path.startsWith('/') ? path : `/${path}`;
33
+ return `${base}${cleanPath}`;
34
+ }
35
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,cAAwB;IACnE,IAAI,MAAW,CAAA;IACf,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QACpC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAA;YAC/B,OAAO,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAA;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,IAAY;IAC5D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAA;IAC1D,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,CAAA;AAC9B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@cloudauth/core",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./test": {
15
+ "types": "./dist/test/index.d.ts",
16
+ "import": "./dist/test/index.js",
17
+ "default": "./dist/test/index.js"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "typecheck": "tsc --noEmit",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
25
+ "test:coverage": "vitest run --coverage"
26
+ }
27
+ }