@itwin/core-backend 4.6.0-dev.1 → 4.6.0-dev.13

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,6 +1,31 @@
1
1
  # Change Log - @itwin/core-backend
2
2
 
3
- This log was last generated on Mon, 25 Mar 2024 22:24:35 GMT and should not be manually modified.
3
+ This log was last generated on Mon, 15 Apr 2024 20:32:33 GMT and should not be manually modified.
4
+
5
+ ## 4.5.1
6
+ Wed, 03 Apr 2024 18:26:58 GMT
7
+
8
+ _Version update only_
9
+
10
+ ## 4.5.0
11
+ Tue, 02 Apr 2024 19:06:00 GMT
12
+
13
+ ### Updates
14
+
15
+ - Fix SectionDrawing.insert to insert a SectionDrawingModel, not a DrawingModel.
16
+ - Added busyTimeout parameter to allow read/write connection to set it.
17
+ - Added new tests for selecting duplicate property names using UseECSqlPropertyNames QueryRowFormat.
18
+ - Add metadata to errors thrown by `insertElement`, `updateElement` and `deleteElement` in `IModelDb`
19
+ - make case of pattern_useconstantlod match backend code
20
+ - `IModelDb`: Fix `IModelDb.views.accessViewStore` ignoring supplied `userToken` and `accessLevel` values
21
+ - Throws an error if BlobContainer.service is undefined in CloudSqlite.requestToken
22
+ - add SnapshotDb.openCheckpoint to open a checkpoint directly from its cloud container
23
+ - Introduce EditableWorkspaceDb.
24
+
25
+ ## 4.4.9
26
+ Mon, 15 Apr 2024 20:29:22 GMT
27
+
28
+ _Version update only_
4
29
 
5
30
  ## 4.4.8
6
31
  Mon, 25 Mar 2024 22:22:26 GMT
@@ -7,7 +7,7 @@ import { Schema } from "./Schema";
7
7
  *
8
8
  * It is automatically registered when [[IModelHost.startup]] is called.
9
9
  *
10
- * ** Example:**
10
+ * Example:
11
11
  * ``` ts
12
12
  * [[include:BisCore.registerSchemaAndGetClass]]
13
13
  * ```
@@ -27,7 +27,7 @@ const displayStyleMod = require("./DisplayStyle");
27
27
  *
28
28
  * It is automatically registered when [[IModelHost.startup]] is called.
29
29
  *
