@dbos-inc/knex-datasource 3.0.8-preview → 3.0.8-preview.g493d2d1c2b
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/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -76
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/index.ts +71 -90
- package/package.json +5 -6
- package/tests/config.test.ts +1 -1
- package/tests/datasource.test.ts +41 -164
- package/tests/test-helpers.ts +2 -3
package/tests/datasource.test.ts
CHANGED
|
@@ -12,7 +12,6 @@ interface transaction_completion {
|
|
|
12
12
|
workflow_id: string;
|
|
13
13
|
function_num: number;
|
|
14
14
|
output: string | null;
|
|
15
|
-
error: string | null;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
describe('KnexDataSource', () => {
|
|
@@ -23,9 +22,9 @@ describe('KnexDataSource', () => {
|
|
|
23
22
|
const client = new Client({ ...config.connection, database: 'postgres' });
|
|
24
23
|
try {
|
|
25
24
|
await client.connect();
|
|
26
|
-
await dropDB(client, 'knex_ds_test'
|
|
27
|
-
await dropDB(client, 'knex_ds_test_dbos_sys'
|
|
28
|
-
await dropDB(client, config.connection.database
|
|
25
|
+
await dropDB(client, 'knex_ds_test');
|
|
26
|
+
await dropDB(client, 'knex_ds_test_dbos_sys');
|
|
27
|
+
await dropDB(client, config.connection.database);
|
|
29
28
|
await ensureDB(client, config.connection.database);
|
|
30
29
|
} finally {
|
|
31
30
|
await client.end();
|
|
@@ -44,19 +43,13 @@ describe('KnexDataSource', () => {
|
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
await KnexDataSource.initializeInternalSchema(config);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
afterAll(async () => {
|
|
50
|
-
await userDB.end();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
beforeEach(async () => {
|
|
54
46
|
DBOS.setConfig({ name: 'knex-ds-test' });
|
|
55
47
|
await DBOS.launch();
|
|
56
48
|
});
|
|
57
49
|
|
|
58
|
-
|
|
50
|
+
afterAll(async () => {
|
|
59
51
|
await DBOS.shutdown();
|
|
52
|
+
await userDB.end();
|
|
60
53
|
});
|
|
61
54
|
|
|
62
55
|
test('insert dataSource.register function', async () => {
|
|
@@ -65,7 +58,7 @@ describe('KnexDataSource', () => {
|
|
|
65
58
|
await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
|
|
66
59
|
const workflowID = randomUUID();
|
|
67
60
|
|
|
68
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () =>
|
|
61
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorfklowReg(user))).resolves.toEqual({
|
|
69
62
|
user,
|
|
70
63
|
greet_count: 1,
|
|
71
64
|
});
|
|
@@ -78,19 +71,7 @@ describe('KnexDataSource', () => {
|
|
|
78
71
|
expect(rows[0].workflow_id).toBe(workflowID);
|
|
79
72
|
expect(rows[0].function_num).toBe(0);
|
|
80
73
|
expect(rows[0].output).not.toBeNull();
|
|
81
|
-
expect(SuperJSON.parse(rows[0].output!)).
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('rerun insert dataSource.register function', async () => {
|
|
85
|
-
const user = 'rerunTest1';
|
|
86
|
-
|
|
87
|
-
await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
|
|
88
|
-
const workflowID = randomUUID();
|
|
89
|
-
|
|
90
|
-
const result = await DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowReg(user));
|
|
91
|
-
expect(result).toMatchObject({ user, greet_count: 1 });
|
|
92
|
-
|
|
93
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowReg(user))).resolves.toMatchObject(result);
|
|
74
|
+
expect(SuperJSON.parse(rows[0].output!)).toEqual({ user, greet_count: 1 });
|
|
94
75
|
});
|
|
95
76
|
|
|
96
77
|
test('insert dataSource.runAsTx function', async () => {
|
|
@@ -99,7 +80,7 @@ describe('KnexDataSource', () => {
|
|
|
99
80
|
await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
|
|
100
81
|
const workflowID = randomUUID();
|
|
101
82
|
|
|
102
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () =>
|
|
83
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorfklowRunTx(user))).resolves.toEqual({
|
|
103
84
|
user,
|
|
104
85
|
greet_count: 1,
|
|
105
86
|
});
|
|
@@ -112,32 +93,9 @@ describe('KnexDataSource', () => {
|
|
|
112
93
|
expect(rows[0].workflow_id).toBe(workflowID);
|
|
113
94
|
expect(rows[0].function_num).toBe(0);
|
|
114
95
|
expect(rows[0].output).not.toBeNull();
|
|
115
|
-
expect(SuperJSON.parse(rows[0].output!)).
|
|
96
|
+
expect(SuperJSON.parse(rows[0].output!)).toEqual({ user, greet_count: 1 });
|
|
116
97
|
});
|
|
117
98
|
|
|
118
|
-
test('rerun insert dataSource.runAsTx function', async () => {
|
|
119
|
-
const user = 'rerunTest2';
|
|
120
|
-
|
|
121
|
-
await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
|
|
122
|
-
const workflowID = randomUUID();
|
|
123
|
-
|
|
124
|
-
const result = await DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowRunTx(user));
|
|
125
|
-
expect(result).toMatchObject({ user, greet_count: 1 });
|
|
126
|
-
|
|
127
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowRunTx(user))).resolves.toMatchObject(
|
|
128
|
-
result,
|
|
129
|
-
);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
async function throws<R>(func: () => Promise<R>): Promise<unknown> {
|
|
133
|
-
try {
|
|
134
|
-
await func();
|
|
135
|
-
fail('Expected function to throw an error');
|
|
136
|
-
} catch (error) {
|
|
137
|
-
return error;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
99
|
test('error dataSource.register function', async () => {
|
|
142
100
|
const user = 'errorTest1';
|
|
143
101
|
|
|
@@ -145,42 +103,17 @@ describe('KnexDataSource', () => {
|
|
|
145
103
|
await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
|
|
146
104
|
const workflowID = randomUUID();
|
|
147
105
|
|
|
148
|
-
|
|
149
|
-
expect(error).toBeInstanceOf(Error);
|
|
150
|
-
expect((error as Error).message).toMatch(/^test error \d+$/);
|
|
151
|
-
|
|
152
|
-
const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
|
|
153
|
-
expect(rows.length).toBe(1);
|
|
154
|
-
expect(rows[0].greet_count).toBe(10);
|
|
106
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowReg(user))).rejects.toThrow('test error');
|
|
155
107
|
|
|
156
108
|
const { rows: txOutput } = await userDB.query<transaction_completion>(
|
|
157
109
|
'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
|
|
158
110
|
[workflowID],
|
|
159
111
|
);
|
|
160
|
-
expect(txOutput.length).toBe(
|
|
161
|
-
expect(txOutput[0].workflow_id).toBe(workflowID);
|
|
162
|
-
expect(txOutput[0].function_num).toBe(0);
|
|
163
|
-
expect(txOutput[0].output).toBeNull();
|
|
164
|
-
expect(txOutput[0].error).not.toBeNull();
|
|
165
|
-
const $error = SuperJSON.parse(txOutput[0].error!);
|
|
166
|
-
expect($error).toBeInstanceOf(Error);
|
|
167
|
-
expect(($error as Error).message).toMatch(/^test error \d+$/);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
test('rerun error dataSource.register function', async () => {
|
|
171
|
-
const user = 'rerunErrorTest1';
|
|
172
|
-
|
|
173
|
-
await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
|
|
174
|
-
await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
|
|
175
|
-
const workflowID = randomUUID();
|
|
176
|
-
|
|
177
|
-
const error = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowReg(user)));
|
|
178
|
-
expect(error).toBeInstanceOf(Error);
|
|
179
|
-
expect((error as Error).message).toMatch(/^test error \d+$/);
|
|
112
|
+
expect(txOutput.length).toBe(0);
|
|
180
113
|
|
|
181
|
-
const
|
|
182
|
-
expect(
|
|
183
|
-
expect(
|
|
114
|
+
const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
|
|
115
|
+
expect(rows.length).toBe(1);
|
|
116
|
+
expect(rows[0].greet_count).toBe(10);
|
|
184
117
|
});
|
|
185
118
|
|
|
186
119
|
test('error dataSource.runAsTx function', async () => {
|
|
@@ -190,42 +123,17 @@ describe('KnexDataSource', () => {
|
|
|
190
123
|
await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
|
|
191
124
|
const workflowID = randomUUID();
|
|
192
125
|
|
|
193
|
-
|
|
194
|
-
expect(error).toBeInstanceOf(Error);
|
|
195
|
-
expect((error as Error).message).toMatch(/^test error \d+$/);
|
|
196
|
-
|
|
197
|
-
const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
|
|
198
|
-
expect(rows.length).toBe(1);
|
|
199
|
-
expect(rows[0].greet_count).toBe(10);
|
|
126
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user))).rejects.toThrow('test error');
|
|
200
127
|
|
|
201
128
|
const { rows: txOutput } = await userDB.query<transaction_completion>(
|
|
202
129
|
'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
|
|
203
130
|
[workflowID],
|
|
204
131
|
);
|
|
205
|
-
expect(txOutput.length).toBe(
|
|
206
|
-
expect(txOutput[0].workflow_id).toBe(workflowID);
|
|
207
|
-
expect(txOutput[0].function_num).toBe(0);
|
|
208
|
-
expect(txOutput[0].output).toBeNull();
|
|
209
|
-
expect(txOutput[0].error).not.toBeNull();
|
|
210
|
-
const $error = SuperJSON.parse(txOutput[0].error!);
|
|
211
|
-
expect($error).toBeInstanceOf(Error);
|
|
212
|
-
expect(($error as Error).message).toMatch(/^test error \d+$/);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test('rerun error dataSource.runAsTx function', async () => {
|
|
216
|
-
const user = 'rerunErrorTest2';
|
|
132
|
+
expect(txOutput.length).toBe(0);
|
|
217
133
|
|
|
218
|
-
await userDB.query('
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const error = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user)));
|
|
223
|
-
expect(error).toBeInstanceOf(Error);
|
|
224
|
-
expect((error as Error).message).toMatch(/^test error \d+$/);
|
|
225
|
-
|
|
226
|
-
const error2 = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user)));
|
|
227
|
-
expect(error2).toBeInstanceOf(Error);
|
|
228
|
-
expect((error2 as Error).message).toMatch((error as Error).message);
|
|
134
|
+
const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
|
|
135
|
+
expect(rows.length).toBe(1);
|
|
136
|
+
expect(rows[0].greet_count).toBe(10);
|
|
229
137
|
});
|
|
230
138
|
|
|
231
139
|
test('readonly dataSource.register function', async () => {
|
|
@@ -235,14 +143,15 @@ describe('KnexDataSource', () => {
|
|
|
235
143
|
await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
|
|
236
144
|
|
|
237
145
|
const workflowID = randomUUID();
|
|
238
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowReg(user))).resolves.
|
|
146
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowReg(user))).resolves.toEqual({
|
|
239
147
|
user,
|
|
240
148
|
greet_count: 10,
|
|
241
149
|
});
|
|
242
150
|
|
|
243
|
-
const { rows } = await userDB.query(
|
|
244
|
-
|
|
245
|
-
|
|
151
|
+
const { rows } = await userDB.query<transaction_completion>(
|
|
152
|
+
'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
|
|
153
|
+
[workflowID],
|
|
154
|
+
);
|
|
246
155
|
expect(rows.length).toBe(0);
|
|
247
156
|
});
|
|
248
157
|
|
|
@@ -253,7 +162,7 @@ describe('KnexDataSource', () => {
|
|
|
253
162
|
await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
|
|
254
163
|
|
|
255
164
|
const workflowID = randomUUID();
|
|
256
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowRunTx(user))).resolves.
|
|
165
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowRunTx(user))).resolves.toEqual({
|
|
257
166
|
user,
|
|
258
167
|
greet_count: 10,
|
|
259
168
|
});
|
|
@@ -270,7 +179,7 @@ describe('KnexDataSource', () => {
|
|
|
270
179
|
await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
|
|
271
180
|
|
|
272
181
|
const workflowID = randomUUID();
|
|
273
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () => regStaticWorkflow(user))).resolves.
|
|
182
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regStaticWorkflow(user))).resolves.toEqual([
|
|
274
183
|
{ user, greet_count: 1 },
|
|
275
184
|
{ user, greet_count: 1 },
|
|
276
185
|
]);
|
|
@@ -282,45 +191,11 @@ describe('KnexDataSource', () => {
|
|
|
282
191
|
await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
|
|
283
192
|
|
|
284
193
|
const workflowID = randomUUID();
|
|
285
|
-
await expect(DBOS.withNextWorkflowID(workflowID, () => regInstanceWorkflow(user))).resolves.
|
|
194
|
+
await expect(DBOS.withNextWorkflowID(workflowID, () => regInstanceWorkflow(user))).resolves.toEqual([
|
|
286
195
|
{ user, greet_count: 1 },
|
|
287
196
|
{ user, greet_count: 1 },
|
|
288
197
|
]);
|
|
289
198
|
});
|
|
290
|
-
|
|
291
|
-
test('invoke-reg-tx-fun-outside-wf', async () => {
|
|
292
|
-
const user = 'outsideWfUser' + Date.now();
|
|
293
|
-
const result = await regInsertFunction(user);
|
|
294
|
-
expect(result).toMatchObject({ user, greet_count: 1 });
|
|
295
|
-
|
|
296
|
-
const txResults = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE output LIKE $1', [
|
|
297
|
-
`%${user}%`,
|
|
298
|
-
]);
|
|
299
|
-
expect(txResults.rows.length).toBe(0);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
test('invoke-reg-tx-static-method-outside-wf', async () => {
|
|
303
|
-
const user = 'outsideWfUser' + Date.now();
|
|
304
|
-
const result = await StaticClass.insertFunction(user);
|
|
305
|
-
expect(result).toMatchObject({ user, greet_count: 1 });
|
|
306
|
-
|
|
307
|
-
const txResults = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE output LIKE $1', [
|
|
308
|
-
`%${user}%`,
|
|
309
|
-
]);
|
|
310
|
-
expect(txResults.rows.length).toBe(0);
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
test('invoke-reg-tx-inst-method-outside-wf', async () => {
|
|
314
|
-
const user = 'outsideWfUser' + Date.now();
|
|
315
|
-
const instance = new InstanceClass();
|
|
316
|
-
const result = await instance.insertFunction(user);
|
|
317
|
-
expect(result).toMatchObject({ user, greet_count: 1 });
|
|
318
|
-
|
|
319
|
-
const txResults = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE output LIKE $1', [
|
|
320
|
-
`%${user}%`,
|
|
321
|
-
]);
|
|
322
|
-
expect(txResults.rows.length).toBe(0);
|
|
323
|
-
});
|
|
324
199
|
});
|
|
325
200
|
|
|
326
201
|
export interface greetings {
|
|
@@ -336,22 +211,23 @@ async function insertFunction(user: string) {
|
|
|
336
211
|
.returning('greet_count');
|
|
337
212
|
const row = rows.length > 0 ? rows[0] : undefined;
|
|
338
213
|
|
|
339
|
-
return { user, greet_count: row?.greet_count
|
|
214
|
+
return { user, greet_count: row?.greet_count };
|
|
340
215
|
}
|
|
341
216
|
|
|
342
217
|
async function errorFunction(user: string) {
|
|
343
|
-
const
|
|
344
|
-
throw new Error(
|
|
218
|
+
const result = await insertFunction(user);
|
|
219
|
+
throw new Error('test error');
|
|
220
|
+
return result;
|
|
345
221
|
}
|
|
346
222
|
|
|
347
223
|
async function readFunction(user: string) {
|
|
348
224
|
const row = await KnexDataSource.client<greetings>('greetings').select('greet_count').where('name', user).first();
|
|
349
|
-
return { user, greet_count: row?.greet_count
|
|
225
|
+
return { user, greet_count: row?.greet_count };
|
|
350
226
|
}
|
|
351
227
|
|
|
352
|
-
const regInsertFunction = dataSource.registerTransaction(insertFunction);
|
|
353
|
-
const regErrorFunction = dataSource.registerTransaction(errorFunction);
|
|
354
|
-
const regReadFunction = dataSource.registerTransaction(readFunction, { readOnly: true });
|
|
228
|
+
const regInsertFunction = dataSource.registerTransaction(insertFunction, 'insertFunction');
|
|
229
|
+
const regErrorFunction = dataSource.registerTransaction(errorFunction, 'errorFunction');
|
|
230
|
+
const regReadFunction = dataSource.registerTransaction(readFunction, 'readFunction', { readOnly: true });
|
|
355
231
|
|
|
356
232
|
class StaticClass {
|
|
357
233
|
static async insertFunction(user: string) {
|
|
@@ -363,8 +239,8 @@ class StaticClass {
|
|
|
363
239
|
}
|
|
364
240
|
}
|
|
365
241
|
|
|
366
|
-
StaticClass.insertFunction = dataSource.registerTransaction(StaticClass.insertFunction);
|
|
367
|
-
StaticClass.readFunction = dataSource.registerTransaction(StaticClass.readFunction,
|
|
242
|
+
StaticClass.insertFunction = dataSource.registerTransaction(StaticClass.insertFunction, 'insertFunction');
|
|
243
|
+
StaticClass.readFunction = dataSource.registerTransaction(StaticClass.readFunction, 'readFunction');
|
|
368
244
|
|
|
369
245
|
class InstanceClass {
|
|
370
246
|
async insertFunction(user: string) {
|
|
@@ -379,11 +255,12 @@ class InstanceClass {
|
|
|
379
255
|
InstanceClass.prototype.insertFunction = dataSource.registerTransaction(
|
|
380
256
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
381
257
|
InstanceClass.prototype.insertFunction,
|
|
258
|
+
'insertFunction',
|
|
382
259
|
);
|
|
383
260
|
InstanceClass.prototype.readFunction = dataSource.registerTransaction(
|
|
384
261
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
385
262
|
InstanceClass.prototype.readFunction,
|
|
386
|
-
|
|
263
|
+
'readFunction',
|
|
387
264
|
);
|
|
388
265
|
|
|
389
266
|
async function insertWorkflowReg(user: string) {
|
|
@@ -423,8 +300,8 @@ async function instanceWorkflow(user: string) {
|
|
|
423
300
|
return [result, readResult];
|
|
424
301
|
}
|
|
425
302
|
|
|
426
|
-
const
|
|
427
|
-
const
|
|
303
|
+
const regInsertWorfklowReg = DBOS.registerWorkflow(insertWorkflowReg, 'insertWorkflowReg');
|
|
304
|
+
const regInsertWorfklowRunTx = DBOS.registerWorkflow(insertWorkflowRunTx, 'insertWorkflowRunTx');
|
|
428
305
|
const regErrorWorkflowReg = DBOS.registerWorkflow(errorWorkflowReg, 'errorWorkflowReg');
|
|
429
306
|
const regErrorWorkflowRunTx = DBOS.registerWorkflow(errorWorkflowRunTx, 'errorWorkflowRunTx');
|
|
430
307
|
const regReadWorkflowReg = DBOS.registerWorkflow(readWorkflowReg, 'readWorkflowReg');
|
package/tests/test-helpers.ts
CHANGED
|
@@ -7,7 +7,6 @@ export async function ensureDB(client: Client, name: string) {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export async function dropDB(client: Client, name: string
|
|
11
|
-
|
|
12
|
-
await client.query(`DROP DATABASE IF EXISTS ${name} ${withForce}`);
|
|
10
|
+
export async function dropDB(client: Client, name: string) {
|
|
11
|
+
await client.query(`DROP DATABASE IF EXISTS ${name}`);
|
|
13
12
|
}
|