@vpmedia/simplify 1.73.0 → 1.75.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.
Files changed (217) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/const/http_status.d.ts +66 -0
  3. package/dist/const/http_status.d.ts.map +1 -0
  4. package/dist/const/http_status.js +133 -0
  5. package/dist/const/http_status.js.map +1 -0
  6. package/dist/index.d.ts +34 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/{src → dist}/index.js +3 -20
  9. package/dist/index.js.map +1 -0
  10. package/dist/logging/AbstractLogHandler.d.ts +17 -0
  11. package/dist/logging/AbstractLogHandler.d.ts.map +1 -0
  12. package/dist/logging/AbstractLogHandler.js +16 -0
  13. package/dist/logging/AbstractLogHandler.js.map +1 -0
  14. package/dist/logging/ConsoleLogHandler.d.ts +13 -0
  15. package/dist/logging/ConsoleLogHandler.d.ts.map +1 -0
  16. package/dist/logging/ConsoleLogHandler.js +41 -0
  17. package/dist/logging/ConsoleLogHandler.js.map +1 -0
  18. package/dist/logging/Logger.d.ts +19 -0
  19. package/dist/logging/Logger.d.ts.map +1 -0
  20. package/dist/logging/Logger.js +51 -0
  21. package/dist/logging/Logger.js.map +1 -0
  22. package/dist/logging/OpenTelemetryLogHandler.d.ts +15 -0
  23. package/dist/logging/OpenTelemetryLogHandler.d.ts.map +1 -0
  24. package/dist/logging/OpenTelemetryLogHandler.js +21 -0
  25. package/dist/logging/OpenTelemetryLogHandler.js.map +1 -0
  26. package/dist/logging/SentryLogHandler.d.ts +13 -0
  27. package/dist/logging/SentryLogHandler.d.ts.map +1 -0
  28. package/dist/logging/SentryLogHandler.js +36 -0
  29. package/dist/logging/SentryLogHandler.js.map +1 -0
  30. package/dist/logging/const.d.ts +14 -0
  31. package/dist/logging/const.d.ts.map +1 -0
  32. package/dist/logging/const.js +21 -0
  33. package/dist/logging/const.js.map +1 -0
  34. package/dist/logging/util.d.ts +14 -0
  35. package/dist/logging/util.d.ts.map +1 -0
  36. package/dist/logging/util.js +34 -0
  37. package/dist/logging/util.js.map +1 -0
  38. package/dist/pagelifecycle/const.d.ts +15 -0
  39. package/dist/pagelifecycle/const.d.ts.map +1 -0
  40. package/dist/pagelifecycle/const.js +27 -0
  41. package/dist/pagelifecycle/const.js.map +1 -0
  42. package/dist/pagelifecycle/typedef.d.ts +4 -0
  43. package/dist/pagelifecycle/typedef.d.ts.map +1 -0
  44. package/dist/pagelifecycle/typedef.js +2 -0
  45. package/dist/pagelifecycle/typedef.js.map +1 -0
  46. package/dist/pagelifecycle/util.d.ts +31 -0
  47. package/dist/pagelifecycle/util.d.ts.map +1 -0
  48. package/dist/pagelifecycle/util.js +117 -0
  49. package/dist/pagelifecycle/util.js.map +1 -0
  50. package/dist/typecheck/TypeCheckError.d.ts +11 -0
  51. package/dist/typecheck/TypeCheckError.d.ts.map +1 -0
  52. package/dist/typecheck/TypeCheckError.js +12 -0
  53. package/dist/typecheck/TypeCheckError.js.map +1 -0
  54. package/dist/typecheck/TypeChecker.d.ts +27 -0
  55. package/dist/typecheck/TypeChecker.d.ts.map +1 -0
  56. package/dist/typecheck/TypeChecker.js +69 -0
  57. package/dist/typecheck/TypeChecker.js.map +1 -0
  58. package/dist/typecheck/util.d.ts +17 -0
  59. package/dist/typecheck/util.d.ts.map +1 -0
  60. package/dist/typecheck/util.js +42 -0
  61. package/dist/typecheck/util.js.map +1 -0
  62. package/dist/util/async.d.ts +13 -0
  63. package/dist/util/async.d.ts.map +1 -0
  64. package/dist/util/async.js +39 -0
  65. package/dist/util/async.js.map +1 -0
  66. package/dist/util/error.d.ts +16 -0
  67. package/dist/util/error.d.ts.map +1 -0
  68. package/dist/util/error.js +27 -0
  69. package/dist/util/error.js.map +1 -0
  70. package/dist/util/event_emitter.d.ts +42 -0
  71. package/dist/util/event_emitter.d.ts.map +1 -0
  72. package/dist/util/event_emitter.js +127 -0
  73. package/dist/util/event_emitter.js.map +1 -0
  74. package/dist/util/fetch.d.ts +22 -0
  75. package/dist/util/fetch.d.ts.map +1 -0
  76. package/dist/util/fetch.js +75 -0
  77. package/dist/util/fetch.js.map +1 -0
  78. package/dist/util/number.d.ts +23 -0
  79. package/dist/util/number.d.ts.map +1 -0
  80. package/dist/util/number.js +52 -0
  81. package/dist/util/number.js.map +1 -0
  82. package/dist/util/object.d.ts +24 -0
  83. package/dist/util/object.d.ts.map +1 -0
  84. package/dist/util/object.js +83 -0
  85. package/dist/util/object.js.map +1 -0
  86. package/dist/util/query.d.ts +11 -0
  87. package/dist/util/query.d.ts.map +1 -0
  88. package/dist/util/query.js +24 -0
  89. package/dist/util/query.js.map +1 -0
  90. package/dist/util/state.d.ts +5 -0
  91. package/dist/util/state.d.ts.map +1 -0
  92. package/dist/util/state.js +19 -0
  93. package/dist/util/state.js.map +1 -0
  94. package/dist/util/string.d.ts +25 -0
  95. package/dist/util/string.d.ts.map +1 -0
  96. package/dist/util/string.js +59 -0
  97. package/dist/util/string.js.map +1 -0
  98. package/dist/util/uuid.d.ts +13 -0
  99. package/dist/util/uuid.d.ts.map +1 -0
  100. package/dist/util/uuid.js +27 -0
  101. package/dist/util/uuid.js.map +1 -0
  102. package/dist/util/validate.d.ts +106 -0
  103. package/dist/util/validate.d.ts.map +1 -0
  104. package/dist/util/validate.js +139 -0
  105. package/dist/util/validate.js.map +1 -0
  106. package/package.json +31 -16
  107. package/src/const/http_status.test.ts +7 -0
  108. package/src/const/{http_status.js → http_status.ts} +1 -1
  109. package/src/index.ts +51 -0
  110. package/src/logging/AbstractLogHandler.ts +31 -0
  111. package/src/logging/{ConsoleLogHandler.js → ConsoleLogHandler.ts} +15 -13
  112. package/src/logging/Logger.test.ts +69 -0
  113. package/src/logging/Logger.ts +77 -0
  114. package/src/logging/OpenTelemetryLogHandler.ts +40 -0
  115. package/src/logging/SentryLogHandler.ts +44 -0
  116. package/src/logging/{const.js → const.ts} +1 -1
  117. package/src/logging/util.test.ts +33 -0
  118. package/src/logging/util.ts +36 -0
  119. package/src/pagelifecycle/{const.js → const.ts} +2 -2
  120. package/src/pagelifecycle/typedef.ts +5 -0
  121. package/src/pagelifecycle/util.test.ts +99 -0
  122. package/src/pagelifecycle/{util.js → util.ts} +14 -27
  123. package/src/typecheck/{TypeCheckError.js → TypeCheckError.ts} +7 -3
  124. package/src/typecheck/TypeChecker.test.ts +70 -0
  125. package/src/typecheck/{TypeChecker.js → TypeChecker.ts} +10 -27
  126. package/src/typecheck/util.test.ts +36 -0
  127. package/src/typecheck/util.ts +50 -0
  128. package/src/util/async.test.ts +74 -0
  129. package/src/util/{async.js → async.ts} +3 -11
  130. package/src/util/error.test.ts +32 -0
  131. package/src/util/error.ts +37 -0
  132. package/src/util/event_emitter.test.ts +228 -0
  133. package/src/util/event_emitter.ts +147 -0
  134. package/src/util/fetch.test.ts +62 -0
  135. package/src/util/{fetch.js → fetch.ts} +40 -31
  136. package/src/util/number.test.ts +124 -0
  137. package/src/util/number.ts +58 -0
  138. package/src/util/object.test.ts +203 -0
  139. package/src/util/{object.js → object.ts} +14 -21
  140. package/src/util/query.test.ts +71 -0
  141. package/src/util/query.ts +35 -0
  142. package/src/util/state.test.ts +47 -0
  143. package/src/util/{state.js → state.ts} +3 -6
  144. package/src/util/string.test.ts +64 -0
  145. package/src/util/string.ts +65 -0
  146. package/src/util/uuid.test.ts +53 -0
  147. package/src/util/uuid.ts +31 -0
  148. package/src/util/validate.test.ts +309 -0
  149. package/src/util/validate.ts +230 -0
  150. package/.vscode/extensions.json +0 -6
  151. package/.vscode/settings.json +0 -27
  152. package/src/logging/AbstractLogHandler.js +0 -23
  153. package/src/logging/Logger.js +0 -115
  154. package/src/logging/OpenTelemetryLogHandler.js +0 -30
  155. package/src/logging/SentryLogHandler.js +0 -46
  156. package/src/logging/util.js +0 -41
  157. package/src/pagelifecycle/typedef.js +0 -9
  158. package/src/typecheck/util.js +0 -60
  159. package/src/util/error.js +0 -33
  160. package/src/util/event_emitter.js +0 -196
  161. package/src/util/number.js +0 -118
  162. package/src/util/query.js +0 -32
  163. package/src/util/string.js +0 -76
  164. package/src/util/uuid.js +0 -35
  165. package/src/util/validate.js +0 -247
  166. package/types/const/http_status.d.ts +0 -131
  167. package/types/const/http_status.d.ts.map +0 -1
  168. package/types/index.d.ts +0 -26
  169. package/types/index.d.ts.map +0 -1
  170. package/types/logging/AbstractLogHandler.d.ts +0 -20
  171. package/types/logging/AbstractLogHandler.d.ts.map +0 -1
  172. package/types/logging/ConsoleLogHandler.d.ts +0 -9
  173. package/types/logging/ConsoleLogHandler.d.ts.map +0 -1
  174. package/types/logging/Logger.d.ts +0 -66
  175. package/types/logging/Logger.d.ts.map +0 -1
  176. package/types/logging/OpenTelemetryLogHandler.d.ts +0 -11
  177. package/types/logging/OpenTelemetryLogHandler.d.ts.map +0 -1
  178. package/types/logging/SentryLogHandler.d.ts +0 -9
  179. package/types/logging/SentryLogHandler.d.ts.map +0 -1
  180. package/types/logging/const.d.ts +0 -14
  181. package/types/logging/const.d.ts.map +0 -1
  182. package/types/logging/util.d.ts +0 -4
  183. package/types/logging/util.d.ts.map +0 -1
  184. package/types/pagelifecycle/const.d.ts +0 -15
  185. package/types/pagelifecycle/const.d.ts.map +0 -1
  186. package/types/pagelifecycle/typedef.d.ts +0 -4
  187. package/types/pagelifecycle/typedef.d.ts.map +0 -1
  188. package/types/pagelifecycle/util.d.ts +0 -8
  189. package/types/pagelifecycle/util.d.ts.map +0 -1
  190. package/types/typecheck/TypeCheckError.d.ts +0 -13
  191. package/types/typecheck/TypeCheckError.d.ts.map +0 -1
  192. package/types/typecheck/TypeChecker.d.ts +0 -40
  193. package/types/typecheck/TypeChecker.d.ts.map +0 -1
  194. package/types/typecheck/util.d.ts +0 -4
  195. package/types/typecheck/util.d.ts.map +0 -1
  196. package/types/util/async.d.ts +0 -4
  197. package/types/util/async.d.ts.map +0 -1
  198. package/types/util/error.d.ts +0 -3
  199. package/types/util/error.d.ts.map +0 -1
  200. package/types/util/event_emitter.d.ts +0 -69
  201. package/types/util/event_emitter.d.ts.map +0 -1
  202. package/types/util/fetch.d.ts +0 -22
  203. package/types/util/fetch.d.ts.map +0 -1
  204. package/types/util/number.d.ts +0 -11
  205. package/types/util/number.d.ts.map +0 -1
  206. package/types/util/object.d.ts +0 -6
  207. package/types/util/object.d.ts.map +0 -1
  208. package/types/util/query.d.ts +0 -3
  209. package/types/util/query.d.ts.map +0 -1
  210. package/types/util/state.d.ts +0 -2
  211. package/types/util/state.d.ts.map +0 -1
  212. package/types/util/string.d.ts +0 -7
  213. package/types/util/string.d.ts.map +0 -1
  214. package/types/util/uuid.d.ts +0 -4
  215. package/types/util/uuid.d.ts.map +0 -1
  216. package/types/util/validate.d.ts +0 -45
  217. package/types/util/validate.d.ts.map +0 -1
