@streamlayer/sdk-web-api 0.18.0 → 0.19.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/lib/grpc/queries/user.d.ts +3 -3
- package/lib/grpc/queries/user.js +3 -8
- package/lib/grpc/subscription.d.ts +24 -6
- package/lib/grpc/subscription.js +95 -29
- package/lib/grpc/transport.d.ts +6 -6
- package/lib/grpc/transport.js +9 -17
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/utils/devtools.js +16 -5
- package/lib/utils/grpc-stub.js +1 -1
- package/package.json +10 -10
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { ReadableAtom } from 'nanostores';
|
|
2
|
-
import type { BypassAuthRequest
|
|
2
|
+
import type { BypassAuthRequest } from '@streamlayer/sl-eslib/users/users_pb';
|
|
3
3
|
import { PlainMessage } from '@bufbuild/protobuf';
|
|
4
4
|
import { Transport } from '../transport';
|
|
5
5
|
export declare const $user: ($userToken: ReadableAtom<string | undefined>, transport: Transport) => import("@nanostores/query").FetcherStore<import("@streamlayer/sl-eslib/users/users_pb").MeResponse, any>;
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const bypassLogin: (transport: Transport) => ({ userKey, schema, init }: PlainMessage<BypassAuthRequest>) => Promise<import("@streamlayer/sl-eslib/users/users_pb").BypassAuthResponse>;
|
|
7
7
|
export declare const bypassAuth: (transport: Transport, params: {
|
|
8
8
|
userKey?: string;
|
|
9
9
|
schema?: string;
|
|
10
10
|
init?: boolean;
|
|
11
|
-
}) => Promise<BypassAuthResponse>;
|
|
11
|
+
}) => Promise<import("@streamlayer/sl-eslib/users/users_pb").BypassAuthResponse>;
|
|
12
12
|
export declare const $userSettings: ($userToken: ReadableAtom<string | undefined>, transport: Transport) => import("@nanostores/query").FetcherStore<import("@streamlayer/sl-eslib/sdkSettings/client/client_pb").ClientSettings | undefined, any>;
|
|
13
13
|
export declare const register: (transport: Transport, phone: string) => Promise<import("@streamlayer/sl-eslib/users/users_pb").RegisterResponse>;
|
package/lib/grpc/queries/user.js
CHANGED
|
@@ -12,14 +12,9 @@ export const $user = ($userToken, transport) => {
|
|
|
12
12
|
fetcher: () => client.me({}),
|
|
13
13
|
});
|
|
14
14
|
};
|
|
15
|
-
export const
|
|
16
|
-
const { client
|
|
17
|
-
return
|
|
18
|
-
const [updateCache] = getCacheUpdater(queryKeyStr);
|
|
19
|
-
const user = await client.bypassAuth({ userKey, schema, init });
|
|
20
|
-
updateCache(user);
|
|
21
|
-
return user;
|
|
22
|
-
});
|
|
15
|
+
export const bypassLogin = (transport) => {
|
|
16
|
+
const { client } = transport.createPromiseClient(Users, { method: 'bypassAuth' });
|
|
17
|
+
return ({ userKey, schema, init }) => client.bypassAuth({ userKey, schema, init });
|
|
23
18
|
};
|
|
24
19
|
export const bypassAuth = (transport, params) => {
|
|
25
20
|
const { client } = transport.createPromiseClient(Users, { method: 'bypassAuth' });
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PromiseClient } from '@connectrpc/connect';
|
|
2
2
|
import { Atom } from 'nanostores';
|
|
3
3
|
import type { ServiceType, Message, PlainMessage, MethodInfoServerStreaming } from '@bufbuild/protobuf';
|
|
4
4
|
import { Transport } from './transport';
|
|
5
|
+
type StreamPromiseClient<T extends ServiceType> = {
|
|
6
|
+
[P in keyof PromiseClient<T> as T['methods'][P] extends MethodInfoServerStreaming<any, any> ? P : never]: T['methods'][P] extends MethodInfoServerStreaming<any, any> ? PromiseClient<T>[P] : never;
|
|
7
|
+
};
|
|
5
8
|
type StreamMethods<T extends ServiceType> = {
|
|
6
|
-
[P in keyof
|
|
9
|
+
[P in keyof StreamPromiseClient<T>]: P;
|
|
7
10
|
};
|
|
8
|
-
export type StreamMethod<T extends ServiceType> = StreamMethods<T>[keyof StreamMethods<T>] extends keyof
|
|
11
|
+
export type StreamMethod<T extends ServiceType> = StreamMethods<T>[keyof StreamMethods<T>] extends keyof StreamPromiseClient<T> ? StreamMethods<T>[keyof StreamMethods<T>] : never;
|
|
9
12
|
declare enum ServerStreamSubscriptionStatus {
|
|
10
13
|
Init = "init",
|
|
11
14
|
Ready = "ready",
|
|
@@ -13,21 +16,28 @@ declare enum ServerStreamSubscriptionStatus {
|
|
|
13
16
|
Connected = "connected",
|
|
14
17
|
Disconnected = "disconnected",
|
|
15
18
|
Failed = "failed",
|
|
19
|
+
Reconnect = "reconnect",
|
|
16
20
|
Reconnecting = "reconnecting"
|
|
17
21
|
}
|
|
18
22
|
export type ServerStreamSubscriptionOptions = {
|
|
19
23
|
name: string;
|
|
20
24
|
withStore?: boolean;
|
|
25
|
+
reconnectDelay?: number;
|
|
26
|
+
reconnectMaxDelay?: number;
|
|
27
|
+
reconnectMaxAttempts?: number;
|
|
21
28
|
};
|
|
22
|
-
export declare class ServerStreamSubscription<T extends ServiceType, Request extends Message<Request>, Response extends Message<Response>, M extends
|
|
29
|
+
export declare class ServerStreamSubscription<T extends ServiceType, Request extends Message<Request>, Response extends Message<Response>, M extends keyof StreamMethods<T> = keyof StreamMethods<T>, Method extends StreamPromiseClient<T>[M] = StreamPromiseClient<T>[M]> {
|
|
23
30
|
params: Atom<PlainMessage<Request>> | PlainMessage<Request>;
|
|
24
|
-
private
|
|
31
|
+
private streamCancel?;
|
|
25
32
|
private method;
|
|
26
|
-
private
|
|
33
|
+
private options;
|
|
27
34
|
private headers;
|
|
28
35
|
private listeners;
|
|
29
36
|
private state;
|
|
30
37
|
private store?;
|
|
38
|
+
private paramsListener?;
|
|
39
|
+
private reconnectTimeout?;
|
|
40
|
+
private attempt;
|
|
31
41
|
constructor(headers: Transport['$headers'], method: Method, params: Atom<PlainMessage<Request>> | PlainMessage<Request>, options: ServerStreamSubscriptionOptions);
|
|
32
42
|
updateState: (status: ServerStreamSubscriptionStatus) => void;
|
|
33
43
|
addStateLog: (msg: string) => void;
|
|
@@ -35,9 +45,17 @@ export declare class ServerStreamSubscription<T extends ServiceType, Request ext
|
|
|
35
45
|
removeListener: (name: string) => void;
|
|
36
46
|
connect: () => void;
|
|
37
47
|
disconnect: () => void;
|
|
48
|
+
/**
|
|
49
|
+
* Reconnect after delay, if not already reconnecting, otherwise do nothing
|
|
50
|
+
*/
|
|
38
51
|
reconnect: () => void;
|
|
39
52
|
getStore: () => import("nanostores").WritableAtom<Response | null | undefined> | undefined;
|
|
40
53
|
private onData;
|
|
54
|
+
/**
|
|
55
|
+
* Disconnect if error is not instance of ConnectError or stream is Canceled,
|
|
56
|
+
* Reconnect in other cases
|
|
57
|
+
* Do nothing if error is undefined
|
|
58
|
+
*/
|
|
41
59
|
private onStreamError;
|
|
42
60
|
}
|
|
43
61
|
export {};
|
package/lib/grpc/subscription.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MapStore, SingleStore, createMapStore, createSingleStore } from '@streamlayer/sdk-web-interfaces';
|
|
2
|
-
import { Code } from '@connectrpc/connect';
|
|
2
|
+
import { ConnectError, Code } from '@connectrpc/connect';
|
|
3
3
|
var ServerStreamSubscriptionStatus;
|
|
4
4
|
(function (ServerStreamSubscriptionStatus) {
|
|
5
5
|
ServerStreamSubscriptionStatus["Init"] = "init";
|
|
@@ -8,17 +8,21 @@ var ServerStreamSubscriptionStatus;
|
|
|
8
8
|
ServerStreamSubscriptionStatus["Connected"] = "connected";
|
|
9
9
|
ServerStreamSubscriptionStatus["Disconnected"] = "disconnected";
|
|
10
10
|
ServerStreamSubscriptionStatus["Failed"] = "failed";
|
|
11
|
+
ServerStreamSubscriptionStatus["Reconnect"] = "reconnect";
|
|
11
12
|
ServerStreamSubscriptionStatus["Reconnecting"] = "reconnecting";
|
|
12
13
|
})(ServerStreamSubscriptionStatus || (ServerStreamSubscriptionStatus = {}));
|
|
13
14
|
export class ServerStreamSubscription {
|
|
14
15
|
params;
|
|
15
|
-
|
|
16
|
+
streamCancel;
|
|
16
17
|
method;
|
|
17
|
-
|
|
18
|
+
options;
|
|
18
19
|
headers;
|
|
19
20
|
listeners;
|
|
20
21
|
state;
|
|
21
22
|
store;
|
|
23
|
+
paramsListener;
|
|
24
|
+
reconnectTimeout;
|
|
25
|
+
attempt = 0;
|
|
22
26
|
constructor(headers, method, params, options) {
|
|
23
27
|
const initState = {
|
|
24
28
|
status: ServerStreamSubscriptionStatus.Init,
|
|
@@ -26,7 +30,13 @@ export class ServerStreamSubscription {
|
|
|
26
30
|
log: [],
|
|
27
31
|
};
|
|
28
32
|
this.state = new MapStore(createMapStore(initState), `subscription:${options.name}:state`);
|
|
29
|
-
this.
|
|
33
|
+
this.options = {
|
|
34
|
+
...options,
|
|
35
|
+
reconnectDelay: options.reconnectDelay ?? 1000,
|
|
36
|
+
reconnectMaxDelay: options.reconnectMaxDelay ?? 30000,
|
|
37
|
+
reconnectMaxAttempts: options.reconnectMaxAttempts ?? 10,
|
|
38
|
+
withStore: options.withStore ?? false,
|
|
39
|
+
};
|
|
30
40
|
this.headers = headers;
|
|
31
41
|
this.listeners = new Map();
|
|
32
42
|
this.params = params;
|
|
@@ -35,8 +45,11 @@ export class ServerStreamSubscription {
|
|
|
35
45
|
this.store = new SingleStore(createSingleStore(null), `subscription:${options.name}:store`);
|
|
36
46
|
}
|
|
37
47
|
if ('subscribe' in params && typeof params.subscribe === 'function') {
|
|
38
|
-
params.subscribe(() => {
|
|
39
|
-
this.
|
|
48
|
+
this.paramsListener = params.subscribe((newParams) => {
|
|
49
|
+
if (this.state.getValue('status') === ServerStreamSubscriptionStatus.Connected) {
|
|
50
|
+
this.addStateLog(`params updated, reconnect => ${JSON.stringify(newParams)}`);
|
|
51
|
+
this.reconnect();
|
|
52
|
+
}
|
|
40
53
|
});
|
|
41
54
|
}
|
|
42
55
|
this.updateState(ServerStreamSubscriptionStatus.Ready);
|
|
@@ -52,7 +65,7 @@ export class ServerStreamSubscription {
|
|
|
52
65
|
};
|
|
53
66
|
addListener = (name, listener) => {
|
|
54
67
|
if (this.listeners.has(name)) {
|
|
55
|
-
this.addStateLog(`listener '${name}' not added`);
|
|
68
|
+
this.addStateLog(`listener '${name}' not added, already exists`);
|
|
56
69
|
return false;
|
|
57
70
|
}
|
|
58
71
|
this.listeners.set(name, listener);
|
|
@@ -65,50 +78,103 @@ export class ServerStreamSubscription {
|
|
|
65
78
|
};
|
|
66
79
|
connect = () => {
|
|
67
80
|
this.updateState(ServerStreamSubscriptionStatus.Connecting);
|
|
68
|
-
if (this.
|
|
81
|
+
if (this.streamCancel) {
|
|
69
82
|
this.addStateLog(`disconnect prev connection`);
|
|
70
|
-
this.
|
|
83
|
+
this.streamCancel.abort();
|
|
84
|
+
this.streamCancel = undefined;
|
|
71
85
|
}
|
|
72
|
-
const params = 'get' in this.params && typeof this.params.get === 'function' ? this.params.get() : this.params;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
const params = ('get' in this.params && typeof this.params.get === 'function' ? this.params.get() : this.params);
|
|
87
|
+
const fn = async () => {
|
|
88
|
+
this.streamCancel = new AbortController();
|
|
89
|
+
try {
|
|
90
|
+
const options = {
|
|
91
|
+
headers: this.headers.getValues(),
|
|
92
|
+
signal: this.streamCancel.signal,
|
|
93
|
+
};
|
|
94
|
+
const stream = this.method(params, options);
|
|
95
|
+
for await (const res of stream) {
|
|
96
|
+
this.attempt = 0;
|
|
97
|
+
this.onData(res);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (err instanceof ConnectError && err.code != Code.Canceled) {
|
|
102
|
+
void this.onStreamError(err);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
void fn();
|
|
78
107
|
this.updateState(ServerStreamSubscriptionStatus.Connected);
|
|
79
108
|
};
|
|
80
109
|
disconnect = () => {
|
|
81
|
-
if (this.
|
|
82
|
-
this.
|
|
110
|
+
if (this.streamCancel) {
|
|
111
|
+
this.streamCancel.abort();
|
|
83
112
|
}
|
|
84
113
|
this.listeners.clear();
|
|
114
|
+
this.paramsListener?.();
|
|
115
|
+
clearTimeout(this.reconnectTimeout);
|
|
116
|
+
this.reconnectTimeout = undefined;
|
|
85
117
|
this.updateState(ServerStreamSubscriptionStatus.Disconnected);
|
|
86
118
|
};
|
|
119
|
+
/**
|
|
120
|
+
* Reconnect after delay, if not already reconnecting, otherwise do nothing
|
|
121
|
+
*/
|
|
87
122
|
reconnect = () => {
|
|
88
|
-
this.
|
|
89
|
-
|
|
123
|
+
if (!this.reconnectTimeout) {
|
|
124
|
+
if (this.attempt < this.options.reconnectMaxAttempts) {
|
|
125
|
+
this.updateState(ServerStreamSubscriptionStatus.Reconnect);
|
|
126
|
+
// https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter/
|
|
127
|
+
const backoff = Math.min(this.options.reconnectMaxDelay, Math.pow(2, this.attempt) * this.options.reconnectDelay);
|
|
128
|
+
const delayMs = Math.round((backoff * (1 + Math.random())) / 2);
|
|
129
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
130
|
+
this.attempt++;
|
|
131
|
+
this.updateState(ServerStreamSubscriptionStatus.Reconnecting);
|
|
132
|
+
this.addStateLog(`reconnect attempt ${this.attempt} after ${delayMs}ms`);
|
|
133
|
+
this.connect();
|
|
134
|
+
this.reconnectTimeout = undefined;
|
|
135
|
+
}, delayMs);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
this.addStateLog(`max reconnect attempts reached`);
|
|
139
|
+
this.disconnect();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
this.addStateLog(`already reconnecting`);
|
|
144
|
+
}
|
|
90
145
|
};
|
|
91
146
|
getStore = () => this.store?.getStore();
|
|
92
147
|
onData = (response) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
this.store
|
|
148
|
+
try {
|
|
149
|
+
this.addStateLog(`received data => ${JSON.stringify(response)}`);
|
|
150
|
+
if (this.store) {
|
|
151
|
+
this.store.setValue(response);
|
|
152
|
+
}
|
|
153
|
+
for (const [, listener] of this.listeners) {
|
|
154
|
+
listener(response);
|
|
155
|
+
}
|
|
156
|
+
this.addStateLog(`data routed to ${this.listeners.size} listeners`);
|
|
96
157
|
}
|
|
97
|
-
|
|
98
|
-
|
|
158
|
+
catch (err) {
|
|
159
|
+
this.addStateLog(`error process data => ${err}`);
|
|
99
160
|
}
|
|
100
|
-
this.addStateLog(`data routed to ${this.listeners.size} listeners`);
|
|
101
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* Disconnect if error is not instance of ConnectError or stream is Canceled,
|
|
164
|
+
* Reconnect in other cases
|
|
165
|
+
* Do nothing if error is undefined
|
|
166
|
+
*/
|
|
102
167
|
onStreamError = (error) => {
|
|
168
|
+
this.addStateLog(`error => ${error ? JSON.stringify(error) : 'undefined'}}`);
|
|
103
169
|
if (error === undefined) {
|
|
104
170
|
return;
|
|
105
171
|
}
|
|
106
|
-
if (error
|
|
172
|
+
if (error instanceof ConnectError && error.code !== Code.Canceled) {
|
|
107
173
|
this.updateState(ServerStreamSubscriptionStatus.Failed);
|
|
108
174
|
this.state.setValue('error', error);
|
|
175
|
+
this.reconnect();
|
|
176
|
+
return;
|
|
109
177
|
}
|
|
110
|
-
|
|
111
|
-
this.disconnect();
|
|
112
|
-
}
|
|
178
|
+
this.disconnect();
|
|
113
179
|
};
|
|
114
180
|
}
|
package/lib/grpc/transport.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRouterTransport, ConnectRouter, Interceptor, PromiseClient,
|
|
1
|
+
import { createRouterTransport, ConnectRouter, Interceptor, PromiseClient, UnaryRequest, StreamRequest } from '@connectrpc/connect';
|
|
2
2
|
import type { ServiceType, Message, PlainMessage } from '@bufbuild/protobuf';
|
|
3
3
|
import { createGrpcWebTransport } from '@connectrpc/connect-web';
|
|
4
4
|
import type { KeyInput } from '@nanostores/query';
|
|
@@ -9,6 +9,7 @@ type KnownHeaders = {
|
|
|
9
9
|
authorization?: string;
|
|
10
10
|
sdk?: string;
|
|
11
11
|
'sl-device-id': string;
|
|
12
|
+
'sl-user-id'?: string;
|
|
12
13
|
} & Record<string, string>;
|
|
13
14
|
export type GrpcTransport = Transport['transport'];
|
|
14
15
|
type ReservedHeaders = 'sdk' | 'authorization';
|
|
@@ -42,13 +43,12 @@ export declare class Transport {
|
|
|
42
43
|
private callbackClients;
|
|
43
44
|
private subscriptions;
|
|
44
45
|
constructor(host: string);
|
|
45
|
-
addSubscription: <T extends ServiceType, Req extends Message<Req>, Res extends Message<Res>>(method:
|
|
46
|
+
addSubscription: <T extends ServiceType, Req extends Message<Req>, Res extends Message<Res>>(method: { [P in keyof PromiseClient<T> as T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? P : never]: T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? PromiseClient<T>[P] : never; }[keyof { [P in keyof PromiseClient<T> as T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? P : never]: T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? PromiseClient<T>[P] : never; }], params: PlainMessage<Req> | Atom<PlainMessage<Req>>, options: ServerStreamSubscriptionOptions) => ServerStreamSubscription<ServiceType, Message<import("@bufbuild/protobuf").AnyMessage>, Message<import("@bufbuild/protobuf").AnyMessage>, never, never> | ServerStreamSubscription<T, Req, Res, keyof { [P in keyof PromiseClient<T> as T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? P : never]: T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? PromiseClient<T>[P] : never; }, { [P in keyof PromiseClient<T> as T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? P : never]: T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? PromiseClient<T>[P] : never; }[keyof { [P in keyof PromiseClient<T> as T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? P : never]: T["methods"][P] extends import("@bufbuild/protobuf").MethodInfoServerStreaming<any, any> ? PromiseClient<T>[P] : never; }]>;
|
|
46
47
|
removeSubscription: (subscription: ServerStreamSubscription<ServiceType, Message, Message>) => void;
|
|
47
48
|
disconnect: () => void;
|
|
48
49
|
registerInterceptor: (interceptor: Interceptor) => void;
|
|
49
50
|
removeInterceptor: (interceptor: Interceptor) => void;
|
|
50
51
|
getClient: <T extends ServiceType>(service: T) => PromiseClient<T>;
|
|
51
|
-
getCallbackClient: <T extends ServiceType>(service: T) => CallbackClient<T>;
|
|
52
52
|
createPromiseClient: <T extends ServiceType>(service: T, { params, method }: {
|
|
53
53
|
params?: KeyInput | undefined;
|
|
54
54
|
method: keyof T["methods"];
|
|
@@ -57,11 +57,11 @@ export declare class Transport {
|
|
|
57
57
|
queryKey: ((string | number | true) | import("nanostores").ReadableAtom<(string | number | true) | (false | void | null | undefined)> | import("@nanostores/query").FetcherStore<any, any>)[];
|
|
58
58
|
queryKeyStr: string;
|
|
59
59
|
};
|
|
60
|
-
|
|
61
|
-
client:
|
|
60
|
+
createStreamClient: <T extends ServiceType>(service: T) => {
|
|
61
|
+
client: PromiseClient<T>;
|
|
62
62
|
};
|
|
63
63
|
setSdkKey: (sdkKey: string) => void;
|
|
64
|
-
setAuth: (token
|
|
64
|
+
setAuth: (token: string, userId: string) => void;
|
|
65
65
|
setHeader: <T extends string = string>(name: ExcludeReservedHeaders<T>, value: string) => void;
|
|
66
66
|
getHeader: (name: keyof KnownHeaders) => string;
|
|
67
67
|
getHeaders: () => KnownHeaders;
|
package/lib/grpc/transport.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MapStore, createMapStore } from '@streamlayer/sdk-web-interfaces';
|
|
2
|
-
import { createRouterTransport, createPromiseClient,
|
|
2
|
+
import { createRouterTransport, createPromiseClient, } from '@connectrpc/connect';
|
|
3
3
|
import { createGrpcWebTransport } from '@connectrpc/connect-web';
|
|
4
4
|
import { nanoquery } from '@nanostores/query';
|
|
5
5
|
import { __GRPC_DEVTOOLS_EXTENSION__ } from '../utils/devtools';
|
|
@@ -61,9 +61,9 @@ export class Transport {
|
|
|
61
61
|
};
|
|
62
62
|
// cleanup subscriptions
|
|
63
63
|
disconnect = () => {
|
|
64
|
-
for (const [
|
|
64
|
+
for (const [params, subscription] of this.subscriptions) {
|
|
65
65
|
subscription.disconnect();
|
|
66
|
-
this.subscriptions.delete(
|
|
66
|
+
this.subscriptions.delete(params);
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
69
|
registerInterceptor = (interceptor) => {
|
|
@@ -81,15 +81,6 @@ export class Transport {
|
|
|
81
81
|
this.clients.set(serviceName, client);
|
|
82
82
|
return client;
|
|
83
83
|
};
|
|
84
|
-
getCallbackClient = (service) => {
|
|
85
|
-
const serviceName = service.typeName;
|
|
86
|
-
if (this.callbackClients.has(serviceName)) {
|
|
87
|
-
return this.callbackClients.get(serviceName);
|
|
88
|
-
}
|
|
89
|
-
const client = createCallbackClient(service, this.transport);
|
|
90
|
-
this.callbackClients.set(serviceName, client);
|
|
91
|
-
return client;
|
|
92
|
-
};
|
|
93
84
|
// create unary client, used for query request
|
|
94
85
|
createPromiseClient = (service, { params = [], method }) => {
|
|
95
86
|
const client = this.getClient(service);
|
|
@@ -102,16 +93,17 @@ export class Transport {
|
|
|
102
93
|
const queryKeyWithoutParams = [service.typeName, methodName.charAt(0).toLowerCase() + methodName.slice(1)];
|
|
103
94
|
return { client, queryKey, queryKeyStr: queryKeyWithoutParams.join('') };
|
|
104
95
|
};
|
|
105
|
-
// create
|
|
106
|
-
|
|
107
|
-
const client = this.
|
|
96
|
+
// create promise client, used for server stream subscriptions
|
|
97
|
+
createStreamClient = (service) => {
|
|
98
|
+
const client = this.getClient(service);
|
|
108
99
|
return { client };
|
|
109
100
|
};
|
|
110
101
|
setSdkKey = (sdkKey) => {
|
|
111
102
|
this.$headers.setValue('sdk', sdkKey);
|
|
112
103
|
};
|
|
113
|
-
setAuth = (token) => {
|
|
104
|
+
setAuth = (token, userId) => {
|
|
114
105
|
this.$headers.setValue('authorization', token);
|
|
106
|
+
this.$headers.setValue('sl-user-id', userId);
|
|
115
107
|
};
|
|
116
108
|
setHeader = (name, value) => this.$headers.setValue(name, value);
|
|
117
109
|
getHeader = (name) => this.$headers.getValue(name);
|
|
@@ -145,7 +137,7 @@ export class Transport {
|
|
|
145
137
|
export class MockTransport extends Transport {
|
|
146
138
|
calls;
|
|
147
139
|
constructor(transport) {
|
|
148
|
-
super(process.env.NX_GRPC_HOST || 'https://grpc-
|
|
140
|
+
super(process.env.NX_GRPC_HOST || 'https://grpc-sdk.next.streamlayer.io:443');
|
|
149
141
|
this.calls = [];
|
|
150
142
|
this.interceptors.push((next) => (req) => {
|
|
151
143
|
this.calls.push(req);
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -5,5 +5,6 @@ export const transport = (instance, opts, done) => {
|
|
|
5
5
|
instance.transport = new Transport(opts.host);
|
|
6
6
|
instance.sdk.host = instance.transport.host;
|
|
7
7
|
instance.transport.setSdkKey(opts.sdkKey);
|
|
8
|
+
instance.transport.setHeader('sl-sdk-version', opts.version || '-');
|
|
8
9
|
done();
|
|
9
10
|
};
|
package/lib/utils/devtools.js
CHANGED
|
@@ -16,18 +16,20 @@ async function* logEach(store, stream) {
|
|
|
16
16
|
export const __GRPC_DEVTOOLS_EXTENSION__ = () => (next) => async (request) => {
|
|
17
17
|
const store = {
|
|
18
18
|
name: request.url,
|
|
19
|
-
|
|
19
|
+
stream: request.stream,
|
|
20
|
+
sent_at: Date.now(),
|
|
21
|
+
request: {
|
|
22
|
+
// clone headers to avoid mutating
|
|
23
|
+
header: Object.fromEntries(request.header.entries()),
|
|
24
|
+
},
|
|
20
25
|
response: {},
|
|
21
26
|
};
|
|
22
|
-
store.request.header = Object.fromEntries(request.header.entries());
|
|
23
|
-
store.sent_at = Date.now();
|
|
24
27
|
try {
|
|
25
28
|
const response = await next(request);
|
|
26
29
|
store.received_at = Date.now();
|
|
27
|
-
store.stream = response.stream;
|
|
28
30
|
store.response.header = Object.fromEntries(response.header.entries());
|
|
29
31
|
store.response.trailer = Object.fromEntries(response.trailer.entries());
|
|
30
|
-
if (!
|
|
32
|
+
if (!request.stream) {
|
|
31
33
|
store.request.message = request.message;
|
|
32
34
|
store.response.message = response.message;
|
|
33
35
|
store.latency = store.received_at - store.sent_at;
|
|
@@ -38,6 +40,15 @@ export const __GRPC_DEVTOOLS_EXTENSION__ = () => (next) => async (request) => {
|
|
|
38
40
|
window.postMessage(msg);
|
|
39
41
|
}
|
|
40
42
|
else {
|
|
43
|
+
store.request.message = request.message;
|
|
44
|
+
const msg = {
|
|
45
|
+
type: '__GRPC_DEVTOOLS_EXTENSION__',
|
|
46
|
+
data: {
|
|
47
|
+
...store,
|
|
48
|
+
stream: false,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
window.postMessage(msg);
|
|
41
52
|
return {
|
|
42
53
|
...response,
|
|
43
54
|
message: logEach(store, response.message),
|
package/lib/utils/grpc-stub.js
CHANGED
|
@@ -3,7 +3,7 @@ export class GrpcStub {
|
|
|
3
3
|
transport;
|
|
4
4
|
stubs;
|
|
5
5
|
constructor() {
|
|
6
|
-
this.transport = new Transport(process.env.NX_GRPC_HOST || 'https://grpc-
|
|
6
|
+
this.transport = new Transport(process.env.NX_GRPC_HOST || 'https://grpc-sdk.next.streamlayer.io:443');
|
|
7
7
|
this.stubs = new Map();
|
|
8
8
|
const stubbedUnary = (service, method, signal, timeoutMs, header, input) => {
|
|
9
9
|
const key = `${service.typeName}${method.name}`.toLowerCase();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamlayer/sdk-web-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"typings": "./lib/index.d.ts",
|
|
@@ -21,16 +21,16 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@streamlayer/sdk-web-interfaces": "^0.
|
|
24
|
+
"@streamlayer/sdk-web-interfaces": "^0.19.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"@
|
|
29
|
-
"@connectrpc/connect": "
|
|
30
|
-
"@
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"nanostores": "
|
|
34
|
-
"tslib": "
|
|
27
|
+
"@bufbuild/protobuf": "^1.6.0",
|
|
28
|
+
"@connectrpc/connect": "^1.3.0",
|
|
29
|
+
"@connectrpc/connect-web": "^1.3.0",
|
|
30
|
+
"@nanostores/query": "^0.2.8",
|
|
31
|
+
"@streamlayer/sl-eslib": "^5.63.3",
|
|
32
|
+
"@swc/helpers": "^0.5.3",
|
|
33
|
+
"nanostores": "^0.9.5",
|
|
34
|
+
"tslib": "^2.6.2"
|
|
35
35
|
}
|
|
36
36
|
}
|