@esmalley/ts-utils 2.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +16 -27
- package/dist/cjs/index.js.map +7 -0
- package/dist/esm/index.js +16 -11
- package/dist/esm/index.js.map +7 -0
- package/dist/{cjs → types}/Kontororu/Socket.d.ts +9 -4
- package/dist/types/Kontororu/Socket.d.ts.map +1 -0
- package/package.json +9 -7
- package/dist/cjs/Arithmetic.js +0 -9
- package/dist/cjs/Arrayifier.js +0 -69
- package/dist/cjs/CSV.js +0 -39
- package/dist/cjs/Color.js +0 -348
- package/dist/cjs/Dates.js +0 -358
- package/dist/cjs/Kontororu/Socket.d.ts.map +0 -1
- package/dist/cjs/Kontororu/Socket.js +0 -221
- package/dist/cjs/Kontororu.js +0 -27
- package/dist/cjs/Objector.js +0 -124
- package/dist/cjs/Sorter.js +0 -32
- package/dist/cjs/Style.js +0 -475
- package/dist/cjs/Text.js +0 -39
- package/dist/cjs/Theme.js +0 -507
- package/dist/cjs/Toaster.js +0 -49
- package/dist/esm/Arithmetic.d.ts +0 -4
- package/dist/esm/Arithmetic.d.ts.map +0 -1
- package/dist/esm/Arithmetic.js +0 -5
- package/dist/esm/Arrayifier.d.ts +0 -29
- package/dist/esm/Arrayifier.d.ts.map +0 -1
- package/dist/esm/Arrayifier.js +0 -65
- package/dist/esm/CSV.d.ts +0 -10
- package/dist/esm/CSV.d.ts.map +0 -1
- package/dist/esm/CSV.js +0 -35
- package/dist/esm/Color.d.ts +0 -93
- package/dist/esm/Color.d.ts.map +0 -1
- package/dist/esm/Color.js +0 -344
- package/dist/esm/Dates.d.ts +0 -51
- package/dist/esm/Dates.d.ts.map +0 -1
- package/dist/esm/Dates.js +0 -354
- package/dist/esm/Kontororu/Socket.d.ts +0 -44
- package/dist/esm/Kontororu/Socket.d.ts.map +0 -1
- package/dist/esm/Kontororu/Socket.js +0 -218
- package/dist/esm/Kontororu.d.ts +0 -8
- package/dist/esm/Kontororu.d.ts.map +0 -1
- package/dist/esm/Kontororu.js +0 -23
- package/dist/esm/Objector.d.ts +0 -32
- package/dist/esm/Objector.d.ts.map +0 -1
- package/dist/esm/Objector.js +0 -120
- package/dist/esm/Sorter.d.ts +0 -8
- package/dist/esm/Sorter.d.ts.map +0 -1
- package/dist/esm/Sorter.js +0 -28
- package/dist/esm/Style.d.ts +0 -63
- package/dist/esm/Style.d.ts.map +0 -1
- package/dist/esm/Style.js +0 -471
- package/dist/esm/Text.d.ts +0 -5
- package/dist/esm/Text.d.ts.map +0 -1
- package/dist/esm/Text.js +0 -35
- package/dist/esm/Theme.d.ts +0 -1413
- package/dist/esm/Theme.d.ts.map +0 -1
- package/dist/esm/Theme.js +0 -503
- package/dist/esm/Toaster.d.ts +0 -24
- package/dist/esm/Toaster.d.ts.map +0 -1
- package/dist/esm/Toaster.js +0 -46
- package/dist/esm/index.d.ts +0 -12
- package/dist/esm/index.d.ts.map +0 -1
- /package/dist/{cjs → types}/Arithmetic.d.ts +0 -0
- /package/dist/{cjs → types}/Arithmetic.d.ts.map +0 -0
- /package/dist/{cjs → types}/Arrayifier.d.ts +0 -0
- /package/dist/{cjs → types}/Arrayifier.d.ts.map +0 -0
- /package/dist/{cjs → types}/CSV.d.ts +0 -0
- /package/dist/{cjs → types}/CSV.d.ts.map +0 -0
- /package/dist/{cjs → types}/Color.d.ts +0 -0
- /package/dist/{cjs → types}/Color.d.ts.map +0 -0
- /package/dist/{cjs → types}/Dates.d.ts +0 -0
- /package/dist/{cjs → types}/Dates.d.ts.map +0 -0
- /package/dist/{cjs → types}/Kontororu.d.ts +0 -0
- /package/dist/{cjs → types}/Kontororu.d.ts.map +0 -0
- /package/dist/{cjs → types}/Objector.d.ts +0 -0
- /package/dist/{cjs → types}/Objector.d.ts.map +0 -0
- /package/dist/{cjs → types}/Sorter.d.ts +0 -0
- /package/dist/{cjs → types}/Sorter.d.ts.map +0 -0
- /package/dist/{cjs → types}/Style.d.ts +0 -0
- /package/dist/{cjs → types}/Style.d.ts.map +0 -0
- /package/dist/{cjs → types}/Text.d.ts +0 -0
- /package/dist/{cjs → types}/Text.d.ts.map +0 -0
- /package/dist/{cjs → types}/Theme.d.ts +0 -0
- /package/dist/{cjs → types}/Theme.d.ts.map +0 -0
- /package/dist/{cjs → types}/Toaster.d.ts +0 -0
- /package/dist/{cjs → types}/Toaster.d.ts.map +0 -0
- /package/dist/{cjs → types}/index.d.ts +0 -0
- /package/dist/{cjs → types}/index.d.ts.map +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Socket.d.ts","sourceRoot":"","sources":["../../../src/Kontororu/Socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAS7C,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,WAAW,GAAG,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ,CAAA;AAUD,cAAM,MAAO,SAAQ,SAAS;IAC5B,OAAO,CAAC,EAAE,CAAC,CAAY;IAEvB,OAAO,CAAC,gBAAgB,CAAgC;IAExD,OAAO,CAAC,QAAQ,CAA4I;IAE5J,OAAO,CAAC,GAAG,CAAoE;IAE/E,OAAO,CAAC,UAAU,CAAC,CAAS;IAE5B,OAAO,CAAC,aAAa,CAAuB;IAG5C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,iBAAiB,CAAC,CAAiB;IAG3C,OAAO,CAAC,wBAAwB,CAAsB;IAEtD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAQ;IAE9C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA2C;IAEnF,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA2C;;IAyC5E,OAAO,CAAC,UAAU,EAAE,MAAM;IA+BjC;;;OAGG;IACI,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,aAAa;IAa1C,UAAU;IAYjB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;OAEG;IACH,OAAO,CAAC,eAAe;IAuBvB,OAAO,CAAC,WAAW;IA+BnB,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,YAAY;CAMrB;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.socket = void 0;
|
|
4
|
-
const Kontororu_js_1 = require("src/Kontororu.js");
|
|
5
|
-
const hostname = process.env.NEXT_PUBLIC_WS_HOST;
|
|
6
|
-
const port = process.env.NEXT_PUBLIC_WS_PORT;
|
|
7
|
-
const path = process.env.NEXT_PUBLIC_WS_PATH;
|
|
8
|
-
const debug = false;
|
|
9
|
-
class Socket extends Kontororu_js_1.Kontororu {
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
this.connection_state = 'connected';
|
|
13
|
-
this.protocol = (typeof window !== 'undefined' && window.location && window.location.protocol && window.location.protocol === 'https:' ? 'wss:' : 'ws:');
|
|
14
|
-
this.url = `${this.protocol}//${hostname}${port ? `:${port}` : ''}/${path}`;
|
|
15
|
-
this.message_queue = [];
|
|
16
|
-
// Reconnection logic
|
|
17
|
-
this.reconnect_attempts = 0;
|
|
18
|
-
this.should_reconnect = true;
|
|
19
|
-
// Heartbeat / Sleep Detection Logic
|
|
20
|
-
this.last_heartbeat_timestamp = Date.now();
|
|
21
|
-
// How often the server pings THIS specific client (5 seconds)
|
|
22
|
-
this.HEARTBEAT_INTERVAL_MS = 5000;
|
|
23
|
-
// Calculate threshold: 2 missed beats + 1 second of network jitter buffer
|
|
24
|
-
this.SUSPENSION_THRESHOLD_MS = (this.HEARTBEAT_INTERVAL_MS * 2) + 1000;
|
|
25
|
-
// 3 Heartbeats + 1s buffer = 16 seconds
|
|
26
|
-
this.DISCONNECT_THRESHOLD_MS = (this.HEARTBEAT_INTERVAL_MS * 3) + 1000;
|
|
27
|
-
if (typeof document !== 'undefined') {
|
|
28
|
-
document.addEventListener('visibilitychange', (event) => {
|
|
29
|
-
if (document.visibilityState === 'visible') {
|
|
30
|
-
this.check_staleness('tab_switch');
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
if (typeof window !== 'undefined') {
|
|
35
|
-
const offlineChecker = () => {
|
|
36
|
-
const check = 3;
|
|
37
|
-
let checked = 1;
|
|
38
|
-
const checker = () => {
|
|
39
|
-
if (checked > check) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
setTimeout(() => {
|
|
43
|
-
this.check_staleness('offline');
|
|
44
|
-
checked++;
|
|
45
|
-
checker();
|
|
46
|
-
}, (this.HEARTBEAT_INTERVAL_MS) + 500);
|
|
47
|
-
};
|
|
48
|
-
checker();
|
|
49
|
-
};
|
|
50
|
-
window.addEventListener('online', () => {
|
|
51
|
-
window.removeEventListener('offline', offlineChecker);
|
|
52
|
-
});
|
|
53
|
-
window.addEventListener('offline', offlineChecker);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
connect(session_id) {
|
|
57
|
-
if (!session_id) {
|
|
58
|
-
console.warn('session_id required to open ws');
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (this.ws &&
|
|
62
|
-
(this.ws.readyState === WebSocket.OPEN ||
|
|
63
|
-
this.ws.readyState === WebSocket.CONNECTING)) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
this.ws = new WebSocket(this.url);
|
|
67
|
-
if (debug)
|
|
68
|
-
console.log('new websocket');
|
|
69
|
-
this.session_id = session_id;
|
|
70
|
-
// Reset heartbeat timer on new connection
|
|
71
|
-
this.last_heartbeat_timestamp = Date.now();
|
|
72
|
-
this.ws.addEventListener('open', (event) => this.handle_open(event));
|
|
73
|
-
this.ws.addEventListener('message', (event) => this.handle_message(event));
|
|
74
|
-
this.ws.addEventListener('close', (event) => this.handle_close(event));
|
|
75
|
-
this.ws.addEventListener('error', (event) => this.handle_error(event));
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Send message if the websocket is open,
|
|
79
|
-
* otherwise add it to the message queue
|
|
80
|
-
*/
|
|
81
|
-
message({ type, table, id }) {
|
|
82
|
-
const payload = { type, table, id };
|
|
83
|
-
if (this.ws &&
|
|
84
|
-
this.ws.readyState === WebSocket.OPEN) {
|
|
85
|
-
this.ws.send(JSON.stringify(payload));
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
this.message_queue.push(payload);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
disconnect() {
|
|
92
|
-
if (debug)
|
|
93
|
-
console.log('websocket disconnect()');
|
|
94
|
-
this.update_connection_state('disconnected');
|
|
95
|
-
// if we are manually disconnecting we do not want an auto reconnect
|
|
96
|
-
this.should_reconnect = false;
|
|
97
|
-
this.ws?.close();
|
|
98
|
-
this.ws = undefined;
|
|
99
|
-
if (this.reconnect_timeout) {
|
|
100
|
-
clearTimeout(this.reconnect_timeout);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Update the connection state, dispatch an event if it actually changed.
|
|
105
|
-
*/
|
|
106
|
-
update_connection_state(new_connection_state) {
|
|
107
|
-
const old_connection_state = this.connection_state;
|
|
108
|
-
if (this.connection_state !== new_connection_state) {
|
|
109
|
-
if (debug)
|
|
110
|
-
console.log('update_connection_state', new_connection_state);
|
|
111
|
-
this.connection_state = new_connection_state;
|
|
112
|
-
if (debug)
|
|
113
|
-
console.warn(`[Socket] State changed to: ${this.connection_state}`);
|
|
114
|
-
this.dispatchEvent(new CustomEvent('connection_state', { detail: this.connection_state }));
|
|
115
|
-
if ((new_connection_state === 'connected' || new_connection_state === 'reconnected') &&
|
|
116
|
-
(old_connection_state === 'stale' || old_connection_state === 'disconnected')) {
|
|
117
|
-
this.dispatchEvent(new CustomEvent('refresh', { bubbles: true }));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Helper to determine if we need to fetch missing data
|
|
123
|
-
*/
|
|
124
|
-
check_staleness(source) {
|
|
125
|
-
const now = Date.now();
|
|
126
|
-
const time_since_last = now - this.last_heartbeat_timestamp;
|
|
127
|
-
if (debug)
|
|
128
|
-
console.log('websocket check_staleness()', source, time_since_last);
|
|
129
|
-
if (!this.ws ||
|
|
130
|
-
this.ws.readyState === this.ws.CLOSED ||
|
|
131
|
-
time_since_last > this.DISCONNECT_THRESHOLD_MS) {
|
|
132
|
-
this.update_connection_state('disconnected');
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
// If gap is larger than threshold, we missed messages
|
|
136
|
-
if (time_since_last > this.SUSPENSION_THRESHOLD_MS) {
|
|
137
|
-
this.update_connection_state('stale');
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
this.update_connection_state('connected');
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
handle_open(event) {
|
|
144
|
-
if (debug)
|
|
145
|
-
console.log('websocket handle open()');
|
|
146
|
-
if (this.ws &&
|
|
147
|
-
this.ws.readyState === this.ws.OPEN) {
|
|
148
|
-
this.update_connection_state('connected');
|
|
149
|
-
}
|
|
150
|
-
// clear reconnect timeout if we connected
|
|
151
|
-
if (this.reconnect_timeout) {
|
|
152
|
-
clearTimeout(this.reconnect_timeout);
|
|
153
|
-
}
|
|
154
|
-
// If we are reconnecting (attempts > 0), we definitely missed data.
|
|
155
|
-
if (this.reconnect_attempts > 0) {
|
|
156
|
-
if (debug)
|
|
157
|
-
console.log('[Socket] Reconnected. Triggering refresh.');
|
|
158
|
-
this.dispatchEvent(new CustomEvent('refresh', { bubbles: true }));
|
|
159
|
-
}
|
|
160
|
-
// reset the reconnect attempts
|
|
161
|
-
this.reconnect_attempts = 0;
|
|
162
|
-
this.ws?.send(JSON.stringify({ type: 'session', table: 'session', id: this.session_id }));
|
|
163
|
-
while (this.message_queue.length > 0) {
|
|
164
|
-
const queuedMsg = this.message_queue.shift();
|
|
165
|
-
this.ws?.send(JSON.stringify(queuedMsg));
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
handle_message(event) {
|
|
169
|
-
if (debug)
|
|
170
|
-
console.log('websocket handle message()');
|
|
171
|
-
try {
|
|
172
|
-
const data = JSON.parse(event.data);
|
|
173
|
-
if (debug)
|
|
174
|
-
console.log('data', data);
|
|
175
|
-
// HEARTBEAT CHECK: Intercept heartbeat messages
|
|
176
|
-
if (data.type === 'heartbeat') {
|
|
177
|
-
this.check_staleness('heartbeat');
|
|
178
|
-
this.last_heartbeat_timestamp = Date.now();
|
|
179
|
-
return; // Do not bubble 'heartbeat' to the UI
|
|
180
|
-
}
|
|
181
|
-
// todo not sure I like this
|
|
182
|
-
const messageEvent = new CustomEvent('message', {
|
|
183
|
-
detail: JSON.parse(event.data),
|
|
184
|
-
bubbles: true,
|
|
185
|
-
});
|
|
186
|
-
this.dispatchEvent(messageEvent);
|
|
187
|
-
}
|
|
188
|
-
catch (e) {
|
|
189
|
-
const messageEvent = new CustomEvent('message', {
|
|
190
|
-
detail: event.data,
|
|
191
|
-
bubbles: true,
|
|
192
|
-
});
|
|
193
|
-
this.dispatchEvent(messageEvent);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
handle_close(event) {
|
|
197
|
-
if (debug)
|
|
198
|
-
console.log('websocket handle close()');
|
|
199
|
-
this.update_connection_state('disconnected');
|
|
200
|
-
if (this.should_reconnect) {
|
|
201
|
-
const delay = Math.min(1000 * Math.pow(2, this.reconnect_attempts), 30000);
|
|
202
|
-
if (debug)
|
|
203
|
-
console.log(`Connection lost. Retrying in ${delay}ms... (Attempt ${this.reconnect_attempts + 1})`);
|
|
204
|
-
this.reconnect_timeout = setTimeout(() => {
|
|
205
|
-
this.reconnect_attempts++;
|
|
206
|
-
if (this.session_id) {
|
|
207
|
-
this.connect(this.session_id);
|
|
208
|
-
}
|
|
209
|
-
}, delay);
|
|
210
|
-
}
|
|
211
|
-
this.ws = undefined;
|
|
212
|
-
}
|
|
213
|
-
handle_error(event) {
|
|
214
|
-
if (debug)
|
|
215
|
-
console.log('websocket handle error()');
|
|
216
|
-
this.update_connection_state('disconnected');
|
|
217
|
-
console.error('WebSocket Error:', event);
|
|
218
|
-
this.ws?.close();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
exports.socket = new Socket();
|
package/dist/cjs/Kontororu.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// コントロール
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.Kontororu = void 0;
|
|
5
|
-
class Kontororu extends EventTarget {
|
|
6
|
-
constructor() {
|
|
7
|
-
super();
|
|
8
|
-
this.listeners = {};
|
|
9
|
-
}
|
|
10
|
-
addEventListener(type, listener) {
|
|
11
|
-
super.addEventListener(type, listener);
|
|
12
|
-
if (!this.listeners[type]) {
|
|
13
|
-
this.listeners[type] = [];
|
|
14
|
-
}
|
|
15
|
-
this.listeners[type].push(listener);
|
|
16
|
-
}
|
|
17
|
-
removeEventListener(type, listener) {
|
|
18
|
-
super.removeEventListener(type, listener);
|
|
19
|
-
if (this.listeners[type]) {
|
|
20
|
-
this.listeners[type] = this.listeners[type].filter((l) => l !== listener);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
getListeners(type) {
|
|
24
|
-
return this.listeners[type] || [];
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
exports.Kontororu = Kontororu;
|
package/dist/cjs/Objector.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/* eslint-disable no-restricted-syntax */
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.Objector = void 0;
|
|
5
|
-
/**
|
|
6
|
-
* Class to manipulate objects
|
|
7
|
-
*/
|
|
8
|
-
class Objector {
|
|
9
|
-
// constructor() {
|
|
10
|
-
// }
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
-
static deepClone(obj, memo = new WeakMap()) {
|
|
13
|
-
// Check if the input is null or not an object/array
|
|
14
|
-
if (obj === null || typeof obj !== 'object') {
|
|
15
|
-
return obj;
|
|
16
|
-
}
|
|
17
|
-
// Check if the object is already in the memo
|
|
18
|
-
if (memo.has(obj)) {
|
|
19
|
-
return memo.get(obj);
|
|
20
|
-
}
|
|
21
|
-
// Handle built-in types
|
|
22
|
-
if (obj instanceof Date) {
|
|
23
|
-
return new Date(obj.getTime());
|
|
24
|
-
}
|
|
25
|
-
if (obj instanceof RegExp) {
|
|
26
|
-
return new RegExp(obj.source, obj.flags);
|
|
27
|
-
}
|
|
28
|
-
if (obj instanceof Map) {
|
|
29
|
-
const clonedMap = new Map();
|
|
30
|
-
memo.set(obj, clonedMap);
|
|
31
|
-
obj.forEach((value, key) => clonedMap.set(key, Objector.deepClone(value, memo)));
|
|
32
|
-
return clonedMap;
|
|
33
|
-
}
|
|
34
|
-
if (obj instanceof Set) {
|
|
35
|
-
const newSet = new Set();
|
|
36
|
-
for (const item of obj) {
|
|
37
|
-
newSet.add(Objector.deepClone(item));
|
|
38
|
-
}
|
|
39
|
-
return newSet;
|
|
40
|
-
}
|
|
41
|
-
// Handle arrays
|
|
42
|
-
if (Array.isArray(obj)) {
|
|
43
|
-
const clonedArray = obj.map((item) => Objector.deepClone(item, memo));
|
|
44
|
-
memo.set(obj, clonedArray);
|
|
45
|
-
return clonedArray;
|
|
46
|
-
}
|
|
47
|
-
// Handle objects
|
|
48
|
-
const clonedObj = Object.create(Object.getPrototypeOf(obj));
|
|
49
|
-
memo.set(obj, clonedObj);
|
|
50
|
-
// Cast the source 'obj' to a record so we can read its keys dynamically
|
|
51
|
-
const sourceObj = obj;
|
|
52
|
-
// per Gemini
|
|
53
|
-
/**
|
|
54
|
-
* While it appears to be two steps, the first step (Object.keys()) is a native C++ function in the JavaScript engine.
|
|
55
|
-
* It's highly optimized for this specific task and is often faster than the JIT compiler can make the for...in loop with its conditional checks.
|
|
56
|
-
*/
|
|
57
|
-
Object.keys(sourceObj).forEach((key) => {
|
|
58
|
-
clonedObj[key] = Objector.deepClone(sourceObj[key], memo);
|
|
59
|
-
});
|
|
60
|
-
/*
|
|
61
|
-
for (const key in obj) {
|
|
62
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
63
|
-
clonedObj[key] = Objector.deepClone(obj[key], memo);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
*/
|
|
67
|
-
// Symbol keys
|
|
68
|
-
Object.getOwnPropertySymbols(sourceObj).forEach((sym) => {
|
|
69
|
-
if (Object.prototype.propertyIsEnumerable.call(sourceObj, sym)) {
|
|
70
|
-
clonedObj[sym] = Objector.deepClone(sourceObj[sym], memo);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
return clonedObj;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Deeply merges one or more source objects into a target object.
|
|
77
|
-
*
|
|
78
|
-
* - Each property from the sources is deep-cloned before being assigned.
|
|
79
|
-
* - Existing properties in the target are overwritten by matching keys in later sources.
|
|
80
|
-
* - Does not use spread or Object.assign.
|
|
81
|
-
* - Mutates and returns the target object.
|
|
82
|
-
*
|
|
83
|
-
* @template T - The type of the target object.
|
|
84
|
-
* @param {T} target - The object to extend.
|
|
85
|
-
* @param {...U[]} sources - One or more source objects whose properties will be copied to the target.
|
|
86
|
-
* @returns {T & U} The mutated target object containing all deep-cloned properties from the sources.
|
|
87
|
-
*
|
|
88
|
-
* @throws {TypeError} If the target is null or undefined.
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* const target = { a: 1 };
|
|
92
|
-
* const source = { b: { nested: 2 } };
|
|
93
|
-
* Objector.extender(target, source);
|
|
94
|
-
* // target is now { a: 1, b: { nested: 2 } }
|
|
95
|
-
*/
|
|
96
|
-
static extender(target, ...sources) {
|
|
97
|
-
if (target == null) {
|
|
98
|
-
throw new TypeError('Cannot convert undefined or null to object');
|
|
99
|
-
}
|
|
100
|
-
const to = Object(target);
|
|
101
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
102
|
-
for (const source of sources) {
|
|
103
|
-
if (source != null) {
|
|
104
|
-
// Cast the source to an indexable record
|
|
105
|
-
const s = source;
|
|
106
|
-
// String keys
|
|
107
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
108
|
-
for (const key of Object.keys(s)) {
|
|
109
|
-
to[key] = Objector.deepClone(s[key]);
|
|
110
|
-
}
|
|
111
|
-
// Symbol keys
|
|
112
|
-
const symbols = Object.getOwnPropertySymbols(s);
|
|
113
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
114
|
-
for (const sym of symbols) {
|
|
115
|
-
if (Object.prototype.propertyIsEnumerable.call(s, sym)) {
|
|
116
|
-
to[sym] = Objector.deepClone(s[sym]);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return to;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
exports.Objector = Objector;
|
package/dist/cjs/Sorter.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Sorter = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Table sorting helper utility
|
|
6
|
-
*/
|
|
7
|
-
class Sorter {
|
|
8
|
-
static descendingComparator(a, b, orderBy, direction_) {
|
|
9
|
-
if ((orderBy in a) && b[orderBy] === null) {
|
|
10
|
-
return 1;
|
|
11
|
-
}
|
|
12
|
-
if (a[orderBy] === null && (orderBy in b)) {
|
|
13
|
-
return -1;
|
|
14
|
-
}
|
|
15
|
-
const a_value = a[orderBy];
|
|
16
|
-
const b_value = b[orderBy];
|
|
17
|
-
const direction = direction_ || 'lower';
|
|
18
|
-
if (b_value < a_value) {
|
|
19
|
-
return direction === 'higher' ? 1 : -1;
|
|
20
|
-
}
|
|
21
|
-
if (b_value > a_value) {
|
|
22
|
-
return direction === 'higher' ? -1 : 1;
|
|
23
|
-
}
|
|
24
|
-
return 0;
|
|
25
|
-
}
|
|
26
|
-
static getComparator(order, orderBy, direction) {
|
|
27
|
-
return order === 'desc'
|
|
28
|
-
? (a, b) => this.descendingComparator(a, b, orderBy, direction)
|
|
29
|
-
: (a, b) => -this.descendingComparator(a, b, orderBy, direction);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
exports.Sorter = Sorter;
|