@geekmidas/testkit 9.0.2 → 10.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/{Factory-CUM2767q.d.cts → Factory-Cwzho3c8.d.cts} +2 -2
  2. package/dist/{Factory-ClyZLRsO.d.mts.map → Factory-Cwzho3c8.d.cts.map} +1 -1
  3. package/dist/{Factory-ClyZLRsO.d.mts → Factory-SFupxRC2.d.mts} +2 -2
  4. package/dist/{Factory-CUM2767q.d.cts.map → Factory-SFupxRC2.d.mts.map} +1 -1
  5. package/dist/Factory.d.cts +2 -2
  6. package/dist/Factory.d.mts +2 -2
  7. package/dist/{KyselyFactory-OMwcuAX_.d.cts → KyselyFactory-hMcVtvJq.d.cts} +3 -3
  8. package/dist/{KyselyFactory-CTZmiGI9.d.mts.map → KyselyFactory-hMcVtvJq.d.cts.map} +1 -1
  9. package/dist/{KyselyFactory-CTZmiGI9.d.mts → KyselyFactory-vAxYodck.d.mts} +3 -3
  10. package/dist/{KyselyFactory-OMwcuAX_.d.cts.map → KyselyFactory-vAxYodck.d.mts.map} +1 -1
  11. package/dist/KyselyFactory.d.cts +3 -3
  12. package/dist/KyselyFactory.d.mts +3 -3
  13. package/dist/{ObjectionFactory-DDrKwAoO.d.mts → ObjectionFactory-BWjB49-i.d.mts} +3 -3
  14. package/dist/{ObjectionFactory-DDrKwAoO.d.mts.map → ObjectionFactory-BWjB49-i.d.mts.map} +1 -1
  15. package/dist/{ObjectionFactory-DvmZVHhe.d.cts → ObjectionFactory-DW-qwnqO.d.cts} +3 -3
  16. package/dist/{ObjectionFactory-DvmZVHhe.d.cts.map → ObjectionFactory-DW-qwnqO.d.cts.map} +1 -1
  17. package/dist/ObjectionFactory.d.cts +3 -3
  18. package/dist/ObjectionFactory.d.mts +3 -3
  19. package/dist/{VitestKyselyTransactionIsolator-CfSMOFlN.mjs → VitestKyselyTransactionIsolator-1Saieke7.mjs} +10 -3
  20. package/dist/VitestKyselyTransactionIsolator-1Saieke7.mjs.map +1 -0
  21. package/dist/{VitestKyselyTransactionIsolator-0CqOsuc9.cjs → VitestKyselyTransactionIsolator-BjJSXryR.cjs} +10 -3
  22. package/dist/VitestKyselyTransactionIsolator-BjJSXryR.cjs.map +1 -0
  23. package/dist/{VitestKyselyTransactionIsolator-CduJlHoT.d.cts → VitestKyselyTransactionIsolator-CwlTo6yf.d.mts} +8 -3
  24. package/dist/VitestKyselyTransactionIsolator-CwlTo6yf.d.mts.map +1 -0
  25. package/dist/{VitestKyselyTransactionIsolator-Cswnnj0k.d.mts → VitestKyselyTransactionIsolator-DJasVuIZ.d.cts} +8 -3
  26. package/dist/VitestKyselyTransactionIsolator-DJasVuIZ.d.cts.map +1 -0
  27. package/dist/VitestKyselyTransactionIsolator.cjs +2 -2
  28. package/dist/VitestKyselyTransactionIsolator.d.cts +2 -2
  29. package/dist/VitestKyselyTransactionIsolator.d.mts +2 -2
  30. package/dist/VitestKyselyTransactionIsolator.mjs +2 -2
  31. package/dist/{VitestObjectionTransactionIsolator-CNo40EdC.mjs → VitestObjectionTransactionIsolator-B_VSWFum.mjs} +2 -2
  32. package/dist/{VitestObjectionTransactionIsolator-CNo40EdC.mjs.map → VitestObjectionTransactionIsolator-B_VSWFum.mjs.map} +1 -1
  33. package/dist/{VitestObjectionTransactionIsolator-BXoR6xdG.d.cts → VitestObjectionTransactionIsolator-CTTjvTPO.d.cts} +2 -2
  34. package/dist/{VitestObjectionTransactionIsolator-BXoR6xdG.d.cts.map → VitestObjectionTransactionIsolator-CTTjvTPO.d.cts.map} +1 -1
  35. package/dist/{VitestObjectionTransactionIsolator-x6hY5j4u.d.mts → VitestObjectionTransactionIsolator-CyZG6nq4.d.mts} +2 -2
  36. package/dist/{VitestObjectionTransactionIsolator-x6hY5j4u.d.mts.map → VitestObjectionTransactionIsolator-CyZG6nq4.d.mts.map} +1 -1
  37. package/dist/{VitestObjectionTransactionIsolator-B5J9jjKq.cjs → VitestObjectionTransactionIsolator-DDoJTu7e.cjs} +2 -2
  38. package/dist/{VitestObjectionTransactionIsolator-B5J9jjKq.cjs.map → VitestObjectionTransactionIsolator-DDoJTu7e.cjs.map} +1 -1
  39. package/dist/VitestObjectionTransactionIsolator.cjs +2 -2
  40. package/dist/VitestObjectionTransactionIsolator.d.cts +2 -2
  41. package/dist/VitestObjectionTransactionIsolator.d.mts +2 -2
  42. package/dist/VitestObjectionTransactionIsolator.mjs +2 -2
  43. package/dist/{VitestTransactionIsolator-BNWJqh9f.d.mts → VitestTransactionIsolator-BLaw80cx.d.mts} +20 -4
  44. package/dist/VitestTransactionIsolator-BLaw80cx.d.mts.map +1 -0
  45. package/dist/{VitestTransactionIsolator-D6ZxLWys.mjs → VitestTransactionIsolator-CvwPecpl.mjs} +17 -4
  46. package/dist/VitestTransactionIsolator-CvwPecpl.mjs.map +1 -0
  47. package/dist/{VitestTransactionIsolator-CtZaOUjH.cjs → VitestTransactionIsolator-DyiX-QtK.cjs} +17 -4
  48. package/dist/VitestTransactionIsolator-DyiX-QtK.cjs.map +1 -0
  49. package/dist/{VitestTransactionIsolator-CSroc7Df.d.cts → VitestTransactionIsolator-glcxyS_R.d.cts} +20 -4
  50. package/dist/VitestTransactionIsolator-glcxyS_R.d.cts.map +1 -0
  51. package/dist/VitestTransactionIsolator.cjs +1 -1
  52. package/dist/VitestTransactionIsolator.d.cts +2 -2
  53. package/dist/VitestTransactionIsolator.d.mts +2 -2
  54. package/dist/VitestTransactionIsolator.mjs +1 -1
  55. package/dist/better-auth.d.cts +2 -2
  56. package/dist/better-auth.d.mts +2 -2
  57. package/dist/{directory-DGOcVlKD.d.cts → directory-Bpz5c5pj.d.cts} +3 -3
  58. package/dist/{directory-DGOcVlKD.d.cts.map → directory-Bpz5c5pj.d.cts.map} +1 -1
  59. package/dist/{faker-BcjUfHxx.d.mts → faker-DHh7xs4u.d.mts} +3 -3
  60. package/dist/{faker-BcjUfHxx.d.mts.map → faker-DHh7xs4u.d.mts.map} +1 -1
  61. package/dist/{faker-zVCm31nU.d.cts → faker-Dg3trU4a.d.cts} +3 -3
  62. package/dist/{faker-zVCm31nU.d.cts.map → faker-Dg3trU4a.d.cts.map} +1 -1
  63. package/dist/faker.d.cts +1 -1
  64. package/dist/faker.d.mts +1 -1
  65. package/dist/kysely.cjs +2 -2
  66. package/dist/kysely.d.cts +5 -5
  67. package/dist/kysely.d.mts +5 -5
  68. package/dist/kysely.mjs +2 -2
  69. package/dist/objection.cjs +2 -2
  70. package/dist/objection.d.cts +5 -5
  71. package/dist/objection.d.mts +5 -5
  72. package/dist/objection.mjs +2 -2
  73. package/dist/os/directory.d.cts +1 -1
  74. package/dist/os/index.d.cts +1 -1
  75. package/dist/requestContext.cjs +1 -1
  76. package/dist/requestContext.d.cts +1 -1
  77. package/dist/requestContext.d.mts +1 -1
  78. package/dist/requestContext.mjs +1 -1
  79. package/package.json +10 -7
  80. package/CHANGELOG.md +0 -151
  81. package/dist/VitestKyselyTransactionIsolator-0CqOsuc9.cjs.map +0 -1
  82. package/dist/VitestKyselyTransactionIsolator-CduJlHoT.d.cts.map +0 -1
  83. package/dist/VitestKyselyTransactionIsolator-CfSMOFlN.mjs.map +0 -1
  84. package/dist/VitestKyselyTransactionIsolator-Cswnnj0k.d.mts.map +0 -1
  85. package/dist/VitestTransactionIsolator-BNWJqh9f.d.mts.map +0 -1
  86. package/dist/VitestTransactionIsolator-CSroc7Df.d.cts.map +0 -1
  87. package/dist/VitestTransactionIsolator-CtZaOUjH.cjs.map +0 -1
  88. package/dist/VitestTransactionIsolator-D6ZxLWys.mjs.map +0 -1
  89. package/src/Factory.ts +0 -174
  90. package/src/KyselyFactory.ts +0 -391
  91. package/src/ObjectionFactory.ts +0 -412
  92. package/src/PostgresKyselyMigrator.ts +0 -104
  93. package/src/PostgresMigrator.ts +0 -193
  94. package/src/PostgresObjectionMigrator.ts +0 -138
  95. package/src/VitestKyselyTransactionIsolator.ts +0 -72
  96. package/src/VitestObjectionTransactionIsolator.ts +0 -75
  97. package/src/VitestTransactionIsolator.ts +0 -348
  98. package/src/__tests__/Factory.spec.ts +0 -178
  99. package/src/__tests__/KyselyFactory.spec.ts +0 -458
  100. package/src/__tests__/ObjectionFactory.spec.ts +0 -586
  101. package/src/__tests__/PostgresKyselyMigrator.spec.ts +0 -794
  102. package/src/__tests__/PostgresMigrator.spec.ts +0 -471
  103. package/src/__tests__/PostgresObjectionMigrator.spec.ts +0 -634
  104. package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +0 -138
  105. package/src/__tests__/benchmark.spec.ts +0 -140
  106. package/src/__tests__/better-auth.spec.ts +0 -21
  107. package/src/__tests__/faker.spec.ts +0 -231
  108. package/src/__tests__/initScript.spec.ts +0 -332
  109. package/src/__tests__/integration.spec.ts +0 -610
  110. package/src/__tests__/requestContext.spec.ts +0 -113
  111. package/src/__tests__/utilities.spec.ts +0 -211
  112. package/src/aws.ts +0 -131
  113. package/src/benchmark.ts +0 -48
  114. package/src/better-auth.ts +0 -310
  115. package/src/faker.ts +0 -349
  116. package/src/helpers.ts +0 -45
  117. package/src/initScript.ts +0 -122
  118. package/src/kysely.ts +0 -166
  119. package/src/logger.ts +0 -18
  120. package/src/objection.ts +0 -157
  121. package/src/os/directory.ts +0 -26
  122. package/src/os/index.ts +0 -1
  123. package/src/requestContext.ts +0 -119
  124. package/src/timer.ts +0 -3
  125. package/test/globalSetup.ts +0 -54
  126. package/test/helpers.ts +0 -268
  127. package/test/migrations/1749664623372_user.ts +0 -22
  128. package/tsconfig.json +0 -9
  129. package/vitest.config.ts +0 -8
