@feathersjs/transport-commons 5.0.0-pre.2 → 5.0.0-pre.20
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/CHANGELOG.md +184 -0
- package/LICENSE +1 -1
- package/README.md +2 -2
- package/lib/channels/index.d.ts +13 -11
- package/lib/channels/index.js +11 -11
- package/lib/channels/index.js.map +1 -1
- package/lib/channels/mixins.d.ts +2 -2
- package/lib/channels/mixins.js +4 -7
- package/lib/channels/mixins.js.map +1 -1
- package/lib/client.js +3 -6
- package/lib/client.js.map +1 -1
- package/lib/http.d.ts +35 -0
- package/lib/http.js +77 -0
- package/lib/http.js.map +1 -0
- package/lib/index.d.ts +3 -2
- package/lib/index.js +27 -1
- package/lib/index.js.map +1 -1
- package/lib/routing/index.d.ts +9 -4
- package/lib/routing/index.js +20 -16
- package/lib/routing/index.js.map +1 -1
- package/lib/routing/router.d.ts +5 -3
- package/lib/routing/router.js +35 -23
- package/lib/routing/router.js.map +1 -1
- package/lib/socket/index.js +7 -10
- package/lib/socket/index.js.map +1 -1
- package/lib/socket/utils.js +43 -54
- package/lib/socket/utils.js.map +1 -1
- package/package.json +17 -15
- package/src/channels/index.ts +17 -15
- package/src/channels/mixins.ts +4 -4
- package/src/client.ts +2 -2
- package/src/http.ts +95 -0
- package/src/index.ts +10 -2
- package/src/routing/index.ts +28 -23
- package/src/routing/router.ts +33 -22
- package/src/socket/index.ts +2 -2
- package/src/socket/utils.ts +6 -6
package/src/http.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { MethodNotAllowed } from '@feathersjs/errors/lib';
|
|
2
|
+
import { HookContext, NullableId, Params } from '@feathersjs/feathers';
|
|
3
|
+
import encodeUrl from 'encodeurl';
|
|
4
|
+
|
|
5
|
+
export const METHOD_HEADER = 'x-service-method';
|
|
6
|
+
|
|
7
|
+
export interface ServiceParams {
|
|
8
|
+
id: NullableId,
|
|
9
|
+
data: any,
|
|
10
|
+
params: Params
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const statusCodes = {
|
|
14
|
+
created: 201,
|
|
15
|
+
noContent: 204,
|
|
16
|
+
methodNotAllowed: 405,
|
|
17
|
+
success: 200,
|
|
18
|
+
seeOther: 303
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const knownMethods: { [key: string]: string } = {
|
|
22
|
+
post: 'create',
|
|
23
|
+
patch: 'patch',
|
|
24
|
+
put: 'update',
|
|
25
|
+
delete: 'remove'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function getServiceMethod (_httpMethod: string, id: unknown, headerOverride?: string) {
|
|
29
|
+
const httpMethod = _httpMethod.toLowerCase();
|
|
30
|
+
|
|
31
|
+
if (httpMethod === 'post' && headerOverride) {
|
|
32
|
+
return headerOverride;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const mappedMethod = knownMethods[httpMethod];
|
|
36
|
+
|
|
37
|
+
if (mappedMethod) {
|
|
38
|
+
return mappedMethod;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (httpMethod === 'get') {
|
|
42
|
+
return id === null ? 'find' : 'get';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
throw new MethodNotAllowed(`Method ${_httpMethod} not allowed`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const argumentsFor = {
|
|
49
|
+
get: ({ id, params }: ServiceParams) => [ id, params ],
|
|
50
|
+
find: ({ params }: ServiceParams) => [ params ],
|
|
51
|
+
create: ({ data, params }: ServiceParams) => [ data, params ],
|
|
52
|
+
update: ({ id, data, params }: ServiceParams) => [ id, data, params ],
|
|
53
|
+
patch: ({ id, data, params }: ServiceParams) => [ id, data, params ],
|
|
54
|
+
remove: ({ id, params }: ServiceParams) => [ id, params ],
|
|
55
|
+
default: ({ data, params }: ServiceParams) => [ data, params ]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getStatusCode (context: HookContext, body: any, location: string|string[]) {
|
|
59
|
+
const { http = {} } = context;
|
|
60
|
+
|
|
61
|
+
if (http.status) {
|
|
62
|
+
return http.status;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (context.method === 'create') {
|
|
66
|
+
return statusCodes.created;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (location !== undefined) {
|
|
70
|
+
return statusCodes.seeOther;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!body) {
|
|
74
|
+
return statusCodes.noContent;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return statusCodes.success;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function getResponse (context: HookContext) {
|
|
81
|
+
const { http = {} } = context;
|
|
82
|
+
const body = context.dispatch !== undefined ? context.dispatch : context.result;
|
|
83
|
+
|
|
84
|
+
let headers = http.headers || {};
|
|
85
|
+
let location = headers.Location;
|
|
86
|
+
|
|
87
|
+
if (http.location !== undefined) {
|
|
88
|
+
location = encodeUrl(http.location);
|
|
89
|
+
headers = { ...headers, Location: location };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const status = getStatusCode(context, body, location);
|
|
93
|
+
|
|
94
|
+
return { status, headers, body };
|
|
95
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { socket } from './socket';
|
|
2
2
|
import { routing } from './routing';
|
|
3
|
-
import { channels } from './channels';
|
|
3
|
+
import { channels, Channel, CombinedChannel, RealTimeConnection } from './channels';
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export * as http from './http';
|
|
6
|
+
export {
|
|
7
|
+
socket,
|
|
8
|
+
routing,
|
|
9
|
+
channels,
|
|
10
|
+
Channel,
|
|
11
|
+
CombinedChannel,
|
|
12
|
+
RealTimeConnection
|
|
13
|
+
};
|
package/src/routing/index.ts
CHANGED
|
@@ -1,45 +1,50 @@
|
|
|
1
|
-
import { Application, Service } from '@feathersjs/feathers';
|
|
1
|
+
import { Application, Service, ServiceOptions } from '@feathersjs/feathers';
|
|
2
2
|
import { Router } from './router';
|
|
3
3
|
|
|
4
4
|
declare module '@feathersjs/feathers/lib/declarations' {
|
|
5
5
|
interface RouteLookup {
|
|
6
|
-
service: Service
|
|
7
|
-
params: { [key: string]:
|
|
6
|
+
service: Service,
|
|
7
|
+
params: { [key: string]: any }
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
interface Application<
|
|
11
|
-
routes: Router<
|
|
10
|
+
interface Application<Services, Settings> { // eslint-disable-line
|
|
11
|
+
routes: Router<{
|
|
12
|
+
service: Service,
|
|
13
|
+
params?: { [key: string]: any }
|
|
14
|
+
}>;
|
|
12
15
|
lookup (path: string): RouteLookup;
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export * from './router';
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const lookup = function (this: Application, path: string) {
|
|
22
|
+
const result = this.routes.lookup(path);
|
|
23
|
+
|
|
24
|
+
if (result === null) {
|
|
25
|
+
return null;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
const
|
|
28
|
+
const { params: colonParams, data: { service, params: dataParams } } = result;
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
routes,
|
|
27
|
-
lookup (this: Application, path: string) {
|
|
28
|
-
const result = this.routes.lookup(path);
|
|
30
|
+
const params = dataParams ? { ...dataParams, ...colonParams } : colonParams;
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
return { service, params };
|
|
33
|
+
};
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
export const routing = () => (app: Application) => {
|
|
36
|
+
if (typeof app.lookup === 'function') {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
40
|
+
app.routes = new Router();
|
|
41
|
+
app.lookup = lookup;
|
|
39
42
|
|
|
40
43
|
// Add a mixin that registers a service on the router
|
|
41
|
-
app.mixins.push((service: Service
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
app.mixins.push((service: Service, path: string, options: ServiceOptions) => {
|
|
45
|
+
const { routeParams: params = {} } = options;
|
|
46
|
+
|
|
47
|
+
app.routes.insert(path, { service, params });
|
|
48
|
+
app.routes.insert(`${path}/:__id`, { service, params });
|
|
44
49
|
});
|
|
45
50
|
};
|
package/src/routing/router.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { stripSlashes } from '@feathersjs/commons';
|
|
2
|
-
import { BadRequest } from '@feathersjs/errors';
|
|
3
2
|
|
|
4
3
|
export interface LookupData {
|
|
5
4
|
params: { [key: string]: string };
|
|
@@ -12,62 +11,74 @@ export interface LookupResult<T> extends LookupData {
|
|
|
12
11
|
export class RouteNode<T = any> {
|
|
13
12
|
data?: T;
|
|
14
13
|
children: { [key: string]: RouteNode } = {};
|
|
15
|
-
|
|
14
|
+
placeholders: RouteNode[] = [];
|
|
16
15
|
|
|
17
|
-
constructor (public name: string) {}
|
|
16
|
+
constructor (public name: string, public depth: number) {}
|
|
18
17
|
|
|
19
18
|
insert (path: string[], data: T): RouteNode<T> {
|
|
20
|
-
if (
|
|
19
|
+
if (this.depth === path.length) {
|
|
20
|
+
if (this.data !== undefined) {
|
|
21
|
+
throw new Error(`Path ${path.join('/')} already exists`);
|
|
22
|
+
}
|
|
23
|
+
|
|
21
24
|
this.data = data;
|
|
22
25
|
return this;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
const
|
|
28
|
+
const current = path[this.depth];
|
|
29
|
+
const nextDepth = this.depth + 1;
|
|
26
30
|
|
|
27
31
|
if (current.startsWith(':')) {
|
|
28
|
-
|
|
29
|
-
const
|
|
32
|
+
// Insert a placeholder node like /messages/:id
|
|
33
|
+
const placeholderName = current.substring(1);
|
|
34
|
+
let placeholder = this.placeholders.find(p => p.name === placeholderName);
|
|
30
35
|
|
|
31
36
|
if (!placeholder) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
throw new BadRequest(`Can not add route with placeholder ':${name}' because placeholder ':${placeholder.name}' already exists`);
|
|
37
|
+
placeholder = new RouteNode(placeholderName, nextDepth);
|
|
38
|
+
this.placeholders.push(placeholder);
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
return
|
|
41
|
+
return placeholder.insert(path, data);
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
const child = this.children[current] || new RouteNode(current, nextDepth);
|
|
45
|
+
|
|
46
|
+
this.children[current] = child;
|
|
41
47
|
|
|
42
|
-
return
|
|
48
|
+
return child.insert(path, data);
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
lookup (path: string[], info: LookupData): LookupResult<T>|null {
|
|
46
|
-
if (path.length ===
|
|
47
|
-
return {
|
|
52
|
+
if (path.length === this.depth) {
|
|
53
|
+
return this.data === undefined ? null : {
|
|
48
54
|
...info,
|
|
49
55
|
data: this.data
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
const
|
|
59
|
+
const current = path[this.depth];
|
|
54
60
|
const child = this.children[current];
|
|
55
61
|
|
|
56
62
|
if (child) {
|
|
57
|
-
return child.lookup(
|
|
63
|
+
return child.lookup(path, info);
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
// This will return the first placeholder that matches early
|
|
67
|
+
for(const placeholder of this.placeholders) {
|
|
68
|
+
const result = placeholder.lookup(path, info);
|
|
69
|
+
|
|
70
|
+
if (result !== null) {
|
|
71
|
+
result.params[placeholder.name] = current;
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
return null;
|
|
66
77
|
}
|
|
67
78
|
}
|
|
68
79
|
|
|
69
|
-
export class Router<T> {
|
|
70
|
-
root: RouteNode<T> = new RouteNode<T>('')
|
|
80
|
+
export class Router<T = any> {
|
|
81
|
+
constructor (public root: RouteNode<T> = new RouteNode<T>('', 0)) {}
|
|
71
82
|
|
|
72
83
|
getPath (path: string) {
|
|
73
84
|
return stripSlashes(path).split('/');
|
package/src/socket/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Application, getServiceOptions, Params } from '@feathersjs/feathers';
|
|
2
|
-
import
|
|
2
|
+
import { createDebug } from '@feathersjs/commons';
|
|
3
3
|
import { channels } from '../channels';
|
|
4
4
|
import { routing } from '../routing';
|
|
5
5
|
import { getDispatcher, runMethod } from './utils';
|
|
6
6
|
import { RealTimeConnection } from '../channels/channel/base';
|
|
7
7
|
|
|
8
|
-
const debug =
|
|
8
|
+
const debug = createDebug('@feathersjs/transport-commons');
|
|
9
9
|
|
|
10
10
|
export interface SocketOptions {
|
|
11
11
|
done: Promise<any>;
|
package/src/socket/utils.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import Debug from 'debug';
|
|
2
|
-
import isEqual from 'lodash/isEqual';
|
|
3
|
-
import { NotFound, MethodNotAllowed, BadRequest } from '@feathersjs/errors';
|
|
4
1
|
import { HookContext, Application, createContext, getServiceOptions } from '@feathersjs/feathers';
|
|
2
|
+
import { NotFound, MethodNotAllowed, BadRequest } from '@feathersjs/errors';
|
|
3
|
+
import { createDebug } from '@feathersjs/commons';
|
|
4
|
+
import isEqual from 'lodash/isEqual';
|
|
5
5
|
import { CombinedChannel } from '../channels/channel/combined';
|
|
6
6
|
import { RealTimeConnection } from '../channels/channel/base';
|
|
7
7
|
|
|
8
|
-
const debug =
|
|
8
|
+
const debug = createDebug('@feathersjs/transport-commons');
|
|
9
9
|
|
|
10
10
|
export const DEFAULT_PARAMS_POSITION = 1;
|
|
11
11
|
|
|
@@ -91,7 +91,7 @@ export async function runMethod (app: Application, connection: RealTimeConnectio
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
const position = paramsPositions[method] !== undefined ? paramsPositions[method] : DEFAULT_PARAMS_POSITION;
|
|
94
|
-
const query = methodArgs[position]
|
|
94
|
+
const query = Object.assign({}, methodArgs[position]);
|
|
95
95
|
// `params` have to be re-mapped to the query and added with the route
|
|
96
96
|
const params = Object.assign({ query, route, connection }, connection);
|
|
97
97
|
|
|
@@ -108,7 +108,7 @@ export async function runMethod (app: Application, connection: RealTimeConnectio
|
|
|
108
108
|
|
|
109
109
|
debug(`Returned successfully ${trace}`, result);
|
|
110
110
|
callback(null, result);
|
|
111
|
-
} catch (error) {
|
|
111
|
+
} catch (error: any) {
|
|
112
112
|
handleError(error);
|
|
113
113
|
}
|
|
114
114
|
}
|