@getsoda/core 0.2.2 → 0.3.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/README.md +80 -0
- package/dist/app/app.d.ts +15 -5
- package/dist/app/app.d.ts.map +1 -1
- package/dist/app/app.js +31 -8
- package/dist/app/app.js.map +1 -1
- package/dist/app/index.d.ts +1 -1
- package/dist/app/index.d.ts.map +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +2 -0
- package/dist/config/config.js.map +1 -1
- package/dist/di/errors.d.ts.map +1 -1
- package/dist/di/errors.js +2 -0
- package/dist/di/errors.js.map +1 -1
- package/dist/http/arguments.d.ts +19 -6
- package/dist/http/arguments.d.ts.map +1 -1
- package/dist/http/arguments.js +7 -0
- package/dist/http/arguments.js.map +1 -1
- package/dist/http/cookies.d.ts.map +1 -1
- package/dist/http/cookies.js +2 -0
- package/dist/http/cookies.js.map +1 -1
- package/dist/http/decorators.d.ts +12 -5
- package/dist/http/decorators.d.ts.map +1 -1
- package/dist/http/decorators.js +7 -2
- package/dist/http/decorators.js.map +1 -1
- package/dist/http/errors.d.ts +3 -1
- package/dist/http/errors.d.ts.map +1 -1
- package/dist/http/errors.js +2 -0
- package/dist/http/errors.js.map +1 -1
- package/dist/http/index.d.ts +6 -4
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +3 -2
- package/dist/http/index.js.map +1 -1
- package/dist/http/parsers.d.ts +4 -0
- package/dist/http/parsers.d.ts.map +1 -1
- package/dist/http/parsers.js +9 -5
- package/dist/http/parsers.js.map +1 -1
- package/dist/http/pipeline.d.ts +4 -5
- package/dist/http/pipeline.d.ts.map +1 -1
- package/dist/http/pipeline.js +2 -2
- package/dist/http/pipeline.js.map +1 -1
- package/dist/http/routes.d.ts +27 -2
- package/dist/http/routes.d.ts.map +1 -1
- package/dist/http/routes.js +34 -20
- package/dist/http/routes.js.map +1 -1
- package/dist/http/sse.d.ts +39 -0
- package/dist/http/sse.d.ts.map +1 -0
- package/dist/http/sse.js +89 -0
- package/dist/http/sse.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/openapi/decorators.d.ts +41 -0
- package/dist/openapi/decorators.d.ts.map +1 -0
- package/dist/openapi/decorators.js +29 -0
- package/dist/openapi/decorators.js.map +1 -0
- package/dist/openapi/document.d.ts +62 -0
- package/dist/openapi/document.d.ts.map +1 -0
- package/dist/openapi/document.js +135 -0
- package/dist/openapi/document.js.map +1 -0
- package/dist/openapi/index.d.ts +11 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js +8 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/openapi/module.d.ts +26 -0
- package/dist/openapi/module.d.ts.map +1 -0
- package/dist/openapi/module.js +73 -0
- package/dist/openapi/module.js.map +1 -0
- package/dist/routing/errors.d.ts.map +1 -1
- package/dist/routing/errors.js +2 -0
- package/dist/routing/errors.js.map +1 -1
- package/dist/testing/index.d.ts +46 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +49 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/utils/errors.d.ts +11 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +22 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/object.d.ts +4 -0
- package/dist/utils/object.d.ts.map +1 -1
- package/dist/utils/object.js +16 -0
- package/dist/utils/object.js.map +1 -1
- package/dist/websocket/decorators.d.ts +31 -0
- package/dist/websocket/decorators.d.ts.map +1 -0
- package/dist/websocket/decorators.js +43 -0
- package/dist/websocket/decorators.js.map +1 -0
- package/dist/websocket/gateway.d.ts +61 -0
- package/dist/websocket/gateway.d.ts.map +1 -0
- package/dist/websocket/gateway.js +142 -0
- package/dist/websocket/gateway.js.map +1 -0
- package/dist/websocket/index.d.ts +7 -0
- package/dist/websocket/index.d.ts.map +1 -0
- package/dist/websocket/index.js +6 -0
- package/dist/websocket/index.js.map +1 -0
- package/package.json +12 -1
- package/src/app/app.ts +69 -18
- package/src/app/index.ts +1 -1
- package/src/config/config.ts +2 -0
- package/src/di/errors.ts +3 -0
- package/src/http/arguments.ts +31 -6
- package/src/http/cookies.ts +2 -0
- package/src/http/decorators.ts +16 -8
- package/src/http/errors.ts +7 -0
- package/src/http/index.ts +6 -4
- package/src/http/parsers.ts +18 -7
- package/src/http/pipeline.ts +6 -6
- package/src/http/routes.ts +68 -29
- package/src/http/sse.ts +120 -0
- package/src/index.ts +1 -0
- package/src/openapi/decorators.ts +50 -0
- package/src/openapi/document.ts +221 -0
- package/src/openapi/index.ts +11 -0
- package/src/openapi/module.ts +95 -0
- package/src/routing/errors.ts +3 -0
- package/src/testing/index.ts +73 -0
- package/src/utils/errors.ts +25 -0
- package/src/utils/object.ts +23 -0
- package/src/websocket/decorators.ts +55 -0
- package/src/websocket/gateway.ts +213 -0
- package/src/websocket/index.ts +7 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Testing an application over HTTP, as Nest's `Test.createTestingModule()`
|
|
4
|
+
* with supertest does, on a real Bun server bound to a free port.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { createTestApp } from '@getsoda/core/testing'
|
|
8
|
+
*
|
|
9
|
+
* const app = await createTestApp(AppModule, {
|
|
10
|
+
* overrides: [provide(UsersRepository, { useValue: new MemoryUsersRepository() })],
|
|
11
|
+
* })
|
|
12
|
+
*
|
|
13
|
+
* afterAll(() => app.close())
|
|
14
|
+
*
|
|
15
|
+
* test('creates a user', async () => {
|
|
16
|
+
* const response = await app.request('/users', { method: 'POST', json: { name: 'Bo' } })
|
|
17
|
+
*
|
|
18
|
+
* expect(response.status).toBe(201)
|
|
19
|
+
* })
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* A single service needs no server: `createContainer(Module, { overrides })`.
|
|
23
|
+
*/
|
|
24
|
+
import { createApp } from '../app/app.js';
|
|
25
|
+
/**
|
|
26
|
+
* Creates `root` and serves it on a free port. Options are those of
|
|
27
|
+
* `createApp`: `overrides` replace providers; the logger is silent unless one is given.
|
|
28
|
+
*/
|
|
29
|
+
export const createTestApp = async (root, options = {}) => {
|
|
30
|
+
const app = await createApp(root, { logger: false, ...options });
|
|
31
|
+
const server = await app.listen({ port: 0, hostname: '127.0.0.1' });
|
|
32
|
+
const close = () => app.close();
|
|
33
|
+
return {
|
|
34
|
+
app,
|
|
35
|
+
url: server.url,
|
|
36
|
+
get: (token) => app.container.get(token),
|
|
37
|
+
request: (path, { json, ...init } = {}) => {
|
|
38
|
+
if (json === undefined) {
|
|
39
|
+
return fetch(new URL(path, server.url), init);
|
|
40
|
+
}
|
|
41
|
+
const headers = new Headers(init.headers);
|
|
42
|
+
headers.set('content-type', 'application/json');
|
|
43
|
+
return fetch(new URL(path, server.url), { ...init, headers, body: JSON.stringify(json) });
|
|
44
|
+
},
|
|
45
|
+
close,
|
|
46
|
+
[Symbol.asyncDispose]: close,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAqBzC;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,IAAkB,EAAE,OAAO,GAAe,EAAE,EAAoB,EAAE;IACpG,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;IAChE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;IACnE,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,CAAA;IAE/B,OAAO;QACL,GAAG;QACH,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QACxC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE;YACxC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAA;YAC/C,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAEzC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;YAE/C,OAAO,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC3F,CAAC;QACD,KAAK;QACL,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK;KAC7B,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Error utilities.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Removes the frames of the framework from the stack of an error about the
|
|
7
|
+
* application's code (a missing provider, an invalid route): the runtime then
|
|
8
|
+
* points at the application, not at the framework, and the message says the rest.
|
|
9
|
+
*/
|
|
10
|
+
export declare const hideFrameworkFrames: (error: Error) => void;
|
|
11
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,UAAW,KAAK,KAAG,IASlD,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Error utilities.
|
|
4
|
+
*/
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
/** Where the framework's own files are: `src/` from sources, `dist/` once built. */
|
|
7
|
+
const FRAMEWORK = fileURLToPath(new URL('../', import.meta.url));
|
|
8
|
+
/**
|
|
9
|
+
* Removes the frames of the framework from the stack of an error about the
|
|
10
|
+
* application's code (a missing provider, an invalid route): the runtime then
|
|
11
|
+
* points at the application, not at the framework, and the message says the rest.
|
|
12
|
+
*/
|
|
13
|
+
export const hideFrameworkFrames = (error) => {
|
|
14
|
+
if (error.stack === undefined) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
error.stack = error.stack
|
|
18
|
+
.split('\n')
|
|
19
|
+
.filter((line) => !(line.trimStart().startsWith('at ') && line.includes(FRAMEWORK)))
|
|
20
|
+
.join('\n');
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,oFAAoF;AACpF,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAEhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAY,EAAQ,EAAE;IACxD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAM;IACR,CAAC;IAED,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK;SACtB,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;SACnF,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC,CAAA"}
|
package/dist/utils/object.d.ts
CHANGED
|
@@ -11,4 +11,8 @@
|
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
13
|
export declare const createNullObject: <T extends object>() => T;
|
|
14
|
+
/**
|
|
15
|
+
* Public method names along the prototype chain, most derived first, without duplicates.
|
|
16
|
+
*/
|
|
17
|
+
export declare const methodNames: (instance: object) => string[];
|
|
14
18
|
//# sourceMappingURL=object.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../src/utils/object.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,OAAK,CAA6B,CAAA"}
|
|
1
|
+
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../src/utils/object.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,OAAK,CAA6B,CAAA;AAEnF;;GAEG;AACH,eAAO,MAAM,WAAW,aAAc,MAAM,KAAG,MAAM,EAkBpD,CAAA"}
|
package/dist/utils/object.js
CHANGED
|
@@ -11,4 +11,20 @@
|
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
13
|
export const createNullObject = () => Object.create(null);
|
|
14
|
+
/**
|
|
15
|
+
* Public method names along the prototype chain, most derived first, without duplicates.
|
|
16
|
+
*/
|
|
17
|
+
export const methodNames = (instance) => {
|
|
18
|
+
const names = [];
|
|
19
|
+
const seen = new Set(['constructor']);
|
|
20
|
+
for (let prototype = Object.getPrototypeOf(instance); prototype !== null && prototype !== Object.prototype; prototype = Object.getPrototypeOf(prototype)) {
|
|
21
|
+
for (const name of Object.getOwnPropertyNames(prototype)) {
|
|
22
|
+
if (!seen.has(name)) {
|
|
23
|
+
seen.add(name);
|
|
24
|
+
names.push(name);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return names;
|
|
29
|
+
};
|
|
14
30
|
//# sourceMappingURL=object.js.map
|
package/dist/utils/object.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object.js","sourceRoot":"","sources":["../../src/utils/object.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAwB,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAM,CAAA"}
|
|
1
|
+
{"version":3,"file":"object.js","sourceRoot":"","sources":["../../src/utils/object.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAwB,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAM,CAAA;AAEnF;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAY,EAAE;IACxD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,aAAa,CAAC,CAAC,CAAA;IAE7C,KACE,IAAI,SAAS,GAAkB,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,EAC9D,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,MAAM,CAAC,SAAS,EACpD,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,EAC5C,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBACd,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Decorators of WebSocket gateways, as in `@nestjs/websockets`.
|
|
4
|
+
*/
|
|
5
|
+
import type { Constructor } from '../di/index.ts';
|
|
6
|
+
/**
|
|
7
|
+
* Declares a gateway: WebSocket connections upgraded from `GET path`. List it
|
|
8
|
+
* in the `controllers` of its module: like a controller, it is an entry point
|
|
9
|
+
* the framework creates, and its guards run on the handshake.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* @WebSocketGateway('/chat')
|
|
13
|
+
* @UseGuards(JwtGuard)
|
|
14
|
+
* class ChatGateway {
|
|
15
|
+
* @SubscribeMessage('message')
|
|
16
|
+
* message(data: unknown, socket: GatewaySocket) {
|
|
17
|
+
* return { event: 'message', data }
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const WebSocketGateway: (path: string) => (target: Constructor<unknown>, _context: ClassDecoratorContext<Constructor<unknown>>) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Handles the frames `{ "event": event, "data": ... }` of a gateway. The
|
|
25
|
+
* method receives `(data, socket)`; what it returns, unless `undefined`, is
|
|
26
|
+
* sent back as JSON.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SubscribeMessage: (event: string) => <This, M extends (this: This, ...args: any[]) => unknown>(method: M, context: ClassMethodDecoratorContext<This, M>) => void;
|
|
29
|
+
export declare const getGatewayPath: (target: Constructor<unknown>) => string | undefined;
|
|
30
|
+
export declare const getSubscribedEvent: (method: object) => string | undefined;
|
|
31
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/websocket/decorators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAMjD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB,SACpB,MAAM,cACJ,WAAW,CAAC,OAAO,CAAC,YAAY,qBAAqB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAG,IAMtF,CAAA;AAEH;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UACnB,MAAM,MACb,IAAI,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,UAAU,CAAC,WAAW,2BAA2B,CAAC,IAAI,EAAE,CAAC,CAAC,KAAG,IAMpH,CAAA;AAEH,eAAO,MAAM,cAAc,WAAY,WAAW,CAAC,OAAO,CAAC,KAAG,MAAM,GAAG,SAAiC,CAAA;AAExG,eAAO,MAAM,kBAAkB,WAAY,MAAM,KAAG,MAAM,GAAG,SAA+B,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Decorators of WebSocket gateways, as in `@nestjs/websockets`.
|
|
4
|
+
*/
|
|
5
|
+
import { ControllerError } from '../http/errors.js';
|
|
6
|
+
const gateways = new WeakMap();
|
|
7
|
+
const events = new WeakMap();
|
|
8
|
+
/**
|
|
9
|
+
* Declares a gateway: WebSocket connections upgraded from `GET path`. List it
|
|
10
|
+
* in the `controllers` of its module: like a controller, it is an entry point
|
|
11
|
+
* the framework creates, and its guards run on the handshake.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* @WebSocketGateway('/chat')
|
|
15
|
+
* @UseGuards(JwtGuard)
|
|
16
|
+
* class ChatGateway {
|
|
17
|
+
* @SubscribeMessage('message')
|
|
18
|
+
* message(data: unknown, socket: GatewaySocket) {
|
|
19
|
+
* return { event: 'message', data }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export const WebSocketGateway = (path) => (target, _context) => {
|
|
25
|
+
if (!path.startsWith('/') || /[:*?]/.test(path)) {
|
|
26
|
+
throw new ControllerError('INVALID_PATH', `@WebSocketGateway('${path}'): a gateway path is static and starts with "/"`);
|
|
27
|
+
}
|
|
28
|
+
gateways.set(target, path);
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Handles the frames `{ "event": event, "data": ... }` of a gateway. The
|
|
32
|
+
* method receives `(data, socket)`; what it returns, unless `undefined`, is
|
|
33
|
+
* sent back as JSON.
|
|
34
|
+
*/
|
|
35
|
+
export const SubscribeMessage = (event) => (method, context) => {
|
|
36
|
+
if (context.static || context.private) {
|
|
37
|
+
throw new ControllerError('INVALID_HANDLER', `@SubscribeMessage('${event}') must decorate a public instance method`);
|
|
38
|
+
}
|
|
39
|
+
events.set(method, event);
|
|
40
|
+
};
|
|
41
|
+
export const getGatewayPath = (target) => gateways.get(target);
|
|
42
|
+
export const getSubscribedEvent = (method) => events.get(method);
|
|
43
|
+
//# sourceMappingURL=decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/websocket/decorators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEnD,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAgC,CAAA;AAC5D,MAAM,MAAM,GAAG,IAAI,OAAO,EAAkB,CAAA;AAE5C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,CAAC,IAAY,EAAE,EAAE,CACjB,CAAC,MAA4B,EAAE,QAAqD,EAAQ,EAAE;IAC5F,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,eAAe,CAAC,cAAc,EAAE,sBAAsB,IAAI,kDAAkD,CAAC,CAAA;IACzH,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;AAC5B,CAAC,CAAA;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,CAAC,KAAa,EAAE,EAAE,CAClB,CAA0D,MAAS,EAAE,OAA6C,EAAQ,EAAE;IAC1H,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,IAAI,eAAe,CAAC,iBAAiB,EAAE,sBAAsB,KAAK,2CAA2C,CAAC,CAAA;IACtH,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAC3B,CAAC,CAAA;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAA4B,EAAsB,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAExG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAsB,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Serving a gateway: the handshake goes through the route pipeline (guards
|
|
4
|
+
* and exception filters of the gateway), then frames are dispatched to its
|
|
5
|
+
* `@SubscribeMessage()` methods.
|
|
6
|
+
*
|
|
7
|
+
* The protocol is the one of Nest's `WsAdapter`: text frames holding
|
|
8
|
+
* `{ "event": string, "data": any }`. Frames that are not JSON, not such an
|
|
9
|
+
* object, or name no handled event are dropped silently, as anyone can send
|
|
10
|
+
* them; errors of the gateway's own code are reported.
|
|
11
|
+
*/
|
|
12
|
+
import type { ControllerEntry } from '../di/index.ts';
|
|
13
|
+
import type { Context } from '../http/context.ts';
|
|
14
|
+
import type { FilterStep, GuardStep } from '../http/pipeline.ts';
|
|
15
|
+
/** What a gateway socket carries. */
|
|
16
|
+
export interface GatewaySocketData {
|
|
17
|
+
/** Context of the handshake request: what its guards set is read with `context.get(key)`. */
|
|
18
|
+
readonly context: Context;
|
|
19
|
+
/** @internal */
|
|
20
|
+
readonly gateway: GatewayRuntime;
|
|
21
|
+
}
|
|
22
|
+
/** A connection of a gateway: Bun's `ServerWebSocket`, with `subscribe()`, `publish()`... */
|
|
23
|
+
export type GatewaySocket = Bun.ServerWebSocket<GatewaySocketData>;
|
|
24
|
+
/** `handleConnection(socket)`: called when a client is connected. */
|
|
25
|
+
export interface OnGatewayConnection {
|
|
26
|
+
handleConnection(socket: GatewaySocket): unknown;
|
|
27
|
+
}
|
|
28
|
+
/** `handleDisconnect(socket, code, reason)`: called when a connection is closed. */
|
|
29
|
+
export interface OnGatewayDisconnect {
|
|
30
|
+
handleDisconnect(socket: GatewaySocket, code: number, reason: string): unknown;
|
|
31
|
+
}
|
|
32
|
+
/** The live part of a gateway: its sockets and handlers. */
|
|
33
|
+
export declare class GatewayRuntime {
|
|
34
|
+
#private;
|
|
35
|
+
constructor(instance: object, onError: (error: unknown, req: Request) => void);
|
|
36
|
+
get events(): readonly string[];
|
|
37
|
+
open(socket: GatewaySocket): void;
|
|
38
|
+
message(socket: GatewaySocket, message: string | Buffer): void;
|
|
39
|
+
close(socket: GatewaySocket, code: number, reason: string): void;
|
|
40
|
+
/** Closes every connection, as the application shuts down. */
|
|
41
|
+
closeAll(): void;
|
|
42
|
+
}
|
|
43
|
+
/** Bun's handlers for every gateway of a server: each socket knows its gateway. */
|
|
44
|
+
export declare const websocketHandler: Bun.WebSocketHandler<GatewaySocketData>;
|
|
45
|
+
export interface GatewayParts {
|
|
46
|
+
readonly entry: ControllerEntry;
|
|
47
|
+
readonly path: string;
|
|
48
|
+
readonly guards: readonly GuardStep[];
|
|
49
|
+
readonly filters: readonly FilterStep[];
|
|
50
|
+
readonly metadata: ReadonlyMap<symbol, unknown>;
|
|
51
|
+
readonly onError: (error: unknown, req: Request) => void;
|
|
52
|
+
}
|
|
53
|
+
/** A gateway ready to serve: its native route and its runtime. */
|
|
54
|
+
export interface BuiltGateway {
|
|
55
|
+
readonly path: string;
|
|
56
|
+
readonly runtime: GatewayRuntime;
|
|
57
|
+
/** The native route of the handshake, for `Bun.serve({ routes })`. */
|
|
58
|
+
readonly handle: (req: Bun.BunRequest, server: Bun.Server<GatewaySocketData>) => Response | undefined | Promise<Response | undefined>;
|
|
59
|
+
}
|
|
60
|
+
export declare const buildGateway: (parts: GatewayParts) => BuiltGateway;
|
|
61
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/websocket/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAErD,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,oBAAoB,CAAA;AAE5D,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAKhE,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,6FAA6F;IAC7F,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,gBAAgB;IAChB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;CACjC;AAED,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAA;AAElE,qEAAqE;AACrE,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAA;CACjD;AAED,oFAAoF;AACpF,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;CAC/E;AAoBD,4DAA4D;AAC5D,qBAAa,cAAc;;IAMzB,YAAY,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,EAY5E;IAED,IAAI,MAAM,IAAI,SAAS,MAAM,EAAE,CAE9B;IAED,IAAI,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAGhC;IAED,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB7D;IAED,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/D;IAED,8DAA8D;IAC9D,QAAQ,IAAI,IAAI,CAIf;CAqBF;AAkBD,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,EAAE,GAAG,CAAC,gBAAgB,CAAC,iBAAiB,CAIpE,CAAA;AAKD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/C,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;CACzD;AAED,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;IAChC,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAA;CACtI;AAED,eAAO,MAAM,YAAY,UAAW,YAAY,KAAG,YA2BlD,CAAA"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Serving a gateway: the handshake goes through the route pipeline (guards
|
|
4
|
+
* and exception filters of the gateway), then frames are dispatched to its
|
|
5
|
+
* `@SubscribeMessage()` methods.
|
|
6
|
+
*
|
|
7
|
+
* The protocol is the one of Nest's `WsAdapter`: text frames holding
|
|
8
|
+
* `{ "event": string, "data": any }`. Frames that are not JSON, not such an
|
|
9
|
+
* object, or name no handled event are dropped silently, as anyone can send
|
|
10
|
+
* them; errors of the gateway's own code are reported.
|
|
11
|
+
*/
|
|
12
|
+
import { parseJson } from '../http/body.js';
|
|
13
|
+
import { createPipeline } from '../http/pipeline.js';
|
|
14
|
+
import { methodNames } from '../utils/object.js';
|
|
15
|
+
import { isThenable } from '../utils/promise.js';
|
|
16
|
+
import { getSubscribedEvent } from './decorators.js';
|
|
17
|
+
/** Code of the close frame sent when the application shuts down. */
|
|
18
|
+
const GOING_AWAY = 1001;
|
|
19
|
+
/** Runs `fn`, reporting a synchronous or asynchronous failure. */
|
|
20
|
+
const settle = (fn, report, then) => {
|
|
21
|
+
try {
|
|
22
|
+
const result = fn();
|
|
23
|
+
if (isThenable(result)) {
|
|
24
|
+
Promise.resolve(result).then(then, report);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
then?.(result);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
report(error);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/** The live part of a gateway: its sockets and handlers. */
|
|
35
|
+
export class GatewayRuntime {
|
|
36
|
+
#instance;
|
|
37
|
+
#handlers = new Map();
|
|
38
|
+
#sockets = new Set();
|
|
39
|
+
#onError;
|
|
40
|
+
constructor(instance, onError) {
|
|
41
|
+
this.#instance = instance;
|
|
42
|
+
this.#onError = onError;
|
|
43
|
+
for (const name of methodNames(instance)) {
|
|
44
|
+
const method = this.#instance[name];
|
|
45
|
+
const event = getSubscribedEvent(method);
|
|
46
|
+
if (event !== undefined) {
|
|
47
|
+
this.#handlers.set(event, method);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
get events() {
|
|
52
|
+
return [...this.#handlers.keys()];
|
|
53
|
+
}
|
|
54
|
+
open(socket) {
|
|
55
|
+
this.#sockets.add(socket);
|
|
56
|
+
this.#call('handleConnection', socket, [socket]);
|
|
57
|
+
}
|
|
58
|
+
message(socket, message) {
|
|
59
|
+
const frame = typeof message === 'string' ? parseFrame(message) : undefined;
|
|
60
|
+
const handler = frame === undefined ? undefined : this.#handlers.get(frame.event);
|
|
61
|
+
if (handler === undefined) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
settle(() => handler.call(this.#instance, frame.data, socket), (error) => this.#onError(error, socket.data.context.req), (result) => {
|
|
65
|
+
if (result !== undefined) {
|
|
66
|
+
this.#send(socket, result);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
close(socket, code, reason) {
|
|
71
|
+
this.#sockets.delete(socket);
|
|
72
|
+
this.#call('handleDisconnect', socket, [socket, code, reason]);
|
|
73
|
+
}
|
|
74
|
+
/** Closes every connection, as the application shuts down. */
|
|
75
|
+
closeAll() {
|
|
76
|
+
for (const socket of this.#sockets) {
|
|
77
|
+
socket.close(GOING_AWAY, 'Server shutting down');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
#call(hook, socket, args) {
|
|
81
|
+
const fn = this.#instance[hook];
|
|
82
|
+
if (typeof fn === 'function') {
|
|
83
|
+
settle(() => fn.apply(this.#instance, args), (error) => this.#onError(error, socket.data.context.req));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
#send(socket, value) {
|
|
87
|
+
try {
|
|
88
|
+
// JSON.stringify throws on cycles and bigints: an application error, reported.
|
|
89
|
+
socket.send(JSON.stringify(value));
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
this.#onError(error, socket.data.context.req);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const parseFrame = (message) => {
|
|
97
|
+
let frame;
|
|
98
|
+
try {
|
|
99
|
+
frame = parseJson(message);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
if (typeof frame !== 'object' || frame === null || typeof frame.event !== 'string') {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
return frame;
|
|
108
|
+
};
|
|
109
|
+
/** Bun's handlers for every gateway of a server: each socket knows its gateway. */
|
|
110
|
+
export const websocketHandler = {
|
|
111
|
+
open: (socket) => socket.data.gateway.open(socket),
|
|
112
|
+
message: (socket, message) => socket.data.gateway.message(socket, message),
|
|
113
|
+
close: (socket, code, reason) => socket.data.gateway.close(socket, code, reason),
|
|
114
|
+
};
|
|
115
|
+
/** Result of the handshake once the connection is upgraded: Bun wants no response then. */
|
|
116
|
+
const UPGRADED = Symbol('upgraded');
|
|
117
|
+
export const buildGateway = (parts) => {
|
|
118
|
+
const runtime = new GatewayRuntime(parts.entry.instance, parts.onError);
|
|
119
|
+
const route = { controller: parts.entry.controller, handler: 'handshake', method: 'GET', path: parts.path, metadata: parts.metadata };
|
|
120
|
+
// The pipeline is built once; the server of each request is found here.
|
|
121
|
+
const servers = new WeakMap();
|
|
122
|
+
const pipeline = createPipeline({
|
|
123
|
+
route,
|
|
124
|
+
guards: parts.guards,
|
|
125
|
+
interceptors: [],
|
|
126
|
+
filters: parts.filters,
|
|
127
|
+
invoke: (ctx) => servers.get(ctx.req).upgrade(ctx.req, { data: { context: ctx, gateway: runtime } })
|
|
128
|
+
? UPGRADED
|
|
129
|
+
: new Response('Expected a WebSocket upgrade', { status: 426, headers: { upgrade: 'websocket' } }),
|
|
130
|
+
respond: (value) => (value === UPGRADED ? undefined : value),
|
|
131
|
+
onError: parts.onError,
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
path: parts.path,
|
|
135
|
+
runtime,
|
|
136
|
+
handle: (req, server) => {
|
|
137
|
+
servers.set(req, server);
|
|
138
|
+
return pipeline(req, {});
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/websocket/gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* WebSocket gateways, as in `@nestjs/websockets`.
|
|
4
|
+
*/
|
|
5
|
+
export { SubscribeMessage, WebSocketGateway } from './decorators.ts';
|
|
6
|
+
export type { GatewaySocket, GatewaySocketData, OnGatewayConnection, OnGatewayDisconnect } from './gateway.ts';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACpE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getsoda/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Class-based web framework for Bun: modules, dependency injection and decorators like Nest, on Bun's native router",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -32,6 +32,14 @@
|
|
|
32
32
|
"types": "./dist/jwt/index.d.ts",
|
|
33
33
|
"default": "./dist/jwt/index.js"
|
|
34
34
|
},
|
|
35
|
+
"./openapi": {
|
|
36
|
+
"types": "./dist/openapi/index.d.ts",
|
|
37
|
+
"default": "./dist/openapi/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./testing": {
|
|
40
|
+
"types": "./dist/testing/index.d.ts",
|
|
41
|
+
"default": "./dist/testing/index.js"
|
|
42
|
+
},
|
|
35
43
|
"./package.json": "./package.json"
|
|
36
44
|
},
|
|
37
45
|
"types": "./dist/index.d.ts",
|
|
@@ -47,5 +55,8 @@
|
|
|
47
55
|
"scripts": {
|
|
48
56
|
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
49
57
|
"prepublishOnly": "cd ../.. && bun run lint && bun run typecheck && bun run test && cd packages/core && bun run build"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"zod": "4.6.7"
|
|
50
61
|
}
|
|
51
62
|
}
|