@drizzle-adapter/d1 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/6e148680931b1bfcb993e0463aced3b0a6d6cf50af24dea2dcc2c3b2e9ae9e3b.sqlite +0 -0
- package/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/6e148680931b1bfcb993e0463aced3b0a6d6cf50af24dea2dcc2c3b2e9ae9e3b.sqlite-shm +0 -0
- package/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/6e148680931b1bfcb993e0463aced3b0a6d6cf50af24dea2dcc2c3b2e9ae9e3b.sqlite-wal +0 -0
- package/LICENSE +674 -0
- package/README.md +260 -0
- package/dist/Adapter/D1DrizzleAdapter.d.ts +32 -0
- package/dist/Adapter/D1DrizzleAdapter.js +41 -0
- package/dist/Adapter/D1DrizzleConnection.d.ts +29 -0
- package/dist/Adapter/D1DrizzleConnection.js +39 -0
- package/dist/Adapter/D1DrizzleDataTypes.d.ts +3 -0
- package/dist/Adapter/D1DrizzleDataTypes.js +3 -0
- package/dist/Adapter/index.d.ts +2 -0
- package/dist/Adapter/index.js +2 -0
- package/dist/Factory/D1DrizzleAdapterFactory.d.ts +12 -0
- package/dist/Factory/D1DrizzleAdapterFactory.js +12 -0
- package/dist/Factory/index.d.ts +1 -0
- package/dist/Factory/index.js +1 -0
- package/dist/Interface/D1DrizzleClientInterface.d.ts +13 -0
- package/dist/Interface/D1DrizzleClientInterface.js +1 -0
- package/dist/Interface/index.d.ts +1 -0
- package/dist/Interface/index.js +1 -0
- package/dist/Type/Types.d.ts +5 -0
- package/dist/Type/Types.js +1 -0
- package/dist/Type/index.d.ts +1 -0
- package/dist/Type/index.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/eslint.config.mjs +6 -0
- package/package.json +34 -0
- package/src/Adapter/D1DrizzleAdapter.ts +50 -0
- package/src/Adapter/D1DrizzleConnection.ts +53 -0
- package/src/Adapter/D1DrizzleDataTypes.ts +3 -0
- package/src/Adapter/index.ts +2 -0
- package/src/Factory/D1DrizzleAdapterFactory.ts +17 -0
- package/src/Factory/index.ts +1 -0
- package/src/Interface/D1DrizzleClientInterface.ts +15 -0
- package/src/Interface/index.ts +1 -0
- package/src/Type/Types.ts +7 -0
- package/src/Type/index.ts +1 -0
- package/src/index.ts +8 -0
- package/tests/Adapter/D1DrizzleAdapter.test.ts +36 -0
- package/tests/Adapter/D1DrizzleConnection.test.ts +40 -0
- package/tests/Factory/D1DrizzleAdapterFactory.test.ts +41 -0
- package/tests/Integration/D1DrizzleAdapter.integration.test.ts +101 -0
- package/tests/Integration/D1DrizzleMigrations.integration.test.ts +100 -0
- package/tests/test-runner.ts +51 -0
- package/tests/worker.ts +334 -0
- package/tsconfig.eslint.json +4 -0
- package/tsconfig.json +38 -0
- package/vitest.config.ts +15 -0
- package/wrangler.toml +8 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TypeD1DatabaseConfig } from '../Type/Types';
|
|
2
|
+
import { D1DrizzleAdapter } from '../Adapter/D1DrizzleAdapter';
|
|
3
|
+
import type { DrizzleAdapterFactoryInterface } from '@drizzle-adapter/core';
|
|
4
|
+
|
|
5
|
+
export class D1DrizzleAdapterFactory implements DrizzleAdapterFactoryInterface
|
|
6
|
+
{
|
|
7
|
+
/**
|
|
8
|
+
* Returns a adapter.
|
|
9
|
+
*
|
|
10
|
+
* @param {TypeD1DatabaseConfig} databaseConfig
|
|
11
|
+
* @returns {Promise<D1DrizzleAdapter>}
|
|
12
|
+
*/
|
|
13
|
+
public async create(databaseConfig: TypeD1DatabaseConfig): Promise<D1DrizzleAdapter>
|
|
14
|
+
{
|
|
15
|
+
return new D1DrizzleAdapter(databaseConfig.DATABASE);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './D1DrizzleAdapterFactory';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AnyD1Database } from 'drizzle-orm/d1';
|
|
2
|
+
import type { DrizzleClientInterface } from '@drizzle-adapter/core';
|
|
3
|
+
|
|
4
|
+
export interface D1DrizzleClientInterface extends DrizzleClientInterface
|
|
5
|
+
{
|
|
6
|
+
execute(...args: any[]): ReturnType<AnyD1Database['run']>;
|
|
7
|
+
$with(...args: any[]): ReturnType<AnyD1Database['$with']>;
|
|
8
|
+
$count(...args: any[]): ReturnType<AnyD1Database['$count']>;
|
|
9
|
+
with(...args: any[]): ReturnType<AnyD1Database['with']>;
|
|
10
|
+
select(...args: any[]): ReturnType<AnyD1Database['select']>;
|
|
11
|
+
selectDistinct(...args: any[]): ReturnType<AnyD1Database['selectDistinct']>;
|
|
12
|
+
update(...args: any[]): ReturnType<AnyD1Database['update']>;
|
|
13
|
+
insert(...args: any[]): ReturnType<AnyD1Database['insert']>;
|
|
14
|
+
transaction(...args: any[]): ReturnType<AnyD1Database['transaction']>;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './D1DrizzleClientInterface';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Types';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './Adapter';
|
|
2
|
+
export * from './Factory';
|
|
3
|
+
export * from './Interface';
|
|
4
|
+
export * from './Type';
|
|
5
|
+
|
|
6
|
+
// default export so that core factory can use it directly
|
|
7
|
+
import { D1DrizzleAdapterFactory } from './Factory';
|
|
8
|
+
export default D1DrizzleAdapterFactory;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { D1DrizzleAdapter } from '../../src/Adapter/D1DrizzleAdapter';
|
|
3
|
+
import { D1DrizzleConnection } from '../../src/Adapter/D1DrizzleConnection';
|
|
4
|
+
import { SqliteCoreDrizzleDataTypes } from '@drizzle-adapter/sqlite-core';
|
|
5
|
+
import type { D1Database } from '@cloudflare/workers-types';
|
|
6
|
+
|
|
7
|
+
describe('D1DrizzleAdapter', () => {
|
|
8
|
+
const mockD1Database: D1Database = {
|
|
9
|
+
prepare: vi.fn(),
|
|
10
|
+
batch: vi.fn(),
|
|
11
|
+
exec: vi.fn(),
|
|
12
|
+
dump: vi.fn()
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
it('should create an instance with a D1 database', () => {
|
|
16
|
+
const adapter = new D1DrizzleAdapter(mockD1Database);
|
|
17
|
+
expect(adapter).toBeInstanceOf(D1DrizzleAdapter);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return sqlite as dialect', () => {
|
|
21
|
+
const adapter = new D1DrizzleAdapter(mockD1Database);
|
|
22
|
+
expect(adapter.getDialect()).toBe('sqlite');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return SqliteCoreDrizzleDataTypes instance', () => {
|
|
26
|
+
const adapter = new D1DrizzleAdapter(mockD1Database);
|
|
27
|
+
const dataTypes = adapter.getDataTypes();
|
|
28
|
+
expect(dataTypes).toBeInstanceOf(SqliteCoreDrizzleDataTypes);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should return D1DrizzleConnection instance with the provided database', () => {
|
|
32
|
+
const adapter = new D1DrizzleAdapter(mockD1Database);
|
|
33
|
+
const connection = adapter.getConnection();
|
|
34
|
+
expect(connection).toBeInstanceOf(D1DrizzleConnection);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { D1DrizzleConnection } from '../../src/Adapter/D1DrizzleConnection';
|
|
3
|
+
import { drizzle } from 'drizzle-orm/d1';
|
|
4
|
+
import type { D1Database } from '@cloudflare/workers-types';
|
|
5
|
+
|
|
6
|
+
// Mock drizzle-orm/d1
|
|
7
|
+
vi.mock('drizzle-orm/d1', () => ({
|
|
8
|
+
drizzle: vi.fn().mockReturnValue({ mockedClient: true })
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
describe('D1DrizzleConnection', () => {
|
|
12
|
+
const mockD1Database: D1Database = {
|
|
13
|
+
prepare: vi.fn(),
|
|
14
|
+
batch: vi.fn(),
|
|
15
|
+
exec: vi.fn(),
|
|
16
|
+
dump: vi.fn()
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
it('should create an instance with a D1 database and initialize drizzle', () => {
|
|
20
|
+
const connection = new D1DrizzleConnection(mockD1Database);
|
|
21
|
+
expect(connection).toBeInstanceOf(D1DrizzleConnection);
|
|
22
|
+
expect(drizzle).toHaveBeenCalledWith(mockD1Database);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should not perform any operation on connect (serverless)', async () => {
|
|
26
|
+
const connection = new D1DrizzleConnection(mockD1Database);
|
|
27
|
+
await expect(connection.connect()).resolves.toBeUndefined();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should not perform any operation on disconnect (serverless)', async () => {
|
|
31
|
+
const connection = new D1DrizzleConnection(mockD1Database);
|
|
32
|
+
await expect(connection.disconnect()).resolves.toBeUndefined();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return the query client', async () => {
|
|
36
|
+
const connection = new D1DrizzleConnection(mockD1Database);
|
|
37
|
+
const client = await connection.getClient();
|
|
38
|
+
expect(client).toEqual({ mockedClient: true });
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { D1DrizzleAdapterFactory } from '../../src/Factory';
|
|
3
|
+
import { D1DrizzleAdapter } from '../../src/Adapter';
|
|
4
|
+
import { drizzle } from 'drizzle-orm/d1';
|
|
5
|
+
import type { D1Database } from '@cloudflare/workers-types';
|
|
6
|
+
import type { TypeD1DatabaseConfig } from '../../src/Type';
|
|
7
|
+
|
|
8
|
+
// Mock drizzle-orm/d1
|
|
9
|
+
vi.mock('drizzle-orm/d1', () => ({
|
|
10
|
+
drizzle: vi.fn().mockReturnValue({ mockedQueryBuilder: true })
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe('D1DrizzleAdapterFactory', () => {
|
|
14
|
+
const mockD1Database: D1Database = {
|
|
15
|
+
prepare: vi.fn(),
|
|
16
|
+
batch: vi.fn(),
|
|
17
|
+
exec: vi.fn(),
|
|
18
|
+
dump: vi.fn()
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const mockDatabaseConfig: TypeD1DatabaseConfig = {
|
|
22
|
+
DATABASE_DRIVER: 'd1',
|
|
23
|
+
DATABASE_URL: mockD1Database
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
vi.clearAllMocks();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should be instantiable', () => {
|
|
31
|
+
const factory = new D1DrizzleAdapterFactory();
|
|
32
|
+
expect(factory).toBeInstanceOf(D1DrizzleAdapterFactory);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should create a D1DrizzleAdapter instance', async () => {
|
|
36
|
+
const factory = new D1DrizzleAdapterFactory();
|
|
37
|
+
const adapter = await factory.create(mockDatabaseConfig);
|
|
38
|
+
|
|
39
|
+
expect(adapter).toBeInstanceOf(D1DrizzleAdapter);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { getWorker, isReady, getWorkerUrl } from '../test-runner';
|
|
3
|
+
|
|
4
|
+
interface User {
|
|
5
|
+
id: number;
|
|
6
|
+
name: string;
|
|
7
|
+
email: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface CreateRecordResponse {
|
|
11
|
+
success: boolean;
|
|
12
|
+
result: User;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UpdateRecordResponse {
|
|
16
|
+
success: boolean;
|
|
17
|
+
result: User;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface SelectRecordsResponse {
|
|
21
|
+
success: boolean;
|
|
22
|
+
allUsers: User[];
|
|
23
|
+
specificUser: User;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('D1DrizzleAdapter Integration Tests', () => {
|
|
27
|
+
it('should create a new record', async () => {
|
|
28
|
+
if (!isReady()) {
|
|
29
|
+
console.log('Skipping test: worker not ready');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const worker = getWorker();
|
|
34
|
+
const workerUrl = getWorkerUrl();
|
|
35
|
+
if (!worker || !workerUrl) {
|
|
36
|
+
throw new Error('Worker not available');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const response = await worker.fetch(`${workerUrl}/test/create-record`);
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
const error = await response.text();
|
|
42
|
+
console.error('Error response:', error);
|
|
43
|
+
}
|
|
44
|
+
expect(response.ok).toBe(true);
|
|
45
|
+
|
|
46
|
+
const data = await response.json() as CreateRecordResponse;
|
|
47
|
+
expect(data.success).toBe(true);
|
|
48
|
+
expect(data.result.name).toBe('John Doe');
|
|
49
|
+
expect(data.result.email).toBe('john@example.com');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should update an existing record', async () => {
|
|
53
|
+
if (!isReady()) {
|
|
54
|
+
console.log('Skipping test: worker not ready');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const worker = getWorker();
|
|
59
|
+
const workerUrl = getWorkerUrl();
|
|
60
|
+
if (!worker || !workerUrl) {
|
|
61
|
+
throw new Error('Worker not available');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const response = await worker.fetch(`${workerUrl}/test/update-record`);
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
const error = await response.text();
|
|
67
|
+
console.error('Error response:', error);
|
|
68
|
+
}
|
|
69
|
+
expect(response.ok).toBe(true);
|
|
70
|
+
|
|
71
|
+
const data = await response.json() as UpdateRecordResponse;
|
|
72
|
+
expect(data.success).toBe(true);
|
|
73
|
+
expect(data.result.name).toBe('Jane Smith');
|
|
74
|
+
expect(data.result.email).toBe('jane@example.com');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should select records', async () => {
|
|
78
|
+
if (!isReady()) {
|
|
79
|
+
console.log('Skipping test: worker not ready');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const worker = getWorker();
|
|
84
|
+
const workerUrl = getWorkerUrl();
|
|
85
|
+
if (!worker || !workerUrl) {
|
|
86
|
+
throw new Error('Worker not available');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const response = await worker.fetch(`${workerUrl}/test/select-records`);
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
const error = await response.text();
|
|
92
|
+
console.error('Error response:', error);
|
|
93
|
+
}
|
|
94
|
+
expect(response.ok).toBe(true);
|
|
95
|
+
|
|
96
|
+
const data = await response.json() as SelectRecordsResponse;
|
|
97
|
+
expect(data.success).toBe(true);
|
|
98
|
+
expect(data.allUsers.length).toBeGreaterThanOrEqual(2);
|
|
99
|
+
expect(data.specificUser.name).toBe('User 1');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { getWorker, isReady, getWorkerUrl } from '../test-runner';
|
|
3
|
+
|
|
4
|
+
interface EventAction {
|
|
5
|
+
id: number;
|
|
6
|
+
createdAt: number;
|
|
7
|
+
updatedAt: number;
|
|
8
|
+
action: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface MigrationsResponse {
|
|
12
|
+
success: boolean;
|
|
13
|
+
initial: EventAction;
|
|
14
|
+
updated: EventAction;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ConstraintsResponse {
|
|
18
|
+
success: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface TextTypeResponse {
|
|
22
|
+
success: boolean;
|
|
23
|
+
result: EventAction;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('D1Drizzle Migrations Integration Tests', () => {
|
|
27
|
+
it('should create a table with migrations', async () => {
|
|
28
|
+
if (!isReady()) {
|
|
29
|
+
console.log('Skipping test: worker not ready');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const worker = getWorker();
|
|
34
|
+
const workerUrl = getWorkerUrl();
|
|
35
|
+
if (!worker || !workerUrl) {
|
|
36
|
+
throw new Error('Worker not available');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const response = await worker.fetch(`${workerUrl}/test/migrations`);
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
const error = await response.text();
|
|
42
|
+
console.error('Error response:', error);
|
|
43
|
+
}
|
|
44
|
+
expect(response.ok).toBe(true);
|
|
45
|
+
|
|
46
|
+
const data = await response.json() as MigrationsResponse;
|
|
47
|
+
expect(data.success).toBe(true);
|
|
48
|
+
expect(data.initial.action).toBe('TEST_ACTION');
|
|
49
|
+
expect(data.updated.action).toBe('UPDATED_ACTION');
|
|
50
|
+
expect(data.updated.updatedAt).toBeGreaterThan(data.initial.updatedAt);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should enforce NOT NULL constraints', async () => {
|
|
54
|
+
if (!isReady()) {
|
|
55
|
+
console.log('Skipping test: worker not ready');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const worker = getWorker();
|
|
60
|
+
const workerUrl = getWorkerUrl();
|
|
61
|
+
if (!worker || !workerUrl) {
|
|
62
|
+
throw new Error('Worker not available');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const response = await worker.fetch(`${workerUrl}/test/constraints`);
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const error = await response.text();
|
|
68
|
+
console.error('Error response:', error);
|
|
69
|
+
}
|
|
70
|
+
expect(response.ok).toBe(true);
|
|
71
|
+
|
|
72
|
+
const data = await response.json() as ConstraintsResponse;
|
|
73
|
+
expect(data.success).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should handle TEXT data type properly', async () => {
|
|
77
|
+
if (!isReady()) {
|
|
78
|
+
console.log('Skipping test: worker not ready');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const worker = getWorker();
|
|
83
|
+
const workerUrl = getWorkerUrl();
|
|
84
|
+
if (!worker || !workerUrl) {
|
|
85
|
+
throw new Error('Worker not available');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const response = await worker.fetch(`${workerUrl}/test/text-type`);
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
const error = await response.text();
|
|
91
|
+
console.error('Error response:', error);
|
|
92
|
+
}
|
|
93
|
+
expect(response.ok).toBe(true);
|
|
94
|
+
|
|
95
|
+
const data = await response.json() as TextTypeResponse;
|
|
96
|
+
expect(data.success).toBe(true);
|
|
97
|
+
expect(data.result.action.length).toBe(1000);
|
|
98
|
+
expect(data.result.action).toBe('A'.repeat(1000));
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { unstable_dev } from 'wrangler';
|
|
2
|
+
import type { UnstableDevWorker } from 'wrangler';
|
|
3
|
+
import { beforeAll, afterAll } from 'vitest';
|
|
4
|
+
|
|
5
|
+
let worker: UnstableDevWorker | null = null;
|
|
6
|
+
let isWorkerReady = false;
|
|
7
|
+
let workerUrl: string | null = null;
|
|
8
|
+
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
try {
|
|
11
|
+
// Start worker with D1 binding
|
|
12
|
+
worker = await unstable_dev('tests/worker.ts', {
|
|
13
|
+
experimental: { disableExperimentalWarning: true },
|
|
14
|
+
local: true
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Store worker URL
|
|
18
|
+
workerUrl = `http://${worker.address}:${worker.port}`;
|
|
19
|
+
|
|
20
|
+
// Test if worker is ready
|
|
21
|
+
const response = await worker.fetch('/__d1');
|
|
22
|
+
if (response.ok) {
|
|
23
|
+
isWorkerReady = true;
|
|
24
|
+
console.log('Worker ready');
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error('Failed to start worker:', error);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterAll(async () => {
|
|
32
|
+
if (worker) {
|
|
33
|
+
await worker.stop();
|
|
34
|
+
console.log('Worker stopped');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Export function to get worker status
|
|
39
|
+
export function isReady(): boolean {
|
|
40
|
+
return isWorkerReady;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Export function to get worker
|
|
44
|
+
export function getWorker(): UnstableDevWorker | null {
|
|
45
|
+
return worker;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Export function to get worker URL
|
|
49
|
+
export function getWorkerUrl(): string | null {
|
|
50
|
+
return workerUrl;
|
|
51
|
+
}
|