@servicetitan/log-service 30.3.0 → 31.0.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/dist/bind-log.js +1 -0
- package/dist/bind-log.js.map +1 -1
- package/dist/connection-service.js +38 -27
- package/dist/connection-service.js.map +1 -1
- package/dist/global-error-handler.js +99 -98
- package/dist/global-error-handler.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/log-config-provider.js +10 -1
- package/dist/log-config-provider.js.map +1 -1
- package/dist/log-config.js +2 -1
- package/dist/log-config.js.map +1 -1
- package/dist/log-sender.d.ts +2 -1
- package/dist/log-sender.d.ts.map +1 -1
- package/dist/log-sender.js +53 -89
- package/dist/log-sender.js.map +1 -1
- package/dist/log-service.js +29 -9
- package/dist/log-service.js.map +1 -1
- package/dist/log-storage.d.ts +1 -1
- package/dist/log-storage.d.ts.map +1 -1
- package/dist/log-storage.js +90 -99
- package/dist/log-storage.js.map +1 -1
- package/dist/log.d.ts +2 -1
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +97 -137
- package/dist/log.js.map +1 -1
- package/dist/serialize-with-metadata.js +8 -9
- package/dist/serialize-with-metadata.js.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +13 -10
- package/src/log-sender.ts +2 -1
- package/src/log-storage.ts +2 -1
- package/src/log.ts +2 -1
package/dist/log-sender.js
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
15
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
16
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for
|
|
17
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
18
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
}
|
|
7
|
-
|
|
19
|
+
}
|
|
20
|
+
function _ts_metadata(k, v) {
|
|
8
21
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return function
|
|
12
|
-
|
|
22
|
+
}
|
|
23
|
+
function _ts_param(paramIndex, decorator) {
|
|
24
|
+
return function(target, key) {
|
|
25
|
+
decorator(target, key, paramIndex);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
13
28
|
import axios from 'axios';
|
|
14
29
|
import { injectable, inject, Store } from '@servicetitan/react-ioc';
|
|
15
30
|
import { reaction } from 'mobx';
|
|
@@ -21,65 +36,7 @@ const DEFAULT_SEND_INTERVAL = 60 * SECOND;
|
|
|
21
36
|
const INITIAL_RETRY_INTERVAL = SECOND;
|
|
22
37
|
const MAX_RETRY_INTERVAL = INITIAL_RETRY_INTERVAL * 512;
|
|
23
38
|
const BATCH_SIZE = 128;
|
|
24
|
-
|
|
25
|
-
constructor(connectionService, logStorage, logConfig, log) {
|
|
26
|
-
super();
|
|
27
|
-
Object.defineProperty(this, "connectionService", {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
configurable: true,
|
|
30
|
-
writable: true,
|
|
31
|
-
value: connectionService
|
|
32
|
-
});
|
|
33
|
-
Object.defineProperty(this, "logStorage", {
|
|
34
|
-
enumerable: true,
|
|
35
|
-
configurable: true,
|
|
36
|
-
writable: true,
|
|
37
|
-
value: logStorage
|
|
38
|
-
});
|
|
39
|
-
Object.defineProperty(this, "logConfig", {
|
|
40
|
-
enumerable: true,
|
|
41
|
-
configurable: true,
|
|
42
|
-
writable: true,
|
|
43
|
-
value: logConfig
|
|
44
|
-
});
|
|
45
|
-
Object.defineProperty(this, "log", {
|
|
46
|
-
enumerable: true,
|
|
47
|
-
configurable: true,
|
|
48
|
-
writable: true,
|
|
49
|
-
value: log
|
|
50
|
-
});
|
|
51
|
-
Object.defineProperty(this, "inSendFailedScenario", {
|
|
52
|
-
enumerable: true,
|
|
53
|
-
configurable: true,
|
|
54
|
-
writable: true,
|
|
55
|
-
value: false
|
|
56
|
-
});
|
|
57
|
-
Object.defineProperty(this, "isSending", {
|
|
58
|
-
enumerable: true,
|
|
59
|
-
configurable: true,
|
|
60
|
-
writable: true,
|
|
61
|
-
value: false
|
|
62
|
-
});
|
|
63
|
-
Object.defineProperty(this, "onItemsChangedDisposer", {
|
|
64
|
-
enumerable: true,
|
|
65
|
-
configurable: true,
|
|
66
|
-
writable: true,
|
|
67
|
-
value: void 0
|
|
68
|
-
});
|
|
69
|
-
Object.defineProperty(this, "sendInterval", {
|
|
70
|
-
enumerable: true,
|
|
71
|
-
configurable: true,
|
|
72
|
-
writable: true,
|
|
73
|
-
value: DEFAULT_SEND_INTERVAL
|
|
74
|
-
});
|
|
75
|
-
Object.defineProperty(this, "intervalId", {
|
|
76
|
-
enumerable: true,
|
|
77
|
-
configurable: true,
|
|
78
|
-
writable: true,
|
|
79
|
-
value: void 0
|
|
80
|
-
});
|
|
81
|
-
this.setRegularSendScenario();
|
|
82
|
-
}
|
|
39
|
+
export class LogSender extends Store {
|
|
83
40
|
dispose() {
|
|
84
41
|
window.clearInterval(this.intervalId);
|
|
85
42
|
}
|
|
@@ -91,7 +48,7 @@ let LogSender = class LogSender extends Store {
|
|
|
91
48
|
setSendInterval(interval) {
|
|
92
49
|
this.sendInterval = interval;
|
|
93
50
|
window.clearInterval(this.intervalId);
|
|
94
|
-
this.intervalId = window.setInterval(()
|
|
51
|
+
this.intervalId = window.setInterval(()=>{
|
|
95
52
|
if (this.logStorage.items.length > 0) {
|
|
96
53
|
this.send();
|
|
97
54
|
}
|
|
@@ -105,13 +62,14 @@ let LogSender = class LogSender extends Store {
|
|
|
105
62
|
/*
|
|
106
63
|
* Using Web Locks API to prevent multiple tabs from simultaneously
|
|
107
64
|
* sending previously saved items. If the API isn't available, ¯\_(ツ)_/¯
|
|
108
|
-
*/
|
|
109
|
-
if (!('locks' in globalThis.navigator)) {
|
|
65
|
+
*/ if (!('locks' in globalThis.navigator)) {
|
|
110
66
|
this.sendEvents();
|
|
111
67
|
return;
|
|
112
68
|
}
|
|
113
69
|
// eslint-disable-next-line no-restricted-globals
|
|
114
|
-
navigator.locks.request(this.logConfig.storageKey, {
|
|
70
|
+
navigator.locks.request(this.logConfig.storageKey, {
|
|
71
|
+
ifAvailable: true
|
|
72
|
+
}, async (lock)=>{
|
|
115
73
|
if (lock) {
|
|
116
74
|
await this.sendEvents();
|
|
117
75
|
}
|
|
@@ -131,47 +89,53 @@ let LogSender = class LogSender extends Store {
|
|
|
131
89
|
this.setRegularSendScenario();
|
|
132
90
|
}
|
|
133
91
|
}
|
|
134
|
-
}
|
|
135
|
-
catch (e) {
|
|
92
|
+
} catch (e) {
|
|
136
93
|
this.setFailedSendScenario();
|
|
137
|
-
/* istanbul ignore next */
|
|
138
|
-
if (process.env.NODE_ENV !== 'test') {
|
|
94
|
+
/* istanbul ignore next */ if (process.env.NODE_ENV !== 'test') {
|
|
139
95
|
throw e;
|
|
140
96
|
}
|
|
141
|
-
}
|
|
142
|
-
finally {
|
|
97
|
+
} finally{
|
|
143
98
|
this.isSending = false;
|
|
144
99
|
}
|
|
145
100
|
}
|
|
146
101
|
setRegularSendScenario() {
|
|
147
102
|
this.inSendFailedScenario = false;
|
|
148
103
|
this.setSendInterval(DEFAULT_SEND_INTERVAL);
|
|
149
|
-
this.onItemsChangedDisposer = reaction(()
|
|
104
|
+
this.onItemsChangedDisposer = reaction(()=>this.logStorage.items, (items)=>this.onItemsChanged(items));
|
|
150
105
|
}
|
|
151
106
|
setFailedSendScenario() {
|
|
152
|
-
var
|
|
107
|
+
var _this_onItemsChangedDisposer, _this;
|
|
153
108
|
if (this.inSendFailedScenario) {
|
|
154
109
|
this.increaseSendInterval();
|
|
155
110
|
return;
|
|
156
111
|
}
|
|
157
112
|
this.inSendFailedScenario = true;
|
|
158
113
|
this.setSendInterval(INITIAL_RETRY_INTERVAL);
|
|
159
|
-
(
|
|
114
|
+
(_this_onItemsChangedDisposer = (_this = this).onItemsChangedDisposer) === null || _this_onItemsChangedDisposer === void 0 ? void 0 : _this_onItemsChangedDisposer.call(_this);
|
|
160
115
|
}
|
|
161
116
|
increaseSendInterval() {
|
|
162
117
|
if (this.sendInterval < MAX_RETRY_INTERVAL) {
|
|
163
118
|
this.setSendInterval(this.sendInterval * 2);
|
|
164
119
|
}
|
|
165
120
|
}
|
|
166
|
-
|
|
167
|
-
|
|
121
|
+
constructor(connectionService, logStorage, logConfig, log){
|
|
122
|
+
super(), _define_property(this, "connectionService", void 0), _define_property(this, "logStorage", void 0), _define_property(this, "logConfig", void 0), _define_property(this, "log", void 0), _define_property(this, "inSendFailedScenario", void 0), _define_property(this, "isSending", void 0), _define_property(this, "onItemsChangedDisposer", void 0), _define_property(this, "sendInterval", void 0), _define_property(this, "intervalId", void 0), this.connectionService = connectionService, this.logStorage = logStorage, this.logConfig = logConfig, this.log = log, this.inSendFailedScenario = false, this.isSending = false, this.sendInterval = DEFAULT_SEND_INTERVAL;
|
|
123
|
+
this.setRegularSendScenario();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
LogSender = _ts_decorate([
|
|
168
127
|
injectable(),
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
128
|
+
_ts_param(0, inject(ConnectionService)),
|
|
129
|
+
_ts_param(1, inject(LogStorage)),
|
|
130
|
+
_ts_param(2, inject(LOG_CONFIG_TOKEN)),
|
|
131
|
+
_ts_param(3, inject(Log)),
|
|
132
|
+
_ts_metadata("design:type", Function),
|
|
133
|
+
_ts_metadata("design:paramtypes", [
|
|
134
|
+
typeof ConnectionService === "undefined" ? Object : ConnectionService,
|
|
135
|
+
typeof LogStorage === "undefined" ? Object : LogStorage,
|
|
136
|
+
typeof LogConfig === "undefined" ? Object : LogConfig,
|
|
137
|
+
typeof Log === "undefined" ? Object : Log
|
|
138
|
+
])
|
|
175
139
|
], LogSender);
|
|
176
|
-
|
|
140
|
+
|
|
177
141
|
//# sourceMappingURL=log-sender.js.map
|
package/dist/log-sender.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../src/log-sender.ts"],"sourcesContent":["import axios from 'axios';\n\nimport { injectable, inject, Store } from '@servicetitan/react-ioc';\nimport { reaction, IReactionDisposer } from 'mobx';\n\nimport { ConnectionService } from './connection-service';\nimport type { LogConfig } from './log';\nimport { LOG_CONFIG_TOKEN, Log } from './log';\nimport { LogStorage, lastId, StorageItem } from './log-storage';\n\nconst SECOND = 1000;\nconst DEFAULT_SEND_INTERVAL = 60 * SECOND;\nconst INITIAL_RETRY_INTERVAL = SECOND;\nconst MAX_RETRY_INTERVAL = INITIAL_RETRY_INTERVAL * 512;\nconst BATCH_SIZE = 128;\n\n@injectable()\nexport class LogSender extends Store {\n private inSendFailedScenario = false;\n private isSending = false;\n private onItemsChangedDisposer?: IReactionDisposer;\n private sendInterval = DEFAULT_SEND_INTERVAL;\n private intervalId?: number;\n\n constructor(\n @inject(ConnectionService) readonly connectionService: ConnectionService,\n @inject(LogStorage) readonly logStorage: LogStorage,\n @inject(LOG_CONFIG_TOKEN) private readonly logConfig: LogConfig,\n @inject(Log) readonly log: Log\n ) {\n super();\n this.setRegularSendScenario();\n }\n\n dispose() {\n window.clearInterval(this.intervalId);\n }\n\n private onItemsChanged(items: StorageItem[]) {\n if (items.length >= BATCH_SIZE) {\n this.send();\n }\n }\n\n private setSendInterval(interval: number) {\n this.sendInterval = interval;\n window.clearInterval(this.intervalId);\n this.intervalId = window.setInterval(() => {\n if (this.logStorage.items.length > 0) {\n this.send();\n }\n }, interval);\n }\n\n private send() {\n // If offline, punt\n if (!this.connectionService.online) {\n return;\n }\n\n /*\n * Using Web Locks API to prevent multiple tabs from simultaneously\n * sending previously saved items. If the API isn't available, ¯\\_(ツ)_/¯\n */\n if (!('locks' in globalThis.navigator)) {\n this.sendEvents();\n return;\n }\n\n // eslint-disable-next-line no-restricted-globals\n navigator.locks.request(this.logConfig.storageKey, { ifAvailable: true }, async lock => {\n if (lock) {\n await this.sendEvents();\n }\n });\n }\n\n private async sendEvents() {\n if (this.isSending) {\n return;\n }\n\n this.isSending = true;\n try {\n const logEvents = this.logStorage.loadBatch(BATCH_SIZE);\n if (logEvents.length) {\n await axios.post(this.logConfig.endpoint, logEvents);\n this.logStorage.deleteToId(lastId(logEvents));\n\n if (this.inSendFailedScenario) {\n this.setRegularSendScenario();\n }\n }\n } catch (e) {\n this.setFailedSendScenario();\n /* istanbul ignore next */\n if (process.env.NODE_ENV !== 'test') {\n throw e;\n }\n } finally {\n this.isSending = false;\n }\n }\n\n private setRegularSendScenario() {\n this.inSendFailedScenario = false;\n this.setSendInterval(DEFAULT_SEND_INTERVAL);\n this.onItemsChangedDisposer = reaction(\n () => this.logStorage.items,\n items => this.onItemsChanged(items)\n );\n }\n\n private setFailedSendScenario() {\n if (this.inSendFailedScenario) {\n this.increaseSendInterval();\n return;\n }\n\n this.inSendFailedScenario = true;\n this.setSendInterval(INITIAL_RETRY_INTERVAL);\n this.onItemsChangedDisposer?.();\n }\n\n private increaseSendInterval() {\n if (this.sendInterval < MAX_RETRY_INTERVAL) {\n this.setSendInterval(this.sendInterval * 2);\n }\n }\n}\n"],"names":["axios","injectable","inject","Store","reaction","ConnectionService","LOG_CONFIG_TOKEN","Log","LogStorage","lastId","SECOND","DEFAULT_SEND_INTERVAL","INITIAL_RETRY_INTERVAL","MAX_RETRY_INTERVAL","BATCH_SIZE","LogSender","dispose","window","clearInterval","intervalId","onItemsChanged","items","length","send","setSendInterval","interval","sendInterval","setInterval","logStorage","connectionService","online","globalThis","navigator","sendEvents","locks","request","logConfig","storageKey","ifAvailable","lock","isSending","logEvents","loadBatch","post","endpoint","deleteToId","inSendFailedScenario","setRegularSendScenario","e","setFailedSendScenario","process","env","NODE_ENV","onItemsChangedDisposer","increaseSendInterval","constructor","log"],"mappings":"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"}
|
package/dist/log-service.js
CHANGED
|
@@ -1,30 +1,50 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
|
-
import { Provider, useDependencies, useOptionalDependencies
|
|
3
|
+
import { Provider, useDependencies, useOptionalDependencies } from '@servicetitan/react-ioc';
|
|
4
4
|
import { ConnectionService } from './connection-service';
|
|
5
5
|
import { LOG_PARENT_TOKEN, Log } from './log';
|
|
6
6
|
import { LOG_CONFIG_TOKEN, defaultLogConfig } from './log-config';
|
|
7
7
|
import { LogSender } from './log-sender';
|
|
8
8
|
import { LogStorage } from './log-storage';
|
|
9
|
-
export const LogService = ({ children, endpoint = defaultLogConfig.endpoint, storageKey = defaultLogConfig.storageKey
|
|
9
|
+
export const LogService = ({ children, endpoint = defaultLogConfig.endpoint, storageKey = defaultLogConfig.storageKey })=>{
|
|
10
10
|
const [parentLog] = useOptionalDependencies(Log);
|
|
11
|
-
const singletons = useMemo(()
|
|
11
|
+
const singletons = useMemo(()=>{
|
|
12
12
|
const result = [
|
|
13
|
-
{
|
|
13
|
+
{
|
|
14
|
+
provide: LOG_CONFIG_TOKEN,
|
|
15
|
+
useValue: {
|
|
16
|
+
endpoint,
|
|
17
|
+
storageKey
|
|
18
|
+
}
|
|
19
|
+
},
|
|
14
20
|
ConnectionService,
|
|
15
21
|
Log,
|
|
16
22
|
LogStorage,
|
|
17
|
-
LogSender
|
|
23
|
+
LogSender
|
|
18
24
|
];
|
|
19
25
|
if (parentLog) {
|
|
20
|
-
result.push({
|
|
26
|
+
result.push({
|
|
27
|
+
provide: LOG_PARENT_TOKEN,
|
|
28
|
+
useValue: parentLog
|
|
29
|
+
});
|
|
21
30
|
}
|
|
22
31
|
return result;
|
|
23
|
-
}, [
|
|
24
|
-
|
|
32
|
+
}, [
|
|
33
|
+
endpoint,
|
|
34
|
+
parentLog,
|
|
35
|
+
storageKey
|
|
36
|
+
]);
|
|
37
|
+
return /*#__PURE__*/ _jsxs(Provider, {
|
|
38
|
+
singletons: singletons,
|
|
39
|
+
children: [
|
|
40
|
+
/*#__PURE__*/ _jsx(InitializeLogSender, {}),
|
|
41
|
+
children
|
|
42
|
+
]
|
|
43
|
+
});
|
|
25
44
|
};
|
|
26
|
-
const InitializeLogSender = ()
|
|
45
|
+
const InitializeLogSender = ()=>{
|
|
27
46
|
useDependencies(LogSender);
|
|
28
47
|
return null;
|
|
29
48
|
};
|
|
49
|
+
|
|
30
50
|
//# sourceMappingURL=log-service.js.map
|
package/dist/log-service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../src/log-service.tsx"],"sourcesContent":["import { FC, PropsWithChildren, useMemo } from 'react';\nimport {\n Provider,\n ProviderProps,\n useDependencies,\n useOptionalDependencies,\n} from '@servicetitan/react-ioc';\nimport { ConnectionService } from './connection-service';\nimport { LOG_PARENT_TOKEN, Log } from './log';\nimport { LOG_CONFIG_TOKEN, defaultLogConfig } from './log-config';\nimport { LogSender } from './log-sender';\nimport { LogStorage } from './log-storage';\n\nexport interface LogServiceProps extends PropsWithChildren {\n endpoint?: string;\n storageKey?: string;\n}\n\nexport const LogService: FC<LogServiceProps> = ({\n children,\n endpoint = defaultLogConfig.endpoint,\n storageKey = defaultLogConfig.storageKey,\n}) => {\n const [parentLog] = useOptionalDependencies(Log);\n\n const singletons = useMemo(() => {\n const result: ProviderProps['singletons'] = [\n { provide: LOG_CONFIG_TOKEN, useValue: { endpoint, storageKey } },\n ConnectionService,\n Log,\n LogStorage,\n LogSender,\n ];\n if (parentLog) {\n result.push({ provide: LOG_PARENT_TOKEN, useValue: parentLog });\n }\n return result;\n }, [endpoint, parentLog, storageKey]);\n\n return (\n <Provider singletons={singletons}>\n <InitializeLogSender />\n {children}\n </Provider>\n );\n};\n\nconst InitializeLogSender: FC = () => {\n useDependencies(LogSender);\n return null;\n};\n"],"names":["useMemo","Provider","useDependencies","useOptionalDependencies","ConnectionService","LOG_PARENT_TOKEN","Log","LOG_CONFIG_TOKEN","defaultLogConfig","LogSender","LogStorage","LogService","children","endpoint","storageKey","parentLog","singletons","result","provide","useValue","push","InitializeLogSender"],"mappings":";AAAA,SAAgCA,OAAO,QAAQ,QAAQ;AACvD,SACIC,QAAQ,EAERC,eAAe,EACfC,uBAAuB,QACpB,0BAA0B;AACjC,SAASC,iBAAiB,QAAQ,uBAAuB;AACzD,SAASC,gBAAgB,EAAEC,GAAG,QAAQ,QAAQ;AAC9C,SAASC,gBAAgB,EAAEC,gBAAgB,QAAQ,eAAe;AAClE,SAASC,SAAS,QAAQ,eAAe;AACzC,SAASC,UAAU,QAAQ,gBAAgB;AAO3C,OAAO,MAAMC,aAAkC,CAAC,EAC5CC,QAAQ,EACRC,WAAWL,iBAAiBK,QAAQ,EACpCC,aAAaN,iBAAiBM,UAAU,EAC3C;IACG,MAAM,CAACC,UAAU,GAAGZ,wBAAwBG;IAE5C,MAAMU,aAAahB,QAAQ;QACvB,MAAMiB,SAAsC;YACxC;gBAAEC,SAASX;gBAAkBY,UAAU;oBAAEN;oBAAUC;gBAAW;YAAE;YAChEV;YACAE;YACAI;YACAD;SACH;QACD,IAAIM,WAAW;YACXE,OAAOG,IAAI,CAAC;gBAAEF,SAASb;gBAAkBc,UAAUJ;YAAU;QACjE;QACA,OAAOE;IACX,GAAG;QAACJ;QAAUE;QAAWD;KAAW;IAEpC,qBACI,MAACb;QAASe,YAAYA;;0BAClB,KAACK;YACAT;;;AAGb,EAAE;AAEF,MAAMS,sBAA0B;IAC5BnB,gBAAgBO;IAChB,OAAO;AACX"}
|
package/dist/log-storage.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-storage.d.ts","sourceRoot":"","sources":["../src/log-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"log-storage.d.ts","sourceRoot":"","sources":["../src/log-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACrB;AAWD,qBACa,UAAW,SAAQ,KAAK;IAUK,OAAO,CAAC,QAAQ,CAAC,SAAS;IARhE,KAAK,EAAE,WAAW,EAAE,CAAM;IAE1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAK;IAE7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAmB;gBAEoB,SAAS,EAAE,SAAS;IA0B3E,OAAO;IAIP,IAAI,MAAM,IAAI,SAAS,CAEtB;IAED,KAAK,CAAC,KAAK,EAAE,aAAa;IAgB1B,UAAU,CAAC,EAAE,EAAE,MAAM;IAcrB,SAAS,CAAC,SAAS,EAAE,MAAM;IAI3B,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,QAAQ;IAKhB,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,KAAK,iBAAiB,GAE5B;IAED,OAAO,CAAC,cAAc;CAIzB;AAMD,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,CAMnD"}
|
package/dist/log-storage.js
CHANGED
|
@@ -1,82 +1,41 @@
|
|
|
1
|
-
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
15
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
16
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for
|
|
17
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
18
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
}
|
|
7
|
-
|
|
19
|
+
}
|
|
20
|
+
function _ts_metadata(k, v) {
|
|
8
21
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return function
|
|
12
|
-
|
|
22
|
+
}
|
|
23
|
+
function _ts_param(paramIndex, decorator) {
|
|
24
|
+
return function(target, key) {
|
|
25
|
+
decorator(target, key, paramIndex);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
13
28
|
import { inject, injectable, Store } from '@servicetitan/react-ioc';
|
|
14
29
|
import { observable, action, makeObservable, toJS } from 'mobx';
|
|
15
30
|
import { LOG_CONFIG_TOKEN } from './log-config';
|
|
16
|
-
var EventType
|
|
17
|
-
(function (EventType) {
|
|
31
|
+
var EventType = /*#__PURE__*/ function(EventType) {
|
|
18
32
|
EventType["Delete"] = "delete";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
super();
|
|
23
|
-
Object.defineProperty(this, "logConfig", {
|
|
24
|
-
enumerable: true,
|
|
25
|
-
configurable: true,
|
|
26
|
-
writable: true,
|
|
27
|
-
value: logConfig
|
|
28
|
-
});
|
|
29
|
-
Object.defineProperty(this, "items", {
|
|
30
|
-
enumerable: true,
|
|
31
|
-
configurable: true,
|
|
32
|
-
writable: true,
|
|
33
|
-
value: []
|
|
34
|
-
});
|
|
35
|
-
Object.defineProperty(this, "maxLogSize", {
|
|
36
|
-
enumerable: true,
|
|
37
|
-
configurable: true,
|
|
38
|
-
writable: true,
|
|
39
|
-
value: 1000
|
|
40
|
-
});
|
|
41
|
-
Object.defineProperty(this, "version", {
|
|
42
|
-
enumerable: true,
|
|
43
|
-
configurable: true,
|
|
44
|
-
writable: true,
|
|
45
|
-
value: 1
|
|
46
|
-
});
|
|
47
|
-
Object.defineProperty(this, "nextItemId", {
|
|
48
|
-
enumerable: true,
|
|
49
|
-
configurable: true,
|
|
50
|
-
writable: true,
|
|
51
|
-
value: void 0
|
|
52
|
-
});
|
|
53
|
-
Object.defineProperty(this, "channel", {
|
|
54
|
-
enumerable: true,
|
|
55
|
-
configurable: true,
|
|
56
|
-
writable: true,
|
|
57
|
-
value: void 0
|
|
58
|
-
});
|
|
59
|
-
makeObservable(this);
|
|
60
|
-
const version = window.parseInt(localStorage.getItem(this.storageVersionKey));
|
|
61
|
-
if (version !== this.version) {
|
|
62
|
-
localStorage.removeItem(this.storageKey);
|
|
63
|
-
localStorage.setItem(this.storageVersionKey, String(this.version));
|
|
64
|
-
}
|
|
65
|
-
this.loadSavedItems();
|
|
66
|
-
this.nextItemId = lastId(this.items) + 1;
|
|
67
|
-
/*
|
|
68
|
-
* Use the BroadcastChannel API to prevent different tabs from processing
|
|
69
|
-
* the saved items. The first one to process the items sends a "delete" event
|
|
70
|
-
* that causes all other instances to discard them from memory.
|
|
71
|
-
*/
|
|
72
|
-
if ('BroadcastChannel' in globalThis) {
|
|
73
|
-
this.channel = new BroadcastChannel(logConfig.storageKey);
|
|
74
|
-
this.channel.addEventListener('message', ({ data }) => this.handleDeleteEvent(data));
|
|
75
|
-
}
|
|
76
|
-
}
|
|
33
|
+
return EventType;
|
|
34
|
+
}(EventType || {});
|
|
35
|
+
export class LogStorage extends Store {
|
|
77
36
|
dispose() {
|
|
78
|
-
var
|
|
79
|
-
(
|
|
37
|
+
var _this_channel;
|
|
38
|
+
(_this_channel = this.channel) === null || _this_channel === void 0 ? void 0 : _this_channel.close();
|
|
80
39
|
}
|
|
81
40
|
get config() {
|
|
82
41
|
return this.logConfig;
|
|
@@ -89,15 +48,18 @@ let LogStorage = class LogStorage extends Store {
|
|
|
89
48
|
code: entry.code,
|
|
90
49
|
message: entry.message,
|
|
91
50
|
data: JSON.stringify(entry.data),
|
|
92
|
-
exception: this.stringifyError(entry.error)
|
|
51
|
+
exception: this.stringifyError(entry.error)
|
|
93
52
|
};
|
|
94
|
-
let items = [
|
|
53
|
+
let items = [
|
|
54
|
+
...this.items,
|
|
55
|
+
item
|
|
56
|
+
];
|
|
95
57
|
items = items.slice(-this.maxLogSize);
|
|
96
58
|
this.setItems(items);
|
|
97
59
|
}
|
|
98
60
|
deleteToId(id) {
|
|
99
61
|
const deletedItems = [];
|
|
100
|
-
const items = this.items.filter(item
|
|
62
|
+
const items = this.items.filter((item)=>{
|
|
101
63
|
if (item.id > id) {
|
|
102
64
|
return true;
|
|
103
65
|
}
|
|
@@ -111,40 +73,40 @@ let LogStorage = class LogStorage extends Store {
|
|
|
111
73
|
return this.items.slice(0, batchSize);
|
|
112
74
|
}
|
|
113
75
|
loadSavedItems() {
|
|
114
|
-
var _a;
|
|
115
76
|
try {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
items.forEach((item)
|
|
77
|
+
var _JSON_parse;
|
|
78
|
+
const items = (_JSON_parse = JSON.parse(localStorage.getItem(this.storageKey))) !== null && _JSON_parse !== void 0 ? _JSON_parse : [];
|
|
79
|
+
/* migrate error -> exception */ items.forEach((item)=>{
|
|
119
80
|
if (typeof item.error === 'string') {
|
|
120
81
|
item.exception = item.error;
|
|
121
82
|
delete item.error;
|
|
122
83
|
}
|
|
123
84
|
});
|
|
124
85
|
this.setItems(items);
|
|
125
|
-
}
|
|
126
|
-
catch (_b) {
|
|
86
|
+
} catch (e) {
|
|
127
87
|
this.setItems([]);
|
|
128
88
|
}
|
|
129
89
|
}
|
|
130
90
|
postDeleteEvent(items) {
|
|
131
91
|
if (this.channel) {
|
|
132
92
|
const event = {
|
|
133
|
-
type:
|
|
134
|
-
items: items.map(item
|
|
93
|
+
type: "delete",
|
|
94
|
+
items: items.map((item)=>toJS(item))
|
|
135
95
|
};
|
|
136
96
|
this.channel.postMessage(event);
|
|
137
97
|
}
|
|
138
98
|
}
|
|
139
99
|
handleDeleteEvent(event) {
|
|
140
|
-
/* istanbul ignore next: because there's only one event type */
|
|
141
|
-
if (event.type !== EventType.Delete) {
|
|
100
|
+
/* istanbul ignore next: because there's only one event type */ if (event.type !== "delete") {
|
|
142
101
|
return;
|
|
143
102
|
}
|
|
144
103
|
// Map item id to object for fast lookup
|
|
145
|
-
const map = new Map(event.items.map(item
|
|
104
|
+
const map = new Map(event.items.map((item)=>[
|
|
105
|
+
item.id,
|
|
106
|
+
item
|
|
107
|
+
]));
|
|
146
108
|
// Discard deleted items
|
|
147
|
-
const items = this.items.filter(item
|
|
109
|
+
const items = this.items.filter((item)=>!isEqual(item, map.get(item.id)));
|
|
148
110
|
this.setItems(items);
|
|
149
111
|
// If no more items, close channel; all saved items have been processed
|
|
150
112
|
if (items.length === 0 && this.channel) {
|
|
@@ -153,7 +115,9 @@ let LogStorage = class LogStorage extends Store {
|
|
|
153
115
|
}
|
|
154
116
|
}
|
|
155
117
|
setItems(items) {
|
|
156
|
-
this.items = [
|
|
118
|
+
this.items = [
|
|
119
|
+
...items
|
|
120
|
+
];
|
|
157
121
|
localStorage.setItem(this.storageKey, JSON.stringify(this.items));
|
|
158
122
|
}
|
|
159
123
|
get storageKey() {
|
|
@@ -163,28 +127,54 @@ let LogStorage = class LogStorage extends Store {
|
|
|
163
127
|
return `${this.storageKey}Version`;
|
|
164
128
|
}
|
|
165
129
|
stringifyError(error) {
|
|
166
|
-
const detail = error ? {
|
|
130
|
+
const detail = error ? {
|
|
131
|
+
message: error.message.toString(),
|
|
132
|
+
stack: error.stack
|
|
133
|
+
} : null;
|
|
167
134
|
return JSON.stringify(detail);
|
|
168
135
|
}
|
|
169
|
-
|
|
170
|
-
|
|
136
|
+
constructor(logConfig){
|
|
137
|
+
super(), _define_property(this, "logConfig", void 0), _define_property(this, "items", void 0), _define_property(this, "maxLogSize", void 0), _define_property(this, "version", void 0), _define_property(this, "nextItemId", void 0), _define_property(this, "channel", void 0), this.logConfig = logConfig, this.items = [], this.maxLogSize = 1000, this.version = 1;
|
|
138
|
+
makeObservable(this);
|
|
139
|
+
const version = window.parseInt(localStorage.getItem(this.storageVersionKey));
|
|
140
|
+
if (version !== this.version) {
|
|
141
|
+
localStorage.removeItem(this.storageKey);
|
|
142
|
+
localStorage.setItem(this.storageVersionKey, String(this.version));
|
|
143
|
+
}
|
|
144
|
+
this.loadSavedItems();
|
|
145
|
+
this.nextItemId = lastId(this.items) + 1;
|
|
146
|
+
/*
|
|
147
|
+
* Use the BroadcastChannel API to prevent different tabs from processing
|
|
148
|
+
* the saved items. The first one to process the items sends a "delete" event
|
|
149
|
+
* that causes all other instances to discard them from memory.
|
|
150
|
+
*/ if ('BroadcastChannel' in globalThis) {
|
|
151
|
+
this.channel = new BroadcastChannel(logConfig.storageKey);
|
|
152
|
+
this.channel.addEventListener('message', ({ data })=>this.handleDeleteEvent(data));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
_ts_decorate([
|
|
171
157
|
observable,
|
|
172
|
-
|
|
158
|
+
_ts_metadata("design:type", Array)
|
|
173
159
|
], LogStorage.prototype, "items", void 0);
|
|
174
|
-
|
|
160
|
+
_ts_decorate([
|
|
175
161
|
action,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
162
|
+
_ts_metadata("design:type", Function),
|
|
163
|
+
_ts_metadata("design:paramtypes", [
|
|
164
|
+
Array
|
|
165
|
+
]),
|
|
166
|
+
_ts_metadata("design:returntype", void 0)
|
|
179
167
|
], LogStorage.prototype, "setItems", null);
|
|
180
|
-
LogStorage =
|
|
168
|
+
LogStorage = _ts_decorate([
|
|
181
169
|
injectable(),
|
|
182
|
-
|
|
183
|
-
|
|
170
|
+
_ts_param(0, inject(LOG_CONFIG_TOKEN)),
|
|
171
|
+
_ts_metadata("design:type", Function),
|
|
172
|
+
_ts_metadata("design:paramtypes", [
|
|
173
|
+
typeof LogConfig === "undefined" ? Object : LogConfig
|
|
174
|
+
])
|
|
184
175
|
], LogStorage);
|
|
185
|
-
export { LogStorage };
|
|
186
176
|
function isEqual(a, b) {
|
|
187
|
-
return b && Object.keys(a).every((key)
|
|
177
|
+
return b && Object.keys(a).every((key)=>a[key] === b[key]);
|
|
188
178
|
}
|
|
189
179
|
export function lastId(items) {
|
|
190
180
|
if (!items.length) {
|
|
@@ -193,4 +183,5 @@ export function lastId(items) {
|
|
|
193
183
|
const item = items[items.length - 1];
|
|
194
184
|
return item.id;
|
|
195
185
|
}
|
|
186
|
+
|
|
196
187
|
//# sourceMappingURL=log-storage.js.map
|
package/dist/log-storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-storage.js","sourceRoot":"","sources":["../src/log-storage.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/log-storage.ts"],"sourcesContent":["import { inject, injectable, Store } from '@servicetitan/react-ioc';\nimport { observable, action, makeObservable, toJS } from 'mobx';\n\nimport { EntryComplete, Nullable } from './log';\nimport type { LogConfig } from './log-config';\nimport { LOG_CONFIG_TOKEN } from './log-config';\n\nexport interface StorageItem {\n id: number;\n type: string;\n category: Nullable<string>;\n code: Nullable<string>;\n message: Nullable<string>;\n data: string;\n exception: string;\n}\n\nenum EventType {\n Delete = 'delete',\n}\n\ninterface DeleteEvent {\n type: EventType;\n items: StorageItem[];\n}\n\n@injectable()\nexport class LogStorage extends Store {\n @observable\n items: StorageItem[] = [];\n\n private readonly maxLogSize = 1000;\n private readonly version = 1;\n\n private nextItemId: number;\n private channel?: BroadcastChannel;\n\n constructor(@inject(LOG_CONFIG_TOKEN) private readonly logConfig: LogConfig) {\n super();\n makeObservable(this);\n\n const version = window.parseInt(localStorage.getItem(this.storageVersionKey) as string);\n if (version !== this.version) {\n localStorage.removeItem(this.storageKey);\n localStorage.setItem(this.storageVersionKey, String(this.version));\n }\n\n this.loadSavedItems();\n this.nextItemId = lastId(this.items) + 1;\n\n /*\n * Use the BroadcastChannel API to prevent different tabs from processing\n * the saved items. The first one to process the items sends a \"delete\" event\n * that causes all other instances to discard them from memory.\n */\n if ('BroadcastChannel' in globalThis) {\n this.channel = new BroadcastChannel(logConfig.storageKey);\n this.channel.addEventListener('message', ({ data }: MessageEvent<DeleteEvent>) =>\n this.handleDeleteEvent(data)\n );\n }\n }\n\n dispose() {\n this.channel?.close();\n }\n\n get config(): LogConfig {\n return this.logConfig;\n }\n\n store(entry: EntryComplete) {\n const item: StorageItem = {\n id: this.nextItemId++,\n type: entry.type,\n category: entry.category,\n code: entry.code,\n message: entry.message,\n data: JSON.stringify(entry.data),\n exception: this.stringifyError(entry.error),\n };\n\n let items = [...this.items, item];\n items = items.slice(-this.maxLogSize);\n this.setItems(items);\n }\n\n deleteToId(id: number) {\n const deletedItems: StorageItem[] = [];\n const items = this.items.filter(item => {\n if (item.id > id) {\n return true;\n }\n deletedItems.push(item);\n return false;\n });\n\n this.setItems(items);\n this.postDeleteEvent(deletedItems);\n }\n\n loadBatch(batchSize: number) {\n return this.items.slice(0, batchSize);\n }\n\n private loadSavedItems() {\n try {\n const items = JSON.parse(localStorage.getItem(this.storageKey) as string) ?? [];\n\n /* migrate error -> exception */\n items.forEach((item: StorageItem & { error?: string }) => {\n if (typeof item.error === 'string') {\n item.exception = item.error;\n delete item.error;\n }\n });\n this.setItems(items);\n } catch {\n this.setItems([]);\n }\n }\n\n private postDeleteEvent(items: StorageItem[]) {\n if (this.channel) {\n const event: DeleteEvent = {\n type: EventType.Delete,\n items: items.map(item => toJS(item)),\n };\n this.channel.postMessage(event);\n }\n }\n\n private handleDeleteEvent(event: DeleteEvent) {\n /* istanbul ignore next: because there's only one event type */\n if (event.type !== EventType.Delete) {\n return;\n }\n\n // Map item id to object for fast lookup\n const map = new Map<number, StorageItem>(event.items.map(item => [item.id, item]));\n\n // Discard deleted items\n const items = this.items.filter(item => !isEqual(item, map.get(item.id)));\n this.setItems(items);\n\n // If no more items, close channel; all saved items have been processed\n if (items.length === 0 && this.channel) {\n this.channel.close();\n delete this.channel;\n }\n }\n\n @action\n private setItems(items: StorageItem[]) {\n this.items = [...items];\n localStorage.setItem(this.storageKey, JSON.stringify(this.items));\n }\n\n private get storageKey() {\n return this.logConfig.storageKey;\n }\n\n private get storageVersionKey() {\n return `${this.storageKey}Version`;\n }\n\n private stringifyError(error: Nullable<Error>) {\n const detail = error ? { message: error.message.toString(), stack: error.stack } : null;\n return JSON.stringify(detail);\n }\n}\n\nfunction isEqual(a: StorageItem, b?: StorageItem) {\n return b && Object.keys(a).every((key: keyof StorageItem) => a[key] === b[key]);\n}\n\nexport function lastId(items: StorageItem[]): number {\n if (!items.length) {\n return 0;\n }\n const item = items[items.length - 1];\n return item.id;\n}\n"],"names":["inject","injectable","Store","observable","action","makeObservable","toJS","LOG_CONFIG_TOKEN","EventType","LogStorage","dispose","channel","close","config","logConfig","store","entry","item","id","nextItemId","type","category","code","message","data","JSON","stringify","exception","stringifyError","error","items","slice","maxLogSize","setItems","deleteToId","deletedItems","filter","push","postDeleteEvent","loadBatch","batchSize","loadSavedItems","parse","localStorage","getItem","storageKey","forEach","event","map","postMessage","handleDeleteEvent","Map","isEqual","get","length","setItem","storageVersionKey","detail","toString","stack","constructor","version","window","parseInt","removeItem","String","lastId","globalThis","BroadcastChannel","addEventListener","a","b","Object","keys","every","key"],"mappings":"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"}
|