@singularsystems/neo-core 1.6.2 → 1.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Neo core changelog
2
2
 
3
+ ## Version 1.6.4 (15 September 2026)
4
+
5
+ - Added support for `AbortSignal` in ConfigService and AuthenticationService. Equivalent to CancellationToken.
6
+ - Changes to AuthenticationService to allow deferred load of config (by passing a callback to the constructor).
7
+ - Added methods to `IAppConnectionMonitor`.
8
+
9
+ ## Version 1.6.3 (20 July 2026)
10
+
11
+ - Fixed issue with `Utils.createInstance` not passing parameters correctly.
12
+
3
13
  ## Version 1.6.2 (10 July 2026)
4
14
 
5
15
  - PageManager
@@ -0,0 +1,7 @@
1
+ export default class AbortHelper {
2
+ /**
3
+ * Returns early if the abort signal is triggered, otherwise resolves with the result of the promise.
4
+ * Returns undefined if aborted.
5
+ */
6
+ static race<T>(promise: Promise<T>, abortSignal?: AbortSignal): Promise<T | undefined>;
7
+ }
@@ -0,0 +1,39 @@
1
+ import { __awaiter, __generator } from "tslib";
2
+ var AbortHelper = /** @class */ (function () {
3
+ function AbortHelper() {
4
+ }
5
+ /**
6
+ * Returns early if the abort signal is triggered, otherwise resolves with the result of the promise.
7
+ * Returns undefined if aborted.
8
+ */
9
+ AbortHelper.race = function (promise, abortSignal) {
10
+ return __awaiter(this, void 0, void 0, function () {
11
+ return __generator(this, function (_a) {
12
+ switch (_a.label) {
13
+ case 0:
14
+ if (!!abortSignal) return [3 /*break*/, 2];
15
+ return [4 /*yield*/, promise];
16
+ case 1: return [2 /*return*/, _a.sent()];
17
+ case 2:
18
+ if (abortSignal.aborted) {
19
+ return [2 /*return*/, undefined];
20
+ }
21
+ return [4 /*yield*/, new Promise(function (resolve, reject) {
22
+ var onAbort = function () { return resolve(undefined); };
23
+ abortSignal.addEventListener("abort", onAbort, { once: true });
24
+ promise.then(function (result) {
25
+ abortSignal.removeEventListener("abort", onAbort);
26
+ resolve(result);
27
+ }, function (error) {
28
+ abortSignal.removeEventListener("abort", onAbort);
29
+ reject(error);
30
+ });
31
+ })];
32
+ case 3: return [2 /*return*/, _a.sent()];
33
+ }
34
+ });
35
+ });
36
+ };
37
+ return AbortHelper;
38
+ }());
39
+ export default AbortHelper;
File without changes
File without changes
@@ -2,6 +2,11 @@ import { AxiosPromise } from "axios";
2
2
  import { IConfigModel, IConfigModelData } from './ConfigModel';
3
3
  import { IDbSet } from "../../IndexDb/IDbSet";
4
4
  export interface IConfigService {
5
+ readonly hasOfflineConfig: boolean;
6
+ /**
7
+ * Load and process the config file from the specified path.
8
+ */
9
+ loadConfig(options?: ILoadConfigOptions): Promise<IConfigModel>;
5
10
  /**
6
11
  * Load and process the config file from the specified path.
7
12
  * Path will default to [baseUrl]/config.json
@@ -16,13 +21,22 @@ export interface IConfigService {
16
21
  * Use this if `loadConfig` fails, and you have an offline copy of the config data. */
17
22
  setConfig(configData: any): IConfigModel;
18
23
  }
24
+ interface ILoadConfigOptions {
25
+ /** Path to the config file. Defaults to [baseUrl]/config.json if not specified. */
26
+ path?: string;
27
+ /** Signal to abort the config loading request if needed. */
28
+ abortSignal?: AbortSignal;
29
+ }
19
30
  export declare class ConfigService implements IConfigService {
20
31
  private config;
21
32
  constructor(config: IConfigModel);
33
+ get hasOfflineConfig(): boolean;
22
34
  loadConfig(path?: string, store?: IDbSet<IConfigModelData>): Promise<IConfigModel>;
23
- fetchConfig(path?: string | undefined): AxiosPromise<any>;
35
+ loadConfig(options?: ILoadConfigOptions): Promise<IConfigModel>;
36
+ fetchConfig(path?: string | undefined, abortSignal?: AbortSignal): AxiosPromise<any>;
24
37
  setConfig(configData: any): IConfigModel;
25
38
  static get isDevelopment(): boolean;
26
39
  /** Throws the error if in development mode, otherwise logs it. */
27
40
  static tryShowError(e: any): void;
28
41
  }
