import SystemId from 'system/enum/id'; import TypeNode from 'type/type-node'; import DraftField from 'type/draft-field'; import InstanceNode from 'type/instance-node'; import buildNodeUrl from 'utility/build-node-url'; import getFieldKeys from 'utility/get-field-keys'; import NodeParameters from 'type/node-parameters'; import AddValueToListOperation from 'operation/add-value-to-list'; import LoadNodeFromUrlOperation from 'operation/load-node-from-url'; import Operation, { OperationInput } from 'operation'; interface Input extends OperationInput { readonly node_parameters: NodeParameters; readonly fields: DraftField[]; } class CreateInstanceOperation extends Operation { protected async performInternal(): Promise { const type_node = await this.fetchTypeNode(); const instance_node = await this.createInstance(type_node); await this.addInstanceToType(instance_node, type_node); return instance_node; } private async fetchTypeNode(): Promise { const url = this.getTypeUrl(); const repository = this.getRepository(); const account = this.getAccount(); const input = { url, repository, account }; const operation = new LoadNodeFromUrlOperation(input); const node = await operation.perform(); return node as TypeNode; } private async createInstance(type_node: TypeNode): Promise { const node = this.buildNode(type_node); const repository = this.getRepository(); return repository.storeNode(node); } private buildNode(type_node: TypeNode): InstanceNode { const url = this.getUrl(); const type_url = this.getTypeUrl(); const draft_fields = this.getDraftFields(); const creator = this.getAccountUrl(); const changes: string[] = []; const permissions = this.buildPermissions(); const created_at = Date.now(); const updated_at = created_at; let node: InstanceNode = { url, type: type_url, creator, created_at, updated_at, changes, permissions }; draft_fields.forEach((draft_field) => { const { key, value } = draft_field; node = { ...node, [key]: value }; }); const type_field_keys = getFieldKeys(type_node); type_field_keys.forEach((type_field_key) => { if (node[type_field_key] !== undefined) { return; } node = { ...node, [type_field_key]: null }; }); return node; } private async addInstanceToType( instance_node: InstanceNode, type_node: TypeNode ): Promise { const repository = this.getRepository(); const account = this.getAccount(); const input = { node: type_node, field_key: 'instances', value: instance_node.url, repository, account }; const operation = new AddValueToListOperation(input); await operation.perform(); } private getUrl(): string { const hostname = this.getHostname(); const parameters = this.getNodeParameters(); return buildNodeUrl(hostname, parameters); } private getTypeUrl(): string { const hostname = this.getHostname(); const parameters = this.getNodeParameters(); return buildNodeUrl(hostname, { type_id: SystemId.GENERIC_TYPE, id: parameters.type_id }); } private buildPermissions(): string[] { const hostname = this.getHostname(); const everyone_read_url = buildNodeUrl(hostname, { type_id: SystemId.PERMISSION_TYPE, id: SystemId.EVERYONE_READ_PERMISSION }); return [everyone_read_url]; } private getNodeParameters(): NodeParameters { const input = this.getInput(); return input.node_parameters; } private getDraftFields(): DraftField[] { const input = this.getInput(); return input.fields; } private getAccountUrl(): string { const account = this.getAccount(); return account.url; } } export default CreateInstanceOperation;