@corva/ui 3.79.0-2 → 3.79.0-4
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/cjs-bundle/clients/api/apiCore.js +1 -1
- package/cjs-bundle/clients/api/apiCore.js.map +1 -1
- package/cjs-bundle/clients/subscriptions/socket-client.v2.js +1 -1
- package/cjs-bundle/clients/subscriptions/socket-client.v2.js.map +1 -1
- package/cjs-bundle/clients/subscriptions/subscriptions-auth-recovery.js +2 -0
- package/cjs-bundle/clients/subscriptions/subscriptions-auth-recovery.js.map +1 -0
- package/cjs-bundle/clients/subscriptions/subscriptions-client.dummy.js +1 -1
- package/cjs-bundle/clients/subscriptions/subscriptions-client.dummy.js.map +1 -1
- package/cjs-bundle/clients/subscriptions/subscriptions-client.factory.js +1 -1
- package/cjs-bundle/clients/subscriptions/subscriptions-client.factory.js.map +1 -1
- package/cjs-bundle/clients/subscriptions/subscriptions-client.js +1 -1
- package/cjs-bundle/clients/subscriptions/subscriptions-client.js.map +1 -1
- package/clients/api/apiCore.d.ts +2 -0
- package/clients/api/apiCore.d.ts.map +1 -1
- package/clients/api/apiCore.js +1 -1
- package/clients/api/apiCore.js.map +1 -1
- package/clients/subscriptions/__tests__/subscriptions-auth-recovery.test.d.ts +2 -0
- package/clients/subscriptions/__tests__/subscriptions-auth-recovery.test.d.ts.map +1 -0
- package/clients/subscriptions/socket-client.v2.d.ts +8 -0
- package/clients/subscriptions/socket-client.v2.d.ts.map +1 -1
- package/clients/subscriptions/socket-client.v2.js +1 -1
- package/clients/subscriptions/socket-client.v2.js.map +1 -1
- package/clients/subscriptions/subscriptions-auth-recovery.d.ts +53 -0
- package/clients/subscriptions/subscriptions-auth-recovery.d.ts.map +1 -0
- package/clients/subscriptions/subscriptions-auth-recovery.js +2 -0
- package/clients/subscriptions/subscriptions-auth-recovery.js.map +1 -0
- package/clients/subscriptions/subscriptions-client.d.ts +6 -1
- package/clients/subscriptions/subscriptions-client.d.ts.map +1 -1
- package/clients/subscriptions/subscriptions-client.dummy.d.ts +2 -1
- package/clients/subscriptions/subscriptions-client.dummy.d.ts.map +1 -1
- package/clients/subscriptions/subscriptions-client.dummy.js +1 -1
- package/clients/subscriptions/subscriptions-client.dummy.js.map +1 -1
- package/clients/subscriptions/subscriptions-client.factory.d.ts +8 -0
- package/clients/subscriptions/subscriptions-client.factory.d.ts.map +1 -1
- package/clients/subscriptions/subscriptions-client.factory.js +1 -1
- package/clients/subscriptions/subscriptions-client.factory.js.map +1 -1
- package/clients/subscriptions/subscriptions-client.js +1 -1
- package/clients/subscriptions/subscriptions-client.js.map +1 -1
- package/clients/subscriptions/types.d.ts +5 -0
- package/clients/subscriptions/types.d.ts.map +1 -1
- package/components/Drillstring/BHAComponentDetail/constants.d.ts +2 -2
- package/mcp-server/server.mjs +11 -9
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -6,6 +6,14 @@ export declare const socketClientV2: {
|
|
|
6
6
|
}) => any;
|
|
7
7
|
}) => () => void;
|
|
8
8
|
onConnectionChange: (handler: OnConnectionChange) => () => void;
|
|
9
|
+
/**
|
|
10
|
+
* Disconnect and drop the shared client (logout). The next `subscribe` builds a fresh socket.
|
|
11
|
+
*/
|
|
9
12
|
disconnect: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Reconnect the shared client if it has given up (e.g. an expired session while the tab was
|
|
15
|
+
* suspended). No-op when there is no client yet, it is connected, or it is already retrying.
|
|
16
|
+
*/
|
|
17
|
+
ensureConnected: () => void;
|
|
10
18
|
};
|
|
11
19
|
//# sourceMappingURL=socket-client.v2.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-client.v2.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/socket-client.v2.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE/D,eAAO,MAAM,cAAc;IACzB,SAAS,GAAG,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,gBAClE,CAAC,qBACI;QAAE,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG;YAAE,IAAI,EAAE,CAAC,CAAA;SAAE,KAAK,GAAG,CAAA;KAAE;IAOtE,kBAAkB,YAAY,kBAAkB;IAIhD,UAAU;
|
|
1
|
+
{"version":3,"file":"socket-client.v2.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/socket-client.v2.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE/D,eAAO,MAAM,cAAc;IACzB,SAAS,GAAG,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,gBAClE,CAAC,qBACI;QAAE,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG;YAAE,IAAI,EAAE,CAAC,CAAA;SAAE,KAAK,GAAG,CAAA;KAAE;IAOtE,kBAAkB,YAAY,kBAAkB;IAIhD;;OAEG;IACH,UAAU;IAGV;;;OAGG;IACH,eAAe;CAGhB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"@babel/runtime/helpers/defineProperty";import{getChannelName as t}from"./get-channel-name.js";import{SubscriptionsClientFactory as
|
|
1
|
+
import e from"@babel/runtime/helpers/defineProperty";import{getChannelName as t}from"./get-channel-name.js";import{SubscriptionsClientFactory as n}from"./subscriptions-client.factory.js";function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(t){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?r(Object(o),!0).forEach((function(n){e(t,n,o[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):r(Object(o)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))}))}return t}var c={subscribe:function(e,r){var c=r.onDataReceive,i=n.init(),s=t(e);return i.subscribe(s,(function(t){return c(o(o({},e),{},{data:t}))}))},onConnectionChange:function(e){return n.init().onConnectionChange(e)},disconnect:function(){n.dispose()},ensureConnected:function(){var e;null===(e=n.get())||void 0===e||e.ensureConnected()}};export{c as socketClientV2};
|
|
2
2
|
//# sourceMappingURL=socket-client.v2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-client.v2.js","sources":["../../../src/clients/subscriptions/socket-client.v2.ts"],"sourcesContent":["import { getChannelName } from './get-channel-name';\nimport { SubscriptionsClientFactory } from './subscriptions-client.factory';\nimport { SubscribeOptions, OnConnectionChange } from './types';\n\nexport const socketClientV2 = {\n subscribe: <O extends SubscribeOptions = SubscribeOptions, T = Record<string, any>>(\n subscription: O,\n { onDataReceive }: { onDataReceive: (data: O & { data: T }) => any }\n ) => {\n const client = SubscriptionsClientFactory.init();\n const channel = getChannelName(subscription);\n\n return client.subscribe<T>(channel, data => onDataReceive({ ...subscription, data }));\n },\n onConnectionChange: (handler: OnConnectionChange) => {\n const client = SubscriptionsClientFactory.init();\n return client.onConnectionChange(handler);\n },\n disconnect: () => {\n
|
|
1
|
+
{"version":3,"file":"socket-client.v2.js","sources":["../../../src/clients/subscriptions/socket-client.v2.ts"],"sourcesContent":["import { getChannelName } from './get-channel-name';\nimport { SubscriptionsClientFactory } from './subscriptions-client.factory';\nimport { SubscribeOptions, OnConnectionChange } from './types';\n\nexport const socketClientV2 = {\n subscribe: <O extends SubscribeOptions = SubscribeOptions, T = Record<string, any>>(\n subscription: O,\n { onDataReceive }: { onDataReceive: (data: O & { data: T }) => any }\n ) => {\n const client = SubscriptionsClientFactory.init();\n const channel = getChannelName(subscription);\n\n return client.subscribe<T>(channel, data => onDataReceive({ ...subscription, data }));\n },\n onConnectionChange: (handler: OnConnectionChange) => {\n const client = SubscriptionsClientFactory.init();\n return client.onConnectionChange(handler);\n },\n /**\n * Disconnect and drop the shared client (logout). The next `subscribe` builds a fresh socket.\n */\n disconnect: () => {\n SubscriptionsClientFactory.dispose();\n },\n /**\n * Reconnect the shared client if it has given up (e.g. an expired session while the tab was\n * suspended). No-op when there is no client yet, it is connected, or it is already retrying.\n */\n ensureConnected: () => {\n SubscriptionsClientFactory.get()?.ensureConnected();\n },\n};\n"],"names":["socketClientV2","subscribe","subscription","_ref","onDataReceive","client","SubscriptionsClientFactory","init","channel","getChannelName","data","onConnectionChange","handler","disconnect","dispose","ensureConnected","_SubscriptionsClientF","get"],"mappings":"0vBAIO,IAAMA,EAAiB,CAC5BC,UAAW,SACTC,EAEGC,GAAA,IADDC,IAAAA,cAEIC,EAASC,EAA2BC,OACpCC,EAAUC,EAAeP,GAE/B,OAAOG,EAAOJ,UAAaO,GAAS,SAAAE,GAAI,OAAIN,SAAmBF,GAAY,GAAA,CAAEQ,KAAAA,OAC9E,EACDC,mBAAoB,SAACC,GAEnB,OADeN,EAA2BC,OAC5BI,mBAAmBC,EAClC,EAIDC,WAAY,WACVP,EAA2BQ,SAC5B,EAKDC,gBAAiB,WAAM,IAAAC,EACrB,QAAAA,EAAAV,EAA2BW,aAA3B,IAAAD,GAAAA,EAAkCD,iBACpC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Socket } from 'socket.io-client';
|
|
2
|
+
/**
|
|
3
|
+
* Handshake rejection codes sent by corva-subscriptions (see its README, "Handshake rejections").
|
|
4
|
+
*/
|
|
5
|
+
export type UnauthorizedErrorCode = 'credentials_required' | 'credentials_bad_format' | 'token_expired' | 'invalid_token';
|
|
6
|
+
type ConnectError = Error & {
|
|
7
|
+
data?: {
|
|
8
|
+
type?: string;
|
|
9
|
+
code?: UnauthorizedErrorCode | string;
|
|
10
|
+
message?: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export declare const MAX_AUTH_RECONNECT_ATTEMPTS = 3;
|
|
14
|
+
export declare const AUTH_RECONNECT_BASE_DELAY_MS = 1000;
|
|
15
|
+
export declare const isUnauthorizedConnectError: (err: unknown) => err is ConnectError;
|
|
16
|
+
export interface AuthRecoveryDeps {
|
|
17
|
+
tryRefresh: () => Promise<void>;
|
|
18
|
+
handleAuthFailure: (error: unknown) => void;
|
|
19
|
+
isLoginRoute: () => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Impersonation swaps only the auth cookie; the refresh cookie stays the admin's. A refresh would
|
|
22
|
+
* therefore come back as a plain admin session and silently end the impersonation, so while
|
|
23
|
+
* impersonating the socket is left down and the existing HTTP 401 handling decides what happens.
|
|
24
|
+
*/
|
|
25
|
+
isImpersonating: () => boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface SocketAuthRecovery {
|
|
28
|
+
/**
|
|
29
|
+
* Reconnect a socket that has given up: socket.io stops reconnecting for good after a handshake
|
|
30
|
+
* rejection, and so do we once the attempt cap is reached. No-op while connected or while either
|
|
31
|
+
* side is still retrying. Meant for "the tab is visible again" moments.
|
|
32
|
+
*/
|
|
33
|
+
ensureConnected(): void;
|
|
34
|
+
/** Detach the listeners and cancel any pending retry. */
|
|
35
|
+
dispose(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Recover from an authentication rejection at the socket.io handshake.
|
|
39
|
+
*
|
|
40
|
+
* The server verifies the session cookie once, during the handshake. When the JWT in it has
|
|
41
|
+
* expired (typically after the tab was suspended long enough for the connection to drop), the
|
|
42
|
+
* handshake is rejected and socket.io-client treats that as final: it destroys the socket and sets
|
|
43
|
+
* `skipReconnect`, so nothing ever retries. HTTP calls recover through `AuthRecovery` on their next
|
|
44
|
+
* 401, but the socket never issues an HTTP call, so it stayed dead until a page reload.
|
|
45
|
+
*
|
|
46
|
+
* This closes the loop: on an `UnauthorizedError` connect_error, refresh the session (the browser
|
|
47
|
+
* then re-sends the fresh cookie on the next handshake) and call `socket.connect()`, with capped
|
|
48
|
+
* exponential backoff. A failed refresh is handed to `AuthRecovery.handleAuthFailure`, which
|
|
49
|
+
* redirects to /login when the session is really gone and does nothing for a transient failure.
|
|
50
|
+
*/
|
|
51
|
+
export declare const attachAuthRecovery: (socket: Socket, deps?: Partial<AuthRecoveryDeps>) => SocketAuthRecovery;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=subscriptions-auth-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptions-auth-recovery.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/subscriptions-auth-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAK/C;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B,sBAAsB,GACtB,wBAAwB,GACxB,eAAe,GACf,eAAe,CAAC;AAEpB,KAAK,YAAY,GAAG,KAAK,GAAG;IAC1B,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnF,CAAC;AAEF,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAalD,eAAO,MAAM,0BAA0B,QAAS,OAAO,KAAG,GAAG,IAAI,YACM,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,iBAAiB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B;;;;OAIG;IACH,eAAe,EAAE,MAAM,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,eAAe,IAAI,IAAI,CAAC;IACxB,yDAAyD;IACzD,OAAO,IAAI,IAAI,CAAC;CACjB;AAUD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,WACrB,MAAM,SACR,OAAO,CAAC,gBAAgB,CAAC,KAC9B,kBAmGF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import n from"@babel/runtime/helpers/asyncToGenerator";import e from"@babel/runtime/helpers/defineProperty";import t from"@babel/runtime/regenerator";import{authRecovery as r}from"../api/apiCore.js";import{isImpersonating as o}from"../clientStorage/index.js";import{LOGIN_ROUTES_REGEXP as i}from"./constants.js";function u(n,e){var t=Object.keys(n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(n);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),t.push.apply(t,r)}return t}function c(n){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?u(Object(r),!0).forEach((function(t){e(n,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(r)):u(Object(r)).forEach((function(e){Object.defineProperty(n,e,Object.getOwnPropertyDescriptor(r,e))}))}return n}var a=3,f=1e3,l=new Set(["token_expired","credentials_required","invalid_token"]),s=function(n){var e;return"UnauthorizedError"===(null==n||null===(e=n.data)||void 0===e?void 0:e.type)},p=function(){return{tryRefresh:function(){return r.tryRefresh()},handleAuthFailure:function(n){function e(e){return n.apply(this,arguments)}return e.toString=function(){return n.toString()},e}((function(n){return r.handleAuthFailure(n)})),isLoginRoute:function(){return i.test(window.location.pathname)},isImpersonating:function(){return o()}}},d=function(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=c(c({},p()),r),i=o.tryRefresh,u=o.handleAuthFailure,a=o.isLoginRoute,f=o.isImpersonating,d=0,m=null,h=null,b=!1,v=function(){null!==m&&(clearTimeout(m),m=null)},y=function(){if(!(b||null!==m||d>=3)){var n=.75+.5*Math.random(),e=1e3*Math.pow(2,d)*n;d+=1,m=setTimeout((function(){m=null,O()}),e)}},O=function(){return h||(h=n(t.mark((function n(){return t.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return n.prev=0,n.next=3,i();case 3:n.next=10;break;case 5:return n.prev=5,n.t0=n.catch(0),u(n.t0),y(),n.abrupt("return");case 10:b||e.connect();case 11:case"end":return n.stop()}}),n,null,[[0,5]])})))().finally((function(){h=null})))},g=function(n){var e;if(s(n)){var t=null===(e=n.data)||void 0===e?void 0:e.code;t&&l.has(t)&&(a()||f()||y())}},j=function(){d=0};return e.on("connect_error",g),e.on("connect",j),{ensureConnected:function(){if(!(b||e.connected||e.active||h)){if(d=0,null!==m)return v(),void O();e.connect()}},dispose:function(){b=!0,v(),e.off("connect_error",g),e.off("connect",j)}}};export{f as AUTH_RECONNECT_BASE_DELAY_MS,a as MAX_AUTH_RECONNECT_ATTEMPTS,d as attachAuthRecovery,s as isUnauthorizedConnectError};
|
|
2
|
+
//# sourceMappingURL=subscriptions-auth-recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptions-auth-recovery.js","sources":["../../../src/clients/subscriptions/subscriptions-auth-recovery.ts"],"sourcesContent":["import type { Socket } from 'socket.io-client';\nimport { authRecovery } from '../api/apiCore';\nimport { isImpersonating as isImpersonatingSession } from '../clientStorage';\nimport { LOGIN_ROUTES_REGEXP } from './constants';\n\n/**\n * Handshake rejection codes sent by corva-subscriptions (see its README, \"Handshake rejections\").\n */\nexport type UnauthorizedErrorCode =\n | 'credentials_required'\n | 'credentials_bad_format'\n | 'token_expired'\n | 'invalid_token';\n\ntype ConnectError = Error & {\n data?: { type?: string; code?: UnauthorizedErrorCode | string; message?: string };\n};\n\nexport const MAX_AUTH_RECONNECT_ATTEMPTS = 3;\nexport const AUTH_RECONNECT_BASE_DELAY_MS = 1_000;\n\n/**\n * Codes a session refresh can fix. `invalid_token` is included because a server that predates the\n * `token_expired` code reports an expired token that way; the attempt cap bounds the cost when the\n * token really is invalid. `credentials_bad_format` is a client bug and is never retried.\n */\nconst REFRESHABLE_CODES: ReadonlySet<string> = new Set([\n 'token_expired',\n 'credentials_required',\n 'invalid_token',\n]);\n\nexport const isUnauthorizedConnectError = (err: unknown): err is ConnectError =>\n (err as ConnectError | undefined)?.data?.type === 'UnauthorizedError';\n\nexport interface AuthRecoveryDeps {\n tryRefresh: () => Promise<void>;\n handleAuthFailure: (error: unknown) => void;\n isLoginRoute: () => boolean;\n /**\n * Impersonation swaps only the auth cookie; the refresh cookie stays the admin's. A refresh would\n * therefore come back as a plain admin session and silently end the impersonation, so while\n * impersonating the socket is left down and the existing HTTP 401 handling decides what happens.\n */\n isImpersonating: () => boolean;\n}\n\nexport interface SocketAuthRecovery {\n /**\n * Reconnect a socket that has given up: socket.io stops reconnecting for good after a handshake\n * rejection, and so do we once the attempt cap is reached. No-op while connected or while either\n * side is still retrying. Meant for \"the tab is visible again\" moments.\n */\n ensureConnected(): void;\n /** Detach the listeners and cancel any pending retry. */\n dispose(): void;\n}\n\nconst defaultDeps = (): AuthRecoveryDeps => ({\n tryRefresh: () => authRecovery.tryRefresh(),\n handleAuthFailure: error =>\n authRecovery.handleAuthFailure(error as Parameters<typeof authRecovery.handleAuthFailure>[0]),\n isLoginRoute: () => LOGIN_ROUTES_REGEXP.test(window.location.pathname),\n isImpersonating: () => isImpersonatingSession(),\n});\n\n/**\n * Recover from an authentication rejection at the socket.io handshake.\n *\n * The server verifies the session cookie once, during the handshake. When the JWT in it has\n * expired (typically after the tab was suspended long enough for the connection to drop), the\n * handshake is rejected and socket.io-client treats that as final: it destroys the socket and sets\n * `skipReconnect`, so nothing ever retries. HTTP calls recover through `AuthRecovery` on their next\n * 401, but the socket never issues an HTTP call, so it stayed dead until a page reload.\n *\n * This closes the loop: on an `UnauthorizedError` connect_error, refresh the session (the browser\n * then re-sends the fresh cookie on the next handshake) and call `socket.connect()`, with capped\n * exponential backoff. A failed refresh is handed to `AuthRecovery.handleAuthFailure`, which\n * redirects to /login when the session is really gone and does nothing for a transient failure.\n */\nexport const attachAuthRecovery = (\n socket: Socket,\n deps: Partial<AuthRecoveryDeps> = {}\n): SocketAuthRecovery => {\n const { tryRefresh, handleAuthFailure, isLoginRoute, isImpersonating } = {\n ...defaultDeps(),\n ...deps,\n };\n\n let attempts = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n /** The refresh currently in flight, so a resume does not connect with the stale cookie meanwhile. */\n let refreshing: Promise<void> | null = null;\n let disposed = false;\n\n const clearTimer = () => {\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n const schedule = () => {\n if (disposed || timer !== null || attempts >= MAX_AUTH_RECONNECT_ATTEMPTS) return;\n\n const jitter = 0.75 + Math.random() * 0.5;\n const delay = AUTH_RECONNECT_BASE_DELAY_MS * 2 ** attempts * jitter;\n\n attempts += 1;\n timer = setTimeout(() => {\n timer = null;\n void refreshAndConnect();\n }, delay);\n };\n\n const refreshAndConnect = () => {\n if (refreshing) return refreshing;\n\n refreshing = (async () => {\n try {\n await tryRefresh();\n } catch (error) {\n handleAuthFailure(error);\n // A transient failure (network) gets another go within the cap; a redirect unloads the page.\n schedule();\n return;\n }\n\n if (!disposed) socket.connect();\n })().finally(() => {\n refreshing = null;\n });\n\n return refreshing;\n };\n\n const onConnectError = (err: Error) => {\n if (!isUnauthorizedConnectError(err)) return; // transport errors: socket.io retries those itself\n\n const code = err.data?.code;\n if (!code || !REFRESHABLE_CODES.has(code)) return;\n // After logout there is no refresh cookie; every /v1/user_token call would just 401.\n if (isLoginRoute()) return;\n // See AuthRecoveryDeps.isImpersonating: refreshing here would end the impersonation.\n if (isImpersonating()) return;\n\n schedule();\n };\n\n const onConnect = () => {\n attempts = 0;\n };\n\n socket.on('connect_error', onConnectError);\n socket.on('connect', onConnect);\n\n return {\n ensureConnected: () => {\n // `active` is true while socket.io itself is (re)connecting; leave it alone then.\n if (disposed || socket.connected || socket.active) return;\n // The in-flight refresh connects when it resolves; connecting now would handshake with the\n // cookie that was just rejected.\n if (refreshing) return;\n\n attempts = 0;\n\n if (timer !== null) {\n // A retry is already queued because auth failed: do it now rather than after the backoff.\n clearTimer();\n void refreshAndConnect();\n return;\n }\n\n socket.connect();\n },\n dispose: () => {\n disposed = true;\n clearTimer();\n socket.off('connect_error', onConnectError);\n socket.off('connect', onConnect);\n },\n };\n};\n"],"names":["MAX_AUTH_RECONNECT_ATTEMPTS","AUTH_RECONNECT_BASE_DELAY_MS","REFRESHABLE_CODES","Set","isUnauthorizedConnectError","err","_data","data","type","defaultDeps","tryRefresh","authRecovery","handleAuthFailure","_handleAuthFailure","_x","apply","this","arguments","toString","error","isLoginRoute","LOGIN_ROUTES_REGEXP","test","window","location","pathname","isImpersonating","isImpersonatingSession","attachAuthRecovery","socket","deps","length","undefined","attempts","timer","refreshing","disposed","clearTimer","clearTimeout","schedule","jitter","Math","random","delay","pow","setTimeout","refreshAndConnect","_asyncToGenerator","_regeneratorRuntime","mark","_callee","wrap","_context","prev","next","t0","abrupt","connect","stop","finally","onConnectError","_err$data","code","has","onConnect","on","ensureConnected","connected","active","dispose","off"],"mappings":"u3BAkBO,IAAMA,EAA8B,EAC9BC,EAA+B,IAOtCC,EAAyC,IAAIC,IAAI,CACrD,gBACA,uBACA,kBAGWC,EAA6B,SAACC,GAAY,IAAAC,EAAA,MACH,uBAAjDD,SAAD,QAACA,EAAAA,EAAkCE,YAAnC,IAAAD,OAACD,EAADC,EAAyCE,KAA4B,EAyBjEC,EAAc,WAAH,MAA4B,CAC3CC,WAAY,WAAA,OAAMC,EAAaD,YAAY,EAC3CE,kBAAiB,SAAAC,GAAA,SAAAD,EAAAE,GAAA,OAAAD,EAAAE,MAAAC,KAAAC,UAAA,CAAA,OAAAL,EAAAM,SAAA,WAAA,OAAAL,EAAAK,UAAA,EAAAN,CAAA,CAAA,EAAE,SAAAO,GAAK,OACtBR,EAAaC,kBAAkBO,EAA8D,IAC/FC,aAAc,WAAA,OAAMC,EAAoBC,KAAKC,OAAOC,SAASC,SAAS,EACtEC,gBAAiB,WAAA,OAAMC,GAAwB,EAChD,EAgBYC,EAAqB,SAChCC,GAEuB,IADvBC,EAAkCb,UAAAc,OAAA,QAAAC,IAAAf,UAAA,GAAAA,UAAA,GAAA,CAAA,EAG7BR,EAAAA,EAAAA,EAAAA,CAAAA,EAAAA,KACAqB,GAFGpB,IAAAA,WAAYE,IAAAA,kBAAmBQ,IAAAA,aAAcM,IAAAA,gBAKjDO,EAAW,EACXC,EAA8C,KAE9CC,EAAmC,KACnCC,GAAW,EAETC,EAAa,WACH,OAAVH,IACFI,aAAaJ,GACbA,EAAQ,OAINK,EAAW,WACf,KAAIH,GAAsB,OAAVF,GAAkBD,GArFK,GAqFvC,CAEA,IAAMO,EAAS,IAAuB,GAAhBC,KAAKC,SACrBC,EAvFkC,IAuFEF,KAAAG,IAAG,EAAKX,GAAWO,EAE7DP,GAAY,EACZC,EAAQW,YAAW,WACjBX,EAAQ,KACHY,GACN,GAAEH,EATwE,GAYvEG,EAAoB,WACxB,OAAIX,IAEJA,EAAaY,EAACC,EAAAC,MAAA,SAAAC,IAAA,OAAAF,EAAAG,MAAA,SAAAC,GAAA,OAAA,OAAAA,EAAAC,KAAAD,EAAAE,MAAA,KAAA,EAAA,OAAAF,EAAAC,KAAA,EAAAD,EAAAE,KAAA,EAEJ5C,IAAY,KAAA,EAAA0C,EAAAE,KAAA,GAAA,MAAA,KAAA,EAIP,OAJOF,EAAAC,KAAA,EAAAD,EAAAG,GAAAH,EAAA,MAAA,GAElBxC,EAAwBwC,EAAAG,IAExBhB,IAAWa,EAAAI,OAAA,UAAA,KAAA,GAIRpB,GAAUP,EAAO4B,UAAU,KAAA,GAAA,IAAA,MAAA,OAAAL,EAAAM,OAAA,GAAAR,EAAA,KAAA,CAAA,CAAA,EAAA,IAAA,IAVrBH,GAWRY,SAAQ,WACXxB,EAAa,IACf,MAKIyB,EAAiB,SAACvD,GAAe,IAAAwD,EACrC,GAAKzD,EAA2BC,GAAhC,CAEA,IAAMyD,EAAe,QAARzD,EAAAA,EAAIE,YAAI,IAAAsD,OAAA,EAARA,EAAUC,KAClBA,GAAS5D,EAAkB6D,IAAID,KAEhC1C,KAEAM,KAEJa,IAT6C,GAYzCyB,EAAY,WAChB/B,EAAW,GAMb,OAHAJ,EAAOoC,GAAG,gBAAiBL,GAC3B/B,EAAOoC,GAAG,UAAWD,GAEd,CACLE,gBAAiB,WAEf,KAAI9B,GAAYP,EAAOsC,WAAatC,EAAOuC,QAGvCjC,GAAJ,CAIA,GAFAF,EAAW,EAEG,OAAVC,EAIF,OAFAG,SACKS,IAIPjB,EAAO4B,SAXS,CAYjB,EACDY,QAAS,WACPjC,GAAW,EACXC,IACAR,EAAOyC,IAAI,gBAAiBV,GAC5B/B,EAAOyC,IAAI,UAAWN,EACxB,EAEJ"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { Socket } from 'socket.io-client';
|
|
2
|
+
import { SocketAuthRecovery } from './subscriptions-auth-recovery';
|
|
2
3
|
import { SubcriptionsClient, SubscriptionsClientV2Events, SubscriptionsClientV2ServerEvents, AcknowledgeCb, OnDataReceive, OnConnectionChange } from './types';
|
|
3
4
|
export declare class SubscriptionsClientV2 implements SubcriptionsClient {
|
|
4
5
|
private readonly _socket;
|
|
5
|
-
|
|
6
|
+
private readonly _recovery?;
|
|
7
|
+
/** Listeners this client put on the Manager; `socket.removeAllListeners()` does not reach those. */
|
|
8
|
+
private readonly _managerListeners;
|
|
9
|
+
constructor(_socket: Socket<SubscriptionsClientV2Events, SubscriptionsClientV2ServerEvents>, _recovery?: SocketAuthRecovery | undefined);
|
|
6
10
|
subscribe<T>(channel: string, onData: OnDataReceive<T>, ack?: AcknowledgeCb): () => void;
|
|
7
11
|
unsubscribe<T>(channel: string, onData: OnDataReceive<T>, ack?: AcknowledgeCb): void;
|
|
8
12
|
disconnect(): this;
|
|
13
|
+
ensureConnected(): void;
|
|
9
14
|
onConnectionChange: (handler: OnConnectionChange) => () => void;
|
|
10
15
|
private _validateArgs;
|
|
11
16
|
private _shouldEmitToServer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions-client.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/subscriptions-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,iCAAiC,EACjC,aAAa,EACb,aAAa,EACb,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,qBAAa,qBAAsB,YAAW,kBAAkB;
|
|
1
|
+
{"version":3,"file":"subscriptions-client.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/subscriptions-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,iCAAiC,EACjC,aAAa,EACb,aAAa,EACb,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,qBAAa,qBAAsB,YAAW,kBAAkB;IAM5D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAIxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAT7B,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAyB;IAE3D,YAEmB,OAAO,EAAE,MAAM,CAC9B,2BAA2B,EAC3B,iCAAiC,CAClC,EACgB,SAAS,CAAC,EAAE,kBAAkB,YAAA,EAC7C;IAEJ,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,aAAa,cAe1E;IAED,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,aAAa,QAM5E;IAED,UAAU,SAQT;IAED,eAAe,SASd;IAED,kBAAkB,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,MAAM,IAAI,CAwB7D;IAEF,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,KAAK;CAuBd"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { AcknowledgeCb, OnConnectionChange, OnDataReceive, SubcriptionsClient } from
|
|
1
|
+
import { AcknowledgeCb, OnConnectionChange, OnDataReceive, SubcriptionsClient } from './types';
|
|
2
2
|
export declare class DummySubscriptionsClient implements SubcriptionsClient {
|
|
3
3
|
subscribe<T>(_channel: string, _onData: OnDataReceive<T>, _ack?: AcknowledgeCb): () => void;
|
|
4
4
|
unsubscribe<T>(_channel: string, _onData: OnDataReceive<T>, _ack?: AcknowledgeCb): void;
|
|
5
5
|
disconnect(): void;
|
|
6
|
+
ensureConnected(): void;
|
|
6
7
|
onConnectionChange(_handler: OnConnectionChange): () => void;
|
|
7
8
|
}
|
|
8
9
|
//# sourceMappingURL=subscriptions-client.dummy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions-client.dummy.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/subscriptions-client.dummy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE/F,qBAAa,wBAAyB,YAAW,kBAAkB;IACjE,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,IAAI,CAE1F;IAED,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,IAAI,CAEtF;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAG3D;CACF"}
|
|
1
|
+
{"version":3,"file":"subscriptions-client.dummy.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/subscriptions-client.dummy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE/F,qBAAa,wBAAyB,YAAW,kBAAkB;IACjE,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,IAAI,CAE1F;IAED,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,IAAI,CAEtF;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,eAAe,IAAI,IAAI,CAEtB;IAED,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAG3D;CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"@babel/runtime/helpers/classCallCheck";import n from"@babel/runtime/helpers/createClass";var u=function(){function u(){e(this,u)}return n(u,[{key:"subscribe",value:function(e,n,u){return function(){}}},{key:"unsubscribe",value:function(e,n,u){}},{key:"disconnect",value:function(){}},{key:"ensureConnected",value:function(){}},{key:"onConnectionChange",value:function(e){return function(){}}}]),u}();export{u as DummySubscriptionsClient};
|
|
2
2
|
//# sourceMappingURL=subscriptions-client.dummy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions-client.dummy.js","sources":["../../../src/clients/subscriptions/subscriptions-client.dummy.ts"],"sourcesContent":["import { AcknowledgeCb, OnConnectionChange, OnDataReceive, SubcriptionsClient } from
|
|
1
|
+
{"version":3,"file":"subscriptions-client.dummy.js","sources":["../../../src/clients/subscriptions/subscriptions-client.dummy.ts"],"sourcesContent":["import { AcknowledgeCb, OnConnectionChange, OnDataReceive, SubcriptionsClient } from './types';\n\nexport class DummySubscriptionsClient implements SubcriptionsClient {\n subscribe<T>(_channel: string, _onData: OnDataReceive<T>, _ack?: AcknowledgeCb): () => void {\n return () => {};\n }\n\n unsubscribe<T>(_channel: string, _onData: OnDataReceive<T>, _ack?: AcknowledgeCb): void {\n return;\n }\n\n disconnect(): void {\n return;\n }\n\n ensureConnected(): void {\n return;\n }\n\n onConnectionChange(_handler: OnConnectionChange): () => void {\n // no socket on reports routes; return noop unsubscriber\n return () => {};\n }\n}\n"],"names":["DummySubscriptionsClient","_classCallCheck","this","_createClass","key","value","_channel","_onData","_ack","_handler"],"mappings":"uGAEA,IAAaA,EAAwB,WAAA,SAAAA,IAAAC,EAAAC,KAAAF,EAAA,CAoBlC,OApBkCG,EAAAH,EAAA,CAAA,CAAAI,IAAA,YAAAC,MACnC,SAAaC,EAAkBC,EAA2BC,GACxD,OAAO,WAAM,CACf,GAAC,CAAAJ,IAAA,cAAAC,MAED,SAAeC,EAAkBC,EAA2BC,GAE5D,GAAC,CAAAJ,IAAA,aAAAC,MAED,WAEA,GAAC,CAAAD,IAAA,kBAAAC,MAED,WAEA,GAAC,CAAAD,IAAA,qBAAAC,MAED,SAAmBI,GAEjB,OAAO,WAAM,CACf,KAACT,CAAA,CApBkC"}
|
|
@@ -2,6 +2,14 @@ import { SubcriptionsClient } from './types';
|
|
|
2
2
|
export declare class SubscriptionsClientFactory {
|
|
3
3
|
private static readonly instances;
|
|
4
4
|
static init(url?: string): SubcriptionsClient;
|
|
5
|
+
/** The client for `url` if one exists; unlike `init()` this never creates a socket. */
|
|
6
|
+
static get(url?: string): SubcriptionsClient | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Disconnect and forget the client for `url`, so the next `init()` builds a fresh socket.
|
|
9
|
+
* A manually disconnected socket.io client never reconnects on its own, so keeping it cached
|
|
10
|
+
* (as logout used to) handed a later login in the same tab a permanently dead client.
|
|
11
|
+
*/
|
|
12
|
+
static dispose(url?: string): void;
|
|
5
13
|
private static create;
|
|
6
14
|
}
|
|
7
15
|
//# sourceMappingURL=subscriptions-client.factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions-client.factory.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/subscriptions-client.factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"subscriptions-client.factory.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/subscriptions-client.factory.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C,qBAAa,0BAA0B;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAyC;IAE1E,OAAc,IAAI,CAAC,GAAG,SAAoB,sBAQzC;IAED,uFAAuF;IACvF,OAAc,GAAG,CAAC,GAAG,SAAoB,kCAExC;IAED;;;;OAIG;IACH,OAAc,OAAO,CAAC,GAAG,SAAoB,QAK5C;IAED,OAAO,CAAC,MAAM,CAAC,MAAM;CAmEtB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"@babel/runtime/helpers/classCallCheck";import t from"@babel/runtime/helpers/createClass";import
|
|
1
|
+
import e from"@babel/runtime/helpers/classCallCheck";import t from"@babel/runtime/helpers/createClass";import n from"@babel/runtime/helpers/defineProperty";import{io as r}from"socket.io-client";import{IGNORED_ROUTES_REGEXP as i,getHrefDebugField as o,SUBSCRIPTIONS_URL as s}from"./constants.js";import{isUnauthorizedConnectError as c,attachAuthRecovery as a}from"./subscriptions-auth-recovery.js";import{SubscriptionsClientV2 as u}from"./subscriptions-client.js";import{DummySubscriptionsClient as l}from"./subscriptions-client.dummy.js";function p(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}var f=function(){function f(){e(this,f)}return t(f,null,[{key:"init",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:s,t=new URL(e).origin;return this.instances.has(t)||this.instances.set(t,this.create(e)),this.instances.get(t)}},{key:"get",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:s;return this.instances.get(new URL(e).origin)}},{key:"dispose",value:function(){var e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:s,n=new URL(t).origin;null===(e=this.instances.get(n))||void 0===e||e.disconnect(),this.instances.delete(n)}},{key:"create",value:function(e){if(i.test(window.location.pathname))return new l;var t=r(e,{transports:["websocket"],autoConnect:!0,path:process.env.REACT_APP_SUBSCRIPTIONS_PATH||"/socket.io"}),s=0,f=!1;return t.on("connect_error",(function(e){c(e)&&(f=!0)})),t.on("connect",(function(){var e=1===(s+=1)&&!f;(f=!1,t.recovered)||(e||Object.keys(t._callbacks).filter((function(e){return e.startsWith("$data#")})).map((function(e){return e.replace("$data#","")})).forEach((function(e){t.emit("subscribe",function(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?p(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):p(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}({channel:e},o()))})))})),new u(t,a(t))}}]),f}();n(f,"instances",new Map);export{f as SubscriptionsClientFactory};
|
|
2
2
|
//# sourceMappingURL=subscriptions-client.factory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions-client.factory.js","sources":["../../../src/clients/subscriptions/subscriptions-client.factory.ts"],"sourcesContent":["import { io } from 'socket.io-client';\nimport { IGNORED_ROUTES_REGEXP, SUBSCRIPTIONS_URL, getHrefDebugField } from './constants';\nimport { SubscriptionsClientV2 } from './subscriptions-client';\nimport { DummySubscriptionsClient } from './subscriptions-client.dummy';\nimport { SubcriptionsClient } from './types';\n\nexport class SubscriptionsClientFactory {\n private static readonly instances = new Map<string, SubcriptionsClient>();\n\n public static init(url = SUBSCRIPTIONS_URL) {\n const key = new URL(url).origin;\n\n if (!this.instances.has(key)) {\n this.instances.set(key, this.create(url));\n }\n\n return this.instances.get(key)!;\n }\n private static create(url: string): SubcriptionsClient {\n if (IGNORED_ROUTES_REGEXP.test(window.location.pathname)) {\n return new DummySubscriptionsClient();\n }\n\n const socket = io(url, {\n transports: ['websocket'],\n // NOTE: no need to connect manually, it will be done automatically\n autoConnect: true,\n path: process.env.REACT_APP_SUBSCRIPTIONS_PATH || '/socket.io',\n });\n\n let connectAttempts = 0;\n\n /**\n * We need to resend \"subscribe\" events on 2+ \"connect\" events:\n * 1. initial connection, subscribes will be handled by io queue\n * 2. reconnection, need to resend existing subscriptions\n * 3. ...\n */\n socket.on('connect', () => {\n connectAttempts += 1;\n\n if (socket.recovered) {\n /**\n *
|
|
1
|
+
{"version":3,"file":"subscriptions-client.factory.js","sources":["../../../src/clients/subscriptions/subscriptions-client.factory.ts"],"sourcesContent":["import { io } from 'socket.io-client';\nimport { IGNORED_ROUTES_REGEXP, SUBSCRIPTIONS_URL, getHrefDebugField } from './constants';\nimport { attachAuthRecovery, isUnauthorizedConnectError } from './subscriptions-auth-recovery';\nimport { SubscriptionsClientV2 } from './subscriptions-client';\nimport { DummySubscriptionsClient } from './subscriptions-client.dummy';\nimport { SubcriptionsClient } from './types';\n\nexport class SubscriptionsClientFactory {\n private static readonly instances = new Map<string, SubcriptionsClient>();\n\n public static init(url = SUBSCRIPTIONS_URL) {\n const key = new URL(url).origin;\n\n if (!this.instances.has(key)) {\n this.instances.set(key, this.create(url));\n }\n\n return this.instances.get(key)!;\n }\n\n /** The client for `url` if one exists; unlike `init()` this never creates a socket. */\n public static get(url = SUBSCRIPTIONS_URL) {\n return this.instances.get(new URL(url).origin);\n }\n\n /**\n * Disconnect and forget the client for `url`, so the next `init()` builds a fresh socket.\n * A manually disconnected socket.io client never reconnects on its own, so keeping it cached\n * (as logout used to) handed a later login in the same tab a permanently dead client.\n */\n public static dispose(url = SUBSCRIPTIONS_URL) {\n const key = new URL(url).origin;\n\n this.instances.get(key)?.disconnect();\n this.instances.delete(key);\n }\n\n private static create(url: string): SubcriptionsClient {\n if (IGNORED_ROUTES_REGEXP.test(window.location.pathname)) {\n return new DummySubscriptionsClient();\n }\n\n const socket = io(url, {\n transports: ['websocket'],\n // NOTE: no need to connect manually, it will be done automatically\n autoConnect: true,\n path: process.env.REACT_APP_SUBSCRIPTIONS_PATH || '/socket.io',\n });\n\n let connectAttempts = 0;\n let handshakeRejected = false;\n\n socket.on('connect_error', err => {\n if (isUnauthorizedConnectError(err)) handshakeRejected = true;\n });\n\n /**\n * We need to resend \"subscribe\" events on 2+ \"connect\" events:\n * 1. initial connection, subscribes will be handled by io queue\n * 2. reconnection, need to resend existing subscriptions\n * 3. ...\n *\n * A first connection that follows a rejected handshake counts as a reconnection too. The\n * subscribes emitted before it sat in socket.io's send buffer, but every emit carries an ack\n * timeout (see the frontend's Sentry integration) and a timed-out ack removes its packet from\n * that buffer. If refreshing the session took longer than the timeout, relying on the buffer\n * would leave a connected socket with no subscriptions.\n */\n socket.on('connect', () => {\n connectAttempts += 1;\n\n const isCleanFirstConnect = connectAttempts === 1 && !handshakeRejected;\n handshakeRejected = false;\n\n if (socket.recovered) {\n /**\n * subscriptions restored by the socket.io server\n * @see https://socket.io/docs/v4/server-initialization/#server-events\n */\n return;\n }\n\n if (isCleanFirstConnect) {\n // initial connection, subscribes will be handled by io queue\n return;\n }\n\n /**\n * @description\n * channel names resolved from private property of socket.io lib\n * @see https://github.com/socketio/emitter/blob/8a2ece1f367dd9898791ee663940386147d2d688/lib/cjs/index.js#L161\n */\n // @ts-expect-error\n const channels = Object.keys(socket._callbacks)\n .filter(key => key.startsWith('$data#'))\n .map(key => key.replace('$data#', ''));\n\n channels.forEach(channel => {\n socket.emit('subscribe', { channel, ...getHrefDebugField() });\n });\n });\n\n return new SubscriptionsClientV2(socket, attachAuthRecovery(socket));\n }\n}\n"],"names":["SubscriptionsClientFactory","_classCallCheck","this","_createClass","key","value","url","SUBSCRIPTIONS_URL","URL","origin","instances","has","set","create","get","_this$instances$get","disconnect","delete","IGNORED_ROUTES_REGEXP","test","window","location","pathname","DummySubscriptionsClient","socket","io","transports","autoConnect","path","process","env","REACT_APP_SUBSCRIPTIONS_PATH","connectAttempts","handshakeRejected","on","err","isUnauthorizedConnectError","isCleanFirstConnect","recovered","Object","keys","_callbacks","filter","startsWith","map","replace","forEach","channel","emit","_objectSpread","getHrefDebugField","SubscriptionsClientV2","attachAuthRecovery","_defineProperty","Map"],"mappings":"wvBAOA,IAAaA,EAA0B,WAAA,SAAAA,IAAAC,EAAAC,KAAAF,EAAA,CAgGpC,OAhGoCG,EAAAH,EAAA,KAAA,CAAA,CAAAI,IAAA,OAAAC,MAGrC,WAA4C,IAAzBC,yDAAMC,EACjBH,EAAM,IAAII,IAAIF,GAAKG,OAMzB,OAJKP,KAAKQ,UAAUC,IAAIP,IACtBF,KAAKQ,UAAUE,IAAIR,EAAKF,KAAKW,OAAOP,IAG/BJ,KAAKQ,UAAUI,IAAIV,EAC5B,GAEA,CAAAA,IAAA,MAAAC,MACA,WAA2C,IAAzBC,yDAAMC,EACtB,OAAOL,KAAKQ,UAAUI,IAAI,IAAIN,IAAIF,GAAKG,OACzC,GAEA,CAAAL,IAAA,UAAAC,MAKA,WAA+C,IAAAU,EAAzBT,yDAAMC,EACpBH,EAAM,IAAII,IAAIF,GAAKG,OAEF,QAAnBM,EAAAb,KAACQ,UAAUI,IAAIV,UAAI,IAAAW,GAAvBA,EAAyBC,aACzBd,KAAKQ,UAAUO,OAAOb,EACxB,GAAC,CAAAA,IAAA,SAAAC,MAED,SAAsBC,GACpB,GAAIY,EAAsBC,KAAKC,OAAOC,SAASC,UAC7C,OAAO,IAAIC,EAGb,IAAMC,EAASC,EAAGnB,EAAK,CACrBoB,WAAY,CAAC,aAEbC,aAAa,EACbC,KAAMC,QAAQC,IAAIC,8BAAgC,eAGhDC,EAAkB,EAClBC,GAAoB,EAoDxB,OAlDAT,EAAOU,GAAG,iBAAiB,SAAAC,GACrBC,EAA2BD,KAAMF,GAAoB,EAC3D,IAcAT,EAAOU,GAAG,WAAW,WAGnB,IAAMG,EAA0C,KAFhDL,GAAmB,KAEmCC,GACtDA,GAAoB,EAEhBT,EAAOc,aAQPD,GAWaE,OAAOC,KAAKhB,EAAOiB,YACjCC,QAAO,SAAAtC,GAAG,OAAIA,EAAIuC,WAAW,SAAS,IACtCC,KAAI,SAAAxC,GAAG,OAAIA,EAAIyC,QAAQ,SAAU,OAE3BC,SAAQ,SAAAC,GACfvB,EAAOwB,KAAK,2WAAWC,CAAA,CAAIF,QAAAA,GAAYG,KACzC,IACF,IAEO,IAAIC,EAAsB3B,EAAQ4B,EAAmB5B,GAC9D,KAACxB,CAAA,CAhGoC,GAiGtCqD,EAjGYrD,EAA0B,YACD,IAAIsD"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"@babel/runtime/helpers/classCallCheck";import t from"@babel/runtime/helpers/createClass";import n from"@babel/runtime/helpers/defineProperty";import{getHrefDebugField as r}from"./constants.js";function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}var s=function(){function o(t,r){var c=this;e(this,o),this._socket=t,this._recovery=r,n(this,"_managerListeners",new Set),n(this,"onConnectionChange",(function(e){var t=function(){return e({status:"connected"})},n=function(t){return e({status:"disconnected",reason:t})},r=function(){return e({status:"reconnecting"})},o=function(t){return e({status:"error",reason:(null==t?void 0:t.message)||String(t)})},s=c._socket.io;return c._socket.on("connect",t),c._socket.on("disconnect",n),null==s||s.on("reconnect_attempt",r),c._managerListeners.add(r),c._socket.on("connect_error",o),function(){c._socket.off("connect",t),c._socket.off("disconnect",n),null==s||s.off("reconnect_attempt",r),c._managerListeners.delete(r),c._socket.off("connect_error",o)}}))}return t(o,[{key:"subscribe",value:function(e,t,n){var r=this;this._validateArgs(e,t,n),this._socket.on("data#".concat(e),t),this._emit("subscribe",e,n);var o=function(){return r.unsubscribe(e,t,n)};return Object.defineProperty(o,"name",{value:"unsubscribe_".concat(e.replace(/[^\w]/g,"_")),writable:!1}),o}},{key:"unsubscribe",value:function(e,t,n){this._validateArgs(e,t,n),this._emit("unsubscribe",e,n),this._socket.off("data#".concat(e),t)}},{key:"disconnect",value:function(){var e,t=this;return null===(e=this._recovery)||void 0===e||e.dispose(),this._socket.disconnect(),this._socket.removeAllListeners(),this._managerListeners.forEach((function(e){var n;return null===(n=t._socket.io)||void 0===n?void 0:n.off("reconnect_attempt",e)})),this._managerListeners.clear(),this}},{key:"ensureConnected",value:function(){this._recovery?this._recovery.ensureConnected():this._socket.connected||this._socket.active||this._socket.connect()}},{key:"_validateArgs",value:function(e,t,n){if("string"!=typeof e||!e)throw new Error("Channel must be a non-empty string");if("function"!=typeof t)throw new Error("onData handler must be a function");if(void 0!==n&&"function"!=typeof n)throw new Error("ack must be a function")}},{key:"_shouldEmitToServer",value:function(e){return 1===this._socket.listeners("data#".concat(e)).length}},{key:"_emit",value:function(e,t,n){if(!this._shouldEmitToServer(t))return null==n?void 0:n();n?this._socket.emitWithAck(e,c({channel:t},r()),(function(r){return r.ok?n():n(new Error("Failed to ".concat(e," to channel ").concat(t,": ").concat(r.error)))})):this._socket.emit(e,c({channel:t},r()))}}]),o}();export{s as SubscriptionsClientV2};
|
|
2
2
|
//# sourceMappingURL=subscriptions-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions-client.js","sources":["../../../src/clients/subscriptions/subscriptions-client.ts"],"sourcesContent":["import { Socket } from 'socket.io-client';\nimport { getHrefDebugField } from './constants';\nimport {\n SubcriptionsClient,\n SubscriptionsClientV2Events,\n SubscriptionsClientV2ServerEvents,\n AcknowledgeCb,\n OnDataReceive,\n OnConnectionChange,\n} from './types';\n\nexport class SubscriptionsClientV2 implements SubcriptionsClient {\n constructor(\n private readonly _socket: Socket
|
|
1
|
+
{"version":3,"file":"subscriptions-client.js","sources":["../../../src/clients/subscriptions/subscriptions-client.ts"],"sourcesContent":["import { Socket } from 'socket.io-client';\nimport { getHrefDebugField } from './constants';\nimport { SocketAuthRecovery } from './subscriptions-auth-recovery';\nimport {\n SubcriptionsClient,\n SubscriptionsClientV2Events,\n SubscriptionsClientV2ServerEvents,\n AcknowledgeCb,\n OnDataReceive,\n OnConnectionChange,\n} from './types';\n\nexport class SubscriptionsClientV2 implements SubcriptionsClient {\n /** Listeners this client put on the Manager; `socket.removeAllListeners()` does not reach those. */\n private readonly _managerListeners = new Set<() => void>();\n\n constructor(\n // Keep the name: corva-web-frontend's Sentry integration reaches the raw socket through it.\n private readonly _socket: Socket<\n SubscriptionsClientV2Events,\n SubscriptionsClientV2ServerEvents\n >,\n private readonly _recovery?: SocketAuthRecovery\n ) {}\n\n subscribe<T>(channel: string, onData: OnDataReceive<T>, ack?: AcknowledgeCb) {\n this._validateArgs(channel, onData, ack);\n\n this._socket.on(`data#${channel}`, onData);\n\n this._emit('subscribe', channel, ack);\n\n const unsubscribe = () => this.unsubscribe(channel, onData, ack);\n\n Object.defineProperty(unsubscribe, 'name', {\n value: `unsubscribe_${channel.replace(/[^\\w]/g, '_')}`,\n writable: false,\n });\n\n return unsubscribe;\n }\n\n unsubscribe<T>(channel: string, onData: OnDataReceive<T>, ack?: AcknowledgeCb) {\n this._validateArgs(channel, onData, ack);\n\n this._emit('unsubscribe', channel, ack);\n\n this._socket.off(`data#${channel}`, onData);\n }\n\n disconnect() {\n this._recovery?.dispose();\n this._socket.disconnect();\n this._socket.removeAllListeners();\n this._managerListeners.forEach(listener => this._socket.io?.off('reconnect_attempt', listener));\n this._managerListeners.clear();\n\n return this;\n }\n\n ensureConnected() {\n if (this._recovery) {\n this._recovery.ensureConnected();\n return;\n }\n\n if (!this._socket.connected && !this._socket.active) {\n this._socket.connect();\n }\n }\n\n onConnectionChange: (handler: OnConnectionChange) => () => void = handler => {\n const onConnect = () => handler({ status: 'connected' });\n const onDisconnect = (reason?: string) => handler({ status: 'disconnected', reason });\n const onReconnectAttempt = () => handler({ status: 'reconnecting' });\n const onConnectError = (err?: any) =>\n handler({ status: 'error', reason: err?.message || String(err) });\n\n // Reconnection events belong to the Manager (`socket.io`), not the Socket: a `reconnect*`\n // listener on the Socket never fires in socket.io v4.\n const manager = this._socket.io;\n\n this._socket.on('connect', onConnect as any);\n this._socket.on('disconnect', onDisconnect as any);\n manager?.on('reconnect_attempt', onReconnectAttempt);\n this._managerListeners.add(onReconnectAttempt);\n this._socket.on('connect_error', onConnectError as any);\n\n return () => {\n this._socket.off('connect', onConnect as any);\n this._socket.off('disconnect', onDisconnect as any);\n manager?.off('reconnect_attempt', onReconnectAttempt);\n this._managerListeners.delete(onReconnectAttempt);\n this._socket.off('connect_error', onConnectError as any);\n };\n };\n\n private _validateArgs(channel: unknown, onData: unknown, ack?: unknown) {\n if (typeof channel !== 'string' || !channel) {\n throw new Error('Channel must be a non-empty string');\n }\n if (typeof onData !== 'function') {\n throw new Error('onData handler must be a function');\n }\n\n if (ack !== undefined && typeof ack !== 'function') {\n throw new Error('ack must be a function');\n }\n }\n\n private _shouldEmitToServer(channel: string) {\n // emit when the only present listener is a current one\n return this._socket.listeners(`data#${channel}`).length === 1;\n }\n\n private _emit(event: 'subscribe' | 'unsubscribe', channel: string, ack?: AcknowledgeCb) {\n if (!this._shouldEmitToServer(channel)) {\n return ack?.();\n }\n\n if (!ack) {\n this._socket.emit(event, { channel, ...getHrefDebugField() });\n\n return;\n }\n\n void this._socket.emitWithAck(\n event,\n { channel, ...getHrefDebugField() },\n (res: { ok: boolean; error?: string }) => {\n if (res.ok) {\n return ack();\n }\n\n return ack(new Error(`Failed to ${event} to channel ${channel}: ${res.error}`));\n }\n );\n }\n}\n"],"names":["SubscriptionsClientV2","_socket","_recovery","_this","this","_classCallCheck","_defineProperty","Set","handler","onConnect","status","onDisconnect","reason","onReconnectAttempt","onConnectError","err","message","String","manager","io","on","_managerListeners","add","off","delete","_createClass","key","value","channel","onData","ack","_this2","_validateArgs","_emit","unsubscribe","Object","defineProperty","concat","replace","writable","_this$_recovery","_this3","dispose","disconnect","removeAllListeners","forEach","listener","_this3$_socket$io","clear","ensureConnected","connected","active","connect","Error","undefined","listeners","length","event","_shouldEmitToServer","emitWithAck","_objectSpread","getHrefDebugField","res","ok","error","emit"],"mappings":"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"}
|
|
@@ -35,6 +35,11 @@ export interface SubcriptionsClient {
|
|
|
35
35
|
subscribe<T>(channel: string, onData: OnDataReceive<T>, ack?: AcknowledgeCb): () => void;
|
|
36
36
|
unsubscribe<T>(channel: string, onData: OnDataReceive<T>, ack?: AcknowledgeCb): void;
|
|
37
37
|
disconnect(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Reconnect if the socket has given up (after an auth rejection, or a manual disconnect). No-op
|
|
40
|
+
* while connected or while socket.io is already retrying. Call when the tab becomes visible.
|
|
41
|
+
*/
|
|
42
|
+
ensureConnected(): void;
|
|
38
43
|
onConnectionChange(handler: OnConnectionChange): () => void;
|
|
39
44
|
}
|
|
40
45
|
export type ConnectionStatus = 'connected' | 'disconnected' | 'reconnecting' | 'error';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,EAAE,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,2BAA2B;IAC1C,CAAC,KAAK,EAAE,QAAQ,MAAM,EAAE,GAAG,GAAG,CAAC;CAChC;AAED,MAAM,WAAW,iCAAiC;IAChD,SAAS,EAAE,CACT,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;KAAE,EAC1D,GAAG,CAAC,EAAE,aAAa,KAChB,IAAI,CAAC;IACV,WAAW,EAAE,CACX,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;KAAE,EAC1D,GAAG,CAAC,EAAE,aAAa,KAChB,IAAI,CAAC;CACX;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,aAAa,GAAG,MAAM,IAAI,CAAC;IACzF,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrF,UAAU,IAAI,IAAI,CAAC;IACnB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAAC;CAC7D;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,OAAO,CAAC;AACvF,MAAM,MAAM,gBAAgB,GAAG;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/clients/subscriptions/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,EAAE,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,2BAA2B;IAC1C,CAAC,KAAK,EAAE,QAAQ,MAAM,EAAE,GAAG,GAAG,CAAC;CAChC;AAED,MAAM,WAAW,iCAAiC;IAChD,SAAS,EAAE,CACT,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;KAAE,EAC1D,GAAG,CAAC,EAAE,aAAa,KAChB,IAAI,CAAC;IACV,WAAW,EAAE,CACX,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;KAAE,EAC1D,GAAG,CAAC,EAAE,aAAa,KAChB,IAAI,CAAC;CACX;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,aAAa,GAAG,MAAM,IAAI,CAAC;IACzF,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrF,UAAU,IAAI,IAAI,CAAC;IACnB;;;OAGG;IACH,eAAe,IAAI,IAAI,CAAC;IACxB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAAC;CAC7D;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,OAAO,CAAC;AACvF,MAAM,MAAM,gBAAgB,GAAG;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC"}
|
|
@@ -106,10 +106,10 @@ export declare const BHA_COMPONENT_TYPES: ({
|
|
|
106
106
|
})[];
|
|
107
107
|
})[];
|
|
108
108
|
export declare const BHA_GENERAL_FIELD_TYPES: ({
|
|
109
|
+
unit?: undefined;
|
|
109
110
|
name: string;
|
|
110
111
|
label: string;
|
|
111
112
|
cond?: undefined;
|
|
112
|
-
unit?: undefined;
|
|
113
113
|
col_size?: undefined;
|
|
114
114
|
family?: undefined;
|
|
115
115
|
} | {
|
|
@@ -134,8 +134,8 @@ export declare const BHA_GENERAL_FIELD_TYPES: ({
|
|
|
134
134
|
col_size: number;
|
|
135
135
|
family?: undefined;
|
|
136
136
|
} | {
|
|
137
|
-
cond?: undefined;
|
|
138
137
|
unit?: undefined;
|
|
138
|
+
cond?: undefined;
|
|
139
139
|
name: string;
|
|
140
140
|
label: string;
|
|
141
141
|
col_size: number;
|