@hpcc-js/util 3.5.1 → 3.5.4

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.
package/src/stateful.ts CHANGED
@@ -1,178 +1,178 @@
1
- import { Dispatch, IObserverHandle, Message } from "./dispatch.ts";
2
- import { deepEquals } from "./immutable.ts";
3
-
4
- class PropChangedMessage extends Message {
5
-
6
- constructor(readonly property: string, public newValue: any, public oldValue?: any) {
7
- super();
8
- }
9
-
10
- get canConflate(): boolean { return true; }
11
- conflate(other: PropChangedMessage) {
12
- if (this.property === other.property) {
13
- this.newValue = other.newValue;
14
- return true;
15
- }
16
- return false;
17
- }
18
-
19
- void(): boolean {
20
- return deepEquals(this.newValue, this.oldValue);
21
- }
22
- }
23
-
24
- export interface IEvent {
25
- id: string;
26
- oldValue: any;
27
- newValue: any;
28
- }
29
-
30
- export type StatePropCallback = (changes: IEvent) => void;
31
- export type StateCallback = (changes: IEvent[]) => void;
32
- export type StateEvents = "propChanged" | "changed";
33
- export class StateObject<U, I> {
34
- private _espState: Partial<U> = {} as U;
35
- private _dispatch = new Dispatch<PropChangedMessage>();
36
- private _monitorHandle?: any;
37
- protected _monitorTickCount: number = 0;
38
-
39
- protected clear(newVals?: Partial<I>) {
40
- this._espState = {} as U;
41
- if (newVals !== void 0) {
42
- this.set(newVals as I);
43
- }
44
- this._monitorTickCount = 0;
45
- }
46
-
47
- protected get(): U;
48
- protected get<K extends keyof U>(key: K, defValue?: U[K]): U[K];
49
- protected get<K extends keyof U>(key?: K, defValue?: U[K]): Partial<U> | U[K] | undefined {
50
- if (key === void 0) {
51
- return this._espState;
52
- }
53
- return this.has(key) ? this._espState[key] : defValue;
54
- }
55
-
56
- protected set(newVals: I): void;
57
- protected set<K extends keyof U>(key: K, newVal: U[K], batchMode?: boolean): void;
58
- protected set<K extends keyof U>(keyOrNewVals: K | U, newVal?: U[K]): void {
59
- if (typeof keyOrNewVals === "string") {
60
- return this.setSingle(keyOrNewVals as any, newVal as U[K]); // TODO: "as any" should not be needed (TS >= 3.1.x)
61
- }
62
- this.setAll(keyOrNewVals as Partial<U>);
63
- }
64
-
65
- private setSingle<K extends keyof U>(key: K, newVal: U[K] | undefined): void {
66
- const oldVal = this._espState[key];
67
- this._espState[key] = newVal;
68
- this._dispatch.post(new PropChangedMessage(key as string, newVal, oldVal));
69
- }
70
-
71
- private setAll(_: Partial<U>): void {
72
- for (const key in _) {
73
- if (_.hasOwnProperty(key)) {
74
- this.setSingle(key, _[key]);
75
- }
76
- }
77
- }
78
-
79
- protected has<K extends keyof U>(key: K): boolean {
80
- return this._espState[key] !== void 0;
81
- }
82
-
83
- addObserver(eventID: StateEvents, callback: StateCallback): IObserverHandle;
84
- addObserver(eventID: StateEvents, propID: keyof U, callback: StatePropCallback): IObserverHandle;
85
- addObserver(eventID: StateEvents, propIDOrCallback: StateCallback | keyof U, callback?: StatePropCallback): IObserverHandle {
86
- if (this.isCallback(propIDOrCallback)) {
87
- if (eventID !== "changed") throw new Error("Invalid eventID: " + eventID);
88
- return this._dispatch.attach((messages: PropChangedMessage[]) => {
89
- propIDOrCallback(messages.map(m => ({
90
- id: m.property,
91
- oldValue: m.oldValue,
92
- newValue: m.newValue
93
- })));
94
- });
95
- } else {
96
- if (eventID !== "propChanged") throw new Error("Invalid eventID: " + eventID);
97
- return this._dispatch.attach((messages: PropChangedMessage[]) => {
98
- const filteredMessages = messages.filter(m => m.property === propIDOrCallback);
99
- if (filteredMessages.length) {
100
- if (filteredMessages.length > 1) {
101
- console.warn("Should only be 1 message?");
102
- }
103
- const event = filteredMessages[filteredMessages.length - 1];
104
- callback!({
105
- id: event.property,
106
- oldValue: event.oldValue,
107
- newValue: event.newValue
108
- });
109
- }
110
- });
111
- }
112
- }
113
-
114
- on(eventID: StateEvents, callback: StateCallback): this;
115
- on(eventID: StateEvents, propID: keyof U, callback: StatePropCallback): this;
116
- on(eventID: StateEvents, propIDOrCallback: StateCallback | keyof U, callback?: StatePropCallback): this {
117
- this.addObserver(eventID, propIDOrCallback as any, callback as any);
118
- return this;
119
- }
120
-
121
- protected isCallback(propIDOrCallback: StateCallback | keyof U): propIDOrCallback is StateCallback {
122
- return (typeof propIDOrCallback === "function");
123
- }
124
-
125
- protected hasEventListener(): boolean {
126
- return this._dispatch.hasObserver();
127
- }
128
-
129
- // Monitoring ---
130
- protected async refresh(full: boolean = false): Promise<this> {
131
- await Promise.resolve();
132
- return this;
133
- }
134
-
135
- protected _monitor(): void {
136
- if (this._monitorHandle) {
137
- this._monitorTickCount = 0;
138
- return;
139
- }
140
-
141
- this._monitorHandle = setTimeout(() => {
142
- const refreshPromise: Promise<any> = this.hasEventListener() ? this.refresh() : Promise.resolve();
143
- refreshPromise.then(() => {
144
- this._monitor();
145
- });
146
- delete this._monitorHandle;
147
- }, this._monitorTimeoutDuration());
148
- }
149
-
150
- protected _monitorTimeoutDuration(): number {
151
- ++this._monitorTickCount;
152
- if (this._monitorTickCount <= 1) { // Once
153
- return 0;
154
- }
155
- return 30000;
156
- }
157
-
158
- watch(callback: StateCallback, triggerChange: boolean = true): IObserverHandle {
159
- if (typeof callback !== "function") {
160
- throw new Error("Invalid Callback");
161
- }
162
- if (triggerChange) {
163
- setTimeout(() => {
164
- const props: any = this.get();
165
- const changes: IEvent[] = [];
166
- for (const key in props) {
167
- if (props.hasOwnProperty(props)) {
168
- changes.push({ id: key, newValue: props[key], oldValue: undefined });
169
- }
170
- }
171
- callback(changes);
172
- }, 0);
173
- }
174
- const retVal = this.addObserver("changed", callback);
175
- this._monitor();
176
- return retVal;
177
- }
178
- }
1
+ import { Dispatch, IObserverHandle, Message } from "./dispatch.ts";
2
+ import { deepEquals } from "./immutable.ts";
3
+
4
+ class PropChangedMessage extends Message {
5
+
6
+ constructor(readonly property: string, public newValue: any, public oldValue?: any) {
7
+ super();
8
+ }
9
+
10
+ get canConflate(): boolean { return true; }
11
+ conflate(other: PropChangedMessage) {
12
+ if (this.property === other.property) {
13
+ this.newValue = other.newValue;
14
+ return true;
15
+ }
16
+ return false;
17
+ }
18
+
19
+ void(): boolean {
20
+ return deepEquals(this.newValue, this.oldValue);
21
+ }
22
+ }
23
+
24
+ export interface IEvent {
25
+ id: string;
26
+ oldValue: any;
27
+ newValue: any;
28
+ }
29
+
30
+ export type StatePropCallback = (changes: IEvent) => void;
31
+ export type StateCallback = (changes: IEvent[]) => void;
32
+ export type StateEvents = "propChanged" | "changed";
33
+ export class StateObject<U, I> {
34
+ private _espState: Partial<U> = {} as U;
35
+ private _dispatch = new Dispatch<PropChangedMessage>();
36
+ private _monitorHandle?: any;
37
+ protected _monitorTickCount: number = 0;
38
+
39
+ protected clear(newVals?: Partial<I>) {
40
+ this._espState = {} as U;
41
+ if (newVals !== void 0) {
42
+ this.set(newVals as I);
43
+ }
44
+ this._monitorTickCount = 0;
45
+ }
46
+
47
+ protected get(): U;
48
+ protected get<K extends keyof U>(key: K, defValue?: U[K]): U[K];
49
+ protected get<K extends keyof U>(key?: K, defValue?: U[K]): Partial<U> | U[K] | undefined {
50
+ if (key === void 0) {
51
+ return this._espState;
52
+ }
53
+ return this.has(key) ? this._espState[key] : defValue;
54
+ }
55
+
56
+ protected set(newVals: I): void;
57
+ protected set<K extends keyof U>(key: K, newVal: U[K], batchMode?: boolean): void;
58
+ protected set<K extends keyof U>(keyOrNewVals: K | U, newVal?: U[K]): void {
59
+ if (typeof keyOrNewVals === "string") {
60
+ return this.setSingle(keyOrNewVals as any, newVal as U[K]); // TODO: "as any" should not be needed (TS >= 3.1.x)
61
+ }
62
+ this.setAll(keyOrNewVals as Partial<U>);
63
+ }
64
+
65
+ private setSingle<K extends keyof U>(key: K, newVal: U[K] | undefined): void {
66
+ const oldVal = this._espState[key];
67
+ this._espState[key] = newVal;
68
+ this._dispatch.post(new PropChangedMessage(key as string, newVal, oldVal));
69
+ }
70
+
71
+ private setAll(_: Partial<U>): void {
72
+ for (const key in _) {
73
+ if (_.hasOwnProperty(key)) {
74
+ this.setSingle(key, _[key]);
75
+ }
76
+ }
77
+ }
78
+
79
+ protected has<K extends keyof U>(key: K): boolean {
80
+ return this._espState[key] !== void 0;
81
+ }
82
+
83
+ addObserver(eventID: StateEvents, callback: StateCallback): IObserverHandle;
84
+ addObserver(eventID: StateEvents, propID: keyof U, callback: StatePropCallback): IObserverHandle;
85
+ addObserver(eventID: StateEvents, propIDOrCallback: StateCallback | keyof U, callback?: StatePropCallback): IObserverHandle {
86
+ if (this.isCallback(propIDOrCallback)) {
87
+ if (eventID !== "changed") throw new Error("Invalid eventID: " + eventID);
88
+ return this._dispatch.attach((messages: PropChangedMessage[]) => {
89
+ propIDOrCallback(messages.map(m => ({
90
+ id: m.property,
91
+ oldValue: m.oldValue,
92
+ newValue: m.newValue
93
+ })));
94
+ });
95
+ } else {
96
+ if (eventID !== "propChanged") throw new Error("Invalid eventID: " + eventID);
97
+ return this._dispatch.attach((messages: PropChangedMessage[]) => {
98
+ const filteredMessages = messages.filter(m => m.property === propIDOrCallback);
99
+ if (filteredMessages.length) {
100
+ if (filteredMessages.length > 1) {
101
+ console.warn("Should only be 1 message?");
102
+ }
103
+ const event = filteredMessages[filteredMessages.length - 1];
104
+ callback!({
105
+ id: event.property,
106
+ oldValue: event.oldValue,
107
+ newValue: event.newValue
108
+ });
109
+ }
110
+ });
111
+ }
112
+ }
113
+
114
+ on(eventID: StateEvents, callback: StateCallback): this;
115
+ on(eventID: StateEvents, propID: keyof U, callback: StatePropCallback): this;
116
+ on(eventID: StateEvents, propIDOrCallback: StateCallback | keyof U, callback?: StatePropCallback): this {
117
+ this.addObserver(eventID, propIDOrCallback as any, callback as any);
118
+ return this;
119
+ }
120
+
121
+ protected isCallback(propIDOrCallback: StateCallback | keyof U): propIDOrCallback is StateCallback {
122
+ return (typeof propIDOrCallback === "function");
123
+ }
124
+
125
+ protected hasEventListener(): boolean {
126
+ return this._dispatch.hasObserver();
127
+ }
128
+
129
+ // Monitoring ---
130
+ protected async refresh(full: boolean = false): Promise<this> {
131
+ await Promise.resolve();
132
+ return this;
133
+ }
134
+
135
+ protected _monitor(): void {
136
+ if (this._monitorHandle) {
137
+ this._monitorTickCount = 0;
138
+ return;
139
+ }
140
+
141
+ this._monitorHandle = setTimeout(() => {
142
+ const refreshPromise: Promise<any> = this.hasEventListener() ? this.refresh() : Promise.resolve();
143
+ refreshPromise.then(() => {
144
+ this._monitor();
145
+ });
146
+ delete this._monitorHandle;
147
+ }, this._monitorTimeoutDuration());
148
+ }
149
+
150
+ protected _monitorTimeoutDuration(): number {
151
+ ++this._monitorTickCount;
152
+ if (this._monitorTickCount <= 1) { // Once
153
+ return 0;
154
+ }
155
+ return 30000;
156
+ }
157
+
158
+ watch(callback: StateCallback, triggerChange: boolean = true): IObserverHandle {
159
+ if (typeof callback !== "function") {
160
+ throw new Error("Invalid Callback");
161
+ }
162
+ if (triggerChange) {
163
+ setTimeout(() => {
164
+ const props: any = this.get();
165
+ const changes: IEvent[] = [];
166
+ for (const key in props) {
167
+ if (props.hasOwnProperty(props)) {
168
+ changes.push({ id: key, newValue: props[key], oldValue: undefined });
169
+ }
170
+ }
171
+ callback(changes);
172
+ }, 0);
173
+ }
174
+ const retVal = this.addObserver("changed", callback);
175
+ this._monitor();
176
+ return retVal;
177
+ }
178
+ }
package/src/string.ts CHANGED
@@ -1,21 +1,21 @@
1
- export function trim(str: string, char: string): string {
2
- if (typeof char !== "string") return str;
3
- if (char.length === 0) return str;
4
- while (str.indexOf(char) === 0) {
5
- str = str.substring(1);
6
- }
7
- while (endsWith(str, char)) {
8
- str = str.substring(0, str.length - 1);
9
- }
10
- return str;
11
- }
12
-
13
- export function endsWith(origString: string, searchString: string, position?: number) {
14
- const subjectString = origString.toString();
15
- if (typeof position !== "number" || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
16
- position = subjectString.length;
17
- }
18
- position -= searchString.length;
19
- const lastIndex = subjectString.lastIndexOf(searchString, position);
20
- return lastIndex !== -1 && lastIndex === position;
21
- }
1
+ export function trim(str: string, char: string): string {
2
+ if (typeof char !== "string") return str;
3
+ if (char.length === 0) return str;
4
+ while (str.indexOf(char) === 0) {
5
+ str = str.substring(1);
6
+ }
7
+ while (endsWith(str, char)) {
8
+ str = str.substring(0, str.length - 1);
9
+ }
10
+ return str;
11
+ }
12
+
13
+ export function endsWith(origString: string, searchString: string, position?: number) {
14
+ const subjectString = origString.toString();
15
+ if (typeof position !== "number" || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
16
+ position = subjectString.length;
17
+ }
18
+ position -= searchString.length;
19
+ const lastIndex = subjectString.lastIndexOf(searchString, position);
20
+ return lastIndex !== -1 && lastIndex === position;
21
+ }
package/src/url.ts CHANGED
@@ -1,27 +1,27 @@
1
- export function join(...segments: string[]) {
2
- const parts: string[] = segments.reduce((parts: string[], segment) => {
3
- // Remove leading slashes from non-first part.
4
- if (parts.length > 0) {
5
- segment = segment.replace(/^\//, "");
6
- }
7
- // Remove trailing slashes.
8
- segment = segment.replace(/\/$/, "");
9
- return [...parts, ...segment.split("/")];
10
- }, []);
11
- const resultParts = [];
12
- for (const part of parts) {
13
- if (part === ".") {
14
- continue;
15
- }
16
- if (part === "..") {
17
- resultParts.pop();
18
- continue;
19
- }
20
- resultParts.push(part);
21
- }
22
- return resultParts.join("/");
23
- }
24
-
25
- export function dirname(path: string) {
26
- return join(path, "..");
27
- }
1
+ export function join(...segments: string[]) {
2
+ const parts: string[] = segments.reduce((parts: string[], segment) => {
3
+ // Remove leading slashes from non-first part.
4
+ if (parts.length > 0) {
5
+ segment = segment.replace(/^\//, "");
6
+ }
7
+ // Remove trailing slashes.
8
+ segment = segment.replace(/\/$/, "");
9
+ return [...parts, ...segment.split("/")];
10
+ }, []);
11
+ const resultParts = [];
12
+ for (const part of parts) {
13
+ if (part === ".") {
14
+ continue;
15
+ }
16
+ if (part === "..") {
17
+ resultParts.pop();
18
+ continue;
19
+ }
20
+ resultParts.push(part);
21
+ }
22
+ return resultParts.join("/");
23
+ }
24
+
25
+ export function dirname(path: string) {
26
+ return join(path, "..");
27
+ }
@@ -1,47 +1,47 @@
1
- const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2
-
3
- function toUTF8Bytes(value: string): Uint8Array {
4
- if (typeof TextEncoder !== "undefined") {
5
- return new TextEncoder().encode(value);
6
- }
7
-
8
- const encoded = encodeURIComponent(value);
9
- const bytes: number[] = [];
10
- for (let i = 0; i < encoded.length; ++i) {
11
- if (encoded[i] === "%") {
12
- bytes.push(parseInt(encoded.substring(i + 1, i + 3), 16));
13
- i += 2;
14
- } else {
15
- bytes.push(encoded.charCodeAt(i));
16
- }
17
- }
18
- return Uint8Array.from(bytes);
19
- }
20
-
21
- function bytesToBase64(bytes: Uint8Array): string {
22
- let output = "";
23
- for (let i = 0; i < bytes.length; i += 3) {
24
- const byte1 = bytes[i];
25
- const hasByte2 = i + 1 < bytes.length;
26
- const hasByte3 = i + 2 < bytes.length;
27
- const byte2 = hasByte2 ? bytes[i + 1] : 0;
28
- const byte3 = hasByte3 ? bytes[i + 2] : 0;
29
-
30
- output += BASE64_ALPHABET[byte1 >> 2];
31
- output += BASE64_ALPHABET[((byte1 & 0x03) << 4) | (byte2 >> 4)];
32
- output += hasByte2 ? BASE64_ALPHABET[((byte2 & 0x0f) << 2) | (byte3 >> 6)] : "=";
33
- output += hasByte3 ? BASE64_ALPHABET[byte3 & 0x3f] : "=";
34
- }
35
- return output;
36
- }
37
-
38
- export function utf8ToBase64(value: string = ""): string {
39
- const normalized = value == null ? "" : String(value);
40
-
41
- const maybeBuffer = (globalThis as any)?.Buffer;
42
- if (maybeBuffer?.from) {
43
- return maybeBuffer.from(normalized, "utf8").toString("base64");
44
- }
45
-
46
- return bytesToBase64(toUTF8Bytes(normalized));
47
- }
1
+ const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2
+
3
+ function toUTF8Bytes(value: string): Uint8Array {
4
+ if (typeof TextEncoder !== "undefined") {
5
+ return new TextEncoder().encode(value);
6
+ }
7
+
8
+ const encoded = encodeURIComponent(value);
9
+ const bytes: number[] = [];
10
+ for (let i = 0; i < encoded.length; ++i) {
11
+ if (encoded[i] === "%") {
12
+ bytes.push(parseInt(encoded.substring(i + 1, i + 3), 16));
13
+ i += 2;
14
+ } else {
15
+ bytes.push(encoded.charCodeAt(i));
16
+ }
17
+ }
18
+ return Uint8Array.from(bytes);
19
+ }
20
+
21
+ function bytesToBase64(bytes: Uint8Array): string {
22
+ let output = "";
23
+ for (let i = 0; i < bytes.length; i += 3) {
24
+ const byte1 = bytes[i];
25
+ const hasByte2 = i + 1 < bytes.length;
26
+ const hasByte3 = i + 2 < bytes.length;
27
+ const byte2 = hasByte2 ? bytes[i + 1] : 0;
28
+ const byte3 = hasByte3 ? bytes[i + 2] : 0;
29
+
30
+ output += BASE64_ALPHABET[byte1 >> 2];
31
+ output += BASE64_ALPHABET[((byte1 & 0x03) << 4) | (byte2 >> 4)];
32
+ output += hasByte2 ? BASE64_ALPHABET[((byte2 & 0x0f) << 2) | (byte3 >> 6)] : "=";
33
+ output += hasByte3 ? BASE64_ALPHABET[byte3 & 0x3f] : "=";
34
+ }
35
+ return output;
36
+ }
37
+
38
+ export function utf8ToBase64(value: string = ""): string {
39
+ const normalized = value == null ? "" : String(value);
40
+
41
+ const maybeBuffer = (globalThis as any)?.Buffer;
42
+ if (maybeBuffer?.from) {
43
+ return maybeBuffer.from(normalized, "utf8").toString("base64");
44
+ }
45
+
46
+ return bytesToBase64(toUTF8Bytes(normalized));
47
+ }