30
- * ** Example:**
30
+ * Example:
31
31
  * ``` ts
32
32
  * [[include:BisCore.registerSchemaAndGetClass]]
33
33
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"BisCoreSchema.js","sourceRoot":"","sources":["../../src/BisCoreSchema.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,6BAA6B;AAC7B,0CAA0C;AAC1C,mDAAgD;AAChD,wCAAwC;AACxC,6CAA6C;AAC7C,sDAAsD;AACtD,6CAA8C;AAC9C,0CAA0C;AAC1C,oCAAoC;AACpC,0CAA0C;AAC1C,qCAA2C;AAC3C,wCAAwC;AACxC,4CAA4C;AAC5C,kDAAkD;AAElD;;;;;;;;;;GAUG;AACH,MAAa,aAAc,SAAQ,eAAM;IAChC,MAAM,KAAc,UAAU,KAAa,OAAO,SAAS,CAAC,CAAC,CAAC;IAC9D,MAAM,KAAK,cAAc,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,2BAAc,CAAC,eAAe,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,UAAU,eAAe,CAAC,CAAC,CAAC,CAAC;IAEhK,gBAAgB;IACT,MAAM,CAAC,cAAc;QAC1B,IAAI,IAAI,KAAK,gBAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC;YACvD,OAAO;QAET,gBAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,gBAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAE7B,sHAAsH;QACtH;YACE,UAAU;YACV,SAAS;YACT,QAAQ;YACR,WAAW;YACX,OAAO;YACP,OAAO;YACP,UAAU;YACV,WAAW;YACX,iBAAiB;YACjB,eAAe;SAChB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,6BAAa,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,CAAC;CACF;AA1BD,sCA0BC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Schema\n */\n\nimport * as path from \"path\";\nimport * as categoryMod from \"./Category\";\nimport { ClassRegistry } from \"./ClassRegistry\";\nimport * as elementMod from \"./Element\";\nimport * as aspectMod from \"./ElementAspect\";\nimport * as externalSourceMod from \"./ExternalSource\";\nimport { KnownLocations } from \"./IModelHost\";\nimport * as materialMod from \"./Material\";\nimport * as modelMod from \"./Model\";\nimport * as linkMod from \"./Relationship\";\nimport { Schema, Schemas } from \"./Schema\";\nimport * as textureMod from \"./Texture\";\nimport * as viewMod from \"./ViewDefinition\";\nimport * as displayStyleMod from \"./DisplayStyle\";\n\n/**\n * The [BisCore]($docs/bis/guide/fundamentals/schemas-domains.md) schema is the lowest level Schema in an iModel.\n *\n * It is automatically registered when [[IModelHost.startup]] is called.\n *\n * ** Example:**\n * ``` ts\n * [[include:BisCore.registerSchemaAndGetClass]]\n * ```\n * @public\n */\nexport class BisCoreSchema extends Schema {\n public static override get schemaName(): string { return \"BisCore\"; }\n public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, \"ECSchemas\", \"Dgn\", `${BisCoreSchema.schemaName}.ecschema.xml`); }\n\n /** @internal */\n public static registerSchema() {\n if (this === Schemas.getRegisteredSchema(this.schemaName))\n return;\n\n Schemas.unregisterSchema(this.schemaName);\n Schemas.registerSchema(this);\n\n // this list should include all backend .ts files with implementations of Entity-based classes. Order does not matter.\n [\n elementMod,\n aspectMod,\n modelMod,\n categoryMod,\n viewMod,\n linkMod,\n textureMod,\n materialMod,\n externalSourceMod,\n displayStyleMod,\n ].forEach((module) => ClassRegistry.registerModule(module, this));\n }\n}\n"]}
1
+ {"version":3,"file":"BisCoreSchema.js","sourceRoot":"","sources":["../../src/BisCoreSchema.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,6BAA6B;AAC7B,0CAA0C;AAC1C,mDAAgD;AAChD,wCAAwC;AACxC,6CAA6C;AAC7C,sDAAsD;AACtD,6CAA8C;AAC9C,0CAA0C;AAC1C,oCAAoC;AACpC,0CAA0C;AAC1C,qCAA2C;AAC3C,wCAAwC;AACxC,4CAA4C;AAC5C,kDAAkD;AAElD;;;;;;;;;;GAUG;AACH,MAAa,aAAc,SAAQ,eAAM;IAChC,MAAM,KAAc,UAAU,KAAa,OAAO,SAAS,CAAC,CAAC,CAAC;IAC9D,MAAM,KAAK,cAAc,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,2BAAc,CAAC,eAAe,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,UAAU,eAAe,CAAC,CAAC,CAAC,CAAC;IAEhK,gBAAgB;IACT,MAAM,CAAC,cAAc;QAC1B,IAAI,IAAI,KAAK,gBAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC;YACvD,OAAO;QAET,gBAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,gBAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAE7B,sHAAsH;QACtH;YACE,UAAU;YACV,SAAS;YACT,QAAQ;YACR,WAAW;YACX,OAAO;YACP,OAAO;YACP,UAAU;YACV,WAAW;YACX,iBAAiB;YACjB,eAAe;SAChB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,6BAAa,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,CAAC;CACF;AA1BD,sCA0BC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Schema\n */\n\nimport * as path from \"path\";\nimport * as categoryMod from \"./Category\";\nimport { ClassRegistry } from \"./ClassRegistry\";\nimport * as elementMod from \"./Element\";\nimport * as aspectMod from \"./ElementAspect\";\nimport * as externalSourceMod from \"./ExternalSource\";\nimport { KnownLocations } from \"./IModelHost\";\nimport * as materialMod from \"./Material\";\nimport * as modelMod from \"./Model\";\nimport * as linkMod from \"./Relationship\";\nimport { Schema, Schemas } from \"./Schema\";\nimport * as textureMod from \"./Texture\";\nimport * as viewMod from \"./ViewDefinition\";\nimport * as displayStyleMod from \"./DisplayStyle\";\n\n/**\n * The [BisCore]($docs/bis/guide/fundamentals/schemas-domains.md) schema is the lowest level Schema in an iModel.\n *\n * It is automatically registered when [[IModelHost.startup]] is called.\n *\n * Example:\n * ``` ts\n * [[include:BisCore.registerSchemaAndGetClass]]\n * ```\n * @public\n */\nexport class BisCoreSchema extends Schema {\n public static override get schemaName(): string { return \"BisCore\"; }\n public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, \"ECSchemas\", \"Dgn\", `${BisCoreSchema.schemaName}.ecschema.xml`); }\n\n /** @internal */\n public static registerSchema() {\n if (this === Schemas.getRegisteredSchema(this.schemaName))\n return;\n\n Schemas.unregisterSchema(this.schemaName);\n Schemas.registerSchema(this);\n\n // this list should include all backend .ts files with implementations of Entity-based classes. Order does not matter.\n [\n elementMod,\n aspectMod,\n modelMod,\n categoryMod,\n viewMod,\n linkMod,\n textureMod,\n materialMod,\n externalSourceMod,\n displayStyleMod,\n ].forEach((module) => ClassRegistry.registerModule(module, this));\n }\n}\n"]}
@@ -14,8 +14,6 @@ export type ChannelKey = string;
14
14
  * @beta
15
15
  */
16
16
  export interface ChannelControl {
17
- /** Determine whether this [[IModelDb]] has any channels in it. */
18
- get hasChannels(): boolean;
19
17
  /** Add a new channel to the list of allowed channels of the [[IModelDb]] for this session.
20
18
  * @param channelKey The key for the channel to become editable in this session.
21
19
  */
@@ -29,13 +27,14 @@ export interface ChannelControl {
29
27
  */
30
28
  getChannelKey(elementId: Id64String): ChannelKey;
31
29
  /** Make an existing element a new Channel root.
32
- * @note if the element is already in a channel, this will throw an error.
30
+ * @throws if the element is already in a channel different than the shared channel, or if
31
+ * there is already another channelRoot element for the specified channelKey
33
32
  */
34
33
  makeChannelRoot(args: {
35
34
  elementId: Id64String;
36
35
  channelKey: ChannelKey;
37
36
  }): void;
38
- /** Insert a new Subject element that is a Channel root in this iModel.
37
+ /** Insert a new Subject element that is a Channel Root in this iModel.
39
38
  * @returns the ElementId of the new Subject element.
40
39
  * @note if the parentSubject element is already in a channel, this will add the Subject element and then throw an error without making it a Channel root.
41
40
  */
@@ -49,6 +48,13 @@ export interface ChannelControl {
49
48
  /** Optional description for new Subject. */
50
49
  description?: string;
51
50
  }): Id64String;
51
+ /**
52
+ * Queries for the element Id acting as the ChannelRoot for a given channelKey, if any
53
+ * @param channelKey The key for the channel to query for
54
+ * @returns The element Id of the ChannelRoot element of the specified Channel key, or undefined if
55
+ * there is no ChannelRoot for it
56
+ */
57
+ queryChannelRoot(channelKey: ChannelKey): Id64String | undefined;
52
58
  /** @internal */
53
59
  verifyChannel(modelId: Id64String): void;
54
60
  }
@@ -60,16 +66,13 @@ export declare namespace ChannelControl {
60
66
  /** @internal */
61
67
  export declare class ChannelAdmin implements ChannelControl {
62
68
  private _iModel;
63
- static readonly sharedChannel = "shared";
64
69
  static readonly channelClassName = "bis:ChannelRootAspect";
65
70
  private _allowedChannels;
66
71
  private _allowedModels;
67
72
  private _deniedModels;
68
- private _hasChannels?;
69
73
  constructor(_iModel: IModelDb);
70
74
  addAllowedChannel(channelKey: ChannelKey): void;
71
75
  removeAllowedChannel(channelKey: ChannelKey): void;
72
- get hasChannels(): boolean;
73
76
  getChannelKey(elementId: Id64String): ChannelKey;
74
77
  verifyChannel(modelId: Id64String): void;
75
78
  makeChannelRoot(args: {
@@ -82,5 +85,6 @@ export declare class ChannelAdmin implements ChannelControl {
82
85
  parentSubjectId?: Id64String;
83
86
  description?: string;
84
87
  }): Id64String;
88
+ queryChannelRoot(channelKey: ChannelKey): Id64String | undefined;
85
89
  }
86
90
  //# sourceMappingURL=ChannelControl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelControl.d.ts","sourceRoot":"","sources":["../../src/ChannelControl.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAY,UAAU,EAAkC,MAAM,qBAAqB,CAAC;AAG3F,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,IAAI,WAAW,IAAI,OAAO,CAAC;IAC3B;;OAEG;IACH,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAChD;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACnD;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAAC;IACjD;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/E;;;OAGG;IACH,oBAAoB,CAAC,IAAI,EAAE;QACzB,0CAA0C;QAC1C,WAAW,EAAE,MAAM,CAAC;QACpB,kGAAkG;QAClG,UAAU,EAAE,UAAU,CAAC;QACvB,oFAAoF;QACpF,eAAe,CAAC,EAAE,UAAU,CAAC;QAC7B,4CAA4C;QAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,UAAU,CAAC;IAEf,gBAAgB;IAChB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1C;AAED,YAAY;AACZ,yBAAiB,cAAc,CAAC;IAC9B,wGAAwG;IACjG,MAAM,iBAAiB,WAAW,CAAC;CAC3C;AAED,gBAAgB;AAChB,qBAAa,YAAa,YAAW,cAAc;IAQ9B,OAAO,CAAC,OAAO;IAPlC,gBAAuB,aAAa,YAAY;IAChD,gBAAuB,gBAAgB,2BAA2B;IAClE,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,aAAa,CAAqC;IAC1D,OAAO,CAAC,YAAY,CAAC,CAAU;gBAEJ,OAAO,EAAE,QAAQ;IAGrC,iBAAiB,CAAC,UAAU,EAAE,UAAU;IAIxC,oBAAoB,CAAC,UAAU,EAAE,UAAU;IAIlD,IAAW,WAAW,IAAI,OAAO,CAUhC;IACM,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU;IAkBhD,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAiBxC,eAAe,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE;IAQvE,oBAAoB,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,UAAU,CAAC;QAAC,eAAe,CAAC,EAAE,UAAU,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;CAKnJ"}
1
+ {"version":3,"file":"ChannelControl.d.ts","sourceRoot":"","sources":["../../src/ChannelControl.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAY,UAAU,EAAkC,MAAM,qBAAqB,CAAC;AAG3F,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAChD;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACnD;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAAC;IACjD;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/E;;;OAGG;IACH,oBAAoB,CAAC,IAAI,EAAE;QACzB,0CAA0C;QAC1C,WAAW,EAAE,MAAM,CAAC;QACpB,kGAAkG;QAClG,UAAU,EAAE,UAAU,CAAC;QACvB,oFAAoF;QACpF,eAAe,CAAC,EAAE,UAAU,CAAC;QAC7B,4CAA4C;QAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,UAAU,CAAC;IACf;;;;;OAKG;IACH,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;IAEjE,gBAAgB;IAChB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1C;AAED,YAAY;AACZ,yBAAiB,cAAc,CAAC;IAC9B,wGAAwG;IACjG,MAAM,iBAAiB,WAAW,CAAC;CAC3C;AAED,gBAAgB;AAChB,qBAAa,YAAa,YAAW,cAAc;IAM9B,OAAO,CAAC,OAAO;IALlC,gBAAuB,gBAAgB,2BAA2B;IAClE,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,aAAa,CAAqC;gBAE/B,OAAO,EAAE,QAAQ;IAMrC,iBAAiB,CAAC,UAAU,EAAE,UAAU;IAIxC,oBAAoB,CAAC,UAAU,EAAE,UAAU;IAI3C,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU;IAwBhD,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAiBxC,eAAe,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE;IAUvE,oBAAoB,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,UAAU,CAAC;QAAC,eAAe,CAAC,EAAE,UAAU,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;IAW3I,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS;CAkBxE"}
@@ -11,6 +11,7 @@ exports.ChannelAdmin = exports.ChannelControl = void 0;
11
11
  const core_bentley_1 = require("@itwin/core-bentley");
12
12
  const core_common_1 = require("@itwin/core-common");
13
13
  const Element_1 = require("./Element");
14
+ const IModelHost_1 = require("./IModelHost");
14
15
  /** @beta */
15
16
  var ChannelControl;
16
17
  (function (ChannelControl) {
@@ -24,7 +25,9 @@ class ChannelAdmin {
24
25
  this._allowedChannels = new Set();
25
26
  this._allowedModels = new Set();
26
27
  this._deniedModels = new Map();
27
- this._allowedChannels.add(ChannelControl.sharedChannelName);
28
+ // for backwards compatibility, allow the shared channel unless explicitly turned off in IModelHostOptions.
29
+ if (IModelHost_1.IModelHost.configuration?.allowSharedChannel !== false)
30
+ this._allowedChannels.add(ChannelControl.sharedChannelName);
28
31
  }
29
32
  addAllowedChannel(channelKey) {
30
33
  this._allowedChannels.add(channelKey);
@@ -34,27 +37,22 @@ class ChannelAdmin {
34
37
  this._allowedChannels.delete(channelKey);
35
38
  this._allowedModels.clear();
36
39
  }
37
- get hasChannels() {
38
- if (undefined === this._hasChannels) {
39
- try {
40
- this._hasChannels = this._iModel.withStatement(`SELECT 1 FROM ${ChannelAdmin.channelClassName}`, (stmt) => stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW, false);
41
- }
42
- catch (e) {
43
- // iModel doesn't have channel class in its BIS schema
44
- this._hasChannels = false;
45
- }
46
- }
47
- return this._hasChannels;
48
- }
49
40
  getChannelKey(elementId) {
50
- if (!this.hasChannels || elementId === core_common_1.IModel.rootSubjectId)
41
+ if (elementId === core_common_1.IModel.rootSubjectId)
51
42
  return ChannelControl.sharedChannelName;
52
- const channel = this._iModel.withPreparedStatement(`SELECT Owner FROM ${ChannelAdmin.channelClassName} WHERE Element.Id=?`, (stmt) => {
53
- stmt.bindId(1, elementId);
54
- return core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getValue(0).getString() : undefined;
55
- });
56
- if (channel !== undefined)
57
- return channel;
43
+ try {
44
+ const channel = this._iModel.withPreparedStatement(`SELECT Owner FROM ${ChannelAdmin.channelClassName} WHERE Element.Id=?`, (stmt) => {
45
+ stmt.bindId(1, elementId);
46
+ return core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getValue(0).getString() : undefined;
47
+ });
48
+ if (channel !== undefined)
49
+ return channel;
50
+ }
51
+ catch {
52
+ // Exception happens if the iModel is too old: ChannelRootAspect class not present in the BisCore schema (older than v1.0.10).
53
+ // In that case all data in such iModel is assumed to be in the shared channel.
54
+ return ChannelControl.sharedChannelName;
55
+ }
58
56
  const parentId = this._iModel.withPreparedSqliteStatement("SELECT ParentId,ModelId FROM bis_Element WHERE id=?", (stmt) => {
59
57
  stmt.bindId(1, elementId);
60
58
  if (core_bentley_1.DbResult.BE_SQLITE_ROW !== stmt.step())
@@ -65,7 +63,7 @@ class ChannelAdmin {
65
63
  }
66
64
  verifyChannel(modelId) {
67
65
  // Note: indirect changes are permitted to change any channel
68
- if (!this.hasChannels || this._allowedModels.has(modelId) || this._iModel.nativeDb.isIndirectChanges())
66
+ if (this._allowedModels.has(modelId) || this._iModel.nativeDb.isIndirectChanges())
69
67
  return;
70
68
  const deniedChannel = this._deniedModels.get(modelId);
71
69
  if (undefined !== deniedChannel)
@@ -81,17 +79,39 @@ class ChannelAdmin {
81
79
  makeChannelRoot(args) {
82
80
  if (ChannelControl.sharedChannelName !== this.getChannelKey(args.elementId))
83
81
  throw new Error("channels may not nest");
82
+ if (this.queryChannelRoot(args.channelKey) !== undefined)
83
+ throw new Error("a channel root for the specified key already exists");
84
84
  const props = { classFullName: ChannelAdmin.channelClassName, element: { id: args.elementId }, owner: args.channelKey };
85
85
  this._iModel.elements.insertAspect(props);
86
- this._hasChannels = true;
87
86
  }
88
87
  insertChannelSubject(args) {
88
+ // Check if channelKey already exists before inserting Subject.
89
+ // makeChannelRoot will check that again, but at that point the new Subject is already inserted.
90
+ // Prefer to check twice instead of deleting the Subject in the latter option.
91
+ if (this.queryChannelRoot(args.channelKey) !== undefined)
92
+ throw new Error("a channel root for the specified key already exists");
89
93
  const elementId = Element_1.Subject.insert(this._iModel, args.parentSubjectId ?? core_common_1.IModel.rootSubjectId, args.subjectName, args.description);
90
94
  this.makeChannelRoot({ elementId, channelKey: args.channelKey });
91
95
  return elementId;
92
96
  }
97
+ queryChannelRoot(channelKey) {
98
+ if (channelKey === ChannelControl.sharedChannelName)
99
+ // RootSubject acts as the ChannelRoot element of the shared channel
100
+ return core_common_1.IModel.rootSubjectId;
101
+ try {
102
+ const channelRoot = this._iModel.withPreparedStatement(`SELECT Element.Id FROM ${ChannelAdmin.channelClassName} WHERE Owner=?`, (stmt) => {
103
+ stmt.bindString(1, channelKey);
104
+ return core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getValue(0).getId() : undefined;
105
+ });
106
+ return channelRoot;
107
+ }
108
+ catch {
109
+ // Exception happens if the iModel is too old: ChannelRootAspect class not present in the BisCore schema (older than v1.0.10).
110
+ // In that case all data in such iModel is assumed to be in the shared channel.
111
+ return undefined;
112
+ }
113
+ }
93
114
  }
94
- ChannelAdmin.sharedChannel = "shared";
95
115
  ChannelAdmin.channelClassName = "bis:ChannelRootAspect";
96
116
  exports.ChannelAdmin = ChannelAdmin;
97
117
  //# sourceMappingURL=ChannelControl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelControl.js","sourceRoot":"","sources":["../../src/ChannelControl.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Elements\n */\n\nimport { DbResult, Id64String, IModelStatus, RepositoryStatus } from \"@itwin/core-bentley\";\nimport { ChannelRootAspectProps, IModel, IModelError } from \"@itwin/core-common\";\nimport { Subject } from \"./Element\";\nimport { IModelDb } from \"./IModelDb\";\n\n/** The key for a channel. Used for \"allowed channels\" in [[ChannelControl]]\n * @beta\n */\nexport type ChannelKey = string;\n\n/**\n * Controls which channels of an iModel are permitted for write operations. An implementation of this interface is\n * available via [[IModelDb.channels]].\n * @see [Working With Channels]($docs/learning/backend/Channel.md) for details\n * @beta\n */\nexport interface ChannelControl {\n /** Determine whether this [[IModelDb]] has any channels in it. */\n get hasChannels(): boolean;\n /** Add a new channel to the list of allowed channels of the [[IModelDb]] for this session.\n * @param channelKey The key for the channel to become editable in this session.\n */\n addAllowedChannel(channelKey: ChannelKey): void;\n /** Remove a channel from the list of allowed channels of the [[IModelDb]] for this session.\n * @param channelKey The key of the channel that should no longer be editable in this session.\n */\n removeAllowedChannel(channelKey: ChannelKey): void;\n /** Get the channelKey of the channel for an element by ElementId.\n * @throws if the element does not exist\n */\n getChannelKey(elementId: Id64String): ChannelKey;\n /** Make an existing element a new Channel root.\n * @note if the element is already in a channel, this will throw an error.\n */\n makeChannelRoot(args: { elementId: Id64String, channelKey: ChannelKey }): void;\n /** Insert a new Subject element that is a Channel root in this iModel.\n * @returns the ElementId of the new Subject element.\n * @note if the parentSubject element is already in a channel, this will add the Subject element and then throw an error without making it a Channel root.\n */\n insertChannelSubject(args: {\n /** The name of the new Subject element */\n subjectName: string;\n /** The channel key for the new [[Subject]]. This is the string to pass to [[addAllowedChannel]]*/\n channelKey: ChannelKey;\n /** the Id of the parent of the new Subject. Default is [[IModel.rootSubjectId]]. */\n parentSubjectId?: Id64String;\n /** Optional description for new Subject. */\n description?: string;\n }): Id64String;\n\n /** @internal */\n verifyChannel(modelId: Id64String): void;\n}\n\n/** @beta */\nexport namespace ChannelControl {\n /** the name of the special \"shared\" channel holding information that is editable by any application. */\n export const sharedChannelName = \"shared\";\n}\n\n/** @internal */\nexport class ChannelAdmin implements ChannelControl {\n public static readonly sharedChannel = \"shared\";\n public static readonly channelClassName = \"bis:ChannelRootAspect\";\n private _allowedChannels = new Set<ChannelKey>();\n private _allowedModels = new Set<Id64String>();\n private _deniedModels = new Map<Id64String, ChannelKey>();\n private _hasChannels?: boolean;\n\n public constructor(private _iModel: IModelDb) {\n this._allowedChannels.add(ChannelControl.sharedChannelName);\n }\n public addAllowedChannel(channelKey: ChannelKey) {\n this._allowedChannels.add(channelKey);\n this._deniedModels.clear();\n }\n public removeAllowedChannel(channelKey: ChannelKey) {\n this._allowedChannels.delete(channelKey);\n this._allowedModels.clear();\n }\n public get hasChannels(): boolean {\n if (undefined === this._hasChannels) {\n try {\n this._hasChannels = this._iModel.withStatement(`SELECT 1 FROM ${ChannelAdmin.channelClassName}`, (stmt) => stmt.step() === DbResult.BE_SQLITE_ROW, false);\n } catch (e) {\n // iModel doesn't have channel class in its BIS schema\n this._hasChannels = false;\n }\n }\n return this._hasChannels;\n }\n public getChannelKey(elementId: Id64String): ChannelKey {\n if (!this.hasChannels || elementId === IModel.rootSubjectId)\n return ChannelControl.sharedChannelName;\n\n const channel = this._iModel.withPreparedStatement(`SELECT Owner FROM ${ChannelAdmin.channelClassName} WHERE Element.Id=?`, (stmt) => {\n stmt.bindId(1, elementId);\n return DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getValue(0).getString() : undefined;\n });\n if (channel !== undefined)\n return channel;\n const parentId = this._iModel.withPreparedSqliteStatement(\"SELECT ParentId,ModelId FROM bis_Element WHERE id=?\", (stmt) => {\n stmt.bindId(1, elementId);\n if (DbResult.BE_SQLITE_ROW !== stmt.step())\n throw new IModelError(IModelStatus.NotFound, \"Element does not exist\");\n return stmt.getValueId(0) ?? stmt.getValueId(1); // if parent is undefined, use modelId\n });\n return this.getChannelKey(parentId);\n }\n public verifyChannel(modelId: Id64String): void {\n // Note: indirect changes are permitted to change any channel\n if (!this.hasChannels || this._allowedModels.has(modelId) || this._iModel.nativeDb.isIndirectChanges())\n return;\n\n const deniedChannel = this._deniedModels.get(modelId);\n if (undefined !== deniedChannel)\n throw new IModelError(RepositoryStatus.ChannelConstraintViolation, `channel \"${deniedChannel}\" is not allowed`);\n\n const channel = this.getChannelKey(modelId);\n if (this._allowedChannels.has(channel)) {\n this._allowedModels.add(modelId);\n return;\n }\n this._deniedModels.set(modelId, channel);\n return this.verifyChannel(modelId);\n }\n public makeChannelRoot(args: { elementId: Id64String, channelKey: ChannelKey }) {\n if (ChannelControl.sharedChannelName !== this.getChannelKey(args.elementId))\n throw new Error(\"channels may not nest\");\n\n const props: ChannelRootAspectProps = { classFullName: ChannelAdmin.channelClassName, element: { id: args.elementId }, owner: args.channelKey };\n this._iModel.elements.insertAspect(props);\n this._hasChannels = true;\n }\n public insertChannelSubject(args: { subjectName: string, channelKey: ChannelKey, parentSubjectId?: Id64String, description?: string }): Id64String {\n const elementId = Subject.insert(this._iModel, args.parentSubjectId ?? IModel.rootSubjectId, args.subjectName, args.description);\n this.makeChannelRoot({ elementId, channelKey: args.channelKey });\n return elementId;\n }\n}\n"]}
