@bitblit/ratchet-common 6.0.146-alpha → 6.0.148-alpha

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 (140) hide show
  1. package/package.json +2 -1
  2. package/src/2d/line-2d.ts +6 -0
  3. package/src/2d/matrix-factory.ts +94 -0
  4. package/src/2d/plane-2d-type.ts +6 -0
  5. package/src/2d/plane-2d.ts +7 -0
  6. package/src/2d/point-2d.ts +4 -0
  7. package/src/2d/poly-line-2d.ts +5 -0
  8. package/src/2d/ratchet-2d.spec.ts +205 -0
  9. package/src/2d/ratchet-2d.ts +350 -0
  10. package/src/2d/transformation-matrix.ts +19 -0
  11. package/src/build/build-information.ts +8 -0
  12. package/src/build/ratchet-common-info.ts +19 -0
  13. package/src/histogram/histogram-entry.ts +4 -0
  14. package/src/histogram/histogram.spec.ts +25 -0
  15. package/src/histogram/histogram.ts +61 -0
  16. package/src/jwt/common-jwt-token.ts +17 -0
  17. package/src/jwt/expired-jwt-handling.ts +5 -0
  18. package/src/jwt/jwt-decode-only-ratchet.ts +26 -0
  19. package/src/jwt/jwt-payload-expiration-ratchet.ts +45 -0
  20. package/src/jwt/jwt-token-base.ts +14 -0
  21. package/src/lang/array-ratchet.spec.ts +79 -0
  22. package/src/lang/array-ratchet.ts +141 -0
  23. package/src/lang/base64-ratchet.spec.ts +48 -0
  24. package/src/lang/base64-ratchet.ts +247 -0
  25. package/src/lang/boolean-ratchet.spec.ts +95 -0
  26. package/src/lang/boolean-ratchet.ts +52 -0
  27. package/src/lang/composite-last-success-provider.spec.ts +31 -0
  28. package/src/lang/composite-last-success-provider.ts +30 -0
  29. package/src/lang/currency-ratchet.ts +29 -0
  30. package/src/lang/date-ratchet.spec.ts +27 -0
  31. package/src/lang/date-ratchet.ts +42 -0
  32. package/src/lang/duration-ratchet.spec.ts +47 -0
  33. package/src/lang/duration-ratchet.ts +77 -0
  34. package/src/lang/enum-ratchet.spec.ts +45 -0
  35. package/src/lang/enum-ratchet.ts +41 -0
  36. package/src/lang/error-handling-approach.ts +6 -0
  37. package/src/lang/error-ratchet.spec.ts +25 -0
  38. package/src/lang/error-ratchet.ts +70 -0
  39. package/src/lang/esm-ratchet.ts +81 -0
  40. package/src/lang/expiring-object.spec.ts +56 -0
  41. package/src/lang/expiring-object.ts +84 -0
  42. package/src/lang/geolocation-ratchet.spec.ts +177 -0
  43. package/src/lang/geolocation-ratchet.ts +341 -0
  44. package/src/lang/global-ratchet.spec.ts +17 -0
  45. package/src/lang/global-ratchet.ts +105 -0
  46. package/src/lang/key-value.ts +8 -0
  47. package/src/lang/last-success-provider.ts +4 -0
  48. package/src/lang/map-ratchet.spec.ts +113 -0
  49. package/src/lang/map-ratchet.ts +220 -0
  50. package/src/lang/no.spec.ts +9 -0
  51. package/src/lang/no.ts +7 -0
  52. package/src/lang/number-ratchet.spec.ts +154 -0
  53. package/src/lang/number-ratchet.ts +253 -0
  54. package/src/lang/parsed-url.ts +10 -0
  55. package/src/lang/promise-ratchet.spec.ts +104 -0
  56. package/src/lang/promise-ratchet.ts +196 -0
  57. package/src/lang/range.ts +4 -0
  58. package/src/lang/require-ratchet.spec.ts +85 -0
  59. package/src/lang/require-ratchet.ts +68 -0
  60. package/src/lang/simple-arg-ratchet.spec.ts +13 -0
  61. package/src/lang/simple-arg-ratchet.ts +47 -0
  62. package/src/lang/simple-encryption-ratchet.ts +88 -0
  63. package/src/lang/sort-ratchet.spec.ts +58 -0
  64. package/src/lang/sort-ratchet.ts +50 -0
  65. package/src/lang/stop-watch.spec.ts +53 -0
  66. package/src/lang/stop-watch.ts +202 -0
  67. package/src/lang/string-ratchet.spec.ts +226 -0
  68. package/src/lang/string-ratchet.ts +676 -0
  69. package/src/lang/time-zone-ratchet.spec.ts +51 -0
  70. package/src/lang/time-zone-ratchet.ts +148 -0
  71. package/src/lang/timeout-token.spec.ts +12 -0
  72. package/src/lang/timeout-token.ts +21 -0
  73. package/src/lang/uint-8-array-ratchet.spec.ts +22 -0
  74. package/src/lang/uint-8-array-ratchet.ts +48 -0
  75. package/src/lang/web-stream-ratchet.spec.ts +12 -0
  76. package/src/lang/web-stream-ratchet.ts +96 -0
  77. package/src/logger/classic-single-line-log-message-formatter.ts +19 -0
  78. package/src/logger/log-message-builder.ts +60 -0
  79. package/src/logger/log-message-format-type.ts +11 -0
  80. package/src/logger/log-message-formatter.ts +6 -0
  81. package/src/logger/log-message-processor.ts +6 -0
  82. package/src/logger/log-message.ts +9 -0
  83. package/src/logger/log-snapshot.ts +6 -0
  84. package/src/logger/logger-instance.ts +269 -0
  85. package/src/logger/logger-level-name.ts +11 -0
  86. package/src/logger/logger-meta.ts +7 -0
  87. package/src/logger/logger-options.ts +14 -0
  88. package/src/logger/logger-output-function.ts +10 -0
  89. package/src/logger/logger-ring-buffer.ts +89 -0
  90. package/src/logger/logger-util.spec.ts +11 -0
  91. package/src/logger/logger-util.ts +68 -0
  92. package/src/logger/logger.spec.ts +177 -0
  93. package/src/logger/logger.ts +213 -0
  94. package/src/logger/none-log-message-formatter.ts +10 -0
  95. package/src/logger/single-line-no-level-log-message-formatter.ts +18 -0
  96. package/src/logger/structured-json-log-message-formatter.ts +25 -0
  97. package/src/mail/archive-email-result.ts +8 -0
  98. package/src/mail/email-attachment.ts +23 -0
  99. package/src/mail/mail-sending-provider.ts +21 -0
  100. package/src/mail/mailer-config.ts +30 -0
  101. package/src/mail/mailer-like.ts +38 -0
  102. package/src/mail/mailer-util.ts +65 -0
  103. package/src/mail/mailer.spec.ts +120 -0
  104. package/src/mail/mailer.ts +214 -0
  105. package/src/mail/ready-to-send-email.ts +67 -0
  106. package/src/mail/resolved-ready-to-send-email.ts +17 -0
  107. package/src/mail/send-email-result.ts +16 -0
  108. package/src/mail/test-mail-sending-provider.ts +35 -0
  109. package/src/network/browser-local-ip-provider.spec.ts +23 -0
  110. package/src/network/browser-local-ip-provider.ts +26 -0
  111. package/src/network/fixed-local-ip-provider.ts +9 -0
  112. package/src/network/local-ip-provider.ts +4 -0
  113. package/src/network/network-ratchet.spec.ts +17 -0
  114. package/src/network/network-ratchet.ts +209 -0
  115. package/src/network/remote-file-tracker/backup-result.ts +6 -0
  116. package/src/network/remote-file-tracker/file-transfer-result-type.ts +5 -0
  117. package/src/network/remote-file-tracker/file-transfer-result.ts +9 -0
  118. package/src/network/remote-file-tracker/remote-file-tracker-options.ts +6 -0
  119. package/src/network/remote-file-tracker/remote-file-tracker-push-options.ts +4 -0
  120. package/src/network/remote-file-tracker/remote-file-tracker.ts +117 -0
  121. package/src/network/remote-file-tracker/remote-file-tracking-provider.ts +19 -0
  122. package/src/network/remote-file-tracker/remote-status-data-and-content.ts +6 -0
  123. package/src/network/remote-file-tracker/remote-status-data.ts +7 -0
  124. package/src/network/restful-api-http-error.spec.ts +13 -0
  125. package/src/network/restful-api-http-error.ts +173 -0
  126. package/src/template/ratchet-template-renderer.ts +8 -0
  127. package/src/third-party/google/google-recaptcha-ratchet.spec.ts +27 -0
  128. package/src/third-party/google/google-recaptcha-ratchet.ts +36 -0
  129. package/src/third-party/twilio/twilio-ratchet.ts +92 -0
  130. package/src/third-party/twilio/twilio-verify-ratchet.ts +83 -0
  131. package/src/transform/built-in-transforms.ts +214 -0
  132. package/src/transform/transform-ratchet.spec.ts +134 -0
  133. package/src/transform/transform-ratchet.ts +88 -0
  134. package/src/transform/transform-rule.ts +7 -0
  135. package/src/tx/transaction-configuration.ts +8 -0
  136. package/src/tx/transaction-final-state.ts +7 -0
  137. package/src/tx/transaction-ratchet.spec.ts +150 -0
  138. package/src/tx/transaction-ratchet.ts +98 -0
  139. package/src/tx/transaction-result.ts +10 -0
  140. package/src/tx/transaction-step.ts +5 -0
