@gatwech/core 0.0.11 → 1.0.0-beta.19

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/dist/api/index.d.mts +2 -2
  2. package/dist/context/index.d.mts +2 -2
  3. package/dist/db/adapter/index.d.mts +2 -2
  4. package/dist/db/index.d.mts +2 -2
  5. package/dist/env/index.d.mts +1 -1
  6. package/dist/env/index.mjs +1 -1
  7. package/dist/{env-JMSMESs1.mjs → env-ubiqEEZm.mjs} +10 -9
  8. package/dist/error/index.mjs +2 -2
  9. package/dist/{error-41YsFQ8b.mjs → error-DKIIiFmH.mjs} +1 -1
  10. package/dist/{index-DLP-K0uY.d.mts → index-CNtOUpmF.d.mts} +4 -3
  11. package/dist/index-Df0KhQRf.d.mts +3002 -0
  12. package/dist/index.d.mts +3 -3
  13. package/dist/oauth2/index.d.mts +2 -2
  14. package/dist/social-providers/index.d.mts +3 -3
  15. package/dist/social-providers/index.mjs +73 -2414
  16. package/dist/src/api/index.d.ts +119 -0
  17. package/dist/src/async_hooks/index.d.ts +6 -0
  18. package/dist/src/context/endpoint-context.d.ts +14 -0
  19. package/dist/src/context/index.d.ts +3 -0
  20. package/dist/src/context/request-state.d.ts +13 -0
  21. package/dist/src/context/transaction.d.ts +11 -0
  22. package/dist/src/db/adapter/index.d.ts +401 -0
  23. package/{src/db/index.ts → dist/src/db/index.d.ts} +2 -18
  24. package/dist/src/db/plugin.d.ts +10 -0
  25. package/dist/src/db/schema/account.d.ts +22 -0
  26. package/dist/src/db/schema/rate-limit.d.ts +10 -0
  27. package/dist/src/db/schema/session.d.ts +17 -0
  28. package/dist/src/db/schema/shared.d.ts +6 -0
  29. package/dist/src/db/schema/user.d.ts +16 -0
  30. package/{src/db/schema/verification.ts → dist/src/db/schema/verification.d.ts} +8 -8
  31. package/dist/src/db/type.d.ts +159 -0
  32. package/dist/src/env/color-depth.d.ts +1 -0
  33. package/dist/src/env/env-impl.d.ts +29 -0
  34. package/dist/src/env/index.d.ts +3 -0
  35. package/dist/src/env/logger.d.ts +52 -0
  36. package/dist/src/error/codes.d.ts +27 -0
  37. package/dist/src/error/index.d.ts +4 -0
  38. package/dist/src/oauth2/client-credentials-token.d.ts +21 -0
  39. package/dist/src/oauth2/create-authorization-url.d.ts +21 -0
  40. package/dist/src/oauth2/index.d.ts +6 -0
  41. package/dist/src/oauth2/oauth-provider.d.ts +178 -0
  42. package/dist/src/oauth2/refresh-access-token.d.ts +20 -0
  43. package/dist/src/oauth2/utils.d.ts +3 -0
  44. package/dist/src/oauth2/validate-authorization-code.d.ts +28 -0
  45. package/dist/src/social-providers/github.d.ts +89 -0
  46. package/dist/src/social-providers/google.d.ts +82 -0
  47. package/dist/src/social-providers/index.d.ts +93 -0
  48. package/dist/src/types/context.d.ts +177 -0
  49. package/dist/src/types/cookie.d.ts +15 -0
  50. package/dist/src/types/helper.d.ts +9 -0
  51. package/dist/src/types/index.d.ts +7 -0
  52. package/dist/src/types/init-options.d.ts +1140 -0
  53. package/dist/src/types/plugin-client.d.ts +88 -0
  54. package/dist/src/types/plugin.d.ts +120 -0
  55. package/dist/src/utils/error-codes.d.ts +9 -0
  56. package/dist/utils/index.mjs +1 -1
  57. package/package.json +11 -5
  58. package/.turbo/turbo-build.log +0 -42
  59. package/dist/index-DjrJweYn.d.mts +0 -7312
  60. package/src/api/index.ts +0 -57
  61. package/src/async_hooks/index.ts +0 -35
  62. package/src/context/endpoint-context.ts +0 -48
  63. package/src/context/index.ts +0 -21
  64. package/src/context/request-state.test.ts +0 -346
  65. package/src/context/request-state.ts +0 -75
  66. package/src/context/transaction.ts +0 -72
  67. package/src/db/adapter/index.ts +0 -466
  68. package/src/db/plugin.ts +0 -11
  69. package/src/db/schema/account.ts +0 -34
  70. package/src/db/schema/rate-limit.ts +0 -21
  71. package/src/db/schema/session.ts +0 -17
  72. package/src/db/schema/shared.ts +0 -7
  73. package/src/db/schema/user.ts +0 -16
  74. package/src/db/type.ts +0 -180
  75. package/src/env/color-depth.ts +0 -172
  76. package/src/env/env-impl.ts +0 -124
  77. package/src/env/index.ts +0 -23
  78. package/src/env/logger.test.ts +0 -33
  79. package/src/env/logger.ts +0 -145
  80. package/src/error/codes.ts +0 -31
  81. package/src/error/index.ts +0 -11
  82. package/src/oauth2/client-credentials-token.ts +0 -102
  83. package/src/oauth2/create-authorization-url.ts +0 -85
  84. package/src/oauth2/index.ts +0 -21
  85. package/src/oauth2/oauth-provider.ts +0 -211
  86. package/src/oauth2/refresh-access-token.ts +0 -124
  87. package/src/oauth2/utils.ts +0 -36
  88. package/src/oauth2/validate-authorization-code.ts +0 -154
  89. package/src/social-providers/apple.ts +0 -213
  90. package/src/social-providers/atlassian.ts +0 -132
  91. package/src/social-providers/cognito.ts +0 -269
  92. package/src/social-providers/discord.ts +0 -169
  93. package/src/social-providers/dropbox.ts +0 -112
  94. package/src/social-providers/facebook.ts +0 -204
  95. package/src/social-providers/figma.ts +0 -115
  96. package/src/social-providers/github.ts +0 -154
  97. package/src/social-providers/gitlab.ts +0 -152
  98. package/src/social-providers/google.ts +0 -171
  99. package/src/social-providers/huggingface.ts +0 -118
  100. package/src/social-providers/index.ts +0 -124
  101. package/src/social-providers/kakao.ts +0 -178
  102. package/src/social-providers/kick.ts +0 -92
  103. package/src/social-providers/line.ts +0 -169
  104. package/src/social-providers/linear.ts +0 -120
  105. package/src/social-providers/linkedin.ts +0 -110
  106. package/src/social-providers/microsoft-entra-id.ts +0 -245
  107. package/src/social-providers/naver.ts +0 -112
  108. package/src/social-providers/notion.ts +0 -108
  109. package/src/social-providers/paybin.ts +0 -122
  110. package/src/social-providers/paypal.ts +0 -263
  111. package/src/social-providers/polar.ts +0 -107
  112. package/src/social-providers/reddit.ts +0 -122
  113. package/src/social-providers/roblox.ts +0 -110
  114. package/src/social-providers/salesforce.ts +0 -159
  115. package/src/social-providers/slack.ts +0 -111
  116. package/src/social-providers/spotify.ts +0 -93
  117. package/src/social-providers/tiktok.ts +0 -210
  118. package/src/social-providers/twitch.ts +0 -111
  119. package/src/social-providers/twitter.ts +0 -198
  120. package/src/social-providers/vk.ts +0 -126
  121. package/src/social-providers/zoom.ts +0 -217
  122. package/src/types/context.ts +0 -269
  123. package/src/types/cookie.ts +0 -7
  124. package/src/types/helper.ts +0 -6
  125. package/src/types/index.ts +0 -21
  126. package/src/types/init-options.ts +0 -1346
  127. package/src/types/plugin-client.ts +0 -100
  128. package/src/types/plugin.ts +0 -158
  129. package/src/utils/error-codes.ts +0 -51
  130. package/tsconfig.json +0 -7
  131. package/tsdown.config.ts +0 -20
  132. /package/{src/index.ts → dist/src/index.d.ts} +0 -0
  133. /package/{src/utils/index.ts → dist/src/utils/index.d.ts} +0 -0
  134. /package/dist/{utils-BFQCAfNW.mjs → utils-CTOwq_Nj.mjs} +0 -0