@@ -1,211 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { describe, expect, it } from 'vitest';
4
- import {
5
- createMockContext,
6
- createMockV1Event,
7
- createMockV2Event,
8
- } from '../aws';
9
- import { createMockLogger } from '../logger';
10
- import { itWithDir } from '../os/directory';
11
- import { waitFor } from '../timer';
12
-
13
- describe('testkit utilities', () => {
14
- describe('createMockLogger', () => {
15
- it('should create a logger with all required methods', () => {
16
- const logger = createMockLogger();
17
-
18
- expect(logger.debug).toBeDefined();
19
- expect(logger.info).toBeDefined();
20
- expect(logger.warn).toBeDefined();
21
- expect(logger.error).toBeDefined();
22
- expect(logger.fatal).toBeDefined();
23
- expect(logger.trace).toBeDefined();
24
- expect(logger.child).toBeDefined();
25
- });
26
-
27
- it('should have mock functions that can be called', () => {
28
- const logger = createMockLogger();
29
-
30
- logger.debug('debug message');
31
- logger.info({ data: 'test' }, 'info message');
32
- logger.warn('warning');
33
- logger.error('error');
34
- logger.fatal('fatal');
35
- logger.trace('trace');
36
-
37
- expect(logger.debug).toHaveBeenCalledWith('debug message');
38
- expect(logger.info).toHaveBeenCalledWith(
39
- { data: 'test' },
40
- 'info message',
41
- );
42
- expect(logger.warn).toHaveBeenCalledWith('warning');
43
- expect(logger.error).toHaveBeenCalledWith('error');
44
- expect(logger.fatal).toHaveBeenCalledWith('fatal');
45
- expect(logger.trace).toHaveBeenCalledWith('trace');
46
- });
47
-
48
- it('should return itself from child()', () => {
49
- const logger = createMockLogger();
50
- const childLogger = logger.child({ module: 'test' });
51
-
52
- expect(childLogger).toBe(logger);
53
- expect(logger.child).toHaveBeenCalledWith({ module: 'test' });
54
- });
55
- });
56
-
57
- describe('waitFor', () => {
58
- it('should wait for the specified time', async () => {
59
- const start = Date.now();
60
- await waitFor(50);
61
- const elapsed = Date.now() - start;
62
-
63
- expect(elapsed).toBeGreaterThanOrEqual(40);
64
- expect(elapsed).toBeLessThan(150);
65
- });
66
-
67
- it('should resolve without a value', async () => {
68
- const result = await waitFor(10);
69
- expect(result).toBeUndefined();
70
- });
71
- });
72
-
73
- describe('AWS mock utilities', () => {
74
- describe('createMockContext', () => {
75
- it('should create a valid Lambda context', () => {
76
- const context = createMockContext();
77
-
78
- expect(context.awsRequestId).toBe('test-request-id');
79
- expect(context.functionName).toBe('test-function');
80
- expect(context.functionVersion).toBe('1');
81
- expect(context.memoryLimitInMB).toBe('128');
82
- expect(context.logGroupName).toBe('/aws/lambda/test-function');
83
- expect(context.invokedFunctionArn).toContain('arn:aws:lambda');
84
- });
85
-
86
- it('should have mock callback functions', () => {
87
- const context = createMockContext();
88
-
89
- expect(context.done).toBeDefined();
90
- expect(context.fail).toBeDefined();
91
- expect(context.succeed).toBeDefined();
92
-
93
- context.done();
94
- context.fail(new Error('test'));
95
- context.succeed('result');
96
-
97
- expect(context.done).toHaveBeenCalled();
98
- expect(context.fail).toHaveBeenCalled();
99
- expect(context.succeed).toHaveBeenCalled();
100
- });
101
-
102
- it('should return remaining time', () => {
103
- const context = createMockContext();
104
- const remaining = context.getRemainingTimeInMillis();
105
-
106
- expect(remaining).toBe(5000);
107
- });
108
- });
109
-
110
- describe('createMockV1Event', () => {
111
- it('should create a valid API Gateway V1 event', () => {
112
- const event = createMockV1Event();
113
-
114
- expect(event.httpMethod).toBe('GET');
115
- expect(event.path).toBe('/test');
116
- expect(event.headers['content-type']).toBe('application/json');
117
- expect(event.requestContext.accountId).toBe('123456789012');
118
- expect(event.requestContext.stage).toBe('test');
119
- });
120
-
121
- it('should allow overriding properties', () => {
122
- const event = createMockV1Event({
123
- httpMethod: 'POST',
124
- path: '/users',
125
- body: JSON.stringify({ name: 'test' }),
126
- pathParameters: { id: '123' },
127
- queryStringParameters: { page: '1' },
128
- });
129
-
130
- expect(event.httpMethod).toBe('POST');
131
- expect(event.path).toBe('/users');
132
- expect(event.body).toBe(JSON.stringify({ name: 'test' }));
133
- expect(event.pathParameters).toEqual({ id: '123' });
134
- expect(event.queryStringParameters).toEqual({ page: '1' });
135
- });
136
-
137
- it('should have correct identity fields', () => {
138
- const event = createMockV1Event();
139
-
140
- expect(event.requestContext.identity.sourceIp).toBe('127.0.0.1');
141
- expect(event.requestContext.identity.userAgent).toBe('test-agent');
142
- });
143
- });
144
-
145
- describe('createMockV2Event', () => {
146
- it('should create a valid API Gateway V2 event', () => {
147
- const event = createMockV2Event();
148
-
149
- expect(event.version).toBe('2.0');
150
- expect(event.routeKey).toBe('GET /test');
151
- expect(event.rawPath).toBe('/test');
152
- expect(event.headers['content-type']).toBe('application/json');
153
- expect(event.requestContext.accountId).toBe('123456789012');
154
- });
155
-
156
- it('should allow overriding properties', () => {
157
- const event = createMockV2Event({
158
- routeKey: 'POST /users',
159
- rawPath: '/users',
160
- body: JSON.stringify({ name: 'test' }),
161
- pathParameters: { id: '123' },
162
- queryStringParameters: { page: '1' },
163
- });
164
-
165
- expect(event.routeKey).toBe('POST /users');
166
- expect(event.rawPath).toBe('/users');
167
- expect(event.body).toBe(JSON.stringify({ name: 'test' }));
168
- expect(event.pathParameters).toEqual({ id: '123' });
169
- expect(event.queryStringParameters).toEqual({ page: '1' });
170
- });
171
-
172
- it('should have correct HTTP context', () => {
173
- const event = createMockV2Event();
174
-
175
- expect(event.requestContext.http.method).toBe('GET');
176
- expect(event.requestContext.http.path).toBe('/test');
177
- expect(event.requestContext.http.sourceIp).toBe('127.0.0.1');
178
- expect(event.requestContext.http.userAgent).toBe('test-agent');
179
- });
180
- });
181
- });
182
-
183
- describe('itWithDir', () => {
184
- itWithDir('should provide a temporary directory', async ({ dir }) => {
185
- expect(dir).toBeDefined();
186
- expect(typeof dir).toBe('string');
187
-
188
- // Directory should exist
189
- const stat = await fs.stat(dir);
190
- expect(stat.isDirectory()).toBe(true);
191
- });
192
-
193
- itWithDir(
194
- 'should allow creating files in the directory',
195
- async ({ dir }) => {
196
- const testFile = path.join(dir, 'test.txt');
197
- await fs.writeFile(testFile, 'hello');
198
-
199
- const content = await fs.readFile(testFile, 'utf-8');
200
- expect(content).toBe('hello');
201
- },
202
- );
203
-
204
- itWithDir('should provide unique directories per test', async ({ dir }) => {
205
- // The directory should have a UUID-like name (uppercase hex)
206
- const dirName = path.basename(dir);
207
- expect(dirName).toMatch(/^[A-F0-9]{32}$/);
208
- expect(dir.length).toBeGreaterThan(10);
209
- });
210
- });
211
- });
package/src/aws.ts DELETED
@@ -1,131 +0,0 @@
1
- import type {
2
- APIGatewayProxyEvent,
3
- APIGatewayProxyEventV2,
4
- Context,
5
- } from 'aws-lambda';
6
- import { vi } from 'vitest';
7
-
8
- /**
9
- * Shared test utilities for AWS Lambda adapter testing
10
- */
11
-
12
- /**
13
- * Creates a mock AWS Lambda Context for testing
14
- */
15
- export function createMockContext(): Context {
16
- return {
17
- awsRequestId: 'test-request-id',
18
- callbackWaitsForEmptyEventLoop: false,
19
- functionName: 'test-function',
20
- functionVersion: '1',
21
- invokedFunctionArn:
22
- 'arn:aws:lambda:us-east-1:123456789012:function:test-function',
23
- memoryLimitInMB: '128',
24
- logGroupName: '/aws/lambda/test-function',
25
- logStreamName: '2024/01/01/[$LATEST]abcdef123456',
26
- getRemainingTimeInMillis: () => 5000,
27
- done: vi.fn(),
28
- fail: vi.fn(),
29
- succeed: vi.fn(),
30
- };
31
- }
32
-
33
- /**
34
- * Creates a mock AWS API Gateway V1 (REST API) event for testing
35
- */
36
- export function createMockV1Event(
37
- overrides: Partial<APIGatewayProxyEvent> = {},
38
- ): APIGatewayProxyEvent {
39
- return {
40
- body: null,
41
- headers: {
42
- 'content-type': 'application/json',
43
- 'user-agent': 'test-agent',
44
- host: 'test.example.com',
45
- },
46
- multiValueHeaders: {},
47
- httpMethod: 'GET',
48
- isBase64Encoded: false,
49
- path: '/test',
50
- pathParameters: null,
51
- queryStringParameters: null,
52
- multiValueQueryStringParameters: null,
53
- stageVariables: null,
54
- requestContext: {
55
- accountId: '123456789012',
56
- apiId: 'api-id',
57
- authorizer: null,
58
- protocol: 'HTTP/1.1',
59
- httpMethod: 'GET',
60
- path: '/test',
61
- stage: 'test',
62
- requestId: 'request-id',
63
- requestTimeEpoch: 1704067200000,
64
- resourceId: 'resource-id',
65
- resourcePath: '/test',
66
- identity: {
67
- accessKey: null,
68
- accountId: null,
69
- apiKey: null,
70
- apiKeyId: null,
71
- caller: null,
72
- cognitoAuthenticationProvider: null,
73
- cognitoAuthenticationType: null,
74
- cognitoIdentityId: null,
75
- cognitoIdentityPoolId: null,
76
- principalOrgId: null,
77
- sourceIp: '127.0.0.1',
78
- user: null,
79
- userAgent: 'test-agent',
80
- userArn: null,
81
- clientCert: null,
82
- },
83
- },
84
- resource: '/test',
85
- ...overrides,
86
- };
87
- }
88
-
89
- /**
90
- * Creates a mock AWS API Gateway V2 (HTTP API) event for testing
91
- */
92
- export function createMockV2Event(
93
- overrides: Partial<APIGatewayProxyEventV2> = {},
94
- ): APIGatewayProxyEventV2 {
95
- return {
96
- version: '2.0',
97
- routeKey: 'GET /test',
98
- rawPath: '/test',
99
- rawQueryString: '',
100
- headers: {
101
- 'content-type': 'application/json',
102
- 'user-agent': 'test-agent',
103
- host: 'test.example.com',
104
- },
105
- requestContext: {
106
- accountId: '123456789012',
107
- apiId: 'api-id',
108
- domainName: 'test.example.com',
109
- domainPrefix: 'api',
110
- requestId: 'request-id',
111
- routeKey: 'GET /test',
112
- stage: 'test',
113
- time: '01/Jan/2024:00:00:00 +0000',
114
- timeEpoch: 1704067200000,
115
- http: {
116
- method: 'GET',
117
- path: '/test',
118
- protocol: 'HTTP/1.1',
119
- sourceIp: '127.0.0.1',
120
- userAgent: 'test-agent',
121
- },
122
- },
123
- body: undefined,
124
- pathParameters: undefined,
125
- isBase64Encoded: false,
126
- stageVariables: undefined,
127
- queryStringParameters: undefined,
128
- cookies: undefined,
129
- ...overrides,
130
- };
131
- }
package/src/benchmark.ts DELETED
@@ -1,48 +0,0 @@
1
- /**
2
- * Generates an array of test records for benchmark data sets.
3
- *
4
- * @param count - Number of records to generate
5
- * @returns Array of test data objects
6
- */
7
- export function generateTestData(
8
- count: number,
9
- ): Array<{ id: string; name: string; value: number }> {
10
- return Array.from({ length: count }, (_, i) => ({
11
- id: `id-${i}`,
12
- name: `Item ${i}`,
13
- value: Math.random() * 1000,
14
- }));
15
- }
16
-
17
- /**
18
- * Generates unique keys for cache benchmarks to avoid collisions.
19
- *
20
- * @param prefix - Key prefix
21
- * @param count - Number of keys to generate
22
- * @returns Array of unique cache keys
23
- */
24
- export function generateCacheKeys(prefix: string, count: number): string[] {
25
- return Array.from({ length: count }, (_, i) => `${prefix}:${i}`);
26
- }
27
-
28
- /**
29
- * Generates IP addresses for rate limit benchmarks.
30
- *
31
- * @param count - Number of IPs to generate
32
- * @param subnet - Subnet prefix (default: '192.168.1')
33
- * @returns Array of IP addresses
34
- */
35
- export function generateIpAddresses(
36
- count: number,
37
- subnet: string = '192.168.1',
38
- ): string[] {
39
- return Array.from({ length: count }, (_, i) => `${subnet}.${i % 256}`);
40
- }
41
-
42
- /**
43
- * Creates a random IP address for rate limit benchmarks.
44
- */
45
- export function randomIpAddress(): string {
46
- const octet = () => Math.floor(Math.random() * 256);
47
- return `${octet()}.${octet()}.${octet()}.${octet()}`;
48
- }
@@ -1,310 +0,0 @@
1
- import {
2
- createAdapterFactory,
3
- type DBAdapterDebugLogOption,
4
- type Where,
5
- } from 'better-auth/adapters';
6
-
7
- interface MemoryAdapterConfig {
8
- debugLogs?: DBAdapterDebugLogOption;
9
- usePlural?: boolean;
10
- initialData?: Record<string, any[]>;
11
- }
12
-
13
- class MemoryStore {
14
- constructor(
15
- initialData?: Record<string, any[]>,
16
- private readonly data: Map<string, any> = new Map(),
17
- ) {
18
- if (initialData) {
19
- for (const [model, records] of Object.entries(initialData)) {
20
- const modelData = new Map();
21
- for (const record of records) {
22
- modelData.set(record.id, { ...record });
23
- }
24
- this.data.set(model, modelData);
25
- }
26
- }
27
- }
28
-
29
- getModel(modelName: string): Map<string, any> {
30
- if (!this.data.has(modelName)) {
31
- this.data.set(modelName, new Map());
32
- }
33
- return this.data.get(modelName)!;
34
- }
35
-
36
- clear() {
37
- this.data.clear();
38
- }
39
-
40
- getAllData() {
41
- const result: Record<string, any[]> = {};
42
- for (const [model, records] of this.data.entries()) {
43
- result[model] = Array.from(records.values());
44
- }
45
- return result;
46
- }
47
- }
48
-
49
- function matchesWhere(record: any, where?: Where[]): boolean {
50
- if (!where || where.length === 0) return true;
51
-
52
- let result: boolean | null = null;
53
-
54
- for (const condition of where) {
55
- const { field, value, operator = 'eq', connector = 'AND' } = condition;
56
- const recordValue = record[field];
57
-
58
- let matches = false;
59
-
60
- switch (operator) {
61
- case 'eq':
62
- matches = recordValue === value;
63
- break;
64
- case 'ne':
65
- matches = recordValue !== value;
66
- break;
67
- case 'lt':
68
- matches = value != null && recordValue < value;
69
- break;
70
- case 'lte':
71
- matches = value != null && recordValue <= value;
72
- break;
73
- case 'gt':
74
- matches = value != null && recordValue > value;
75
- break;
76
- case 'gte':
77
- matches = value != null && recordValue >= value;
78
- break;
79
- case 'in':
80
- matches =
81
- Array.isArray(value) && (value as unknown[]).includes(recordValue);
82
- break;
83
- case 'not_in':
84
- matches =
85
- Array.isArray(value) && !(value as unknown[]).includes(recordValue);
86
- break;
87
- case 'contains':
88
- matches =
89
- typeof recordValue === 'string' &&
90
- typeof value === 'string' &&
91
- recordValue.includes(value);
92
- break;
93
- case 'starts_with':
94
- matches =
95
- typeof recordValue === 'string' &&
96
- typeof value === 'string' &&
97
- recordValue.startsWith(value);
98
- break;
99
- case 'ends_with':
100
- matches =
101
- typeof recordValue === 'string' &&
102
- typeof value === 'string' &&
103
- recordValue.endsWith(value);
104
- break;
105
- default:
106
- matches = recordValue === value;
107
- }
108
-
109
- // Apply connector logic
110
- if (result === null) {
111
- result = matches;
112
- } else if (connector === 'OR') {
113
- result = result || matches;
114
- } else {
115
- // Default: AND
116
- result = result && matches;
117
- }
118
- }
119
-
120
- return result ?? true;
121
- }
122
- type SortBy = {
123
- field: string;
124
- direction: 'asc' | 'desc';
125
- };
126
-
127
- function applySorting(records: any[], sortBy?: SortBy): any[] {
128
- if (!sortBy) return records;
129
-
130
- const { field, direction } = sortBy;
131
-
132
- return records.sort((a, b) => {
133
- const aVal = a[field];
134
- const bVal = b[field];
135
-
136
- if (aVal === bVal) return 0;
137
- if (aVal == null) return direction === 'asc' ? -1 : 1;
138
- if (bVal == null) return direction === 'asc' ? 1 : -1;
139
-
140
- const comparison = aVal < bVal ? -1 : 1;
141
- return direction === 'asc' ? comparison : -comparison;
142
- });
143
- }
144
-
145
- export const memoryAdapter = (
146
- config: MemoryAdapterConfig = {},
147
- store = new Map(),
148
- ) => {
149
- const storeInstance = new MemoryStore(config.initialData, store);
150
-
151
- const adapterInstance = createAdapterFactory({
152
- config: {
153
- adapterId: 'memory-adapter',
154
- adapterName: 'Memory Adapter',
155
- usePlural: config.usePlural ?? false,
156
- debugLogs: config.debugLogs ?? false,
157
- supportsJSON: true,
158
- supportsDates: true,
159
- supportsBooleans: true,
160
- supportsNumericIds: false,
161
- },
162
-
163
- // Note: The framework automatically transforms field names in both directions:
164
- // - Input data is already transformed before reaching the adapter (e.g., email -> email_address)
165
- // - Output data is automatically transformed after the adapter returns (e.g., email_address -> email)
166
- // Therefore, we should NOT call transformInput or transformOutput ourselves.
167
- adapter: ({ debugLog, getModelName, transformWhereClause }) => ({
168
- create: async ({ data, model }) => {
169
- debugLog('CREATE', { model, data });
170
- const modelName = getModelName(model);
171
- const modelData = storeInstance.getModel(modelName);
172
-
173
- // Data is already transformed by the framework - store directly
174
- const record = data as Record<string, unknown>;
175
- if (!record.id) {
176
- record.id = crypto.randomUUID();
177
- }
178
-
179
- const id = record.id as string;
180
- modelData.set(id, { ...record });
181
- return modelData.get(id);
182
- },
183
-
184
- findOne: async ({ where, model }) => {
185
- debugLog('FIND_ONE', { model, where });
186
- const modelName = getModelName(model);
187
- const modelData = storeInstance.getModel(modelName);
188
- const transformedWhere = transformWhereClause({ model, where });
189
-
190
- for (const record of modelData.values()) {
191
- if (matchesWhere(record, transformedWhere)) {
192
- return record;
193
- }
194
- }
195
- return null;
196
- },
197
-
198
- findMany: async ({ where, model, limit, offset, sortBy }) => {
199
- debugLog('FIND_MANY', { model, where });
200
-
201
- const modelName = getModelName(model);
202
- const modelData = storeInstance.getModel(modelName);
203
- const transformedWhere = transformWhereClause({ model, where });
204
-
205
- let results = Array.from(modelData.values()).filter((record) =>
206
- matchesWhere(record, transformedWhere),
207
- );
208
-
209
- if (sortBy) {
210
- results = applySorting(results, sortBy);
211
- }
212
-
213
- if (offset) {
214
- results = results.slice(offset);
215
- }
216
- if (limit) {
217
- results = results.slice(0, limit);
218
- }
219
-
220
- return results;
221
- },
222
-
223
- update: async ({ where, update, model }) => {
224
- debugLog('UPDATE', { model, where });
225
-
226
- const modelName = getModelName(model);
227
- const modelData = storeInstance.getModel(modelName);
228
- const transformedWhere = transformWhereClause({ model, where });
229
-
230
- for (const [id, record] of modelData.entries()) {
231
- if (matchesWhere(record, transformedWhere)) {
232
- // Update data is already transformed by the framework
233
- const updated = { ...record, ...update };
234
- modelData.set(id, updated);
235
- return updated;
236
- }
237
- }
238
- return null;
239
- },
240
-
241
- updateMany: async ({ where, update, model }) => {
242
- debugLog('UPDATE_MANY', { model, where });
243
- const modelName = getModelName(model);
244
- const modelData = storeInstance.getModel(modelName);
245
- const transformedWhere = transformWhereClause({ model, where });
246
-
247
- let count = 0;
248
-
249
- for (const [id, record] of modelData.entries()) {
250
- if (matchesWhere(record, transformedWhere)) {
251
- // Update data is already transformed by the framework
252
- modelData.set(id, { ...record, ...update });
253
- count++;
254
- }
255
- }
256
- return count;
257
- },
258
-
259
- delete: async ({ where, model }) => {
260
- debugLog('DELETE', { model, where });
261
- const modelName = getModelName(model);
262
- const modelData = storeInstance.getModel(modelName);
263
- const transformedWhere = transformWhereClause({ model, where });
264
-
265
- for (const [id, record] of modelData.entries()) {
266
- if (matchesWhere(record, transformedWhere)) {
267
- modelData.delete(id);
268
- return;
269
- }
270
- }
271
- },
272
-
273
- deleteMany: async ({ where, model }) => {
274
- debugLog('DELETE_MANY', { model, where });
275
- const modelName = getModelName(model);
276
- const modelData = storeInstance.getModel(modelName);
277
- const transformedWhere = transformWhereClause({ model, where });
278
-
279
- const toDelete: string[] = [];
280
- for (const [id, record] of modelData.entries()) {
281
- if (matchesWhere(record, transformedWhere)) {
282
- toDelete.push(id);
283
- }
284
- }
285
-
286
- for (const id of toDelete) {
287
- modelData.delete(id);
288
- }
289
- return toDelete.length;
290
- },
291
-
292
- count: async ({ where, model }) => {
293
- const modelName = getModelName(model);
294
- const modelData = storeInstance.getModel(modelName);
295
- const transformedWhere = transformWhereClause({ model, where });
296
-
297
- return Array.from(modelData.values()).filter((record) =>
298
- matchesWhere(record, transformedWhere),
299
- ).length;
300
- },
301
- }),
302
- });
303
-
304
- // Add utility methods to the adapter
305
- return Object.assign(adapterInstance, {
306
- clear: () => store.clear(),
307
- getAllData: () => storeInstance.getAllData(),
308
- getStore: () => store,
309
- });
310
- };