@@ -1,8 +1,11 @@
1
- import { AbstractLogHandler } from './AbstractLogHandler.js';
1
+ import { AbstractLogHandler, type LogExtra } from './AbstractLogHandler.js';
2
2
  import { LOG_LEVEL_DEBUG } from './const.js';
3
+ import type { Logger } from './Logger.js';
3
4
  import { formatLogMessage } from './util.js';
4
5
 
5
- const CONSOLE_FUNCTIONS = [
6
+ type ConsoleFn = (...data: unknown[]) => void;
7
+
8
+ const CONSOLE_FUNCTIONS: ReadonlyArray<ConsoleFn | null> = [
6
9
  null, // silent
7
10
  console.error, // fatal
8
11
  console.error, // error
@@ -14,29 +17,28 @@ const CONSOLE_FUNCTIONS = [
14
17
  export class ConsoleLogHandler extends AbstractLogHandler {
15
18
  /**
16
19
  * Console log handler.
17
- * @param {number} level - Log handler level.
18
20
  */
19
- constructor(level = LOG_LEVEL_DEBUG) {
21
+ constructor(level: number = LOG_LEVEL_DEBUG) {
20
22
  super(level);
21
23
  }
22
24
 
23
25
  /**
24
26
  * Emit log record.
25
- * @param {import('./Logger.js').Logger} logger - Logger instance.
26
- * @param {number} timestamp - Log timestamp.
27
- * @param {number} level - Log level.
28
- * @param {string} message - Log message.
29
- * @param {object | null | undefined} extra - Log extra data.
30
- * @param {Error | null | undefined} error - Log error.
31
- * @throws {Error}
32
27
  */
33
- emit(logger, timestamp, level, message, extra, error) {
28
+ override emit(
29
+ logger: Logger,
30
+ timestamp: number,
31
+ level: number,
32
+ message: string,
33
+ extra: LogExtra | null | undefined,
34
+ error: Error | null | undefined
35
+ ): void {
34
36
  if (logger.level < level) {
35
37
  return;
36
38
  }
37
39
  const logMessage = formatLogMessage(logger, timestamp, level, message);
38
40
  const consoleFunction = CONSOLE_FUNCTIONS[level];
39
- if (consoleFunction === null) {
41
+ if (consoleFunction === null || consoleFunction === undefined) {
40
42
  return;
41
43
  }
42
44
  if (error) {
@@ -0,0 +1,69 @@
1
+ import { AbstractLogHandler, type LogExtra } from './AbstractLogHandler.js';
2
+ import { LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_WARNING } from './const.js';
3
+ import { Logger } from './Logger.js';
4
+
5
+ class TestLogHandler extends AbstractLogHandler {
6
+ emitLogLogger: Logger | null = null;
7
+ emitLogTimestamp: number | null = null;
8
+ emitLogLevel: number | null = null;
9
+ emitLogMessage: string | null = null;
10
+ emitLogExtra: LogExtra | null | undefined = null;
11
+ emitLogError: Error | null | undefined = null;
12
+
13
+ constructor() {
14
+ super(LOG_LEVEL_DEBUG);
15
+ }
16
+
17
+ override emit(
18
+ logger: Logger,
19
+ timestamp: number,
20
+ level: number,
21
+ message: string,
22
+ extra: LogExtra | null | undefined,
23
+ error: Error | null | undefined
24
+ ): void {
25
+ this.emitLogLogger = logger;
26
+ this.emitLogTimestamp = timestamp;
27
+ this.emitLogLevel = level;
28
+ this.emitLogMessage = message;
29
+ this.emitLogExtra = extra;
30
+ this.emitLogError = error;
31
+ }
32
+ }
33
+
34
+ test('Tests Logger default level', () => {
35
+ const logger = new Logger('test');
36
+ expect(logger.level).toBe(LOG_LEVEL_DEBUG);
37
+ });
38
+
39
+ test('Tests Logger custom handler', () => {
40
+ const logger = new Logger('test');
41
+ const testLogHandler = new TestLogHandler();
42
+ Logger.addHandler(testLogHandler);
43
+ // debug
44
+ logger.debug('debug');
45
+ expect(testLogHandler.emitLogLevel).toBe(LOG_LEVEL_DEBUG);
46
+ expect(testLogHandler.emitLogMessage).toBe('debug');
47
+ // info
48
+ logger.info('info');
49
+ expect(testLogHandler.emitLogLevel).toBe(LOG_LEVEL_INFO);
50
+ expect(testLogHandler.emitLogMessage).toBe('info');
51
+ // warning
52
+ logger.warn('warning');
53
+ expect(testLogHandler.emitLogLevel).toBe(LOG_LEVEL_WARNING);
54
+ expect(testLogHandler.emitLogMessage).toBe('warning');
55
+ logger.warning('warning');
56
+ expect(testLogHandler.emitLogLevel).toBe(LOG_LEVEL_WARNING);
57
+ expect(testLogHandler.emitLogMessage).toBe('warning');
58
+ // error
59
+ logger.error('error');
60
+ expect(testLogHandler.emitLogLevel).toBe(LOG_LEVEL_ERROR);
61
+ expect(testLogHandler.emitLogMessage).toBe('error');
62
+ // exception
63
+ logger.exception('test', new Error('test_error'), { context: 'ctx' });
64
+ expect(testLogHandler.emitLogLevel).toBe(LOG_LEVEL_FATAL);
65
+ expect(testLogHandler.emitLogMessage).toBe('test');
66
+ expect(testLogHandler.emitLogError?.message).toBe('test_error');
67
+ expect(testLogHandler.emitLogLogger).toBe(logger);
68
+ expect(testLogHandler.emitLogExtra?.['context']).toBe('ctx');
69
+ });
@@ -0,0 +1,77 @@
1
+ import { getURLParam } from '../util/query.js';
2
+ import type { AbstractLogHandler, LogExtra } from './AbstractLogHandler.js';
3
+ import {
4
+ LOG_LEVEL_DEBUG,
5
+ LOG_LEVEL_ERROR,
6
+ LOG_LEVEL_FATAL,
7
+ LOG_LEVEL_INFO,
8
+ LOG_LEVEL_SILENT,
9
+ LOG_LEVEL_WARNING,
10
+ } from './const.js';
11
+ import { getAppEnvironment } from './util.js';
12
+
13
+ const ROOT_LOGGER_NAME = 'root';
14
+
15
+ export class Logger {
16
+ static handlers: AbstractLogHandler[] = [];
17
+
18
+ name: string;
19
+ level: number;
20
+
21
+ /**
22
+ * Creates a new Logger instance.
23
+ */
24
+ constructor(name: string = ROOT_LOGGER_NAME) {
25
+ this.name = name ?? ROOT_LOGGER_NAME;
26
+ const appEnvironment = getAppEnvironment();
27
+ const isProduction = appEnvironment === 'production' || appEnvironment === 'release';
28
+ const defaultLevel = isProduction ? LOG_LEVEL_SILENT : LOG_LEVEL_DEBUG;
29
+ const parameterName = `log_${this.name.toLowerCase()}`;
30
+ const paramLevel =
31
+ getURLParam(parameterName, getURLParam('log_all', defaultLevel.toString())) ?? defaultLevel.toString();
32
+ this.level = Number.parseInt(paramLevel, 10);
33
+ }
34
+
35
+ static addHandler = (handler: AbstractLogHandler): void => {
36
+ Logger.handlers.push(handler);
37
+ };
38
+
39
+ static emit = (
40
+ logger: Logger,
41
+ level: number,
42
+ message: string,
43
+ extra?: LogExtra | null,
44
+ error?: Error | null
45
+ ): void => {
46
+ const timestamp = Date.now();
47
+ for (const handler of Logger.handlers) {
48
+ if (handler.level >= level) {
49
+ handler.emit(logger, timestamp, level, message, extra, error);
50
+ }
51
+ }
52
+ };
53
+
54
+ debug(message: string, extra?: LogExtra | null): void {
55
+ Logger.emit(this, LOG_LEVEL_DEBUG, message, extra);
56
+ }
57
+
58
+ info(message: string, extra?: LogExtra | null): void {
59
+ Logger.emit(this, LOG_LEVEL_INFO, message, extra);
60
+ }
61
+
62
+ warn(message: string, extra?: LogExtra | null): void {
63
+ Logger.emit(this, LOG_LEVEL_WARNING, message, extra);
64
+ }
65
+
66
+ warning(message: string, extra?: LogExtra | null): void {
67
+ Logger.emit(this, LOG_LEVEL_WARNING, message, extra);
68
+ }
69
+
70
+ error(message: string, extra?: LogExtra | null): void {
71
+ Logger.emit(this, LOG_LEVEL_ERROR, message, extra);
72
+ }
73
+
74
+ exception(message: string, error: Error, extra?: LogExtra | null): void {
75
+ Logger.emit(this, LOG_LEVEL_FATAL, message, extra, error);
76
+ }
77
+ }
@@ -0,0 +1,40 @@
1
+ import { AbstractLogHandler, type LogExtra } from './AbstractLogHandler.js';
2
+ import type { Logger } from './Logger.js';
3
+
4
+ export type OpenTelemetryLogEmitter = (
5
+ logger: Logger,
6
+ timestamp: number,
7
+ level: number,
8
+ message: string,
9
+ extra: LogExtra | null | undefined,
10
+ error: Error | null | undefined
11
+ ) => void;
12
+
13
+ export class OpenTelemetryLogHandler extends AbstractLogHandler {
14
+ emitter: OpenTelemetryLogEmitter;
15
+
16
+ /**
17
+ * Open Telemetry log handler.
18
+ */
19
+ constructor(level: number, emitter: OpenTelemetryLogEmitter) {
20
+ super(level);
21
+ this.emitter = emitter;
22
+ }
23
+
24
+ /**
25
+ * Emit log record.
26
+ */
27
+ override emit(
28
+ logger: Logger,
29
+ timestamp: number,
30
+ level: number,
31
+ message: string,
32
+ extra: LogExtra | null | undefined,
33
+ error: Error | null | undefined
34
+ ): void {
35
+ if (!this.emitter) {
36
+ return;
37
+ }
38
+ this.emitter(logger, timestamp, level, message, extra, error);
39
+ }
40
+ }
@@ -0,0 +1,44 @@
1
+ import { addBreadcrumb, captureException, captureMessage, type SeverityLevel } from '@sentry/browser';
2
+ import { AbstractLogHandler, type LogExtra } from './AbstractLogHandler.js';
3
+ import { LOG_LEVEL_DEBUG, LOG_LEVEL_WARNING } from './const.js';
4
+ import type { Logger } from './Logger.js';
5
+ import { getLogLevelName } from './util.js';
6
+
7
+ export class SentryLogHandler extends AbstractLogHandler {
8
+ /**
9
+ * Sentry log handler.
10
+ */
11
+ constructor(level: number = LOG_LEVEL_DEBUG) {
12
+ super(level);
13
+ }
14
+
15
+ /**
16
+ * Emit log record.
17
+ */
18
+ override emit(
19
+ logger: Logger,
20
+ _timestamp: number,
21
+ level: number,
22
+ message: string,
23
+ extra: LogExtra | null | undefined,
24
+ error: Error | null | undefined
25
+ ): void {
26
+ const levelName = getLogLevelName(level) as SeverityLevel;
27
+ const logMessage = `[${logger.name}] ${message}`;
28
+ const breadcrumb = {
29
+ type: 'default',
30
+ category: 'console',
31
+ message: logMessage,
32
+ level: levelName,
33
+ data: extra ?? undefined,
34
+ };
35
+ addBreadcrumb(breadcrumb);
36
+ if (error) {
37
+ extra?.tags ? captureException(error, { tags: extra.tags }) : captureException(error);
38
+ } else if (level === LOG_LEVEL_WARNING) {
39
+ extra?.tags
40
+ ? captureMessage(logMessage, { level: 'warning', tags: extra.tags })
41
+ : captureMessage(logMessage, { level: 'warning' });
42
+ }
43
+ }
44
+ }
@@ -12,7 +12,7 @@ export const LOG_LEVEL_NAME_WARNING = 'warning';
12
12
  export const LOG_LEVEL_NAME_INFO = 'info';
13
13
  export const LOG_LEVEL_NAME_DEBUG = 'debug';
14
14
 
15
- export const LOG_LEVEL_NAMES = [
15
+ export const LOG_LEVEL_NAMES: readonly string[] = [
16
16
  LOG_LEVEL_NAME_SILENT,
17
17
  LOG_LEVEL_NAME_FATAL,
18
18
  LOG_LEVEL_NAME_ERROR,
@@ -0,0 +1,33 @@
1
+ import {
2
+ LOG_LEVEL_DEBUG,
3
+ LOG_LEVEL_ERROR,
4
+ LOG_LEVEL_FATAL,
5
+ LOG_LEVEL_INFO,
6
+ LOG_LEVEL_NAME_DEBUG,
7
+ LOG_LEVEL_NAME_ERROR,
8
+ LOG_LEVEL_NAME_FATAL,
9
+ LOG_LEVEL_NAME_INFO,
10
+ LOG_LEVEL_NAME_SILENT,
11
+ LOG_LEVEL_NAME_WARNING,
12
+ LOG_LEVEL_SILENT,
13
+ LOG_LEVEL_WARNING,
14
+ } from './const.js';
15
+ import { Logger } from './Logger.js';
16
+ import { formatLogMessage, getLogLevelName } from './util.js';
17
+
18
+ test('formatLogMessage()', () => {
19
+ expect(
20
+ formatLogMessage(new Logger('loggerName'), Date.now(), LOG_LEVEL_INFO, 'logMessage').endsWith(
21
+ '[loggerName] logMessage'
22
+ )
23
+ ).toBe(true);
24
+ });
25
+
26
+ test('getLogLevelName()', () => {
27
+ expect(getLogLevelName(LOG_LEVEL_DEBUG)).toBe(LOG_LEVEL_NAME_DEBUG);
28
+ expect(getLogLevelName(LOG_LEVEL_INFO)).toBe(LOG_LEVEL_NAME_INFO);
29
+ expect(getLogLevelName(LOG_LEVEL_WARNING)).toBe(LOG_LEVEL_NAME_WARNING);
30
+ expect(getLogLevelName(LOG_LEVEL_ERROR)).toBe(LOG_LEVEL_NAME_ERROR);
31
+ expect(getLogLevelName(LOG_LEVEL_FATAL)).toBe(LOG_LEVEL_NAME_FATAL);
32
+ expect(getLogLevelName(LOG_LEVEL_SILENT)).toBe(LOG_LEVEL_NAME_SILENT);
33
+ });
@@ -0,0 +1,36 @@
1
+ import type { Logger } from './Logger.js';
2
+ import { LOG_LEVEL_NAMES } from './const.js';
3
+
4
+ /**
5
+ * Format log message.
6
+ */
7
+ export const formatLogMessage = (logger: Logger, timestamp: number, _level: number, message: string): string =>
8
+ `${timestamp} [${logger.name}] ${message}`;
9
+
10
+ /**
11
+ * Get log level name.
12
+ */
13
+ export const getLogLevelName = (level: number): string | undefined => LOG_LEVEL_NAMES[level];
14
+
15
+ /**
16
+ * Returns the application environment identifier.
17
+ */
18
+ export const getAppEnvironment = (): string => {
19
+ let appEnvironment = 'local';
20
+ try {
21
+ const { env } = import.meta as unknown as { env?: Record<string, string | undefined> };
22
+ if (env?.['VITE_APP_ENVIRONMENT']) {
23
+ appEnvironment = env['VITE_APP_ENVIRONMENT'];
24
+ }
25
+ } catch {
26
+ // pass
27
+ }
28
+ try {
29
+ if (process.env['APP_ENVIRONMENT']) {
30
+ appEnvironment = process.env['APP_ENVIRONMENT'];
31
+ }
32
+ } catch {
33
+ // pass
34
+ }
35
+ return appEnvironment;
36
+ };
@@ -4,7 +4,7 @@ export const PAGE_LIFECYCLE_STATE_PASSIVE = 'passive';
4
4
  export const PAGE_LIFECYCLE_STATE_FROZEN = 'frozen';
5
5
  export const PAGE_LIFECYCLE_STATE_TERMINATED = 'terminated';
6
6
 
7
- export const PAGE_LIFECYCLE_STATES = new Set([
7
+ export const PAGE_LIFECYCLE_STATES: ReadonlySet<string> = new Set([
8
8
  PAGE_LIFECYCLE_STATE_ACTIVE,
9
9
  PAGE_LIFECYCLE_STATE_FROZEN,
10
10
  PAGE_LIFECYCLE_STATE_HIDDEN,
@@ -18,7 +18,7 @@ export const DOCUMENT_STATE_COMPLETE = 'complete';
18
18
  export const DOCUMENT_STATE_INTERACTIVE = 'interactive';
19
19
  export const DOCUMENT_STATE_LOADING = 'loading';
20
20
 
21
- export const DOCUMENT_STATES = new Set([
21
+ export const DOCUMENT_STATES: ReadonlySet<string> = new Set([
22
22
  DOCUMENT_STATE_COMPLETE,
23
23
  DOCUMENT_STATE_DOM_LOADED,
24
24
  DOCUMENT_STATE_FULLY_LOADED,
@@ -0,0 +1,5 @@
1
+ export const TYPEDEF = true;
2
+
3
+ export type PageLifecycleState = 'hidden' | 'active' | 'passive' | 'frozen' | 'terminated';
4
+
5
+ export type DocumentState = 'loading' | 'interactive' | 'complete' | 'domLoaded' | 'fullyLoaded';
@@ -0,0 +1,99 @@
1
+ import { beforeAll, describe, expect, it } from 'vitest';
2
+ import {
3
+ DOCUMENT_STATE_CHANGE_EVENT,
4
+ DOCUMENT_STATES,
5
+ PAGE_LIFECYCLE_STATE_CHANGE_EVENT,
6
+ PAGE_LIFECYCLE_STATES,
7
+ } from './const.js';
8
+ import {
9
+ getDocumentState,
10
+ getPageLifecycleEventEmitter,
11
+ getPageLifecycleState,
12
+ initPageLifecycle,
13
+ isPageLifecycleInitialized,
14
+ } from './util.js';
15
+
16
+ describe('Page Lifecycle', () => {
17
+ beforeAll(() => {
18
+ initPageLifecycle();
19
+ });
20
+
21
+ it('should initialize page lifecycle', () => {
22
+ expect(isPageLifecycleInitialized()).toBe(true);
23
+ });
24
+
25
+ it('should return current page lifecycle state', () => {
26
+ const state = getPageLifecycleState();
27
+ expect(state).toBeOneOf([...PAGE_LIFECYCLE_STATES]);
28
+ });
29
+
30
+ it('should return current document state', () => {
31
+ const state = getDocumentState();
32
+ expect(state).toBeOneOf([...DOCUMENT_STATES]);
33
+ });
34
+
35
+ it('should return event emitter instance', () => {
36
+ const emitter = getPageLifecycleEventEmitter();
37
+ expect(emitter).toBeDefined();
38
+ });
39
+
40
+ it('should handle page lifecycle state changes', () => {
41
+ const emitter = getPageLifecycleEventEmitter();
42
+ let stateChanged = false;
43
+
44
+ emitter.on(PAGE_LIFECYCLE_STATE_CHANGE_EVENT, (data: unknown) => {
45
+ stateChanged = true;
46
+ expect(data).toHaveProperty('previousState');
47
+ expect(data).toHaveProperty('nextState');
48
+ });
49
+
50
+ // Trigger visibility change
51
+ const originalVisibilityState = document.visibilityState;
52
+ Object.defineProperty(document, 'visibilityState', {
53
+ value: originalVisibilityState === 'visible' ? 'hidden' : 'visible',
54
+ writable: true,
55
+ configurable: true,
56
+ });
57
+
58
+ document.dispatchEvent(new Event('visibilitychange'));
59
+
60
+ // Restore original state
61
+ Object.defineProperty(document, 'visibilityState', {
62
+ value: originalVisibilityState,
63
+ writable: true,
64
+ configurable: true,
65
+ });
66
+
67
+ expect(stateChanged).toBe(true);
68
+ });
69
+
70
+ it('should handle document state changes', () => {
71
+ const emitter = getPageLifecycleEventEmitter();
72
+ let stateChanged = false;
73
+
74
+ emitter.on(DOCUMENT_STATE_CHANGE_EVENT, (data: unknown) => {
75
+ stateChanged = true;
76
+ expect(data).toHaveProperty('previousState');
77
+ expect(data).toHaveProperty('nextState');
78
+ });
79
+
80
+ // Trigger ready state change
81
+ const originalReadyState = document.readyState;
82
+ Object.defineProperty(document, 'readyState', {
83
+ value: originalReadyState === 'complete' ? 'interactive' : 'complete',
84
+ writable: true,
85
+ configurable: true,
86
+ });
87
+
88
+ document.dispatchEvent(new Event('readystatechange'));
89
+
90
+ // Restore original state
91
+ Object.defineProperty(document, 'readyState', {
92
+ value: originalReadyState,
93
+ writable: true,
94
+ configurable: true,
95
+ });
96
+
97
+ expect(stateChanged).toBe(true);
98
+ });
99
+ });
@@ -16,27 +16,24 @@ import {
16
16
  PAGE_LIFECYCLE_STATE_PASSIVE,
17
17
  PAGE_LIFECYCLE_STATE_TERMINATED,
18
18
  } from './const.js';
19
+ import type { DocumentState, PageLifecycleState } from './typedef.js';
19
20
 
20
21
  const logger = new Logger('pagelifecycle');
21
22
 
22
23
  const eventEmitter = new EventEmitter();
23
24
 
24
- /** @type {import('./typedef.js').PageLifecycleState | null | undefined} */
25
- let currentPageLifecycleState = null;
25
+ let currentPageLifecycleState: PageLifecycleState | null | undefined = null;
26
26
 
27
- /** @type {import('./typedef.js').DocumentState | null | undefined} */
28
- let currentDocumentState = null;
27
+ let currentDocumentState: DocumentState | null | undefined = null;
29
28
 
30
29
  let isInitialized = false;
31
30
 
32
- /** @type {Record<string, (() => void)[]>} */
33
- const callbacks = {};
31
+ const callbacks: Record<string, (() => void)[]> = {};
34
32
 
35
33
  /**
36
34
  * Run callbacks for a specific state change.
37
- * @param {import('./typedef.js').DocumentState | import('./typedef.js').PageLifecycleState} state - Callback state condition.
38
35
  */
39
- const processCallbacks = (state) => {
36
+ const processCallbacks = (state: DocumentState | PageLifecycleState): void => {
40
37
  const stateCallbacks = callbacks[state];
41
38
  if (!stateCallbacks) {
42
39
  return;
@@ -49,9 +46,8 @@ const processCallbacks = (state) => {
49
46
 
50
47
  /**
51
48
  * Detects the current page lifecycle state.
52
- * @returns {import('./typedef.js').PageLifecycleState} Current page lifecycle state.
53
49
  */
54
- const detectPageLifecycleState = () => {
50
+ const detectPageLifecycleState = (): PageLifecycleState => {
55
51
  if (document.visibilityState === 'hidden') {
56
52
  return PAGE_LIFECYCLE_STATE_HIDDEN;
57
53
  }
@@ -63,9 +59,8 @@ const detectPageLifecycleState = () => {
63
59
 
64
60
  /**
65
61
  * Handles page lifecycle state change.
66
- * @param {import('./typedef.js').PageLifecycleState} nextState - Next page lifecycle state.
67
62
  */
68
- const onPageLifecycleStateChange = (nextState) => {
63
+ const onPageLifecycleStateChange = (nextState: PageLifecycleState): void => {
69
64
  const previousState = currentPageLifecycleState;
70
65
  if (nextState !== previousState) {
71
66
  currentPageLifecycleState = nextState;
@@ -78,9 +73,8 @@ const onPageLifecycleStateChange = (nextState) => {
78
73
 
79
74
  /**
80
75
  * Handles document state change.
81
- * @param {import('./typedef.js').DocumentState} nextState - Next document state.
82
76
  */
83
- const onDocumentStateChange = (nextState) => {
77
+ const onDocumentStateChange = (nextState: DocumentState): void => {
84
78
  const previousState = currentDocumentState;
85
79
  if (nextState !== previousState) {
86
80
  currentDocumentState = nextState;
@@ -94,7 +88,7 @@ const onDocumentStateChange = (nextState) => {
94
88
  /**
95
89
  * Initialize page lifecycle observer.
96
90
  */
97
- export const initPageLifecycle = () => {
91
+ export const initPageLifecycle = (): void => {
98
92
  if (isInitialized) {
99
93
  return;
100
94
  }
@@ -103,7 +97,6 @@ export const initPageLifecycle = () => {
103
97
  onDocumentStateChange(document.readyState);
104
98
  const options = { capture: true };
105
99
  document.addEventListener('visibilitychange', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
106
- // globalThis.addEventListener('popstate', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
107
100
  globalThis.addEventListener('pageshow', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
108
101
  globalThis.addEventListener('focus', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
109
102
  globalThis.addEventListener('blur', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
@@ -123,21 +116,18 @@ export const initPageLifecycle = () => {
123
116
 
124
117
  /**
125
118
  * Returns the current page lifecycle state.
126
- * @returns {string | null | undefined} Current page lifecycle state.
127
119
  */
128
- export const getPageLifecycleState = () => currentPageLifecycleState;
120
+ export const getPageLifecycleState = (): PageLifecycleState | null | undefined => currentPageLifecycleState;
129
121
 
130
122
  /**
131
123
  * Returns the current document state.
132
- * @returns {import('./typedef.js').DocumentState | null | undefined} Current document state.
133
124
  */
134
- export const getDocumentState = () => currentDocumentState;
125
+ export const getDocumentState = (): DocumentState | null | undefined => currentDocumentState;
135
126
 
136
127
  /**
137
128
  * Returns the event emitter instance.
138
- * @returns {EventEmitter} Event emitter instance.
139
129
  */
140
- export const getPageLifecycleEventEmitter = () => {
130
+ export const getPageLifecycleEventEmitter = (): EventEmitter => {
141
131
  if (!isInitialized) {
142
132
  initPageLifecycle();
143
133
  }
@@ -146,16 +136,13 @@ export const getPageLifecycleEventEmitter = () => {
146
136
 
147
137
  /**
148
138
  * Returns the page lifecycle observer initialized state.
149
- * @returns {boolean} Page lifecycle observer initialized flag.
150
139
  */
151
- export const isPageLifecycleInitialized = () => isInitialized;
140
+ export const isPageLifecycleInitialized = (): boolean => isInitialized;
152
141
 
153
142
  /**
154
143
  * Add callback for a specific state change.
155
- * @param {import('./typedef.js').DocumentState | import('./typedef.js').PageLifecycleState} state - Callback state condition.
156
- * @param {() => void} callback - Callback function.
157
144
  */
158
- export const addPageLifecycleCallback = (state, callback) => {
145
+ export const addPageLifecycleCallback = (state: DocumentState | PageLifecycleState, callback: () => void): void => {
159
146
  const stateCallbacks = callbacks[state] ?? [];
160
147
  stateCallbacks.push(callback);
161
148
  callbacks[state] = stateCallbacks;
@@ -1,10 +1,14 @@
1
+ export interface TypeCheckErrorOptions extends ErrorOptions {
2
+ value?: unknown;
3
+ }
4
+
1
5
  export class TypeCheckError extends TypeError {
6
+ value: unknown;
7
+
2
8
  /**
3
9
  * Creates a new `TypeCheckError` instance.
4
- * @param {string} message - Error message.
5
- * @param {{ cause?: unknown, value?: unknown }} [options] - Error options.
6
10
  */
7
- constructor(message, options) {
11
+ constructor(message: string, options?: TypeCheckErrorOptions) {
8
12
  super(message, options);
9
13
  this.name = 'TypeCheckError';
10
14
  this.value = options?.value;