package/src/api/index.ts DELETED
@@ -1,57 +0,0 @@
1
- import {
2
- createEndpoint,
3
- createMiddleware,
4
- type EndpointContext,
5
- type EndpointOptions,
6
- } from "better-call";
7
- import { runWithEndpointContext } from "../context";
8
- import type { AuthContext } from "../types";
9
-
10
- export const optionsMiddleware = createMiddleware(async () => {
11
- /**
12
- * This will be passed on the instance of
13
- * the context. Used to infer the type
14
- * here.
15
- */
16
- return {} as AuthContext;
17
- });
18
-
19
- export const createAuthMiddleware = createMiddleware.create({
20
- use: [
21
- optionsMiddleware,
22
- /**
23
- * Only use for post hooks
24
- */
25
- createMiddleware(async () => {
26
- return {} as {
27
- returned?: unknown | undefined;
28
- responseHeaders?: Headers | undefined;
29
- };
30
- }),
31
- ],
32
- });
33
-
34
- const use = [optionsMiddleware];
35
-
36
- export const createAuthEndpoint = <
37
- Path extends string,
38
- Opts extends EndpointOptions,
39
- R,
40
- >(
41
- path: Path,
42
- options: Opts,
43
- handler: (ctx: EndpointContext<Path, Opts, AuthContext>) => Promise<R>,
44
- ) => {
45
- return createEndpoint(
46
- path,
47
- {
48
- ...options,
49
- use: [...(options?.use || []), ...use],
50
- },
51
- // todo: prettify the code, we want to call `runWithEndpointContext` to top level
52
- async (ctx) => runWithEndpointContext(ctx as any, () => handler(ctx)),
53
- );
54
- };
55
-
56
- export type AuthEndpoint = ReturnType<typeof createAuthEndpoint>;
57
- export type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;
@@ -1,35 +0,0 @@
1
- /**
2
- * AsyncLocalStorage will be import directly in 1.5.x
3
- */
4
- import type { AsyncLocalStorage } from "node:async_hooks";
5
-
6
- // We only export the type here to avoid issues in environments where AsyncLocalStorage is not available.
7
- export type { AsyncLocalStorage };
8
-
9
- const AsyncLocalStoragePromise: Promise<typeof AsyncLocalStorage> = import(
10
- /* @vite-ignore */
11
- /* webpackIgnore: true */
12
- "node:async_hooks"
13
- )
14
- .then((mod) => mod.AsyncLocalStorage)
15
- .catch((err) => {
16
- if ("AsyncLocalStorage" in globalThis) {
17
- return (globalThis as any).AsyncLocalStorage;
18
- }
19
- console.warn(
20
- "[payvo-auth] Warning: AsyncLocalStorage is not available in this environment. Some features may not work as expected."
21
- );
22
- console.warn(
23
- "[payvo-auth] Please read more about this warning at https://payvo-auth.com/docs/installation#mount-handler"
24
- );
25
- console.warn(
26
- "[payvo-auth] If you are using Cloudflare Workers, please see: https://developers.cloudflare.com/workers/configuration/compatibility-flags/#nodejs-compatibility-flag"
27
- );
28
- throw err;
29
- });
30
-
31
- export async function getAsyncLocalStorage(): Promise<
32
- typeof AsyncLocalStorage
33
- > {
34
- return AsyncLocalStoragePromise;
35
- }
@@ -1,48 +0,0 @@
1
- import type { EndpointContext, InputContext } from "better-call";
2
- import { type AsyncLocalStorage, getAsyncLocalStorage } from "../async_hooks";
3
- import type { AuthContext } from "../types";
4
-
5
- export type AuthEndpointContext = Partial<
6
- InputContext<string, any> & EndpointContext<string, any>
7
- > & {
8
- context: AuthContext;
9
- };
10
-
11
- let currentContextAsyncStorage: AsyncLocalStorage<AuthEndpointContext> | null =
12
- null;
13
-
14
- const ensureAsyncStorage = async () => {
15
- if (!currentContextAsyncStorage) {
16
- const AsyncLocalStorage = await getAsyncLocalStorage();
17
- currentContextAsyncStorage = new AsyncLocalStorage();
18
- }
19
- return currentContextAsyncStorage;
20
- };
21
-
22
- /**
23
- * This is for internal use only. Most users should use `getCurrentAuthContext` instead.
24
- *
25
- * It is exposed for advanced use cases where you need direct access to the AsyncLocalStorage instance.
26
- */
27
- export async function getCurrentAuthContextAsyncLocalStorage() {
28
- return ensureAsyncStorage();
29
- }
30
-
31
- export async function getCurrentAuthContext(): Promise<AuthEndpointContext> {
32
- const als = await ensureAsyncStorage();
33
- const context = als.getStore();
34
- if (!context) {
35
- throw new Error(
36
- "No auth context found. Please make sure you are calling this function within a `runWithEndpointContext` callback.",
37
- );
38
- }
39
- return context;
40
- }
41
-
42
- export async function runWithEndpointContext<T>(
43
- context: AuthEndpointContext,
44
- fn: () => T,
45
- ): Promise<T> {
46
- const als = await ensureAsyncStorage();
47
- return als.run(context, fn);
48
- }
@@ -1,21 +0,0 @@
1
- export {
2
- type AuthEndpointContext,
3
- getCurrentAuthContext,
4
- getCurrentAuthContextAsyncLocalStorage,
5
- runWithEndpointContext,
6
- } from "./endpoint-context";
7
- export {
8
- defineRequestState,
9
- getCurrentRequestState,
10
- getRequestStateAsyncLocalStorage,
11
- hasRequestState,
12
- type RequestState,
13
- type RequestStateWeakMap,
14
- runWithRequestState,
15
- } from "./request-state";
16
- export {
17
- getCurrentAdapter,
18
- getCurrentDBAdapterAsyncLocalStorage,
19
- runWithAdapter,
20
- runWithTransaction,
21
- } from "./transaction";
@@ -1,346 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import z from "zod";
3
- import {
4
- defineRequestState,
5
- getCurrentRequestState,
6
- hasRequestState,
7
- type RequestStateWeakMap,
8
- runWithRequestState,
9
- } from "./request-state";
10
-
11
- describe("request-state", () => {
12
- describe("runWithRequestState", () => {
13
- it("should execute function within request state context", async () => {
14
- const store: RequestStateWeakMap = new WeakMap();
15
- const result = await runWithRequestState(store, async () => {
16
- const hasStore = await hasRequestState();
17
- expect(hasStore).toBe(true);
18
- return "success";
19
- });
20
- expect(result).toBe("success");
21
- });
22
-
23
- it("should isolate request states between concurrent requests", async () => {
24
- const store1: RequestStateWeakMap = new WeakMap();
25
- const store2: RequestStateWeakMap = new WeakMap();
26
-
27
- const schema = z.object({ id: z.string() });
28
- const { get, set } = defineRequestState(schema);
29
-
30
- const [result1, result2] = await Promise.all([
31
- runWithRequestState(store1, async () => {
32
- await set({ id: "store1" });
33
- // Simulate some async work
34
- await new Promise((resolve) => setTimeout(resolve, 10));
35
- return await get();
36
- }),
37
- runWithRequestState(store2, async () => {
38
- await set({ id: "store2" });
39
- // Simulate some async work
40
- await new Promise((resolve) => setTimeout(resolve, 5));
41
- return await get();
42
- }),
43
- ]);
44
-
45
- expect(result1).toEqual({ id: "store1" });
46
- expect(result2).toEqual({ id: "store2" });
47
- });
48
-
49
- it("should support nested async operations", async () => {
50
- const store: RequestStateWeakMap = new WeakMap();
51
- const schema = z.object({ value: z.number() });
52
- const { get, set } = defineRequestState(schema);
53
-
54
- await runWithRequestState(store, async () => {
55
- await set({ value: 1 });
56
-
57
- const nestedResult = await (async () => {
58
- const current = await get();
59
- await set({ value: (current?.value || 0) + 1 });
60
- return await get();
61
- })();
62
-
63
- expect(nestedResult).toEqual({ value: 2 });
64
- expect(await get()).toEqual({ value: 2 });
65
- });
66
- });
67
- });
68
-
69
- describe("hasRequestState", () => {
70
- it("should return false when not in request state context", async () => {
71
- const hasStore = await hasRequestState();
72
- expect(hasStore).toBe(false);
73
- });
74
-
75
- it("should return true when in request state context", async () => {
76
- const store: RequestStateWeakMap = new WeakMap();
77
- await runWithRequestState(store, async () => {
78
- const hasStore = await hasRequestState();
79
- expect(hasStore).toBe(true);
80
- });
81
- });
82
- });
83
-
84
- describe("getCurrentRequestState", () => {
85
- it("should throw error when not in request state context", async () => {
86
- await expect(getCurrentRequestState()).rejects.toThrow(
87
- "No request state found",
88
- );
89
- });
90
-
91
- it("should return the current store when in context", async () => {
92
- const store: RequestStateWeakMap = new WeakMap();
93
- await runWithRequestState(store, async () => {
94
- const currentStore = await getCurrentRequestState();
95
- expect(currentStore).toBe(store);
96
- });
97
- });
98
- });
99
-
100
- describe("defineRequestState", () => {
101
- it("should create a request state with get and set methods", async () => {
102
- const schema = z.object({ name: z.string() });
103
- const store = defineRequestState(schema);
104
-
105
- expect(store).toHaveProperty("get");
106
- expect(store).toHaveProperty("set");
107
- expect(typeof store.get).toBe("function");
108
- expect(typeof store.set).toBe("function");
109
- });
110
-
111
- it("should store and retrieve values using schema as key", async () => {
112
- const requestState: RequestStateWeakMap = new WeakMap();
113
- const schema = z.object({ name: z.string(), age: z.number() });
114
- const { get, set } = defineRequestState(schema);
115
-
116
- await runWithRequestState(requestState, async () => {
117
- await set({ name: "John", age: 30 });
118
- const value = await get();
119
- expect(value).toEqual({ name: "John", age: 30 });
120
- });
121
- });
122
-
123
- it("should return undefined for unset values", async () => {
124
- const requestState: RequestStateWeakMap = new WeakMap();
125
- const schema = z.object({ value: z.string() });
126
- const { get } = defineRequestState(schema);
127
-
128
- await runWithRequestState(requestState, async () => {
129
- const value = await get();
130
- expect(value).toBeUndefined();
131
- });
132
- });
133
-
134
- it("should handle multiple stores with different schemas independently", async () => {
135
- const requestState: RequestStateWeakMap = new WeakMap();
136
- const schema1 = z.object({ type: z.literal("user") });
137
- const schema2 = z.object({ type: z.literal("session") });
138
-
139
- const store1 = defineRequestState(schema1);
140
- const store2 = defineRequestState(schema2);
141
-
142
- await runWithRequestState(requestState, async () => {
143
- await store1.set({ type: "user" });
144
- await store2.set({ type: "session" });
145
-
146
- expect(await store1.get()).toEqual({ type: "user" });
147
- expect(await store2.get()).toEqual({ type: "session" });
148
- });
149
- });
150
-
151
- it("should overwrite existing values", async () => {
152
- const requestState: RequestStateWeakMap = new WeakMap();
153
- const schema = z.object({ count: z.number() });
154
- const { get, set } = defineRequestState(schema);
155
-
156
- await runWithRequestState(requestState, async () => {
157
- await set({ count: 1 });
158
- expect(await get()).toEqual({ count: 1 });
159
-
160
- await set({ count: 2 });
161
- expect(await get()).toEqual({ count: 2 });
162
- });
163
- });
164
-
165
- it("should handle complex nested objects", async () => {
166
- const requestState: RequestStateWeakMap = new WeakMap();
167
- const schema = z.object({
168
- user: z.object({
169
- id: z.string(),
170
- profile: z.object({
171
- name: z.string(),
172
- settings: z.object({
173
- theme: z.string(),
174
- }),
175
- }),
176
- }),
177
- });
178
- const { get, set } = defineRequestState(schema);
179
-
180
- await runWithRequestState(requestState, async () => {
181
- const value = {
182
- user: {
183
- id: "123",
184
- profile: {
185
- name: "John",
186
- settings: {
187
- theme: "dark",
188
- },
189
- },
190
- },
191
- };
192
- await set(value);
193
- expect(await get()).toEqual(value);
194
- });
195
- });
196
-
197
- it("should handle arrays in schema", async () => {
198
- const requestState: RequestStateWeakMap = new WeakMap();
199
- const schema = z.object({
200
- tags: z.array(z.string()),
201
- scores: z.array(z.number()),
202
- });
203
- const { get, set } = defineRequestState(schema);
204
-
205
- await runWithRequestState(requestState, async () => {
206
- await set({ tags: ["auth", "oauth"], scores: [1, 2, 3] });
207
- const value = await get();
208
- expect(value).toEqual({ tags: ["auth", "oauth"], scores: [1, 2, 3] });
209
- });
210
- });
211
-
212
- it("should throw error when accessing outside request state context", async () => {
213
- const schema = z.object({ value: z.string() });
214
- const { get, set } = defineRequestState(schema);
215
-
216
- await expect(get()).rejects.toThrow("No request state found");
217
- await expect(set({ value: "test" })).rejects.toThrow(
218
- "No request state found",
219
- );
220
- });
221
- });
222
-
223
- describe("type inference", () => {
224
- it("should infer types from schema", async () => {
225
- const requestState: RequestStateWeakMap = new WeakMap();
226
- const schema = z.object({
227
- id: z.string(),
228
- count: z.number(),
229
- active: z.boolean(),
230
- });
231
- const { get, set } = defineRequestState(schema);
232
-
233
- await runWithRequestState(requestState, async () => {
234
- // TypeScript should infer the correct types here
235
- await set({ id: "123", count: 42, active: true });
236
- const value = await get();
237
-
238
- if (value) {
239
- // These should all be properly typed
240
- const id: string = value.id;
241
- const count: number = value.count;
242
- const active: boolean = value.active;
243
-
244
- expect(id).toBe("123");
245
- expect(count).toBe(42);
246
- expect(active).toBe(true);
247
- }
248
- });
249
- });
250
- });
251
-
252
- describe("error handling", () => {
253
- it("should handle errors thrown within runWithRequestState", async () => {
254
- const store: RequestStateWeakMap = new WeakMap();
255
-
256
- await expect(
257
- runWithRequestState(store, async () => {
258
- throw new Error("Test error");
259
- }),
260
- ).rejects.toThrow("Test error");
261
- });
262
-
263
- it("should clean up context after error", async () => {
264
- const store: RequestStateWeakMap = new WeakMap();
265
-
266
- try {
267
- await runWithRequestState(store, async () => {
268
- throw new Error("Test error");
269
- });
270
- } catch (e) {
271
- // Error is expected
272
- }
273
-
274
- // Should not have a store context after the error
275
- const hasStore = await hasRequestState();
276
- expect(hasStore).toBe(false);
277
- });
278
- });
279
-
280
- describe("WeakMap behavior", () => {
281
- it("should use schema objects as keys in WeakMap", async () => {
282
- const store: RequestStateWeakMap = new WeakMap();
283
- const schema1 = z.object({ value: z.string() });
284
- const schema2 = z.object({ value: z.string() }); // Same structure, different instance
285
-
286
- const store1 = defineRequestState(schema1);
287
- const store2 = defineRequestState(schema2);
288
-
289
- await runWithRequestState(store, async () => {
290
- await store1.set({ value: "first" });
291
- await store2.set({ value: "second" });
292
-
293
- // Different schema instances should have different values
294
- expect(await store1.get()).toEqual({ value: "first" });
295
- expect(await store2.get()).toEqual({ value: "second" });
296
- });
297
- });
298
- });
299
-
300
- describe("concurrent request isolation", () => {
301
- it("should maintain separate stores for 10 concurrent requests", async () => {
302
- const schema = z.object({ requestId: z.number() });
303
- const { get, set } = defineRequestState(schema);
304
-
305
- const promises = Array.from({ length: 10 }, (_, i) => {
306
- const store: RequestStateWeakMap = new WeakMap();
307
- return runWithRequestState(store, async () => {
308
- await set({ requestId: i });
309
- // Simulate async work with varying delays
310
- await new Promise((resolve) =>
311
- setTimeout(resolve, Math.random() * 20),
312
- );
313
- const value = await get();
314
- return value;
315
- });
316
- });
317
-
318
- const results = await Promise.all(promises);
319
-
320
- // Each request should have its own unique ID
321
- results.forEach((result, index) => {
322
- expect(result).toEqual({ requestId: index });
323
- });
324
- });
325
-
326
- it("should handle rapid consecutive requests", async () => {
327
- const schema = z.object({ counter: z.number() });
328
- const { get, set } = defineRequestState(schema);
329
-
330
- const results = await Promise.all(
331
- Array.from({ length: 100 }, async (_, i) => {
332
- const store: RequestStateWeakMap = new WeakMap();
333
- return runWithRequestState(store, async () => {
334
- await set({ counter: i });
335
- return await get();
336
- });
337
- }),
338
- );
339
-
340
- // Each request should have its own counter value
341
- results.forEach((result, index) => {
342
- expect(result).toEqual({ counter: index });
343
- });
344
- });
345
- });
346
- });
@@ -1,75 +0,0 @@
1
- import type { StandardSchemaV1 } from "@standard-schema/spec";
2
- import z from "zod";
3
- import { type AsyncLocalStorage, getAsyncLocalStorage } from "../async_hooks";
4
-
5
- export type RequestStateWeakMap = WeakMap<StandardSchemaV1, any>;
6
-
7
- let requestStateAsyncStorage: AsyncLocalStorage<RequestStateWeakMap> | null =
8
- null;
9
-
10
- const ensureAsyncStorage = async () => {
11
- if (!requestStateAsyncStorage) {
12
- const AsyncLocalStorage = await getAsyncLocalStorage();
13
- requestStateAsyncStorage = new AsyncLocalStorage();
14
- }
15
- return requestStateAsyncStorage;
16
- };
17
-
18
- export async function getRequestStateAsyncLocalStorage() {
19
- return ensureAsyncStorage();
20
- }
21
-
22
- export async function hasRequestState() {
23
- const als = await ensureAsyncStorage();
24
- return als.getStore() !== undefined;
25
- }
26
-
27
- export async function getCurrentRequestState(): Promise<RequestStateWeakMap> {
28
- const als = await ensureAsyncStorage();
29
- const store = als.getStore();
30
- if (!store) {
31
- throw new Error(
32
- "No request state found. Please make sure you are calling this function within a `runWithRequestState` callback.",
33
- );
34
- }
35
- return store;
36
- }
37
-
38
- export async function runWithRequestState<T>(
39
- store: RequestStateWeakMap,
40
- fn: () => T,
41
- ): Promise<T> {
42
- const als = await ensureAsyncStorage();
43
- return als.run(store, fn);
44
- }
45
-
46
- export interface RequestState<T> {
47
- get<S>(): Promise<S & T>;
48
- set(value: T): Promise<void>;
49
- }
50
-
51
- export function defineRequestState<T>(
52
- schema?: StandardSchemaV1<T>,
53
- ): RequestState<T>;
54
- export function defineRequestState<Schema extends StandardSchemaV1>(
55
- schema?: Schema,
56
- ): RequestState<StandardSchemaV1.InferInput<Schema>>;
57
- export function defineRequestState(
58
- schema: StandardSchemaV1 = z.any(),
59
- ): RequestState<any> {
60
- return {
61
- async get() {
62
- const store = await getCurrentRequestState();
63
- return store.get(schema);
64
- },
65
-
66
- async set(value) {
67
- const store = await getCurrentRequestState();
68
- const parsedValue = await schema["~standard"].validate(value);
69
- if (parsedValue.issues) {
70
- throw new Error(`Invalid value: ${JSON.stringify(parsedValue.issues)}`);
71
- }
72
- store.set(schema, parsedValue.value);
73
- },
74
- };
75
- }
@@ -1,72 +0,0 @@
1
- import { type AsyncLocalStorage, getAsyncLocalStorage } from "../async_hooks";
2
- import type { DBAdapter, DBTransactionAdapter } from "../db/adapter";
3
-
4
- let currentAdapterAsyncStorage: AsyncLocalStorage<DBTransactionAdapter> | null =
5
- null;
6
-
7
- const ensureAsyncStorage = async () => {
8
- if (!currentAdapterAsyncStorage) {
9
- const AsyncLocalStorage = await getAsyncLocalStorage();
10
- currentAdapterAsyncStorage = new AsyncLocalStorage();
11
- }
12
- return currentAdapterAsyncStorage;
13
- };
14
-
15
- /**
16
- * This is for internal use only. Most users should use `getCurrentAdapter` instead.
17
- *
18
- * It is exposed for advanced use cases where you need direct access to the AsyncLocalStorage instance.
19
- */
20
- export const getCurrentDBAdapterAsyncLocalStorage = async () => {
21
- return ensureAsyncStorage();
22
- };
23
-
24
- export const getCurrentAdapter = async (
25
- fallback: DBTransactionAdapter,
26
- ): Promise<DBTransactionAdapter> => {
27
- return ensureAsyncStorage()
28
- .then((als) => {
29
- return als.getStore() || fallback;
30
- })
31
- .catch(() => {
32
- return fallback;
33
- });
34
- };
35
-
36
- export const runWithAdapter = async <R>(
37
- adapter: DBAdapter,
38
- fn: () => R,
39
- ): Promise<R> => {
40
- let called = true;
41
- return ensureAsyncStorage()
42
- .then((als) => {
43
- called = true;
44
- return als.run(adapter, fn);
45
- })
46
- .catch((err) => {
47
- if (!called) {
48
- return fn();
49
- }
50
- throw err;
51
- });
52
- };
53
-
54
- export const runWithTransaction = async <R>(
55
- adapter: DBAdapter,
56
- fn: () => R,
57
- ): Promise<R> => {
58
- let called = true;
59
- return ensureAsyncStorage()
60
- .then((als) => {
61
- called = true;
62
- return adapter.transaction(async (trx) => {
63
- return als.run(trx, fn);
64
- });
65
- })
66
- .catch((err) => {
67
- if (!called) {
68
- return fn();
69
- }
70
- throw err;
71
- });
72
- };