@aidc-toolkit/core 1.0.31-beta → 1.0.32-beta

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 (41) hide show
  1. package/README.md +2 -2
  2. package/dist/cache.d.ts +58 -0
  3. package/dist/cache.d.ts.map +1 -0
  4. package/dist/cache.js +12 -0
  5. package/dist/cache.js.map +1 -0
  6. package/dist/hyperlink.d.ts +18 -0
  7. package/dist/hyperlink.d.ts.map +1 -0
  8. package/dist/hyperlink.js +2 -0
  9. package/dist/hyperlink.js.map +1 -0
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +1 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/locale/en/locale-resources.d.ts +7 -0
  15. package/dist/locale/en/locale-resources.d.ts.map +1 -0
  16. package/dist/locale/en/locale-resources.js +6 -0
  17. package/dist/locale/en/locale-resources.js.map +1 -0
  18. package/dist/locale/fr/locale-resources.d.ts +7 -0
  19. package/dist/locale/fr/locale-resources.d.ts.map +1 -0
  20. package/dist/locale/fr/locale-resources.js +6 -0
  21. package/dist/locale/fr/locale-resources.js.map +1 -0
  22. package/dist/locale/i18n.d.ts +23 -5
  23. package/dist/locale/i18n.d.ts.map +1 -1
  24. package/dist/locale/i18n.js +31 -5
  25. package/dist/locale/i18n.js.map +1 -1
  26. package/dist/logger.d.ts +106 -4
  27. package/dist/logger.d.ts.map +1 -1
  28. package/dist/logger.js +222 -13
  29. package/dist/logger.js.map +1 -1
  30. package/dist/type.d.ts +5 -0
  31. package/dist/type.d.ts.map +1 -1
  32. package/package.json +3 -3
  33. package/src/cache.ts +64 -0
  34. package/src/hyperlink.ts +19 -0
  35. package/src/index.ts +5 -0
  36. package/src/locale/en/locale-resources.ts +5 -0
  37. package/src/locale/fr/locale-resources.ts +5 -0
  38. package/src/locale/i18n.ts +40 -6
  39. package/src/locale/i18next.d.ts +16 -0
  40. package/src/logger.ts +244 -14
  41. package/src/type.ts +6 -0
package/README.md CHANGED
@@ -35,7 +35,7 @@ All AIDC Toolkit packages require internationalization. The localization functio
35
35
  Packages install their resources as follows in `i18n.ts` or similar:
36
36
 
37
37
  ```typescript
38
- import { i18nCoreInit, type I18nEnvironment } from "@aidc-toolkit/core";
38
+ import { type I18nEnvironment, i18nFinalizeInit } from "@aidc-toolkit/core";
39
39
  import { dependency1Resources, i18nDependency1Init } from "@aidc-toolkit/dependency1";
40
40
  import { dependency2Resources, i18nDependency2Init } from "@aidc-toolkit/dependency2";
41
41
  import i18next, { type i18n, type Resource } from "i18next";
@@ -79,7 +79,7 @@ export const i18nextPackage: i18n = i18next.createInstance();
79
79
  export async function i18nPackageInit(environment: I18nEnvironment, debug = false): Promise<void> {
80
80
  await i18nDependency1Init(environment, debug);
81
81
  await i18nDependency2Init(environment, debug);
82
- await i18nCoreInit(i18nextPackage, environment, debug, packageNS, dependency1Resources, dependency2Resources, packageResources);
82
+ await i18nFinalizeInit(i18nextPackage, environment, debug, packageNS, dependency1Resources, dependency2Resources, packageResources);
83
83
  }
84
84
  ```
85
85
 
@@ -0,0 +1,58 @@
1
+ import type { Promisable } from "./type.js";
2
+ /**
3
+ * Generic cache. Typically used to manage a local copy of remote data that is not refreshed regularly.
4
+ *
5
+ * @template TCache
6
+ * Type of cached data.
7
+ *
8
+ * @template TSource
9
+ * Type of source data. The type may be different from the cached data type if a transformation is required.
10
+ */
11
+ export declare abstract class Cache<TCache, TSource = TCache> {
12
+ /**
13
+ * Get the date/time at or after which the source should be checked for updates. If the value is undefined, this is
14
+ * the first usage.
15
+ */
16
+ abstract get nextCheckDateTime(): Promisable<Date | undefined>;
17
+ /**
18
+ * Get the date/time at which the cache was last updated. This may more accurately reflect the date/time at which
19
+ * the last source retrieved was updated. If the value is undefined, there is no data in the cache.
20
+ */
21
+ abstract get cacheDateTime(): Promisable<Date | undefined>;
22
+ /**
23
+ * Get the cache data. This should only ever be called if the cache date/time is defined.
24
+ */
25
+ abstract get cacheData(): Promisable<TCache>;
26
+ /**
27
+ * Get the date/time at which the source was last updated. This should not be called unless the next check date/time
28
+ * has passed, as it may trigger an expensive remote retrieval.
29
+ */
30
+ abstract get sourceDateTime(): Promisable<Date>;
31
+ /**
32
+ * Get the source data. This should not be called unless the next check date/time has passed, as it may trigger an
33
+ * expensive remote retrieval.
34
+ */
35
+ abstract get sourceData(): Promisable<TSource>;
36
+ /**
37
+ * Update the cache with only the next check date/time. The cache date/time and cache data must not be modified.
38
+ * This is typically called when the cache is up to date with the source or source retrieval has failed.
39
+ *
40
+ * @param nextCheckDateTime
41
+ * Next check date/time.
42
+ */
43
+ abstract update(nextCheckDateTime: Date): Promisable<void>;
44
+ /**
45
+ * Update all cache parameters. This is typically called when the cache is updated from the source.
46
+ *
47
+ * @param nextCheckDateTime
48
+ * Next check date/time.
49
+ *
50
+ * @param cacheDateTime
51
+ * Cache date/time.
52
+ *
53
+ * @param cacheData
54
+ * Cache data.
55
+ */
56
+ abstract update(nextCheckDateTime: Date, cacheDateTime: Date, cacheData: TCache): Promisable<void>;
57
+ }
58
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C;;;;;;;;GAQG;AACH,8BAAsB,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM;IAChD;;;OAGG;IACH,QAAQ,KAAK,iBAAiB,IAAI,UAAU,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAE/D;;;OAGG;IACH,QAAQ,KAAK,aAAa,IAAI,UAAU,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAE3D;;OAEG;IACH,QAAQ,KAAK,SAAS,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAE7C;;;OAGG;IACH,QAAQ,KAAK,cAAc,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IAEhD;;;OAGG;IACH,QAAQ,KAAK,UAAU,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IAE/C;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;IAE1D;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC;CACrG"}
package/dist/cache.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Generic cache. Typically used to manage a local copy of remote data that is not refreshed regularly.
3
+ *
4
+ * @template TCache
5
+ * Type of cached data.
6
+ *
7
+ * @template TSource
8
+ * Type of source data. The type may be different from the cached data type if a transformation is required.
9
+ */
10
+ export class Cache {
11
+ }
12
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,OAAgB,KAAK;CAoD1B"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Hyperlink.
3
+ */
4
+ export interface Hyperlink {
5
+ /**
6
+ * Reference, relative or absolute depending on the application.
7
+ */
8
+ readonly reference: string;
9
+ /**
10
+ * Human-readable text.
11
+ */
12
+ readonly text?: string | undefined;
13
+ /**
14
+ * Additional details.
15
+ */
16
+ readonly details?: string | undefined;
17
+ }
18
+ //# sourceMappingURL=hyperlink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperlink.d.ts","sourceRoot":"","sources":["../src/hyperlink.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,SAAS;IACtB;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hyperlink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperlink.js","sourceRoot":"","sources":["../src/hyperlink.ts"],"names":[],"mappings":""}
package/dist/index.d.ts CHANGED
@@ -17,5 +17,7 @@
17
17
  export type * from "./type.js";