42
+ export {};
@@ -8,17 +8,31 @@ var ConfigService = /** @class */ (function () {
8
8
  function ConfigService(config) {
9
9
  this.config = config;
10
10
  }
11
- ConfigService.prototype.loadConfig = function (path, store) {
11
+ Object.defineProperty(ConfigService.prototype, "hasOfflineConfig", {
12
+ get: function () {
13
+ return localStorage.getItem(storageKey) !== null;
14
+ },
15
+ enumerable: false,
16
+ configurable: true
17
+ });
18
+ ConfigService.prototype.loadConfig = function (pathOrOptions, store) {
12
19
  return __awaiter(this, void 0, void 0, function () {
13
- var configData, e_1, storedConfig;
20
+ var options, configData, e_1, storedConfig;
14
21
  return __generator(this, function (_a) {
15
22
  switch (_a.label) {
16
23
  case 0:
24
+ options = {};
25
+ if (typeof pathOrOptions === "string") {
26
+ options.path = pathOrOptions;
27
+ }
28
+ else if (typeof pathOrOptions === "object") {
29
+ options = pathOrOptions;
30
+ }
17
31
  if (!(!this.config.supportsOffline || navigator.onLine)) return [3 /*break*/, 7];
18
32
  _a.label = 1;
19
33
  case 1:
20
34
  _a.trys.push([1, 6, , 7]);
21
- return [4 /*yield*/, this.fetchConfig(path)];
35
+ return [4 /*yield*/, this.fetchConfig(options.path, options.abortSignal)];
22
36
  case 2:
23
37
  configData = (_a.sent()).data;
24
38
  if (!store) return [3 /*break*/, 4];
@@ -63,11 +77,11 @@ var ConfigService = /** @class */ (function () {
63
77
  });
64
78
  });
65
79
  };
66
- ConfigService.prototype.fetchConfig = function (path) {
80
+ ConfigService.prototype.fetchConfig = function (path, abortSignal) {
67
81
  path = path !== null && path !== void 0 ? path : "".concat(this.config.baseUrl, "/config.json");
68
82
  // Fetch config with timestamp to prevent caching
69
83
  var timestamp = new Date().getTime();
70
- return Axios.get("".concat(path, "?").concat(timestamp));
84
+ return Axios.get("".concat(path, "?").concat(timestamp), { signal: abortSignal });
71
85
  };
72
86
  ConfigService.prototype.setConfig = function (configData) {
73
87
  // The raw parsed json objects properties are copied into the config model.
@@ -0,0 +1,31 @@
1
+ type Newable<T> = new () => T;
2
+ /** Fluent syntax for setting the scope of a binding which creates a new instance (`to` / `toDynamicValue`). */
3
+ export interface IBindingInSyntax {
4
+ /** The same instance will be returned for every request. This is the default for `toConstantValue`. */
5
+ inSingletonScope(): void;
6
+ /** A new instance will be created for every request. This is the default for `to` / `toDynamicValue`. */
7
+ inTransientScope(): void;
8
+ }
9
+ /** Fluent syntax for specifying how a service identifier should be resolved. */
10
+ export interface IBindingToSyntax<T> {
11
+ /** Resolves the service by constructing a new instance of the given class (using its parameterless constructor). */
12
+ to(constructor: Newable<T>): IBindingInSyntax;
13
+ /** Resolves the service to a fixed value. */
14
+ toConstantValue(value: T): void;
15
+ /** Resolves the service using a factory function. */
16
+ toDynamicValue(factory: () => T): IBindingInSyntax;
17
+ }
18
+ /** @internal */
19
+ export declare class ServiceBinding<T> implements IBindingToSyntax<T>, IBindingInSyntax {
20
+ private factory?;
21
+ private singleton;
22
+ private instance?;
23
+ private hasInstance;
24
+ to(constructor: Newable<T>): IBindingInSyntax;
25
+ toConstantValue(value: T): void;
26
+ toDynamicValue(factory: () => T): IBindingInSyntax;
27
+ inSingletonScope(): void;
28
+ inTransientScope(): void;
29
+ resolve(): T;
30
+ }
31
+ export {};
@@ -0,0 +1,35 @@
1
+ /** @internal */
2
+ export class ServiceBinding {
3
+ constructor() {
4
+ this.singleton = false;
5
+ this.hasInstance = false;
6
+ }
7
+ to(constructor) {
8
+ this.factory = () => new constructor();
9
+ return this;
10
+ }
11
+ toConstantValue(value) {
12
+ this.factory = () => value;
13
+ this.singleton = true;
14
+ }
15
+ toDynamicValue(factory) {
16
+ this.factory = factory;
17
+ return this;
18
+ }
19
+ inSingletonScope() {
20
+ this.singleton = true;
21
+ }
22
+ inTransientScope() {
23
+ this.singleton = false;
24
+ }
25
+ resolve() {
26
+ if (this.singleton) {
27
+ if (!this.hasInstance) {
28
+ this.instance = this.factory();
29
+ this.hasInstance = true;
30
+ }
31
+ return this.instance;
32
+ }
33
+ return this.factory();
34
+ }
35
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Wraps a property decorator body so the resulting decorator works both as a legacy (experimentalDecorators)
3
+ * decorator - called as (target, propertyKey) - and as a TC39 / "v3" decorator - called as (value, context).
4
+ * v3 decorators don't have access to the class constructor until an instance is created, so in that case
5
+ * `apply` is deferred to context.addInitializer, which fires once for every instance created (including
6
+ * instances of subclasses that don't redeclare the property). It's guarded to only run once per concrete
7
+ * class, since some decorators (e.g. Parent) push into arrays and aren't safe to re-apply.
8
+ */
9
+ export declare function propertyDecorator(apply: (ctor: any, propertyKey: string) => void): (targetOrValue: any, propertyKeyOrContext: any) => void;
10
+ /**
11
+ * Same as propertyDecorator, but for decorators that need the property descriptor (accessors / methods).
12
+ * For v3 decorators the descriptor is read from the prototype once the first instance is constructed,
13
+ * by which point the class body (and so the getter/setter pair) is fully defined.
14
+ */
15
+ export declare function accessorDecorator(apply: (ctor: any, propertyKey: string, descriptor: PropertyDescriptor) => void): (targetOrValue: any, propertyKeyOrContext: any, legacyDescriptor?: PropertyDescriptor) => void;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Wraps a property decorator body so the resulting decorator works both as a legacy (experimentalDecorators)
3
+ * decorator - called as (target, propertyKey) - and as a TC39 / "v3" decorator - called as (value, context).
4
+ * v3 decorators don't have access to the class constructor until an instance is created, so in that case
5
+ * `apply` is deferred to context.addInitializer, which fires once for every instance created (including
6
+ * instances of subclasses that don't redeclare the property). It's guarded to only run once per concrete
7
+ * class, since some decorators (e.g. Parent) push into arrays and aren't safe to re-apply.
8
+ */
9
+ export function propertyDecorator(apply) {
10
+ return function (targetOrValue, propertyKeyOrContext) {
11
+ if (propertyKeyOrContext && typeof propertyKeyOrContext === "object") {
12
+ // v3 decorator: propertyKeyOrContext is a DecoratorContext.
13
+ const context = propertyKeyOrContext;
14
+ const propertyKey = context.name;
15
+ const appliedTo = new WeakSet();
16
+ context.addInitializer(function () {
17
+ const ctor = this.constructor;
18
+ if (!appliedTo.has(ctor)) {
19
+ appliedTo.add(ctor);
20
+ apply(ctor, propertyKey);
21
+ }
22
+ });
23
+ }
24
+ else {
25
+ // Legacy decorator: targetOrValue is the class prototype.
26
+ apply(targetOrValue.constructor, propertyKeyOrContext);
27
+ }
28
+ };
29
+ }
30
+ /**
31
+ * Walks up the prototype chain to find a property descriptor declared on a base class,
32
+ * since inherited accessors aren't own properties of a subclass' prototype.
33
+ */
34
+ function getInheritedPropertyDescriptor(proto, propertyKey) {
35
+ while (proto) {
36
+ const descriptor = Object.getOwnPropertyDescriptor(proto, propertyKey);
37
+ if (descriptor) {
38
+ return descriptor;
39
+ }
40
+ proto = Object.getPrototypeOf(proto);
41
+ }
42
+ return undefined;
43
+ }
44
+ /**
45
+ * Same as propertyDecorator, but for decorators that need the property descriptor (accessors / methods).
46
+ * For v3 decorators the descriptor is read from the prototype once the first instance is constructed,
47
+ * by which point the class body (and so the getter/setter pair) is fully defined.
48
+ */
49
+ export function accessorDecorator(apply) {
50
+ return function (targetOrValue, propertyKeyOrContext, legacyDescriptor) {
51
+ if (propertyKeyOrContext && typeof propertyKeyOrContext === "object") {
52
+ // v3 decorator
53
+ const propertyKey = propertyKeyOrContext.name;
54
+ const appliedTo = new WeakSet();
55
+ propertyKeyOrContext.addInitializer(function () {
56
+ const ctor = this.constructor;
57
+ if (!appliedTo.has(ctor)) {
58
+ appliedTo.add(ctor);
59
+ // The accessor may be declared on a base class' prototype, not the concrete instance's own.
60
+ const descriptor = getInheritedPropertyDescriptor(ctor.prototype, propertyKey);
61
+ apply(ctor, propertyKey, descriptor);
62
+ }
63
+ });
64
+ }
65
+ else {
66
+ // Legacy decorator
67
+ apply(targetOrValue.constructor, propertyKeyOrContext, legacyDescriptor);
68
+ }
69
+ };
70
+ }
@@ -197,15 +197,16 @@ var NeoTypeInfo = /** @class */ (function () {
197
197
  }
198
198
  };
199
199
  NeoTypeInfo.prototype.createInstance = function () {
200
+ var _a;
200
201
  var args = [];
201
202
  for (var _i = 0; _i < arguments.length; _i++) {
202
203
  args[_i] = arguments[_i];
203
204
  }
204
205
  if (this.wrapperConstructor) {
205
- return this.wrapperConstructor(args);
206
+ return this.wrapperConstructor.apply(this, args);
206
207
  }
207
208
  else {
208
- return new this.objectConstructor(args);
209
+ return new ((_a = this.objectConstructor).bind.apply(_a, __spreadArray([void 0], args, false)))();
209
210
  }
210
211
  };
211
212
  /** Gets the override constructor which can setup a neo model. */
@@ -1,9 +1,7 @@
1
- import { IAuthenticationService } from "../Security";
2
1
  import { ConnectionState } from "./IConnectionManager";
3
2
  import { IAppConnectionMonitor } from "./IAppConnectionMonitor";
4
3
  export default abstract class AppConnectionMonitor implements IAppConnectionMonitor {
5
- protected authenticationService: IAuthenticationService;
6
- constructor(authenticationService: IAuthenticationService);
4
+ constructor();
7
5
  protected reconnectDelayMs: number;
8
6
  private state;
9
7
  get isOnline(): boolean;
@@ -16,6 +14,6 @@ export default abstract class AppConnectionMonitor implements IAppConnectionMoni
16
14
  */
17
15
  protected onReconnected(): Promise<void> | void;
18
16
  private updateOnlineStatus;
19
- private markOffline;
20
- tryConnect(forceAllowRedirect?: boolean): Promise<void>;
17
+ markOffline(): void;
18
+ tryConnect(): Promise<void>;
21
19
  }
@@ -1,14 +1,12 @@
1
- import { __awaiter, __decorate, __extends, __generator, __metadata, __param } from "tslib";
1
+ import { __awaiter, __extends, __generator } from "tslib";
2
2
  import { Utils } from '../Utils';
3
3
  import NeoTypes from '../AppServices/NeoTypes';
4
- import { inject } from 'inversify';
5
4
  import { ConnectionState } from "./IConnectionManager";
6
5
  import Globals from "../Globals";
7
6
  import ModelBase from "../Model/ModelBase";
8
7
  var AppConnectionMonitor = /** @class */ (function () {
9
- function AppConnectionMonitor(authenticationService) {
8
+ function AppConnectionMonitor() {
10
9
  var _this = this;
11
- this.authenticationService = authenticationService;
12
10
  this.reconnectDelayMs = 5000;
13
11
  this.updateOnlineStatus = this.updateOnlineStatus.bind(this);
14
12
  this.state = new State();
@@ -55,7 +53,7 @@ var AppConnectionMonitor = /** @class */ (function () {
55
53
  var _this = this;
56
54
  return __generator(this, function (_a) {
57
55
  if (navigator.onLine) {
58
- Utils.debounce(this, function () { return _this.tryConnect(false); }, this.reconnectDelayMs);
56
+ Utils.debounce(this, function () { return _this.tryConnect(); }, this.reconnectDelayMs);
59
57
  }
60
58
  else {
61
59
  this.markOffline();
@@ -68,67 +66,56 @@ var AppConnectionMonitor = /** @class */ (function () {
68
66
  this.state.connectionState = ConnectionState.Disconnected;
69
67
  };
70
68
  AppConnectionMonitor.prototype.tryConnect = function () {
71
- return __awaiter(this, arguments, void 0, function (forceAllowRedirect) {
72
- var user, _a, canRedirect, _b, e_1;
73
- if (forceAllowRedirect === void 0) { forceAllowRedirect = false; }
74
- return __generator(this, function (_c) {
75
- switch (_c.label) {
69
+ return __awaiter(this, void 0, void 0, function () {
70
+ var authenticationService, user, _a, canRedirect, e_1;
71
+ return __generator(this, function (_b) {
72
+ switch (_b.label) {
76
73
  case 0:
77
74
  Utils.clearDebounce(this);
78
75
  if (this.state.connectionState === ConnectionState.Connected) {
79
76
  return [2 /*return*/];
80
77
  }
81
78
  this.state.connectionState = ConnectionState.ReConnecting;
82
- _c.label = 1;
79
+ _b.label = 1;
83
80
  case 1:
84
- _c.trys.push([1, 13, , 14]);
81
+ _b.trys.push([1, 11, , 12]);
82
+ authenticationService = Globals.appService.get(NeoTypes.Security.AuthenticationService);
85
83
  if (!this.state.requiresSignInRedirect) return [3 /*break*/, 2];
86
84
  _a = null;
87
85
  return [3 /*break*/, 4];
88
- case 2: return [4 /*yield*/, this.authenticationService.signinSilent()];
86
+ case 2: return [4 /*yield*/, authenticationService.signinSilent()];
89
87
  case 3:
90
- _a = _c.sent();
91
- _c.label = 4;
88
+ _a = _b.sent();
89
+ _b.label = 4;
92
90
  case 4:
93
91
  user = _a;
94
92
  if (!user) return [3 /*break*/, 6];
95
93
  this.state.connectionState = ConnectionState.Connected;
96
94
  return [4 /*yield*/, this.onReconnected()];
97
95
  case 5:
98
- _c.sent();
99
- return [3 /*break*/, 12];
100
- case 6:
101
- if (!forceAllowRedirect) return [3 /*break*/, 7];
102
- _b = true;
103
- return [3 /*break*/, 9];
104
- case 7: return [4 /*yield*/, this.beforeSigninRedirect()];
96
+ _b.sent();
97
+ return [3 /*break*/, 10];
98
+ case 6: return [4 /*yield*/, this.beforeSigninRedirect()];
99
+ case 7:
100
+ canRedirect = _b.sent();
101
+ if (!canRedirect) return [3 /*break*/, 9];
102
+ return [4 /*yield*/, authenticationService.beginSignIn()];
105
103
  case 8:
106
- _b = _c.sent();
107
- _c.label = 9;
108
- case 9:
109
- canRedirect = _b;
110
- if (!canRedirect) return [3 /*break*/, 11];
111
- return [4 /*yield*/, this.authenticationService.beginSignIn()];
112
- case 10:
113
- _c.sent();
104
+ _b.sent();
114
105
  return [2 /*return*/];
115
- case 11:
106
+ case 9:
116
107
  this.state.requiresSignInRedirect = true;
117
- _c.label = 12;
118
- case 12: return [3 /*break*/, 14];
119
- case 13:
120
- e_1 = _c.sent();
108
+ _b.label = 10;
109
+ case 10: return [3 /*break*/, 12];
110
+ case 11:
111
+ e_1 = _b.sent();
121
112
  this.state.connectionState = ConnectionState.Disconnected;
122
- return [3 /*break*/, 14];
123
- case 14: return [2 /*return*/];
113
+ return [3 /*break*/, 12];
114
+ case 12: return [2 /*return*/];
124
115
  }
125
116
  });
126
117
  });
127
118
  };
128
- AppConnectionMonitor = __decorate([
129
- __param(0, inject(NeoTypes.Security.AuthenticationService.symbol)),
130
- __metadata("design:paramtypes", [Object])
131
- ], AppConnectionMonitor);
132
119
  return AppConnectionMonitor;
133
120
  }());
134
121
  export default AppConnectionMonitor;
@@ -3,4 +3,8 @@ export interface IAppConnectionMonitor {
3
3
  readonly isOnline: boolean;
4
4
  readonly requiresSignInRedirect: boolean;
5
5
  readonly connectionState: ConnectionState;
6
+ /** Attempts to reconnect the application. */
7
+ tryConnect(): Promise<void>;
8
+ /** Sets the connection state to offline. Causes NetworkUtils.isOnline to return false. */
9
+ markOffline(): void;
6
10
  }
@@ -1,11 +1,17 @@
1
1
  import { IUser } from './IUser';
2
2
  import { ISignInResult } from './SignInResult';
3
+ export interface IRestoreSessionOptions {
4
+ /** Whether to attempt a silent sign in if a session exists. */
5
+ silentSignIn?: boolean;
6
+ /** Signal to abort the session restoration request if needed. */
7
+ abortSignal?: AbortSignal;
8
+ }
3
9
  export default interface IAuthenticationService {
4
10
  /**
5
11
  * Load a user from session storage if there is a stored token.
6
12
  * Will also try perform a silent sign in if opened from another window.
7
13
  */
8
- loadUserFromSession(): Promise<IUser | null>;
14
+ loadUserFromSession(options?: IRestoreSessionOptions): Promise<IUser | null>;
9
15
  /**
10
16
  * Checks if the user is signed in, and if not, redirects to login.
11
17
  * Returns true if the user is logged in.
@@ -30,6 +36,8 @@ export default interface IAuthenticationService {
30
36
  endSignInSilent(): Promise<any>;
31
37
  beginSignOut(): void;
32
38
  endSignOut(): Promise<any>;
39
+ /** Returns the offline user if available */
40
+ getOfflineUser(): IUser | null;
33
41
  /** Returns true if there is a user, and the token has not expired */
34
42
  readonly isAuthenticated: boolean;
35
43
  /** Returns the current user */
@@ -1,6 +1,6 @@
1
1
  import { IOidcUser, IUserManager } from './OidcTypes';
2
2
  import OidcUser from './OidcUser';
3
- import IAuthenticationService from '../IAuthenticationService';
3
+ import IAuthenticationService, { IRestoreSessionOptions } from '../IAuthenticationService';
4
4
  import { AxiosInstance } from 'axios';
5
5
  import { SignInResult } from '../SignInResult';
6
6
  /**
@@ -8,20 +8,23 @@ import { SignInResult } from '../SignInResult';
8
8
  * You must override this class and provide the user manager implementation from the oidc library.
9
9
  */
10
10
  export default abstract class OidcAuthService<TUser extends OidcUser = OidcUser> implements IAuthenticationService {
11
- protected userManager: IUserManager;
12
11
  private axios;
13
12
  private config;
14
13
  private _user;
15
14
  private isRedirecting;
16
15
  private afterUserLoadedPromise;
16
+ private userManagerSetup;
17
+ private _userManager?;
17
18
  /**
18
19
  * Creates an Oidc auth service
19
20
  * @param userManager Oidc-client user manager instance
20
21
  * @param user User which existed in storage at startup
21
22
  */
22
- constructor(userManager: IUserManager, axios: AxiosInstance, config?: import("../../AppServices").IConfigModel);
23
+ constructor(userManager: IUserManager | (() => IUserManager), axios: AxiosInstance, config?: import("../../AppServices").IConfigModel);
23
24
  isSigningOut: boolean;
24
- loadUserFromSession(): Promise<TUser | null>;
25
+ /** Oidc-client user manager instance */
26
+ protected get userManager(): IUserManager;
27
+ loadUserFromSession(options?: IRestoreSessionOptions): Promise<TUser | null>;
25
28
  ensureSignedIn(redirectLocal?: string): boolean;
26
29
  beginSignIn(redirectPath?: string): Promise<any>;
27
30
  /**
@@ -34,11 +37,12 @@ export default abstract class OidcAuthService<TUser extends OidcUser = OidcUser>
34
37
  */
35
38
  tryCompleteSignIn(): Promise<SignInResult>;
36
39
  endSignInSilent(): Promise<any>;
40
+ getOfflineUser(): TUser | null;
37
41
  protected setUserDataAsync(userData: IOidcUser): Promise<void>;
38
42
  private onUserLoaded;
39
43
  protected afterUserLoaded(): Promise<void> | void;
40
44
  private awaitAfterUserLoadedAsync;
41
- protected createUser(user: IOidcUser): OidcUser;
45
+ protected createUser(user: IOidcUser): TUser;
42
46
  private onUserUnloaded;
43
47
  private setUser;
44
48
  signinSilent(): Promise<TUser | null>;
@@ -2,7 +2,7 @@ import { __awaiter, __decorate, __generator, __metadata } from "tslib";
2
2
  import { Observable } from '../../Model/Decorators';
3
3
  import OidcUser from './OidcUser';
4
4
  import { SignInResult } from '../SignInResult';
5
- import { Misc } from '../../';
5
+ import { AbortHelper, Misc } from '../../';
6
6
  import { NeoTypes } from '../../AppServices';
7
7
  import NetworkUtils from "../../Network/NetworkUtils";
8
8
  var storageKey = "neo-app-user-data";
@@ -18,50 +18,70 @@ var OidcAuthService = /** @class */ (function () {
18
18
  */
19
19
  function OidcAuthService(userManager, axios, config) {
20
20
  if (config === void 0) { config = Misc.Globals.appService.get(NeoTypes.Config.ConfigModel); }
21
- var _this = this;
22
- this.userManager = userManager;
23
21
  this.axios = axios;
24
22
  this.config = config;
25
23
  this._user = null;
26
24
  this.isRedirecting = false;
27
25
  this.isSigningOut = false;
28
- this.userManager = userManager;
29
- this.userManager.events.addUserLoaded(this.onUserLoaded.bind(this));
30
- this.userManager.events.addUserUnloaded(this.onUserUnloaded.bind(this));
31
- if (!this.userManager.settings.automaticSilentRenew) {
32
- // If automaticSilentRenew is set to true, then the user manager will handle automatic renewal.
33
- this.userManager.events.addAccessTokenExpiring(function () { return _this.userManager.signinSilent(); });
34
- }
26
+ this.userManagerSetup = userManager;
35
27
  }
36
- OidcAuthService.prototype.loadUserFromSession = function () {
28
+ Object.defineProperty(OidcAuthService.prototype, "userManager", {
29
+ /** Oidc-client user manager instance */
30
+ get: function () {
31
+ var _this = this;
32
+ if (!this._userManager) {
33
+ this._userManager = typeof this.userManagerSetup === 'function' ? this.userManagerSetup() : this.userManagerSetup;
34
+ this._userManager.events.addUserLoaded(this.onUserLoaded.bind(this));
35
+ this._userManager.events.addUserUnloaded(this.onUserUnloaded.bind(this));
36
+ if (!this._userManager.settings.automaticSilentRenew) {
37
+ // If automaticSilentRenew is set to true, then the user manager will handle automatic renewal.
38
+ this._userManager.events.addAccessTokenExpiring(function () { return _this.userManager.signinSilent(); });
39
+ }
40
+ }
41
+ return this._userManager;
42
+ },
43
+ enumerable: false,
44
+ configurable: true
45
+ });
46
+ OidcAuthService.prototype.loadUserFromSession = function (options) {
37
47
  return __awaiter(this, void 0, void 0, function () {
38
- var userData, user;
39
- return __generator(this, function (_a) {
40
- switch (_a.label) {
41
- case 0:
42
- if (!NetworkUtils.useCachedData(this.config)) return [3 /*break*/, 3];
43
- userData = localStorage.getItem(storageKey);
44
- if (!userData) return [3 /*break*/, 2];
45
- return [4 /*yield*/, this.setUserDataAsync(JSON.parse(userData))];
48
+ var userData, userDataJson;
49
+ var _a, _b;
50
+ return __generator(this, function (_c) {
51
+ switch (_c.label) {
52
+ case 0: return [4 /*yield*/, this.userManager.getUser()];
46
53
  case 1:
47
- _a.sent();
48
- _a.label = 2;
49
- case 2: return [2 /*return*/, this.user];
50
- case 3: return [4 /*yield*/, this.userManager.getUser()];
51
- case 4:
52
- user = _a.sent();
53
- if (!(user && !user.expired)) return [3 /*break*/, 6];
54
+ userData = _c.sent();
55
+ if (!(userData && !userData.expired)) return [3 /*break*/, 3];
54
56
  // Get user does not raise the onUserLoaded event, so we call it manually.
55
- return [4 /*yield*/, this.setUserDataAsync(user)];
56
- case 5:
57
+ return [4 /*yield*/, this.setUserDataAsync(userData)];
58
+ case 2:
57
59
  // Get user does not raise the onUserLoaded event, so we call it manually.
58
- _a.sent();
60
+ _c.sent();
59
61
  return [2 /*return*/, this.user];
62
+ case 3:
63
+ userDataJson = localStorage.getItem(storageKey);
64
+ if (userDataJson) {
65
+ userData = JSON.parse(userDataJson);
66
+ }
67
+ if (!NetworkUtils.useCachedData(this.config)) return [3 /*break*/, 6];
68
+ if (!userData) return [3 /*break*/, 5];
69
+ return [4 /*yield*/, this.setUserDataAsync(userData)];
70
+ case 4:
71
+ _c.sent();
72
+ _c.label = 5;
73
+ case 5: return [2 /*return*/, this.user];
60
74
  case 6:
61
- if (!!!window.opener) return [3 /*break*/, 8];
62
- return [4 /*yield*/, this.signinSilent()];
63
- case 7: return [2 /*return*/, _a.sent()];
64
- case 8: return [2 /*return*/, null];
75
+ if (!((_a = options === null || options === void 0 ? void 0 : options.silentSignIn) !== null && _a !== void 0 ? _a : !!window.opener)) return [3 /*break*/, 9];
76
+ return [4 /*yield*/, AbortHelper.race(this.signinSilent(), options === null || options === void 0 ? void 0 : options.abortSignal)];
77
+ case 7:
78
+ _c.sent();
79
+ if (!(((_b = options === null || options === void 0 ? void 0 : options.abortSignal) === null || _b === void 0 ? void 0 : _b.aborted) && !this.user && userData)) return [3 /*break*/, 9];
80
+ return [4 /*yield*/, this.setUserDataAsync(userData)];
81
+ case 8:
82
+ _c.sent();
83
+ _c.label = 9;
84
+ case 9: return [2 /*return*/, this.user];
65
85
  }
66
86
  });
67
87
  });
@@ -148,6 +168,14 @@ var OidcAuthService = /** @class */ (function () {
148
168
  OidcAuthService.prototype.endSignInSilent = function () {
149
169
  return this.userManager.signinSilentCallback();
150
170
  };
171
+ OidcAuthService.prototype.getOfflineUser = function () {
172
+ var userDataJson = localStorage.getItem(storageKey);
173
+ if (userDataJson) {
174
+ var userData = JSON.parse(userDataJson);
175
+ return this.createUser(userData);
176
+ }
177
+ return null;
178
+ };
151
179
  OidcAuthService.prototype.setUserDataAsync = function (userData) {
152
180
  return __awaiter(this, void 0, void 0, function () {
153
181
  return __generator(this, function (_a) {
package/dist/Utils.d.ts CHANGED
@@ -45,7 +45,7 @@ export declare class Utils {
45
45
  static sameTypes(type1: Function, type2: Function): boolean;
46
46
  static getTypeName(type: Function): string;
47
47
  /**
48
- * Creates an instance of a model decorated with @NeoModel. Use this in static methods on a model class that is compiled with babel (React projects).
48
+ * Creates an instance of a neo model decorated with @NeoModel. Use this in static methods on a model class that is compiled with babel (React projects).
49
49
  * @param type Type to create.
50
50
  * @param args Constructor args.
51
51
  */
package/dist/Utils.js CHANGED
@@ -78,20 +78,21 @@ var Utils = /** @class */ (function () {
78
78
  return (_a = constructor.typeName) !== null && _a !== void 0 ? _a : constructor.name;
79
79
  };
80
80
  /**
81
- * Creates an instance of a model decorated with @NeoModel. Use this in static methods on a model class that is compiled with babel (React projects).
81
+ * Creates an instance of a neo model decorated with @NeoModel. Use this in static methods on a model class that is compiled with babel (React projects).
82
82
  * @param type Type to create.
83
83
  * @param args Constructor args.
84
84
  */
85
85
  Utils.createInstance = function (type) {
86
+ var _a;
86
87
  var args = [];
87
88
  for (var _i = 1; _i < arguments.length; _i++) {
88
89
  args[_i - 1] = arguments[_i];
89
90
  }
90
91
  if (type.prototype.constructor.neo) {
91
- return ensureTypeInfo(type).neo.createInstance(args);
92
+ return (_a = ensureTypeInfo(type).neo).createInstance.apply(_a, args);
92
93
  }
93
94
  else {
94
- throw "Cannot instantiate '".concat(type.name, "' because it does not have an @NeoModel attribute.");
95
+ throw "Cannot instantiate '".concat(type.name, "' because it does not call this.makeBindable(), or this.makeObservable().");
95
96
  }
96
97
  };
97
98
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import "reflect-metadata";
2
2
  import './Extensions';
3
+ import AbortHelper from './AbortHelper';
3
4
  import AxiosUtils from "./AxiosUtils";
4
5
  import List from './Model/List';
5
6
  import NeoModel from './Model/NeoModel';
@@ -31,7 +32,7 @@ import * as SignalR from './SignalR';
31
32
  import * as Validation from './Validation';
32
33
  import * as Views from './Views/IViewBase';
33
34
  declare const NotifyUtils: Components.INotificationHelper;
34
- export { AxiosUtils, AppServices, Attributes, Components, Data, DateUtils, DebounceHelper, EnumHelper, FileUtils, JsonSchema, Localisation, List, MenuUtils, Misc, ModalUtils, Model, NeoModel, NeoStrings, Network, NotifyUtils, Numeric, NumberUtils, Routing, Rules, Security, SignalR, StringUtils, Validation, Views, };
35
+ export { AbortHelper, AxiosUtils, AppServices, Attributes, Components, Data, DateUtils, DebounceHelper, EnumHelper, FileUtils, JsonSchema, Localisation, List, MenuUtils, Misc, ModalUtils, Model, NeoModel, NeoStrings, Network, NotifyUtils, Numeric, NumberUtils, Routing, Rules, Security, SignalR, StringUtils, Validation, Views, };
35
36
  export { runInTask, createProperty };
36
37
  export { default as ModelBase } from './Model/ModelBase';
37
38
  export { default as ValueObject } from './Model/ValueObject';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import "reflect-metadata";
2
2
  import './Extensions';
3
3
  // Individual exports
4
+ import AbortHelper from './AbortHelper';
4
5
  import AxiosUtils from "./AxiosUtils";
5
6
  import List from './Model/List';
6
7
  import NeoModel from './Model/NeoModel';
@@ -36,7 +37,7 @@ import * as Views from './Views/IViewBase';
36
37
  import { NotificationHelper } from './Components/Notifications/NotificationHelper';
37
38
  var NotifyUtils = new NotificationHelper();
38
39
  // Types
39
- export { AxiosUtils, AppServices, Attributes, Components, Data, DateUtils, DebounceHelper, EnumHelper, FileUtils, JsonSchema, Localisation, List, MenuUtils, Misc, ModalUtils, Model, NeoModel, NeoStrings, Network, NotifyUtils, Numeric, NumberUtils, Routing, Rules, Security, SignalR, StringUtils, Validation, Views, };
40
+ export { AbortHelper, AxiosUtils, AppServices, Attributes, Components, Data, DateUtils, DebounceHelper, EnumHelper, FileUtils, JsonSchema, Localisation, List, MenuUtils, Misc, ModalUtils, Model, NeoModel, NeoStrings, Network, NotifyUtils, Numeric, NumberUtils, Routing, Rules, Security, SignalR, StringUtils, Validation, Views, };
40
41
  // Functions
41
42
  export { runInTask, createProperty };
42
43
  export { default as ModelBase } from './Model/ModelBase';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singularsystems/neo-core",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "Core functionality for the Neo client library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,45 +0,0 @@
1
- export declare enum ConnectionState {
2
- /** Has not tried to connect yet. */
3
- NotStarted = 0,
4
- /** Is connected. */
5
- Connected = 1,
6
- /** Is reconnecting after failing to connect, or being disconnected. */
7
- ReConnecting = 2,
8
- /** Is disconnected and not trying to reconnect. */
9
- Disconnected = 3
10
- }
11
- export declare enum ConnectionType {
12
- SignalR = 0
13
- }
14
- export interface IConnection {
15
- readonly connectionState: ConnectionState;
16
- }
17
- export declare class ConnectionInfo {
18
- readonly connection: IConnection;
19
- readonly connectionName: string;
20
- readonly connectionType: ConnectionType;
21
- constructor(connection: IConnection, connectionName: string, connectionType: ConnectionType);
22
- }
23
- /** A connection manager is used to display the connection state of multiple connected services to the user. */
24
- export interface IConnectionManager {
25
- /**
26
- * Returns the max state of all the connections.
27
- */
28
- readonly connectionState: ConnectionState;
29
- /**
30
- * Gets a list of connections that have been registered.
31
- */
32
- readonly connections: ConnectionInfo[];
33
- /**
34
- * Registers a connection to be monitored.
35
- * @param connection The connection to monitor.
36
- * @param connectionName The display name of the connection.
37
- */
38
- registerConnection(connection: IConnection, connectionName: string, connectionType: ConnectionType): void;
39
- }
40
- export declare class ConnectionManager implements IConnectionManager {
41
- private _connections;
42
- registerConnection(connection: IConnection, connectionName: string, connectionType: ConnectionType): void;
43
- get connectionState(): ConnectionState;
44
- get connections(): ConnectionInfo[];
45
- }
@@ -1,61 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import { Computed } from './Model/Decorators';
3
- import { injectable } from 'inversify';
4
- export var ConnectionState;
5
- (function (ConnectionState) {
6
- /** Has not tried to connect yet. */
7
- ConnectionState[ConnectionState["NotStarted"] = 0] = "NotStarted";
8
- /** Is connected. */
9
- ConnectionState[ConnectionState["Connected"] = 1] = "Connected";
10
- /** Is reconnecting after failing to connect, or being disconnected. */
11
- ConnectionState[ConnectionState["ReConnecting"] = 2] = "ReConnecting";
12
- /** Is disconnected and not trying to reconnect. */
13
- ConnectionState[ConnectionState["Disconnected"] = 3] = "Disconnected";
14
- })(ConnectionState || (ConnectionState = {}));
15
- export var ConnectionType;
16
- (function (ConnectionType) {
17
- ConnectionType[ConnectionType["SignalR"] = 0] = "SignalR";
18
- })(ConnectionType || (ConnectionType = {}));
19
- var ConnectionInfo = /** @class */ (function () {
20
- function ConnectionInfo(connection, connectionName, connectionType) {
21
- this.connection = connection;
22
- this.connectionName = connectionName;
23
- this.connectionType = connectionType;
24
- }
25
- return ConnectionInfo;
26
- }());
27
- export { ConnectionInfo };
28
- var ConnectionManager = /** @class */ (function () {
29
- function ConnectionManager() {
30
- this._connections = new Map();
31
- }
32
- ConnectionManager.prototype.registerConnection = function (connection, connectionName, connectionType) {
33
- if (!this._connections.has(connectionName)) {
34
- this._connections.set(connectionName, new ConnectionInfo(connection, connectionName, connectionType));
35
- }
36
- };
37
- Object.defineProperty(ConnectionManager.prototype, "connectionState", {
38
- get: function () {
39
- return this.connections.reduce(function (p, c) { return Math.max(p, c.connection.connectionState); }, ConnectionState.NotStarted);
40
- },
41
- enumerable: false,
42
- configurable: true
43
- });
44
- Object.defineProperty(ConnectionManager.prototype, "connections", {
45
- get: function () {
46
- return Array.from(this._connections.values());
47
- },
48
- enumerable: false,
49
- configurable: true
50
- });
51
- __decorate([
52
- Computed(),
53
- __metadata("design:type", Number),
54
- __metadata("design:paramtypes", [])
55
- ], ConnectionManager.prototype, "connectionState", null);
56
- ConnectionManager = __decorate([
57
- injectable()
58
- ], ConnectionManager);
59
- return ConnectionManager;
60
- }());
61
- export { ConnectionManager };