@bitblit/ratchet-common 6.0.145-alpha → 6.0.147-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,50 @@
1
+ /*
2
+ Helper functions for working with sorting.
3
+
4
+ Note that the functions in here do NOT claim to be able to correctly
5
+ sort undefined in all cases, since certain browsers will auto
6
+ sort undefined in arrays to certain places and never even
7
+ call this function. To be safe, filter and convert yourself
8
+ before sorting if undefined is a possibility
9
+
10
+ See : https://stackoverflow.com/questions/4783242/javascript-array-sort-with-undefined-values
11
+ */
12
+
13
+ import { RequireRatchet } from './require-ratchet.js';
14
+ import { NumberRatchet } from './number-ratchet.js';
15
+
16
+ export class SortRatchet {
17
+ // Prevent instantiation
18
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
19
+ private constructor() {}
20
+
21
+ public static sortNullToTop<T>(a: T, b: T, bothNonNullSort: (c: T, d: T) => number): number {
22
+ return SortRatchet.nullSafeSort(a, b, true, bothNonNullSort);
23
+ }
24
+
25
+ public static sortNullToBottom<T>(a: T, b: T, bothNonNullSort: (c: T, d: T) => number): number {
26
+ return SortRatchet.nullSafeSort(a, b, false, bothNonNullSort);
27
+ }
28
+
29
+ public static nullSafeSort<T>(a: T, b: T, nullsOnTop: boolean, bothNonNullSort: (c: T, d: T) => number): number {
30
+ let rval: number;
31
+
32
+ if (RequireRatchet.isNullOrUndefined(a) && RequireRatchet.isNullOrUndefined(b)) {
33
+ rval = 0;
34
+ } else if (RequireRatchet.isNullOrUndefined(a)) {
35
+ rval = nullsOnTop ? -Infinity : Infinity;
36
+ } else if (RequireRatchet.isNullOrUndefined(b)) {
37
+ rval = nullsOnTop ? Infinity : -Infinity;
38
+ } else {
39
+ rval = bothNonNullSort(a, b);
40
+ }
41
+
42
+ return rval;
43
+ }
44
+
45
+ public static sortNumericStringsAsNumbers(a: string | number, b: string | number, sortNonNumbersToTop?: boolean): number {
46
+ const an: number = NumberRatchet.safeNumber(a);
47
+ const bn: number = NumberRatchet.safeNumber(b);
48
+ return SortRatchet.nullSafeSort<number>(an, bn, sortNonNumbersToTop, (ax: number, bx: number) => ax - bx);
49
+ }
50
+ }
@@ -0,0 +1,53 @@
1
+ import { StopWatch } from './stop-watch.js';
2
+ import { PromiseRatchet } from './promise-ratchet.js';
3
+ import { describe, expect, test } from 'vitest';
4
+
5
+ describe('#elapsedMS', function () {
6
+ test('should calculate elapsed MS correctly', async () => {
7
+ const sw: StopWatch = new StopWatch();
8
+ sw.moveCreateTime(-501);
9
+ //await PromiseRatchet.wait(500);
10
+ const elapsed: number = sw.elapsedMS();
11
+ expect(elapsed).toBeGreaterThan(500);
12
+ expect(elapsed).toBeLessThan(600);
13
+ });
14
+
15
+ test('should dump all', async () => {
16
+ const sw: StopWatch = new StopWatch();
17
+ sw.start('a1');
18
+ await PromiseRatchet.wait(50);
19
+ sw.stop('a1');
20
+ sw.start('b1');
21
+ await PromiseRatchet.wait(60);
22
+ sw.stop('b1');
23
+ sw.start('c1');
24
+ await PromiseRatchet.wait(70);
25
+ sw.stop('c1');
26
+ const names: string[] = sw.timerNames();
27
+ expect(names).toContain('a1');
28
+ expect(names).toContain('b1');
29
+ expect(names).toContain('c1');
30
+
31
+ const out: string = sw.dumpAll();
32
+ expect(out).toContain('a1');
33
+ expect(out).toContain('b1');
34
+ expect(out).toContain('c1');
35
+ expect(out).toContain('Overall');
36
+ });
37
+
38
+ test('should calc expected', async () => {
39
+ const sw: StopWatch = new StopWatch();
40
+
41
+ for (let i = 0; i < 10; i++) {
42
+ const elapsedTenths: number = Math.floor(sw.elapsedMS() / 100);
43
+ const expectedTenths: number = Math.floor(sw.expectedRemainingMS(i / 10) / 100);
44
+ if (i > 0) {
45
+ expect(elapsedTenths).toEqual(i);
46
+ expect(expectedTenths).toEqual(10 - i);
47
+ }
48
+ sw.moveCreateTime(-100);
49
+ //Logger.info('%d elapsed %d expected -- %s', elapsedTenths, expectedTenths);
50
+ //await PromiseRatchet.wait(100);
51
+ }
52
+ });
53
+ });
@@ -0,0 +1,202 @@
1
+ import { DurationRatchet } from './duration-ratchet.js';
2
+ import { StringRatchet } from './string-ratchet.js';
3
+ import { RequireRatchet } from './require-ratchet.js';
4
+ import { LoggerLevelName } from '../logger/logger-level-name.js';
5
+ import { Logger } from '../logger/logger.js';
6
+
7
+ /*
8
+ Class to simplify timing
9
+ */
10
+
11
+ export class StopWatch {
12
+ get createTime(): number {
13
+ return this._createTime;
14
+ }
15
+
16
+ private starts: Map<string, number> = new Map<string, number>();
17
+ private ends: Map<string, number> = new Map<string, number>();
18
+
19
+ private _createTime: number = Date.now();
20
+ private _label: string = StringRatchet.createRandomHexString(4);
21
+ private _labelIncludedInOutput = false;
22
+
23
+ // This is mainly used for testing - allows me to programmitically
24
+ // move the create-time into the past for testing things. Might have
25
+ // some other uses, not really sure
26
+ public moveCreateTime(offset: number): number {
27
+ this._createTime+=offset;
28
+ return this._createTime;
29
+ }
30
+
31
+ public withLabel(val: string): StopWatch {
32
+ this._label = StringRatchet.trimToNull(val);
33
+ return this;
34
+ }
35
+
36
+ public withLabelIncludedInOutput(val: boolean): StopWatch {
37
+ this._labelIncludedInOutput = val;
38
+ return this;
39
+ }
40
+
41
+ get label(): string {
42
+ return this._label;
43
+ }
44
+
45
+ set label(value: string) {
46
+ this._label = value;
47
+ }
48
+
49
+ get labelIncludedInOutput(): boolean {
50
+ return this._labelIncludedInOutput;
51
+ }
52
+
53
+ set labelIncludedInOutput(value: boolean) {
54
+ this._labelIncludedInOutput = value;
55
+ }
56
+
57
+ public start(name: string): number {
58
+ RequireRatchet.notNullUndefinedOrOnlyWhitespaceString(name, 'name');
59
+ const now: number = Date.now();
60
+ this.starts.set(StringRatchet.trimToNull(name), now);
61
+ return now;
62
+ }
63
+
64
+ public stop(name: string): number {
65
+ RequireRatchet.notNullUndefinedOrOnlyWhitespaceString(name, 'name');
66
+ const now: number = Date.now();
67
+ this.ends.set(StringRatchet.trimToNull(name), now);
68
+ return now;
69
+ }
70
+
71
+ public reset(name: string): void {
72
+ RequireRatchet.notNullUndefinedOrOnlyWhitespaceString(name, 'name');
73
+ this.starts.delete(StringRatchet.trimToNull(name));
74
+ this.ends.delete(StringRatchet.trimToNull(name));
75
+ }
76
+
77
+ public hasTimer(name: string): boolean {
78
+ RequireRatchet.notNullUndefinedOrOnlyWhitespaceString(name, 'name');
79
+ return this.starts.has(name);
80
+ }
81
+
82
+ public log(name?: string, shortForm?: boolean, logLevel: LoggerLevelName = LoggerLevelName.info): void {
83
+ Logger.logByLevel(logLevel, this.dump(name, shortForm));
84
+ }
85
+
86
+ public logExpected(pctComplete: number, name?: string, shortForm?: boolean, logLevel: LoggerLevelName = LoggerLevelName.info): void {
87
+ Logger.logByLevel(logLevel, this.dumpExpected(pctComplete, name, shortForm));
88
+ }
89
+
90
+ public timerNames(): string[] {
91
+ return Array.from(this.starts.keys());
92
+ }
93
+
94
+ public dumpAll(separator = ', ', shortForm?: boolean): string {
95
+ const outs: string[] = this.timerNames().map((s) => this.dump(s, shortForm));
96
+ let rval: string = 'Overall: ' + this.dump(null, shortForm);
97
+ if (outs.length > 0) {
98
+ rval += separator;
99
+ rval += outs.join(separator);
100
+ }
101
+ return rval;
102
+ }
103
+
104
+ public dump(name?: string, shortForm?: boolean): string {
105
+ let rval: string = this._labelIncludedInOutput ? this._label + ' ' : '';
106
+ const cleanName: string = StringRatchet.trimToNull(name);
107
+ if (cleanName && !this.hasTimer(cleanName)) {
108
+ rval += 'No such timer : ' + cleanName;
109
+ } else {
110
+ const start: number = name ? this.starts.get(cleanName) : this._createTime;
111
+ const end: number = name ? this.ends.get(cleanName) : Date.now();
112
+ rval += (cleanName || 'Default') + ' ';
113
+ if (!!start && !!end) {
114
+ rval += 'completed in ' + DurationRatchet.formatMsDuration(end - start, !shortForm);
115
+ } else if (start) {
116
+ rval += 'running for ' + DurationRatchet.formatMsDuration(Date.now() - start, !shortForm);
117
+ }
118
+ }
119
+ return rval;
120
+ }
121
+
122
+ public dumpExpectedByIdx(idx: number, total: number, name?: string, shortForm?: boolean): string {
123
+ RequireRatchet.true(idx > 0 && idx < total, 'IDX must be >=0 and less than total');
124
+ return this.dumpExpected(idx / total, name, shortForm);
125
+ }
126
+
127
+ public dumpExpected(pctComplete: number, name?: string, shortForm?: boolean): string {
128
+ let rval: string = this._labelIncludedInOutput ? this._label + ' ' : '';
129
+ const cleanName: string = StringRatchet.trimToNull(name);
130
+ if (cleanName && !this.hasTimer(cleanName)) {
131
+ rval += 'No such timer : ' + cleanName;
132
+ } else {
133
+ if (!pctComplete || pctComplete <= 0) {
134
+ rval += 'Cannot generate output for 0 percent complete';
135
+ } else if (pctComplete > 1) {
136
+ rval += 'Cannot generate output for percent > 1';
137
+ } else {
138
+ rval += (cleanName || 'Default') + ' ';
139
+ const remainMS: number = this.expectedRemainingMS(pctComplete, cleanName);
140
+ const elapsedMS: number = this.elapsedMS(cleanName);
141
+ //const expectedTotalMS: number = elapsedMS + remainMS;
142
+ if (remainMS === 0) {
143
+ rval += 'completed in ' + DurationRatchet.formatMsDuration(elapsedMS, !shortForm);
144
+ } else if (remainMS > 0) {
145
+ rval +=
146
+ 'running for ' +
147
+ DurationRatchet.formatMsDuration(elapsedMS, !shortForm) +
148
+ ' approx ' +
149
+ DurationRatchet.formatMsDuration(remainMS, !shortForm) +
150
+ ' remaining';
151
+ } else {
152
+ throw new Error('Cannot happen - had negative remaining time : ' + remainMS);
153
+ }
154
+ }
155
+ }
156
+ return rval;
157
+ }
158
+
159
+ public expectedRemainingMSByIdx(idx: number, total: number, name?: string): number {
160
+ RequireRatchet.true(idx > 0 && idx < total, 'IDX must be >=0 and less than total');
161
+ return this.expectedRemainingMS(idx / total, name);
162
+ }
163
+
164
+ public expectedRemainingMS(pctComplete: number, name?: string): number {
165
+ let rval: number = null;
166
+ if (!pctComplete || pctComplete <= 0) {
167
+ // return null, no such thing
168
+ } else if (pctComplete > 1) {
169
+ // return null, no such thing for percent larger than one
170
+ } else {
171
+ const cleanName: string = StringRatchet.trimToNull(name);
172
+ const start: number = name ? this.starts.get(cleanName) : this._createTime;
173
+ const end: number = name ? this.ends.get(cleanName) : null;
174
+ if (!!start && !!end) {
175
+ rval = end - start; // already completed
176
+ } else if (start) {
177
+ const now: number = Date.now();
178
+ const elapsedMS: number = now - start;
179
+ const expectedTotalMS: number = Math.ceil(elapsedMS / pctComplete);
180
+ rval = expectedTotalMS - elapsedMS;
181
+ }
182
+ }
183
+ return rval;
184
+ }
185
+
186
+ public elapsedMS(name?: string): number {
187
+ let rval: number = null;
188
+ const cleanName: string = StringRatchet.trimToNull(name);
189
+ if (cleanName && !this.hasTimer(cleanName)) {
190
+ rval = null;
191
+ } else {
192
+ const start: number = name ? this.starts.get(cleanName) : this._createTime;
193
+ const end: number = name ? this.ends.get(cleanName) : Date.now();
194
+ if (!!start && !!end) {
195
+ rval = end - start;
196
+ } else if (start) {
197
+ rval = Date.now() - start;
198
+ }
199
+ }
200
+ return rval;
201
+ }
202
+ }
@@ -0,0 +1,226 @@
1
+ import { StringRatchet } from './string-ratchet.js';
2
+ import { describe, expect, test } from 'vitest';
3
+
4
+ describe('#formatBytes', function () {
5
+ test('should format 0 bytes correctly', function () {
6
+ const result = StringRatchet.formatBytes(0);
7
+ expect(result).toEqual('0 Bytes');
8
+ });
9
+
10
+ test('should format less than a Kb correctly', function () {
11
+ const result = StringRatchet.formatBytes(123);
12
+ expect(result).toEqual('123 Bytes');
13
+ });
14
+
15
+ test('should format less than a Mb correctly', function () {
16
+ const result = StringRatchet.formatBytes(1024);
17
+ expect(result).toEqual('1 KB');
18
+ });
19
+
20
+ test('should format less than a Mb correctly with 3 decimals', function () {
21
+ const result = StringRatchet.formatBytes(1234, 3);
22
+ expect(result).toEqual('1.205 KB');
23
+ });
24
+ });
25
+
26
+ describe('#safeToString', function () {
27
+ test('should return "asdf"', function () {
28
+ const result = StringRatchet.safeString('asdf');
29
+ expect(result).toEqual('asdf');
30
+ });
31
+
32
+ test('should return "55"', function () {
33
+ const result = StringRatchet.safeString(55);
34
+ expect(result).toEqual('55');
35
+ });
36
+ });
37
+
38
+ describe('#obscure', function () {
39
+ test('should return "pa****rd"', function () {
40
+ const result = StringRatchet.obscure('password', 2, 2);
41
+ expect(result).toEqual('pa****rd');
42
+ });
43
+
44
+ test('should return null', function () {
45
+ const result = StringRatchet.obscure(null, 2, 2);
46
+ expect(result).toBeNull();
47
+ });
48
+
49
+ test('should return "p**s"', function () {
50
+ const result = StringRatchet.obscure('pass', 2, 2);
51
+ expect(result).toEqual('p**s');
52
+ });
53
+
54
+ test('should return "****"', function () {
55
+ const result = StringRatchet.obscure('pass', 0, 0);
56
+ expect(result).toEqual('****');
57
+ });
58
+
59
+ test('should return "p***"', function () {
60
+ const result = StringRatchet.obscure('pass', 1, 0);
61
+ expect(result).toEqual('p***');
62
+ });
63
+
64
+ test('should return "***s"', function () {
65
+ const result = StringRatchet.obscure('pass', 0, 1);
66
+ expect(result).toEqual('***s');
67
+ });
68
+ });
69
+
70
+ describe('#randomGeneration', function () {
71
+ test('should generate a guid"', function () {
72
+ const result = StringRatchet.createType4Guid();
73
+ expect(result).toBeTruthy();
74
+ });
75
+
76
+ test('should generate a random hex string"', function () {
77
+ const result = StringRatchet.createRandomHexString(12);
78
+ expect(result).toBeTruthy();
79
+ expect(result.length).toEqual(12);
80
+ });
81
+
82
+ test('should generate a random string from an alphabet"', function () {
83
+ const result = StringRatchet.createRandomStringFromAlphabet(StringRatchet.LOWER_CASE_LATIN, 12);
84
+ expect(result).toBeTruthy();
85
+ expect(result.length).toEqual(12);
86
+ });
87
+
88
+ });
89
+
90
+ describe('#leadingZeros', function () {
91
+ test('should generate string with leading zeros"', function () {
92
+ const result = StringRatchet.leadingZeros(25, 4);
93
+ expect(result).toEqual('0025');
94
+ });
95
+
96
+ test('should generate string with leading zeros and a negative sign"', function () {
97
+ const result = StringRatchet.leadingZeros(-8, 2);
98
+ expect(result).toEqual('-08');
99
+ });
100
+ });
101
+
102
+ describe('#stripNonNumeric', function () {
103
+ test('should return a string containing only numbers"', function () {
104
+ const result: string = StringRatchet.stripNonNumeric('702-555-1212');
105
+ expect(result).toEqual('7025551212');
106
+ });
107
+ });
108
+
109
+ describe('#stringContainsOnly', function () {
110
+ test('should check string contains only valid chars"', function () {
111
+ expect(StringRatchet.stringContainsOnly('test', 'tes')).toBeTruthy();
112
+ expect(StringRatchet.stringContainsOnly('test', 'teg')).toBeFalsy();
113
+
114
+ expect(StringRatchet.stringContainsOnlyAlphanumeric('test')).toBeTruthy();
115
+ expect(StringRatchet.stringContainsOnlyAlphanumeric('tes-')).toBeFalsy();
116
+
117
+ expect(StringRatchet.stringContainsOnlyHex('1a3')).toBeTruthy();
118
+ expect(StringRatchet.stringContainsOnlyHex('test')).toBeFalsy();
119
+ });
120
+ });
121
+
122
+ describe('#stringCsvSafe', function () {
123
+ test('should make values safe to place in a CSV"', function () {
124
+ expect(StringRatchet.csvSafe('test')).toEqual('test');
125
+ expect(StringRatchet.csvSafe('test,and 1')).toEqual('"test,and 1"');
126
+ expect(StringRatchet.csvSafe(1)).toEqual('1');
127
+ expect(StringRatchet.csvSafe("test'blah")).toEqual('"test\'blah"');
128
+ });
129
+ });
130
+
131
+ describe('#trimToEmpty', function () {
132
+ test('should return an empty string for null"', function () {
133
+ const result: string = StringRatchet.trimToEmpty(null);
134
+ expect(result).toEqual('');
135
+ });
136
+
137
+ test('should return an empty string for undefined"', function () {
138
+ const result: string = StringRatchet.trimToEmpty(undefined);
139
+ expect(result).toEqual('');
140
+ });
141
+
142
+ test('should return an empty string"', function () {
143
+ const result: string = StringRatchet.trimToEmpty(' ');
144
+ expect(result).toEqual('');
145
+ });
146
+
147
+ test('should return an abc"', function () {
148
+ const result: string = StringRatchet.trimToEmpty('abc ');
149
+ expect(result).toEqual('abc');
150
+ });
151
+
152
+ test('should return string "5"', function () {
153
+ const result: string = StringRatchet.trimToEmpty(5 as any); // as any to fool TSC for testing
154
+ expect(result).toEqual('5');
155
+ });
156
+ });
157
+
158
+ describe('#trimStringPropertiesInPlace', function () {
159
+ test('should trim properties to null"', function () {
160
+ const test: any = {
161
+ a: 'test ',
162
+ b: 1,
163
+ c: ' test',
164
+ d: null,
165
+ e: ' ',
166
+ };
167
+ const nullResult: any = StringRatchet.trimAllStringPropertiesToNullInPlace<any>(test);
168
+
169
+ expect(nullResult).not.toBeNull();
170
+ expect(nullResult['a']).toEqual('test');
171
+ expect(nullResult['b']).toEqual(1);
172
+ expect(nullResult['c']).toEqual('test');
173
+ expect(nullResult['d']).toEqual(null);
174
+ expect(nullResult['e']).toEqual(null);
175
+ });
176
+
177
+ test('should trim properties to empty"', function () {
178
+ const test: any = {
179
+ a: 'test ',
180
+ b: 1,
181
+ c: ' test',
182
+ d: null,
183
+ e: ' ',
184
+ };
185
+ const emptyResult: any = StringRatchet.trimAllStringPropertiesToEmptyInPlace<any>(test);
186
+
187
+ expect(emptyResult).not.toBeNull();
188
+ expect(emptyResult['a']).toEqual('test');
189
+ expect(emptyResult['b']).toEqual(1);
190
+ expect(emptyResult['c']).toEqual('test');
191
+ expect(emptyResult['d']).toEqual(null);
192
+ expect(emptyResult['e']).toEqual('');
193
+ });
194
+ });
195
+
196
+ describe('#createShortUid', function () {
197
+ test('should return a short uid', function () {
198
+ for (let i = 0; i < 20; i++) {
199
+ console.log(StringRatchet.createShortUid());
200
+ }
201
+
202
+ const result: string = StringRatchet.createShortUid();
203
+ expect(result).toBeTruthy();
204
+ expect(result.length).toBeGreaterThan(0);
205
+ });
206
+ });
207
+
208
+ describe('#circSafeFormat', function () {
209
+ test('should format correctly when contents are circular', function () {
210
+ const testOb: any = {
211
+ a: 1,
212
+ b: 2,
213
+ };
214
+ testOb['c'] = testOb;
215
+ const out: string = StringRatchet.format('This is a test : %j', testOb);
216
+ expect(out).not.toBeNull;
217
+ });
218
+ });
219
+
220
+ describe('substring finder', () => {
221
+ test('should detect substring', () => {
222
+ expect(StringRatchet.longestNonOverlappingRepeatingSubstring('abc123abc')).toEqual('abc');
223
+ expect(StringRatchet.longestNonOverlappingRepeatingSubstring('abc123456')).toEqual(null);
224
+ });
225
+ });
226
+