@ohbug/core 2.1.0 → 2.2.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.
@@ -0,0 +1,29 @@
1
+ import { OhbugClientConstructor, OhbugEventWithMethods, OhbugExtension } from '@ohbug/types';
2
+
3
+ declare const Client: OhbugClientConstructor;
4
+
5
+ declare function isEvent(eventLike: any): eventLike is OhbugEventWithMethods<any>;
6
+
7
+ declare function defineExtension(extension: OhbugExtension): OhbugExtension;
8
+
9
+ declare const enum EventTypes {
10
+ UNCAUGHT_ERROR = "uncaughtError",
11
+ RESOURCE_ERROR = "resourceError",
12
+ UNHANDLEDREJECTION_ERROR = "unhandledrejectionError",
13
+ AJAX_ERROR = "ajaxError",
14
+ FETCH_ERROR = "fetchError",
15
+ WEBSOCKET_ERROR = "websocketError",
16
+ UNKNOWN_ERROR = "unknownError",
17
+ MESSAGE = "message",
18
+ FEEDBACK = "feedback",
19
+ VIEW = "view",
20
+ REACT = "react",
21
+ VUE = "vue",
22
+ ANGULAR = "angular",
23
+ MINIAPP_ERROR = "miniappError",
24
+ MINIAPP_UNHANDLEDREJECTION_ERROR = "miniappUnhandledrejectionError",
25
+ MINIAPP_PAGENOTFOUND_ERROR = "miniappPagenotfoundError",
26
+ MINIAPP_MEMORYWARNING_ERROR = "miniappMemorywarningError"
27
+ }
28
+
29
+ export { Client, EventTypes, defineExtension, isEvent };
package/dist/index.js CHANGED
@@ -1,5 +1,635 @@
1
- "use strict";var R=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var K=(e,t)=>{for(var n in t)R(e,n,{get:t[n],enumerable:!0})},G=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of k(t))!P.call(e,a)&&a!==n&&R(e,a,{get:()=>t[a],enumerable:!(r=I(t,a))||r.enumerable});return e};var F=e=>G(R({},"__esModule",{value:!0}),e);var H={};K(H,{Client:()=>$,EventTypes:()=>W,defineExtension:()=>B,isEvent:()=>y});module.exports=F(H);var c=require("@ohbug/utils");var u=require("@ohbug/utils"),A={apiKey:{defaultValue:void 0,message:"is required",validate:e=>Boolean(e)&&(0,u.isString)(e)},appVersion:{defaultValue:void 0,message:"should be a string",validate:e=>e===void 0||(0,u.isString)(e)},appType:{defaultValue:void 0,message:"should be a string",validate:e=>e===void 0||(0,u.isString)(e)},releaseStage:{defaultValue:"production",message:"should be a string",validate:e=>e===void 0||(0,u.isString)(e)},endpoint:{defaultValue:"http://localhost:6660",message:"should be a string",validate:e=>e===void 0||(0,u.isString)(e)},maxActions:{defaultValue:30,message:"should be a number between 0 and 100",validate:e=>e===void 0||(0,u.isNumber)(e)&&e>=1&&e<=100},onEvent:{defaultValue:e=>e,message:"should be a function",validate:e=>e===void 0||(0,u.isFunction)(e)},onNotify:{defaultValue:()=>{},message:"should be a function",validate:e=>e===void 0||(0,u.isFunction)(e)},logger:{defaultValue:u.logger,message:"should be null or an object with methods { log, info, warn, error }",validate:e=>e===void 0||e&&["log","info","warn","error"].reduce((t,n)=>t&&typeof e[n]=="function",!0)},user:{defaultValue:void 0,message:"should be an object and have up to 6 attributes",validate:e=>e===void 0||(0,u.isObject)(e)&&Object.keys(e).length<=6},metadata:{defaultValue:void 0,message:"should be an object",validate:e=>e===void 0||(0,u.isObject)(e)}};var l=require("@ohbug/utils");var b=class{type;timestamp;message;data;constructor(t,n,r,a){this.type=r,this.timestamp=a||new Date().toISOString(),this.message=t,this.data=n}};function S(e,t){return new Error(`Invalid configuration
2
- ${Object.keys(e).map(n=>`- ${n} ${e[n]}, got ${JSON.stringify(t[n])}`).join(`
3
- `)}
4
- `)}function O(e,t){return new Error(`Invalid data
5
- - ${e}, got ${JSON.stringify(t)}`)}function p(e,t,n){!t||(e[t]=n)}function m(e,t){if(e[t])return e[t]}function _(e,t){if(e[t])return delete e[t]}var D=class{apiKey;appVersion;appType;timestamp;category;type;sdk;device;detail;user;actions;metadata;releaseStage;__client;constructor(t,n){let{apiKey:r,appVersion:a,appType:i,releaseStage:o,timestamp:d,category:g,type:h,sdk:f,detail:E,device:C,user:M,actions:w,metadata:j}=t;this.apiKey=r,this.appVersion=a,this.appType=i,this.releaseStage=o,this.timestamp=d,this.category=g,this.type=h,this.sdk=f,this.detail=E,this.device=C,this.user=M,this.actions=w,this.metadata=j??{},this.__client=n}get __isOhbugEvent(){return!0}addAction(t,n,r,a){var f;let i=this.actions,o=(0,l.isString)(t)?t:"",d=n||{},g=(0,l.isString)(r)?r:"",h=new b(o,d,g,a);i.length>=(((f=this.__client)==null?void 0:f.__config.maxActions)??30)&&i.shift(),i.push(h)}getUser(){return this.user}setUser(t){var n;if((0,l.isObject)(t)&&Object.keys(t).length<=6)return this.user={...this.user,...t},this.getUser();(n=this.__client)==null||n.__logger.error(O("setUser should be an object and have up to 6 attributes",t))}addMetadata(t,n){return p(this.metadata,t,n)}getMetadata(t){return m(this.metadata,t)}deleteMetadata(t){return _(this.metadata,t)}toJSON(){let{apiKey:t,appVersion:n,appType:r,timestamp:a,category:i,type:o,sdk:d,device:g,detail:h,user:f,actions:E,metadata:C,releaseStage:M}=this;return{apiKey:t,appVersion:n,appType:r,timestamp:a,category:i,type:o,sdk:d,device:g,detail:h,user:f,actions:E,metadata:C,releaseStage:M}}};function v(e,t){let{apiKey:n,appVersion:r,appType:a,releaseStage:i}=t.__config,o=new Date().toISOString(),d=t.__device(t),g,h,f;return(0,l.isObject)(e)&&Object.prototype.hasOwnProperty.call(e,"type")&&Object.prototype.hasOwnProperty.call(e,"detail")?(g=e.category||"error",h=e.type,f=e.detail):(g="error",h="unknownError",f=e),new D({apiKey:n,appVersion:r,appType:a,timestamp:o,category:g,type:h,sdk:t.__sdk,device:d,user:t.__user,detail:f,actions:t.__actions,metadata:t.__metadata,releaseStage:i},t)}function x(e,t){let n=[t.__config.onEvent,...t.__extensions.map(({onEvent:r})=>r)].filter(r=>(0,l.isFunction)(r));return n.length===0?e:n.reduce((r,a)=>r&&(0,l.isFunction)(a)?a(r,t):null,e)}function y(e){return Boolean(e==null?void 0:e.__isOhbugEvent)}var U=require("@ohbug/utils");function J(e,t){[t.__config.onNotify,...t.__extensions.filter(({onNotify:r})=>(0,U.isFunction)(r)).map(({onNotify:r})=>r)].forEach(r=>r==null?void 0:r(e,t))}async function N(e,t){try{let n=null;return e&&(n=await t.__notifier(e),J(e,t)),n}catch(n){t.__logger.error(n)}}function V(e,t){return Object.keys(t).reduce((r,a)=>{let i=e[a],{defaultValue:o,message:d,validate:g}=t[a];return i!==void 0?g(i)?r.config[a]=i:(r.config[a]=o,r.errors[a]=d):r.config[a]=o,r},{config:{},errors:{}})}var $=class{__sdk;__config;__logger;__device;__notifier;__extensions;__actions;__user;__metadata;constructor({sdk:t,config:n,schema:r=A,device:a,notifier:i}){let{config:o,errors:d}=V(n,r);this.__sdk=t,this.__config=o,this.__logger=o.logger,this.__device=a,this.__notifier=i,this.__extensions=[],this.__actions=[],this.__user=o.user,this.__metadata={},(0,c.isObject)(o.metadata)&&Object.keys(o.metadata).forEach(g=>{this.addMetadata(g,o.metadata[g])}),Object.keys(d).length&&this.__logger.warn(S(d,n))}use(t){var n;return this.__extensions.push(t),(n=t.onSetup)==null||n.call(t,this),this}createEvent(t){let n=v(t,this);return x(n,this)}notify(t,n){let r;return Boolean(t)&&!y(t)?r=this.createEvent(t):r=t,n&&(r=n(r)),N(r,this)}addAction(t,n,r,a){let i=this.__actions,o=(0,c.isString)(t)?t:"",d=n||{},g=(0,c.isString)(r)?r:"",h=new b(o,d,g,a);i.length>=this.__config.maxActions&&i.shift(),i.push(h)}getUser(){return this.__user}setUser(t){if((0,c.isObject)(t)&&Object.keys(t).length<=6)return this.__user={...this.__user,...t},this.getUser();this.__logger.warn(O("setUser should be an object and have up to 6 attributes",t))}addMetadata(t,n){return p(this.__metadata,t,n)}getMetadata(t){return m(this.__metadata,t)}deleteMetadata(t){return _(this.__metadata,t)}};function B(e){return e||{}}var W=(s=>(s.UNCAUGHT_ERROR="uncaughtError",s.RESOURCE_ERROR="resourceError",s.UNHANDLEDREJECTION_ERROR="unhandledrejectionError",s.AJAX_ERROR="ajaxError",s.FETCH_ERROR="fetchError",s.WEBSOCKET_ERROR="websocketError",s.UNKNOWN_ERROR="unknownError",s.MESSAGE="message",s.FEEDBACK="feedback",s.VIEW="view",s.REACT="react",s.VUE="vue",s.ANGULAR="angular",s.MINIAPP_ERROR="miniappError",s.MINIAPP_UNHANDLEDREJECTION_ERROR="miniappUnhandledrejectionError",s.MINIAPP_PAGENOTFOUND_ERROR="miniappPagenotfoundError",s.MINIAPP_MEMORYWARNING_ERROR="miniappMemorywarningError",s))(W||{});0&&(module.exports={Client,EventTypes,defineExtension,isEvent});
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var __export = (target, all) => {
21
+ for (var name in all)
22
+ __defProp(target, name, { get: all[name], enumerable: true });
23
+ };
24
+ var __copyProps = (to, from, except, desc) => {
25
+ if (from && typeof from === "object" || typeof from === "function") {
26
+ for (let key of __getOwnPropNames(from))
27
+ if (!__hasOwnProp.call(to, key) && key !== except)
28
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
29
+ }
30
+ return to;
31
+ };
32
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
+ var __publicField = (obj, key, value) => {
34
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
35
+ return value;
36
+ };
37
+
38
+ // src/index.ts
39
+ var src_exports = {};
40
+ __export(src_exports, {
41
+ Client: () => Client,
42
+ EventTypes: () => EventTypes,
43
+ defineExtension: () => defineExtension,
44
+ isEvent: () => isEvent
45
+ });
46
+ module.exports = __toCommonJS(src_exports);
47
+
48
+ // src/client.ts
49
+ var import_utils4 = require("@ohbug/utils");
50
+
51
+ // src/config.ts
52
+ var import_utils = require("@ohbug/utils");
53
+ var schema = {
54
+ // base
55
+ apiKey: {
56
+ defaultValue: void 0,
57
+ message: "is required",
58
+ validate: (value) => Boolean(value) && (0, import_utils.isString)(value)
59
+ },
60
+ appVersion: {
61
+ defaultValue: void 0,
62
+ message: "should be a string",
63
+ validate: (value) => value === void 0 || (0, import_utils.isString)(value)
64
+ },
65
+ appType: {
66
+ defaultValue: void 0,
67
+ message: "should be a string",
68
+ validate: (value) => value === void 0 || (0, import_utils.isString)(value)
69
+ },
70
+ releaseStage: {
71
+ defaultValue: "production",
72
+ message: "should be a string",
73
+ validate: (value) => value === void 0 || (0, import_utils.isString)(value)
74
+ },
75
+ endpoint: {
76
+ defaultValue: "http://localhost:6660",
77
+ message: "should be a string",
78
+ validate: (value) => value === void 0 || (0, import_utils.isString)(value)
79
+ },
80
+ maxActions: {
81
+ defaultValue: 30,
82
+ message: "should be a number between 0 and 100",
83
+ validate: (value) => value === void 0 || (0, import_utils.isNumber)(value) && value >= 0 && value <= 100
84
+ },
85
+ // hooks
86
+ onEvent: {
87
+ defaultValue: (event) => event,
88
+ message: "should be a function",
89
+ validate: (value) => value === void 0 || (0, import_utils.isFunction)(value)
90
+ },
91
+ onNotify: {
92
+ defaultValue: () => {
93
+ },
94
+ message: "should be a function",
95
+ validate: (value) => value === void 0 || (0, import_utils.isFunction)(value)
96
+ },
97
+ // utils
98
+ logger: {
99
+ defaultValue: import_utils.logger,
100
+ message: "should be null or an object with methods { log, info, warn, error }",
101
+ validate: (value) => value === void 0 || value && ["log", "info", "warn", "error"].reduce(
102
+ (accumulator, method) => accumulator && typeof value[method] === "function",
103
+ true
104
+ )
105
+ },
106
+ // data
107
+ user: {
108
+ defaultValue: void 0,
109
+ message: "should be an object and have up to 6 attributes",
110
+ validate: (value) => value === void 0 || (0, import_utils.isObject)(value) && Object.keys(value).length <= 6
111
+ },
112
+ metadata: {
113
+ defaultValue: void 0,
114
+ message: "should be an object",
115
+ validate: (value) => value === void 0 || (0, import_utils.isObject)(value)
116
+ }
117
+ };
118
+
119
+ // src/event.ts
120
+ var import_utils2 = require("@ohbug/utils");
121
+
122
+ // src/action.ts
123
+ var Action = class {
124
+ constructor(message, data, type, timestamp) {
125
+ __publicField(this, "type");
126
+ __publicField(this, "timestamp");
127
+ __publicField(this, "message");
128
+ __publicField(this, "data");
129
+ this.type = type;
130
+ this.timestamp = timestamp || (/* @__PURE__ */ new Date()).toISOString();
131
+ this.message = message;
132
+ this.data = data;
133
+ }
134
+ };
135
+
136
+ // src/lib/getErrorMessage.ts
137
+ function getConfigErrorMessage(errors, config) {
138
+ return new Error(`Invalid configuration
139
+ ${Object.keys(errors).map((key) => {
140
+ return `- ${key} ${errors[key]}, got ${JSON.stringify(config[key])}`;
141
+ }).join("\n")}
142
+ `);
143
+ }
144
+ function getErrorMessage(message, data) {
145
+ return new Error(`Invalid data
146
+ - ${message}, got ${JSON.stringify(data)}`);
147
+ }
148
+
149
+ // src/lib/metadata.ts
150
+ function addMetadata(map, section, data) {
151
+ if (!section)
152
+ return;
153
+ map[section] = data;
154
+ }
155
+ function getMetadata(map, section) {
156
+ if (map[section]) {
157
+ return map[section];
158
+ }
159
+ return void 0;
160
+ }
161
+ function deleteMetadata(map, section) {
162
+ if (map[section]) {
163
+ return delete map[section];
164
+ }
165
+ return void 0;
166
+ }
167
+
168
+ // src/event.ts
169
+ var Event = class {
170
+ constructor(values, client) {
171
+ __publicField(this, "apiKey");
172
+ __publicField(this, "appVersion");
173
+ __publicField(this, "appType");
174
+ __publicField(this, "timestamp");
175
+ __publicField(this, "category");
176
+ __publicField(this, "type");
177
+ __publicField(this, "sdk");
178
+ __publicField(this, "device");
179
+ __publicField(this, "detail");
180
+ __publicField(this, "user");
181
+ __publicField(this, "actions");
182
+ __publicField(this, "metadata");
183
+ __publicField(this, "releaseStage");
184
+ __publicField(this, "__client");
185
+ const {
186
+ apiKey,
187
+ appVersion,
188
+ appType,
189
+ releaseStage,
190
+ timestamp,
191
+ category,
192
+ type,
193
+ sdk,
194
+ detail,
195
+ device,
196
+ user,
197
+ actions,
198
+ metadata
199
+ } = values;
200
+ this.apiKey = apiKey;
201
+ this.appVersion = appVersion;
202
+ this.appType = appType;
203
+ this.releaseStage = releaseStage;
204
+ this.timestamp = timestamp;
205
+ this.category = category;
206
+ this.type = type;
207
+ this.sdk = sdk;
208
+ this.detail = detail;
209
+ this.device = device;
210
+ this.user = user;
211
+ this.actions = actions;
212
+ this.metadata = metadata != null ? metadata : {};
213
+ this.__client = client;
214
+ }
215
+ get __isOhbugEvent() {
216
+ return true;
217
+ }
218
+ /**
219
+ * Add an action.
220
+ * Once the threshold is reached, the oldest actions will be deleted.
221
+ * 新增一个动作。
222
+ * 一旦达到阈值,最老的 Action 将被删除。
223
+ *
224
+ * @param message
225
+ * @param data
226
+ * @param type
227
+ * @param timestamp
228
+ */
229
+ addAction(message, data, type, timestamp) {
230
+ var _a, _b;
231
+ const actions = this.actions;
232
+ const targetMessage = (0, import_utils2.isString)(message) ? message : "";
233
+ const targetData = data || {};
234
+ const targetType = (0, import_utils2.isString)(type) ? type : "";
235
+ const action = new Action(targetMessage, targetData, targetType, timestamp);
236
+ const maxActions = (_b = (_a = this.__client) == null ? void 0 : _a.__config.maxActions) != null ? _b : 30;
237
+ if (maxActions > 0) {
238
+ if (actions.length >= maxActions) {
239
+ actions.shift();
240
+ }
241
+ actions.push(action);
242
+ }
243
+ }
244
+ /**
245
+ * Get current user information
246
+ * 获取当前的用户信息
247
+ */
248
+ getUser() {
249
+ return this.user;
250
+ }
251
+ /**
252
+ * Set current user information
253
+ * 设置当前的用户信息
254
+ */
255
+ setUser(user) {
256
+ var _a;
257
+ if ((0, import_utils2.isObject)(user) && Object.keys(user).length <= 6) {
258
+ this.user = __spreadValues(__spreadValues({}, this.user), user);
259
+ return this.getUser();
260
+ }
261
+ (_a = this.__client) == null ? void 0 : _a.__logger.error(getErrorMessage(
262
+ "setUser should be an object and have up to 6 attributes",
263
+ user
264
+ ));
265
+ return void 0;
266
+ }
267
+ /**
268
+ * Add metadata
269
+ * 新增 metadata
270
+ *
271
+ * @param section
272
+ * @param data
273
+ */
274
+ addMetadata(section, data) {
275
+ return addMetadata(this.metadata, section, data);
276
+ }
277
+ /**
278
+ * Get metadata
279
+ * 获取 metadata
280
+ *
281
+ * @param section
282
+ */
283
+ getMetadata(section) {
284
+ return getMetadata(this.metadata, section);
285
+ }
286
+ /**
287
+ * Delete metadata
288
+ * 删除 metadata
289
+ *
290
+ * @param section
291
+ */
292
+ deleteMetadata(section) {
293
+ return deleteMetadata(this.metadata, section);
294
+ }
295
+ toJSON() {
296
+ const {
297
+ apiKey,
298
+ appVersion,
299
+ appType,
300
+ timestamp,
301
+ category,
302
+ type,
303
+ sdk,
304
+ device,
305
+ detail,
306
+ user,
307
+ actions,
308
+ metadata,
309
+ releaseStage
310
+ } = this;
311
+ return {
312
+ apiKey,
313
+ appVersion,
314
+ appType,
315
+ timestamp,
316
+ category,
317
+ type,
318
+ sdk,
319
+ device,
320
+ detail,
321
+ user,
322
+ actions,
323
+ metadata,
324
+ releaseStage
325
+ };
326
+ }
327
+ };
328
+ function createEvent(values, client) {
329
+ const { apiKey, appVersion, appType, releaseStage } = client.__config;
330
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
331
+ const device = client.__device(client);
332
+ let category;
333
+ let type;
334
+ let detail;
335
+ if ((0, import_utils2.isObject)(values) && Object.prototype.hasOwnProperty.call(values, "type") && Object.prototype.hasOwnProperty.call(values, "detail")) {
336
+ category = values.category || "error";
337
+ type = values.type;
338
+ detail = values.detail;
339
+ } else {
340
+ category = "error";
341
+ type = "unknownError";
342
+ detail = values;
343
+ }
344
+ return new Event(
345
+ {
346
+ apiKey,
347
+ appVersion,
348
+ appType,
349
+ timestamp,
350
+ category,
351
+ type,
352
+ sdk: client.__sdk,
353
+ device,
354
+ user: client.__user,
355
+ detail,
356
+ actions: client.__actions,
357
+ metadata: client.__metadata,
358
+ releaseStage
359
+ },
360
+ client
361
+ );
362
+ }
363
+ function handleEventCreated(event, client) {
364
+ const funcs = [
365
+ client.__config.onEvent,
366
+ ...client.__extensions.map(({ onEvent }) => onEvent)
367
+ ].filter((v) => (0, import_utils2.isFunction)(v));
368
+ if (funcs.length === 0) {
369
+ return event;
370
+ }
371
+ return funcs.reduce((previous, current) => {
372
+ if (previous && (0, import_utils2.isFunction)(current)) {
373
+ return current(previous, client);
374
+ }
375
+ return null;
376
+ }, event);
377
+ }
378
+ function isEvent(eventLike) {
379
+ return Boolean(eventLike == null ? void 0 : eventLike.__isOhbugEvent);
380
+ }
381
+
382
+ // src/notify.ts
383
+ var import_utils3 = require("@ohbug/utils");
384
+ function handleNotified(event, client) {
385
+ const funcs = [
386
+ client.__config.onNotify,
387
+ ...client.__extensions.filter(({ onNotify }) => (0, import_utils3.isFunction)(onNotify)).map(({ onNotify }) => onNotify)
388
+ ];
389
+ funcs.forEach((func) => func == null ? void 0 : func(event, client));
390
+ }
391
+ async function notify(event, client) {
392
+ try {
393
+ let result = null;
394
+ if (event) {
395
+ result = await client.__notifier(event);
396
+ handleNotified(event, client);
397
+ }
398
+ return result;
399
+ } catch (e) {
400
+ client.__logger.error(e);
401
+ }
402
+ }
403
+
404
+ // src/lib/verifyConfig.ts
405
+ function verifyConfig(config, schema2) {
406
+ const keys = Object.keys(schema2);
407
+ return keys.reduce(
408
+ (accumulator, key) => {
409
+ const configValue = config[key];
410
+ const { defaultValue, message, validate } = schema2[key];
411
+ if (configValue !== void 0) {
412
+ const valid = validate(configValue);
413
+ if (valid) {
414
+ accumulator.config[key] = configValue;
415
+ } else {
416
+ accumulator.config[key] = defaultValue;
417
+ accumulator.errors[key] = message;
418
+ }
419
+ } else {
420
+ accumulator.config[key] = defaultValue;
421
+ }
422
+ return accumulator;
423
+ },
424
+ {
425
+ config: {},
426
+ errors: {}
427
+ }
428
+ );
429
+ }
430
+
431
+ // src/client.ts
432
+ var Client = class Client2 {
433
+ constructor({
434
+ sdk,
435
+ config: baseConfig,
436
+ schema: schema2 = schema,
437
+ device,
438
+ notifier,
439
+ destroy
440
+ }) {
441
+ __publicField(this, "__sdk");
442
+ __publicField(this, "__config");
443
+ __publicField(this, "__logger");
444
+ __publicField(this, "__device");
445
+ __publicField(this, "__notifier");
446
+ __publicField(this, "__destroy");
447
+ __publicField(this, "__extensions");
448
+ __publicField(this, "__actions");
449
+ __publicField(this, "__user");
450
+ __publicField(this, "__metadata");
451
+ const { config, errors } = verifyConfig(baseConfig, schema2);
452
+ this.__sdk = sdk;
453
+ this.__config = config;
454
+ this.__logger = config.logger;
455
+ this.__device = device;
456
+ this.__notifier = notifier;
457
+ this.__destroy = destroy;
458
+ this.__extensions = [];
459
+ this.__actions = [];
460
+ this.__user = config.user;
461
+ this.__metadata = {};
462
+ if ((0, import_utils4.isObject)(config.metadata)) {
463
+ Object.keys(config.metadata).forEach((key) => {
464
+ this.addMetadata(key, config.metadata[key]);
465
+ });
466
+ }
467
+ if (Object.keys(errors).length) {
468
+ this.__logger.warn(getConfigErrorMessage(errors, baseConfig));
469
+ }
470
+ }
471
+ /**
472
+ * Load extension
473
+ * 加载扩展
474
+ *
475
+ * @param extension
476
+ */
477
+ use(extension) {
478
+ var _a;
479
+ this.__extensions.push(extension);
480
+ (_a = extension.onSetup) == null ? void 0 : _a.call(extension, this);
481
+ return this;
482
+ }
483
+ destroy() {
484
+ var _a;
485
+ if (this.__destroy) {
486
+ this.__logger.info(
487
+ "%c @ohbug/core %c has been destroyed %c",
488
+ "background:#333; padding: 2px 1px; color: #FFF",
489
+ "background:#FF6F61; padding: 2px 1px; color: #FFF",
490
+ "background:transparent"
491
+ );
492
+ return (_a = this.__destroy) == null ? void 0 : _a.call(this);
493
+ }
494
+ }
495
+ /**
496
+ * Create an event, you will get a data body containing device actions and other information
497
+ * 创建事件,将会得到一个含有 device actions 等信息的数据体
498
+ *
499
+ * @param value
500
+ */
501
+ createEvent(value) {
502
+ const event = createEvent(value, this);
503
+ return handleEventCreated(event, this);
504
+ }
505
+ /**
506
+ * Used to trigger the reporting interface
507
+ * 用于触发上报接口
508
+ *
509
+ * @param eventLike
510
+ * @param beforeNotify
511
+ */
512
+ notify(eventLike, beforeNotify) {
513
+ let event;
514
+ if (Boolean(eventLike) && !isEvent(eventLike)) {
515
+ event = this.createEvent(eventLike);
516
+ } else {
517
+ event = eventLike;
518
+ }
519
+ if (beforeNotify)
520
+ event = beforeNotify(event);
521
+ return notify(event, this);
522
+ }
523
+ /**
524
+ * Add an action.
525
+ * Once the threshold is reached, the oldest actions will be deleted.
526
+ * 新增一个动作。
527
+ * 一旦达到阈值,最老的 Action 将被删除。
528
+ *
529
+ * @param message
530
+ * @param data
531
+ * @param type
532
+ * @param timestamp
533
+ */
534
+ addAction(message, data, type, timestamp) {
535
+ var _a;
536
+ const actions = this.__actions;
537
+ const targetMessage = (0, import_utils4.isString)(message) ? message : "";
538
+ const targetData = data || {};
539
+ const targetType = (0, import_utils4.isString)(type) ? type : "";
540
+ const action = new Action(targetMessage, targetData, targetType, timestamp);
541
+ const maxActions = (_a = this.__config.maxActions) != null ? _a : 30;
542
+ if (maxActions > 0) {
543
+ if (actions.length >= maxActions) {
544
+ actions.shift();
545
+ }
546
+ actions.push(action);
547
+ }
548
+ }
549
+ /**
550
+ * Get current user information
551
+ * 获取当前的用户信息
552
+ */
553
+ getUser() {
554
+ return this.__user;
555
+ }
556
+ /**
557
+ * Set current user information
558
+ * 设置当前的用户信息
559
+ */
560
+ setUser(user) {
561
+ if ((0, import_utils4.isObject)(user) && Object.keys(user).length <= 6) {
562
+ this.__user = __spreadValues(__spreadValues({}, this.__user), user);
563
+ return this.getUser();
564
+ }
565
+ this.__logger.warn(getErrorMessage(
566
+ "setUser should be an object and have up to 6 attributes",
567
+ user
568
+ ));
569
+ return void 0;
570
+ }
571
+ /**
572
+ * Add metadata
573
+ * 新增 metadata
574
+ *
575
+ * @param section
576
+ * @param data
577
+ */
578
+ addMetadata(section, data) {
579
+ return addMetadata(this.__metadata, section, data);
580
+ }
581
+ /**
582
+ * Get metadata
583
+ * 获取 metadata
584
+ *
585
+ * @param section
586
+ */
587
+ getMetadata(section) {
588
+ return getMetadata(this.__metadata, section);
589
+ }
590
+ /**
591
+ * Delete metadata
592
+ * 删除 metadata
593
+ *
594
+ * @param section
595
+ */
596
+ deleteMetadata(section) {
597
+ return deleteMetadata(this.__metadata, section);
598
+ }
599
+ };
600
+
601
+ // src/extension.ts
602
+ function defineExtension(extension) {
603
+ if (!extension)
604
+ return {};
605
+ return extension;
606
+ }
607
+
608
+ // src/types.ts
609
+ var EventTypes = /* @__PURE__ */ ((EventTypes2) => {
610
+ EventTypes2["UNCAUGHT_ERROR"] = "uncaughtError";
611
+ EventTypes2["RESOURCE_ERROR"] = "resourceError";
612
+ EventTypes2["UNHANDLEDREJECTION_ERROR"] = "unhandledrejectionError";
613
+ EventTypes2["AJAX_ERROR"] = "ajaxError";
614
+ EventTypes2["FETCH_ERROR"] = "fetchError";
615
+ EventTypes2["WEBSOCKET_ERROR"] = "websocketError";
616
+ EventTypes2["UNKNOWN_ERROR"] = "unknownError";
617
+ EventTypes2["MESSAGE"] = "message";
618
+ EventTypes2["FEEDBACK"] = "feedback";
619
+ EventTypes2["VIEW"] = "view";
620
+ EventTypes2["REACT"] = "react";
621
+ EventTypes2["VUE"] = "vue";
622
+ EventTypes2["ANGULAR"] = "angular";
623
+ EventTypes2["MINIAPP_ERROR"] = "miniappError";
624
+ EventTypes2["MINIAPP_UNHANDLEDREJECTION_ERROR"] = "miniappUnhandledrejectionError";
625
+ EventTypes2["MINIAPP_PAGENOTFOUND_ERROR"] = "miniappPagenotfoundError";
626
+ EventTypes2["MINIAPP_MEMORYWARNING_ERROR"] = "miniappMemorywarningError";
627
+ return EventTypes2;
628
+ })(EventTypes || {});
629
+ // Annotate the CommonJS export names for ESM import in node:
630
+ 0 && (module.exports = {
631
+ Client,
632
+ EventTypes,
633
+ defineExtension,
634
+ isEvent
635
+ });
package/dist/index.mjs CHANGED
@@ -1,5 +1,608 @@
1
- import{isObject as w,isString as j}from"@ohbug/utils";import{isFunction as M,isNumber as P,isObject as R,isString as l,logger as K}from"@ohbug/utils";var D={apiKey:{defaultValue:void 0,message:"is required",validate:e=>Boolean(e)&&l(e)},appVersion:{defaultValue:void 0,message:"should be a string",validate:e=>e===void 0||l(e)},appType:{defaultValue:void 0,message:"should be a string",validate:e=>e===void 0||l(e)},releaseStage:{defaultValue:"production",message:"should be a string",validate:e=>e===void 0||l(e)},endpoint:{defaultValue:"http://localhost:6660",message:"should be a string",validate:e=>e===void 0||l(e)},maxActions:{defaultValue:30,message:"should be a number between 0 and 100",validate:e=>e===void 0||P(e)&&e>=1&&e<=100},onEvent:{defaultValue:e=>e,message:"should be a function",validate:e=>e===void 0||M(e)},onNotify:{defaultValue:()=>{},message:"should be a function",validate:e=>e===void 0||M(e)},logger:{defaultValue:K,message:"should be null or an object with methods { log, info, warn, error }",validate:e=>e===void 0||e&&["log","info","warn","error"].reduce((t,n)=>t&&typeof e[n]=="function",!0)},user:{defaultValue:void 0,message:"should be an object and have up to 6 attributes",validate:e=>e===void 0||R(e)&&Object.keys(e).length<=6},metadata:{defaultValue:void 0,message:"should be an object",validate:e=>e===void 0||R(e)}};import{isFunction as S,isObject as x,isString as v}from"@ohbug/utils";var f=class{type;timestamp;message;data;constructor(t,n,r,a){this.type=r,this.timestamp=a||new Date().toISOString(),this.message=t,this.data=n}};function A(e,t){return new Error(`Invalid configuration
2
- ${Object.keys(e).map(n=>`- ${n} ${e[n]}, got ${JSON.stringify(t[n])}`).join(`
3
- `)}
4
- `)}function b(e,t){return new Error(`Invalid data
5
- - ${e}, got ${JSON.stringify(t)}`)}function c(e,t,n){!t||(e[t]=n)}function O(e,t){if(e[t])return e[t]}function p(e,t){if(e[t])return delete e[t]}var E=class{apiKey;appVersion;appType;timestamp;category;type;sdk;device;detail;user;actions;metadata;releaseStage;__client;constructor(t,n){let{apiKey:r,appVersion:a,appType:i,releaseStage:o,timestamp:u,category:g,type:d,sdk:h,detail:m,device:_,user:y,actions:I,metadata:k}=t;this.apiKey=r,this.appVersion=a,this.appType=i,this.releaseStage=o,this.timestamp=u,this.category=g,this.type=d,this.sdk=h,this.detail=m,this.device=_,this.user=y,this.actions=I,this.metadata=k??{},this.__client=n}get __isOhbugEvent(){return!0}addAction(t,n,r,a){var h;let i=this.actions,o=v(t)?t:"",u=n||{},g=v(r)?r:"",d=new f(o,u,g,a);i.length>=(((h=this.__client)==null?void 0:h.__config.maxActions)??30)&&i.shift(),i.push(d)}getUser(){return this.user}setUser(t){var n;if(x(t)&&Object.keys(t).length<=6)return this.user={...this.user,...t},this.getUser();(n=this.__client)==null||n.__logger.error(b("setUser should be an object and have up to 6 attributes",t))}addMetadata(t,n){return c(this.metadata,t,n)}getMetadata(t){return O(this.metadata,t)}deleteMetadata(t){return p(this.metadata,t)}toJSON(){let{apiKey:t,appVersion:n,appType:r,timestamp:a,category:i,type:o,sdk:u,device:g,detail:d,user:h,actions:m,metadata:_,releaseStage:y}=this;return{apiKey:t,appVersion:n,appType:r,timestamp:a,category:i,type:o,sdk:u,device:g,detail:d,user:h,actions:m,metadata:_,releaseStage:y}}};function U(e,t){let{apiKey:n,appVersion:r,appType:a,releaseStage:i}=t.__config,o=new Date().toISOString(),u=t.__device(t),g,d,h;return x(e)&&Object.prototype.hasOwnProperty.call(e,"type")&&Object.prototype.hasOwnProperty.call(e,"detail")?(g=e.category||"error",d=e.type,h=e.detail):(g="error",d="unknownError",h=e),new E({apiKey:n,appVersion:r,appType:a,timestamp:o,category:g,type:d,sdk:t.__sdk,device:u,user:t.__user,detail:h,actions:t.__actions,metadata:t.__metadata,releaseStage:i},t)}function N(e,t){let n=[t.__config.onEvent,...t.__extensions.map(({onEvent:r})=>r)].filter(r=>S(r));return n.length===0?e:n.reduce((r,a)=>r&&S(a)?a(r,t):null,e)}function C(e){return Boolean(e==null?void 0:e.__isOhbugEvent)}import{isFunction as G}from"@ohbug/utils";function F(e,t){[t.__config.onNotify,...t.__extensions.filter(({onNotify:r})=>G(r)).map(({onNotify:r})=>r)].forEach(r=>r==null?void 0:r(e,t))}async function V(e,t){try{let n=null;return e&&(n=await t.__notifier(e),F(e,t)),n}catch(n){t.__logger.error(n)}}function W(e,t){return Object.keys(t).reduce((r,a)=>{let i=e[a],{defaultValue:o,message:u,validate:g}=t[a];return i!==void 0?g(i)?r.config[a]=i:(r.config[a]=o,r.errors[a]=u):r.config[a]=o,r},{config:{},errors:{}})}var dt=class{__sdk;__config;__logger;__device;__notifier;__extensions;__actions;__user;__metadata;constructor({sdk:t,config:n,schema:r=D,device:a,notifier:i}){let{config:o,errors:u}=W(n,r);this.__sdk=t,this.__config=o,this.__logger=o.logger,this.__device=a,this.__notifier=i,this.__extensions=[],this.__actions=[],this.__user=o.user,this.__metadata={},w(o.metadata)&&Object.keys(o.metadata).forEach(g=>{this.addMetadata(g,o.metadata[g])}),Object.keys(u).length&&this.__logger.warn(A(u,n))}use(t){var n;return this.__extensions.push(t),(n=t.onSetup)==null||n.call(t,this),this}createEvent(t){let n=U(t,this);return N(n,this)}notify(t,n){let r;return Boolean(t)&&!C(t)?r=this.createEvent(t):r=t,n&&(r=n(r)),V(r,this)}addAction(t,n,r,a){let i=this.__actions,o=j(t)?t:"",u=n||{},g=j(r)?r:"",d=new f(o,u,g,a);i.length>=this.__config.maxActions&&i.shift(),i.push(d)}getUser(){return this.__user}setUser(t){if(w(t)&&Object.keys(t).length<=6)return this.__user={...this.__user,...t},this.getUser();this.__logger.warn(b("setUser should be an object and have up to 6 attributes",t))}addMetadata(t,n){return c(this.__metadata,t,n)}getMetadata(t){return O(this.__metadata,t)}deleteMetadata(t){return p(this.__metadata,t)}};function lt(e){return e||{}}var J=(s=>(s.UNCAUGHT_ERROR="uncaughtError",s.RESOURCE_ERROR="resourceError",s.UNHANDLEDREJECTION_ERROR="unhandledrejectionError",s.AJAX_ERROR="ajaxError",s.FETCH_ERROR="fetchError",s.WEBSOCKET_ERROR="websocketError",s.UNKNOWN_ERROR="unknownError",s.MESSAGE="message",s.FEEDBACK="feedback",s.VIEW="view",s.REACT="react",s.VUE="vue",s.ANGULAR="angular",s.MINIAPP_ERROR="miniappError",s.MINIAPP_UNHANDLEDREJECTION_ERROR="miniappUnhandledrejectionError",s.MINIAPP_PAGENOTFOUND_ERROR="miniappPagenotfoundError",s.MINIAPP_MEMORYWARNING_ERROR="miniappMemorywarningError",s))(J||{});export{dt as Client,J as EventTypes,lt as defineExtension,C as isEvent};
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ }
15
+ return a;
16
+ };
17
+ var __publicField = (obj, key, value) => {
18
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
19
+ return value;
20
+ };
21
+
22
+ // src/client.ts
23
+ import { isObject as isObject3, isString as isString3 } from "@ohbug/utils";
24
+
25
+ // src/config.ts
26
+ import { isFunction, isNumber, isObject, isString, logger } from "@ohbug/utils";
27
+ var schema = {
28
+ // base
29
+ apiKey: {
30
+ defaultValue: void 0,
31
+ message: "is required",
32
+ validate: (value) => Boolean(value) && isString(value)
33
+ },
34
+ appVersion: {
35
+ defaultValue: void 0,
36
+ message: "should be a string",
37
+ validate: (value) => value === void 0 || isString(value)
38
+ },
39
+ appType: {
40
+ defaultValue: void 0,
41
+ message: "should be a string",
42
+ validate: (value) => value === void 0 || isString(value)
43
+ },
44
+ releaseStage: {
45
+ defaultValue: "production",
46
+ message: "should be a string",
47
+ validate: (value) => value === void 0 || isString(value)
48
+ },
49
+ endpoint: {
50
+ defaultValue: "http://localhost:6660",
51
+ message: "should be a string",
52
+ validate: (value) => value === void 0 || isString(value)
53
+ },
54
+ maxActions: {
55
+ defaultValue: 30,
56
+ message: "should be a number between 0 and 100",
57
+ validate: (value) => value === void 0 || isNumber(value) && value >= 0 && value <= 100
58
+ },
59
+ // hooks
60
+ onEvent: {
61
+ defaultValue: (event) => event,
62
+ message: "should be a function",
63
+ validate: (value) => value === void 0 || isFunction(value)
64
+ },
65
+ onNotify: {
66
+ defaultValue: () => {
67
+ },
68
+ message: "should be a function",
69
+ validate: (value) => value === void 0 || isFunction(value)
70
+ },
71
+ // utils
72
+ logger: {
73
+ defaultValue: logger,
74
+ message: "should be null or an object with methods { log, info, warn, error }",
75
+ validate: (value) => value === void 0 || value && ["log", "info", "warn", "error"].reduce(
76
+ (accumulator, method) => accumulator && typeof value[method] === "function",
77
+ true
78
+ )
79
+ },
80
+ // data
81
+ user: {
82
+ defaultValue: void 0,
83
+ message: "should be an object and have up to 6 attributes",
84
+ validate: (value) => value === void 0 || isObject(value) && Object.keys(value).length <= 6
85
+ },
86
+ metadata: {
87
+ defaultValue: void 0,
88
+ message: "should be an object",
89
+ validate: (value) => value === void 0 || isObject(value)
90
+ }
91
+ };
92
+
93
+ // src/event.ts
94
+ import { isFunction as isFunction2, isObject as isObject2, isString as isString2 } from "@ohbug/utils";
95
+
96
+ // src/action.ts
97
+ var Action = class {
98
+ constructor(message, data, type, timestamp) {
99
+ __publicField(this, "type");
100
+ __publicField(this, "timestamp");
101
+ __publicField(this, "message");
102
+ __publicField(this, "data");
103
+ this.type = type;
104
+ this.timestamp = timestamp || (/* @__PURE__ */ new Date()).toISOString();
105
+ this.message = message;
106
+ this.data = data;
107
+ }
108
+ };
109
+
110
+ // src/lib/getErrorMessage.ts
111
+ function getConfigErrorMessage(errors, config) {
112
+ return new Error(`Invalid configuration
113
+ ${Object.keys(errors).map((key) => {
114
+ return `- ${key} ${errors[key]}, got ${JSON.stringify(config[key])}`;
115
+ }).join("\n")}
116
+ `);
117
+ }
118
+ function getErrorMessage(message, data) {
119
+ return new Error(`Invalid data
120
+ - ${message}, got ${JSON.stringify(data)}`);
121
+ }
122
+
123
+ // src/lib/metadata.ts
124
+ function addMetadata(map, section, data) {
125
+ if (!section)
126
+ return;
127
+ map[section] = data;
128
+ }
129
+ function getMetadata(map, section) {
130
+ if (map[section]) {
131
+ return map[section];
132
+ }
133
+ return void 0;
134
+ }
135
+ function deleteMetadata(map, section) {
136
+ if (map[section]) {
137
+ return delete map[section];
138
+ }
139
+ return void 0;
140
+ }
141
+
142
+ // src/event.ts
143
+ var Event = class {
144
+ constructor(values, client) {
145
+ __publicField(this, "apiKey");
146
+ __publicField(this, "appVersion");
147
+ __publicField(this, "appType");
148
+ __publicField(this, "timestamp");
149
+ __publicField(this, "category");
150
+ __publicField(this, "type");
151
+ __publicField(this, "sdk");
152
+ __publicField(this, "device");
153
+ __publicField(this, "detail");
154
+ __publicField(this, "user");
155
+ __publicField(this, "actions");
156
+ __publicField(this, "metadata");
157
+ __publicField(this, "releaseStage");
158
+ __publicField(this, "__client");
159
+ const {
160
+ apiKey,
161
+ appVersion,
162
+ appType,
163
+ releaseStage,
164
+ timestamp,
165
+ category,
166
+ type,
167
+ sdk,
168
+ detail,
169
+ device,
170
+ user,
171
+ actions,
172
+ metadata
173
+ } = values;
174
+ this.apiKey = apiKey;
175
+ this.appVersion = appVersion;
176
+ this.appType = appType;
177
+ this.releaseStage = releaseStage;
178
+ this.timestamp = timestamp;
179
+ this.category = category;
180
+ this.type = type;
181
+ this.sdk = sdk;
182
+ this.detail = detail;
183
+ this.device = device;
184
+ this.user = user;
185
+ this.actions = actions;
186
+ this.metadata = metadata != null ? metadata : {};
187
+ this.__client = client;
188
+ }
189
+ get __isOhbugEvent() {
190
+ return true;
191
+ }
192
+ /**
193
+ * Add an action.
194
+ * Once the threshold is reached, the oldest actions will be deleted.
195
+ * 新增一个动作。
196
+ * 一旦达到阈值,最老的 Action 将被删除。
197
+ *
198
+ * @param message
199
+ * @param data
200
+ * @param type
201
+ * @param timestamp
202
+ */
203
+ addAction(message, data, type, timestamp) {
204
+ var _a, _b;
205
+ const actions = this.actions;
206
+ const targetMessage = isString2(message) ? message : "";
207
+ const targetData = data || {};
208
+ const targetType = isString2(type) ? type : "";
209
+ const action = new Action(targetMessage, targetData, targetType, timestamp);
210
+ const maxActions = (_b = (_a = this.__client) == null ? void 0 : _a.__config.maxActions) != null ? _b : 30;
211
+ if (maxActions > 0) {
212
+ if (actions.length >= maxActions) {
213
+ actions.shift();
214
+ }
215
+ actions.push(action);
216
+ }
217
+ }
218
+ /**
219
+ * Get current user information
220
+ * 获取当前的用户信息
221
+ */
222
+ getUser() {
223
+ return this.user;
224
+ }
225
+ /**
226
+ * Set current user information
227
+ * 设置当前的用户信息
228
+ */
229
+ setUser(user) {
230
+ var _a;
231
+ if (isObject2(user) && Object.keys(user).length <= 6) {
232
+ this.user = __spreadValues(__spreadValues({}, this.user), user);
233
+ return this.getUser();
234
+ }
235
+ (_a = this.__client) == null ? void 0 : _a.__logger.error(getErrorMessage(
236
+ "setUser should be an object and have up to 6 attributes",
237
+ user
238
+ ));
239
+ return void 0;
240
+ }
241
+ /**
242
+ * Add metadata
243
+ * 新增 metadata
244
+ *
245
+ * @param section
246
+ * @param data
247
+ */
248
+ addMetadata(section, data) {
249
+ return addMetadata(this.metadata, section, data);
250
+ }
251
+ /**
252
+ * Get metadata
253
+ * 获取 metadata
254
+ *
255
+ * @param section
256
+ */
257
+ getMetadata(section) {
258
+ return getMetadata(this.metadata, section);
259
+ }
260
+ /**
261
+ * Delete metadata
262
+ * 删除 metadata
263
+ *
264
+ * @param section
265
+ */
266
+ deleteMetadata(section) {
267
+ return deleteMetadata(this.metadata, section);
268
+ }
269
+ toJSON() {
270
+ const {
271
+ apiKey,
272
+ appVersion,
273
+ appType,
274
+ timestamp,
275
+ category,
276
+ type,
277
+ sdk,
278
+ device,
279
+ detail,
280
+ user,
281
+ actions,
282
+ metadata,
283
+ releaseStage
284
+ } = this;
285
+ return {
286
+ apiKey,
287
+ appVersion,
288
+ appType,
289
+ timestamp,
290
+ category,
291
+ type,
292
+ sdk,
293
+ device,
294
+ detail,
295
+ user,
296
+ actions,
297
+ metadata,
298
+ releaseStage
299
+ };
300
+ }
301
+ };
302
+ function createEvent(values, client) {
303
+ const { apiKey, appVersion, appType, releaseStage } = client.__config;
304
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
305
+ const device = client.__device(client);
306
+ let category;
307
+ let type;
308
+ let detail;
309
+ if (isObject2(values) && Object.prototype.hasOwnProperty.call(values, "type") && Object.prototype.hasOwnProperty.call(values, "detail")) {
310
+ category = values.category || "error";
311
+ type = values.type;
312
+ detail = values.detail;
313
+ } else {
314
+ category = "error";
315
+ type = "unknownError";
316
+ detail = values;
317
+ }
318
+ return new Event(
319
+ {
320
+ apiKey,
321
+ appVersion,
322
+ appType,
323
+ timestamp,
324
+ category,
325
+ type,
326
+ sdk: client.__sdk,
327
+ device,
328
+ user: client.__user,
329
+ detail,
330
+ actions: client.__actions,
331
+ metadata: client.__metadata,
332
+ releaseStage
333
+ },
334
+ client
335
+ );
336
+ }
337
+ function handleEventCreated(event, client) {
338
+ const funcs = [
339
+ client.__config.onEvent,
340
+ ...client.__extensions.map(({ onEvent }) => onEvent)
341
+ ].filter((v) => isFunction2(v));
342
+ if (funcs.length === 0) {
343
+ return event;
344
+ }
345
+ return funcs.reduce((previous, current) => {
346
+ if (previous && isFunction2(current)) {
347
+ return current(previous, client);
348
+ }
349
+ return null;
350
+ }, event);
351
+ }
352
+ function isEvent(eventLike) {
353
+ return Boolean(eventLike == null ? void 0 : eventLike.__isOhbugEvent);
354
+ }
355
+
356
+ // src/notify.ts
357
+ import { isFunction as isFunction3 } from "@ohbug/utils";
358
+ function handleNotified(event, client) {
359
+ const funcs = [
360
+ client.__config.onNotify,
361
+ ...client.__extensions.filter(({ onNotify }) => isFunction3(onNotify)).map(({ onNotify }) => onNotify)
362
+ ];
363
+ funcs.forEach((func) => func == null ? void 0 : func(event, client));
364
+ }
365
+ async function notify(event, client) {
366
+ try {
367
+ let result = null;
368
+ if (event) {
369
+ result = await client.__notifier(event);
370
+ handleNotified(event, client);
371
+ }
372
+ return result;
373
+ } catch (e) {
374
+ client.__logger.error(e);
375
+ }
376
+ }
377
+
378
+ // src/lib/verifyConfig.ts
379
+ function verifyConfig(config, schema2) {
380
+ const keys = Object.keys(schema2);
381
+ return keys.reduce(
382
+ (accumulator, key) => {
383
+ const configValue = config[key];
384
+ const { defaultValue, message, validate } = schema2[key];
385
+ if (configValue !== void 0) {
386
+ const valid = validate(configValue);
387
+ if (valid) {
388
+ accumulator.config[key] = configValue;
389
+ } else {
390
+ accumulator.config[key] = defaultValue;
391
+ accumulator.errors[key] = message;
392
+ }
393
+ } else {
394
+ accumulator.config[key] = defaultValue;
395
+ }
396
+ return accumulator;
397
+ },
398
+ {
399
+ config: {},
400
+ errors: {}
401
+ }
402
+ );
403
+ }
404
+
405
+ // src/client.ts
406
+ var Client = class Client2 {
407
+ constructor({
408
+ sdk,
409
+ config: baseConfig,
410
+ schema: schema2 = schema,
411
+ device,
412
+ notifier,
413
+ destroy
414
+ }) {
415
+ __publicField(this, "__sdk");
416
+ __publicField(this, "__config");
417
+ __publicField(this, "__logger");
418
+ __publicField(this, "__device");
419
+ __publicField(this, "__notifier");
420
+ __publicField(this, "__destroy");
421
+ __publicField(this, "__extensions");
422
+ __publicField(this, "__actions");
423
+ __publicField(this, "__user");
424
+ __publicField(this, "__metadata");
425
+ const { config, errors } = verifyConfig(baseConfig, schema2);
426
+ this.__sdk = sdk;
427
+ this.__config = config;
428
+ this.__logger = config.logger;
429
+ this.__device = device;
430
+ this.__notifier = notifier;
431
+ this.__destroy = destroy;
432
+ this.__extensions = [];
433
+ this.__actions = [];
434
+ this.__user = config.user;
435
+ this.__metadata = {};
436
+ if (isObject3(config.metadata)) {
437
+ Object.keys(config.metadata).forEach((key) => {
438
+ this.addMetadata(key, config.metadata[key]);
439
+ });
440
+ }
441
+ if (Object.keys(errors).length) {
442
+ this.__logger.warn(getConfigErrorMessage(errors, baseConfig));
443
+ }
444
+ }
445
+ /**
446
+ * Load extension
447
+ * 加载扩展
448
+ *
449
+ * @param extension
450
+ */
451
+ use(extension) {
452
+ var _a;
453
+ this.__extensions.push(extension);
454
+ (_a = extension.onSetup) == null ? void 0 : _a.call(extension, this);
455
+ return this;
456
+ }
457
+ destroy() {
458
+ var _a;
459
+ if (this.__destroy) {
460
+ this.__logger.info(
461
+ "%c @ohbug/core %c has been destroyed %c",
462
+ "background:#333; padding: 2px 1px; color: #FFF",
463
+ "background:#FF6F61; padding: 2px 1px; color: #FFF",
464
+ "background:transparent"
465
+ );
466
+ return (_a = this.__destroy) == null ? void 0 : _a.call(this);
467
+ }
468
+ }
469
+ /**
470
+ * Create an event, you will get a data body containing device actions and other information
471
+ * 创建事件,将会得到一个含有 device actions 等信息的数据体
472
+ *
473
+ * @param value
474
+ */
475
+ createEvent(value) {
476
+ const event = createEvent(value, this);
477
+ return handleEventCreated(event, this);
478
+ }
479
+ /**
480
+ * Used to trigger the reporting interface
481
+ * 用于触发上报接口
482
+ *
483
+ * @param eventLike
484
+ * @param beforeNotify
485
+ */
486
+ notify(eventLike, beforeNotify) {
487
+ let event;
488
+ if (Boolean(eventLike) && !isEvent(eventLike)) {
489
+ event = this.createEvent(eventLike);
490
+ } else {
491
+ event = eventLike;
492
+ }
493
+ if (beforeNotify)
494
+ event = beforeNotify(event);
495
+ return notify(event, this);
496
+ }
497
+ /**
498
+ * Add an action.
499
+ * Once the threshold is reached, the oldest actions will be deleted.
500
+ * 新增一个动作。
501
+ * 一旦达到阈值,最老的 Action 将被删除。
502
+ *
503
+ * @param message
504
+ * @param data
505
+ * @param type
506
+ * @param timestamp
507
+ */
508
+ addAction(message, data, type, timestamp) {
509
+ var _a;
510
+ const actions = this.__actions;
511
+ const targetMessage = isString3(message) ? message : "";
512
+ const targetData = data || {};
513
+ const targetType = isString3(type) ? type : "";
514
+ const action = new Action(targetMessage, targetData, targetType, timestamp);
515
+ const maxActions = (_a = this.__config.maxActions) != null ? _a : 30;
516
+ if (maxActions > 0) {
517
+ if (actions.length >= maxActions) {
518
+ actions.shift();
519
+ }
520
+ actions.push(action);
521
+ }
522
+ }
523
+ /**
524
+ * Get current user information
525
+ * 获取当前的用户信息
526
+ */
527
+ getUser() {
528
+ return this.__user;
529
+ }
530
+ /**
531
+ * Set current user information
532
+ * 设置当前的用户信息
533
+ */
534
+ setUser(user) {
535
+ if (isObject3(user) && Object.keys(user).length <= 6) {
536
+ this.__user = __spreadValues(__spreadValues({}, this.__user), user);
537
+ return this.getUser();
538
+ }
539
+ this.__logger.warn(getErrorMessage(
540
+ "setUser should be an object and have up to 6 attributes",
541
+ user
542
+ ));
543
+ return void 0;
544
+ }
545
+ /**
546
+ * Add metadata
547
+ * 新增 metadata
548
+ *
549
+ * @param section
550
+ * @param data
551
+ */
552
+ addMetadata(section, data) {
553
+ return addMetadata(this.__metadata, section, data);
554
+ }
555
+ /**
556
+ * Get metadata
557
+ * 获取 metadata
558
+ *
559
+ * @param section
560
+ */
561
+ getMetadata(section) {
562
+ return getMetadata(this.__metadata, section);
563
+ }
564
+ /**
565
+ * Delete metadata
566
+ * 删除 metadata
567
+ *
568
+ * @param section
569
+ */
570
+ deleteMetadata(section) {
571
+ return deleteMetadata(this.__metadata, section);
572
+ }
573
+ };
574
+
575
+ // src/extension.ts
576
+ function defineExtension(extension) {
577
+ if (!extension)
578
+ return {};
579
+ return extension;
580
+ }
581
+
582
+ // src/types.ts
583
+ var EventTypes = /* @__PURE__ */ ((EventTypes2) => {
584
+ EventTypes2["UNCAUGHT_ERROR"] = "uncaughtError";
585
+ EventTypes2["RESOURCE_ERROR"] = "resourceError";
586
+ EventTypes2["UNHANDLEDREJECTION_ERROR"] = "unhandledrejectionError";
587
+ EventTypes2["AJAX_ERROR"] = "ajaxError";
588
+ EventTypes2["FETCH_ERROR"] = "fetchError";
589
+ EventTypes2["WEBSOCKET_ERROR"] = "websocketError";
590
+ EventTypes2["UNKNOWN_ERROR"] = "unknownError";
591
+ EventTypes2["MESSAGE"] = "message";
592
+ EventTypes2["FEEDBACK"] = "feedback";
593
+ EventTypes2["VIEW"] = "view";
594
+ EventTypes2["REACT"] = "react";
595
+ EventTypes2["VUE"] = "vue";
596
+ EventTypes2["ANGULAR"] = "angular";
597
+ EventTypes2["MINIAPP_ERROR"] = "miniappError";
598
+ EventTypes2["MINIAPP_UNHANDLEDREJECTION_ERROR"] = "miniappUnhandledrejectionError";
599
+ EventTypes2["MINIAPP_PAGENOTFOUND_ERROR"] = "miniappPagenotfoundError";
600
+ EventTypes2["MINIAPP_MEMORYWARNING_ERROR"] = "miniappMemorywarningError";
601
+ return EventTypes2;
602
+ })(EventTypes || {});
603
+ export {
604
+ Client,
605
+ EventTypes,
606
+ defineExtension,
607
+ isEvent
608
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohbug/core",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Responsible for managing Ohbug's workflow",
5
5
  "license": "Apache-2.0",
6
6
  "author": "chenyueban <jasonchan0527@gmail.com>",
@@ -30,12 +30,11 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@ohbug/types": "2.1.0",
34
- "@ohbug/utils": "2.0.5"
33
+ "@ohbug/types": "2.2.0",
34
+ "@ohbug/utils": "2.0.7"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "tsup",
38
38
  "dev": "tsup --watch"
39
- },
40
- "readme": "# `@ohbug/core`\n\n[![npm](https://img.shields.io/npm/v/@ohbug/core.svg?style=flat-square)](https://www.npmjs.com/package/@ohbug/core)\n[![npm bundle size](https://img.shields.io/bundlephobia/min/@ohbug/core?style=flat-square)](https://bundlephobia.com/result?p=@ohbug/core)\n\nEnglish | [简体中文](./README-zh_CN.md)\n\n## Introduction\n\nohbug's core module is responsible for managing ohbug's workflow.\n\n## Installation\n\n```\npnpm instal @ohbug/core\n```\n"
39
+ }
41
40
  }