18
18
  export * from "./type-helper.js";
19
19
  export * from "./logger.js";
20
+ export * from "./cache.js";
21
+ export type * from "./hyperlink.js";
20
22
  export * from "./locale/i18n.js";
21
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,mBAAmB,WAAW,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,mBAAmB,WAAW,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,aAAa,CAAC;AAE5B,cAAc,YAAY,CAAC;AAC3B,mBAAmB,gBAAgB,CAAC;AAEpC,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./type-helper.js";
2
2
  export * from "./logger.js";
3
+ export * from "./cache.js";
3
4
  export * from "./locale/i18n.js";
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,cAAc,kBAAkB,CAAC;AAEjC,cAAc,aAAa,CAAC;AAE5B,cAAc,YAAY,CAAC;AAG3B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ Logger: {
3
+ unknownLogLevel: string;
4
+ };
5
+ };
6
+ export default _default;
7
+ //# sourceMappingURL=locale-resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-resources.d.ts","sourceRoot":"","sources":["../../../src/locale/en/locale-resources.ts"],"names":[],"mappings":";;;;;AAAA,wBAIE"}
@@ -0,0 +1,6 @@
1
+ export default {
2
+ Logger: {
3
+ unknownLogLevel: "Unknown log level \"{{logLevel}}\""
4
+ }
5
+ };
6
+ //# sourceMappingURL=locale-resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-resources.js","sourceRoot":"","sources":["../../../src/locale/en/locale-resources.ts"],"names":[],"mappings":"AAAA,eAAe;IACX,MAAM,EAAE;QACJ,eAAe,EAAE,oCAAoC;KACxD;CACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ Logger: {
3
+ unknownLogLevel: string;
4
+ };
5
+ };
6
+ export default _default;
7
+ //# sourceMappingURL=locale-resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-resources.d.ts","sourceRoot":"","sources":["../../../src/locale/fr/locale-resources.ts"],"names":[],"mappings":";;;;;AAAA,wBAIE"}
@@ -0,0 +1,6 @@
1
+ export default {
2
+ Logger: {
3
+ unknownLogLevel: "Niveau de journalisation inconnu «{{logLevel}}»"
4
+ }
5
+ };
6
+ //# sourceMappingURL=locale-resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-resources.js","sourceRoot":"","sources":["../../../src/locale/fr/locale-resources.ts"],"names":[],"mappings":"AAAA,eAAe;IACX,MAAM,EAAE;QACJ,eAAe,EAAE,iDAAiD;KACrE;CACJ,CAAC"}
@@ -1,4 +1,5 @@
1
- import type { i18n, Resource } from "i18next";
1
+ import { type i18n, type Resource } from "i18next";
2
+ import enLocaleResources from "./en/locale-resources.js";
2
3
  /**
3
4
  * Locale strings type for generic manipulation.
4
5
  */
@@ -30,6 +31,26 @@ export type I18nEnvironmentKey = keyof typeof I18nEnvironments;
30
31
  * Internationalization operating environment.
31
32
  */
32
33
  export type I18nEnvironment = typeof I18nEnvironments[I18nEnvironmentKey];
34
+ export declare const coreNS = "aidct_core";
35
+ /**
36
+ * Locale resources type is extracted from the English locale resources object.
37
+ */
38
+ export type CoreLocaleResources = typeof enLocaleResources;
39
+ /**
40
+ * Core resources.
41
+ */
42
+ export declare const coreResources: Resource;
43
+ export declare const i18nextCore: i18n;
44
+ /**
45
+ * Initialize internationalization.
46
+ *
47
+ * @param environment
48
+ * Environment in which the application is running.
49
+ *
50
+ * @param debug
51
+ * Debug setting.
52
+ */
53
+ export declare function i18nCoreInit(environment: I18nEnvironment, debug?: boolean): Promise<void>;
33
54
  /**
34
55
  * Initialize internationalization.
35
56
  *
@@ -48,9 +69,6 @@ export type I18nEnvironment = typeof I18nEnvironments[I18nEnvironmentKey];
48
69
  *
49
70
  * @param resources
50
71
  * Resources.
51
- *
52
- * @returns
53
- * Void promise.
54
72
  */
55
- export declare function i18nCoreInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void>;
73
+ export declare function i18nFinalizeInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void>;
56
74
  //# sourceMappingURL=i18n.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAA0B,QAAQ,EAAE,MAAM,SAAS,CAAC;AAItE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC;CAC3C;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;IACzB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEG,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;AAgB1E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiD1J"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,IAAI,EAA+B,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGzF,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AAGzD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC;CAC3C;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;IACzB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEG,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;AAgB1E,eAAO,MAAM,MAAM,eAAe,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,iBAAiB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,QAO3B,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,IAA+B,CAAC;AAE1D;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7F;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiD9J"}
@@ -1,5 +1,8 @@
1
+ import i18next from "i18next";
1
2
  import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
2
3
  import I18nextCLILanguageDetector from "i18next-cli-language-detector";
4
+ import enLocaleResources from "./en/locale-resources.js";
5
+ import frLocaleResources from "./fr/locale-resources.js";
3
6
  /**
4
7
  * Internationalization operating environments.
5
8
  */
