@dbos-inc/koa-serve 3.5.8 → 3.5.44-preview.gc094fdab44
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/src/dboshttp.d.ts +0 -15
- package/dist/src/dboshttp.d.ts.map +1 -1
- package/dist/src/dboshttp.js +3 -38
- package/dist/src/dboshttp.js.map +1 -1
- package/dist/src/dboskoa.js +1 -1
- package/dist/src/dboskoa.js.map +1 -1
- package/dist/src/index.d.ts +0 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -17
- package/dist/src/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/dboshttp.ts +4 -61
- package/src/dboskoa.ts +1 -1
- package/src/index.ts +0 -16
- package/tests/auth.test.ts +7 -42
- package/tests/endpoints.test.ts +34 -86
- package/tests/steps.test.ts +0 -5
- package/tests/transactions.test.ts +0 -5
- package/tests/argsource.test.ts +0 -151
- package/tests/validation.test.ts +0 -531
package/package.json
CHANGED
package/src/dboshttp.ts
CHANGED
|
@@ -2,20 +2,7 @@ import { IncomingHttpHeaders } from 'http';
|
|
|
2
2
|
import { ParsedUrlQuery } from 'querystring';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
DBOS,
|
|
7
|
-
DBOSLifecycleCallback,
|
|
8
|
-
Error as DBOSErrors,
|
|
9
|
-
MethodParameter,
|
|
10
|
-
requestArgValidation,
|
|
11
|
-
ArgRequired,
|
|
12
|
-
ArgOptional,
|
|
13
|
-
DefaultArgRequired,
|
|
14
|
-
DefaultArgValidate,
|
|
15
|
-
DefaultArgOptional,
|
|
16
|
-
ArgDate,
|
|
17
|
-
ArgVarchar,
|
|
18
|
-
} from '@dbos-inc/dbos-sdk';
|
|
5
|
+
import { DBOS, DBOSLifecycleCallback, Error as DBOSErrors, MethodParameter } from '@dbos-inc/dbos-sdk';
|
|
19
6
|
|
|
20
7
|
export enum APITypes {
|
|
21
8
|
GET = 'GET',
|
|
@@ -107,7 +94,7 @@ export class DBOSHTTPBase implements DBOSLifecycleCallback {
|
|
|
107
94
|
propertyKey: string,
|
|
108
95
|
descriptor: TypedPropertyDescriptor<(this: This, ...args: Args) => Promise<Return>>,
|
|
109
96
|
) {
|
|
110
|
-
const {
|
|
97
|
+
const { regInfo } = DBOS.associateFunctionWithInfo(er, descriptor.value!, {
|
|
111
98
|
ctorOrProto: target,
|
|
112
99
|
name: propertyKey,
|
|
113
100
|
});
|
|
@@ -117,7 +104,6 @@ export class DBOSHTTPBase implements DBOSLifecycleCallback {
|
|
|
117
104
|
apiURL: url,
|
|
118
105
|
apiType: verb,
|
|
119
106
|
});
|
|
120
|
-
requestArgValidation(registration);
|
|
121
107
|
|
|
122
108
|
return descriptor;
|
|
123
109
|
};
|
|
@@ -148,27 +134,9 @@ export class DBOSHTTPBase implements DBOSLifecycleCallback {
|
|
|
148
134
|
return this.httpApiDec(APITypes.DELETE, url);
|
|
149
135
|
}
|
|
150
136
|
|
|
151
|
-
/** Parameter decorator indicating which source to use (URL, BODY, etc) for arg data */
|
|
152
|
-
static argSource(source: ArgSources) {
|
|
153
|
-
return function (target: object, propertyKey: PropertyKey, parameterIndex: number) {
|
|
154
|
-
const curParam = DBOS.associateParamWithInfo(
|
|
155
|
-
DBOSHTTP,
|
|
156
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
157
|
-
Object.getOwnPropertyDescriptor(target, propertyKey)!.value,
|
|
158
|
-
{
|
|
159
|
-
ctorOrProto: target,
|
|
160
|
-
name: propertyKey.toString(),
|
|
161
|
-
param: parameterIndex,
|
|
162
|
-
},
|
|
163
|
-
) as DBOSHTTPArgInfo;
|
|
164
|
-
|
|
165
|
-
curParam.argSource = source;
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
137
|
protected getArgSource(arg: MethodParameter) {
|
|
170
|
-
|
|
171
|
-
return
|
|
138
|
+
void arg;
|
|
139
|
+
return ArgSources.AUTO;
|
|
172
140
|
}
|
|
173
141
|
|
|
174
142
|
logRegisteredEndpoints(): void {
|
|
@@ -189,29 +157,4 @@ export class DBOSHTTPBase implements DBOSLifecycleCallback {
|
|
|
189
157
|
}
|
|
190
158
|
}
|
|
191
159
|
}
|
|
192
|
-
|
|
193
|
-
static argRequired(target: object, propertyKey: PropertyKey, parameterIndex: number) {
|
|
194
|
-
ArgRequired(target, propertyKey, parameterIndex);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
static argOptional(target: object, propertyKey: PropertyKey, parameterIndex: number) {
|
|
198
|
-
ArgOptional(target, propertyKey, parameterIndex);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
static argDate() {
|
|
202
|
-
return ArgDate();
|
|
203
|
-
}
|
|
204
|
-
static argVarchar(n: number) {
|
|
205
|
-
return ArgVarchar(n);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
static defaultArgRequired<T extends { new (...args: unknown[]): object }>(ctor: T) {
|
|
209
|
-
return DefaultArgRequired(ctor);
|
|
210
|
-
}
|
|
211
|
-
static defaultArgOptional<T extends { new (...args: unknown[]): object }>(ctor: T) {
|
|
212
|
-
return DefaultArgOptional(ctor);
|
|
213
|
-
}
|
|
214
|
-
static defaultArgValidate<T extends { new (...args: unknown[]): object }>(ctor: T) {
|
|
215
|
-
return DefaultArgValidate(ctor);
|
|
216
|
-
}
|
|
217
160
|
}
|
package/src/dboskoa.ts
CHANGED
|
@@ -344,7 +344,7 @@ export class DBOSKoa extends DBOSHTTPBase {
|
|
|
344
344
|
} catch (e) {
|
|
345
345
|
if (e instanceof Error) {
|
|
346
346
|
span?.setStatus({ code: SpanStatusCode.ERROR, message: e.message });
|
|
347
|
-
let st =
|
|
347
|
+
let st = 500;
|
|
348
348
|
if (isClientRequestError(e)) {
|
|
349
349
|
st = 400; // Set to 400: client-side error.
|
|
350
350
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { DBOSKoa } from './dboskoa';
|
|
2
|
-
|
|
3
1
|
export {
|
|
4
2
|
ArgSources,
|
|
5
3
|
DBOSHTTP,
|
|
@@ -14,17 +12,3 @@ export {
|
|
|
14
12
|
} from './dboshttp';
|
|
15
13
|
|
|
16
14
|
export { DBOSKoa, DBOSKoaAuthContext, DBOSKoaClassReg, DBOSKoaAuthMiddleware, DBOSKoaConfig } from './dboskoa';
|
|
17
|
-
|
|
18
|
-
// Export these as unbound functions. We know this is safe,
|
|
19
|
-
// and it more closely matches the existing library syntax.
|
|
20
|
-
// (Using the static function as a decorator, for some reason,
|
|
21
|
-
// is erroneously getting considered as unbound by some lint versions,
|
|
22
|
-
// as there are no parens following it?)
|
|
23
|
-
export const DefaultArgOptional = DBOSKoa.defaultArgOptional;
|
|
24
|
-
export const DefaultArgRequired = DBOSKoa.defaultArgRequired;
|
|
25
|
-
export const DefaultArgValidate = DBOSKoa.defaultArgValidate;
|
|
26
|
-
export const ArgDate = DBOSKoa.argDate;
|
|
27
|
-
export const ArgOptional = DBOSKoa.argOptional;
|
|
28
|
-
export const ArgRequired = DBOSKoa.argRequired;
|
|
29
|
-
export const ArgSource = DBOSKoa.argSource;
|
|
30
|
-
export const ArgVarchar = DBOSKoa.argVarchar;
|
package/tests/auth.test.ts
CHANGED
|
@@ -9,21 +9,13 @@ import request from 'supertest';
|
|
|
9
9
|
|
|
10
10
|
const dhttp = new DBOSKoa();
|
|
11
11
|
|
|
12
|
-
interface TestKvTable {
|
|
13
|
-
id?: number;
|
|
14
|
-
value?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
12
|
describe('httpserver-defsec-tests', () => {
|
|
18
13
|
let app: Koa;
|
|
19
14
|
let appRouter: Router;
|
|
20
15
|
|
|
21
|
-
const testTableName = 'dbos_test_kv';
|
|
22
|
-
|
|
23
16
|
beforeAll(async () => {
|
|
24
17
|
DBOS.setConfig({
|
|
25
18
|
name: 'dbos-koa-test',
|
|
26
|
-
userDatabaseClient: 'pg-node',
|
|
27
19
|
});
|
|
28
20
|
return Promise.resolve();
|
|
29
21
|
});
|
|
@@ -31,8 +23,6 @@ describe('httpserver-defsec-tests', () => {
|
|
|
31
23
|
beforeEach(async () => {
|
|
32
24
|
const _classes = [TestEndpointDefSec, SecondClass];
|
|
33
25
|
await DBOS.launch();
|
|
34
|
-
await DBOS.queryUserDB(`DROP TABLE IF EXISTS ${testTableName};`);
|
|
35
|
-
await DBOS.queryUserDB(`CREATE TABLE IF NOT EXISTS ${testTableName} (id SERIAL PRIMARY KEY, value TEXT);`);
|
|
36
26
|
middlewareCounter = 0;
|
|
37
27
|
middlewareCounter2 = 0;
|
|
38
28
|
middlewareCounterG = 0;
|
|
@@ -71,17 +61,17 @@ describe('httpserver-defsec-tests', () => {
|
|
|
71
61
|
|
|
72
62
|
test('not-authenticated', async () => {
|
|
73
63
|
const response = await request(app.callback()).get('/requireduser?name=alice');
|
|
74
|
-
expect(response.statusCode).toBe(
|
|
64
|
+
expect(response.statusCode).toBe(500);
|
|
75
65
|
});
|
|
76
66
|
|
|
77
67
|
test('not-you', async () => {
|
|
78
68
|
const response = await request(app.callback()).get('/requireduser?name=alice&userid=go_away');
|
|
79
|
-
expect(response.statusCode).toBe(
|
|
69
|
+
expect(response.statusCode).toBe(500);
|
|
80
70
|
});
|
|
81
71
|
|
|
82
72
|
test('not-authorized', async () => {
|
|
83
73
|
const response = await request(app.callback()).get('/requireduser?name=alice&userid=bob');
|
|
84
|
-
expect(response.statusCode).toBe(
|
|
74
|
+
expect(response.statusCode).toBe(500);
|
|
85
75
|
});
|
|
86
76
|
|
|
87
77
|
test('authorized', async () => {
|
|
@@ -93,22 +83,6 @@ describe('httpserver-defsec-tests', () => {
|
|
|
93
83
|
test('cascade-authorized', async () => {
|
|
94
84
|
const response = await request(app.callback()).get('/workflow?name=alice&userid=a_real_user');
|
|
95
85
|
expect(response.statusCode).toBe(200);
|
|
96
|
-
|
|
97
|
-
const txnResponse = await request(app.callback()).get('/transaction?name=alice&userid=a_real_user');
|
|
98
|
-
expect(txnResponse.statusCode).toBe(200);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// We can directly test a transaction with passed in authorizedRoles.
|
|
102
|
-
test('direct-transaction-test', async () => {
|
|
103
|
-
await DBOS.withAuthedContext('user', ['user'], async () => {
|
|
104
|
-
const res = await TestEndpointDefSec.testTranscation('alice');
|
|
105
|
-
expect(res).toBe('hello 1');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Unauthorized.
|
|
109
|
-
await expect(TestEndpointDefSec.testTranscation('alice')).rejects.toThrow(
|
|
110
|
-
new DBOSError.DBOSNotAuthorizedError('User does not have a role with permission to call testTranscation', 403),
|
|
111
|
-
);
|
|
112
86
|
});
|
|
113
87
|
|
|
114
88
|
async function authTestMiddleware(ctx: DBOSKoaAuthContext) {
|
|
@@ -171,18 +145,14 @@ describe('httpserver-defsec-tests', () => {
|
|
|
171
145
|
return Promise.resolve(`Please say hello to ${name}`);
|
|
172
146
|
}
|
|
173
147
|
|
|
174
|
-
@DBOS.
|
|
175
|
-
static async
|
|
176
|
-
|
|
177
|
-
`INSERT INTO ${testTableName}(value) VALUES ($1) RETURNING id`,
|
|
178
|
-
[name],
|
|
179
|
-
);
|
|
180
|
-
return `hello ${rows[0].id}`;
|
|
148
|
+
@DBOS.step()
|
|
149
|
+
static async testStep(name: string) {
|
|
150
|
+
return Promise.resolve(`hello ${name}`);
|
|
181
151
|
}
|
|
182
152
|
|
|
183
153
|
@DBOS.workflow()
|
|
184
154
|
static async testWorkflow(name: string) {
|
|
185
|
-
const res = await TestEndpointDefSec.
|
|
155
|
+
const res = await TestEndpointDefSec.testStep(name);
|
|
186
156
|
return res;
|
|
187
157
|
}
|
|
188
158
|
|
|
@@ -190,11 +160,6 @@ describe('httpserver-defsec-tests', () => {
|
|
|
190
160
|
static async testWfEndpoint(name: string) {
|
|
191
161
|
return await TestEndpointDefSec.testWorkflow(name);
|
|
192
162
|
}
|
|
193
|
-
|
|
194
|
-
@dhttp.getApi('/transaction')
|
|
195
|
-
static async testTxnEndpoint(name: string) {
|
|
196
|
-
return await TestEndpointDefSec.testTranscation(name);
|
|
197
|
-
}
|
|
198
163
|
}
|
|
199
164
|
|
|
200
165
|
class SecondClass {
|
package/tests/endpoints.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import Koa from 'koa';
|
|
3
3
|
import Router from '@koa/router';
|
|
4
4
|
|
|
5
|
-
import { DBOS,
|
|
5
|
+
import { DBOS, Error as DBOSErrors, StatusString } from '@dbos-inc/dbos-sdk';
|
|
6
6
|
|
|
7
7
|
import { DBOSKoa, DBOSKoaAuthContext, RequestIDHeader, WorkflowIDHeader } from '../src';
|
|
8
8
|
|
|
@@ -10,11 +10,6 @@ import request from 'supertest';
|
|
|
10
10
|
|
|
11
11
|
const dhttp = new DBOSKoa();
|
|
12
12
|
|
|
13
|
-
interface TestKvTable {
|
|
14
|
-
id?: number;
|
|
15
|
-
value?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
13
|
import { randomUUID } from 'node:crypto';
|
|
19
14
|
import { IncomingMessage } from 'http';
|
|
20
15
|
import { bodyParser } from '@koa/bodyparser';
|
|
@@ -29,12 +24,9 @@ describe('httpserver-tests', () => {
|
|
|
29
24
|
let app: Koa;
|
|
30
25
|
let appRouter: Router;
|
|
31
26
|
|
|
32
|
-
const testTableName = 'dbos_test_kv';
|
|
33
|
-
|
|
34
27
|
beforeAll(async () => {
|
|
35
28
|
DBOS.setConfig({
|
|
36
29
|
name: 'dbos-koa-test',
|
|
37
|
-
userDatabaseClient: 'pg-node',
|
|
38
30
|
});
|
|
39
31
|
return Promise.resolve();
|
|
40
32
|
});
|
|
@@ -42,8 +34,6 @@ describe('httpserver-tests', () => {
|
|
|
42
34
|
beforeEach(async () => {
|
|
43
35
|
const _classes = [TestEndpoints];
|
|
44
36
|
await DBOS.launch();
|
|
45
|
-
await DBOS.queryUserDB(`DROP TABLE IF EXISTS ${testTableName};`);
|
|
46
|
-
await DBOS.queryUserDB(`CREATE TABLE IF NOT EXISTS ${testTableName} (id INT PRIMARY KEY, value TEXT);`);
|
|
47
37
|
app = new Koa();
|
|
48
38
|
appRouter = new Router();
|
|
49
39
|
dhttp.registerWithApp(app, appRouter);
|
|
@@ -107,17 +97,12 @@ describe('httpserver-tests', () => {
|
|
|
107
97
|
});
|
|
108
98
|
|
|
109
99
|
test('post-test-custom-body', async () => {
|
|
110
|
-
|
|
100
|
+
const response = await request(app.callback())
|
|
111
101
|
.post('/testpost')
|
|
112
102
|
.set('Content-Type', 'application/custom-content-type')
|
|
113
103
|
.send(JSON.stringify({ name: 'alice' }));
|
|
114
104
|
expect(response.statusCode).toBe(200);
|
|
115
105
|
expect(response.text).toBe('hello alice');
|
|
116
|
-
response = await request(app.callback())
|
|
117
|
-
.post('/testpost')
|
|
118
|
-
.set('Content-Type', 'application/rejected-custom-content-type')
|
|
119
|
-
.send(JSON.stringify({ name: 'alice' }));
|
|
120
|
-
expect(response.statusCode).toBe(400);
|
|
121
106
|
});
|
|
122
107
|
|
|
123
108
|
test('put-test', async () => {
|
|
@@ -127,17 +112,12 @@ describe('httpserver-tests', () => {
|
|
|
127
112
|
});
|
|
128
113
|
|
|
129
114
|
test('put-test-custom-body', async () => {
|
|
130
|
-
|
|
115
|
+
const response = await request(app.callback())
|
|
131
116
|
.put('/testput')
|
|
132
117
|
.set('Content-Type', 'application/custom-content-type')
|
|
133
118
|
.send(JSON.stringify({ name: 'alice' }));
|
|
134
119
|
expect(response.statusCode).toBe(200);
|
|
135
120
|
expect(response.text).toBe('hello alice');
|
|
136
|
-
response = await request(app.callback())
|
|
137
|
-
.put('/testput')
|
|
138
|
-
.set('Content-Type', 'application/rejected-custom-content-type')
|
|
139
|
-
.send(JSON.stringify({ name: 'alice' }));
|
|
140
|
-
expect(response.statusCode).toBe(400);
|
|
141
121
|
});
|
|
142
122
|
|
|
143
123
|
test('patch-test', async () => {
|
|
@@ -147,23 +127,12 @@ describe('httpserver-tests', () => {
|
|
|
147
127
|
});
|
|
148
128
|
|
|
149
129
|
test('patch-test-custom-body', async () => {
|
|
150
|
-
|
|
130
|
+
const response = await request(app.callback())
|
|
151
131
|
.patch('/testpatch')
|
|
152
132
|
.set('Content-Type', 'application/custom-content-type')
|
|
153
133
|
.send(JSON.stringify({ name: 'alice' }));
|
|
154
134
|
expect(response.statusCode).toBe(200);
|
|
155
135
|
expect(response.text).toBe('hello alice');
|
|
156
|
-
response = await request(app.callback())
|
|
157
|
-
.patch('/testpatch')
|
|
158
|
-
.set('Content-Type', 'application/rejected-custom-content-type')
|
|
159
|
-
.send(JSON.stringify({ name: 'alice' }));
|
|
160
|
-
expect(response.statusCode).toBe(400);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test('endpoint-transaction', async () => {
|
|
164
|
-
const response = await request(app.callback()).post('/transaction/alice');
|
|
165
|
-
expect(response.statusCode).toBe(200);
|
|
166
|
-
expect(response.text).toBe('hello 1');
|
|
167
136
|
});
|
|
168
137
|
|
|
169
138
|
test('endpoint-step', async () => {
|
|
@@ -175,31 +144,30 @@ describe('httpserver-tests', () => {
|
|
|
175
144
|
test('endpoint-workflow', async () => {
|
|
176
145
|
const response = await request(app.callback()).post('/workflow?name=alice');
|
|
177
146
|
expect(response.statusCode).toBe(200);
|
|
178
|
-
expect(response.text).toBe('
|
|
147
|
+
expect(response.text).toBe('alice');
|
|
179
148
|
});
|
|
180
149
|
|
|
181
150
|
test('endpoint-error', async () => {
|
|
182
151
|
const response = await request(app.callback()).post('/error').send({ name: 'alice' });
|
|
183
152
|
expect(response.statusCode).toBe(500);
|
|
184
|
-
expect(response.body.details.code).toBe('23505'); // Should be the expected error.
|
|
185
153
|
});
|
|
186
154
|
|
|
187
155
|
test('endpoint-handler', async () => {
|
|
188
156
|
const response = await request(app.callback()).get('/handler/alice');
|
|
189
157
|
expect(response.statusCode).toBe(200);
|
|
190
|
-
expect(response.text).toBe('
|
|
158
|
+
expect(response.text).toBe('alice');
|
|
191
159
|
});
|
|
192
160
|
|
|
193
161
|
test('endpoint-testStartWorkflow', async () => {
|
|
194
162
|
const response = await request(app.callback()).get('/testStartWorkflow/alice');
|
|
195
163
|
expect(response.statusCode).toBe(200);
|
|
196
|
-
expect(response.text).toBe('
|
|
164
|
+
expect(response.text).toBe('alice');
|
|
197
165
|
});
|
|
198
166
|
|
|
199
167
|
test('endpoint-testInvokeWorkflow', async () => {
|
|
200
168
|
const response = await request(app.callback()).get('/testInvokeWorkflow/alice');
|
|
201
169
|
expect(response.statusCode).toBe(200);
|
|
202
|
-
expect(response.text).toBe('
|
|
170
|
+
expect(response.text).toBe('alice');
|
|
203
171
|
});
|
|
204
172
|
|
|
205
173
|
// This feels unclean, but supertest doesn't expose the error message the people we want. See:
|
|
@@ -210,17 +178,11 @@ describe('httpserver-tests', () => {
|
|
|
210
178
|
|
|
211
179
|
test('response-error', async () => {
|
|
212
180
|
const response = await request(app.callback()).get('/dbos-error');
|
|
213
|
-
expect(response.statusCode).toBe(
|
|
181
|
+
expect(response.statusCode).toBe(500);
|
|
214
182
|
expect((response as unknown as Res).res.statusMessage).toBe('customize error');
|
|
215
183
|
expect(response.body.message).toBe('customize error');
|
|
216
184
|
});
|
|
217
185
|
|
|
218
|
-
test('datavalidation-error', async () => {
|
|
219
|
-
const response = await request(app.callback()).get('/query');
|
|
220
|
-
expect(response.statusCode).toBe(400);
|
|
221
|
-
expect(response.body.details.dbosErrorCode).toBe(9);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
186
|
test('dbos-redirect', async () => {
|
|
225
187
|
const response = await request(app.callback()).get('/redirect');
|
|
226
188
|
expect(response.statusCode).toBe(302);
|
|
@@ -248,17 +210,17 @@ describe('httpserver-tests', () => {
|
|
|
248
210
|
|
|
249
211
|
test('not-authenticated', async () => {
|
|
250
212
|
const response = await request(app.callback()).get('/requireduser?name=alice');
|
|
251
|
-
expect(response.statusCode).toBe(
|
|
213
|
+
expect(response.statusCode).toBe(500);
|
|
252
214
|
});
|
|
253
215
|
|
|
254
216
|
test('not-you', async () => {
|
|
255
217
|
const response = await request(app.callback()).get('/requireduser?name=alice&userid=go_away');
|
|
256
|
-
expect(response.statusCode).toBe(
|
|
218
|
+
expect(response.statusCode).toBe(500);
|
|
257
219
|
});
|
|
258
220
|
|
|
259
221
|
test('not-authorized', async () => {
|
|
260
222
|
const response = await request(app.callback()).get('/requireduser?name=alice&userid=bob');
|
|
261
|
-
expect(response.statusCode).toBe(
|
|
223
|
+
expect(response.statusCode).toBe(500);
|
|
262
224
|
});
|
|
263
225
|
|
|
264
226
|
test('authorized', async () => {
|
|
@@ -268,17 +230,17 @@ describe('httpserver-tests', () => {
|
|
|
268
230
|
|
|
269
231
|
test('not-authenticated2', async () => {
|
|
270
232
|
const response = await request(app.callback()).get('/requireduser2?name=alice');
|
|
271
|
-
expect(response.statusCode).toBe(
|
|
233
|
+
expect(response.statusCode).toBe(500);
|
|
272
234
|
});
|
|
273
235
|
|
|
274
236
|
test('not-you2', async () => {
|
|
275
237
|
const response = await request(app.callback()).get('/requireduser2?name=alice&userid=go_away');
|
|
276
|
-
expect(response.statusCode).toBe(
|
|
238
|
+
expect(response.statusCode).toBe(500);
|
|
277
239
|
});
|
|
278
240
|
|
|
279
241
|
test('not-authorized2', async () => {
|
|
280
242
|
const response = await request(app.callback()).get('/requireduser2?name=alice&userid=bob');
|
|
281
|
-
expect(response.statusCode).toBe(
|
|
243
|
+
expect(response.statusCode).toBe(500);
|
|
282
244
|
});
|
|
283
245
|
|
|
284
246
|
test('authorized2', async () => {
|
|
@@ -292,12 +254,12 @@ describe('httpserver-tests', () => {
|
|
|
292
254
|
.post('/workflow?name=bob')
|
|
293
255
|
.set({ 'dbos-idempotency-key': workflowID });
|
|
294
256
|
expect(response.statusCode).toBe(200);
|
|
295
|
-
expect(response.text).toBe('
|
|
257
|
+
expect(response.text).toBe('bob');
|
|
296
258
|
|
|
297
259
|
// Retrieve the workflow with WFID.
|
|
298
260
|
const retrievedHandle = DBOS.retrieveWorkflow(workflowID);
|
|
299
261
|
expect(retrievedHandle).not.toBeNull();
|
|
300
|
-
await expect(retrievedHandle.getResult()).resolves.toBe('
|
|
262
|
+
await expect(retrievedHandle.getResult()).resolves.toBe('bob');
|
|
301
263
|
await expect(retrievedHandle.getStatus()).resolves.toMatchObject({
|
|
302
264
|
status: StatusString.SUCCESS,
|
|
303
265
|
});
|
|
@@ -307,12 +269,12 @@ describe('httpserver-tests', () => {
|
|
|
307
269
|
const workflowID = randomUUID();
|
|
308
270
|
const response = await request(app.callback()).get('/handler/bob').set({ 'dbos-idempotency-key': workflowID });
|
|
309
271
|
expect(response.statusCode).toBe(200);
|
|
310
|
-
expect(response.text).toBe('
|
|
272
|
+
expect(response.text).toBe('bob');
|
|
311
273
|
|
|
312
274
|
// Retrieve the workflow with WFID.
|
|
313
275
|
const retrievedHandle = DBOS.retrieveWorkflow(workflowID);
|
|
314
276
|
expect(retrievedHandle).not.toBeNull();
|
|
315
|
-
await expect(retrievedHandle.getResult()).resolves.toBe('
|
|
277
|
+
await expect(retrievedHandle.getResult()).resolves.toBe('bob');
|
|
316
278
|
await expect(retrievedHandle.getStatus()).resolves.toMatchObject({
|
|
317
279
|
status: StatusString.SUCCESS,
|
|
318
280
|
});
|
|
@@ -349,7 +311,6 @@ describe('httpserver-tests', () => {
|
|
|
349
311
|
parsedMethods: ['POST', 'PUT', 'PATCH', 'GET', 'DELETE'],
|
|
350
312
|
}),
|
|
351
313
|
)
|
|
352
|
-
@DBOSKoa.defaultArgRequired
|
|
353
314
|
class TestEndpoints {
|
|
354
315
|
@dhttp.getApi('/hello')
|
|
355
316
|
static async hello() {
|
|
@@ -378,6 +339,12 @@ describe('httpserver-tests', () => {
|
|
|
378
339
|
return Promise.resolve(url);
|
|
379
340
|
}
|
|
380
341
|
|
|
342
|
+
@dhttp.getApi('/dbos-error')
|
|
343
|
+
@DBOS.workflow()
|
|
344
|
+
static async dbosErr() {
|
|
345
|
+
return Promise.reject(new Error('customize error'));
|
|
346
|
+
}
|
|
347
|
+
|
|
381
348
|
@dhttp.getApi('/query')
|
|
382
349
|
static async helloQuery(name: string) {
|
|
383
350
|
DBOS.logger.info(`query with name ${name}`); // Test logging.
|
|
@@ -423,12 +390,6 @@ describe('httpserver-tests', () => {
|
|
|
423
390
|
return Promise.resolve(`hello ${name}`);
|
|
424
391
|
}
|
|
425
392
|
|
|
426
|
-
@dhttp.getApi('/dbos-error')
|
|
427
|
-
@DBOS.transaction()
|
|
428
|
-
static async dbosErr() {
|
|
429
|
-
return Promise.reject(new DBOSResponseError('customize error', 503));
|
|
430
|
-
}
|
|
431
|
-
|
|
432
393
|
@dhttp.getApi('/handler/:name')
|
|
433
394
|
static async testHandler(name: string) {
|
|
434
395
|
const workflowID: string = DBOSKoa.koaContext.get(WorkflowIDHeader);
|
|
@@ -450,16 +411,6 @@ describe('httpserver-tests', () => {
|
|
|
450
411
|
return await TestEndpoints.testWorkflow(name);
|
|
451
412
|
}
|
|
452
413
|
|
|
453
|
-
@dhttp.postApi('/transaction/:name')
|
|
454
|
-
@DBOS.transaction()
|
|
455
|
-
static async testTransaction(name: string) {
|
|
456
|
-
const { rows } = await DBOS.pgClient.query<TestKvTable>(
|
|
457
|
-
`INSERT INTO ${testTableName}(id, value) VALUES (1, $1) RETURNING id`,
|
|
458
|
-
[name],
|
|
459
|
-
);
|
|
460
|
-
return `hello ${rows[0].id}`;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
414
|
@dhttp.getApi('/step/:input')
|
|
464
415
|
@DBOS.step()
|
|
465
416
|
static async testStep(input: string) {
|
|
@@ -469,30 +420,27 @@ describe('httpserver-tests', () => {
|
|
|
469
420
|
@dhttp.postApi('/workflow')
|
|
470
421
|
@DBOS.workflow()
|
|
471
422
|
static async testWorkflow(name: string) {
|
|
472
|
-
|
|
473
|
-
return TestEndpoints.testStep(res);
|
|
423
|
+
return TestEndpoints.testStep(name);
|
|
474
424
|
}
|
|
475
425
|
|
|
476
426
|
@dhttp.postApi('/error')
|
|
477
427
|
@DBOS.workflow()
|
|
478
428
|
static async testWorkflowError(name: string) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
res = await TestEndpoints.testTransaction(name);
|
|
482
|
-
return res;
|
|
429
|
+
await Promise.resolve();
|
|
430
|
+
throw Error(name);
|
|
483
431
|
}
|
|
484
432
|
|
|
485
433
|
@dhttp.getApi('/requireduser')
|
|
486
434
|
@DBOS.requiredRole(['user'])
|
|
487
435
|
static async testAuth(name: string) {
|
|
488
436
|
if (DBOS.authenticatedUser !== 'a_real_user') {
|
|
489
|
-
throw new
|
|
437
|
+
throw new Error('uid not a real user!');
|
|
490
438
|
}
|
|
491
439
|
if (!DBOS.authenticatedRoles.includes('user')) {
|
|
492
|
-
throw new
|
|
440
|
+
throw new Error("roles don't include user!");
|
|
493
441
|
}
|
|
494
442
|
if (DBOS.assumedRole !== 'user') {
|
|
495
|
-
throw new
|
|
443
|
+
throw new Error('Should never happen! Not assumed to be user');
|
|
496
444
|
}
|
|
497
445
|
return Promise.resolve(`Please say hello to ${name}`);
|
|
498
446
|
}
|
|
@@ -501,13 +449,13 @@ describe('httpserver-tests', () => {
|
|
|
501
449
|
@DBOS.requiredRole(['user'])
|
|
502
450
|
static async testAuth2(name: string) {
|
|
503
451
|
if (DBOS.authenticatedUser !== 'a_real_user') {
|
|
504
|
-
throw new
|
|
452
|
+
throw new Error('uid not a real user!');
|
|
505
453
|
}
|
|
506
454
|
if (!DBOS.authenticatedRoles.includes('user')) {
|
|
507
|
-
throw new
|
|
455
|
+
throw new Error("roles don't include user!");
|
|
508
456
|
}
|
|
509
457
|
if (DBOS.assumedRole !== 'user') {
|
|
510
|
-
throw new
|
|
458
|
+
throw new Error('Should never happen! Not assumed to be user');
|
|
511
459
|
}
|
|
512
460
|
return Promise.resolve(`Please say hello to ${name}`);
|
|
513
461
|
}
|
package/tests/steps.test.ts
CHANGED
|
@@ -56,14 +56,9 @@ describe('registerstep', () => {
|
|
|
56
56
|
expect(response1.statusCode).toBe(200);
|
|
57
57
|
const response2 = await request(app.callback()).get('/api/i2?user=jeremy');
|
|
58
58
|
expect(response2.statusCode).toBe(200);
|
|
59
|
-
const response3 = await request(app.callback()).get('/api/i1');
|
|
60
|
-
expect(response3.statusCode).toBe(400);
|
|
61
|
-
const response4 = await request(app.callback()).get('/api/i2');
|
|
62
|
-
expect(response4.statusCode).toBe(400);
|
|
63
59
|
});
|
|
64
60
|
});
|
|
65
61
|
|
|
66
|
-
@DBOSKoa.defaultArgValidate
|
|
67
62
|
class KnexKoa {
|
|
68
63
|
@customstep()
|
|
69
64
|
@dhttp.getApi('/api/i2')
|
|
@@ -77,14 +77,9 @@ describe('KnexDataSource', () => {
|
|
|
77
77
|
expect(response1.statusCode).toBe(200);
|
|
78
78
|
const response2 = await request(app.callback()).get('/api/i2?user=jeremy');
|
|
79
79
|
expect(response2.statusCode).toBe(200);
|
|
80
|
-
const response3 = await request(app.callback()).get('/api/i1');
|
|
81
|
-
expect(response3.statusCode).toBe(400);
|
|
82
|
-
const response4 = await request(app.callback()).get('/api/i2');
|
|
83
|
-
expect(response4.statusCode).toBe(400);
|
|
84
80
|
});
|
|
85
81
|
});
|
|
86
82
|
|
|
87
|
-
@DBOSKoa.defaultArgValidate
|
|
88
83
|
class KnexKoa {
|
|
89
84
|
@knexds.transaction()
|
|
90
85
|
@dhttp.getApi('/api/i2')
|