@@ -0,0 +1,51 @@
1
+ import { TimeZoneRatchet } from './time-zone-ratchet.js';
2
+ import { describe, expect, test } from 'vitest';
3
+
4
+ const tz: TimeZoneRatchet = TimeZoneRatchet.PACIFIC;
5
+
6
+ describe('#currentHour', function () {
7
+ test('should return 0- 23', function () {
8
+ const result: number = tz.currentHour();
9
+ expect(result).toBeGreaterThanOrEqual(0);
10
+ expect(result).toBeLessThanOrEqual(23);
11
+ });
12
+ });
13
+
14
+ describe('#startOfTodayEpochSeconds', function () {
15
+ test('should never be more than now or more than 86400 seconds in the past', function () {
16
+ const now: number = tz.nowEpochSeconds(); // Math.floor(new Date().getTime() / 1000);
17
+ const start: number = tz.startOfTodayEpochSeconds();
18
+ const result: number = now - start;
19
+ expect(result).toBeGreaterThanOrEqual(0);
20
+ expect(result).toBeLessThanOrEqual(86400);
21
+ });
22
+ });
23
+
24
+ describe('#dailySlotCount', function () {
25
+ test('should return 86400', function () {
26
+ const result: number = tz.dailySlotCount(1000);
27
+ expect(result).toEqual(86400);
28
+ });
29
+ });
30
+
31
+ describe('#currentTimeSlotIdx', function () {
32
+ // CAW 2020-11-01 : This actually fails on the day of spring forward/fall back because of the extra hour!
33
+ test.skip('should return same as current hour', function () {
34
+ const curHour: number = tz.currentHour();
35
+ const hourSlot: number = 1000 * 60 * 60;
36
+ const curSlot: number = tz.currentTimeSlotIdx(hourSlot);
37
+
38
+ expect(curSlot).toEqual(curHour);
39
+ });
40
+ });
41
+
42
+ describe('#matchingTimeSlotIdx', function () {
43
+ // CAW 2020-11-01 : This actually fails on the day of spring forward/fall back because of the extra hour!
44
+ test.skip('should return same as current hour', function () {
45
+ const curHour: number = tz.currentHour();
46
+ const hourSlot: number = 1000 * 60 * 60;
47
+ const matchSlot: number = tz.matchingTimeSlotIdx(new Date().getTime(), hourSlot);
48
+
49
+ expect(matchSlot).toEqual(curHour);
50
+ });
51
+ });
@@ -0,0 +1,148 @@
1
+ import { DateTime } from 'luxon';
2
+
3
+ /*
4
+ Functions for working with dates specifically a given time zone
5
+ TODO: Refactor the 'today' slots to work in terms of the 'matching' slot endpoints
6
+ */
7
+
8
+ export class TimeZoneRatchet {
9
+ public static PACIFIC = new TimeZoneRatchet('America/Los_Angeles');
10
+
11
+ constructor(private timezoneIanaName: string) {
12
+ if (!timezoneIanaName || timezoneIanaName.trim().length === 0) {
13
+ throw 'Timezone cannot be null or empty';
14
+ }
15
+ }
16
+
17
+ public get ianaName(): string {
18
+ return this.timezoneIanaName;
19
+ }
20
+
21
+ // Returns 0-23
22
+ public currentHour(): number {
23
+ const rval = DateTime.local().setZone(this.timezoneIanaName).hour;
24
+ return rval;
25
+ }
26
+
27
+ private toEpochSeconds(dt: DateTime) {
28
+ return Math.round(dt.toMillis() / 1000);
29
+ }
30
+
31
+ public nowEpochSeconds(): number {
32
+ return Math.floor(DateTime.local().setZone(this.timezoneIanaName).toSeconds());
33
+ }
34
+
35
+ // Returns midnight in the current timezone in epoch seconds
36
+ public startOfTodayEpochSeconds(): number {
37
+ const startOfToday = this.toEpochSeconds(
38
+ DateTime.local().setZone(this.timezoneIanaName).set({ hour: 0, minute: 0, second: 0, millisecond: 0 }),
39
+ );
40
+ return startOfToday;
41
+ }
42
+
43
+ // Returns midnight of the passed timestamp in the current timezone in epoch seconds
44
+ public startOfMatchingDayEpochSeconds(inputTS: number): number {
45
+ const startOfToday = this.toEpochSeconds(DateTime.fromMillis(inputTS).set({ hour: 0, minute: 0, second: 0, millisecond: 0 }));
46
+ return startOfToday;
47
+ }
48
+
49
+ // Returns midnight of the passed timestamp in the current timezone in epoch ms
50
+ public startOfMatchingDayEpochMS(inputTS: number): number {
51
+ return this.startOfMatchingDayEpochSeconds(inputTS) * 1000;
52
+ }
53
+
54
+ // Returns the start of the current hour in epoch seconds
55
+ public startOfCurrentHourEpochSeconds(): number {
56
+ const rval = this.toEpochSeconds(DateTime.local().setZone(this.timezoneIanaName).set({ minute: 0, second: 0, millisecond: 0 }));
57
+ return rval;
58
+ }
59
+
60
+ // Returns the start of the current minute in epoch seconds
61
+ public startOfCurrentMinuteEpochSeconds(): number {
62
+ const rval = this.toEpochSeconds(DateTime.local().setZone(this.timezoneIanaName).set({ second: 0, millisecond: 0 }));
63
+ return rval;
64
+ }
65
+
66
+ // Returns the start of the current second in epoch seconds
67
+ public startOfCurrentSecondEpochSeconds(): number {
68
+ const rval = this.toEpochSeconds(DateTime.local().setZone(this.timezoneIanaName).set({ millisecond: 0 }));
69
+ return rval;
70
+ }
71
+
72
+ // Returns midnight in the current timezone in epoch ms
73
+ public startOfTodayEpochMS(): number {
74
+ const startOfToday = DateTime.local().setZone(this.timezoneIanaName).set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).toMillis();
75
+ return startOfToday;
76
+ }
77
+
78
+ /**
79
+ * Returns the number of slots in a day (simple math)
80
+ * @param {number} slotWidthMs
81
+ * @returns {number} containing the number of slots in a day (last one may be partial)
82
+ */
83
+ public dailySlotCount(slotWidthMs: number): number {
84
+ return Math.ceil(86400000 / slotWidthMs);
85
+ }
86
+
87
+ /**
88
+ * Imagine a day cut into N 'slots', each slotWidthMS wide - then there are
89
+ * 86,400,000 / slotWidthMS slots available, indexed from 0 on up. This function
90
+ * returns that index
91
+ * @param {number} slotWidthMs
92
+ * @returns {number} containing the current index
93
+ */
94
+ public currentTimeSlotIdx(slotWidthMs: number): number {
95
+ if (slotWidthMs < 1) {
96
+ throw new Error('Cannot process with slot less than one ms wide');
97
+ }
98
+
99
+ const startOfToday = this.startOfTodayEpochMS();
100
+ const now = new Date().getTime();
101
+ const delta = now - startOfToday;
102
+ const idx = Math.floor(delta / slotWidthMs);
103
+ return idx;
104
+ }
105
+
106
+ /**
107
+ * Imagine a day cut into N 'slots', each slotWidthMS wide - then there are
108
+ * 86,400,000 / slotWidthMS slots available, indexed from 0 on up. This function
109
+ * returns that index
110
+ * @param timestamp Number of the epochMS to check
111
+ * @param slotWidthMs Number of the width of each slot in MS
112
+ */
113
+ public matchingTimeSlotIdx(timestamp: number, slotWidthMs: number): number {
114
+ if (slotWidthMs < 1) {
115
+ throw new Error('Cannot process with slot less than one ms wide');
116
+ }
117
+
118
+ const startOfDay = this.startOfMatchingDayEpochMS(timestamp);
119
+ const delta = timestamp - startOfDay;
120
+
121
+ const idx = Math.floor(delta / slotWidthMs);
122
+ return idx;
123
+ }
124
+
125
+ /**
126
+ * Given the definition of slotWidth and currentTimeSlotIdx from above, return the ms that is the
127
+ * start of the slot that "now" falls within.
128
+ * @param {number} slotWidthMs
129
+ * @returns {number}
130
+ */
131
+ public startOfCurrentSlotEpochMS(slotWidthMs: number): number {
132
+ const startOfToday = this.startOfTodayEpochMS();
133
+ const currentIdx = this.currentTimeSlotIdx(slotWidthMs);
134
+ return startOfToday + currentIdx * slotWidthMs;
135
+ }
136
+
137
+ /**
138
+ * Given the definition of slotWidth and currentTimeSlotIdx from above, return the ms that is the
139
+ * start of the slot that the passed timestamp falls within.
140
+ * @param {number} slotWidthMs
141
+ * @returns {number}
142
+ */
143
+ public startOfMatchingSlotEpochMS(timestamp: number, slotWidthMs: number): number {
144
+ const startOfDay = this.startOfMatchingDayEpochMS(timestamp);
145
+ const currentIdx = this.matchingTimeSlotIdx(timestamp, slotWidthMs);
146
+ return startOfDay + currentIdx * slotWidthMs;
147
+ }
148
+ }
@@ -0,0 +1,12 @@
1
+ import { TimeoutToken } from './timeout-token.js';
2
+ import { describe, expect, test } from 'vitest';
3
+
4
+ describe('#timeoutToken', function () {
5
+ test('should return the correct value for isTimeoutToken', function () {
6
+ const tt: TimeoutToken = new TimeoutToken('title', 20000);
7
+ const ntt: any = { a: 'b' };
8
+
9
+ expect(TimeoutToken.isTimeoutToken(tt)).toBeTruthy();
10
+ expect(TimeoutToken.isTimeoutToken(ntt)).toBeFalsy();
11
+ });
12
+ });
@@ -0,0 +1,21 @@
1
+ import { Logger } from '../logger/logger.js';
2
+ import { LoggerLevelName } from '../logger/logger-level-name.js';
3
+
4
+ export class TimeoutToken {
5
+ private __timeoutTokenFlagField = true;
6
+
7
+ constructor(
8
+ private title: string,
9
+ private timeoutMS: number,
10
+ ) {
11
+ Object.setPrototypeOf(this, TimeoutToken.prototype);
12
+ }
13
+
14
+ public writeToLog(logLevel: LoggerLevelName = LoggerLevelName.warn): void {
15
+ Logger.logByLevel(logLevel, 'Timed out after %d ms waiting for results of %s', this.timeoutMS, this.title);
16
+ }
17
+
18
+ public static isTimeoutToken(value: any): boolean {
19
+ return !!value && !!value['__timeoutTokenFlagField'];
20
+ }
21
+ }
@@ -0,0 +1,22 @@
1
+ import { Uint8ArrayRatchet } from './uint-8-array-ratchet.js';
2
+ import { describe, expect, test } from 'vitest';
3
+
4
+ describe('#Uint8Array', function () {
5
+ test('should combine uint8 arrays', function () {
6
+ const arrayOne: Uint8Array = new Uint8Array([2, 4, 8]);
7
+ const arrayTwo: Uint8Array = new Uint8Array([16, 32, 64]);
8
+ const result: Uint8Array = Uint8ArrayRatchet.mergeArrays([arrayOne, arrayTwo]);
9
+ expect(result).toBeTruthy();
10
+ expect(result.length).toEqual(6);
11
+ expect(result[0]).toEqual(2);
12
+ expect(result[5]).toEqual(64);
13
+ });
14
+
15
+ test('should compare arrays', function () {
16
+ const arrayOne: Uint8Array = new Uint8Array([2, 4, 8]);
17
+ const arrayOneX: Uint8Array = new Uint8Array([2, 4, 8]);
18
+ const arrayTwo: Uint8Array = new Uint8Array([16, 32, 64]);
19
+ expect(Uint8ArrayRatchet.deepEqual(arrayOne, arrayTwo)).toBeFalsy();
20
+ expect(Uint8ArrayRatchet.deepEqual(arrayOne, arrayOneX)).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,48 @@
1
+ // Uint8Array is the common denominator between node and web apis
2
+ // https://medium.com/@naveenkumarasinghe/javascript-lost-in-binaries-buffer-blob-uint8array-arraybuffer-ed8d2b4de44a
3
+ export class Uint8ArrayRatchet {
4
+ // Prevent instantiation
5
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
6
+ private constructor() {}
7
+
8
+ // Taken from https://stackoverflow.com/questions/49129643/how-do-i-merge-an-array-of-uint8arrays
9
+ public static mergeArrays(myArrays: Uint8Array[]): Uint8Array {
10
+ let rval: Uint8Array = null;
11
+ if (myArrays?.length) {
12
+ // Get the total length of all arrays.
13
+ let length = 0;
14
+ myArrays.forEach((item) => {
15
+ length += item.length;
16
+ });
17
+
18
+ // Create a new array with total length and merge all source arrays.
19
+ rval = new Uint8Array(length);
20
+ let offset = 0;
21
+ myArrays.forEach((item) => {
22
+ rval.set(item, offset);
23
+ offset += item.length;
24
+ });
25
+ }
26
+ return rval;
27
+ }
28
+
29
+ public static deepEqual(arr1: Uint8Array, arr2: Uint8Array): boolean {
30
+ let rval = false;
31
+ if (arr1 && arr2 && arr1.length === arr2.length) {
32
+ let mismatch = false;
33
+ for (let i = 0; i < arr1.length && !mismatch; i++) {
34
+ mismatch = arr1[i] !== arr2[i];
35
+ }
36
+ rval = !mismatch;
37
+ }
38
+ return rval;
39
+ }
40
+
41
+ // Taken from https://stackoverflow.com/a/22114687
42
+ public static deepCopy(src: Uint8Array): Uint8Array {
43
+ const tmp: ArrayBuffer = new ArrayBuffer(src.byteLength);
44
+ const dst: Uint8Array = new Uint8Array(tmp);
45
+ dst.set(new Uint8Array(src));
46
+ return dst;
47
+ }
48
+ }
@@ -0,0 +1,12 @@
1
+ import { WebStreamRatchet } from './web-stream-ratchet.js';
2
+ import { describe, expect, test } from 'vitest';
3
+
4
+ describe('#WebStreamRatchet', function () {
5
+ test('should roundtrip from string to stream and back', async () => {
6
+ const input = 'test';
7
+ const r: ReadableStream = WebStreamRatchet.stringToWebReadableStream('test');
8
+ const out: string = await WebStreamRatchet.webReadableStreamToString(r);
9
+
10
+ expect(input).toEqual(out);
11
+ });
12
+ });
@@ -0,0 +1,96 @@
1
+ import { ErrorRatchet } from './error-ratchet.js';
2
+ import { StringRatchet } from './string-ratchet.js';
3
+ import { Uint8ArrayRatchet } from './uint-8-array-ratchet.js';
4
+ import { Logger } from '../logger/logger.js';
5
+
6
+ /**
7
+ * This class is specifically for dealing with web streams, NOT
8
+ * node streams (ie, ReadableStream and WriteableStream, NOT
9
+ * Readable and Writeable, and CERTAINLY not the FS based streams)
10
+ */
11
+ export class WebStreamRatchet {
12
+ // Prevent instantiation
13
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
14
+ private constructor() {}
15
+
16
+ public static async webReadableStreamToUint8Array(stream: ReadableStream): Promise<Uint8Array> {
17
+ const out: Uint8Array[] = [];
18
+ const writer: WritableStream = new WritableStream(
19
+ {
20
+ async write(chunk, _controller): Promise<any> {
21
+ if (typeof chunk === 'string') {
22
+ out.push(StringRatchet.stringToUint8Array(chunk));
23
+ } else {
24
+ out.push(chunk);
25
+ }
26
+
27
+ return null;
28
+ },
29
+ abort(reason) {
30
+ ErrorRatchet.throwFormattedErr('StringWebWritableStream failure : %s', reason);
31
+ },
32
+ },
33
+ {
34
+ highWaterMark: 3,
35
+ size: () => 1,
36
+ },
37
+ );
38
+ try {
39
+ Logger.debug('Starting pipe');
40
+ await stream.pipeTo(writer, { preventAbort: true, preventCancel: true, preventClose: true });
41
+ Logger.debug('Completed pipe');
42
+ return Uint8ArrayRatchet.mergeArrays(out);
43
+ } catch (err) {
44
+ Logger.error('Caught error while trying to convert to array : %s', err, err);
45
+ throw err;
46
+ }
47
+ }
48
+ public static async webReadableStreamToString(stream: ReadableStream): Promise<string> {
49
+ const buf: Uint8Array = await WebStreamRatchet.webReadableStreamToUint8Array(stream);
50
+ return new TextDecoder().decode(buf);
51
+ }
52
+
53
+ public static stringToWebReadableStream(input: string): ReadableStream {
54
+ //if (typeof ReadableStream !== 'undefined') {
55
+ // ErrorRatchet.throwFormattedErr('ReadableStream not supported on this platform');
56
+ // }
57
+
58
+ const rval: ReadableStream = new ReadableStream<string>(
59
+ {
60
+ start(controller) {
61
+ if (input) {
62
+ controller.enqueue(input); // May as well write it all
63
+ }
64
+ controller.close();
65
+ return null;
66
+ },
67
+ },
68
+ {
69
+ highWaterMark: input ? input.length : null,
70
+ },
71
+ );
72
+ return rval;
73
+ }
74
+
75
+ public static uint8ArrayToWebReadableStream(input: Uint8Array): ReadableStream {
76
+ //if (typeof ReadableStream !== 'undefined') {
77
+ // ErrorRatchet.throwFormattedErr('ReadableStream not supported on this platform');
78
+ // }
79
+
80
+ const rval: ReadableStream = new ReadableStream<Uint8Array>(
81
+ {
82
+ start(controller) {
83
+ if (input) {
84
+ controller.enqueue(input); // May as well write it all
85
+ }
86
+ controller.close();
87
+ return null;
88
+ },
89
+ },
90
+ {
91
+ highWaterMark: input ? input.length : null,
92
+ },
93
+ );
94
+ return rval;
95
+ }
96
+ }
@@ -0,0 +1,19 @@
1
+ import { LogMessage } from './log-message.js';
2
+ import { LogMessageFormatter } from './log-message-formatter.js';
3
+ import { LoggerMeta } from './logger-meta.js';
4
+ import { StringRatchet } from '../lang/string-ratchet.js';
5
+
6
+ export class ClassicSingleLineLogMessageFormatter implements LogMessageFormatter {
7
+ public formatMessage(msg: LogMessage, meta: LoggerMeta): string {
8
+ let tmp: string = null;
9
+
10
+ if (msg) {
11
+ tmp = '';
12
+ tmp += meta?.options?.trace ? meta.options.trace + ' ' : '';
13
+
14
+ tmp += '[' + msg.lvl + '] ';
15
+ tmp += StringRatchet.format(msg?.messageSource ?? '', ...(msg.subsVars || []));
16
+ }
17
+ return tmp;
18
+ }
19
+ }
@@ -0,0 +1,60 @@
1
+ import { LoggerLevelName } from './logger-level-name.js';
2
+ import { LogMessage } from './log-message.js';
3
+
4
+ export class LogMessageBuilder {
5
+ private wrapped: LogMessage;
6
+
7
+ constructor(lvl: LoggerLevelName, messageSource?: string) {
8
+ if (!lvl) {
9
+ throw Error('Cannot set level to null/undefined');
10
+ }
11
+ this.wrapped = { lvl: lvl, timestamp: Date.now(), messageSource: messageSource };
12
+ }
13
+
14
+ public clone(): LogMessageBuilder {
15
+ const rval: LogMessageBuilder = new LogMessageBuilder(this.wrapped.lvl, this.wrapped.messageSource);
16
+ rval.wrapped = Object.assign({}, this.wrapped);
17
+ return rval;
18
+ }
19
+
20
+ public level(lvl: LoggerLevelName): LogMessageBuilder {
21
+ if (!lvl) {
22
+ throw Error('Cannot set level to null/undefined');
23
+ }
24
+ this.wrapped.lvl = lvl;
25
+ return this;
26
+ }
27
+
28
+ public timestamp(val: number): LogMessageBuilder {
29
+ if (!val) {
30
+ throw Error('Cannot set timestamp to null/undefined');
31
+ }
32
+ this.wrapped.timestamp = val;
33
+ return this;
34
+ }
35
+
36
+ public messageSource(val: string): LogMessageBuilder {
37
+ this.wrapped.messageSource = val;
38
+ return this;
39
+ }
40
+
41
+ public subVars(val: any[]): LogMessageBuilder {
42
+ this.wrapped.subsVars = val || [];
43
+ return this;
44
+ }
45
+
46
+ public params(val: Record<string, string | number | boolean>): LogMessageBuilder {
47
+ this.wrapped.params = val || {};
48
+ return this;
49
+ }
50
+
51
+ public p(name: string, value: string | number | boolean): LogMessageBuilder {
52
+ this.wrapped.params = this.wrapped.params || {};
53
+ this.wrapped.params[name] = value;
54
+ return this;
55
+ }
56
+
57
+ public toMessage(): LogMessage {
58
+ return Object.assign({}, this.wrapped);
59
+ }
60
+ }
@@ -0,0 +1,11 @@
1
+ // NOTE: This is a psuedo-enum to fix some issues with Typescript enums. See: https://exploringjs.com/tackling-ts/ch_enum-alternatives.html for details
2
+
3
+ export const LogMessageFormatType = {
4
+ ClassicSingleLine: 'ClassicSingleLine',
5
+ SingleLineNoLevel: 'SingleLineNoLevel',
6
+ StructuredJson: 'StructuredJson',
7
+
8
+ None: 'None',
9
+ } as const;
10
+
11
+ export type LogMessageFormatType = (typeof LogMessageFormatType)[keyof typeof LogMessageFormatType];
@@ -0,0 +1,6 @@
1
+ import { LogMessage } from './log-message.js';
2
+ import { LoggerMeta } from './logger-meta.js';
3
+
4
+ export interface LogMessageFormatter {
5
+ formatMessage(msg: LogMessage, meta: LoggerMeta): string;
6
+ }
@@ -0,0 +1,6 @@
1
+ import { LogMessage } from './log-message.js';
2
+
3
+ export interface LogMessageProcessor {
4
+ label?(): string;
5
+ process(msg: LogMessage): LogMessage;
6
+ }
@@ -0,0 +1,9 @@
1
+ import { LoggerLevelName } from './logger-level-name.js';
2
+
3
+ export interface LogMessage {
4
+ lvl: LoggerLevelName;
5
+ timestamp: number;
6
+ messageSource: string;
7
+ subsVars?: any[];
8
+ params?: Record<string, string | number | boolean>;
9
+ }
@@ -0,0 +1,6 @@
1
+ import { LogMessage } from './log-message.js';
2
+
3
+ export interface LogSnapshot {
4
+ logMessagesTruncated: number;
5
+ messages: LogMessage[];
6
+ }