@xh/hoist 76.0.0-SNAPSHOT.1756402657806 → 76.0.0-SNAPSHOT.1756431654493
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/CHANGELOG.md +6 -3
- package/build/types/core/XH.d.ts +13 -0
- package/build/types/utils/js/LogUtils.d.ts +30 -2
- package/cmp/grid/impl/Utils.ts +2 -1
- package/core/HoistComponent.ts +10 -9
- package/core/XH.ts +19 -0
- package/core/exception/ExceptionHandler.ts +1 -1
- package/core/load/LoadSupport.ts +1 -1
- package/data/filter/Utils.ts +2 -1
- package/desktop/cmp/dash/container/impl/DashContainerUtils.ts +4 -3
- package/inspector/instances/InstancesModel.ts +2 -2
- package/kit/ag-grid/index.ts +2 -2
- package/kit/highcharts/index.ts +2 -2
- package/package.json +1 -1
- package/promise/Promise.ts +0 -13
- package/svc/FetchService.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/utils/js/LangUtils.ts +3 -3
- package/utils/js/LogUtils.ts +74 -11
package/CHANGELOG.md
CHANGED
|
@@ -17,12 +17,15 @@
|
|
|
17
17
|
* Handled an edge-case `ViewManager` bug where `enableDefault` changed to `false` after some user
|
|
18
18
|
state had already been persisted w/users pointed at in-code default view. The manager now calls
|
|
19
19
|
its configured `initialViewSpec` function as expected in this case.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Requires hoist-core v31.2
|
|
20
|
+
* `XH.restoreDefaultsAsync` will now clear basic ViewManager state, notably last active view. User
|
|
21
|
+
views themselves will be preserved. Requires `hoist-core >= 31.2`.
|
|
23
22
|
|
|
24
23
|
### ⚙️ Technical
|
|
25
24
|
|
|
25
|
+
* Hoist's client-side logging utilities are now governed by the new `XH.logLevel` property, defining
|
|
26
|
+
a logging severity threshold for the app. Default level is 'info', preventing memory usage and
|
|
27
|
+
performance impacts from verbose logging on level 'debug'. This level can be changed at runtime
|
|
28
|
+
for troubleshooting. See documentation within `LogUtils.ts` for more info.
|
|
26
29
|
* Added control to trigger browser GC from app footer. Useful for troubleshooting memory issues.
|
|
27
30
|
Requires running chromium-based browser via e.g. `start chrome --js-flags="--expose-gc`.
|
|
28
31
|
|
package/build/types/core/XH.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { RouterModel } from '@xh/hoist/appcontainer/RouterModel';
|
|
|
2
2
|
import { HoistAuthModel } from '@xh/hoist/core/HoistAuthModel';
|
|
3
3
|
import { Store } from '@xh/hoist/data';
|
|
4
4
|
import { AlertBannerService, AutoRefreshService, ChangelogService, ConfigService, EnvironmentService, FetchOptions, FetchService, GridAutosizeService, GridExportService, IdentityService, IdleService, InspectorService, JsonBlobService, LocalStorageService, PrefService, SessionStorageService, TrackService, WebSocketService, ClientHealthService } from '@xh/hoist/svc';
|
|
5
|
+
import { LogLevel } from '@xh/hoist/utils/js';
|
|
5
6
|
import { Router, State } from 'router5';
|
|
6
7
|
import { CancelFn } from 'router5/types/types/base';
|
|
7
8
|
import { SetOptional } from 'type-fest';
|
|
@@ -177,6 +178,18 @@ export declare class XHApi {
|
|
|
177
178
|
* @see HoistAuthModel.logoutAsync
|
|
178
179
|
*/
|
|
179
180
|
logoutAsync(): Promise<void>;
|
|
181
|
+
/**
|
|
182
|
+
* Current minimum severity for Hoist log utils (default 'info').
|
|
183
|
+
* Messages logged via managed Hoist log utils with lower severity will be ignored.
|
|
184
|
+
*/
|
|
185
|
+
get logLevel(): LogLevel;
|
|
186
|
+
/**
|
|
187
|
+
* Set the minimum severity for Hoist log utils until the page is refreshed. Optionally persist
|
|
188
|
+
* this adjustment to sessionStorage to maintain for the lifetime of the browser tab.
|
|
189
|
+
*
|
|
190
|
+
* Hint: call this method from the console to adjust your app's log level while troubleshooting.
|
|
191
|
+
*/
|
|
192
|
+
setLogLevel(level: LogLevel, persistInSessionStorage?: boolean): void;
|
|
180
193
|
/**
|
|
181
194
|
* Main entry point to start the client app - initializes and renders application code.
|
|
182
195
|
* Call from the app's entry-point file within your project's `/client-app/src/apps/` folder.
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import { Some } from '@xh/hoist/core';
|
|
2
|
+
/**
|
|
3
|
+
* Utility functions providing managed, structured logging to Hoist apps.
|
|
4
|
+
*
|
|
5
|
+
* Essentially a wrapper around the browser console supporting logging levels, timing, and
|
|
6
|
+
* miscellaneous Hoist display conventions.
|
|
7
|
+
*
|
|
8
|
+
* Objects extending `HoistBase` need not import these functions directly, as they are available
|
|
9
|
+
* via delegates on `HoistBase`.
|
|
10
|
+
*
|
|
11
|
+
* Hoist sets its minimum severity level to 'info' by default. This prevents performance or
|
|
12
|
+
* memory impacts that might result from verbose debug logging. This can be adjusted by calling
|
|
13
|
+
* XH.logLevel from the console.
|
|
14
|
+
*/
|
|
15
|
+
/** Severity Level for log statement */
|
|
16
|
+
export type LogLevel = 'error' | 'warn' | 'info' | 'debug';
|
|
17
|
+
/** Object identifying the source of log statement. Typically, a javascript class */
|
|
2
18
|
export type LogSource = string | {
|
|
3
19
|
displayName: string;
|
|
4
20
|
} | {
|
|
@@ -6,6 +22,20 @@ export type LogSource = string | {
|
|
|
6
22
|
name: string;
|
|
7
23
|
};
|
|
8
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Current minimum severity for Hoist log utils (default 'info').
|
|
27
|
+
* Messages logged via managed Hoist log utils with lower severity will be ignored.
|
|
28
|
+
*
|
|
29
|
+
* @internal - use public `XH.logLevel`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getLogLevel(): LogLevel;
|
|
32
|
+
/**
|
|
33
|
+
* Set the minimum severity for Hoist log utils until the page is refreshed. Optionally persist
|
|
34
|
+
* this adjustment to sessionStorage to maintain for the lifetime of the browser tab.
|
|
35
|
+
*
|
|
36
|
+
* @internal - use public `XH.setLogLevel()`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function setLogLevel(level: LogLevel, persistInSessionStorage?: boolean): void;
|
|
9
39
|
/**
|
|
10
40
|
* Time and log execution of a function to `console.info()`.
|
|
11
41
|
*
|
|
@@ -50,5 +80,3 @@ export declare function logError(msgs: Some<unknown>, source?: LogSource): unkno
|
|
|
50
80
|
* @param source - class, function or string to label the source of the message
|
|
51
81
|
*/
|
|
52
82
|
export declare function logWarn(msgs: Some<unknown>, source?: LogSource): unknown;
|
|
53
|
-
/** Parse a LogSource in to a canonical string label. */
|
|
54
|
-
export declare function parseSource(source: LogSource): string;
|
package/cmp/grid/impl/Utils.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import {Column, ColumnGroup, ColumnRenderer, GroupRowRenderer} from '@xh/hoist/cmp/grid';
|
|
8
8
|
import {HeaderClassParams} from '@xh/hoist/kit/ag-grid';
|
|
9
|
+
import {logWarn} from '@xh/hoist/utils/js';
|
|
9
10
|
import {castArray, isFunction} from 'lodash';
|
|
10
11
|
|
|
11
12
|
/** @internal */
|
|
@@ -18,7 +19,7 @@ export function managedRenderer<T extends ColumnRenderer | GroupRowRenderer>(
|
|
|
18
19
|
try {
|
|
19
20
|
return fn.apply(null, arguments);
|
|
20
21
|
} catch (e) {
|
|
21
|
-
|
|
22
|
+
logWarn([`Renderer for '${identifier}' has thrown an error`, e]);
|
|
22
23
|
return '#ERROR';
|
|
23
24
|
}
|
|
24
25
|
} as unknown as T;
|
package/core/HoistComponent.ts
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
formatSelector,
|
|
26
26
|
HoistModel
|
|
27
27
|
} from './model';
|
|
28
|
-
import {throwIf, warnIf, withDefault} from '@xh/hoist/utils/js';
|
|
28
|
+
import {logError, throwIf, warnIf, withDefault} from '@xh/hoist/utils/js';
|
|
29
29
|
import {getLayoutProps, useOnMount, useOnUnmount} from '@xh/hoist/utils/react';
|
|
30
30
|
import classNames from 'classnames';
|
|
31
31
|
import {isFunction, isPlainObject, isObject} from 'lodash';
|
|
@@ -285,11 +285,11 @@ function wrapWithModel(render: RenderFn, cfg: Config): RenderFn {
|
|
|
285
285
|
|
|
286
286
|
// 2) Validate
|
|
287
287
|
if (!model && !spec.optional && spec instanceof UsesSpec) {
|
|
288
|
-
|
|
289
|
-
Failed to find model with selector '${formatSelector(spec.selector)}'
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
288
|
+
logError(
|
|
289
|
+
`Failed to find model with selector '${formatSelector(spec.selector)}'. Ensure the
|
|
290
|
+
proper model is available via context, or specify using the 'model' prop.`,
|
|
291
|
+
cfg.displayName
|
|
292
|
+
);
|
|
293
293
|
return cmpErrDisplay({...getLayoutProps(props), item: 'No model found'});
|
|
294
294
|
}
|
|
295
295
|
|
|
@@ -408,10 +408,11 @@ function lookupModel(props: HoistProps, modelLookup: ModelLookup, cfg: Config):
|
|
|
408
408
|
// 2) props - instance
|
|
409
409
|
if (model) {
|
|
410
410
|
if (!model.isHoistModel || !model.matchesSelector(selector, true)) {
|
|
411
|
-
|
|
412
|
-
`Incorrect model passed
|
|
411
|
+
logError(
|
|
412
|
+
`Incorrect model passed.
|
|
413
413
|
Expected: ${formatSelector(selector)}
|
|
414
|
-
Received: ${model.constructor.name}
|
|
414
|
+
Received: ${model.constructor.name}`,
|
|
415
|
+
cfg.displayName
|
|
415
416
|
);
|
|
416
417
|
model = null;
|
|
417
418
|
}
|
package/core/XH.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
WebSocketService,
|
|
32
32
|
ClientHealthService
|
|
33
33
|
} from '@xh/hoist/svc';
|
|
34
|
+
import {getLogLevel, setLogLevel, LogLevel} from '@xh/hoist/utils/js';
|
|
34
35
|
import {camelCase, flatten, isString, uniqueId} from 'lodash';
|
|
35
36
|
import {Router, State} from 'router5';
|
|
36
37
|
import {CancelFn} from 'router5/types/types/base';
|
|
@@ -360,6 +361,24 @@ export class XHApi {
|
|
|
360
361
|
this.reloadApp();
|
|
361
362
|
}
|
|
362
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Current minimum severity for Hoist log utils (default 'info').
|
|
366
|
+
* Messages logged via managed Hoist log utils with lower severity will be ignored.
|
|
367
|
+
*/
|
|
368
|
+
get logLevel(): LogLevel {
|
|
369
|
+
return getLogLevel();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Set the minimum severity for Hoist log utils until the page is refreshed. Optionally persist
|
|
374
|
+
* this adjustment to sessionStorage to maintain for the lifetime of the browser tab.
|
|
375
|
+
*
|
|
376
|
+
* Hint: call this method from the console to adjust your app's log level while troubleshooting.
|
|
377
|
+
*/
|
|
378
|
+
setLogLevel(level: LogLevel, persistInSessionStorage: boolean = false) {
|
|
379
|
+
setLogLevel(level, persistInSessionStorage);
|
|
380
|
+
}
|
|
381
|
+
|
|
363
382
|
//----------------------
|
|
364
383
|
// App lifecycle support
|
|
365
384
|
//----------------------
|
|
@@ -312,7 +312,7 @@ export class ExceptionHandler {
|
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
private logException(e: HoistException, opts: ExceptionHandlerOptions) {
|
|
315
|
-
return opts.showAsError ?
|
|
315
|
+
return opts.showAsError ? logError([opts.message, e], this) : logDebug(opts.message, this);
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
private parseOptions(
|
package/core/load/LoadSupport.ts
CHANGED
|
@@ -135,7 +135,7 @@ export async function loadAllAsync(objs: Loadable[], loadSpec?: LoadSpec | any)
|
|
|
135
135
|
ret = await Promise.allSettled(promises);
|
|
136
136
|
|
|
137
137
|
ret.filter(it => it.status === 'rejected').forEach((err: any) =>
|
|
138
|
-
|
|
138
|
+
logError(['Failed to Load Object', err.reason])
|
|
139
139
|
);
|
|
140
140
|
|
|
141
141
|
return ret;
|
package/data/filter/Utils.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import {Some} from '@xh/hoist/core';
|
|
9
9
|
import {CompoundFilter, FunctionFilter} from '@xh/hoist/data';
|
|
10
|
+
import {logError} from '@xh/hoist/utils/js';
|
|
10
11
|
import {castArray, flatMap, groupBy, isArray, isFunction} from 'lodash';
|
|
11
12
|
import {FieldFilter} from './FieldFilter';
|
|
12
13
|
import {Filter} from './Filter';
|
|
@@ -55,7 +56,7 @@ export function parseFilter(spec: FilterLike): Filter {
|
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
logError(['Unable to identify filter type:', s]);
|
|
59
60
|
return null;
|
|
60
61
|
}
|
|
61
62
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import {PlainObject} from '@xh/hoist/core';
|
|
8
8
|
import {DashContainerModel} from '@xh/hoist/desktop/cmp/dash';
|
|
9
9
|
import {serializeIcon} from '@xh/hoist/icon';
|
|
10
|
-
import {throwIf} from '@xh/hoist/utils/js';
|
|
10
|
+
import {logDebug, throwIf} from '@xh/hoist/utils/js';
|
|
11
11
|
import {isArray, isEmpty, isFinite, isNil, isPlainObject, isString, round} from 'lodash';
|
|
12
12
|
import {DashContainerViewSpec} from '../DashContainerViewSpec';
|
|
13
13
|
import GoldenLayout, {ContentItem} from 'golden-layout';
|
|
@@ -119,8 +119,9 @@ function convertStateToGLInner(items = [], viewSpecs = [], containerSize, contai
|
|
|
119
119
|
const viewSpec = viewSpecs.find(v => v.id === item.id);
|
|
120
120
|
|
|
121
121
|
if (!viewSpec) {
|
|
122
|
-
|
|
123
|
-
`Attempted to load non-existent or omitted view from state: ${item.id}
|
|
122
|
+
logDebug(
|
|
123
|
+
`Attempted to load non-existent or omitted view from state: ${item.id}`,
|
|
124
|
+
'DashContainer'
|
|
124
125
|
);
|
|
125
126
|
return null;
|
|
126
127
|
}
|
|
@@ -130,7 +130,7 @@ export class InstancesModel extends HoistModel {
|
|
|
130
130
|
instance = this.getInstance(xhId);
|
|
131
131
|
|
|
132
132
|
if (!instance) {
|
|
133
|
-
|
|
133
|
+
this.logWarn(`Instance with xhId ${xhId} no longer alive - cannot be logged`);
|
|
134
134
|
} else {
|
|
135
135
|
console.log(`[${xhId}]`, instance);
|
|
136
136
|
XH.toast({
|
|
@@ -147,7 +147,7 @@ export class InstancesModel extends HoistModel {
|
|
|
147
147
|
instance = this.getInstance(instanceXhId);
|
|
148
148
|
|
|
149
149
|
if (!instance) {
|
|
150
|
-
|
|
150
|
+
this.logWarn(`Instance ${instanceDisplayName} no longer alive - cannot be logged`);
|
|
151
151
|
} else {
|
|
152
152
|
console.log(`[${instanceDisplayName}].${property}`, instance[property]);
|
|
153
153
|
XH.toast({
|
package/kit/ag-grid/index.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Copyright © 2025 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {checkVersion} from '@xh/hoist/utils/js
|
|
8
|
+
import {checkVersion, logError} from '@xh/hoist/utils/js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* The exports below are ag-Grid components provided at runtime by applications.
|
|
@@ -57,7 +57,7 @@ const MAX_VERSION = '31.*.*';
|
|
|
57
57
|
*/
|
|
58
58
|
export function installAgGrid(ComponentReactWrapper, version: string) {
|
|
59
59
|
if (!checkVersion(version, MIN_VERSION, MAX_VERSION)) {
|
|
60
|
-
|
|
60
|
+
logError(
|
|
61
61
|
`This version of Hoist requires an ag-Grid version between ${MIN_VERSION} and ` +
|
|
62
62
|
`${MAX_VERSION}. Version ${version} detected. ag-Grid will be unavailable.`
|
|
63
63
|
);
|
package/kit/highcharts/index.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Copyright © 2025 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {checkVersion} from '@xh/hoist/utils/js
|
|
8
|
+
import {checkVersion, logError} from '@xh/hoist/utils/js';
|
|
9
9
|
|
|
10
10
|
export let Highcharts = null;
|
|
11
11
|
|
|
@@ -19,7 +19,7 @@ const MAX_VERSION = '11.*.*';
|
|
|
19
19
|
export function installHighcharts(HighchartsImpl) {
|
|
20
20
|
const {version} = HighchartsImpl;
|
|
21
21
|
if (!checkVersion(version, MIN_VERSION, MAX_VERSION)) {
|
|
22
|
-
|
|
22
|
+
logError(
|
|
23
23
|
`This version of Hoist requires a Highcharts version between ${MIN_VERSION} and ` +
|
|
24
24
|
`${MAX_VERSION}. Version ${version} detected. Highcharts will be unavailable.`
|
|
25
25
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "76.0.0-SNAPSHOT.
|
|
3
|
+
"version": "76.0.0-SNAPSHOT.1756431654493",
|
|
4
4
|
"description": "Hoist add-on for building and deploying React Applications.",
|
|
5
5
|
"repository": "github:xh/hoist-react",
|
|
6
6
|
"homepage": "https://xh.io",
|
package/promise/Promise.ts
CHANGED
|
@@ -305,16 +305,3 @@ const enhancePromise = promisePrototype => {
|
|
|
305
305
|
|
|
306
306
|
// Enhance canonical Promises.
|
|
307
307
|
enhancePromise(Promise.prototype);
|
|
308
|
-
|
|
309
|
-
// MS Edge returns a "native Promise" from async functions that won't get the enhancements above.
|
|
310
|
-
// Check to see if we're in such an environment and enhance that prototype as well.
|
|
311
|
-
// @see https://github.com/xh/hoist-react/issues/1411
|
|
312
|
-
const asyncFnReturn = (async () => {})();
|
|
313
|
-
if (!(asyncFnReturn instanceof Promise)) {
|
|
314
|
-
console.debug(
|
|
315
|
-
'"Native" Promise return detected as return from async function - enhancing prototype'
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
// @ts-ignore
|
|
319
|
-
enhancePromise(asyncFnReturn.__proto__);
|
|
320
|
-
}
|
package/svc/FetchService.ts
CHANGED
|
@@ -261,7 +261,7 @@ export class FetchService extends HoistService {
|
|
|
261
261
|
const {correlationIdHeaderKey} = this;
|
|
262
262
|
if (opts.correlationId) {
|
|
263
263
|
if (headers[correlationIdHeaderKey]) {
|
|
264
|
-
|
|
264
|
+
this.logWarn(
|
|
265
265
|
`Header ${correlationIdHeaderKey} value already set within FetchOptions.`
|
|
266
266
|
);
|
|
267
267
|
} else {
|