@itwin/core-backend
Version:
iTwin.js backend components
144 lines • 6.27 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Schema
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Schemas = exports.SchemaMap = exports.Schema = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const ClassRegistry_1 = require("./ClassRegistry");
const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
/** Base class for all schema classes - see [working with schemas and elements in TypeScript]($docs/learning/backend/SchemasAndElementsInTypeScript.md).
*
* When subclassing from Schema, it is good practice to follow this pattern:
*
* ```typescript
* class MyCustomSchema extends Schema {
* public static override get schemaName(): string { return "MyCustomSchema"; }
* public static get classes(): typeof Entity[] {
* return [MyOwnECClass, AnotherECClass];
* }
* public static registerSchema() {
* if (this !== Schemas.getRegisteredSchema(this.schemaName)) {
* Schemas.unregisterSchema(this.schemaName);
* Schemas.registerSchema(this);
* for (const ecClass of this.classes) {
* ClassRegistry.register(ecClass, this);
* }
* }
* }
*
* public static unregisterSchema() {
* Schemas.unregisterSchema(this.schemaName);
* }
* }
* ```
*
* @public
*/
class Schema {
/** The name of the BIS schema handled by this Schema.
* @note Every subclass of Schema ** MUST ** override this method to identify its BIS schema.
* Failure to do so will ordinarily result in an error when the schema is registered, since there may only
* be one JavaScript class for a given BIS schema (usually the errant schema will collide with its superclass.)
*/
static get schemaName() { throw new Error(`you must override static schemaName in ${this.name}`); }
/** Unique identifier for this schema, typed variant of [[schemaName]].
* @internal
*/
static get schemaKey() {
// We cannot cache this here because the schemaName may be overridden without this being overridden
return new ecschema_metadata_1.SchemaKey(this.schemaName, ecschema_metadata_1.ECVersion.NO_VERSION); // backend cares little for versions right now, as only one version can exist in an imodel
}
/** if true, this Schema is a proxy for a missing Domain marked with the `BisCore.SchemaHasBehavior` customAttribute.
* Classes generated for this Schema will disallow protected operations.
* @internal
*/
static get missingRequiredBehavior() { return false; }
/** Get a semver-compatible string from a padded version string.
* works on unpadded version strings as well
* if there is no write version, it will be added
* @example Schema.toSemverString("1.02.03") === "1.2.3"
* @example Schema.toSemverString("1.01") === "1.0.1" // write version was added
* @beta
*/
static toSemverString(paddedVersion) {
const tuple = paddedVersion.split(".").map(Number);
const noWriteVersion = tuple.length === 2;
if (noWriteVersion)
tuple.splice(1, 0, 0); // insert 0 before the second element
return tuple.join(".");
}
/** Schemas may not be instantiated. The method is not private only because that precludes subclassing. It throws an
* error if it is ever called.
* @internal
*/
constructor() { throw new Error(`cannot create an instance of a Schema ${this.constructor.name}`); }
}
exports.Schema = Schema;
/**
* Holds a map of registered schemas.
* @public
*/
class SchemaMap {
_schemas = new Map();
/** @internal */
get(schemaName) {
return this._schemas.get(schemaName.toLowerCase());
}
/** @internal */
set(schemaName, schema) {
this._schemas.set(schemaName.toLowerCase(), schema);
}
/** @internal */
delete(schemaName) {
return this._schemas.delete(schemaName.toLowerCase());
}
/** Register a schema prior to using it.
* @throws [[IModelError]] if a schema of the same name is already registered.
* @public
*/
registerSchema(schema) {
const key = schema.schemaName.toLowerCase();
if (this.get(key))
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.DuplicateName, `Schema "${schema.schemaName}" is already registered`);
this.set(key, schema);
}
}
exports.SchemaMap = SchemaMap;
/** Manages registered schemas
* @public
*/
class Schemas {
static _globalSchemas = new SchemaMap();
constructor() { } // this is a singleton
/** Register a schema prior to using it.
* This method registers the schema globally, to register a schema within the scope of a single iModel, use `IModelDb.schemaMap`.
* @throws [[IModelError]] if a schema of the same name is already registered.
*/
static registerSchema(schema) {
this._globalSchemas.registerSchema(schema);
}
/** Unregister a schema, by name, if one is already registered.
* This function is not normally needed, but is useful for cases where a generated *proxy* schema needs to be replaced by the *real* schema.
* @param schemaName Name of the schema to unregister
* @return true if the schema was unregistered
*/
static unregisterSchema(schemaName) {
const schema = this.getRegisteredSchema(schemaName);
if (undefined !== schema)
ClassRegistry_1.ClassRegistry.unregisterClassesFrom(schema);
return this._globalSchemas.delete(schemaName.toLowerCase());
}
/** Look up a previously registered schema
* @param schemaName The name of the schema
* @returns the previously registered schema or undefined if not registered.
*/
static getRegisteredSchema(schemaName) { return this._globalSchemas.get(schemaName.toLowerCase()); }
}
exports.Schemas = Schemas;
//# sourceMappingURL=Schema.js.map