@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.
- package/dist/{Factory-CUM2767q.d.cts → Factory-Cwzho3c8.d.cts} +2 -2
- package/dist/{Factory-ClyZLRsO.d.mts.map → Factory-Cwzho3c8.d.cts.map} +1 -1
- package/dist/{Factory-ClyZLRsO.d.mts → Factory-SFupxRC2.d.mts} +2 -2
- package/dist/{Factory-CUM2767q.d.cts.map → Factory-SFupxRC2.d.mts.map} +1 -1
- package/dist/Factory.d.cts +2 -2
- package/dist/Factory.d.mts +2 -2
- package/dist/{KyselyFactory-OMwcuAX_.d.cts → KyselyFactory-hMcVtvJq.d.cts} +3 -3
- package/dist/{KyselyFactory-CTZmiGI9.d.mts.map → KyselyFactory-hMcVtvJq.d.cts.map} +1 -1
- package/dist/{KyselyFactory-CTZmiGI9.d.mts → KyselyFactory-vAxYodck.d.mts} +3 -3
- package/dist/{KyselyFactory-OMwcuAX_.d.cts.map → KyselyFactory-vAxYodck.d.mts.map} +1 -1
- package/dist/KyselyFactory.d.cts +3 -3
- package/dist/KyselyFactory.d.mts +3 -3
- package/dist/{ObjectionFactory-DDrKwAoO.d.mts → ObjectionFactory-BWjB49-i.d.mts} +3 -3
- package/dist/{ObjectionFactory-DDrKwAoO.d.mts.map → ObjectionFactory-BWjB49-i.d.mts.map} +1 -1
- package/dist/{ObjectionFactory-DvmZVHhe.d.cts → ObjectionFactory-DW-qwnqO.d.cts} +3 -3
- package/dist/{ObjectionFactory-DvmZVHhe.d.cts.map → ObjectionFactory-DW-qwnqO.d.cts.map} +1 -1
- package/dist/ObjectionFactory.d.cts +3 -3
- package/dist/ObjectionFactory.d.mts +3 -3
- package/dist/{VitestKyselyTransactionIsolator-CfSMOFlN.mjs → VitestKyselyTransactionIsolator-1Saieke7.mjs} +10 -3
- package/dist/VitestKyselyTransactionIsolator-1Saieke7.mjs.map +1 -0
- package/dist/{VitestKyselyTransactionIsolator-0CqOsuc9.cjs → VitestKyselyTransactionIsolator-BjJSXryR.cjs} +10 -3
- package/dist/VitestKyselyTransactionIsolator-BjJSXryR.cjs.map +1 -0
- package/dist/{VitestKyselyTransactionIsolator-CduJlHoT.d.cts → VitestKyselyTransactionIsolator-CwlTo6yf.d.mts} +8 -3
- package/dist/VitestKyselyTransactionIsolator-CwlTo6yf.d.mts.map +1 -0
- package/dist/{VitestKyselyTransactionIsolator-Cswnnj0k.d.mts → VitestKyselyTransactionIsolator-DJasVuIZ.d.cts} +8 -3
- package/dist/VitestKyselyTransactionIsolator-DJasVuIZ.d.cts.map +1 -0
- package/dist/VitestKyselyTransactionIsolator.cjs +2 -2
- package/dist/VitestKyselyTransactionIsolator.d.cts +2 -2
- package/dist/VitestKyselyTransactionIsolator.d.mts +2 -2
- package/dist/VitestKyselyTransactionIsolator.mjs +2 -2
- package/dist/{VitestObjectionTransactionIsolator-CNo40EdC.mjs → VitestObjectionTransactionIsolator-B_VSWFum.mjs} +2 -2
- package/dist/{VitestObjectionTransactionIsolator-CNo40EdC.mjs.map → VitestObjectionTransactionIsolator-B_VSWFum.mjs.map} +1 -1
- package/dist/{VitestObjectionTransactionIsolator-BXoR6xdG.d.cts → VitestObjectionTransactionIsolator-CTTjvTPO.d.cts} +2 -2
- package/dist/{VitestObjectionTransactionIsolator-BXoR6xdG.d.cts.map → VitestObjectionTransactionIsolator-CTTjvTPO.d.cts.map} +1 -1
- package/dist/{VitestObjectionTransactionIsolator-x6hY5j4u.d.mts → VitestObjectionTransactionIsolator-CyZG6nq4.d.mts} +2 -2
- package/dist/{VitestObjectionTransactionIsolator-x6hY5j4u.d.mts.map → VitestObjectionTransactionIsolator-CyZG6nq4.d.mts.map} +1 -1
- package/dist/{VitestObjectionTransactionIsolator-B5J9jjKq.cjs → VitestObjectionTransactionIsolator-DDoJTu7e.cjs} +2 -2
- package/dist/{VitestObjectionTransactionIsolator-B5J9jjKq.cjs.map → VitestObjectionTransactionIsolator-DDoJTu7e.cjs.map} +1 -1
- package/dist/VitestObjectionTransactionIsolator.cjs +2 -2
- package/dist/VitestObjectionTransactionIsolator.d.cts +2 -2
- package/dist/VitestObjectionTransactionIsolator.d.mts +2 -2
- package/dist/VitestObjectionTransactionIsolator.mjs +2 -2
- package/dist/{VitestTransactionIsolator-BNWJqh9f.d.mts → VitestTransactionIsolator-BLaw80cx.d.mts} +20 -4
- package/dist/VitestTransactionIsolator-BLaw80cx.d.mts.map +1 -0
- package/dist/{VitestTransactionIsolator-D6ZxLWys.mjs → VitestTransactionIsolator-CvwPecpl.mjs} +17 -4
- package/dist/VitestTransactionIsolator-CvwPecpl.mjs.map +1 -0
- package/dist/{VitestTransactionIsolator-CtZaOUjH.cjs → VitestTransactionIsolator-DyiX-QtK.cjs} +17 -4
- package/dist/VitestTransactionIsolator-DyiX-QtK.cjs.map +1 -0
- package/dist/{VitestTransactionIsolator-CSroc7Df.d.cts → VitestTransactionIsolator-glcxyS_R.d.cts} +20 -4
- package/dist/VitestTransactionIsolator-glcxyS_R.d.cts.map +1 -0
- package/dist/VitestTransactionIsolator.cjs +1 -1
- package/dist/VitestTransactionIsolator.d.cts +2 -2
- package/dist/VitestTransactionIsolator.d.mts +2 -2
- package/dist/VitestTransactionIsolator.mjs +1 -1
- package/dist/better-auth.d.cts +2 -2
- package/dist/better-auth.d.mts +2 -2
- package/dist/{directory-DGOcVlKD.d.cts → directory-Bpz5c5pj.d.cts} +3 -3
- package/dist/{directory-DGOcVlKD.d.cts.map → directory-Bpz5c5pj.d.cts.map} +1 -1
- package/dist/{faker-BcjUfHxx.d.mts → faker-DHh7xs4u.d.mts} +3 -3
- package/dist/{faker-BcjUfHxx.d.mts.map → faker-DHh7xs4u.d.mts.map} +1 -1
- package/dist/{faker-zVCm31nU.d.cts → faker-Dg3trU4a.d.cts} +3 -3
- package/dist/{faker-zVCm31nU.d.cts.map → faker-Dg3trU4a.d.cts.map} +1 -1
- package/dist/faker.d.cts +1 -1
- package/dist/faker.d.mts +1 -1
- package/dist/kysely.cjs +2 -2
- package/dist/kysely.d.cts +5 -5
- package/dist/kysely.d.mts +5 -5
- package/dist/kysely.mjs +2 -2
- package/dist/objection.cjs +2 -2
- package/dist/objection.d.cts +5 -5
- package/dist/objection.d.mts +5 -5
- package/dist/objection.mjs +2 -2
- package/dist/os/directory.d.cts +1 -1
- package/dist/os/index.d.cts +1 -1
- package/dist/requestContext.cjs +1 -1
- package/dist/requestContext.d.cts +1 -1
- package/dist/requestContext.d.mts +1 -1
- package/dist/requestContext.mjs +1 -1
- package/package.json +10 -7
- package/CHANGELOG.md +0 -151
- package/dist/VitestKyselyTransactionIsolator-0CqOsuc9.cjs.map +0 -1
- package/dist/VitestKyselyTransactionIsolator-CduJlHoT.d.cts.map +0 -1
- package/dist/VitestKyselyTransactionIsolator-CfSMOFlN.mjs.map +0 -1
- package/dist/VitestKyselyTransactionIsolator-Cswnnj0k.d.mts.map +0 -1
- package/dist/VitestTransactionIsolator-BNWJqh9f.d.mts.map +0 -1
- package/dist/VitestTransactionIsolator-CSroc7Df.d.cts.map +0 -1
- package/dist/VitestTransactionIsolator-CtZaOUjH.cjs.map +0 -1
- package/dist/VitestTransactionIsolator-D6ZxLWys.mjs.map +0 -1
- package/src/Factory.ts +0 -174
- package/src/KyselyFactory.ts +0 -391
- package/src/ObjectionFactory.ts +0 -412
- package/src/PostgresKyselyMigrator.ts +0 -104
- package/src/PostgresMigrator.ts +0 -193
- package/src/PostgresObjectionMigrator.ts +0 -138
- package/src/VitestKyselyTransactionIsolator.ts +0 -72
- package/src/VitestObjectionTransactionIsolator.ts +0 -75
- package/src/VitestTransactionIsolator.ts +0 -348
- package/src/__tests__/Factory.spec.ts +0 -178
- package/src/__tests__/KyselyFactory.spec.ts +0 -458
- package/src/__tests__/ObjectionFactory.spec.ts +0 -586
- package/src/__tests__/PostgresKyselyMigrator.spec.ts +0 -794
- package/src/__tests__/PostgresMigrator.spec.ts +0 -471
- package/src/__tests__/PostgresObjectionMigrator.spec.ts +0 -634
- package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +0 -138
- package/src/__tests__/benchmark.spec.ts +0 -140
- package/src/__tests__/better-auth.spec.ts +0 -21
- package/src/__tests__/faker.spec.ts +0 -231
- package/src/__tests__/initScript.spec.ts +0 -332
- package/src/__tests__/integration.spec.ts +0 -610
- package/src/__tests__/requestContext.spec.ts +0 -113
- package/src/__tests__/utilities.spec.ts +0 -211
- package/src/aws.ts +0 -131
- package/src/benchmark.ts +0 -48
- package/src/better-auth.ts +0 -310
- package/src/faker.ts +0 -349
- package/src/helpers.ts +0 -45
- package/src/initScript.ts +0 -122
- package/src/kysely.ts +0 -166
- package/src/logger.ts +0 -18
- package/src/objection.ts +0 -157
- package/src/os/directory.ts +0 -26
- package/src/os/index.ts +0 -1
- package/src/requestContext.ts +0 -119
- package/src/timer.ts +0 -3
- package/test/globalSetup.ts +0 -54
- package/test/helpers.ts +0 -268
- package/test/migrations/1749664623372_user.ts +0 -22
- package/tsconfig.json +0 -9
- 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
|
-
}
|
package/src/better-auth.ts
DELETED
|
@@ -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
|
-
};
|