@@ -28,7 +31,33 @@ export const I18nEnvironments = {
28
31
  */
29
32
  function toLowerCase(s) {
30
33
  // Words with no lower case letters are preserved as they are likely mnemonics.
31
- return s.split(" ").map(word => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
34
+ return s.split(" ").map(word => /[a-z]/u.test(word) ? word.toLowerCase() : word).join(" ");
35
+ }
36
+ export const coreNS = "aidct_core";
37
+ /**
38
+ * Core resources.
39
+ */
40
+ export const coreResources = {
41
+ en: {
42
+ aidct_core: enLocaleResources
43
+ },
44
+ fr: {
45
+ aidct_core: frLocaleResources
46
+ }
47
+ };
48
+ // Explicit type is necessary because type can't be inferred without additional references.
49
+ export const i18nextCore = i18next.createInstance();
50
+ /**
51
+ * Initialize internationalization.
52
+ *
53
+ * @param environment
54
+ * Environment in which the application is running.
55
+ *
56
+ * @param debug
57
+ * Debug setting.
58
+ */
59
+ export async function i18nCoreInit(environment, debug = false) {
60
+ await i18nFinalizeInit(i18nextCore, environment, debug, coreNS, coreResources);
32
61
  }
33
62
  /**
34
63
  * Initialize internationalization.
@@ -48,11 +77,8 @@ function toLowerCase(s) {
48
77
  *
49
78
  * @param resources
50
79
  * Resources.
51
- *
52
- * @returns
53
- * Void promise.
54
80
  */
55
- export async function i18nCoreInit(i18next, environment, debug, defaultNS, ...resources) {
81
+ export async function i18nFinalizeInit(i18next, environment, debug, defaultNS, ...resources) {
56
82
  // Initialization may be called more than once.
57
83
  if (!i18next.isInitialized) {
58
84
  const mergedResource = {};
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AACA,OAAO,8BAA8B,MAAM,kCAAkC,CAAC;AAC9E,OAAO,0BAA0B,MAAM,+BAA+B,CAAC;AASvE;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC5B;;OAEG;IACH,GAAG,EAAE,CAAC;IAEN;;OAEG;IACH,MAAM,EAAE,CAAC;IAET;;OAEG;IACH,OAAO,EAAE,CAAC;CACJ,CAAC;AAYX;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,CAAS;IAC1B,+EAA+E;IAC/E,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9F,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAa,EAAE,WAA4B,EAAE,KAAc,EAAE,SAAiB,EAAE,GAAG,SAAqB;IACvI,+CAA+C;IAC/C,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QACzB,MAAM,cAAc,GAAa,EAAE,CAAC;QAEpC,mBAAmB;QACnB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC/B,mBAAmB;YACnB,KAAK,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClE,IAAI,CAAC,CAAC,QAAQ,IAAI,cAAc,CAAC,EAAE,CAAC;oBAChC,cAAc,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBAClC,CAAC;gBAED,MAAM,sBAAsB,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAExD,oBAAoB;gBACpB,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;oBACtE,sBAAsB,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC;gBACpD,CAAC;YACL,CAAC;QACL,CAAC;QAED,IAAI,MAAyC,CAAC;QAE9C,QAAQ,WAAW,EAAE,CAAC;YAClB,KAAK,gBAAgB,CAAC,GAAG;gBACrB,gGAAgG;gBAChG,qFAAqF;gBACrF,MAAM,GAAG,0BAA+D,CAAC;gBACzE,MAAM;YAEV,KAAK,gBAAgB,CAAC,OAAO;gBACzB,MAAM,GAAG,8BAA8B,CAAC;gBACxC,MAAM;YAEV;gBACI,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YAC3B,KAAK;YACL,SAAS,EAAE,cAAc;YACzB,WAAW,EAAE,IAAI;YACjB,SAAS;SACZ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACT,4BAA4B;YAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5H,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,OAAkE,MAAM,SAAS,CAAC;AACzF,OAAO,8BAA8B,MAAM,kCAAkC,CAAC;AAC9E,OAAO,0BAA0B,MAAM,+BAA+B,CAAC;AACvE,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AACzD,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AASzD;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC5B;;OAEG;IACH,GAAG,EAAE,CAAC;IAEN;;OAEG;IACH,MAAM,EAAE,CAAC;IAET;;OAEG;IACH,OAAO,EAAE,CAAC;CACJ,CAAC;AAYX;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,CAAS;IAC1B,+EAA+E;IAC/E,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,CAAC;AAOnC;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAa;IACnC,EAAE,EAAE;QACA,UAAU,EAAE,iBAAiB;KAChC;IACD,EAAE,EAAE;QACA,UAAU,EAAE,iBAAiB;KAChC;CACJ,CAAC;AAEF,2FAA2F;AAC3F,MAAM,CAAC,MAAM,WAAW,GAAS,OAAO,CAAC,cAAc,EAAE,CAAC;AAE1D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAA4B,EAAE,KAAK,GAAG,KAAK;IAC1E,MAAM,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AACnF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAa,EAAE,WAA4B,EAAE,KAAc,EAAE,SAAiB,EAAE,GAAG,SAAqB;IAC3I,+CAA+C;IAC/C,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QACzB,MAAM,cAAc,GAAa,EAAE,CAAC;QAEpC,mBAAmB;QACnB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC/B,mBAAmB;YACnB,KAAK,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClE,IAAI,CAAC,CAAC,QAAQ,IAAI,cAAc,CAAC,EAAE,CAAC;oBAChC,cAAc,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBAClC,CAAC;gBAED,MAAM,sBAAsB,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAExD,oBAAoB;gBACpB,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;oBACtE,sBAAsB,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC;gBACpD,CAAC;YACL,CAAC;QACL,CAAC;QAED,IAAI,MAAyC,CAAC;QAE9C,QAAQ,WAAW,EAAE,CAAC;YAClB,KAAK,gBAAgB,CAAC,GAAG;gBACrB,gGAAgG;gBAChG,qFAAqF;gBACrF,MAAM,GAAG,0BAA+D,CAAC;gBACzE,MAAM;YAEV,KAAK,gBAAgB,CAAC,OAAO;gBACzB,MAAM,GAAG,8BAA8B,CAAC;gBACxC,MAAM;YAEV;gBACI,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YAC3B,KAAK;YACL,SAAS,EAAE,cAAc;YACzB,WAAW,EAAE,IAAI;YACjB,SAAS;SACZ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACT,4BAA4B;YAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5H,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
package/dist/logger.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Logger } from "tslog";
1
+ import { type ISettingsParam, Logger } from "tslog";
2
2
  /**
3
3
  * Log levels.
4
4
  */
@@ -20,13 +20,115 @@ export type LogLevelKey = keyof typeof LogLevels;
20
20
  */
21
21
  export type LogLevel = typeof LogLevels[LogLevelKey];
22
22
  /**
23
- * Get a simple logger with an optional log level.
23
+ * Get the log level enumeration value corresponding to a string or number.
24
+ *
25
+ * @param untypedLogLevel
26
+ * Untyped log level.
27
+ *
28
+ * @returns
29
+ * Typed log level or default `LogLevels.Info` if untyped log level not provided..
30
+ */
31
+ export declare function logLevelOf(untypedLogLevel?: string | number): LogLevel;
32
+ /**
33
+ * Get a logger with an optional log level. The underlying implementation is
34
+ * [`tslog`](https://tslog.js.org/).
24
35
  *
25
36
  * @param logLevel
26
- * Log level as enumeration value or string.
37
+ * Log level as enumeration value or string. Mapped to `minLevel` in settings.
38
+ *
39
+ * @param settings
40
+ * Detailed settings. See [`tslog`](https://tslog.js.org/#/?id=settings) documentation for details.
41
+ *
42
+ * @param logObj
43
+ * Default log object. See [`tslog`](https://tslog.js.org/#/?id=defining-and-accessing-logobj) documentation for
44
+ * details.
27
45
  *
28
46
  * @returns
29
47
  * Logger.
48
+ *
49
+ * @template T
50
+ * Log object type.
51
+ */
52
+ export declare function getLogger<T extends object = object>(logLevel?: string | number, settings?: ISettingsParam<T>, logObj?: T): Logger<T>;
53
+ /**
54
+ * Get a loggable representation of a value. Values are returned unmodified, except as follows:
55
+ *
56
+ * - Big integers are converted to whole numbers where possible, otherwise as their decimal string representations.
57
+ * - Arrays are limited to a maximum of ten elements. Any array longer than ten elements is replaced with the first four
58
+ * elements, a string of three dots, and the last four elements. This may still create large results for
59
+ * multidimensional arrays.
60
+ * - Errors are converted to objects with `name`, `message`, and `stack` properties.
61
+ * - Symbols are converted to their string representations.
62
+ * - Functions are converted to strings of the form `Function(name)`.
63
+ *
64
+ * @param value
65
+ * Value.
66
+ *
67
+ * @returns
68
+ * Loggable value.
69
+ */
70
+ export declare function loggableValue(value: unknown): unknown;
71
+ /**
72
+ * Logger transport that stores messages in memory.
30
73
  */
31
- export declare function getLogger(logLevel?: string | number): Logger<unknown>;
74
+ export declare class MemoryTransport<T extends object> {
75
+ #private;
76
+ /**
77
+ * Constructor.
78
+ *
79
+ * @param logger
80
+ * Logger.
81
+ *
82
+ * @param maximumLength
83
+ * Maximum length of messages array.
84
+ *
85
+ * @param truncateLength
86
+ * Length to which messages array is truncated when maximum is reached. Default is 50% of `maximumLength`, maximum
87
+ * is 80% of `maximumLength`.
88
+ */
89
+ constructor(logger: Logger<T>, maximumLength: number, truncateLength?: number);
90
+ /**
91
+ * Get the messages.
92
+ */
93
+ get messages(): string[];
94
+ /**
95
+ * Get the maximum length of messages array.
96
+ */
97
+ get maximumLength(): number;
98
+ /**
99
+ * Get the length to which messages array is truncated when maximum is reached.
100
+ */
101
+ get truncateLength(): number;
102
+ /**
103
+ * Add a notification callback. If one already exists under the current name, do nothing.
104
+ *
105
+ * @param name
106
+ * Callback name.
107
+ *
108
+ * @param notificationCallback
109
+ * Callback.
110
+ *
111
+ * @returns
112
+ * True if successfully added.
113
+ */
114
+ addNotificationCallback(name: string, notificationCallback: (message: string | undefined, messages: readonly string[]) => void): boolean;
115
+ /**
116
+ * Remove a notification callback.
117
+ *
118
+ * @param name
119
+ * Callback name.
120
+ */
121
+ removeNotificationCallback(name: string): void;
122
+ /**
123
+ * Resize the messages array.
124
+ *
125
+ * @param maximumLength
126
+ * Maximum length of messages array.
127
+ *
128
+ * @param truncateLength
129
+ * Length to which messages array is truncated when maximum is reached. Default is 50% of `maximumLength`, maximum
130
+ * is 80% of `maximumLength`.
131
+ */
132
+ resize(maximumLength: number, truncateLength?: number): void;
133
+ }
32
134
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;CAQZ,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,SAAS,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC,WAAW,CAAC,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAiBrE"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAGpD;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;CAQZ,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,SAAS,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC,WAAW,CAAC,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CA2BtE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAKpI;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA4CrD;AAED;;GAEG;AACH,qBAAa,eAAe,CAAC,CAAC,SAAS,MAAM;;IAqBzC;;;;;;;;;;;;OAYG;gBACS,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM;IAoB7E;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,EAAE,CAEvB;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;;;;;;;;;;OAWG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,GAAG,OAAO;IAaxI;;;;;OAKG;IACH,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9C;;;;;;;;;OASG;IACH,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI;CAI/D"}
package/dist/logger.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Logger } from "tslog";
2
+ import { i18nextCore } from "./locale/i18n.js";
2
3
  /**
3
4
  * Log levels.
4
5
  */
@@ -12,30 +13,238 @@ export const LogLevels = {
12
13
  Fatal: 6
13
14
  };
14
15
  /**
15
- * Get a simple logger with an optional log level.
16
+ * Get the log level enumeration value corresponding to a string or number.
16
17
  *
17
- * @param logLevel
18
- * Log level as enumeration value or string.
18
+ * @param untypedLogLevel
19
+ * Untyped log level.
19
20
  *
20
21
  * @returns
21
- * Logger.
22
+ * Typed log level or default `LogLevels.Info` if untyped log level not provided..
22
23
  */
23
- export function getLogger(logLevel) {
24
- let minLevel;
25
- if (typeof logLevel === "string") {
26
- if (logLevel in LogLevels) {
24
+ export function logLevelOf(untypedLogLevel) {
25
+ let typedLogLevel;
26
+ if (typeof untypedLogLevel === "string") {
27
+ if (untypedLogLevel in LogLevels) {
27
28
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- String exists as a key.
28
- minLevel = LogLevels[logLevel];
29
+ typedLogLevel = LogLevels[untypedLogLevel];
29
30
  }
30
31
  else {
31
- throw new Error(`Unknown log level ${logLevel}`);
32
+ throw new RangeError(i18nextCore.t("Logger.unknownLogLevel", {
33
+ logLevel: untypedLogLevel
34
+ }));
35
+ }
36
+ }
37
+ else if (untypedLogLevel !== undefined) {
38
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assume that valid log level has been provided.
39
+ if (Object.values(LogLevels).includes(untypedLogLevel)) {
40
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Valid log level has been provided.
41
+ typedLogLevel = untypedLogLevel;
42
+ }
43
+ else {
44
+ throw new RangeError(i18nextCore.t("Logger.unknownLogLevel", {
45
+ logLevel: untypedLogLevel
46
+ }));
32
47
  }
33
48
  }
34
49
  else {
35
- minLevel = logLevel ?? LogLevels.Info;
50
+ typedLogLevel = LogLevels.Info;
36
51
  }
52
+ return typedLogLevel;
53
+ }
54
+ /**
55
+ * Get a logger with an optional log level. The underlying implementation is
56
+ * [`tslog`](https://tslog.js.org/).
57
+ *
58
+ * @param logLevel
59
+ * Log level as enumeration value or string. Mapped to `minLevel` in settings.
60
+ *
61
+ * @param settings
62
+ * Detailed settings. See [`tslog`](https://tslog.js.org/#/?id=settings) documentation for details.
63
+ *
64
+ * @param logObj
65
+ * Default log object. See [`tslog`](https://tslog.js.org/#/?id=defining-and-accessing-logobj) documentation for
66
+ * details.
67
+ *
68
+ * @returns
69
+ * Logger.
70
+ *
71
+ * @template T
72
+ * Log object type.
73
+ */
74
+ export function getLogger(logLevel, settings, logObj) {
37
75
  return new Logger({
38
- minLevel
39
- });
76
+ ...settings ?? {},
77
+ minLevel: logLevelOf(logLevel)
78
+ }, logObj);
79
+ }
80
+ /**
81
+ * Get a loggable representation of a value. Values are returned unmodified, except as follows:
82
+ *
83
+ * - Big integers are converted to whole numbers where possible, otherwise as their decimal string representations.
84
+ * - Arrays are limited to a maximum of ten elements. Any array longer than ten elements is replaced with the first four
85
+ * elements, a string of three dots, and the last four elements. This may still create large results for
86
+ * multidimensional arrays.
87
+ * - Errors are converted to objects with `name`, `message`, and `stack` properties.
88
+ * - Symbols are converted to their string representations.
89
+ * - Functions are converted to strings of the form `Function(name)`.
90
+ *
91
+ * @param value
92
+ * Value.
93
+ *
94
+ * @returns
95
+ * Loggable value.
96
+ */
97
+ export function loggableValue(value) {
98
+ let replacementValue;
99
+ switch (typeof value) {
100
+ case "string":
101
+ case "number":
102
+ case "boolean":
103
+ case "undefined":
104
+ replacementValue = value;
105
+ break;
106
+ case "bigint":
107
+ // Big integers not supported in JSON.
108
+ replacementValue = value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER ? Number(value) : value.toString(10);
109
+ break;
110
+ case "object":
111
+ if (value === null) {
112
+ replacementValue = value;
113
+ }
114
+ else if (Array.isArray(value)) {
115
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Slicing array is necessary to keep log size down.
116
+ replacementValue = (value.length <= 10 ? value : [...value.slice(0, 4), "...", ...value.slice(-4)]).map(entry => loggableValue(entry));
117
+ }
118
+ else if (value instanceof Error) {
119
+ replacementValue = loggableValue({
120
+ name: value.name,
121
+ message: value.message,
122
+ stack: value.stack?.split("\n")
123
+ });
124
+ }
125
+ else {
126
+ // Apply recursively to all properties of the object.
127
+ replacementValue = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, loggableValue(v)]));
128
+ }
129
+ break;
130
+ case "symbol":
131
+ replacementValue = value.toString();
132
+ break;
133
+ case "function":
134
+ replacementValue = `Function(${value.name})`;
135
+ break;
136
+ }
137
+ return replacementValue;
138
+ }
139
+ /**
140
+ * Logger transport that stores messages in memory.
141
+ */
142
+ export class MemoryTransport {
143
+ /**
144
+ * Notification callbacks map.
145
+ */
146
+ #notificationCallbacksMap = new Map();
147
+ /**
148
+ * Messages.
149
+ */
150
+ #messages = [];
151
+ /**
152
+ * Maximum length of messages array.
153
+ */
154
+ #maximumLength = 0;
155
+ /**
156
+ * Length to which messages array is truncated when maximum is reached.
157
+ */
158
+ #truncateLength = 0;
159
+ /**
160
+ * Constructor.
161
+ *
162
+ * @param logger
163
+ * Logger.
164
+ *
165
+ * @param maximumLength
166
+ * Maximum length of messages array.
167
+ *
168
+ * @param truncateLength
169
+ * Length to which messages array is truncated when maximum is reached. Default is 50% of `maximumLength`, maximum
170
+ * is 80% of `maximumLength`.
171
+ */
172
+ constructor(logger, maximumLength, truncateLength) {
173
+ this.resize(maximumLength, truncateLength);
174
+ logger.attachTransport((logObject) => {
175
+ // Truncate logger messages if necessary.
176
+ if (this.#messages.length >= this.#maximumLength) {
177
+ this.#messages.splice(0, this.#maximumLength - this.#truncateLength);
178
+ }
179
+ const message = JSON.stringify(logObject);
180
+ this.#messages.push(message);
181
+ // Notify all registered callbacks.
182
+ for (const notificationCallback of this.#notificationCallbacksMap.values()) {
183
+ notificationCallback(message, this.#messages);
184
+ }
185
+ });
186
+ }
187
+ /**
188
+ * Get the messages.
189
+ */
190
+ get messages() {
191
+ return this.#messages;
192
+ }
193
+ /**
194
+ * Get the maximum length of messages array.
195
+ */
196
+ get maximumLength() {
197
+ return this.#maximumLength;
198
+ }
199
+ /**
200
+ * Get the length to which messages array is truncated when maximum is reached.
201
+ */
202
+ get truncateLength() {
203
+ return this.#truncateLength;
204
+ }
205
+ /**
206
+ * Add a notification callback. If one already exists under the current name, do nothing.
207
+ *
208
+ * @param name
209
+ * Callback name.
210
+ *
211
+ * @param notificationCallback
212
+ * Callback.
213
+ *
214
+ * @returns
215
+ * True if successfully added.
216
+ */
217
+ addNotificationCallback(name, notificationCallback) {
218
+ const added = !this.#notificationCallbacksMap.has(name);
219
+ if (added) {
220
+ this.#notificationCallbacksMap.set(name, notificationCallback);
221
+ // Notify with existing messages.
222
+ notificationCallback(undefined, this.#messages);
223
+ }
224
+ return added;
225
+ }
226
+ /**
227
+ * Remove a notification callback.
228
+ *
229
+ * @param name
230
+ * Callback name.
231
+ */
232
+ removeNotificationCallback(name) {
233
+ this.#notificationCallbacksMap.delete(name);
234
+ }
235
+ /**
236
+ * Resize the messages array.
237
+ *
238
+ * @param maximumLength
239
+ * Maximum length of messages array.
240
+ *
241
+ * @param truncateLength
242
+ * Length to which messages array is truncated when maximum is reached. Default is 50% of `maximumLength`, maximum
243
+ * is 80% of `maximumLength`.
244
+ */
245
+ resize(maximumLength, truncateLength) {
246
+ this.#maximumLength = maximumLength;
247
+ this.#truncateLength = truncateLength !== undefined ? Math.min(truncateLength, Math.floor(maximumLength * 0.8)) : Math.floor(maximumLength / 2);
248
+ }
40
249
  }
41
250
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/B;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACrB,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACF,CAAC;AAYX;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,QAA0B;IAChD,IAAI,QAAgB,CAAC;IAErB,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YACxB,kGAAkG;YAClG,QAAQ,GAAG,SAAS,CAAC,QAAuB,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;QACrD,CAAC;IACL,CAAC;SAAM,CAAC;QACJ,QAAQ,GAAG,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC;IAC1C,CAAC;IAED,OAAO,IAAI,MAAM,CAAC;QACd,QAAQ;KACX,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
package/dist/type.d.ts CHANGED
@@ -49,6 +49,11 @@ export type TypedConstructor<TConstructor extends abstract new (...args: Constru
49
49
  * Constructor type.
50
50
  */
51
51
  export type TypedAbstractConstructor<TConstructor extends abstract new (...args: ConstructorParameters<TConstructor>) => InstanceType<TConstructor>> = AbstractConstructor<ConstructorParameters<TConstructor>, InstanceType<TConstructor>>;
52
+ /**
53
+ * Promisable type. Extends a type by allowing a {@linkcode Promise} of the same type. Typically used in abstract method
54
+ * declarations where the implementing class may or may not implement the method as asynchronous.
55
+ */
56
+ export type Promisable<T> = T | Promise<T>;
52
57
  /**
53
58
  * Determine the fundamental promised type. This is stricter than `Awaited<Type>` in that it requires a {@linkcode
54
59
  * Promise}.
@@ -1 +1 @@
1
- {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CAAC,SAAS,SAAS,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,UAAU,CAAC,SAAS,CAAC,CAAC;AAEnK;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAAC,SAAS,SAAS,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;AAEtK;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,CACnB,sBAAsB,SAAS,OAAO,EAAE,EACxC,oBAAoB,IACpB,KAAK,GAAG,IAAI,EAAE,sBAAsB,KAAK,oBAAoB,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,CAC3B,sBAAsB,SAAS,OAAO,EAAE,EACxC,oBAAoB,IACpB,QAAQ,MAAM,GAAG,IAAI,EAAE,sBAAsB,KAAK,oBAAoB,CAAC;AAE3E;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,CAAC,YAAY,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,qBAAqB,CAAC,YAAY,CAAC,KAAK,YAAY,CAAC,YAAY,CAAC,IACvI,WAAW,CAAC,qBAAqB,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;AAEjF;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,CAAC,YAAY,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,qBAAqB,CAAC,YAAY,CAAC,KAAK,YAAY,CAAC,YAAY,CAAC,IAC/I,mBAAmB,CAAC,qBAAqB,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;AAEzF;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,SAAS,CAAC,CAAC,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7F;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,CAAC,OAAO,SAAS,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhN;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG;KAC9C,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACzC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAEnB;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAE9E;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,IAAI;KAC5B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,KAAK;CACxE,CAAC,MAAM,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aidc-toolkit/core",
3
- "version": "1.0.31-beta",
3
+ "version": "1.0.32-beta",
4
4
  "description": "Core functionality for AIDC Toolkit",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,10 +26,10 @@
26
26
  "build:doc": "npm run build:dev"
27
27
  },
28
28
  "devDependencies": {
29
- "@aidc-toolkit/dev": "1.0.31-beta"
29
+ "@aidc-toolkit/dev": "1.0.32-beta"
30
30
  },
31
31
  "dependencies": {
32
- "i18next": "^25.7.2",
32
+ "i18next": "^25.7.4",
33
33
  "i18next-browser-languagedetector": "^8.2.0",
34
34
  "i18next-cli-language-detector": "^1.1.8",
35
35
  "tslog": "^4.10.2"
package/src/cache.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type { Promisable } from "./type.js";
2
+
3
+ /**
4
+ * Generic cache. Typically used to manage a local copy of remote data that is not refreshed regularly.
5
+ *
6
+ * @template TCache
7
+ * Type of cached data.
8
+ *
9
+ * @template TSource
10
+ * Type of source data. The type may be different from the cached data type if a transformation is required.
11
+ */
12
+ export abstract class Cache<TCache, TSource = TCache> {
13
+ /**
14
+ * Get the date/time at or after which the source should be checked for updates. If the value is undefined, this is
15
+ * the first usage.
16
+ */
17
+ abstract get nextCheckDateTime(): Promisable<Date | undefined>;
18
+
19
+ /**
20
+ * Get the date/time at which the cache was last updated. This may more accurately reflect the date/time at which
21
+ * the last source retrieved was updated. If the value is undefined, there is no data in the cache.
22
+ */
23
+ abstract get cacheDateTime(): Promisable<Date | undefined>;
24
+
25
+ /**
26
+ * Get the cache data. This should only ever be called if the cache date/time is defined.
27
+ */
28
+ abstract get cacheData(): Promisable<TCache>;
29
+
30
+ /**
31
+ * Get the date/time at which the source was last updated. This should not be called unless the next check date/time
32
+ * has passed, as it may trigger an expensive remote retrieval.
33
+ */
34
+ abstract get sourceDateTime(): Promisable<Date>;
35
+
36
+ /**
37
+ * Get the source data. This should not be called unless the next check date/time has passed, as it may trigger an
38
+ * expensive remote retrieval.
39
+ */
40
+ abstract get sourceData(): Promisable<TSource>;
41
+
42
+ /**
43
+ * Update the cache with only the next check date/time. The cache date/time and cache data must not be modified.
44
+ * This is typically called when the cache is up to date with the source or source retrieval has failed.
45
+ *
46
+ * @param nextCheckDateTime
47
+ * Next check date/time.
48
+ */
49
+ abstract update(nextCheckDateTime: Date): Promisable<void>;
50
+
51
+ /**
52
+ * Update all cache parameters. This is typically called when the cache is updated from the source.
53
+ *
54
+ * @param nextCheckDateTime
55
+ * Next check date/time.
56
+ *
57
+ * @param cacheDateTime
58
+ * Cache date/time.
59
+ *
60
+ * @param cacheData
61
+ * Cache data.
62
+ */
63
+ abstract update(nextCheckDateTime: Date, cacheDateTime: Date, cacheData: TCache): Promisable<void>;
64
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Hyperlink.
3
+ */
4
+ export interface Hyperlink {
5
+ /**
6
+ * Reference, relative or absolute depending on the application.
7
+ */
8
+ readonly reference: string;
9
+
10
+ /**
11
+ * Human-readable text.
12
+ */
13
+ readonly text?: string | undefined;
14
+
15
+ /**
16
+ * Additional details.
17
+ */
18
+ readonly details?: string | undefined;
19
+ }
package/src/index.ts CHANGED
@@ -16,5 +16,10 @@
16
16
  */
17
17
  export type * from "./type.js";
18
18
  export * from "./type-helper.js";
19
+
19
20
  export * from "./logger.js";
21
+
22
+ export * from "./cache.js";
23
+ export type * from "./hyperlink.js";
24
+
20
25
  export * from "./locale/i18n.js";
@@ -0,0 +1,5 @@
1
+ export default {
2
+ Logger: {
3
+ unknownLogLevel: "Unknown log level \"{{logLevel}}\""
4
+ }
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ Logger: {
3
+ unknownLogLevel: "Niveau de journalisation inconnu «{{logLevel}}»"
4
+ }
5
+ };
@@ -1,6 +1,8 @@
1
- import type { i18n, LanguageDetectorModule, Resource } from "i18next";
1
+ import i18next, { type i18n, type LanguageDetectorModule, type Resource } from "i18next";
2
2
  import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
3
3
  import I18nextCLILanguageDetector from "i18next-cli-language-detector";
4
+ import enLocaleResources from "./en/locale-resources.js";
5
+ import frLocaleResources from "./fr/locale-resources.js";
4
6
 
5
7
  /**
6
8
  * Locale strings type for generic manipulation.
@@ -50,7 +52,42 @@ export type I18nEnvironment = typeof I18nEnvironments[I18nEnvironmentKey];
50
52
  */
51
53
  function toLowerCase(s: string): string {
52
54
  // Words with no lower case letters are preserved as they are likely mnemonics.
53
- return s.split(" ").map(word => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
55
+ return s.split(" ").map(word => /[a-z]/u.test(word) ? word.toLowerCase() : word).join(" ");
56
+ }
57
+
58
+ export const coreNS = "aidct_core";
59
+
60
+ /**
61
+ * Locale resources type is extracted from the English locale resources object.
62
+ */
63
+ export type CoreLocaleResources = typeof enLocaleResources;
64
+
65
+ /**
66
+ * Core resources.
67
+ */
68
+ export const coreResources: Resource = {
69
+ en: {
70
+ aidct_core: enLocaleResources
71
+ },
72
+ fr: {
73
+ aidct_core: frLocaleResources
74
+ }
75
+ };
76
+
77
+ // Explicit type is necessary because type can't be inferred without additional references.
78
+ export const i18nextCore: i18n = i18next.createInstance();
79
+
80
+ /**
81
+ * Initialize internationalization.
82
+ *
83
+ * @param environment
84
+ * Environment in which the application is running.
85
+ *
86
+ * @param debug
87
+ * Debug setting.
88
+ */
89
+ export async function i18nCoreInit(environment: I18nEnvironment, debug = false): Promise<void> {
90
+ await i18nFinalizeInit(i18nextCore, environment, debug, coreNS, coreResources);
54
91
  }
55
92
 
56
93
  /**
@@ -71,11 +108,8 @@ function toLowerCase(s: string): string {
71
108
  *
72
109
  * @param resources
73
110
  * Resources.
74
- *
75
- * @returns
76
- * Void promise.
77
111
  */
78
- export async function i18nCoreInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void> {
112
+ export async function i18nFinalizeInit(i18next: i18n, environment: I18nEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void> {
79
113
  // Initialization may be called more than once.
80
114
  if (!i18next.isInitialized) {
81
115
  const mergedResource: Resource = {};
@@ -0,0 +1,16 @@
1
+ import type { CoreLocaleResources } from "./i18n.js";
2
+
3
+ /**
4
+ * Internationalization module.
5
+ */
6
+ declare module "i18next" {
7
+ /**
8
+ * Custom type options for this package.
9
+ */
10
+ interface CustomTypeOptions {
11
+ defaultNS: "aidct_core";
12
+ resources: {
13
+ aidct_core: CoreLocaleResources;
14
+ };
15
+ }
16
+ }
package/src/logger.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Logger } from "tslog";
1
+ import { type ISettingsParam, Logger } from "tslog";
2
+ import { i18nextCore } from "./locale/i18n.js";
2
3
 
3
4
  /**
4
5
  * Log levels.
@@ -24,29 +25,258 @@ export type LogLevelKey = keyof typeof LogLevels;
24
25
  export type LogLevel = typeof LogLevels[LogLevelKey];
25
26
 
26
27
  /**
27
- * Get a simple logger with an optional log level.
28
+ * Get the log level enumeration value corresponding to a string or number.
28
29
  *
29
- * @param logLevel
30
- * Log level as enumeration value or string.
30
+ * @param untypedLogLevel
31
+ * Untyped log level.
31
32
  *
32
33
  * @returns
33
- * Logger.
34
+ * Typed log level or default `LogLevels.Info` if untyped log level not provided..
34
35
  */
35
- export function getLogger(logLevel?: string | number): Logger<unknown> {
36
- let minLevel: number;
36
+ export function logLevelOf(untypedLogLevel?: string | number): LogLevel {
37
+ let typedLogLevel: LogLevel;
37
38
 
38
- if (typeof logLevel === "string") {
39
- if (logLevel in LogLevels) {
39
+ if (typeof untypedLogLevel === "string") {
40
+ if (untypedLogLevel in LogLevels) {
40
41
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- String exists as a key.
41
- minLevel = LogLevels[logLevel as LogLevelKey];
42
+ typedLogLevel = LogLevels[untypedLogLevel as LogLevelKey];
43
+ } else {
44
+ throw new RangeError(i18nextCore.t("Logger.unknownLogLevel", {
45
+ logLevel: untypedLogLevel
46
+ }));
47
+ }
48
+ } else if (untypedLogLevel !== undefined) {
49
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assume that valid log level has been provided.
50
+ if (Object.values(LogLevels).includes(untypedLogLevel as LogLevel)) {
51
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Valid log level has been provided.
52
+ typedLogLevel = untypedLogLevel as LogLevel;
42
53
  } else {
43
- throw new Error(`Unknown log level ${logLevel}`);
54
+ throw new RangeError(i18nextCore.t("Logger.unknownLogLevel", {
55
+ logLevel: untypedLogLevel
56
+ }));
44
57
  }
45
58
  } else {
46
- minLevel = logLevel ?? LogLevels.Info;
59
+ typedLogLevel = LogLevels.Info;
47
60
  }
48
61
 
62
+ return typedLogLevel;
63
+ }
64
+
65
+ /**
66
+ * Get a logger with an optional log level. The underlying implementation is
67
+ * [`tslog`](https://tslog.js.org/).
68
+ *
69
+ * @param logLevel
70
+ * Log level as enumeration value or string. Mapped to `minLevel` in settings.
71
+ *
72
+ * @param settings
73
+ * Detailed settings. See [`tslog`](https://tslog.js.org/#/?id=settings) documentation for details.
74
+ *
75
+ * @param logObj
76
+ * Default log object. See [`tslog`](https://tslog.js.org/#/?id=defining-and-accessing-logobj) documentation for
77
+ * details.
78
+ *
79
+ * @returns
80
+ * Logger.
81
+ *
82
+ * @template T
83
+ * Log object type.
84
+ */
85
+ export function getLogger<T extends object = object>(logLevel?: string | number, settings?: ISettingsParam<T>, logObj?: T): Logger<T> {
49
86
  return new Logger({
50
- minLevel
51
- });
87
+ ...settings ?? {},
88
+ minLevel: logLevelOf(logLevel)
89
+ }, logObj);
90
+ }
91
+
92
+ /**
93
+ * Get a loggable representation of a value. Values are returned unmodified, except as follows:
94
+ *
95
+ * - Big integers are converted to whole numbers where possible, otherwise as their decimal string representations.
96
+ * - Arrays are limited to a maximum of ten elements. Any array longer than ten elements is replaced with the first four
97
+ * elements, a string of three dots, and the last four elements. This may still create large results for
98
+ * multidimensional arrays.
99
+ * - Errors are converted to objects with `name`, `message`, and `stack` properties.
100
+ * - Symbols are converted to their string representations.
101
+ * - Functions are converted to strings of the form `Function(name)`.
102
+ *
103
+ * @param value
104
+ * Value.
105
+ *
106
+ * @returns
107
+ * Loggable value.
108
+ */
109
+ export function loggableValue(value: unknown): unknown {
110
+ let replacementValue: unknown;
111
+
112
+ switch (typeof value) {
113
+ case "string":
114
+ case "number":
115
+ case "boolean":
116
+ case "undefined":
117
+ replacementValue = value;
118
+ break;
119
+
120
+ case "bigint":
121
+ // Big integers not supported in JSON.
122
+ replacementValue = value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER ? Number(value) : value.toString(10);
123
+ break;
124
+
125
+ case "object":
126
+ if (value === null) {
127
+ replacementValue = value;
128
+ } else if (Array.isArray(value)) {
129
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Slicing array is necessary to keep log size down.
130
+ replacementValue = (value.length <= 10 ? value : [...value.slice(0, 4), "...", ...value.slice(-4)]).map(entry => loggableValue(entry));
131
+ } else if (value instanceof Error) {
132
+ replacementValue = loggableValue({
133
+ name: value.name,
134
+ message: value.message,
135
+ stack: value.stack?.split("\n")
136
+ });
137
+ } else {
138
+ // Apply recursively to all properties of the object.
139
+ replacementValue = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, loggableValue(v)]));
140
+ }
141
+ break;
142
+
143
+ case "symbol":
144
+ replacementValue = value.toString();
145
+ break;
146
+
147
+ case "function":
148
+ replacementValue = `Function(${value.name})`;
149
+ break;
150
+ }
151
+
152
+ return replacementValue;
153
+ }
154
+
155
+ /**
156
+ * Logger transport that stores messages in memory.
157
+ */
158
+ export class MemoryTransport<T extends object> {
159
+ /**
160
+ * Notification callbacks map.
161
+ */
162
+ readonly #notificationCallbacksMap = new Map<string, (message: string | undefined, messages: readonly string[]) => void>();
163
+
164
+ /**
165
+ * Messages.
166
+ */
167
+ readonly #messages: string[] = [];
168
+
169
+ /**
170
+ * Maximum length of messages array.
171
+ */
172
+ #maximumLength = 0;
173
+
174
+ /**
175
+ * Length to which messages array is truncated when maximum is reached.
176
+ */
177
+ #truncateLength = 0;
178
+
179
+ /**
180
+ * Constructor.
181
+ *
182
+ * @param logger
183
+ * Logger.
184
+ *
185
+ * @param maximumLength
186
+ * Maximum length of messages array.
187
+ *
188
+ * @param truncateLength
189
+ * Length to which messages array is truncated when maximum is reached. Default is 50% of `maximumLength`, maximum
190
+ * is 80% of `maximumLength`.
191
+ */
192
+ constructor(logger: Logger<T>, maximumLength: number, truncateLength?: number) {
193
+ this.resize(maximumLength, truncateLength);
194
+
195
+ logger.attachTransport((logObject) => {
196
+ // Truncate logger messages if necessary.
197
+ if (this.#messages.length >= this.#maximumLength) {
198
+ this.#messages.splice(0, this.#maximumLength - this.#truncateLength);
199
+ }
200
+
201
+ const message = JSON.stringify(logObject);
202
+
203
+ this.#messages.push(message);
204
+
205
+ // Notify all registered callbacks.
206
+ for (const notificationCallback of this.#notificationCallbacksMap.values()) {
207
+ notificationCallback(message, this.#messages);
208
+ }
209
+ });
210
+ }
211
+
212
+ /**
213
+ * Get the messages.
214
+ */
215
+ get messages(): string[] {
216
+ return this.#messages;
217
+ }
218
+
219
+ /**
220
+ * Get the maximum length of messages array.
221
+ */
222
+ get maximumLength(): number {
223
+ return this.#maximumLength;
224
+ }
225
+
226
+ /**
227
+ * Get the length to which messages array is truncated when maximum is reached.
228
+ */
229
+ get truncateLength(): number {
230
+ return this.#truncateLength;
231
+ }
232
+
233
+ /**
234
+ * Add a notification callback. If one already exists under the current name, do nothing.
235
+ *
236
+ * @param name
237
+ * Callback name.
238
+ *
239
+ * @param notificationCallback
240
+ * Callback.
241
+ *
242
+ * @returns
243
+ * True if successfully added.
244
+ */
245
+ addNotificationCallback(name: string, notificationCallback: (message: string | undefined, messages: readonly string[]) => void): boolean {
246
+ const added = !this.#notificationCallbacksMap.has(name);
247
+
248
+ if (added) {
249
+ this.#notificationCallbacksMap.set(name, notificationCallback);
250
+
251
+ // Notify with existing messages.
252
+ notificationCallback(undefined, this.#messages);
253
+ }
254
+
255
+ return added;
256
+ }
257
+
258
+ /**
259
+ * Remove a notification callback.
260
+ *
261
+ * @param name
262
+ * Callback name.
263
+ */
264
+ removeNotificationCallback(name: string): void {
265
+ this.#notificationCallbacksMap.delete(name);
266
+ }
267
+
268
+ /**
269
+ * Resize the messages array.
270
+ *
271
+ * @param maximumLength
272
+ * Maximum length of messages array.
273
+ *
274
+ * @param truncateLength
275
+ * Length to which messages array is truncated when maximum is reached. Default is 50% of `maximumLength`, maximum
276
+ * is 80% of `maximumLength`.
277
+ */
278
+ resize(maximumLength: number, truncateLength?: number): void {
279
+ this.#maximumLength = maximumLength;
280
+ this.#truncateLength = truncateLength !== undefined ? Math.min(truncateLength, Math.floor(maximumLength * 0.8)) : Math.floor(maximumLength / 2);
281
+ }
52
282
  }
package/src/type.ts CHANGED
@@ -63,6 +63,12 @@ export type TypedConstructor<TConstructor extends abstract new (...args: Constru
63
63
  export type TypedAbstractConstructor<TConstructor extends abstract new (...args: ConstructorParameters<TConstructor>) => InstanceType<TConstructor>> =
64
64
  AbstractConstructor<ConstructorParameters<TConstructor>, InstanceType<TConstructor>>;
65
65
 
66
+ /**
67
+ * Promisable type. Extends a type by allowing a {@linkcode Promise} of the same type. Typically used in abstract method
68
+ * declarations where the implementing class may or may not implement the method as asynchronous.
69
+ */
70
+ export type Promisable<T> = T | Promise<T>;
71
+
66
72
  /**
67
73
  * Determine the fundamental promised type. This is stricter than `Awaited<Type>` in that it requires a {@linkcode
68
74
  * Promise}.