1
+ {"version":3,"file":"ChannelControl.js","sourceRoot":"","sources":["../../src/ChannelControl.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Elements\n */\n\nimport { DbResult, Id64String, IModelStatus, RepositoryStatus } from \"@itwin/core-bentley\";\nimport { ChannelRootAspectProps, IModel, IModelError } from \"@itwin/core-common\";\nimport { Subject } from \"./Element\";\nimport { IModelDb } from \"./IModelDb\";\nimport { IModelHost } from \"./IModelHost\";\n\n/** The key for a channel. Used for \"allowed channels\" in [[ChannelControl]]\n * @beta\n */\nexport type ChannelKey = string;\n\n/**\n * Controls which channels of an iModel are permitted for write operations. An implementation of this interface is\n * available via [[IModelDb.channels]].\n * @see [Working With Channels]($docs/learning/backend/Channel.md) for details\n * @beta\n */\nexport interface ChannelControl {\n /** Add a new channel to the list of allowed channels of the [[IModelDb]] for this session.\n * @param channelKey The key for the channel to become editable in this session.\n */\n addAllowedChannel(channelKey: ChannelKey): void;\n /** Remove a channel from the list of allowed channels of the [[IModelDb]] for this session.\n * @param channelKey The key of the channel that should no longer be editable in this session.\n */\n removeAllowedChannel(channelKey: ChannelKey): void;\n /** Get the channelKey of the channel for an element by ElementId.\n * @throws if the element does not exist\n */\n getChannelKey(elementId: Id64String): ChannelKey;\n /** Make an existing element a new Channel root.\n * @throws if the element is already in a channel different than the shared channel, or if\n * there is already another channelRoot element for the specified channelKey\n */\n makeChannelRoot(args: { elementId: Id64String, channelKey: ChannelKey }): void;\n /** Insert a new Subject element that is a Channel Root in this iModel.\n * @returns the ElementId of the new Subject element.\n * @note if the parentSubject element is already in a channel, this will add the Subject element and then throw an error without making it a Channel root.\n */\n insertChannelSubject(args: {\n /** The name of the new Subject element */\n subjectName: string;\n /** The channel key for the new [[Subject]]. This is the string to pass to [[addAllowedChannel]]*/\n channelKey: ChannelKey;\n /** the Id of the parent of the new Subject. Default is [[IModel.rootSubjectId]]. */\n parentSubjectId?: Id64String;\n /** Optional description for new Subject. */\n description?: string;\n }): Id64String;\n /**\n * Queries for the element Id acting as the ChannelRoot for a given channelKey, if any\n * @param channelKey The key for the channel to query for\n * @returns The element Id of the ChannelRoot element of the specified Channel key, or undefined if\n * there is no ChannelRoot for it\n */\n queryChannelRoot(channelKey: ChannelKey): Id64String | undefined;\n\n /** @internal */\n verifyChannel(modelId: Id64String): void;\n}\n\n/** @beta */\nexport namespace ChannelControl {\n /** the name of the special \"shared\" channel holding information that is editable by any application. */\n export const sharedChannelName = \"shared\";\n}\n\n/** @internal */\nexport class ChannelAdmin implements ChannelControl {\n public static readonly channelClassName = \"bis:ChannelRootAspect\";\n private _allowedChannels = new Set<ChannelKey>();\n private _allowedModels = new Set<Id64String>();\n private _deniedModels = new Map<Id64String, ChannelKey>();\n\n public constructor(private _iModel: IModelDb) {\n // for backwards compatibility, allow the shared channel unless explicitly turned off in IModelHostOptions.\n if (IModelHost.configuration?.allowSharedChannel !== false)\n this._allowedChannels.add(ChannelControl.sharedChannelName);\n\n }\n public addAllowedChannel(channelKey: ChannelKey) {\n this._allowedChannels.add(channelKey);\n this._deniedModels.clear();\n }\n public removeAllowedChannel(channelKey: ChannelKey) {\n this._allowedChannels.delete(channelKey);\n this._allowedModels.clear();\n }\n public getChannelKey(elementId: Id64String): ChannelKey {\n if (elementId === IModel.rootSubjectId)\n return ChannelControl.sharedChannelName;\n\n try {\n const channel = this._iModel.withPreparedStatement(`SELECT Owner FROM ${ChannelAdmin.channelClassName} WHERE Element.Id=?`, (stmt) => {\n stmt.bindId(1, elementId);\n return DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getValue(0).getString() : undefined;\n });\n if (channel !== undefined)\n return channel;\n } catch {\n // Exception happens if the iModel is too old: ChannelRootAspect class not present in the BisCore schema (older than v1.0.10).\n // In that case all data in such iModel is assumed to be in the shared channel.\n return ChannelControl.sharedChannelName;\n }\n const parentId = this._iModel.withPreparedSqliteStatement(\"SELECT ParentId,ModelId FROM bis_Element WHERE id=?\", (stmt) => {\n stmt.bindId(1, elementId);\n if (DbResult.BE_SQLITE_ROW !== stmt.step())\n throw new IModelError(IModelStatus.NotFound, \"Element does not exist\");\n return stmt.getValueId(0) ?? stmt.getValueId(1); // if parent is undefined, use modelId\n });\n return this.getChannelKey(parentId);\n }\n public verifyChannel(modelId: Id64String): void {\n // Note: indirect changes are permitted to change any channel\n if (this._allowedModels.has(modelId) || this._iModel.nativeDb.isIndirectChanges())\n return;\n\n const deniedChannel = this._deniedModels.get(modelId);\n if (undefined !== deniedChannel)\n throw new IModelError(RepositoryStatus.ChannelConstraintViolation, `channel \"${deniedChannel}\" is not allowed`);\n\n const channel = this.getChannelKey(modelId);\n if (this._allowedChannels.has(channel)) {\n this._allowedModels.add(modelId);\n return;\n }\n this._deniedModels.set(modelId, channel);\n return this.verifyChannel(modelId);\n }\n public makeChannelRoot(args: { elementId: Id64String, channelKey: ChannelKey }) {\n if (ChannelControl.sharedChannelName !== this.getChannelKey(args.elementId))\n throw new Error(\"channels may not nest\");\n\n if (this.queryChannelRoot(args.channelKey) !== undefined)\n throw new Error(\"a channel root for the specified key already exists\");\n\n const props: ChannelRootAspectProps = { classFullName: ChannelAdmin.channelClassName, element: { id: args.elementId }, owner: args.channelKey };\n this._iModel.elements.insertAspect(props);\n }\n public insertChannelSubject(args: { subjectName: string, channelKey: ChannelKey, parentSubjectId?: Id64String, description?: string }): Id64String {\n // Check if channelKey already exists before inserting Subject.\n // makeChannelRoot will check that again, but at that point the new Subject is already inserted.\n // Prefer to check twice instead of deleting the Subject in the latter option.\n if (this.queryChannelRoot(args.channelKey) !== undefined)\n throw new Error(\"a channel root for the specified key already exists\");\n\n const elementId = Subject.insert(this._iModel, args.parentSubjectId ?? IModel.rootSubjectId, args.subjectName, args.description);\n this.makeChannelRoot({ elementId, channelKey: args.channelKey });\n return elementId;\n }\n public queryChannelRoot(channelKey: ChannelKey): Id64String | undefined {\n if (channelKey === ChannelControl.sharedChannelName)\n // RootSubject acts as the ChannelRoot element of the shared channel\n return IModel.rootSubjectId;\n\n try {\n const channelRoot = this._iModel.withPreparedStatement(`SELECT Element.Id FROM ${ChannelAdmin.channelClassName} WHERE Owner=?`, (stmt) => {\n stmt.bindString(1, channelKey);\n return DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getValue(0).getId() : undefined;\n });\n return channelRoot;\n } catch {\n // Exception happens if the iModel is too old: ChannelRootAspect class not present in the BisCore schema (older than v1.0.10).\n // In that case all data in such iModel is assumed to be in the shared channel.\n return undefined;\n }\n\n }\n}\n"]}
@@ -5,7 +5,9 @@ import { EntityMetaData, IModelError } from "@itwin/core-common";
5
5
  import { Entity } from "./Entity";
