@xh/hoist 73.0.0-SNAPSHOT.1745457790188 → 73.0.0-SNAPSHOT.1745589992773

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 CHANGED
@@ -31,6 +31,8 @@ Requires `hoist-core >= 30.0` with new APIs to support the consolidated Admin Co
31
31
  the client remained on an older version.
32
32
  * Note that a misconfigured build - where the client build version is not set to the same value
33
33
  as the server - would result in a false positive for an upgrade. The two should always match.
34
+ * Calls to `Promise.track()` that are rejected with an exception will be tracked with new
35
+ severity level of `TrackSeverity.ERROR`
34
36
 
35
37
  ## v72.5.1 - 2025-04-15
36
38
 
@@ -165,7 +165,7 @@ export interface AppOptionSpec {
165
165
  /**
166
166
  * Severity levels for tracking. Default is 'INFO'.
167
167
  */
168
- export type TrackSeverity = 'DEBUG' | 'INFO' | 'WARN';
168
+ export type TrackSeverity = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
169
169
  /**
170
170
  * Options for tracking activity on the server via TrackService.
171
171
  */
@@ -18,7 +18,7 @@ declare global {
18
18
  * selector will be handled by this method.
19
19
  * @param fn - catch handler
20
20
  */
21
- catchWhen<TResult = undefined>(selector: ((e: any) => boolean) | Some<string>, fn?: (reason: any) => Awaitable<TResult>): Promise<T | TResult>;
21
+ catchWhen<TResult = undefined>(selector: ((e: unknown) => boolean) | Some<string>, fn?: (reason: unknown) => Awaitable<TResult>): Promise<T | TResult>;
22
22
  /**
23
23
  * Version of `catch()` that passes the error onto Hoist's default exception handler for
24
24
  * convention-driven logging and alerting. Typically called last in a Promise chain.
@@ -27,7 +27,7 @@ declare global {
27
27
  /**
28
28
  * Version of `catchDefault()` that will only catch certain exceptions.
29
29
  */
30
- catchDefaultWhen(selector: ((e: any) => boolean) | Some<string>, options: ExceptionHandlerOptions): Promise<T | undefined>;
30
+ catchDefaultWhen(selector: ((e: unknown) => boolean) | Some<string>, options: ExceptionHandlerOptions): Promise<T | undefined>;
31
31
  /**
32
32
  * Wait on a potentially async function before passing on the original value.
33
33
  * Useful when we want to block and do something on the promise chain, but do not want to
@@ -36,7 +36,7 @@ interface ActivityTrackingConfig {
36
36
  levels?: Array<{
37
37
  username: string | '*';
38
38
  category: string | '*';
39
- severity: 'DEBUG' | 'INFO' | 'WARN';
39
+ severity: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
40
40
  }>;
41
41
  }
42
42
  export {};
@@ -207,7 +207,7 @@ export interface AppOptionSpec {
207
207
  /**
208
208
  * Severity levels for tracking. Default is 'INFO'.
209
209
  */
210
- export type TrackSeverity = 'DEBUG' | 'INFO' | 'WARN';
210
+ export type TrackSeverity = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
211
211
 
212
212
  /**
213
213
  * Options for tracking activity on the server via TrackService.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "73.0.0-SNAPSHOT.1745457790188",
3
+ "version": "73.0.0-SNAPSHOT.1745589992773",
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",
@@ -12,11 +12,13 @@ import {
12
12
  TrackOptions,
13
13
  XH,
14
14
  Some,
15
- Awaitable
15
+ Awaitable,
16
+ TimeoutExceptionConfig
16
17
  } from '@xh/hoist/core';
17
18
  import {action} from '@xh/hoist/mobx';
18
19
  import {olderThan, SECONDS} from '@xh/hoist/utils/datetime';
19
20
  import {castArray, isFunction, isNumber, isString} from 'lodash';
21
+ import {isOmitted} from '@xh/hoist/utils/impl';
20
22
 
21
23
  /**
22
24
  * Enhancements to the Global Promise object.
@@ -39,8 +41,8 @@ declare global {
39
41
  * @param fn - catch handler
40
42
  */
41
43
  catchWhen<TResult = undefined>(
42
- selector: ((e: any) => boolean) | Some<string>,
43
- fn?: (reason: any) => Awaitable<TResult>
44
+ selector: ((e: unknown) => boolean) | Some<string>,
45
+ fn?: (reason: unknown) => Awaitable<TResult>
44
46
  ): Promise<T | TResult>;
45
47
 
46
48
  /**
@@ -53,7 +55,7 @@ declare global {
53
55
  * Version of `catchDefault()` that will only catch certain exceptions.
54
56
  */
55
57
  catchDefaultWhen(
56
- selector: ((e: any) => boolean) | Some<string>,
58
+ selector: ((e: unknown) => boolean) | Some<string>,
57
59
  options: ExceptionHandlerOptions
58
60
  ): Promise<T | undefined>;
59
61
 
@@ -169,43 +171,63 @@ export function never<T>(): Promise<T> {
169
171
  //--------------------------------
170
172
  const enhancePromise = promisePrototype => {
171
173
  Object.assign(promisePrototype, {
172
- thenAction(fn) {
174
+ thenAction<T, TResult>(fn: (value: T) => Awaitable<TResult>): Promise<TResult> {
173
175
  return this.then(action(fn));
174
176
  },
175
177
 
176
- catchWhen(selector, fn) {
177
- return this.catch(e => {
178
+ catchWhen<T, TResult = undefined>(
179
+ selector: ((e: unknown) => boolean) | Some<string>,
180
+ fn?: (reason: unknown) => Awaitable<TResult>
181
+ ): Promise<T | TResult> {
182
+ return this.catch((e: unknown) => {
178
183
  this.throwIfFailsSelector(e, selector);
179
184
  return fn ? fn(e) : undefined;
180
185
  });
181
186
  },
182
187
 
183
- catchDefault(options) {
184
- return this.catch(e => XH.handleException(e, options));
188
+ catchDefault<T>(options?: ExceptionHandlerOptions): Promise<T | undefined> {
189
+ return this.catch((e: unknown) => XH.handleException(e, options));
185
190
  },
186
191
 
187
- catchDefaultWhen(selector, options) {
188
- return this.catch(e => {
192
+ catchDefaultWhen<T>(
193
+ selector: ((e: unknown) => boolean) | Some<string>,
194
+ options: ExceptionHandlerOptions
195
+ ): Promise<T | undefined> {
196
+ return this.catch((e: unknown) => {
189
197
  this.throwIfFailsSelector(e, selector);
190
198
  return XH.handleException(e, options);
191
199
  });
192
200
  },
193
201
 
194
- track(options) {
195
- if (!options || (isFunction(options.omit) ? options.omit() : options.omit)) return this;
196
- if (isString(options)) options = {message: options};
197
-
198
- const startTime = Date.now();
199
- return this.finally(() => {
200
- XH.track({
201
- timestamp: startTime,
202
- elapsed: Date.now() - startTime,
203
- ...options
204
- });
205
- });
202
+ track<T>(options: TrackOptions | string): Promise<T> {
203
+ if (!options) return this;
204
+
205
+ const startTime = Date.now(),
206
+ doTrack = (isError: boolean) => {
207
+ const opts: TrackOptions = isString(options)
208
+ ? {message: options}
209
+ : {...options};
210
+
211
+ opts.timestamp = startTime;
212
+ opts.elapsed = Date.now() - startTime;
213
+ if (isError) opts.severity = 'ERROR';
214
+
215
+ XH.track(opts);
216
+ };
217
+
218
+ return this.then(
219
+ (v: T) => {
220
+ doTrack(true);
221
+ return v;
222
+ },
223
+ (t: unknown) => {
224
+ doTrack(false);
225
+ throw t;
226
+ }
227
+ );
206
228
  },
207
229
 
208
- tap(onFulfillment) {
230
+ tap<T>(onFulfillment: (value: T) => any): Promise<T> {
209
231
  let ret = null;
210
232
  const resolveFn = data => {
211
233
  ret = data;
@@ -215,13 +237,14 @@ const enhancePromise = promisePrototype => {
215
237
  return this.then(resolveFn).then(() => ret);
216
238
  },
217
239
 
218
- wait(interval) {
240
+ wait<T>(interval: number): Promise<T> {
219
241
  return this.finally(() => wait(interval));
220
242
  },
221
243
 
222
- timeout(config) {
223
- if (config == null) return this;
224
- if (isNumber(config)) config = {interval: config};
244
+ timeout<T>(spec: PromiseTimeoutSpec): Promise<T> {
245
+ if (spec == null) return this;
246
+
247
+ const config: TimeoutExceptionConfig = isNumber(spec) ? {interval: spec} : spec;
225
248
  const interval = config.interval;
226
249
 
227
250
  let completed = false;
@@ -236,14 +259,14 @@ const enhancePromise = promisePrototype => {
236
259
  return Promise.race([deadline, promise]);
237
260
  },
238
261
 
239
- linkTo(cfg) {
262
+ linkTo<T>(cfg: PromiseLinkSpec): Promise<T> {
240
263
  if (!cfg) return this;
241
264
 
242
- if (cfg.isTaskObserver) {
265
+ if (cfg instanceof TaskObserver) {
243
266
  cfg = {observer: cfg};
244
267
  }
245
268
 
246
- if (cfg.observer && !(isFunction(cfg.omit) ? cfg.omit() : cfg.omit)) {
269
+ if (cfg.observer && !isOmitted(cfg)) {
247
270
  cfg.observer.linkTo(TaskObserver.forPromise({promise: this, message: cfg.message}));
248
271
  }
249
272
  return this;
@@ -252,7 +275,7 @@ const enhancePromise = promisePrototype => {
252
275
  //--------------------------------
253
276
  // Implementation
254
277
  //--------------------------------
255
- throwIfFailsSelector(e, selector) {
278
+ throwIfFailsSelector(e: any, selector: any) {
256
279
  const fn = isFunction(selector) ? selector : e => castArray(selector).includes(e.name);
257
280
  if (!fn(e)) throw e;
258
281
  }
@@ -168,6 +168,6 @@ interface ActivityTrackingConfig {
168
168
  levels?: Array<{
169
169
  username: string | '*';
170
170
  category: string | '*';
171
- severity: 'DEBUG' | 'INFO' | 'WARN';
171
+ severity: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
172
172
  }>;
173
173
  }