@syncular/testkit 0.0.6-85 → 0.0.6-89
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/http-fixtures.d.ts.map +1 -1
- package/dist/http-fixtures.js +83 -26
- package/dist/http-fixtures.js.map +1 -1
- package/package.json +12 -12
- package/src/http-fixtures.ts +109 -29
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-fixtures.d.ts","sourceRoot":"","sources":["../src/http-fixtures.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"http-fixtures.d.ts","sourceRoot":"","sources":["../src/http-fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAC5B,mBAAmB,EAEnB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAIxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,KAAK,uBAAuB,EAE7B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,iBAAiB,CAAC,EAAE,SAAS,UAAU;IACtD,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,EAAE,iBAAiB,CAAC;IAC3B,GAAG,EAAE,IAAI,CAAC;IACV,UAAU,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,8BAA8B,CAAC,EAAE,SAAS,UAAU;IACnE,aAAa,EAAE,iBAAiB,CAAC;IACjC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC;IACnC,YAAY,EAAE,uBAAuB,CACnC,EAAE,EACF;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CACpB,CAAC,cAAc,CAAC,CAAC;IAClB,IAAI,CAAC,EAAE,uBAAuB,CAAC,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB,CAAC,EAAE,SAAS,YAAY;IACxD,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACf,SAAS,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,uBAAuB,CAAC,EAAE,CAAC,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,CACP,IAAI,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAChD,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,IAAI,EAAE,CACJ,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,SAAS,CAAC,KACxD,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,IAAI,EAAE,CACJ,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,SAAS,CAAC,KACvD,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,QAAQ,EAAE,CACR,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC,KACnD,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,8BAA8B,CAAC,EAAE,SAAS,YAAY;IACrE,aAAa,EAAE,iBAAiB,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,uBAAuB,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAClE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAqDD,wBAAsB,uBAAuB,CAAC,EAAE,SAAS,UAAU,EACjE,OAAO,EAAE,8BAA8B,CAAC,EAAE,CAAC,GAC1C,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAuFhC;AAED,wBAAsB,uBAAuB,CAAC,EAAE,SAAS,YAAY,EACnE,OAAO,EAAE,8BAA8B,CAAC,EAAE,CAAC,GAC1C,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAoEhC"}
|
package/dist/http-fixtures.js
CHANGED
|
@@ -9,24 +9,67 @@ import { createSyncRoutes, } from '@syncular/server-hono';
|
|
|
9
9
|
import { createHttpTransport } from '@syncular/transport-http';
|
|
10
10
|
import { Hono } from 'hono';
|
|
11
11
|
import { createNodeHonoServer } from './hono-node-server.js';
|
|
12
|
+
const PGLITE_INIT_ATTEMPTS = 3;
|
|
13
|
+
function isTransientPgliteInitError(error) {
|
|
14
|
+
return (error.message.includes('access to a null reference') ||
|
|
15
|
+
error.message.includes('_pgl_initdb'));
|
|
16
|
+
}
|
|
17
|
+
function isServerNotRunningError(error) {
|
|
18
|
+
return (error !== null && 'code' in error && error.code === 'ERR_SERVER_NOT_RUNNING');
|
|
19
|
+
}
|
|
20
|
+
async function delay(ms) {
|
|
21
|
+
await new Promise((resolve) => {
|
|
22
|
+
setTimeout(resolve, ms);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async function withPgliteInitRetry(useRetries, create) {
|
|
26
|
+
const maxAttempts = useRetries ? PGLITE_INIT_ATTEMPTS : 1;
|
|
27
|
+
let lastError = null;
|
|
28
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
29
|
+
try {
|
|
30
|
+
return await create();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
const candidate = error instanceof Error ? error : new Error(String(error));
|
|
34
|
+
lastError = candidate;
|
|
35
|
+
const isRetryable = useRetries &&
|
|
36
|
+
attempt < maxAttempts &&
|
|
37
|
+
isTransientPgliteInitError(candidate);
|
|
38
|
+
if (!isRetryable) {
|
|
39
|
+
throw candidate;
|
|
40
|
+
}
|
|
41
|
+
await delay(25 * attempt);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
throw lastError ?? new Error('PGLite initialization failed');
|
|
45
|
+
}
|
|
12
46
|
export async function createHttpServerFixture(options) {
|
|
13
|
-
const db = options.serverDialect === 'pglite'
|
|
14
|
-
? createDatabase({
|
|
15
|
-
dialect: createPgliteDialect(),
|
|
16
|
-
family: 'postgres',
|
|
17
|
-
})
|
|
18
|
-
: createDatabase({
|
|
19
|
-
dialect: createBunSqliteDialect({ path: ':memory:' }),
|
|
20
|
-
family: 'sqlite',
|
|
21
|
-
});
|
|
22
47
|
const dialect = options.serverDialect === 'pglite'
|
|
23
48
|
? createPostgresServerDialect()
|
|
24
49
|
: createSqliteServerDialect();
|
|
25
|
-
await
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
const db = await withPgliteInitRetry(options.serverDialect === 'pglite', async () => {
|
|
51
|
+
const candidateDb = options.serverDialect === 'pglite'
|
|
52
|
+
? createDatabase({
|
|
53
|
+
dialect: createPgliteDialect(),
|
|
54
|
+
family: 'postgres',
|
|
55
|
+
})
|
|
56
|
+
: createDatabase({
|
|
57
|
+
dialect: createBunSqliteDialect({ path: ':memory:' }),
|
|
58
|
+
family: 'sqlite',
|
|
59
|
+
});
|
|
60
|
+
try {
|
|
61
|
+
await ensureSyncSchema(candidateDb, dialect);
|
|
62
|
+
if (dialect.ensureConsoleSchema) {
|
|
63
|
+
await dialect.ensureConsoleSchema(candidateDb);
|
|
64
|
+
}
|
|
65
|
+
await options.createTables(candidateDb);
|
|
66
|
+
return candidateDb;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
await candidateDb.destroy();
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
30
73
|
const app = new Hono();
|
|
31
74
|
const routePath = options.routePath ?? '/sync';
|
|
32
75
|
const syncRoutes = createSyncRoutes({
|
|
@@ -48,6 +91,7 @@ export async function createHttpServerFixture(options) {
|
|
|
48
91
|
});
|
|
49
92
|
const address = httpServer.address();
|
|
50
93
|
const port = typeof address === 'object' && address ? address.port : 0;
|
|
94
|
+
let destroyed = false;
|
|
51
95
|
return {
|
|
52
96
|
db,
|
|
53
97
|
dialect,
|
|
@@ -55,9 +99,13 @@ export async function createHttpServerFixture(options) {
|
|
|
55
99
|
httpServer,
|
|
56
100
|
baseUrl: `http://localhost:${port}`,
|
|
57
101
|
destroy: async () => {
|
|
102
|
+
if (destroyed) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
destroyed = true;
|
|
58
106
|
await new Promise((resolve, reject) => {
|
|
59
107
|
httpServer.close((err) => {
|
|
60
|
-
if (err) {
|
|
108
|
+
if (err && !isServerNotRunningError(err)) {
|
|
61
109
|
reject(err);
|
|
62
110
|
return;
|
|
63
111
|
}
|
|
@@ -69,17 +117,26 @@ export async function createHttpServerFixture(options) {
|
|
|
69
117
|
};
|
|
70
118
|
}
|
|
71
119
|
export async function createHttpClientFixture(options) {
|
|
72
|
-
const db = options.clientDialect === 'pglite'
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
120
|
+
const db = await withPgliteInitRetry(options.clientDialect === 'pglite', async () => {
|
|
121
|
+
const candidateDb = options.clientDialect === 'pglite'
|
|
122
|
+
? createDatabase({
|
|
123
|
+
dialect: createPgliteDialect(),
|
|
124
|
+
family: 'postgres',
|
|
125
|
+
})
|
|
126
|
+
: createDatabase({
|
|
127
|
+
dialect: createBunSqliteDialect({ path: ':memory:' }),
|
|
128
|
+
family: 'sqlite',
|
|
129
|
+
});
|
|
130
|
+
try {
|
|
131
|
+
await ensureClientSyncSchema(candidateDb);
|
|
132
|
+
await options.createTables(candidateDb);
|
|
133
|
+
return candidateDb;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
await candidateDb.destroy();
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
83
140
|
const handlers = [];
|
|
84
141
|
options.registerHandlers(handlers);
|
|
85
142
|
const transport = createHttpTransport({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-fixtures.js","sourceRoot":"","sources":["../src/http-fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,mBAAmB,EACnB,sBAAsB,EAQtB,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAsB,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EACL,gBAAgB,GAIjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAEL,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AA8D1D,MAAM,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"http-fixtures.js","sourceRoot":"","sources":["../src/http-fixtures.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncular/testkit",
|
|
3
|
-
"version": "0.0.6-
|
|
3
|
+
"version": "0.0.6-89",
|
|
4
4
|
"description": "Testing fixtures and utilities for Syncular",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Benjamin Kniffler",
|
|
@@ -41,17 +41,17 @@
|
|
|
41
41
|
"release": "bunx syncular-publish"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@syncular/client": "0.0.6-
|
|
45
|
-
"@syncular/core": "0.0.6-
|
|
46
|
-
"@syncular/dialect-bun-sqlite": "0.0.6-
|
|
47
|
-
"@syncular/dialect-libsql": "0.0.6-
|
|
48
|
-
"@syncular/dialect-pglite": "0.0.6-
|
|
49
|
-
"@syncular/dialect-sqlite3": "0.0.6-
|
|
50
|
-
"@syncular/server": "0.0.6-
|
|
51
|
-
"@syncular/server-dialect-postgres": "0.0.6-
|
|
52
|
-
"@syncular/server-dialect-sqlite": "0.0.6-
|
|
53
|
-
"@syncular/server-hono": "0.0.6-
|
|
54
|
-
"@syncular/transport-http": "0.0.6-
|
|
44
|
+
"@syncular/client": "0.0.6-89",
|
|
45
|
+
"@syncular/core": "0.0.6-89",
|
|
46
|
+
"@syncular/dialect-bun-sqlite": "0.0.6-89",
|
|
47
|
+
"@syncular/dialect-libsql": "0.0.6-89",
|
|
48
|
+
"@syncular/dialect-pglite": "0.0.6-89",
|
|
49
|
+
"@syncular/dialect-sqlite3": "0.0.6-89",
|
|
50
|
+
"@syncular/server": "0.0.6-89",
|
|
51
|
+
"@syncular/server-dialect-postgres": "0.0.6-89",
|
|
52
|
+
"@syncular/server-dialect-sqlite": "0.0.6-89",
|
|
53
|
+
"@syncular/server-hono": "0.0.6-89",
|
|
54
|
+
"@syncular/transport-http": "0.0.6-89",
|
|
55
55
|
"hono": "^4.12.2"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
package/src/http-fixtures.ts
CHANGED
|
@@ -93,30 +93,92 @@ export interface CreateHttpClientFixtureOptions<DB extends SyncClientDb> {
|
|
|
93
93
|
getHeaders?: () => Record<string, string>;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
const PGLITE_INIT_ATTEMPTS = 3;
|
|
97
|
+
|
|
98
|
+
function isTransientPgliteInitError(error: Error): boolean {
|
|
99
|
+
return (
|
|
100
|
+
error.message.includes('access to a null reference') ||
|
|
101
|
+
error.message.includes('_pgl_initdb')
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function isServerNotRunningError(error: Error | null): boolean {
|
|
106
|
+
return (
|
|
107
|
+
error !== null && 'code' in error && error.code === 'ERR_SERVER_NOT_RUNNING'
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function delay(ms: number): Promise<void> {
|
|
112
|
+
await new Promise<void>((resolve) => {
|
|
113
|
+
setTimeout(resolve, ms);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function withPgliteInitRetry<T>(
|
|
118
|
+
useRetries: boolean,
|
|
119
|
+
create: () => Promise<T>
|
|
120
|
+
): Promise<T> {
|
|
121
|
+
const maxAttempts = useRetries ? PGLITE_INIT_ATTEMPTS : 1;
|
|
122
|
+
let lastError: Error | null = null;
|
|
123
|
+
|
|
124
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
125
|
+
try {
|
|
126
|
+
return await create();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
const candidate =
|
|
129
|
+
error instanceof Error ? error : new Error(String(error));
|
|
130
|
+
lastError = candidate;
|
|
131
|
+
|
|
132
|
+
const isRetryable =
|
|
133
|
+
useRetries &&
|
|
134
|
+
attempt < maxAttempts &&
|
|
135
|
+
isTransientPgliteInitError(candidate);
|
|
136
|
+
if (!isRetryable) {
|
|
137
|
+
throw candidate;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
await delay(25 * attempt);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
throw lastError ?? new Error('PGLite initialization failed');
|
|
145
|
+
}
|
|
146
|
+
|
|
96
147
|
export async function createHttpServerFixture<DB extends SyncCoreDb>(
|
|
97
148
|
options: CreateHttpServerFixtureOptions<DB>
|
|
98
149
|
): Promise<HttpServerFixture<DB>> {
|
|
99
|
-
const db =
|
|
100
|
-
options.serverDialect === 'pglite'
|
|
101
|
-
? createDatabase<DB>({
|
|
102
|
-
dialect: createPgliteDialect(),
|
|
103
|
-
family: 'postgres',
|
|
104
|
-
})
|
|
105
|
-
: createDatabase<DB>({
|
|
106
|
-
dialect: createBunSqliteDialect({ path: ':memory:' }),
|
|
107
|
-
family: 'sqlite',
|
|
108
|
-
});
|
|
109
|
-
|
|
110
150
|
const dialect =
|
|
111
151
|
options.serverDialect === 'pglite'
|
|
112
152
|
? createPostgresServerDialect()
|
|
113
153
|
: createSqliteServerDialect();
|
|
114
154
|
|
|
115
|
-
await
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
155
|
+
const db = await withPgliteInitRetry(
|
|
156
|
+
options.serverDialect === 'pglite',
|
|
157
|
+
async () => {
|
|
158
|
+
const candidateDb =
|
|
159
|
+
options.serverDialect === 'pglite'
|
|
160
|
+
? createDatabase<DB>({
|
|
161
|
+
dialect: createPgliteDialect(),
|
|
162
|
+
family: 'postgres',
|
|
163
|
+
})
|
|
164
|
+
: createDatabase<DB>({
|
|
165
|
+
dialect: createBunSqliteDialect({ path: ':memory:' }),
|
|
166
|
+
family: 'sqlite',
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await ensureSyncSchema(candidateDb, dialect);
|
|
171
|
+
if (dialect.ensureConsoleSchema) {
|
|
172
|
+
await dialect.ensureConsoleSchema(candidateDb);
|
|
173
|
+
}
|
|
174
|
+
await options.createTables(candidateDb);
|
|
175
|
+
return candidateDb;
|
|
176
|
+
} catch (error) {
|
|
177
|
+
await candidateDb.destroy();
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
);
|
|
120
182
|
|
|
121
183
|
const app = new Hono();
|
|
122
184
|
const routePath = options.routePath ?? '/sync';
|
|
@@ -145,6 +207,8 @@ export async function createHttpServerFixture<DB extends SyncCoreDb>(
|
|
|
145
207
|
const address = httpServer.address();
|
|
146
208
|
const port = typeof address === 'object' && address ? address.port : 0;
|
|
147
209
|
|
|
210
|
+
let destroyed = false;
|
|
211
|
+
|
|
148
212
|
return {
|
|
149
213
|
db,
|
|
150
214
|
dialect,
|
|
@@ -152,9 +216,14 @@ export async function createHttpServerFixture<DB extends SyncCoreDb>(
|
|
|
152
216
|
httpServer,
|
|
153
217
|
baseUrl: `http://localhost:${port}`,
|
|
154
218
|
destroy: async () => {
|
|
219
|
+
if (destroyed) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
destroyed = true;
|
|
223
|
+
|
|
155
224
|
await new Promise<void>((resolve, reject) => {
|
|
156
225
|
httpServer.close((err) => {
|
|
157
|
-
if (err) {
|
|
226
|
+
if (err && !isServerNotRunningError(err)) {
|
|
158
227
|
reject(err);
|
|
159
228
|
return;
|
|
160
229
|
}
|
|
@@ -169,19 +238,30 @@ export async function createHttpServerFixture<DB extends SyncCoreDb>(
|
|
|
169
238
|
export async function createHttpClientFixture<DB extends SyncClientDb>(
|
|
170
239
|
options: CreateHttpClientFixtureOptions<DB>
|
|
171
240
|
): Promise<HttpClientFixture<DB>> {
|
|
172
|
-
const db =
|
|
173
|
-
options.clientDialect === 'pglite'
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
241
|
+
const db = await withPgliteInitRetry(
|
|
242
|
+
options.clientDialect === 'pglite',
|
|
243
|
+
async () => {
|
|
244
|
+
const candidateDb =
|
|
245
|
+
options.clientDialect === 'pglite'
|
|
246
|
+
? createDatabase<DB>({
|
|
247
|
+
dialect: createPgliteDialect(),
|
|
248
|
+
family: 'postgres',
|
|
249
|
+
})
|
|
250
|
+
: createDatabase<DB>({
|
|
251
|
+
dialect: createBunSqliteDialect({ path: ':memory:' }),
|
|
252
|
+
family: 'sqlite',
|
|
253
|
+
});
|
|
182
254
|
|
|
183
|
-
|
|
184
|
-
|
|
255
|
+
try {
|
|
256
|
+
await ensureClientSyncSchema(candidateDb);
|
|
257
|
+
await options.createTables(candidateDb);
|
|
258
|
+
return candidateDb;
|
|
259
|
+
} catch (error) {
|
|
260
|
+
await candidateDb.destroy();
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
);
|
|
185
265
|
|
|
186
266
|
const handlers: ClientHandlerCollection<DB> = [];
|
|
187
267
|
options.registerHandlers(handlers);
|