@singularsystems/neo-core 1.0.3 → 1.0.5

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.
@@ -46,6 +46,9 @@ export type PartialPlainNonTrackedObject<T> = PartialPlainObject<T> & {
46
46
  export interface NeoModelConstructor extends Function {
47
47
  neo: NeoTypeInfo;
48
48
  }
49
+ export interface NeoModelConstructorInternal extends Function {
50
+ addBusinessRules?(validationRules: ValidationRules<IModelBase>): void;
51
+ }
49
52
  export interface IMakeBindableOptions {
50
53
  /**
51
54
  * Specifies whether properties should be observable
@@ -79,10 +79,15 @@ export default abstract class ModelBase extends BindableBase implements IModelBa
79
79
  * @param shouldSerialise The value determined by the serialiser.
80
80
  */
81
81
  protected canSerialise(shouldSerialise: boolean): boolean;
82
+ /** @deprecated Make your addBusinessRules method `static`. E.g.
83
+ * ```
84
+ * protected static addBusinessRules(rules: ValidationRules<MyType>) {
85
+ * ``` */
86
+ protected addBusinessRules(validationRules: ValidationRules<this>): void;
82
87
  /**
83
- * Add custom business rules. Note, this will be called once per type and should be treated as static.
88
+ * Add custom business rules for this type.
84
89
  */
85
- protected addBusinessRules(validationRules: ValidationRules<this>): void;
90
+ protected static addBusinessRules(rules: ValidationRules<ModelBase>): void;
86
91
  /** The server side type name used to find this type. Include the namespace if there is more than one type with the same name. */
87
92
  static typeName: string | null;
88
93
  }
@@ -142,10 +142,16 @@ var ModelBase = /** @class */ (function (_super) {
142
142
  ModelBase.prototype.canSerialise = function (shouldSerialise) {
143
143
  return shouldSerialise;
144
144
  };
145
+ /** @deprecated Make your addBusinessRules method `static`. E.g.
146
+ * ```
147
+ * protected static addBusinessRules(rules: ValidationRules<MyType>) {
148
+ * ``` */
149
+ ModelBase.prototype.addBusinessRules = function (validationRules) {
150
+ };
145
151
  /**
146
- * Add custom business rules. Note, this will be called once per type and should be treated as static.
152
+ * Add custom business rules for this type.
147
153
  */
148
- ModelBase.prototype.addBusinessRules = function (validationRules) {
154
+ ModelBase.addBusinessRules = function (rules) {
149
155
  };
150
156
  /** The server side type name used to find this type. Include the namespace if there is more than one type with the same name. */
151
157
  ModelBase.typeName = null;
@@ -4,12 +4,15 @@ import PropertyInfo from './PropertyInfo';
4
4
  export declare class RecursionState {
5
5
  stop: boolean;
6
6
  canRecurse: (model: IModelBase, property: PropertyInfo) => boolean;
7
+ canRecurseType(item: any): boolean;
7
8
  pushState(): void;
8
9
  popState(): void;
9
10
  /**
10
11
  * Overwrites the canRecurse callback to always return true.
11
12
  */
12
13
  includeNonTrackedProperties(): this;
14
+ /** Child objects / lists of any type will be included. By default only types extending ModelBase are included. */
15
+ includeNonModelBaseTypes(): this;
13
16
  }
14
17
  export declare class BooleanRecursionState extends RecursionState {
15
18
  flag: boolean;
@@ -1,10 +1,14 @@
1
1
  import { __extends } from "tslib";
2
2
  import { RelationType } from './Misc';
3
+ import ModelBase from "./ModelBase";
3
4
  var RecursionState = /** @class */ (function () {
4
5
  function RecursionState() {
5
6
  this.stop = false;
6
7
  this.canRecurse = function (model, property) { return !property.noTrack; };
7
8
  }
9
+ RecursionState.prototype.canRecurseType = function (item) {
10
+ return item instanceof ModelBase;
11
+ };
8
12
  RecursionState.prototype.pushState = function () {
9
13
  };
10
14
  RecursionState.prototype.popState = function () {
@@ -16,6 +20,11 @@ var RecursionState = /** @class */ (function () {
16
20
  this.canRecurse = function (model, property) { return true; };
17
21
  return this;
18
22
  };
23
+ /** Child objects / lists of any type will be included. By default only types extending ModelBase are included. */
24
+ RecursionState.prototype.includeNonModelBaseTypes = function () {
25
+ this.canRecurseType = function () { return true; };
26
+ return this;
27
+ };
19
28
  return RecursionState;
20
29
  }());
21
30
  export { RecursionState };
@@ -67,32 +76,34 @@ function invokeOnSelfAndChildren(model, state, callback, listCallback, relationT
67
76
  for (var i = 0; i < ctor.neo.children.length; i++) {
68
77
  var cpi = ctor.neo.children[i];
69
78
  if (state.canRecurse(model, cpi)) {
70
- if (cpi.relationType == RelationType.ChildList) {
71
- // @ts-ignore
72
- var childList = model[cpi.propertyName];
73
- if (listCallback)
74
- listCallback(childList, state);
75
- if (state.stop)
76
- return state;
77
- state.pushState();
78
- invokeOnItemsAndChildren(childList, state, callback, listCallback, RelationType.ChildList);
79
- state.popState();
80
- if (state.stop)
81
- return state;
82
- }
83
- else {
84
- try {
79
+ try {
80
+ if (cpi.relationType == RelationType.ChildList) {
81
+ // @ts-ignore
82
+ var childList = model[cpi.propertyName];
83
+ if (listCallback)
84
+ listCallback(childList, state);
85
+ if (state.stop)
86
+ return state;
87
+ if (childList.length && state.canRecurseType(childList[0])) {
88
+ state.pushState();
89
+ invokeOnItemsAndChildren(childList, state, callback, listCallback, RelationType.ChildList);
90
+ state.popState();
91
+ if (state.stop)
92
+ return state;
93
+ }
94
+ }
95
+ else {
85
96
  // @ts-ignore
86
97
  var child = model[cpi.propertyName];
87
- if (child) {
98
+ if (child && state.canRecurseType(child)) {
88
99
  state.pushState();
89
100
  invokeOnSelfAndChildren(child, state, callback, listCallback, cpi.relationType);
90
101
  state.popState();
91
102
  }
92
103
  }
93
- catch (error) {
94
- throw "Error on property '".concat(cpi.propertyName, "' on type '").concat(model.constructor.name, "': ").concat(error);
95
- }
104
+ }
105
+ catch (error) {
106
+ throw "Error on property '".concat(cpi.propertyName, "' on type '").concat(model.constructor.name, "': ").concat(error, ".");
96
107
  }
97
108
  }
98
109
  }
@@ -125,22 +125,24 @@ var NeoTypeInfo = /** @class */ (function () {
125
125
  }
126
126
  };
127
127
  NeoTypeInfo.prototype.addRules = function (instance) {
128
- if (instance.addBusinessRules !== undefined) {
128
+ var _a;
129
+ var addRulesMethod = (_a = this.objectConstructor.addBusinessRules) !== null && _a !== void 0 ? _a : instance.addBusinessRules;
130
+ if (addRulesMethod !== undefined) {
129
131
  var validationRules = new ValidationRules();
130
- instance.addBusinessRules(validationRules);
131
- if (validationRules.rules.some(function (c) { return c instanceof CallbackRule && c.hasBoundFunction; })) {
132
- console.error("Warning: ".concat(this.objectConstructor.name, " has rules which have been added using a bound function, or arrow function."));
132
+ addRulesMethod(validationRules);
133
+ if (validationRules.rules.some(function (c) { return c instanceof CallbackRule && c.hasArrowFunction; })) {
134
+ console.error("Warning: ".concat(this.objectConstructor.name, " has rules which have been added using an arrow function."));
133
135
  }
134
136
  var modelProxy = new ModelProxy(instance);
135
- for (var _i = 0, _a = validationRules.rules; _i < _a.length; _i++) {
136
- var rule = _a[_i];
137
+ for (var _i = 0, _b = validationRules.rules; _i < _b.length; _i++) {
138
+ var rule = _b[_i];
137
139
  var properties = rule.getDisplayProperties(this.propertyMap);
138
140
  if (properties === undefined && rule instanceof ExpressionRule) {
139
141
  properties = modelProxy.tryExtractProperties(rule);
140
142
  }
141
143
  if (properties && properties.length) {
142
- for (var _b = 0, properties_1 = properties; _b < properties_1.length; _b++) {
143
- var property = properties_1[_b];
144
+ for (var _c = 0, properties_1 = properties; _c < properties_1.length; _c++) {
145
+ var property = properties_1[_c];
144
146
  property.rules.push(rule);
145
147
  }
146
148
  }
@@ -26,8 +26,6 @@ export default interface IAuthenticationService {
26
26
  tryCompleteSignIn(): Promise<ISignInResult>;
27
27
  signinSilent(): Promise<any>;
28
28
  endSignInSilent(): Promise<any>;
29
- /** Clears the user locally */
30
- signOutLocal(): void;
31
29
  beginSignOut(): void;
32
30
  endSignOut(): Promise<any>;
33
31
  /** Returns true if there is a user, and the token has not expired */
@@ -11,6 +11,7 @@ export default abstract class OidcAuthService<TUser extends OidcUser = OidcUser>
11
11
  protected userManager: IUserManager;
12
12
  private axios;
13
13
  private _user;
14
+ private isRedirecting;
14
15
  private afterUserLoadedPromise;
15
16
  /**
16
17
  * Creates an Oidc auth service
@@ -18,6 +19,7 @@ export default abstract class OidcAuthService<TUser extends OidcUser = OidcUser>
18
19
  * @param user User which existed in storage at startup
19
20
  */
20
21
  constructor(userManager: IUserManager, axios: AxiosInstance);
22
+ isSigningOut: boolean;
21
23
  loadUserFromToken(): Promise<TUser | null>;
22
24
  loadUserFromSession(): Promise<TUser | null>;
23
25
  ensureSignedIn(redirectLocal?: string): boolean;
@@ -45,7 +47,7 @@ export default abstract class OidcAuthService<TUser extends OidcUser = OidcUser>
45
47
  signinSilent(): Promise<IOidcUser | null>;
46
48
  beginSignOut(): void;
47
49
  endSignOut(): Promise<any>;
48
- signOutLocal(): void;
50
+ private signOutLocal;
49
51
  get user(): TUser | null;
50
52
  get isAuthenticated(): boolean;
51
53
  static createIdentityServerMetadata(identityServerUrl: string): {
@@ -18,6 +18,8 @@ var OidcAuthService = /** @class */ (function () {
18
18
  this.userManager = userManager;
19
19
  this.axios = axios;
20
20
  this._user = null;
21
+ this.isRedirecting = false;
22
+ this.isSigningOut = false;
21
23
  this.userManager = userManager;
22
24
  this.userManager.events.addUserLoaded(this.onUserLoaded.bind(this));
23
25
  this.userManager.events.addUserUnloaded(this.onUserUnloaded.bind(this));
@@ -64,7 +66,11 @@ var OidcAuthService = /** @class */ (function () {
64
66
  * @param redirectPath Local path to redirect to once login is complete.
65
67
  */
66
68
  OidcAuthService.prototype.beginSignIn = function (redirectPath) {
67
- return this.userManager.signinRedirect({ state: redirectPath });
69
+ if (!this.isRedirecting) {
70
+ this.isRedirecting = true;
71
+ return this.userManager.signinRedirect({ state: redirectPath });
72
+ }
73
+ return Promise.resolve();
68
74
  };
69
75
  ;
70
76
  /**
@@ -77,6 +83,7 @@ var OidcAuthService = /** @class */ (function () {
77
83
  switch (_a.label) {
78
84
  case 0:
79
85
  _a.trys.push([0, 2, , 3]);
86
+ this.isRedirecting = false;
80
87
  return [4 /*yield*/, this.userManager.signinRedirectCallback()];
81
88
  case 1:
82
89
  user = _a.sent();
@@ -168,14 +175,20 @@ var OidcAuthService = /** @class */ (function () {
168
175
  return this.userManager.signinSilent();
169
176
  };
170
177
  OidcAuthService.prototype.beginSignOut = function () {
171
- if (this._user) {
172
- this.userManager.signoutRedirect({ id_token_hint: this._user.userData.id_token });
173
- this.signOutLocal();
178
+ if (!this.isRedirecting) {
179
+ if (this._user) {
180
+ this.isRedirecting = true;
181
+ this.isSigningOut = true;
182
+ this.userManager.signoutRedirect({ id_token_hint: this._user.userData.id_token });
183
+ this.signOutLocal();
184
+ }
185
+ this.userManager.clearStaleState();
174
186
  }
175
- this.userManager.clearStaleState();
176
187
  };
177
188
  ;
178
189
  OidcAuthService.prototype.endSignOut = function () {
190
+ this.isRedirecting = false;
191
+ this.isSigningOut = false;
179
192
  return this.userManager.signoutRedirectCallback();
180
193
  };
181
194
  ;
@@ -75,6 +75,7 @@ export declare const Settings: {
75
75
  /** Global allowed extensions. Can be changed on each file upload manager. Must be lower case. */
76
76
  allowedExtensions: string[];
77
77
  fileEditorButton: IButtonOptions;
78
+ browseButton: IButtonOptions;
78
79
  };
79
80
  progressBar: {
80
81
  /** True if you want the animation to be reversed globally. */
package/dist/Settings.js CHANGED
@@ -106,7 +106,8 @@ export var Settings = {
106
106
  disallowedFileExtensions: [".exe", ".bat", ".cmd", ".sh", ".com", ".ps", ".ps1", ".dll"],
107
107
  /** Global allowed extensions. Can be changed on each file upload manager. Must be lower case. */
108
108
  allowedExtensions: [],
109
- fileEditorButton: { variant: "dark" }
109
+ fileEditorButton: { variant: "dark" },
110
+ browseButton: { variant: "light" },
110
111
  },
111
112
  progressBar: {
112
113
  /** True if you want the animation to be reversed globally. */
@@ -57,7 +57,7 @@ export declare abstract class CustomRule<T extends IModelBase> extends Rule impl
57
57
  }
58
58
  export declare class CallbackRule<T extends IModelBase> extends CustomRule<T> {
59
59
  private validateFn;
60
- hasBoundFunction: boolean;
60
+ hasArrowFunction: boolean;
61
61
  constructor(validateFn: (context: RuleContext) => void);
62
62
  checkRule(propertyInstance: IPropertyInstance, context: RuleContext): void;
63
63
  }
@@ -125,14 +125,14 @@ var CallbackRule = /** @class */ (function (_super) {
125
125
  function CallbackRule(validateFn) {
126
126
  var _this = _super.call(this) || this;
127
127
  _this.validateFn = validateFn;
128
- _this.hasBoundFunction = false;
129
- if (!validateFn.hasOwnProperty("prototype")) {
130
- _this.hasBoundFunction = true;
128
+ _this.hasArrowFunction = false;
129
+ if (!validateFn.hasOwnProperty("prototype") && !validateFn.name) {
130
+ _this.hasArrowFunction = true;
131
131
  }
132
132
  return _this;
133
133
  }
134
134
  CallbackRule.prototype.checkRule = function (propertyInstance, context) {
135
- if (this.hasBoundFunction) {
135
+ if (this.hasArrowFunction) {
136
136
  var reboundFn = this.validateFn.bind(propertyInstance.attachedTo);
137
137
  reboundFn(context);
138
138
  }
@@ -5,10 +5,12 @@ export declare class ValidationRules<T extends IModelBase> {
5
5
  rules: CustomRule<T>[];
6
6
  /**
7
7
  * Registers a custom rule.
8
- * NOTE: Do not use an arrow function: add(context => {}), either pass in the address of a function: add(this.myRule), or pass an anonymous function: add(function(context) {}).
9
- * @param ruleFunction
8
+ * - Pass in the address of a function: `add(MyType.prototype.myRule)`
9
+ * - or pass an anonymous function: `add(function(context) {})`
10
+ *
11
+ * **NOTE: Do not use `.bind(this)`, and do not use an arrow function**.
10
12
  */
11
- add(ruleFunction: (context: IRuleContext) => void): ICustomRule<T>;
13
+ add(ruleFunction: (this: T, context: IRuleContext) => void): ICustomRule<T>;
12
14
  failWhen(failCondition: RuleExpression<T>, errorTextExpression: ErrorExpression<T>): IExpressionRule<T>;
13
15
  failWhen(failCondition: RuleExpression<T>, errorText: string): IExpressionRule<T>;
14
16
  warnWhen(condition: RuleExpression<T>, warningTextExpression: ErrorExpression<T>): IExpressionRule<T>;
@@ -6,8 +6,10 @@ var ValidationRules = /** @class */ (function () {
6
6
  }
7
7
  /**
8
8
  * Registers a custom rule.
9
- * NOTE: Do not use an arrow function: add(context => {}), either pass in the address of a function: add(this.myRule), or pass an anonymous function: add(function(context) {}).
10
- * @param ruleFunction
9
+ * - Pass in the address of a function: `add(MyType.prototype.myRule)`
10
+ * - or pass an anonymous function: `add(function(context) {})`
11
+ *
12
+ * **NOTE: Do not use `.bind(this)`, and do not use an arrow function**.
11
13
  */
12
14
  ValidationRules.prototype.add = function (ruleFunction) {
13
15
  var rule = new CallbackRule(ruleFunction);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singularsystems/neo-core",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Core functionality for the Neo client library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",