packageDocumentation module import { AccessToken , GuidString , Id64 , Id64String , Logger } from "@itwin/core-bentley" ; import { request , Response } from "../itwin-client/Request" ; import { ECJsonTypeMap , WsgInstance } from "../wsg/ECJsonTypeMap" ; import { IModelHubClientLoggerCategory } from "../IModelHubClientLoggerCategories" ; import { IModelBaseHandler } from "./BaseHandler" ; import { CodeState } from "./Codes" ; import { ArgumentCheck } from "./Errors" ; import { BaseEventSAS , EventBaseHandler , EventListener , GetEventOperationToRequestType , IModelHubBaseEvent , ListenerSubscription , } from "./EventsBase" ; import { LockLevel , LockType } from "./Locks" ; const loggerCategory = IModelHubClientLoggerCategory . IModelHub ; public export enum IModelHubEventType { internal LockEvent = "LockEvent" , internal AllLocksDeletedEvent = "AllLocksDeletedEvent" , /** Sent when a [[ChangeSet]] is successfully pushed. See [[ChangeSetPostPushEvent]]. */ ChangeSetPostPushEvent = "ChangeSetPostPushEvent" , /** Sent when a [[ChangeSet]] push has started. See [[ChangeSetPrePushEvent]]. */ ChangeSetPrePushEvent = "ChangeSetPrePushEvent" , internal CodeEvent = "CodeEvent" , internal AllCodesDeletedEvent = "AllCodesDeletedEvent" , internal BriefcaseDeletedEvent = "BriefcaseDeletedEvent" , /** Sent when an iModel is deleted. See [[iModelDeletedEvent]]. */ iModelDeletedEvent = "iModelDeletedEvent" , /** Sent when a new named [[Version]] is created. See [[VersionEvent]]. */ VersionEvent = "VersionEvent" , internal CheckpointCreatedEvent = "CheckpointCreatedEvent" , internal CheckpointV2CreatedEvent = "CheckpointV2CreatedEvent" } internal deprecated export type EventType = "LockEvent" | "AllLocksDeletedEvent" | "ChangeSetPostPushEvent" | "ChangeSetPrePushEvent" | "CodeEvent" | "AllCodesDeletedEvent" | "BriefcaseDeletedEvent" | "iModelDeletedEvent" | "VersionEvent" | "CheckpointCreatedEvent" | "CheckpointV2CreatedEvent" ; public export abstract class IModelHubEvent extends IModelHubBaseEvent { /** Id of the iModel where the event occurred. */ public iModelId ? : GuidString ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . iModelId = this . eventTopic ; } } public export abstract class BriefcaseEvent extends IModelHubEvent { /** Id of the [[Briefcase]] involved in this event. */ public briefcaseId : number ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . briefcaseId = obj . BriefcaseId ; } } internal export class LockEvent extends BriefcaseEvent { /** [[LockType]] of the updated Locks. */ public lockType : LockType ; /** [[LockLevel]] of the updated Locks. */ public lockLevel : LockLevel ; /** Id's of the updated Locks. */ public objectIds : Id64String [ ] ; /** Id of the [[ChangeSet]] Locks were released with. */ public releasedWithChangeSet ? : string ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . lockType = LockType [ obj . LockType as keyof typeof LockType ] ; this . lockLevel = LockLevel [ obj . LockLevel as keyof typeof LockLevel ] ; this . objectIds = ( obj . ObjectIds as string [ ] ) . map ( ( value ) => Id64 . fromJSON ( value ) ) ; this . releasedWithChangeSet = obj . ReleasedWithChangeSet ; } } internal export class AllLocksDeletedEvent extends BriefcaseEvent { } public export class ChangeSetPostPushEvent extends BriefcaseEvent { /** Id of the ChangeSet that was pushed. */ public changeSetId : string ; /** Index of the ChangeSet that was pushed. */ public changeSetIndex : string ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . changeSetId = obj . ChangeSetId ; this . changeSetIndex = obj . ChangeSetIndex ; } } public export class ChangeSetPrePushEvent extends IModelHubEvent { } internal export class CodeEvent extends BriefcaseEvent { /** Id of the [CodeSpec]($common) for the updated Codes. */ public codeSpecId : Id64String ; /** Scope of the updated Codes. */ public codeScope : string ; /** Array of the updated Code values. */ public values : string [ ] ; /** State Codes were updated to. */ public state : CodeState = CodeState . Reserved ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . codeSpecId = Id64 . fromJSON ( obj . CodeSpecId ) ; this . codeScope = obj . CodeScope ; this . values = obj . Values ; this . state = obj . State ; } } internal export class AllCodesDeletedEvent extends BriefcaseEvent { } internal export class BriefcaseDeletedEvent extends BriefcaseEvent { } public export class IModelDeletedEvent extends IModelHubEvent { } public export class VersionEvent extends IModelHubEvent { /** Id of the created Version. */ public versionId : GuidString ; /** Name of the created Version. */ public versionName : string ; /** Id of the [[ChangeSet]] that this Version was created for.  */ public changeSetId : string ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . versionId = obj . VersionId ; this . versionName = obj . VersionName ; this . changeSetId = obj . ChangeSetId ; } } internal export class CheckpointCreatedEvent extends IModelHubEvent { /** Index of the [[ChangeSet]] this [[Checkpoint]] was created for.  */ public changeSetIndex : string ; /** Id of the [[ChangeSet]] this [[Checkpoint]] was created for.  */ public changeSetId : string ; /** Id of the [[Version]] this [[Checkpoint]] was created for. */ public versionId ? : GuidString ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . changeSetIndex = obj . ChangeSetIndex ; this . changeSetId = obj . ChangeSetId ; this . versionId = obj . VersionId ; } } internal export class CheckpointV2CreatedEvent extends IModelHubEvent { /** Index of the [[ChangeSet]] this [[CheckpointV2]] was created for.  */ public changeSetIndex : string ; /** Id of the [[ChangeSet]] this [[CheckpointV2]] was created for.  */ public changeSetId : string ; /** Id of the [[Version]] this [[CheckpointV2]] was created for. */ public versionId ? : GuidString ; param obj internal public override fromJson ( obj ) { super . fromJson ( obj ) ; this . changeSetIndex = obj . ChangeSetIndex ; this . changeSetId = obj . ChangeSetId ; this . versionId = obj . VersionId ; } } internal type EventConstructor = ( new ( ) => IModelHubEvent ) ; internal export function constructorFromEventType ( type ) { switch ( type ) { case IModelHubEventType . LockEvent : return LockEvent ; case IModelHubEventType . AllLocksDeletedEvent : return AllLocksDeletedEvent ; case IModelHubEventType . ChangeSetPostPushEvent : return ChangeSetPostPushEvent ; case IModelHubEventType . ChangeSetPrePushEvent : return ChangeSetPrePushEvent ; case IModelHubEventType . CodeEvent : return CodeEvent ; case IModelHubEventType . AllCodesDeletedEvent : return AllCodesDeletedEvent ; case IModelHubEventType . BriefcaseDeletedEvent : return BriefcaseDeletedEvent ; case IModelHubEventType . iModelDeletedEvent : return IModelDeletedEvent ; case IModelHubEventType . VersionEvent : return VersionEvent ; case IModelHubEventType . CheckpointCreatedEvent : return CheckpointCreatedEvent ; case IModelHubEventType . CheckpointV2CreatedEvent : return CheckpointV2CreatedEvent ; } } param response returns internal export function ParseEvent ( response ) { const constructor = constructorFromEventType ( response . header [ "content-type" ] ) ; const event = new constructor ( ) ; event . fromJson ( response . body ) ; return event ; } internal @ ECJsonTypeMap . classToJson ( "wsg" , "iModelScope.EventSubscription" , { schemaPropertyName : "schemaName" , classPropertyName : "className" } ) export class EventSubscription extends WsgInstance { /** Types of the [[IModelHubEvent]]s that this subscription listens to. */ @ ECJsonTypeMap . propertyToJson ( "wsg" , "properties.EventTypes" ) public eventTypes ? : IModelHubEventType [ ] ; } internal @ ECJsonTypeMap . classToJson ( "wsg" , "iModelScope.EventSAS" , { schemaPropertyName : "schemaName" , classPropertyName : "className" } ) export class EventSAS extends BaseEventSAS { } internal export class EventSubscriptionHandler { private _handler : IModelBaseHandler ; param handler constructor ( handler ) { this . _handler = handler ; } param iModelId param instanceId private getRelativeUrl ( iModelId , instanceId ? ) { return `/Repositories/iModel--${ iModelId }/iModelScope/EventSubscription/${ instanceId || "" }` ; } param iModelId param events return throws public async create ( accessToken , iModelId , events ) ; param iModelId param events return throws internal deprecated public async create ( accessToken , iModelId , events ) ; public async create ( accessToken , iModelId , events ) { Logger . logInfo ( loggerCategory , "Creating event subscription on iModel" , ( ) => ( { iModelId } ) ) ; ArgumentCheck . validGuid ( "iModelId" , iModelId ) ; ArgumentCheck . nonEmptyArray ( "events" , events ) ; let subscription = new EventSubscription ( ) ; subscription . eventTypes = events as IModelHubEventType [ ] ; subscription = await this . _handler . postInstance < EventSubscription > ( accessToken , EventSubscription , this . getRelativeUrl ( iModelId ) , subscription ) ; Logger . logTrace ( loggerCategory , "Created event subscription on iModel" , ( ) => ( { iModelId } ) ) ; return subscription ; } param iModelId param subscription return throws throws public async update ( accessToken , iModelId , subscription ) { Logger . logInfo ( loggerCategory , "Updating event subscription on iModel" , ( ) => ( { iModelId } ) ) ; ArgumentCheck . validGuid ( "iModelId" , iModelId ) ; ArgumentCheck . defined ( "subscription" , subscription ) ; ArgumentCheck . validGuid ( "subscription.wsgId" , subscription . wsgId ) ; const updatedSubscription = await this . _handler . postInstance < EventSubscription > ( accessToken , EventSubscription , this . getRelativeUrl ( iModelId , subscription . wsgId ) , subscription ) ; Logger . logTrace ( loggerCategory , "Updated event subscription on iModel" , ( ) => ( { iModelId } ) ) ; return updatedSubscription ; } param iModelId param eventSubscriptionId returns throws throws public async delete ( accessToken , iModelId , eventSubscriptionId ) { Logger . logInfo ( loggerCategory , `Deleting event subscription ${ eventSubscriptionId } from iModel` , ( ) => ( { iModelId } ) ) ; ArgumentCheck . validGuid ( "iModelId" , iModelId ) ; ArgumentCheck . validGuid ( "eventSubscriptionId" , eventSubscriptionId ) ; await this . _handler . delete ( accessToken , this . getRelativeUrl ( iModelId , eventSubscriptionId ) ) ; Logger . logTrace ( loggerCategory , `Deleted event subscription ${ eventSubscriptionId } from iModel` , ( ) => ( { iModelId } ) ) ; } } internal export class EventHandler extends EventBaseHandler { private _subscriptionHandler : EventSubscriptionHandler | undefined ; param handler internal constructor ( handler ) { super ( ) ; this . _handler = handler ; } /** Get a handler for managing [[EventSubscription]]s. */ public get subscriptions ( ) : EventSubscriptionHandler { if ( ! this . _subscriptionHandler ) { this . _subscriptionHandler = new EventSubscriptionHandler ( this . _handler ) ; } return this . _subscriptionHandler ; } param iModelId private getEventSASRelativeUrl ( iModelId ) { return `/Repositories/iModel--${ iModelId }/iModelScope/EventSAS/` ; } param iModelId return throws public async getSASToken ( accessToken , iModelId ) { Logger . logInfo ( loggerCategory , "Getting event SAS token from iModel" , ( ) => ( { iModelId } ) ) ; ArgumentCheck . validGuid ( "iModelId" , iModelId ) ; const eventSAS = await this . _handler . postInstance < EventSAS > ( accessToken , EventSAS , this . getEventSASRelativeUrl ( iModelId ) , new EventSAS ( ) ) ; Logger . logTrace ( loggerCategory , "Got event SAS token from iModel" , ( ) => ( { iModelId } ) ) ; return eventSAS ; } param baseAddress param subscriptionId param timeout private getEventUrl ( baseAddress , subscriptionId , timeout ? ) { let url = `${ baseAddress }/Subscriptions/${ subscriptionId }/messages/head` ; if ( timeout ) { url = `${ url }?timeout=${ timeout }` ; } return url ; } param sasToken param baseAddress param subscriptionId param timeout return throws throws public async getEvent ( sasToken , baseAddress , subscriptionId , timeout ? ) { Logger . logInfo ( loggerCategory , "Getting event from subscription" , ( ) => ( { subscriptionId } ) ) ; ArgumentCheck . defined ( "sasToken" , sasToken ) ; ArgumentCheck . defined ( "baseAddress" , baseAddress ) ; ArgumentCheck . validGuid ( "subscriptionId" , subscriptionId ) ; const options = await this . getEventRequestOptions ( GetEventOperationToRequestType . GetDestructive , sasToken , timeout ) ; const result = await request ( this . getEventUrl ( baseAddress , subscriptionId , timeout ) , options ) ; if ( result . status === 204 ) { Logger . logTrace ( loggerCategory , "No events found on subscription" , ( ) => ( { subscriptionId } ) ) ; return undefined ; } const event = ParseEvent ( result ) ; Logger . logTrace ( loggerCategory , "Got event from subscription" , ( ) => ( { subscriptionId } ) ) ; return event ; } param subscriptionId param iModelId param listener returns throws public createListener < T extends IModelHubEvent > ( authenticationCallback , subscriptionId , iModelId , listener ) { ArgumentCheck . defined ( "authenticationCallback" , authenticationCallback ) ; ArgumentCheck . validGuid ( "subscriptionId" , subscriptionId ) ; ArgumentCheck . validGuid ( "iModelId" , iModelId ) ; const subscription = new ListenerSubscription ( ) ; subscription . authenticationCallback = authenticationCallback ; subscription . getEvent = async ( sasToken , baseAddress , id , timeout ? ) => this . getEvent ( sasToken , baseAddress , id , timeout ) ; subscription . getSASToken = async ( accessToken ) => this . getSASToken ( accessToken , iModelId ) ; subscription . id = subscriptionId ; return EventListener . create ( subscription , listener as ( e : IModelHubBaseEvent ) => void ) ; } }