6
6
  import { IModelDb } from "./IModelDb";
7
7
  import { Schema } from "./Schema";
8
- /** The mapping between a BIS class name (in the form "schema:class") and its JavaScript constructor function
8
+ /** Maintains the mapping between the name of a BIS [ECClass]($ecschema-metadata) (in "schema:class" format) and the JavaScript [[Entity]] class that implements it.
9
+ * Applications or modules that supply their own Entity subclasses should use [[registerModule]] or [[register]] at startup
10
+ * to establish their mappings.
9
11
  * @public
10
12
  */
11
13
  export declare class ClassRegistry {
@@ -14,7 +16,10 @@ export declare class ClassRegistry {
14
16
  static isNotFoundError(err: any): boolean;
15
17
  /** @internal */
16
18
  static makeMetaDataNotFoundError(className: string): IModelError;
17
- /** @internal */
19
+ /** Register a single `entityClass` defined in the specified `schema`.
20
+ * @see [[registerModule]] to register multiple classes.
21
+ * @public
22
+ */
18
23
  static register(entityClass: typeof Entity, schema: typeof Schema): void;
19
24
  /** Generate a proxy Schema for a domain that has not been registered. */
20
25
  private static generateProxySchema;
@@ -30,9 +35,10 @@ export declare class ClassRegistry {
30
35
  * @param entityMetaData The Entity metadata that defines the class
31
36
  */
32
37
  private static generateClassForEntity;
33
- /** Register all of the classes found in the given module that derive from Entity. See the example in [[Schema]]
38
+ /** Register all of the classes found in the given module that derive from [[Entity]].
39
+ * [[register]] will be invoked for each subclass of `Entity` exported by `moduleObj`.
34
40
  * @param moduleObj The module to search for subclasses of Entity
35
- * @param schema The schema for all found classes
41
+ * @param schema The schema that contains all of the [ECClass]($ecschema-metadata)es exported by `moduleObj`.
36
42
  */
37
43
  static registerModule(moduleObj: any, schema: typeof Schema): void;
38
44
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ClassRegistry.d.ts","sourceRoot":"","sources":["../../src/ClassRegistry.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAsB,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AACrG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAW,MAAM,UAAU,CAAC;AAM3C;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAoC;IACrE,gBAAgB;WACF,eAAe,CAAC,GAAG,EAAE,GAAG;IACtC,gBAAgB;WACF,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW;IACvE,gBAAgB;WACF,QAAQ,CAAC,WAAW,EAAE,OAAO,MAAM,EAAE,MAAM,EAAE,OAAO,MAAM;IAYxE,yEAAyE;IACzE,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAqBlC;;;;;;OAMG;WACW,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM;IAkB9E;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAyGrC;;;OAGG;WACW,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,MAAM;IAQlE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAa5B;;;;OAIG;WACW,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,MAAM,GAAG,SAAS;IAInF;;;;OAIG;WACW,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,MAAM;IAM9E;;;;;OAKG;WACW,eAAe,CAAC,aAAa,EAAE,MAAM;IACnD;;;;OAIG;WACW,qBAAqB,CAAC,MAAM,EAAE,OAAO,MAAM;CAM1D;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAkE;IAEnF,wCAAwC;IACjC,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAE9D,gCAAgC;IACzB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;CAClE"}
1
+ {"version":3,"file":"ClassRegistry.d.ts","sourceRoot":"","sources":["../../src/ClassRegistry.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAsB,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AACrG,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAW,MAAM,UAAU,CAAC;AAM3C;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAoC;IACrE,gBAAgB;WACF,eAAe,CAAC,GAAG,EAAE,GAAG;IACtC,gBAAgB;WACF,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW;IACvE;;;OAGG;WACW,QAAQ,CAAC,WAAW,EAAE,OAAO,MAAM,EAAE,MAAM,EAAE,OAAO,MAAM;IAYxE,yEAAyE;IACzE,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAqBlC;;;;;;OAMG;WACW,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM;IAkB9E;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAyGrC;;;;OAIG;WACW,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,MAAM;IAQlE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAa5B;;;;OAIG;WACW,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,MAAM,GAAG,SAAS;IAInF;;;;OAIG;WACW,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,MAAM;IAM9E;;;;;OAKG;WACW,eAAe,CAAC,aAAa,EAAE,MAAM;IACnD;;;;OAIG;WACW,qBAAqB,CAAC,MAAM,EAAE,OAAO,MAAM;CAM1D;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAkE;IAEnF,wCAAwC;IACjC,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAE9D,gCAAgC;IACzB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;CAClE"}
@@ -19,7 +19,9 @@ const Schema_1 = require("./Schema");
19
19
  const EntityReferences_1 = require("./EntityReferences");
20
20
  const assert = require("assert");
21
21
  const isGeneratedClassTag = Symbol("isGeneratedClassTag");
22
- /** The mapping between a BIS class name (in the form "schema:class") and its JavaScript constructor function
22
+ /** Maintains the mapping between the name of a BIS [ECClass]($ecschema-metadata) (in "schema:class" format) and the JavaScript [[Entity]] class that implements it.
23
+ * Applications or modules that supply their own Entity subclasses should use [[registerModule]] or [[register]] at startup
24
+ * to establish their mappings.
23
25
  * @public
24
26
  */
25
27
  class ClassRegistry {
@@ -27,7 +29,10 @@ class ClassRegistry {
27
29
  static isNotFoundError(err) { return (err instanceof core_common_1.IModelError) && (err.errorNumber === core_bentley_1.IModelStatus.NotFound); }
28
30
  /** @internal */
29
31
  static makeMetaDataNotFoundError(className) { return new core_common_1.IModelError(core_bentley_1.IModelStatus.NotFound, `metadata not found for ${className}`); }
30
- /** @internal */
32
+ /** Register a single `entityClass` defined in the specified `schema`.
33
+ * @see [[registerModule]] to register multiple classes.
34
+ * @public
35
+ */
31
36
  static register(entityClass, schema) {
32
37
  entityClass.schema = schema;
33
38
  const key = (`${schema.schemaName}:${entityClass.className}`).toLowerCase();
@@ -174,9 +179,10 @@ class ClassRegistry {
174
179
  this.register(generatedClass, schema); // register it before returning
175
180
  return generatedClass;
176
181
  }
177
- /** Register all of the classes found in the given module that derive from Entity. See the example in [[Schema]]
182
+ /** Register all of the classes found in the given module that derive from [[Entity]].
183
+ * [[register]] will be invoked for each subclass of `Entity` exported by `moduleObj`.
178
184
  * @param moduleObj The module to search for subclasses of Entity
179
- * @param schema The schema for all found classes
185
+ * @param schema The schema that contains all of the [ECClass]($ecschema-metadata)es exported by `moduleObj`.
180
186
  */
181
187
  static registerModule(moduleObj, schema) {
182
188
  for (const thisMember in moduleObj) { // eslint-disable-line guard-for-in
@@ -1 +1 @@
1
- {"version":3,"file":"ClassRegistry.js","sourceRoot":"","sources":["../../src/ClassRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Schema\n */\n\nimport { DbResult, Id64, IModelStatus, Logger } from \"@itwin/core-bentley\";\nimport { EntityMetaData, EntityReferenceSet, IModelError, RelatedElement } from \"@itwin/core-common\";\nimport { Entity } from \"./Entity\";\nimport { IModelDb } from \"./IModelDb\";\nimport { Schema, Schemas } from \"./Schema\";\nimport { EntityReferences } from \"./EntityReferences\";\nimport * as assert from \"assert\";\n\nconst isGeneratedClassTag = Symbol(\"isGeneratedClassTag\");\n\n/** The mapping between a BIS class name (in the form \"schema:class\") and its JavaScript constructor function\n * @public\n */\nexport class ClassRegistry {\n private static readonly _classMap = new Map<string, typeof Entity>();\n /** @internal */\n public static isNotFoundError(err: any) { return (err instanceof IModelError) && (err.errorNumber === IModelStatus.NotFound); }\n /** @internal */\n public static makeMetaDataNotFoundError(className: string): IModelError { return new IModelError(IModelStatus.NotFound, `metadata not found for ${className}`); }\n /** @internal */\n public static register(entityClass: typeof Entity, schema: typeof Schema) {\n entityClass.schema = schema;\n const key = (`${schema.schemaName}:${entityClass.className}`).toLowerCase();\n if (this._classMap.has(key)) {\n const errMsg = `Class ${key} is already registered. Make sure static className member is correct on JavaScript class ${entityClass.name}`;\n Logger.logError(\"core-frontend.classRegistry\", errMsg);\n throw new Error(errMsg);\n }\n\n this._classMap.set(key, entityClass);\n }\n\n /** Generate a proxy Schema for a domain that has not been registered. */\n private static generateProxySchema(domain: string, iModel: IModelDb): typeof Schema {\n const hasBehavior = iModel.withPreparedSqliteStatement(`\n SELECT NULL FROM [ec_CustomAttribute] [c]\n JOIN [ec_schema] [s] ON [s].[Id] = [c].[ContainerId]\n JOIN [ec_class] [e] ON [e].[Id] = [c].[ClassId]\n JOIN [ec_schema] [b] ON [e].[SchemaId] = [b].[Id]\n WHERE [c].[ContainerType] = 1 AND [s].[Name] = ? AND [b].[Name] || '.' || [e].[name] = ?`, (stmt) => {\n stmt.bindString(1, domain);\n stmt.bindString(2, \"BisCore.SchemaHasBehavior\");\n return stmt.step() === DbResult.BE_SQLITE_ROW;\n });\n\n const schemaClass = class extends Schema {\n public static override get schemaName() { return domain; }\n public static override get missingRequiredBehavior() { return hasBehavior; }\n };\n\n Schemas.registerSchema(schemaClass); // register the class before we return it.\n return schemaClass;\n }\n\n /** First, finds the root BisCore entity class for an entity, by traversing base classes and mixin targets (AppliesTo).\n * Then, gets its metadata and returns that.\n * @param iModel - iModel containing the metadata for this type\n * @param ecTypeQualifier - a full name of an ECEntityClass to find the root of\n * @returns the qualified full name of an ECEntityClass\n * @internal public for testing only\n */\n public static getRootEntity(iModel: IModelDb, ecTypeQualifier: string): string {\n const [classSchema, className] = ecTypeQualifier.split(\".\");\n const schemaItemJson = iModel.nativeDb.getSchemaItem(classSchema, className);\n if (schemaItemJson.error)\n throw new IModelError(schemaItemJson.error.status, `failed to get schema item '${ecTypeQualifier}'`);\n\n assert(undefined !== schemaItemJson.result);\n const schemaItem = JSON.parse(schemaItemJson.result);\n if (!(\"appliesTo\" in schemaItem) && schemaItem.baseClass === undefined) {\n return ecTypeQualifier;\n }\n\n // typescript doesn't understand that the inverse of the above condition is\n // (\"appliesTo\" in rootclassMetaData || rootClassMetaData.baseClass !== undefined)\n const parentItemQualifier = schemaItem.appliesTo ?? schemaItem.baseClass as string;\n return this.getRootEntity(iModel, parentItemQualifier);\n }\n\n /** Generate a JavaScript class from Entity metadata.\n * @param entityMetaData The Entity metadata that defines the class\n */\n private static generateClassForEntity(entityMetaData: EntityMetaData, iModel: IModelDb): typeof Entity {\n const name = entityMetaData.ecclass.split(\":\");\n const domainName = name[0];\n const className = name[1];\n\n if (0 === entityMetaData.baseClasses.length) // metadata must contain a superclass\n throw new IModelError(IModelStatus.BadArg, `class ${name} has no superclass`);\n\n // make sure schema exists\n let schema = Schemas.getRegisteredSchema(domainName);\n if (undefined === schema)\n schema = this.generateProxySchema(domainName, iModel); // no schema found, create it too\n\n const superclass = this._classMap.get(entityMetaData.baseClasses[0].toLowerCase());\n if (undefined === superclass)\n throw new IModelError(IModelStatus.NotFound, `cannot find superclass for class ${name}`);\n\n // user defined class hierarchies may skip a class in the hierarchy, and therefore their JS base class cannot\n // be used to tell if there are any generated classes in the hierarchy\n let generatedClassHasNonGeneratedNonCoreAncestor = false;\n let currentSuperclass = superclass;\n const MAX_ITERS = 1000;\n for (let i = 0; i < MAX_ITERS; ++i) {\n if (currentSuperclass.schema.schemaName === \"BisCore\")\n break;\n\n if (!currentSuperclass.isGeneratedClass) {\n generatedClassHasNonGeneratedNonCoreAncestor = true;\n break;\n }\n const superclassMetaData = iModel.classMetaDataRegistry.find(currentSuperclass.classFullName);\n if (superclassMetaData === undefined)\n throw new IModelError(IModelStatus.BadSchema, `could not find the metadata for class '${currentSuperclass.name}', class metadata should be loaded by now`);\n const maybeNextSuperclass = this.getClass(superclassMetaData.baseClasses[0], iModel);\n if (maybeNextSuperclass === undefined)\n throw new IModelError(IModelStatus.BadSchema, `could not find the base class of '${currentSuperclass.name}', all generated classes must have a base class`);\n currentSuperclass = maybeNextSuperclass;\n }\n\n const generatedClass = class extends superclass {\n public static override get className() { return className; }\n private static [isGeneratedClassTag] = true;\n public static override get isGeneratedClass() { return this.hasOwnProperty(isGeneratedClassTag); }\n };\n\n // the above creates an anonymous class. For help debugging, set the \"constructor.name\" property to be the same as the bisClassName.\n Object.defineProperty(generatedClass, \"name\", { get: () => className }); // this is the (only) way to change that readonly property.\n\n // a class only gets an automatic `collectReferenceIds` implementation if:\n // - it is not in the `BisCore` schema\n // - there are no ancestors with manually registered JS implementations, (excluding BisCore base classes)\n if (!generatedClassHasNonGeneratedNonCoreAncestor) {\n const navigationProps = Object.entries(entityMetaData.properties)\n .filter(([_name, prop]) => prop.isNavigation)\n // eslint-disable-next-line @typescript-eslint/no-shadow\n .map(([name, prop]) => {\n assert(prop.relationshipClass);\n const maybeMetaData = iModel.nativeDb.getSchemaItem(...prop.relationshipClass.split(\":\") as [string, string]);\n assert(maybeMetaData.result !== undefined, \"The nav props relationship metadata was not found\");\n const relMetaData = JSON.parse(maybeMetaData.result);\n const rootClassMetaData = ClassRegistry.getRootEntity(iModel, relMetaData.target.constraintClasses[0]);\n // root class must be in BisCore so should be loaded since biscore classes will never get this\n // generated implementation\n const normalizeClassName = (clsName: string) => clsName.replace(\".\", \":\");\n const rootClass = ClassRegistry.findRegisteredClass(normalizeClassName(rootClassMetaData));\n assert(rootClass, `The root class for ${prop.relationshipClass} was not in BisCore.`);\n return { name, concreteEntityType: EntityReferences.typeFromClass(rootClass) };\n });\n\n Object.defineProperty(\n generatedClass.prototype,\n \"collectReferenceIds\",\n {\n value(this: typeof generatedClass, referenceIds: EntityReferenceSet) {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n const superImpl = superclass.prototype[\"collectReferenceIds\"];\n superImpl.call(this, referenceIds);\n for (const navProp of navigationProps) {\n const relatedElem: RelatedElement | undefined = (this as any)[navProp.name]; // cast to any since subclass can have any extensions\n if (!relatedElem || !Id64.isValid(relatedElem.id))\n continue;\n const referenceId = EntityReferences.fromEntityType(relatedElem.id, navProp.concreteEntityType);\n referenceIds.add(referenceId);\n }\n },\n // defaults for methods on a prototype (required for sinon to stub out methods on tests)\n writable: true,\n configurable: true,\n },\n );\n }\n\n // if the schema is a proxy for a domain with behavior, throw exceptions for all protected operations\n if (schema.missingRequiredBehavior) {\n const throwError = () => {\n throw new IModelError(IModelStatus.WrongHandler, `Schema [${domainName}] not registered, but is marked with SchemaHasBehavior`);\n };\n\n superclass.protectedOperations.forEach((operation) => (generatedClass as any)[operation] = throwError);\n }\n\n this.register(generatedClass, schema); // register it before returning\n return generatedClass;\n }\n\n /** Register all of the classes found in the given module that derive from Entity. See the example in [[Schema]]\n * @param moduleObj The module to search for subclasses of Entity\n * @param schema The schema for all found classes\n */\n public static registerModule(moduleObj: any, schema: typeof Schema) {\n for (const thisMember in moduleObj) { // eslint-disable-line guard-for-in\n const thisClass = moduleObj[thisMember];\n if (thisClass.prototype instanceof Entity)\n this.register(thisClass, schema);\n }\n }\n\n /**\n * This function fetches the specified Entity from the imodel, generates a JavaScript class for it, and registers the generated\n * class. This function also ensures that all of the base classes of the Entity exist and are registered.\n */\n private static generateClass(classFullName: string, iModel: IModelDb): typeof Entity {\n const metadata: EntityMetaData | undefined = iModel.classMetaDataRegistry.find(classFullName);\n if (metadata === undefined || metadata.ecclass === undefined)\n throw this.makeMetaDataNotFoundError(classFullName);\n\n // Make sure we have all base classes registered.\n if (metadata.baseClasses && (0 !== metadata.baseClasses.length))\n this.getClass(metadata.baseClasses[0], iModel);\n\n // Now we can generate the class from the classDef.\n return this.generateClassForEntity(metadata, iModel);\n }\n\n /** Find a registered class by classFullName.\n * @param classFullName class to find\n * @param iModel The IModel that contains the class definitions\n * @returns The Entity class or undefined\n */\n public static findRegisteredClass(classFullName: string): typeof Entity | undefined {\n return this._classMap.get(classFullName.toLowerCase());\n }\n\n /** Get the Entity class for the specified Entity className.\n * @param classFullName The full BIS class name of the Entity\n * @param iModel The IModel that contains the class definitions\n * @returns The Entity class\n */\n public static getClass(classFullName: string, iModel: IModelDb): typeof Entity {\n const key = classFullName.toLowerCase();\n const ctor = this._classMap.get(key);\n return ctor ? ctor : this.generateClass(key, iModel);\n }\n\n /** Unregister a class, by name, if one is already registered.\n * This function is not normally needed, but is useful for cases where a generated *proxy* class needs to be replaced by the *real* class.\n * @param classFullName Name of the class to unregister\n * @return true if the class was unregistered\n * @internal\n */\n public static unregisterCLass(classFullName: string) { return this._classMap.delete(classFullName.toLowerCase()); }\n /** Unregister all classes from a schema.\n * This function is not normally needed, but is useful for cases where a generated *proxy* schema needs to be replaced by the *real* schema.\n * @param schema Name of the schema to unregister\n * @internal\n */\n public static unregisterClassesFrom(schema: typeof Schema) {\n for (const entry of Array.from(this._classMap)) {\n if (entry[1].schema === schema)\n this.unregisterCLass(entry[0]);\n }\n }\n}\n\n/**\n * A cache that records the mapping between class names and class metadata.\n * @see [[IModelDb.classMetaDataRegistry]] to access the registry for a specific iModel.\n * @internal\n */\nexport class MetaDataRegistry {\n private _registry: Map<string, EntityMetaData> = new Map<string, EntityMetaData>();\n\n /** Get the specified Entity metadata */\n public find(classFullName: string): EntityMetaData | undefined { return this._registry.get(classFullName.toLowerCase()); }\n\n /** Add metadata to the cache */\n public add(classFullName: string, metaData: EntityMetaData): void { this._registry.set(classFullName.toLowerCase(), metaData); }\n}\n"]}
1
+ {"version":3,"file":"ClassRegistry.js","sourceRoot":"","sources":["../../src/ClassRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Schema\n */\n\nimport { DbResult, Id64, IModelStatus, Logger } from \"@itwin/core-bentley\";\nimport { EntityMetaData, EntityReferenceSet, IModelError, RelatedElement } from \"@itwin/core-common\";\nimport { Entity } from \"./Entity\";\nimport { IModelDb } from \"./IModelDb\";\nimport { Schema, Schemas } from \"./Schema\";\nimport { EntityReferences } from \"./EntityReferences\";\nimport * as assert from \"assert\";\n\nconst isGeneratedClassTag = Symbol(\"isGeneratedClassTag\");\n\n/** Maintains the mapping between the name of a BIS [ECClass]($ecschema-metadata) (in \"schema:class\" format) and the JavaScript [[Entity]] class that implements it.\n * Applications or modules that supply their own Entity subclasses should use [[registerModule]] or [[register]] at startup\n * to establish their mappings.\n * @public\n */\nexport class ClassRegistry {\n private static readonly _classMap = new Map<string, typeof Entity>();\n /** @internal */\n public static isNotFoundError(err: any) { return (err instanceof IModelError) && (err.errorNumber === IModelStatus.NotFound); }\n /** @internal */\n public static makeMetaDataNotFoundError(className: string): IModelError { return new IModelError(IModelStatus.NotFound, `metadata not found for ${className}`); }\n /** Register a single `entityClass` defined in the specified `schema`.\n * @see [[registerModule]] to register multiple classes.\n * @public\n */\n public static register(entityClass: typeof Entity, schema: typeof Schema) {\n entityClass.schema = schema;\n const key = (`${schema.schemaName}:${entityClass.className}`).toLowerCase();\n if (this._classMap.has(key)) {\n const errMsg = `Class ${key} is already registered. Make sure static className member is correct on JavaScript class ${entityClass.name}`;\n Logger.logError(\"core-frontend.classRegistry\", errMsg);\n throw new Error(errMsg);\n }\n\n this._classMap.set(key, entityClass);\n }\n\n /** Generate a proxy Schema for a domain that has not been registered. */\n private static generateProxySchema(domain: string, iModel: IModelDb): typeof Schema {\n const hasBehavior = iModel.withPreparedSqliteStatement(`\n SELECT NULL FROM [ec_CustomAttribute] [c]\n JOIN [ec_schema] [s] ON [s].[Id] = [c].[ContainerId]\n JOIN [ec_class] [e] ON [e].[Id] = [c].[ClassId]\n JOIN [ec_schema] [b] ON [e].[SchemaId] = [b].[Id]\n WHERE [c].[ContainerType] = 1 AND [s].[Name] = ? AND [b].[Name] || '.' || [e].[name] = ?`, (stmt) => {\n stmt.bindString(1, domain);\n stmt.bindString(2, \"BisCore.SchemaHasBehavior\");\n return stmt.step() === DbResult.BE_SQLITE_ROW;\n });\n\n const schemaClass = class extends Schema {\n public static override get schemaName() { return domain; }\n public static override get missingRequiredBehavior() { return hasBehavior; }\n };\n\n Schemas.registerSchema(schemaClass); // register the class before we return it.\n return schemaClass;\n }\n\n /** First, finds the root BisCore entity class for an entity, by traversing base classes and mixin targets (AppliesTo).\n * Then, gets its metadata and returns that.\n * @param iModel - iModel containing the metadata for this type\n * @param ecTypeQualifier - a full name of an ECEntityClass to find the root of\n * @returns the qualified full name of an ECEntityClass\n * @internal public for testing only\n */\n public static getRootEntity(iModel: IModelDb, ecTypeQualifier: string): string {\n const [classSchema, className] = ecTypeQualifier.split(\".\");\n const schemaItemJson = iModel.nativeDb.getSchemaItem(classSchema, className);\n if (schemaItemJson.error)\n throw new IModelError(schemaItemJson.error.status, `failed to get schema item '${ecTypeQualifier}'`);\n\n assert(undefined !== schemaItemJson.result);\n const schemaItem = JSON.parse(schemaItemJson.result);\n if (!(\"appliesTo\" in schemaItem) && schemaItem.baseClass === undefined) {\n return ecTypeQualifier;\n }\n\n // typescript doesn't understand that the inverse of the above condition is\n // (\"appliesTo\" in rootclassMetaData || rootClassMetaData.baseClass !== undefined)\n const parentItemQualifier = schemaItem.appliesTo ?? schemaItem.baseClass as string;\n return this.getRootEntity(iModel, parentItemQualifier);\n }\n\n /** Generate a JavaScript class from Entity metadata.\n * @param entityMetaData The Entity metadata that defines the class\n */\n private static generateClassForEntity(entityMetaData: EntityMetaData, iModel: IModelDb): typeof Entity {\n const name = entityMetaData.ecclass.split(\":\");\n const domainName = name[0];\n const className = name[1];\n\n if (0 === entityMetaData.baseClasses.length) // metadata must contain a superclass\n throw new IModelError(IModelStatus.BadArg, `class ${name} has no superclass`);\n\n // make sure schema exists\n let schema = Schemas.getRegisteredSchema(domainName);\n if (undefined === schema)\n schema = this.generateProxySchema(domainName, iModel); // no schema found, create it too\n\n const superclass = this._classMap.get(entityMetaData.baseClasses[0].toLowerCase());\n if (undefined === superclass)\n throw new IModelError(IModelStatus.NotFound, `cannot find superclass for class ${name}`);\n\n // user defined class hierarchies may skip a class in the hierarchy, and therefore their JS base class cannot\n // be used to tell if there are any generated classes in the hierarchy\n let generatedClassHasNonGeneratedNonCoreAncestor = false;\n let currentSuperclass = superclass;\n const MAX_ITERS = 1000;\n for (let i = 0; i < MAX_ITERS; ++i) {\n if (currentSuperclass.schema.schemaName === \"BisCore\")\n break;\n\n if (!currentSuperclass.isGeneratedClass) {\n generatedClassHasNonGeneratedNonCoreAncestor = true;\n break;\n }\n const superclassMetaData = iModel.classMetaDataRegistry.find(currentSuperclass.classFullName);\n if (superclassMetaData === undefined)\n throw new IModelError(IModelStatus.BadSchema, `could not find the metadata for class '${currentSuperclass.name}', class metadata should be loaded by now`);\n const maybeNextSuperclass = this.getClass(superclassMetaData.baseClasses[0], iModel);\n if (maybeNextSuperclass === undefined)\n throw new IModelError(IModelStatus.BadSchema, `could not find the base class of '${currentSuperclass.name}', all generated classes must have a base class`);\n currentSuperclass = maybeNextSuperclass;\n }\n\n const generatedClass = class extends superclass {\n public static override get className() { return className; }\n private static [isGeneratedClassTag] = true;\n public static override get isGeneratedClass() { return this.hasOwnProperty(isGeneratedClassTag); }\n };\n\n // the above creates an anonymous class. For help debugging, set the \"constructor.name\" property to be the same as the bisClassName.\n Object.defineProperty(generatedClass, \"name\", { get: () => className }); // this is the (only) way to change that readonly property.\n\n // a class only gets an automatic `collectReferenceIds` implementation if:\n // - it is not in the `BisCore` schema\n // - there are no ancestors with manually registered JS implementations, (excluding BisCore base classes)\n if (!generatedClassHasNonGeneratedNonCoreAncestor) {\n const navigationProps = Object.entries(entityMetaData.properties)\n .filter(([_name, prop]) => prop.isNavigation)\n // eslint-disable-next-line @typescript-eslint/no-shadow\n .map(([name, prop]) => {\n assert(prop.relationshipClass);\n const maybeMetaData = iModel.nativeDb.getSchemaItem(...prop.relationshipClass.split(\":\") as [string, string]);\n assert(maybeMetaData.result !== undefined, \"The nav props relationship metadata was not found\");\n const relMetaData = JSON.parse(maybeMetaData.result);\n const rootClassMetaData = ClassRegistry.getRootEntity(iModel, relMetaData.target.constraintClasses[0]);\n // root class must be in BisCore so should be loaded since biscore classes will never get this\n // generated implementation\n const normalizeClassName = (clsName: string) => clsName.replace(\".\", \":\");\n const rootClass = ClassRegistry.findRegisteredClass(normalizeClassName(rootClassMetaData));\n assert(rootClass, `The root class for ${prop.relationshipClass} was not in BisCore.`);\n return { name, concreteEntityType: EntityReferences.typeFromClass(rootClass) };\n });\n\n Object.defineProperty(\n generatedClass.prototype,\n \"collectReferenceIds\",\n {\n value(this: typeof generatedClass, referenceIds: EntityReferenceSet) {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n const superImpl = superclass.prototype[\"collectReferenceIds\"];\n superImpl.call(this, referenceIds);\n for (const navProp of navigationProps) {\n const relatedElem: RelatedElement | undefined = (this as any)[navProp.name]; // cast to any since subclass can have any extensions\n if (!relatedElem || !Id64.isValid(relatedElem.id))\n continue;\n const referenceId = EntityReferences.fromEntityType(relatedElem.id, navProp.concreteEntityType);\n referenceIds.add(referenceId);\n }\n },\n // defaults for methods on a prototype (required for sinon to stub out methods on tests)\n writable: true,\n configurable: true,\n },\n );\n }\n\n // if the schema is a proxy for a domain with behavior, throw exceptions for all protected operations\n if (schema.missingRequiredBehavior) {\n const throwError = () => {\n throw new IModelError(IModelStatus.WrongHandler, `Schema [${domainName}] not registered, but is marked with SchemaHasBehavior`);\n };\n\n superclass.protectedOperations.forEach((operation) => (generatedClass as any)[operation] = throwError);\n }\n\n this.register(generatedClass, schema); // register it before returning\n return generatedClass;\n }\n\n /** Register all of the classes found in the given module that derive from [[Entity]].\n * [[register]] will be invoked for each subclass of `Entity` exported by `moduleObj`.\n * @param moduleObj The module to search for subclasses of Entity\n * @param schema The schema that contains all of the [ECClass]($ecschema-metadata)es exported by `moduleObj`.\n */\n public static registerModule(moduleObj: any, schema: typeof Schema) {\n for (const thisMember in moduleObj) { // eslint-disable-line guard-for-in\n const thisClass = moduleObj[thisMember];\n if (thisClass.prototype instanceof Entity)\n this.register(thisClass, schema);\n }\n }\n\n /**\n * This function fetches the specified Entity from the imodel, generates a JavaScript class for it, and registers the generated\n * class. This function also ensures that all of the base classes of the Entity exist and are registered.\n */\n private static generateClass(classFullName: string, iModel: IModelDb): typeof Entity {\n const metadata: EntityMetaData | undefined = iModel.classMetaDataRegistry.find(classFullName);\n if (metadata === undefined || metadata.ecclass === undefined)\n throw this.makeMetaDataNotFoundError(classFullName);\n\n // Make sure we have all base classes registered.\n if (metadata.baseClasses && (0 !== metadata.baseClasses.length))\n this.getClass(metadata.baseClasses[0], iModel);\n\n // Now we can generate the class from the classDef.\n return this.generateClassForEntity(metadata, iModel);\n }\n\n /** Find a registered class by classFullName.\n * @param classFullName class to find\n * @param iModel The IModel that contains the class definitions\n * @returns The Entity class or undefined\n */\n public static findRegisteredClass(classFullName: string): typeof Entity | undefined {\n return this._classMap.get(classFullName.toLowerCase());\n }\n\n /** Get the Entity class for the specified Entity className.\n * @param classFullName The full BIS class name of the Entity\n * @param iModel The IModel that contains the class definitions\n * @returns The Entity class\n */\n public static getClass(classFullName: string, iModel: IModelDb): typeof Entity {\n const key = classFullName.toLowerCase();\n const ctor = this._classMap.get(key);\n return ctor ? ctor : this.generateClass(key, iModel);\n }\n\n /** Unregister a class, by name, if one is already registered.\n * This function is not normally needed, but is useful for cases where a generated *proxy* class needs to be replaced by the *real* class.\n * @param classFullName Name of the class to unregister\n * @return true if the class was unregistered\n * @internal\n */\n public static unregisterCLass(classFullName: string) { return this._classMap.delete(classFullName.toLowerCase()); }\n /** Unregister all classes from a schema.\n * This function is not normally needed, but is useful for cases where a generated *proxy* schema needs to be replaced by the *real* schema.\n * @param schema Name of the schema to unregister\n * @internal\n */\n public static unregisterClassesFrom(schema: typeof Schema) {\n for (const entry of Array.from(this._classMap)) {\n if (entry[1].schema === schema)\n this.unregisterCLass(entry[0]);\n }\n }\n}\n\n/**\n * A cache that records the mapping between class names and class metadata.\n * @see [[IModelDb.classMetaDataRegistry]] to access the registry for a specific iModel.\n * @internal\n */\nexport class MetaDataRegistry {\n private _registry: Map<string, EntityMetaData> = new Map<string, EntityMetaData>();\n\n /** Get the specified Entity metadata */\n public find(classFullName: string): EntityMetaData | undefined { return this._registry.get(classFullName.toLowerCase()); }\n\n /** Add metadata to the cache */\n public add(classFullName: string, metaData: EntityMetaData): void { this._registry.set(classFullName.toLowerCase(), metaData); }\n}\n"]}
@@ -68,17 +68,24 @@ export interface OnSubModelIdArg extends OnElementArg {
68
68
  /** The modelId of the sub Model */
69
69
  subModelId: Id64String;
70
70
  }
71
- /** Elements are the smallest individually identifiable building blocks for modeling the real world in an iModel.
72
- * Each element represents an entity in the real world. Sets of Elements (contained in [[Model]]s) are used to model
71
+ /** The smallest individually identifiable building block for modeling the real world in an iModel.
72
+ * Each element represents an [[Entity]] in the real world. Sets of Elements (contained in [[Model]]s) are used to model
73
73
  * other Elements that represent larger scale real world entities. Using this recursive modeling strategy,
74
74
  * Elements can represent entities at any scale. Elements can represent physical things or abstract concepts
75
75
  * or simply be information records.
76
76
  *
77
77
  * Every Element has a 64-bit id (inherited from Entity) that uniquely identifies it within an iModel. Every Element also
78
- * has a "code" that identifies its meaning in the real world. Additionally, Elements may have a "federationGuid"
78
+ * has a [[code]] that identifies its meaning in the real world. Additionally, Elements may have a [[federationGuid]]
79
79
  * to hold a GUID, if the element was assigned that GUID by some other federated database. The iModel database enforces
80
80
  * uniqueness of id, code, and federationGuid.
81
81
  *
82
+ * The Element class provides `static` methods like [[onInsert]], [[onUpdated]], [[onCloned]], and [[onChildAdded]] that enable
83
+ * it to customize persistence operations. For example, the base implementations of [[onInsert]], [[onUpdate]], and [[onDelete]]
84
+ * validate that the appropriate [locks]($docs/learning/backend/ConcurrencyControl.md), [codes]($docs/learning/backend/CodeService.md),
85
+ * and [channel permissions]($docs/learning/backend/Channel.md) are obtained before a change to the element is written to the iModel.
86
+ * A subclass of Element that overrides any of these methods **must** call the `super` method as well. An application that supplies its
87
+ * own Element subclasses should register them at startup via [[ClassRegistry.registerModule]] or [[ClassRegistry.register]].
88
+ *
82
89
  * See:
83
90
  * * [Element Fundamentals]($docs/bis/guide/fundamentals/element-fundamentals.md)
84
91
  * * [Working with schemas and elements in TypeScript]($docs/learning/backend/SchemasAndElementsInTypeScript.md)